Vision Transformer

#モチベーション
以下のことが気になった為

* CNNなしで画像分類でSOTAを達成したモデルとどのような構造か？
* CNNなしで画像分類でSOTAを達成したその理由
→CNNより局所的、大局的情報を取得できているためか
* CNNよりいいのか？
→事前学習で画像枚数が9千万枚以上学習できるのであればVitのほうが良い
* CNNは要らなくなるのか？→モデルが小さい場合は必要だろう

# 論文
[AN IMAGE IS WORTH 16X16 WORDS:TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE](https://arxiv.org/pdf/2010.11929.pdf)

# 何がすごいのか？
①SOTAのmodelより学習時間が減っている。精度向上。
パラメータ数が10億個あるBig Transfer(Bit)よりも学習時間が減っている
それでも、TPUv3で230daysとか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/06516845-1a89-c91f-f9eb-073f18210d3e.png)

②CNNいらず
CNN使っている気がするが...

#Vit Transformerの構造
Vitの全体ぞうは以下である
①パッチに分割
②ベクトル化
③CLSの追加
④位置情報の付加
⑤Attentionへ入力
⑥MLP
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/b96955da-6617-5620-5de5-41a7fb43c94b.png)

以下、文章の場合のTransformerと対比しながら見ていく

# ①パッチに分割する
* 文章の場合

【To be, or not to be, that is the question.】

という英文があったとき、以下のように分割する

【"To", "be", ",", "or", "not", "to", "be", ",", "that", "is", "the", "question", "."】

* Vitの場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/9d8e3651-78aa-1fc2-8343-aa71d117fd60.png)

上記例でいえば、パッチN=4（4枚に分けている）
パッチNはパッチサイズP(128）画像サイズWH（今回は256*256）より
N=HW/P^2＝256*256*/128*128＝4で求まる
[参考](https://qiita.com/omiita/items/0049ade809c4817670d7)



# ②ベクトル化
* 文章の場合

エンコーダ：問題を解けるような形式にエンコード（暗号化）する
デコーダ：暗号復元で英語→日本語に変換する

Transformerのエンコーダに入力するためにベクトル表現に変換する.

【"To", "be", ",", "or", "not", "to", "be", ",", "that", "is", "the", "question", "."】
それぞれの単語を特徴ベクトルで見分けれるようにする。
各単語の特徴量は任意に決めることができる。
例えば、300次元とすれば、この英文は13*300のベクトルで表現できる。
この特徴量を学習する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/9f1e3d7d-079e-707c-a4a9-c8b77b2f0733.png)
[参考](https://dajiro.com/entry/2020/06/25/223525)

* Vitの場合
VItの場合も画像を特徴量に変換してTransFormerに入力できる形式にする。
P^2*C(P:パッチサイズ 128  C:3ch)のものを線形変換する。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/105541ff-a5ca-f026-1a10-04b00e4bbe11.png)

どの実装が正しいのか分かっていません。
全結合で特徴量に変換しているが、論文中にはFilterで変換との記載がある。また、Filterを可視化するとConvolution層の序盤のような可視化画像があることから、下記実装①があっているか不明。実装②はConv2Dを使用して変換しているが、こればCNNは使用していないと言えるのか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/a26a58e5-736d-a2f3-89a3-27b54efadaa1.png)


[実装①](https://github.com/lucidrains/vit-pytorch)
全結合で3072->128次元の出力に変換している。

```python:qiita.py
#入力サイズは1バッチ分のデータ64、3チャネル、224*224
 x = rearrange(img, 'b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = p, p2 = p)
#により、1バッチの64データ分、パッチの49個の画像に1画像を分割（224*224/32/32=49)、1画像分の32*32*3chを1次元の配列に直すと3072の配列となる

x = self.patch_to_embedding(x)
print(f"after patch_to_embedding:{x.shape}")
 self.patch_to_embedding = nn.Linear(patch_dim, dim)#patch_dim:3072 dim:128(出力）
```
[実装②](https://github.com/google-research/vision_transformer) にあるEmbeddingの実装ではConv2dが使われている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/474933cb-bdc0-c538-4a3a-da41dae51192.png)

# ③CLSの追加
* 文章の場合

[BERT](https://arxiv.org/pdf/1810.04805.pdf)
記事を入力して、9つのニュース記事のグループのうち、どのグループに属する記事かを推論する場合。

BERTにはCLS（クラス）とSEP（文章の終わり）が存在する。
分類タスクの場合はCLSが使用される。
CLSの出力にMLPなどを接続して分類する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/1efbf8f0-0587-b3f8-e2d5-f9012d73d12d.png)


* Vitの場合

BERT同様にCLSを付加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/74042024-dca1-ac3e-76d7-19a318fcea09.png)


# ④位置情報の付加

* 文章の場合
語順情報の付加
単語の重要度を評価できるが、語順情報を考慮できない為、語順情報をベクトルに付加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/b5e1a988-0202-6337-935b-cd3edb51bae4.png)

posは文章の中で何番目の単語かを表し、iはその単語の特徴量ベクトルのうち何次元目の数値かを表す。
つまりPEは（単語数×埋め込み次元）の形状の配列であり、文章を表す特徴量のテンソルと同じ形状をしてる。
この2つのテンソルを要素ごとに加算することで、Positional Encodingの処理が完了する。

特徴量を300次元とした場合、300次元それぞれに位置の情報を加算する

* Vitの場合

各パッチの特徴量とCLSに位置情報を付加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/b7a7ff77-ec48-838c-6127-e8690c5b06e9.png)

バッチ数が64 パッチ数が49 128次元とした場合(64,49,128),CLSを足して(64,50,128)のテンソルに対して(64,50,128)の形状をしたPEで位置情報を付加する。
1番目のパッチには1を2番目のパッチには2を・・・。加える数は学習する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/8f5d7082-33fa-5a1c-1caf-f277985f7b18.png)

筆者は2Dの位置情報を付加することや、相対距離を付加することも試しているが、顕著な精度の向上は見られていない。元の画像が224*224でもパッチレベルでは14*14などで、学習が簡単で差が出なかったのではと考察している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/bb57920c-71a4-5608-48e4-3d7ee727da90.png)

2D
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/5d9bd016-110d-5aa7-1d8e-2e97a6376dd1.png)


付加する値はパッチの行列が同じだと類似度が高くなる傾向になっている。
パッチ1とパッチ１は同じなので黄色。
同じ行の1-2,3,4,5,6,7とは似た値が付加される為類似度が高くなっている。列方向も同じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/77b34e75-639f-0f41-60d8-305bfe7c643e.png)

ハイパーパラメータによってこの類似度は変わる（加算する値の傾向が変わってくる）。
位置情報の追加の方法より、ハイパーパラメータのほうが重要。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/188e1c9b-838f-0877-e094-d67733bdcbac.png)


# ⑤Attentionへ入力
[Attentionの復習](https://qiita.com/asparagasu/items/6fdd8a842422394f56b1)

* 文章の場合
* 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/026d50ca-d3d5-8890-f334-46fd2e706a85.png)

Layer Normalization
50個の分、1つの文が128単語とした時に128単語にまたがって正規化を行う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/941a8818-19fd-e36b-dfc4-4fb700447b1d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/cf4a5796-adce-593a-932d-2a09eb84e275.png)


* Vitの場合
Layer Normの箇所が異なるのと、層を深くするために残渣結合がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/2ea56439-2129-5eeb-b051-269baf0106fb.png)


# SOTAとの比較
SOTA modelをVITが上回っている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/6d3bd668-bedc-c032-17f5-bba24e41e10c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/1b6c39ee-ceb8-7fc2-36ca-23590323827e.png)
各ベンチマークでVitのほうが性能が良い。
[VATB](https://webbigdata.jp/ai/post-4432)は統一されたベンチマークのこと

# 事前学習
小規模データセットであるImageNet（クラス1,000個の計130万枚）
中規模ImageNet-21k(クラス21,000個の計1,400万枚）
大規模JFT-300M（クラス18,000個の計3億枚） 
で事前学習してImageNetへ転移学習した時の性能。
データセットが少ないときはVitの性能は低い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/0dd86fda-27d8-26a8-1601-fbc4476a6bfb.png)

30M（3千万枚）以下は性能が低い
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/cf71dc9f-1dfa-4d96-e03c-29728c2fe021.png)

# Attention Distance
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/17acde32-be50-d219-3838-887067f9d7bd.png)

画像サイズ：224
ヘッド数：16
試行画像数：128

Attention DistanceはCNNにおける受容野の大きさと同じ
ネットワークが浅いほど参照している画素距離が近く
ネットワークが深くなるほど、広い範囲を参照している
HybridModel（Attentionへの入力がResNetで抽出した特徴量）だと層が浅いときから比較的大きな領域を見ている。

# Attentionの可視化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/de457641-0ddc-d972-876e-73ba38601d01.png)

# Hybrid Architecture
入力を画像のパッチではなく、Resnetで得た特徴量を入力する
赤：モデルが小さいときにはVitの精度をわずかに上回る
緑：Hybridがコスパがよい
青：モデルが大きくなるとVitのほうが良くなる。さらに向上できるようにも思える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/21ce9ad4-0aa4-b1b9-76a5-70d8ee3a489f.png)

# 参考
[参考:1](https://kai760.medium.com/vit-vision-transformer-%E3%81%AE%E8%A6%81%E7%82%B9%E3%82%92%E3%81%BE%E3%81%A8%E3%82%81%E3%82%8B-eacbc26fd016)
[参考:2](https://qiita.com/omiita/items/07e69aef6c156d23c538)
[参考:3](https://qiita.com/omiita/items/0049ade809c4817670d7)
[参考:4](https://ai-scholar.tech/articles/transformer/visiontransformer)
[参考:5](https://deeplearning.hatenablog.com/entry/transformer)
[参考:6](https://deepsquare.jp/2020/10/vision-transformer/)
[参考:7](https://qiita.com/halhorn/items/c91497522be27bde17ce)