Li Mu の精読論文: ViT「An Image Is Worth 16x16 Words: Transformers For Image Recognition At Scale」

ビデオ: ViT 論文の段落ごとの集中読解 [論文集中読解]_哔哩哔哩_bilibili

コード:紙のソースコード

pytorch を使用して Vision Transformer (vit) モデルを構築する

vision_transforme · WZMIAOMIAO/画像処理用ディープラーニング · GitHub

Pytorchの公式ソースコード

VisionTransformer — トーチビジョン API

参考ブログ記事: ViT 論文の段落ごとの集中読解 [論文集中読解] - 哔哩哔哩

李牧論文集中読解シリーズ II: ビジョントランスフォーマー 沈羅華のブログ

目次

1 はじめに

1.1 Vision Transformer の興味深い機能

1.2 タイトル

1.3 概要

1.4 はじめに

NLP分野におけるTransformerの応用

変圧器を視野に適用することの難しさ

マシンビジョンの関連作業に自己注意を適用する

ビジョントランスフォーマーはシーケンスの長さの問題をどのように解決しますか

監視付きトレーニング

先人の最も関連性の高い作品

ViT と CNN ネットワーク使用効果の比較

2. 結論 

3. 関連作品 

NLP分野における変圧器の応用

視覚における自己注意の応用

4 ViTモデル

4.1 全体構造と順伝播

4.2 画像の前処理

4.3 トランスエンコーダ

4.4 MLPヘッドとViT-B/16モデルの構造図

4.5 数式の説明

5 アブレーション実験(付録)

5.1 クラストークン

5.2 位置コーディング

6 モデルのディスカッション

誘導バイアス

ハイブリッド混合モデルのテスト 

大きいサイズの微調整

7 実験パート

7.1 ViT モデルのバリエーション

 7.2 ViTモデルとCNNとの比較結果

7.3 ViT の事前トレーニングにはどのくらいのデータ サイズが必要ですか? (重要な議論)

7.4 結論

8 ViTの可視化   

パッチ埋め込みの視覚化

位置埋め込みの視覚化

自己注意は機能しますか?

アウトトークンの出力

9 自己指導型トレーニング

10 まとめ


        この記事は、AlexNet が 2012 年に提案されて以来、コンピューター ビジョンにおける畳み込みニューラル ネットワークの絶対的な優位性に異議を唱えます。結論としては、十分なデータで事前トレーニングを行っていれば、畳み込みニューラル ネットワークは必要なく、標準のトランスフォーマーを直接使用することで視覚的な問題をうまく解決できるということです。これはモデルにおける CV と NLP の間の障壁を打ち破り、CV の新時代を開き、マルチモーダル分野の開発を前進させます。

paperswithcode は、特定の分野または特定のデータセットで最適な方法は何かをクエリできます。ImageNet データセット上の画像分類の上位ランキングはすべて、Vision Transformer の最新の機械学習 | Papers With Codeに基づいています。

ImageNet ベンチマーク (画像分類) | コード付き論文

        COCO データセットのターゲット検出タスクでは、上位ランキングはすべて Swin Transformer に基づいています。Swin Transformer は、ICCV 21 の最高の論文であり、マルチスケールの Vit (Vision Transformer) として想像できます。

        COCO test-dev ベンチマーク (オブジェクト検出) | コード付き論文

        他の分野 (セマンティック セグメンテーション、インスタンス セグメンテーション、ビデオ、医療、リモート センシング) では、基本的に、Vision Transformer が視覚フィールド全体のすべてのタスクを処理したと言えます。

1 はじめに

1.1 Vision Transformer の興味深い機能

  著者による別の論文:

《ビジョントランスフォーマーの興味深い性質》

以下に示すように:

        図aはオクルージョンを示していますが、このような厳しいオクルージョン状況では、たとえそれが畳み込みニューラルネットワークであっても、人間の目で表示されている絵が鳥であることを観察することは困難です。

        図 b は、データ分布に変化があることを示しています。ここでは、画像に対してテクスチャ除去操作が実行されているため、画像はより魔法のように見えます。

        図 c は、鳥の頭の位置に敵対的パッチが追加されていることを示しています

        図dは、写真を分散させて配置し、組み合わせたものです。

  上記の例では、畳み込みニューラル ネットワークがオブジェクトが何であるかを判断するのは困難ですが、これらすべての例において、Vision Transformer はそれを非常にうまく処理できます。

1.2 タイトル

        1 つの画像は、多くの 16*16 ワードに相当します。なぜ 16*16 ワードなのか? 画像を多数の正方形のパッチに分割します。各正方形のサイズは 16*16 です。この場合、この画像は多数の 16*16 パッチで構成される全体と同等になります。

1.3 概要

  VIT が登場する前は、CV 分野でのセルフ アテンションの適用は非常に限られており、畳み込みと併用されるか、CNN の一部のモジュールがセルフ アテンションに置き換えられていましたが、全体的なアーキテクチャは同じままでした。

  この記事では、画像分類タスクにおいて、純粋な Vision Transformer 構造を使用して一連の画像ブロックに直接作用するだけでも良好な結果が得られることを証明します (最良のモデルは ImageNet1K で 88.55% の精度を達成できます)。特に、大規模なデータで事前トレーニングしてから中小規模のデータセット (ImageNet、CIFAR-100、VATB) に移行した場合、Vision Transformer は最高の畳み込みニューラル ネットワークに匹敵する結果を得ることができます。Transformer のもう 1 つの利点は、必要なトレーニング リソースが少なく、非常に優れたパフォーマンスを発揮することです。

        ここで著者が言及している少ないトレーニング リソースとは、TPUv3 の日数である 2500 日を指します。ここでの少ない値は、より多くのカードを消費するモデルとの比較のためだけに示しています。

1.4 はじめに

NLP分野におけるTransformerの応用

  自己注意に基づくモデル アーキテクチャ、特に Transformer は、NLP の分野ではほぼ必須のアーキテクチャとなっています。現在、より主流の方法は、最初に大規模なデータセットで事前トレーニングを実行し、次に特定の分野のいくつかの小規模なデータセットで微調整することです。Transformer の高い効率性とスケーラビリティのおかげで、1,000 億を超えるパラメータを持つ大規模モデル (GPT3) をトレーニングできるようになりました。モデルやデータセットが成長してもパフォーマンスが飽和することはありません。

  • 多くの場合、より良い結果を得るためにやみくもにデータセットを拡張したり、モデルを拡張したりすることはできません。特にモデルを拡張する場合、過剰適合の問題が発生しやすくなりますが、トランスフォーマーではこのボトルネックは観察されていません。
  • Microsoft と Nvidia は共同で超大規模言語生成モデル Megatron-Turing を発表しました。このモデルにはすでに 5,300 億のパラメーターがあり、パフォーマンスが飽和することなくさまざまなタスクのパフォーマンスを大幅に向上させ続けることができます。

変圧器を視野に適用することの難しさ

        Transformer がセルフアテンションを実行しているときは、相互にペアになっており、この計算量はシーケンスの長さの 2 乗に比例します。現在、自然言語処理において、ハードウェアがサポートする系列長は数百、数千が一般的である(例えば、BERTの系列長は512)。

    最初に解決すべきことは、2D 画像を 1D シーケンス (またはコレクション) に変換する方法です。最も直感的な方法は、各ピクセルを要素として扱い、画像をまっすぐにしてトランスフォーマーに入れることです。これは比較的単純に見えますが、実装はより複雑です。

        一般的に、ビジョンで分類タスクを訓練する場合、画像の入力サイズは約 224*224 です。画像内の各ピクセルを直接要素としてみなした場合、シーケンスの長さは 224*224=50176 ピクセルになります。このサイズは同等です。 BERT シーケンスの長さの 100 倍まで。これは単なる分類タスクです。検出とセグメンテーションでは、多くのモデルの入力が 600*600 または 800*800 以上になり、計算の複雑さが増しています。したがって、視野では、畳み込みニューラル ネットワークはまだ残っています。 AlexNet や ResNet などの支配的なステータス。

マシンビジョンの関連作業に自己注意を適用する

  NLP に触発され、マシン ビジョンに自己注意を適用する方法を研究した作品が数多くあります。畳み込みニューラル ネットワークとセルフ アテンションを混合する作業もあれば、畳み込みニューラル ネットワーク全体を置き換えてセルフ アテンションを使用する作業もあります。これらのメソッドが実際に行っていることは 1 つです。シーケンスの長さが長すぎるため、ビジョン内でトランスフォーマーを使用する方法がないため、シーケンスの長さを削減しようとします。

        非ローカル ニューラル ネットワーク (CVRP、2018): ネットワークの中間層によって出力された特徴マップは、シーケンスの長さを短縮するためにトランスフォーマーの入力シーケンスとして使用されます。例えば、最終段のResNet50の特徴マップのサイズは14×14であり、これを平坦化すると系列要素は196個のみとなり、許容範囲内となる。

        「ビジョン モデルにおけるスタンドアロンと自己注意」 (NeurIPS、2019): 孤立した注意スタンドアロンと軸方向の注意を使用して処理します。具体的には、画像全体を入力するのではなく、ローカルウィンドウ(小さなローカルウィンドウ)で注目度を計算する。ウィンドウのサイズを制御できるため、複雑さが大幅に軽減されます。(畳み込み演算と同様)

        《Axial-DeepLab: パノプティックセグメンテーションのためのスタンドアロン Axial-Attendant》(ECCV,2020a):

  • 分離された自己注意: 画像全体を使用する代わりに、ローカル ウィンドウ (ローカルの小さなウィンドウ) を使用し、このウィンドウのサイズを制御して計算の複雑さを許容範囲内に保ちます。これは畳み込み演算と似ています (畳み込みもローカル ウィンドウで演算されます)
  • 軸の自己注意: 視覚的な計算の複雑さが高い理由は、シーケンスの長さ N=H*W が 2D 行列であるためです。画像の 2D 行列を 2 つの 1D ベクトルに分割してみます。幅の次元でセルフ アテンション (セルフ アテンション) を実行し、次に幅の次元でセルフ アテンションを実行します。これは、2D 行列のセルフ アテンション操作を 2 つの 1D 行列に変換することと同等です。計算の複雑さが大幅に軽減されます     

  これらのモデルは理論的には非常に効率的ですが、実際には、セルフアテンション操作は現在のハードウェアでは高速化できない特殊なセルフアテンション操作であるため、大規模なモデルをトレーニングするのは困難です。したがって、大規模な画像認識では、従来の残差ネットワークが依然として最適です。

        したがって、自己注意はすでにコンピュータ ビジョンに適用されており、畳み込み演算を完全に自己注意に置き換える作業が行われてきました。この記事は、NLP 分野のトランスフォーマーのスケーラビリティに触発されており、標準のトランスフォーマーを画像に直接適用し、変更を最小限に抑えます。

ビジョントランスフォーマーはシーケンスの長さの問題をどのように解決しますか

これを行うには、画像をパッチに分割し、これらのパッチの線形埋め込みのシーケンスを Transformer への入力として提供します。イメージ パッチは、NLP アプリケーションのトークン (単語) と同じように扱われます。教師あり形式で画像分類に関してモデルをトレーニングします。

  • ビジョントランスフォーマーは画像を多数のパッチに分割します。各パッチは 16*16 です。
  • ピクチャのサイズが 224*224 の場合、シーケンス長 (シーケンス長) は N=224*224=50176 となり、これをパッチに置き換えると、パッチは要素に相当し、実効的な長さと幅は224/16= 14 となるため、最終的なシーケンス長は N=14*14=196 となり、これは通常の変圧器では許容可能です。
  • 各パッチを要素として扱うと、完全に接続された層を通じて線形埋め込みが取得され、これらが入力としてトランスフォーマーに渡されます。このとき、画像は 1 つずつ画像ブロックになります。この画像ブロックは、NLP では単語に相当します。文内の単語の数は、画像内のパッチの数に相当します。これがタイトルです。1 枚の画像言及されているのは、多くの 16*16 ワードに相当します

監視付きトレーニング

        この記事では、教師ありトレーニングを使用してビジョン トランスフォーマーをトレーニングします。なぜ監督を強調するのでしょうか?NLP の場合、トランスフォーマーは基本的に、言語モデリングまたはマスク言語モデリングを使用して、教師なしの方法でトレーニングされます。どちらも教師なしトレーニング方法を使用します。しかし、視覚に関しては、ベースライン (ベースライン) ネットワークのほとんどが依然として教師ありトレーニング方法でトレーニングされています。

先人の最も関連性の高い作品

        この記事では、視覚を自然言語処理のタスクとして扱います。特に中間モデルには、BERT とまったく同じトランスフォーマー エンコーダーが使用されます。このような単純なアイデアですが、実際、過去にこれを実行しようと考えた人もいたのです。この記事に最も類似した研究は、ICLR 2020 の論文です。

  • この論文では、入力画像から 2*2 画像パッチを抽出します。
  • なぜ 2*2 なのでしょうか? この論文の著者は CIFAR-10 データセットでのみ実験を行っており、CIFAR-10 データセット上の画像はすべて 32*32 であるため、2*2 パッチを抽出するだけで十分ですが、16* 16 パッチも抽出できません。大きい
  • パッチを解凍したら、セルフアテンションを実行します

        技術的に言えば、これは Vision Transformer ですが、この記事の著者は、この 2 つの違いは、この記事の研究により、事前トレーニングが大規模なデータセットで行われた場合、標準の Transformer で実行できることが証明されたことであると考えています。視覚的に変更や特別な変更を加えることなく使用でき、最高の畳み込みニューラル ネットワークと同等かそれ以上の結果が得られます。

このモデルは ViT に非常に似ていますが、私たちの研究はさらに進んで、大規模な事前トレーニングによってバニラ トランスフォーマーが最先端の CNN と競合できる (またはそれ以上になる) ことを実証しています。

        この記事の主な目的は、Transformer がビジョン分野でどの程度拡張できるかを説明することです。つまり、超大規模データセットと超大規模モデルの両方のサポートにより、Transformer はビジョン分野でも非常に優れた役割を果たすことができます。

ViT と CNN ネットワーク使用効果の比較

        中規模のデータ セット (ImageNet など) でトレーニングする場合、強い制約が課されていない場合、ViT モデルは実際には同じサイズの残差ネットワークよりも弱くなります。

        これに対する著者の説明は次のとおりです。CNN と比較して、変圧器には、CNN が持つ誘導バイアス (先験的な知識や事前に作成された仮定を指す誘導バイアス) が欠けています。

        CNN には通常、次の 2 種類の誘導バイアスがあります。

  •  局所性: CNN はスライディング ウィンドウの形式で画像上で少しずつ畳み込まれます。そのため、画像上の隣接する領域には隣接する特徴があり、物体が近ければ近いほど相関が強くなると想定されます。
  • 変換等分散: 書かれた式は f(g(x))=g(f(x)) で、g 関数が最初に実行されても f 関数が最初に実行されても、最終結果は変わりません; ここで、f は畳み込み演算を表しますg は変換操作を表します。畳み込みニューラル ネットワークでは、畳み込みカーネルはテンプレートと同等であるため、画像内の同じオブジェクトがどこに移動しても、同じ入力が入ってきて同じ畳み込みカーネルに遭遇する限り、出力は常に同じになります。

        ニューラル ネットワークがこれら 2 つの誘導バイアスを持つと、事前情報が大量に得られるため、比較的少ないデータで比較的良好なモデルを学習できます。しかし、変圧器の場合、この事前情報がないため、視覚に関するすべての認識をこれらのデータから学習する必要があります。

        この仮説を検証するために、著者はより大きなデータセット (ImageNet 22k データセット、1400 万サンプル、JFT 300M データセット、300M サンプル) で事前トレーニングを行い、事前トレーニングに十分なデータがあれば、Vit が次のような結果を達成できることを発見しました。現在の最良の残差ニューラル ネットワークよりも優れている

当社の Vision Transformer (ViT) は、十分な規模で事前トレーニングされ、データポイントの少ないタスクに転送された場合に優れた結果を達成します。公開されている ImageNet-21k データセットまたは社内 JFT-300M データセットで事前トレーニングされた場合、ViT は複数の画像認識ベンチマークで最先端に近づくか、それを上回ります。特に、最良のモデルは 88 の精度に達しますImageNet では 55%、90 ImageNet-Real では 72%、94 CIFAR-100 では 55%、77 19 タスクからなる VTAB スイートでは 63%

        上記の VTAB も著者のチームが提案したデータセットで、19 個のデータセットを組み合わせたもので、主にモデルの堅牢性をテストするために使用されていますが、側面から見ると、VisionTransformer の堅牢性も非常に優れていることがわかります。

2.結論 

        この論文の研究は、NLP 分野の標準 Transformer を直接使用して、コンピュータ ビジョンの問題を実行することです。自己注意を使用した以前の研究との違いは、画像ブロックの最初の抽出に加えて、位置コーディングも行われることです。いくつかの画像固有の誘導バイアス、それ以外の場合は画像固有の誘導バイアスは導入されません。この利点は、画像を NLP のトークンとして直接使用でき、NLP の標準の Transformer を画像の分類に使用できることです。

        このシンプルでスケーラブルな戦略を大規模な事前トレーニングと組み合わせると、驚くほど良い効果が得られます。Vision Transformer は、多くの画像分類ベンチマークでこれまでの最良の方法を上回り、比較的安価にトレーニングできます。

著者の将来ビジョンは次のとおりです。

  • Vit は分類だけでなく、検出とセグメンテーションも行います
    • DETR: ターゲット検出の傑作。ターゲット検出全体の前にフレームワークを変更することに等しい
    • Vitが登場してからわずか1か月半後の2020年12月にVit-FRCNNと呼ばれる作品が発表され、Vitが検出に使用されました
    • 2020年12月にセグメンテーションにVitを使用したSETR論文がありました
    • 3 か月後、視覚的な問題により適したマルチスケール設計を Transformer に統合した Swin Transformer が誕生しました。これは、Transformer が視覚分野の一般的なバックボーン ネットワークとして使用できることを実証しました。
  • 自己管理型の事前トレーニング スキームを検討する

        NLP 分野では、すべての大きな変換器は自己教師ありの方法でトレーニングされるため、Vit の論文でもいくつかの初期実験が行われ、この自己教師ありのトレーニング方法も実行可能であることが証明されましたが、教師ありトレーニングと比較するとまだかなりのギャップがあります。

  • ビジョントランスフォーマーを大きくすると、より良い結果が得られる可能性があります

        半年後、同じ著者チームが Scaling Vision Transformer と呼ばれる別の論文を発表しました。この論文では、Transformer が非常に大きくなり、ImageNet 画像分類の精度が 90% 以上に向上した Vit-G が提案されました。

3.関連作品 

NLP分野における変圧器の応用

        2017 年に Transformer が機械翻訳を行うことを提案して以来、Transformer は基本的に多くの NLP タスクで最高のパフォーマンスを発揮する方法です。現在、大規模な変換モデルは大規模コーパスで事前学習され、その後、対象タスクに合わせて微調整されることが一般的であり、その中には BERT と GPT という 2 つのシリーズのよく知られた作品があります。BERT はノイズ除去自己教師あり手法を使用します (実際には、空白を埋め、文内のいくつかの単語に取り消し線を引いて、これらの単語を予測します)。GPT は言語モデリングを使用します (すでに文があり、それを予測します) )単語とは何か、つまり次の単語の予測)を自己監視します。これら 2 つの文字は実際には人工的なもので、コーパスは固定されており、文は完成していますが、その一部が人為的に取り消し線で消されたり、最後の単語が削除されたりして、次の単語を閉じたり予測したりするため、これは自己と呼ばれます。監視付きトレーニング

視覚における自己注意の応用

        視覚において、単純に写真に自己注意を使用したい場合、最も簡単な方法は各ピクセルを要素として扱い、ペアで自己注意を実行させることですが、これは正方形の複雑さであるため、非常に困難です。実際の画像入力サイズに適用することは困難です。現在の分類タスクの 224*224 のように、変圧器は扱いが難しく、人間の目に見える鮮明な画像は言うまでもなく、一般に画質は 1k または 4k で、シーケンスの長さは数百万であり、ピクセル レベルで直接使用されます。トランスフォーマーは現実的ではないため、トランスフォーマーを使用したい場合は、いくつかの近似を行う必要があります。

  • 複雑度が高いのは、画像全体が使用されるためであり、シーケンスの長さが長いため、画像全体の代わりにローカルな近傍 (小さなウィンドウ) をセルフアテンションに使用できるため、シーケンスの長さは大幅に短縮されます。最終的な計算が複雑になる 次数も減ります
  • Sparse Transformer を使用すると、いくつかのまばらな点でのみセルフ アテンションが実行されるため、グローバル アテンションの近似にすぎません。
  • 異なるサイズのブロックにセルフ アテンションを適用するか、極端な場合には軸アテンションを使用します (最初に水平軸でセルフ アテンションを実行し、次に垂直軸でセルフ アテンションを実行します)。シーケンスの長さも大幅に短縮されます。

        これらの特別な自己注意構造は実際にコンピュータ ビジョンで良い結果をもたらしており、パフォーマンスには問題はありませんが、CPU または GPU 上で非常に高速に実行されたり、大規模なモデルでトレーニングが行われたりするものの、オペレーターを高速化するには非常に複雑なエンジニアリングが必要です。可能

        この記事に最も似ている研究は ICLR2020 論文です。違いは、Vision Transformer がより大きなパッチとより大きなデータ セットを使用することです。

        畳み込みニューラル ネットワークと自己注意を組み合わせたコンピュータ ビジョンの分野では、まだ多くの研究が行われています。そのような研究は非常に多く、基本的にビジョンの多くのタスク (検出、分類、ビデオ、マルチモダリティ) をカバーしています。 、など)

        この記事の作品とよく似た別の作品として、画像 GPT という作品があります。

  • GPT は NLP で使用される生成モデルです。画像 GPT も生成モデルであり、教師なしの方法でトレーニングされ、トランスフォーマーを使用する点で Vit に似ています。
  • 画像 GPT が達成できる最終的な効果: トレーニング済みモデルを微調整するか、特徴抽出器として使用する場合、ImageNet での分類精度は最高で 72 にとどまりますが、Vit の最終結果はすでに 88.5 であり、これよりもはるかに高くなります。 72
  • しかし、この結果は、MAEと呼ばれる最近の論文が爆発的に広まった理由でもあります。BEiT と MAE の研究以前は、視覚分野の多くのタスクにおいて、生成ネットワークは識別ネットワークと比較できませんでした。識別ネットワークの結果は生成ネットワークの結果よりもはるかに高いことがよくありましたが、MAE はそれを実現しました。 ImageNet-1k データセット上で生成モデルを使用した結果は、以前の識別モデルよりもはるかに優れており、分類タスクだけでなく、ターゲット検出に対する転移学習の効果も非常に優れていることが最近わかりました。

Vit は実際には別の一連の作業に関連しており、事前トレーニングに ImageNet よりも大きなデータ セットを使用し、追加データを使用するこの方法は、通常、特に良好な結果を達成するのに役立ちます。

  • 2017 年に JFT 300 データセットを紹介した論文では、データセットの増加に伴って畳み込みニューラル ネットワークの効果がどのように増大するかを研究しました。
  • 一部の論文では、大規模なデータセット (ImageNet-21k や JFT 300M など) で事前トレーニングする場合の ImageNet または CIFAR-100 への移行の影響を研究しています。

        この論文では ImageNet-21k と JFT 300M にも焦点を当てていますが、トレーニングは残差ネットワークではなく、トランスフォーマーのトレーニングです。

4 ViTモデル

4.1 全体構造と順伝播

モデルの設計は、可能な限り最も独創的なトランスフォーマーに従って行われます。この利点は、このトランスフォーマーが NLP 分野で長い間普及していることです。直接使用できる非常に効率的な実装がいくつかあることです。

簡単に言えば、モデルは 3 つのモジュールで構成されます。

  • 埋め込み層 (平坦化パッチの線形投影)
  • Transformer Encoder (より詳細な構造は図の右側に示されています)
  • MLP ヘッド (分類のための最終層構造)

順伝播プロセス:

  • Pacth 埋め込み: 最初にピクチャが n 個のパッチに分割され、次にこれらのパッチがシーケンスになり、各パッチが線形投影層に入力されて Pacth 埋め込みが取得されます。たとえば、ViT-L/16 は、各パッチのサイズが 16×16 であることを意味します。       
  • 位置埋め込み: self-attention 自体は入力位置情報を考慮せず、シーケンスをモデル化できません。絵に切り込まれたパッチも整っていて、乱れた後は元の絵ではなくなります。したがって、トランスフォーマーと同様に、位置埋め込みが導入されます。       
  • クラス トークン: これらのパッチのグローバル出力としてすべてのトークンの前に新しいクラス トークンを追加します。これはトランスフォーマーの CLS に相当します (ここでの追加は連結スプライシングです)。位置埋め込みもあり、位置情報は常に0です
  • Pacth embedding+position embedding+class token をまとめて Transformer Encoder に入力して出力を取得します。
  • すべてのトークンは他のトークンと相互作用するため、クラス エンベディングは他のエンベディングから有用な情報を学習できます。クラス トークンの出力は画像全体の特徴として使用され、分類結果は MLP ヘッドを通じて取得されます (VIT は分類のみを実行します)タスク)。最後に、クロス エントロピー関数を使用してモデルをトレーニングします。

         モデル内の Transformer エンコーダは標準の Transformer です。Vision Transformer のアーキテクチャは全体的に非常にシンプルで、特徴は画像を一連のトークンに変換する方法にあります。

4.2 画像の前処理

  標準の Transformer モジュールでは、トークン (ベクトル) シーケンス、つまり 2 次元行列 [num_token, token_dim] の入力が必要です。画像データの場合、データは [H、W、C] 形式の 3 次元行列であるため、最初に埋め込みレイヤーを使用してデータを変換する必要があります。

 

        まず、画像を指定されたサイズに従って多数のパッチに分割します。ViT-B/16 を例にとると、入力画像 (224x224) は 16x16 のパッチ サイズに従って分割され、分割後は 196 個のパッチが得られ、各画像ブロックのサイズは 16*16*3=768 となります。 。

コード実装では、畳み込み層を通じて直接実装されます。コンボリューション カーネル サイズは 16x16、ステップ サイズは 16、コンボリューション カーネルの数は 768 です。畳み込み [224, 224, 3] -> [14, 14, 768] を経て、H と W の 2 次元を平坦化する [14, 14, 768] -> [196, 768] と、これでちょうどいいです。 time それは 2 次元行列になります。これはまさに Transformer が望むものです。

img_size=224, patch_size=16, in_c=3, embed_dim=768, norm_layer=None
nn.Conv2d(in_c, embed_dim, kernel_size=patch_size, stride=patch_size)

        次に、各パッチは線形マップ E によって 1 次元ベクトルにマッピングされます。この完全に接続された層の寸法は 768*768 で、この記事では 2 番目の 768 が D です。

        これで、196*768 の行列であるパッチの埋め込みができました。つまり、196 個のトークンがあり、各トークン ベクトルの次元は 768 です。これまでのところ、視覚の問題を NLP の問題に変えることに成功しています。入力は 2D 画像ではなく一連の 1D トークンです

        追加の cls トークンの次元も 768 です。これにより、次のイメージの情報との直接のスプライシングが容易になります。したがって、最終的に Transformer に入るシーケンス全体の長さは 197*768 です。

        位置埋め込みを学習できます. 各ベクトルは位置情報を表します (ベクトルの次元は 768). これらの位置情報をすべてのトークンに追加すると、シーケンスは 197*768 のままになります。 

        注: 位置エンコーディング情報については、この記事では標準の学習可能な 1 次元位置埋め込みを使用します。これは、BERT で使用される位置エンコーディングでもあります。著者は、2d-aware (2d 情報を処理できる位置エンコードです) などの他のエンコード形式も試しましたが、最終的には結果がほぼ同じで、違いがないことがわかりました。    

画像の前処理用のモジュールを以下に定義します。

class Embed(nn.Module):
    def __init__(self, *, image_size, patch_size, dim, pool = 'cls', channels = 3, 
                 dim_head = 64, emb_dropout = 0.):
        super().__init__()
        assert image_size % patch_size == 0, 'Image dimensions must be divisible by the patch size.'  # 保证一定能够完整切块
        num_patches = (image_size // patch_size) ** 2  # 图像patch的个数
        patch_dim = channels * patch_size ** 2  # 线性变换时的输入大小,即下面的p1*p2*c
        assert pool in {'cls', 'mean'}, 'pool type must be either cls (cls token) or mean (mean pooling)'  # 池化方法必须为cls或者mean

        self.to_patch_embedding = nn.Sequential(
            Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = patch_size, p2 = patch_size), # 把b张c通道的图像分割成b*(h*w)张大小为p1*p2*c的图像块
            nn.Linear(patch_dim, dim),  # 对分割好的图像块进行线性处理,输入维度为每一个patch的所有像素个数,输出为dim(函数传入的参数)
        )

        self.pos_embedding = nn.Parameter(torch.randn(1, num_patches + 1, dim))  # 位置编码,获取一组正态分布的数据用于训练
        self.cls_token = nn.Parameter(torch.randn(1, 1, dim))  # 分类令牌,可训练
        self.dropout = nn.Dropout(emb_dropout)


    def forward(self, img):
        x = self.to_patch_embedding(img)  # 切块操作,shape (b, n, dim),b为批量,n为切块数目,dim为线性操作时输入的神经元个数
        b, n, _ = x.shape  # shape (b, n, 1024)

        cls_tokens = self.cls_token.repeat([b, 1, 1])  # 将self.cls_token由(1, 1, dim)变为shape (b, 1, dim)
        x = torch.cat((cls_tokens, x), dim=1)  # 将分类令牌拼接到输入中,x的shape (b, n+1, 1024)
        x += self.pos_embedding[:, :(n + 1)]  # 加上位置编码,shape (b, n+1, 1024) 不知道[:, :(n + 1)]是干嘛用的,貌似去掉也行
        x = self.dropout(x)
        return x  

パッチの埋め込みでは畳み込み層を使用せず、線形変換を使用するため、これが有利であることに注意してください。それぞれ次の 2 つのネットワークが確立されます。出力はすべて torch.Size([1, 64, 3072])

img = torch.randn([1,3,256,256])
net =  nn.Sequential(
            Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = 32, p2 = 32),
            nn.Linear(3*32*32, 3072),
        )
out_linear = net(img)

patch_embed = nn.Sequential(
    nn.Conv2d(3, 32*32*3, kernel_size=32, stride=32) 
)
out_conv = patch_embed(img).flatten(2).transpose(1, 2)

これら 2 つのネットワークのパラメータ数は 9440256 (3072*3073) です。畳み込み層の不便な点は、実際には埋め込みの最後の次元のサイズが制限されており、次元のサイズを変更したい場合は、別の線形層を追加する必要があることです。線形レイヤーを直接使用する利点は、出力の最後の設定を 1 ステップで実行できることです。

各パッチ内のピクセルが元の画像に隣接するように、線形層の入力を慎重に再形成する必要があることに注意してください (畳み込み方法ではそのような心配はありません)。ここでrerangeが使われているのですが、原理は何でしょうか、reshape関数で何をすればいいのか、まだ分かりません

テスト:

[32,3,256,256] の形状を持つ行列を入力し、各パッチのサイズは 32、埋め込み後の最後の次元のサイズは 1024 です。

img = torch.randn([32,3,256,256])
v = Embed(
    image_size = 256,
    patch_size = 32, 
    dim = 1024,
    emb_dropout = 0.1
)
out = v(img)

out の形状は次のとおりです。

torch.Size([32, 65, 1024])

4.3 トランスエンコーダ

        Transformer Encoder は実際には Encoder Block を L 回繰り返しスタックしています。特殊文字 cls および位置エンコード情報を含む前処理の後、トランスフォーマーによって入力された埋め込みパッチは 197*768 テンソルになります。

class Transformer(nn.Module):
    def __init__(self, dim, depth, heads, dim_head, mlp_dim, dropout = 0.):
        super().__init__()
        self.layers = nn.ModuleList([]) # Transformer包含多个编码器的叠加
        for _ in range(depth):
            # 编码器包含两大块:自注意力模块和前向传播模块
            self.layers.append(nn.ModuleList([
                PreNorm(dim, Attention(dim, heads = heads, dim_head = dim_head, dropout = dropout)),
                PreNorm(dim, FeedForward(dim, mlp_dim, dropout = dropout))
            ]))
    def forward(self, x):
        for attn, ff in self.layers:
            x = attn(x) + x  # 自注意力模块和前向传播模块都使用了残差的模式
            x = ff(x) + x
        return x
  • Layer Norm 層の標準化: テンソルは最初に層ノルムを渡しますが、それが出力された後も 197*768 のままです。
class PreNorm(nn.Module):
    def __init__(self, dim, fn):
        super().__init__()
        self.norm = nn.LayerNorm(dim)  # 正则化
        self.fn = fn  # 具体的操作
    def forward(self, x, **kwargs):
        return self.fn(self.norm(x), **kwargs)
  • マルチヘッドの注意: ViT の基本バージョンが使用される、つまり 12 個のヘッドが使用されると仮定すると、k、q、および v の次元は 197*64 (768/12=64) となり、k の 12 グループになります。 、q、および v が実行されます。セルフアテンション操作が実行され、最後に 12 ヘッドの出力を結合しても、出力は依然として 197*768 です。
class Attention(nn.Module):
    def __init__(self, dim, heads = 8, dim_head = 64, dropout = 0.):
        super().__init__()
        inner_dim = dim_head *  heads
        project_out = not (heads == 1 and dim_head == dim) # 多头注意力或输入和输出维度不相同时为True

        self.heads = heads
        self.scale = dim_head ** -0.5  # 缩放操作

        self.attend = nn.Softmax(dim = -1)
        self.dropout = nn.Dropout(dropout)

        self.to_qkv = nn.Linear(dim, inner_dim * 3, bias = False) # 对Q、K、V三组向量线性操作

        # 线性全连接,如果多头注意力或输入和输出维度不相同,进行映射,变换维度
        self.to_out = nn.Sequential(
            nn.Linear(inner_dim, dim),
            nn.Dropout(dropout)
        ) if project_out else nn.Identity()

    def forward(self, x):
        qkv = self.to_qkv(x).chunk(3, dim = -1)  # 先对Q、K、V进行线性操作,然后chunk成三份
        q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.heads), qkv) # 整理维度,获得Q、K、V

        dots = torch.matmul(q, k.transpose(-1, -2)) * self.scale  # 计算相关性

        attn = self.attend(dots)
        attn = self.dropout(attn)

        out = torch.matmul(attn, v)  # # Softmax运算结果与Value向量相乘,得到最终结果
        out = rearrange(out, 'b h n d -> b n (h d)')  # 重新整理维度
        return self.to_out(out)  # 做线性的全连接操作或者空操作(空操作直接输出out)

torch.chunk(tensor, chunk_num, dim) 関数の関数: torch.cat() の逆で、テンソルを dim (行または列) ごとに chunk_num 個のテンソル ブロックに分割し、タプルを返します。

並べ替え操作は、寸法を調整することです。例えば:

  1. reverserange(out, 'bhnd -> bn (hd)') は out と同じです。transpose(1, 2).reshape(B, N, C)
  2. q, k, v = map(lambda t: reverserange(t, 'bn (hd) -> bhn d', h = self.heads), qkv) は次のように記述できます。
# qkv(): -> [batch_size, num_patches + 1, 3 * total_embed_dim]
# reshape: -> [batch_size, num_patches + 1, 3, num_heads, embed_dim_per_head]
# permute: -> [3, batch_size, num_heads, num_patches + 1, embed_dim_per_head]
qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, total_embed_dim // self.num_heads).permute(2, 0, 3, 1, 4)
# [batch_size, num_heads, num_patches + 1, embed_dim_per_head]
q, k, v = qkv[0], qkv[1], qkv[2]

注意操作の全体的なプロセス:

  1. まず、入力に対してクエリ、キー、値を生成しますが、ここでの「入力」はネットワーク全体の入力でも隠れ層の出力でも構いません。ここで、生成された qkv は長さ 3 のタプルであり、各タプルのサイズは (1, 65, 1024) です。
  2.  qkv を処理して次元を再指定すると、結果の q、k、v の次元はすべて (1、16、65、64) になります。
  3.  q と k のドット乗算を実行すると、得られるドットの次元は (1, 16, 65, 65) になります。
  4.  ドットの最後の次元でソフトマックスを実行して、各パッチの他のパッチに対するアテンション スコアを取得します。
  5. 注目と価値を倍加する
  6.  各次元を再配置して、入力と同じ次元の出力 (1、65、1024) を取得します。
  7. 必要に応じて投影を実行する
  • Dropout/DropPath: 元の論文のコードでは Dropout 層が直接使用されていますが、rwightman によって実装されたコードでは DropPath (確率的深さ) が使用されており、後者の方が優れている可能性があります。
  • レイヤー標準の別のレイヤー、依然として 197*768
  • MLP ブロックは、フル接続 + GELU アクティベーション関数 + ドロップアウトで構成されます。次元を 4 倍 [197, 768] -> [197, 3072] に拡大し、元のノード数 [197, 3072] -> [197, 768] に戻します。 
class FeedForward(nn.Module):
    def __init__(self, dim, hidden_dim, dropout = 0.):
        super().__init__()
        # 前向传播
        self.net = nn.Sequential(
            nn.Linear(dim, hidden_dim),
            nn.GELU(),
            nn.Dropout(dropout),
            nn.Linear(hidden_dim, dim),
            nn.Dropout(dropout)
        )
    def forward(self, x):
        return self.net(x)

       Transformer ブロックに入る前は 197*768 であり、出てきたときも 197*768 ですが、このシーケンスの長さは各トークンに対応する次元サイズと同じであるため、Transformer ブロックを連続的に重ね合わせることができますTransformer ブロック、そして最後に L 層 Transformer ブロックを含むモデルが Transformer エンコーダーを構成します

        Transformer は、最初から最後までのベクトルの長さとして D を使用します。これは 768 です。この寸法は同じモデル内で変更されません。トランスが大きくなると、それに応じて D も大きくなる可能性があります。

Transformer は、すべてのレイヤーを通じて一定の潜在ベクトル サイズDを使用するため、パッチを平坦化し、トレーニング可能な線形投影を使用してD次元にマッピングします。この投影の出力をパッチ埋め込みと呼びます。

4.4 MLPヘッドとViT-B/16モデルの構造図

        分類するには、[class] トークンによって生成された対応する結果、つまり [197, 768] から [class] トークンに対応する [1, 768] を抽出するだけで、MLP ヘッドを通じて最終的な分類結果を取得できます。MLP Head の元の論文では、ImageNet21K を学習させる場合は Linear+tanh 活性化関数+Linear で構成されますが、ImageNet1K や独自のデータに移行する場合は Linear のみを定義すると書かれています。実際には、Transformer Encoder の後に Layer Norm があることに注意してください。

       以下はMung Bean が描いた ViT-B/16 モデル構造図のVision Transformer の詳細な説明です: (Pre-Logits は Linear+tanh であり、一般的な伝達学習が使用できます)。

class ViT(nn.Module):
    def __init__(self, image_size, patch_size, num_classes, 
                 dim, depth, heads, mlp_dim, pool = 'cls', 
                 channels = 3, dim_head = 64, dropout = 0., 
                 emb_dropout = 0.):
        super().__init__()
        self.embed = Embed(image_size, patch_size, dim, 
                 pool = 'cls', channels = 3, 
                 dim_head = 64, emb_dropout = 0.)

        self.transformer = Transformer(dim, depth, heads, dim_head, mlp_dim, dropout)  # Transformer模块

        self.pool = pool
        self.to_latent = nn.Identity()  # 占位操作

        self.mlp_head = nn.Sequential(
            nn.LayerNorm(dim),  # 正则化
            nn.Linear(dim, num_classes)  # 线性输出
        )

    def forward(self, img):
        x = self.embed(img)  # embeding操作
        x = self.transformer(x)  # transformer操作

        x = x.mean(dim = 1) if self.pool == 'mean' else x[:, 0]

        x = self.to_latent(x)
        return self.mlp_head(x)  # 线性输出

4.5 数式の説明

        (1) Xp は画像ブロックのパッチを示し、合計 N 個のパッチがあり、E は線形投影の全結合層を示し、いくつかのパッチ埋め込みが取得されます。クラス埋め込み (Xclass) をその前に接続します。全てのトークンを取得した後、位置コード情報Eposも追加する。

        Z0 はトランス全体の入力です。

        (2)-(3)サイクル

   各トランス ブロックには 2 つの操作があります。1 つはマルチヘッド セルフ アテンション、もう 1 つは MLP です。これら 2 つの操作を実行する前に、最初に層ノルムを実行する必要があり、各層の結果を残差で結び付ける必要があります。

  • ZL' はそれぞれの長い自意識の結果です
  • ZL は各変圧器ブロック全体の結果です

        (4) L層ループ終了後、ZL(最終層の出力)の先頭、つまりクラストークンに対応する出力のZL0を画像全体の特徴量として使用し、最後の分類タスク

完全なコード

import torch
from torch import nn, einsum
import torch.nn.functional as F

from einops import rearrange, repeat
from einops.layers.torch import Rearrange

class Embed(nn.Module):
    def __init__(self, image_size, patch_size, dim, 
                 pool = 'cls', channels = 3, 
                 dim_head = 64, emb_dropout = 0.):
        super().__init__()
        assert image_size % patch_size == 0, 'Image dimensions must be divisible by the patch size.'  # 保证一定能够完整切块
        num_patches = (image_size // patch_size) ** 2  # 获取图像切块的个数
        patch_dim = channels * patch_size ** 2  # 线性变换时的输入大小,即每一个图像宽、高、通道的乘积
        assert pool in {'cls', 'mean'}, 'pool type must be either cls (cls token) or mean (mean pooling)'  # 池化方法必须为cls或者mean

        self.to_patch_embedding = nn.Sequential(
            Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = patch_size, p2 = patch_size),  # 把b张c通道的图像分割成b*(h*w)张大小为P1*p2*c的图像块
            nn.Linear(patch_dim, dim),  # 对分割好的图像块进行线性处理(全连接),输入维度为每一个小块的所有像素个数,输出为dim(函数传入的参数)
        )

        self.pos_embedding = nn.Parameter(torch.randn(1, num_patches + 1, dim))  # 位置编码,获取一组正态分布的数据用于训练
        self.cls_token = nn.Parameter(torch.randn(1, 1, dim))  # 分类令牌,可训练
        self.dropout = nn.Dropout(emb_dropout)


    def forward(self, img):
        x = self.to_patch_embedding(img)  # 切块操作,shape (b, n, dim),b为批量,n为切块数目,dim为最终线性操作时输入的神经元个数
        b, n, _ = x.shape  # shape (b, n, 1024)

        cls_tokens = self.cls_token.repeat([b, 1, 1])  
        # 分类令牌,将self.cls_token(形状为1, 1, dim)赋值为shape (b, 1, dim)
        x = torch.cat((cls_tokens, x), dim=1)  # 将分类令牌拼接到输入中,x的shape (b, n+1, 1024)
        x += self.pos_embedding[:, :(n + 1)]  # 进行位置编码,shape (b, n+1, 1024)
        x = self.dropout(x)
        return x  

class PreNorm(nn.Module):
    def __init__(self, dim, fn):
        super().__init__()
        self.norm = nn.LayerNorm(dim)  # 正则化
        self.fn = fn  # 具体的操作
    def forward(self, x, **kwargs):
        return self.fn(self.norm(x), **kwargs)

class FeedForward(nn.Module):
    def __init__(self, dim, hidden_dim, dropout = 0.):
        super().__init__()
        # 前向传播
        self.net = nn.Sequential(
            nn.Linear(dim, hidden_dim),
            nn.GELU(),
            nn.Dropout(dropout),
            nn.Linear(hidden_dim, dim),
            nn.Dropout(dropout)
        )
    def forward(self, x):
        return self.net(x)

class Attention(nn.Module):
    def __init__(self, dim, heads = 8, dim_head = 64, dropout = 0.):
        super().__init__()
        inner_dim = dim_head *  heads
        project_out = not (heads == 1 and dim_head == dim) # 多头注意力或输入和输出维度不相同时为True

        self.heads = heads
        self.scale = dim_head ** -0.5  # 缩放操作

        self.attend = nn.Softmax(dim = -1)
        self.dropout = nn.Dropout(dropout)

        self.to_qkv = nn.Linear(dim, inner_dim * 3, bias = False) # 对Q、K、V三组向量线性操作

        # 线性全连接,如果多头注意力或输入和输出维度不相同,进行映射,变换维度
        self.to_out = nn.Sequential(
            nn.Linear(inner_dim, dim),
            nn.Dropout(dropout)
        ) if project_out else nn.Identity()

    def forward(self, x):
        qkv = self.to_qkv(x).chunk(3, dim = -1)  # 先对Q、K、V进行线性操作,然后chunk成三份
        q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = self.heads), qkv) # 整理维度,获得Q、K、V

        dots = torch.matmul(q, k.transpose(-1, -2)) * self.scale  # 计算相关性

        attn = self.attend(dots)
        attn = self.dropout(attn)

        out = torch.matmul(attn, v)  # # Softmax运算结果与Value向量相乘,得到最终结果
        out = rearrange(out, 'b h n d -> b n (h d)')  # 重新整理维度
        return self.to_out(out)  # 做线性的全连接操作或者空操作(空操作直接输出out)

class Transformer(nn.Module):
    def __init__(self, dim, depth, heads, dim_head, mlp_dim, dropout = 0.):
        super().__init__()
        self.layers = nn.ModuleList([])  # Transformer包含多个编码器的叠加
        for _ in range(depth):
            # 编码器包含两大块:自注意力模块和前向传播模块
            self.layers.append(nn.ModuleList([
                PreNorm(dim, Attention(dim, heads = heads, dim_head = dim_head, dropout = dropout)),  # 多头自注意力模块
                PreNorm(dim, FeedForward(dim, mlp_dim, dropout = dropout))  # 前向传播模块
            ]))
    def forward(self, x):
        for attn, ff in self.layers:
            # 自注意力模块和前向传播模块都使用了残差的模式
            x = attn(x) + x
            x = ff(x) + x
        return x

class ViT(nn.Module):
    def __init__(self, image_size, patch_size, num_classes, 
                 dim, depth, heads, mlp_dim, pool = 'cls', 
                 channels = 3, dim_head = 64, dropout = 0., 
                 emb_dropout = 0.):
        super().__init__()
        self.embed = Embed(image_size, patch_size, dim, 
                 pool = 'cls', channels = 3, 
                 dim_head = 64, emb_dropout = 0.)

        self.transformer = Transformer(dim, depth, heads, dim_head, mlp_dim, dropout)  # Transformer模块

        self.pool = pool
        self.to_latent = nn.Identity()  # 占位操作

        self.mlp_head = nn.Sequential(
            nn.LayerNorm(dim),  # 正则化
            nn.Linear(dim, num_classes)  # 线性输出
        )

    def forward(self, img):
        x = self.embed(img)  
        x = self.transformer(x)  # transformer操作

        x = x.mean(dim = 1) if self.pool == 'mean' else x[:, 0]

        x = self.to_latent(x)
        return self.mlp_head(x)  # 线性输出

テストを受けてください:

v = ViT(
    image_size = 256,
    patch_size = 32,
    num_classes = 1000,
    dim = 1024,
    depth = 6,
    heads = 16,
    mlp_dim = 2048,
    dropout = 0.1,
    emb_dropout = 0.1
)

img = torch.randn(20, 3, 256, 256)

preds = v(img)
preds.shape

パラメータの説明:

  • image_size: int型パラメータ、画像サイズ。長方形画像の場合、幅と高さの最大値
  • patch_size: int型パラメータ、パッチサイズ。image_sizepatch_size割り切れる。n 16 より大きくなければなりません
  • num_classes: int型パラメータ、カテゴリ数。
  • dim: int 型パラメータ、埋め込みの次元。
  • depth: int 型パラメータ、Transformer モジュールの数。
  • heads: int型パラメータ、マルチヘッド注意における「ヘッド」の数。
  • mlp_dim: int 型パラメータ、多層パーセプトロンの隠れ層のニューロンの数。
  • channels: int 型パラメータ、入力画像のチャンネル数、デフォルトは 3 です。
  • dropout: float 型パラメータ、ドロップアウト確率、値の範囲は[0, 1]、デフォルトは です0.
  • emb_dropout: Float 型パラメータ、埋め込み演算時のドロップアウト確率、値の範囲は です[0, 1],默认为0
  • pool: 文字列型パラメータ。値はclsまたはmean

5 アブレーション実験(付録)

特別なクラスのトークンと位置エンコーディングについて、著者は詳細なアブレーション実験も行いました。Vision Transformer では、画像を前処理する方法と画像の最終出力を後処理する方法が非常に重要であるためです。モデルは標準的なトランスです

5.1 クラストークン

        Transformer の場合、Transformer モデルがあり、その中に n 個の要素があり、その中に n 個の要素がある場合、最初に 1 つ追加するのではなく、n 個の出力に対してグローバル平均プーリングを実行して最終的な特徴を取得することができないのはなぜでしょうか。クラストークン、そして最後にクラストークンの出力を分類に使用しますか?       

        元の Transformer と可能な限り一貫性を保つために、クラス トークンも使用されます。これは、クラス トークンが NLP 分類タスクでも (文理解のグローバル機能としても) 使用されるためです。この記事のクラス トークンは、画像の全体的な特徴として扱い、このトークンの出力を MLP に送信します (MLP では、tanh は分類予測の非線形活性化関数として使用されます)。

        以前は、ビジュアル フィールドではクラス トークンは必要ありませんでした。たとえば、残差ネットワーク Res50 があり、最終段階で 14*14 の特徴マップが生成され、実際にこの特徴マップに基づいてグローバル平均が作成されます。プーリングの全体平均プーリング操作、プーリング後の特徴量は実際には直線化されてベクトルになっており、このときこのベクトルを全体的な画像特徴量として理解することができ、この特徴量を用いて分類を行う。       

        実験を通じて、著者の最終結論は次のとおりです。両方の方法が可能です。つまり、グローバル平均プーリングを通じてグローバル特徴を取得して分類することも、クラス トークンを使用して分類することもできます。この記事のすべての実験はクラス トークンを使用して行われています。主な目的は、元の Transformer にできるだけ近い状態を維持することです (可能な限り近くにいること)。著者は、人々に何か良い効果があるかもしれないと思わせたくありません。特定のトリックや、標準の Transformer でも視覚的な処理ができることを証明するために、CV にいくつかの変更が加えられています。

        2 つの方法の効果の比較を次の図に示します。

        緑色の線はグローバル平均プーリングを表し、青色の線はクラス トークンを表します。緑の線と青の線の効果は最終的には似ていることがわかりますが、著者は緑の線と青の線で使用される学習率が異なることを指摘しました。を直接使用すると、行に示すように効果がオレンジ色になる可能性があります。つまり、十分に調整する必要があります。

5.2 位置コーディング

著者はまた、主に 3 つのアブレーション実験を数多く行ってきました。

  • 1d: NLP で一般的に使用される位置エンコーディングです。この記事で最初から最後まで使用される位置エンコーディングです。
  • 2d: 1d では、画像は 9 正方形のグリッドにフォーマットされ、1 から 9 までの数字が画像ブロックを表すために使用されます。2d では、11、12、13、21 などが画像ブロックを表すために使用されます。全体的な構造情報があるため、視覚的な問題に近いです。具体的な方法としては、元の 1 次元位置コードの次元は d ですが、横座標と縦座標の両方を表す必要があるため、横座標の次元は D/2、縦座標の次元も D/2 になります。つまり、横座標と縦座標を表す D/2 ベクトルがあり、最後に 2 つの D/2 ベクトルが結合されて長さ D のベクトルが得られます。これは 2 次元位置コードと呼ばれます
  • 相対位置エンベディング (相対位置エンコーディング): 1D 位置エンコーディングでは、2 つのパッチ間の距離は、絶対距離またはそれらの間の相対距離 (テキストで言及されているオフセット) のいずれかで表すことができ、これも方法として考えることができます。画像ブロック間の位置情報を表現する

        しかし、このアブレーション実験の最終結果も次のようになります。下の図に示すように、3 つの表現方法の効果は類似しています。

  • No Pos は位置コードが追加されていないことを意味し、効果はあまり良くありませんが、特に悪いというわけではなく、61 の効果は実際にはかなり良いです。
  • 上記の 3 つの形式の位置エンコーディングを比較すると、すべてのパフォーマンスが 64 であり、違いがないことがわかります。
  • 著者は、合理的な説明であると考えていることを述べました. 彼が作成したビジョン トランスフォーマーは、画像ブロックが 224* というグローバルな種類ではなく 14*14 と小さいため、元のピクセル ブロックではなく画像ブロックに対して直接実行されました。 224なので、このような小さなブロックを並べて組み合わせるのは比較的簡単です。または、小さなブロック間の相対的な位置情報を知りたい場合は、位置コードを使用する必要はありません。 

        上記のアブレーション実験から、クラストークンはグローバル平均プーリングに置き換えることもでき、最終的な 1 次元の位置情報エンコード方法も 2 次元または相対位置エンコードに置き換えることができることがわかりますが、やりすぎないようにする必要があります。可能な限り標準トランスフォーマー向けに変更するため、この記事のビジョントランスフォーマーは引き続きクラストークンと 1 次元位置情報エンコード方式を使用します

6 モデルのディスカッション

誘導バイアス

  ビジョントランスフォーマーは、CNN よりも画像固有の誘導バイアスがはるかに少ないです。

        CNN では、局所性 (ローカリティ) と変換等分散 (翻訳等分散) がモデルの各層に反映され、この事前知識がモデル全体に​​浸透します。

        しかし、ViT の場合、MLP 層のみがローカルかつ並進可変ですが、セルフアテンション層はグローバルであり、この種の画像の 2 次元情報 ViT は基本的にあまり使用されません。画像をパッチに分割し、最初に位置エンコーディングを追加する場合にのみ使用されます。さらに、視覚的な問題に対する誘導バイアスはなく、位置エンコーディングもランダムに初期化された 1 次元情報であり、2 次元情報は含まれません。画像ブロック間のすべての距離情報、シーン情報などを最初から学習する必要があります。これは後の結果への伏線でもあります。ビジョン トランスフォーマーはあまり多くの誘導バイアスを使用しないため、小規模および中規模のデータ セットに対する事前トレーニングの効果が畳み込みニューラル ネットワークほど良くないことは理解できます。

ハイブリッド混合モデルのテスト 

        著者はこれについて実験を行いました: 画像にパッチを適用する代わりに、画像全体を Res50 などの CNN に入力し、最終的に 14*14 の特徴マップを取得します。これは、まっすぐにされた後にたまたま 196 個の要素を持ちます。新しく到着した 196 個の要素は完全に接続された層で動作し、新しいパッチ埋め込みを取得します。

        ViT と混合モデルで得られる系列の長さはどちらも 196 なので、以降の操作は同じで、すべて直接トランスフォーマに入力され、最終的に分類されます。

大きいサイズの微調整

  これまでの研究では、微調整する場合、より大きな画像入力サイズを使用すると、多くの場合、より良いモデルが得られることが示されています。しかし、事前にトレーニングされたビジョン トランスフォーマーを使用することは、実際には入力サイズの調整にはあまり適していません。パッチ サイズが同じままで画像が拡大される場合、シーケンスの長さは増加し、事前にトレーニングされた位置コードが役に立たなくなる可能性があります。

  現時点でロケーションコードを使用するにはどうすればよいですか? 著者は、実際には単純な 2D 補間を実行するだけで十分であることを発見しました (完了するには torch の公式補間関数を使用します)。ただし、これは一時的な解決策にすぎず、非常に短いシーケンスから非常に長いシーケンス (256→512 など) に変更する必要がある場合、単純な補間演算では最終的な効果が低下します。これは、微調整時のビジョン トランスフォーマーの制限でもあります。

  画像の位置情報が補間に使用されるため、このブロックのサイズ変更と画像ブロック抽出は、ビジョン トランスフォーマー内で 2D 情報の誘導バイアスを使用する唯一の場所です。

7 実験パート

        主に、残差ネットワーク、vit、およびそれらのハイブリッド モデルの表現学習能力を比較します。

        各モデルのトレーニングに必要なデータ量を理解するには、さまざまなサイズのデータ​​ セットで事前トレーニングを行ってから、多くのデータ セットでテストします。データセットの使用が主に使用されます

  • ImageNet データセット: ImageNet-1k (最もよく使用される 1000 カテゴリ、130 万枚の写真)、ImageNet-21k (21000 カテゴリ、1400 万枚の写真)
  • JFT データセット: Google 独自のデータセット (3 億枚の画像を含む)

        下流のタスクはすべて分類され、一般的に使用されるデータセットが使用されます。

  • シファール
  • オックスフォードのペット
  • オックスフォードの花

        結論: 事前トレーニングの時間コスト (事前トレーニングの長さ) を考慮すると、ビジョン トランスフォーマーは非常に優れたパフォーマンスを発揮し、ほとんどのデータ セットで最良の結果を達成しながら、トレーニングに必要な時間は短くなります。

        著者は自己教師付き実験も行いました。自己教師付き実験の結果は最良ではありませんが、それでも可能であり、より多くの可能性を秘めています。

  • 1 年が経過した後、MAE は ViT をトレーニングする自己管理型の方法が本当に効果があることを証明しました

7.1 ViT モデルのバリエーション

3 つのモデルのパラメータ (Base/Large/Huge、BERT に対応)。の:

  • レイヤー: エンコーダー ブロックがトランスフォーマー エンコーダー内で繰り返しスタックされる回数
  • Hidden Size: 埋め込み層を通過した後の各トークンのベクトルの長さに対応します
  • MLP サイズ: 隠しサイズの 4 倍
  • ヘッド: マルチヘッド アテンション用にいくつかのヘッドがあります。

        ViTaはトランスそのものだけではなく、入力にも関係します。パッチ サイズが変更されると、モデルの位置コードが異なるため、モデルの命名にはパッチ サイズも考慮する必要があります。vit-l 16 は、vit ラージ モデルが使用されていることを意味し、入力パッチ サイズは 16 です。 ※16.トランスフォーマーのシーケンス長はパッチ サイズに反比例します。モデルで使用するパッチ サイズが小さい場合、シーケンス長が増加するため計算コストが高くなります。

 7.2 ViTモデルとCNNとの比較結果

        結果は以下の通りです。次の表は、大規模なデータで事前トレーニングされた後、左の列のデータセットに対するファインチューニング(微調整)のパフォーマンスを示しています

        上の表は、いくつかの vit バリアントと畳み込みニューラル ネットワーク (ビットと騒々しい学生) を比較しています。bit と比較する理由は、bit は確かに以前は比較的大規模な畳み込みニューラル ネットワークであり、作者のチーム自体の作品であるため、比較に使用できるためです。騒々しい学生と比較すると、ImageNet 以前の最もパフォーマンスの高い方法であり、自己トレーニングに疑似ラベル (擬似ラベル) を使用する方法であり、良好な結果も得られています。

        上の表からわかるように、vit huge は比較的小さなパッチ 14*14 を使用してすべてのデータ セットで最良の結果を達成できます。

        しかし、これらの値は近すぎて、わずか数十分の 1 ポイントの差であるため、著者は別の角度から vit の利点を反映する必要があります。

        著者が安いと言っているのは、最大の vit 巨大モデルは 2500 日 tpuv3 日間トレーニングするだけで済むのに対し、ビットは 9900 日かかり、騒々しい学生は 10,000 日以上使用したことを意味します。したがって、この観点から見ると、vit は以前よりも優れているだけではありません。ビットで騒々しい学生はすぐにトレーニングする必要があり、効果はより優れているため、これら 2 つの点から、vit は畳み込みニューラル ネットワークよりも実際に優れていると結論付けることができます。

7.3 ViT の事前トレーニングにはどのくらいのデータ サイズが必要ですか? (重要な議論)

  以下の図は、さまざまなサイズのデータ​​セットで事前トレーニングした後の ImageNet での BiTt と VIT の微調整効果を示しています (x 軸、ImageNet は 1.2M、ImageNet-21k は 14M、JFT は 300M)。

        図の灰色の領域は BiT を表し、上下の境界はそれぞれ ResNet50 構造と ResNet152 構造の使用を表し、5 つの色付きの点は異なる構成の ViT です。 

  • 最小の ImageNet で事前トレーニングを行う場合、基本的にビジョン トランスフォーマーのすべてのポイントは灰色の領域の下にあります。これは、中小規模のデータ セットで事前トレーニングを行う場合のビジョン トランスフォーマーの効果が、それよりもはるかに劣ることを示しています。理由は、ビジョントランスフォーマーが事前知識 (誘導バイアス) を使用しないため、ネットワークをより良く学習させるためにはより大きなデータが必要になるためです。
  • ImageNet-21k で事前トレーニングを行うと、基本的にビジョン トランスフォーマーのすべてのポイントが灰色の領域に入り、ビジョン トランスフォーマーと resnet がほぼ同じであることを示します。
  • 特に大きなデータセット JFT-300M を使用する場合のみ、ビジョントランスフォーマーがビットに対応する res152 よりも高くなります。

        結論: ViT を使用したい場合は、少なくとも ImageNet-21k (データ量 14M) のサイズのデータ​​セットで事前トレーニングする必要があります。それ以外の場合は、CNN を使用する方が良いでしょう。ImageNet-21kよりも大きなデータセットがすでにある場合は、ビジョン トランスフォーマーを使用するとより良い結果が得られます。

        右の図は、JFT データセット上のさまざまなスケールのサブセットをサンプリングした実験結果です。微調整の代わりに特徴抽出器として ViT が使用されています。(トレーニング中に、ドロップアウト、重みの減衰、ラベルの平滑化などの強い制約を削除します。また、異なるスケールのデータセットが同じ分布から得られるため、モデル自体の特性をよりよく確認できます)

        図 3 では、著者はビジョン トランスフォーマーと resnet を比較したいため、トレーニング中にいくつかの強力な制約 (ドロップアウト、重み減衰、ラベル スムージングなど) が使用されるため、ビジョン トランスフォーマー モデル自体の特性を分析するのは簡単ではありません。図 4 では、線形少数ショット評価が行われており、事前トレーニングされたモデルを取得した後、微調整する代わりに特徴抽出器として直接見なされ、これらの特徴をロジスティック回帰に直接使用します。図では 5 ショットがマークされています。つまり、ImageNet で線形評価を行う場合、カテゴリごとに 5 つのサンプルがランダムに選択されるため、この評価は非常に迅速に行われます。著者はこの方法で多くのアブレーション実験を行ってきました。

  • 図 4 の横軸は、事前学習データセットのサイズを示しています。JFT データセットでは、すべてのデータが 1 つのデータセットから取得されており、それほど大きな分布ギャップがないため、異なるスケールのサブセットがサンプリングされています。モデルの効果はモデル自体の特性をよりよく反映することができます
  • 図 4 の結果は、実際には図 3 の結果と似ています。小さな事前トレーニングされたデータ セットを使用する場合、ビジョン トランスフォーマーは resnet よりも完全に劣ります。この記事の説明は、帰納的バイアスと制約手法 (重み減衰、ラベル平滑化など) が欠如しているためです。そのため、1,000 万のデータセットの場合、ビジョン トランスフォーマーが簡単にオーバーフィットし、最後に学習された特徴が得られません。他のタスクには適していません。
  • 事前トレーニング データセットが増加するにつれて、ビジョン トランスフォーマーの堅牢性が向上します。著者は最後の段落で、ビジョン トランスフォーマーを使用してこの種の小さなサンプル学習を行う方法を書きましたが、これは非常に有望な方向性です。

        次の図は、VIT トレーニングの方が安価であるという著者の見解を再度示しています。

        左側の Average-5 は、5 つのデータセット (ImageNet 実物、ペット、花、CIFAR-10、CIFAR-100) に対する彼の検証の平均結果です。右の画像はImageNetでの検証結果です。

        画像内の大きな点と小さな点は、さまざまな構成でサイズが異なるビジョン トランスフォーマーのバリアント、または resnet のバリアントです。すべてのモデルは JFT-300M で事前トレーニングされたモデルです。著者のトレーニングの目的は、モデルの能力をデータセットのサイズに制限することではないため、すべてのモデルは最大のデータセットで事前トレーニングされます。   

7.4 結論

  • 同じ複雑さの下で (垂直方向に沿って見ると)、ViT は BiT よりも優れており、これは ViT トレーニングが CNN よりも安価であることも示しています。
  • 小規模な場合、Hybrid ハイブリッド モデルは他の 2 つよりもうまく機能します。論理的に言えば、ハイブリッド モデルは両方の利点を吸収する必要があります。事前トレーニングにあまり多くのデータを必要とせず、同時にビジョン トランスフォーマーと同じ効果を達成できます。
  • モデルの規模が大きくなるにつれて、Hybrid の精度は徐々に ViT の精度に匹敵し、同じ計算条件では ViT の精度よりもさらに悪くなります。畳み込みニューラル ネットワークによって抽出された特徴が ViT の学習を改善するのに役立たないのはなぜですか? 著者はここではあまり説明しませんでした。
  • ViT も BiT も、規模が拡大してもパフォーマンスが飽和する兆候は見られません。しかし、この図から判断すると、畳み込みニューラルネットワークの効果は飽和していないことがわかります。

8 ViTの可視化   

        著者はまた、いくつかの視覚化を作成し、これらの視覚化を通じてビタミンの内部表現を分析したいと考えました。

パッチ埋め込みの視覚化

      上の図は、E (線形投影層の最初の層) がどのように画像ピクセルを埋め込むかを示しています。最初の 28 個のトークンの視覚化結果のみが表示されています。結果は CNN に似ていることがわかります。CNN は、色やテクスチャなどのいくつかの基礎的な特徴から抽出され、各画像ブロックの基礎的な構造を記述するために使用できます。 。

位置埋め込みの視覚化

        上図の中央は、異なるパッチ間の位置コードのcos類似度を示しており、1に近いほど類似していることを示します。同じ座標であれば、自分と比べて類似度が最も高いはずです。黄色の (最も類似した) 位置はパッチ自体の位置に対応しており、「主人公」に近づくほど点が黄色くなり、学習された位置コードが何らかの距離情報を表すことができることを示していることがわかります。同時に、行と列の規則も学習し、各画像ブロックは同じ列内でより高い類似性を持ち、これは 1 次元の位置コードでありながら 2 次元画像の距離の概念を学習したことを意味します。 1d で十分であるため、2d 位置エンコーディングに切り替えた後も効果が改善されない理由も説明できます。       

自己注意は機能しますか?

        ViT がどのように自己注意を使用して画像内の情報を統合するかを理解するために、さまざまなレイヤーの平均注意距離を分析します。   

        上の図は、24 層ある vitlarge 16 モデルを示しています。そのため、横軸で表されるネットワークの深さは 0 から 24 です。図のカラフルな点は、各トランス ブロック内のマルチヘッドセルフアテンション ヘッドです。 vit ラージの場合、合計 16 個のヘッドがあるため、各列には実際には 16 ポイントがあります。縦軸は、平均注目距離の平均注目距離を表す。図上の 2 つの点は、平均注意距離です。これは、2 つの点のピクセル間の距離に、それらの間の注意の重みを掛けたもので、モデルが非常に離れた 2 つのピクセルに気づくことができるかどうかを反映します。

        法則: 最初の数層では、一部のヘッド間の距離は非常に近く、20 ピクセルに達する場合もありますが、一部のヘッドは 120 ピクセルに達する場合もあります。これは、ネットワークの最下層では、自己注意がグローバルな情報に注意を払っていることを証明しています。一方、ボリューム ニューラル ネットワークとは異なり、最初の層の受容野は最初は非常に小さく、近くのいくつかのピクセルしか見えません。ネットワークが深くなるにつれて、ネットワークによって学習される機能はより高度になり、意味的により有益になります。ネットワークの後半では、モデルの自己注意距離はすでに非常に遠くなっています。つまり、モデルは判断を行うために隣接するピクセルに依存するのではなく、意味論的な概念を学習しています。

一部のヘッドはすでに最下層にある画像の大部分に注目していることがわかり、情報をグローバルに統合する機能がモデルによって実際に使用されていることを示しています。他のアテンションヘッドは、低層で一貫して小さなアテンション距離を持っています。この高度に局所的な注意は、Transformer の前に ResNet を適用するハイブリッド モデルではそれほど顕著ではありません (図 7、右)。これは、CNN の初期の畳み込み層と同様の機能を果たす可能性があることを示唆しています。さらに、注目の距離はネットワークの深さに応じて増加します。

アウトトークンの出力

        上の図は、ネットワークの最後の層の out トークンを使用して行われた、上記の注意の結果の別の検証です。この図から、出力トークンの自己注意が元の入力画像に屈折して戻ると、モデルが実際にこれらの概念を学習したことがわかります。出力トークンはすべての情報 (グローバル特徴) の融合であるため、モデルはすでに最終的な分類に関連する画像領域に焦点を当てることができます。       

全体的に見て、このモデルは分類に意味的に関連する画像領域に対応していることがわかります (図 6)。

9 自己指導型トレーニング

  この部分が付録ではなく本文に掲載されているのは、Transformer モデルが NLP 分野の促進に確かに大きな役割を果たしたと著者が信じているためですが、Transformer の人気を本当に高めるもう 1 つの理由は、実際には大規模な自己教師ありトレーニングです。 。

  NLP における自己監視手法は、MLM タスクまたは次の単語予測です。この記事では BERT を模倣しているため、著者は ViT に特有の目的関数マスク パッチ予測の構築を検討します。具体的には、与えられた画像を多くのパッチに分割し、いくつかのパッチをランダムに消去し、これらのパッチをこのモデルを通じて再構築します。

  しかし、最終的に、ViT-Base/16 は ImageNet 上で 80 程度の正解率しか達成できず、ビジョン トランスフォーマーを最初からトレーニングした場合と比べて 2 ポイント向上しましたが、最高の教師付きトレーニングとはまだ 4 ポイントの差があります。 。したがって、比較研究の結果は今後の課題と考えている。

        自己教師あり学習の中で対比学習が最も優れており、次に登場したViT MoCo v3やDINOはViTをベースとした対比学習を採用しています。

10 まとめ

内容的には、ビジョントランスフォーマーをさまざまな角度から分析、改善、推進することができます。

  • タスクの観点から見ると、ビジョン トランスフォーマーは分類のみを行うため、検出、セグメンテーション、さらには他の分野のタスクにも使用できます。
  • 構造を変更するという観点から見ると、最初のトークン化を変更することも、途中のトランスフォーマー ブロックを変更することもできます。その後、何人かの人々が self-attention を MLP に置き換えましたが、それでも非常にうまく機能します (例: mataformer は、自己注意をプーリング操作に直接置き換えます。視覚領域でも良好な結果を達成できます)。そのため、モデルを改善するためにやるべきことはたくさんあります。
  • 目的関数の観点から、監視を継続して使用することも、さまざまな自己監視トレーニング方法を試すこともできます。

        最も重要なことは、vit は NLP と CV の間のギャップを打ち破ることです。ビデオ、オーディオ、さらにはタッチベースの信号にも使用でき、さまざまなモダリティの信号を使用できることになります。

おすすめ

転載: blog.csdn.net/iwill323/article/details/128387287