必要なのはパッチだけ
公開: [2022 年 1 月 24 日に提出];
発行されたジャーナル/会議: Computer Vision and Pattern Recognition;
紙のアドレス: https://arxiv.org/abs/2201.09792;
コードアドレス: https://github.com/locuslab/convmixer;
0 要約
CNN は長年にわたってコンピューター ビジョン タスクの主要なアーキテクチャでしたが、最近の研究では、Transformer ベースのモデル、特に ViT が場合によっては CNN のパフォーマンスを上回ることが示されています (特に後期の swin Transformer は CNN を完全に凌駕し、Milestone );
ただし、Transformer の自己注意実行時間は 2 次/平方 ( O ( n 2 ) O(n^2)O ( n2 ))、ViT はパッチ埋め込みを使用して、画像の小さな領域を単一の入力特徴に結合し、より大きな画像サイズに適用します。
ViT のパフォーマンスは、Transformer 自体が十分に強力であるためなのか、それとも入力がパッチであるためなのかという疑問が生じます。
この論文は、後者のいくつかの証拠を提供します。
このホワイト ペーパーでは、非常に単純なモデルを提案します。
-
MLP-Mixer はパッチを入力として直接操作し、ミキシング情報を空間次元とチャネル次元に分離し、ネットワーク全体で同じサイズと解像度を維持します。
-
ConvMixer は、標準の畳み込みのみを使用してミキシング ステップを実装します。
その単純さにもかかわらず、このホワイト ペーパーでは、ResNet などの従来のビジョン モデルに加えて、ConvMixer が ViT、MLP-Mixer、および類似のパラメーター数とデータセット サイズのいくつかのバリアントよりも優れていることを示しています。
1 はじめに
このホワイト ペーパーでは、次の質問について検討します。ViT の強力なパフォーマンスは、Transformer 構造自体によるものですか、それとも、このパッチの表現から派生したものなのでしょうか?
この論文では、最近提案された MLP-Mixer (Tolstikhin et al, 2021) との類似性から、「ConvMixer」と呼ばれる非常に単純な畳み込みアーキテクチャを提案します。
ConvMixer の多くの側面は、 ViT または MLP-Mixer に似ています。
- パッチを直接操作します。
- すべてのレイヤーで同じ解像度とサイズの表現を維持します (フィーチャ マップは次元を削減せず、ダウンサンプリングも行いません)。
- 連続するレイヤーの表現はダウンサンプリングされません。
- 情報の「チャネル ミキシング」を「空間ミキシング」から分離します (深さ方向および点方向の変換)。
違い:
- ConvMixer は、これらすべてを標準的な畳み込みだけで行います。
結論: パッチの表現形式は非常に重要です。
2 ConvMixer モデル
2.0 モデルの概要
写真 2 のように:
- 入力画像サイズはc × n × nc × n × nc×n×n、c チャネル、n 幅/高さ。
- パッチサイズはppp、パッチ埋め込み後の数はn / p × n / pn/p × n/pn / p×n / p、h 次元に埋め込まれたベクトル、ベクトル ブロック (特徴マップとも呼ばれる) を取得h × ( n / p ) × ( n / p ) h×(n/p)×(n/p)時間×( n / p )×( n / p );
- このパッチの埋め込みは、Transformer のパッチの埋め込みとは異なります。
- このステップは、入力チャネルをccとして使用することと同じです。c、出力チャネルはhhh、畳み込みカーネル サイズ = patch_size、ストライド = patch_size 畳み込みカーネル デコンボリューションされた機能マップ。
- この特徴マップに対して GeLU アクティベーションと BN を実行し、ConvMixer レイヤーに入力します。
- ConvMixer 層は、深い畳み込みの深さ方向の畳み込みと、点ごとの畳み込み、点ごとの畳み込み、および残差接続で構成されます.各畳み込みの後、GeLU アクティベーションと BN が行われます。
- 深さ方向の変換: will hhhチャネルのそれぞれが畳み込まれます => 空間ミキシング。
- pointwise conv: 1×1 畳み込み、チャネル間の混合。
- ConvMixer レイヤーは深度時間を循環させます。
- 最後に、分類ヘッダーにアクセスします。
パイトーチの実装:
class ConvMixerLayer(nn.Module):
def __init__(self,dim,kernel_size = 9):
super().__init__()
#残差结构
self.Resnet = nn.Sequential(
nn.Conv2d(dim,dim,kernel_size=kernel_size,groups=dim,padding='same'),
nn.GELU(),
nn.BatchNorm2d(dim)
)
#逐点卷积
self.Conv_1x1 = nn.Sequential(
nn.Conv2d(dim,dim,kernel_size=1),
nn.GELU(),
nn.BatchNorm2d(dim)
)
def forward(self,x):
x = x +self.Resnet(x)
x = self.Conv_1x1(x)
return x
class ConvMixer(nn.Module):
def __init__(self,dim,depth,kernel_size=9, patch_size=7, n_classes=1000):
super().__init__()
self.conv2d1 = nn.Sequential(
nn.Conv2d(3,dim,kernel_size=patch_size,stride=patch_size),
nn.GELU(),
nn.BatchNorm2d(dim)
)
self.ConvMixer_blocks =nn.ModuleList([])
for _ in range(depth):
self.ConvMixer_blocks.append(ConvMixerLayer(dim=dim,kernel_size=kernel_size))
self.head = nn.Sequential(
nn.AdaptiveAvgPool2d((1,1)),
nn.Flatten(),
nn.Linear(dim,n_classes)
)
def forward(self,x):
#编码时的卷积
x = self.conv2d1(x)
#多层ConvMixer_block 的计算
for ConvMixer_block in self.ConvMixer_blocks:
x = ConvMixer_block(x)
#分类输出
x = self.head(x)
return x
model = ConvMixer(dim=128,depth=2)
print(model)
ConvMixer(
(conv2d1): Sequential(
(0): Conv2d(3, 128, kernel_size=(7, 7), stride=(7, 7))
(1): GELU()
(2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(ConvMixer_blocks): ModuleList(
(0): ConvMixerLayer(
(Resnet): Sequential(
(0): Conv2d(128, 128, kernel_size=(9, 9), stride=(1, 1), padding=same, groups=128)
(1): GELU()
(2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(Conv_1x1): Sequential(
(0): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1))
(1): GELU()
(2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): ConvMixerLayer(
(Resnet): Sequential(
(0): Conv2d(128, 128, kernel_size=(9, 9), stride=(1, 1), padding=same, groups=128)
(1): GELU()
(2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(Conv_1x1): Sequential(
(0): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1))
(1): GELU()
(2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
)
(head): Sequential(
(0): AdaptiveAvgPool2d(output_size=(1, 1))
(1): Flatten(start_dim=1, end_dim=-1)
(2): Linear(in_features=128, out_features=1000, bias=True)
)
)
2.1 パラメータ設計
ConvMixer のインスタンス化は、次の 4 つのパラメーターに依存します。
- 「幅」または隠し寸法:hhh (パッチ埋め込みの次元);
- ConvMixer レイヤーのサイクル数: depth depth深い; _ _ _
- モデルの内部解像度を制御するパッチ サイズ: ppp;
- 深さ方向の畳み込み層のカーネル サイズ: kkか;
他の ConvMixer モデルの命名規則: ConvMixer-h/d;
2.2 動機
私たちのアーキテクチャはミキシングの考え方に基づいています; 特に、深さ方向の畳み込み dw を選択して空間位置を混合し、点畳み込み pw を選択してチャネル位置を混合します。
以前の研究からの重要な洞察は、MLP と自己注意が離れた空間位置を混在させることができる、つまり、任意に大きな受容野を持つことができるということです。したがって、大規模なカーネル畳み込みを使用して、離れた空間位置をブレンドします。
自己注意と MLP は理論的にはより柔軟であり、大きな受容野とコンテンツ認識行動を可能にしますが、畳み込みの誘導バイアスはビジョン タスクに適しています。このような標準的な操作を使用することで、従来のピラミッド型の漸進的にダウンサンプリングされた畳み込みネットワーク設計と比較して、パッチ表現自体の効果も確認できます。
3回の実験
3.1 トレーニング設定
事前トレーニングやその他のデータなしで、主に ImageNet-1k 分類で ConvMixers を評価します。
ConvMixer を timm フレームワークに追加し、標準に近いセットアップでトレーニングします。デフォルトの timm 増強に加えて、RandAugment、mixup、CutMix、ランダム消去、勾配ノルム クリッピングを使用します。AdamW オプティマイザを使用します。
コンピューティングが限られているため、ImageNet ではハイパーパラメーターの調整をまったく行わず、競合他社よりも少ないエポックでトレーニングします。
したがって、私たちのモデルは過剰に正則化されているか過小に正則化されている可能性があり、報告された精度はモデルの機能を過小評価している可能性があります。
3.2 実験結果
- 精度: ImageNet では、52M のパラメーターを持つ ConvMixer-1536/20 は 81.4% のトップ 1 精度を達成でき、21M のパラメーターを持つ ConvMixer-768/32 は 80.2% のトップ 1 精度を達成できます。
- 幅: より広い ConvMixers はより速く収束するように見えますが、大量のメモリと計算が必要です。
- カーネル サイズ: カーネル サイズを k = 9 から k = 3 に減らすと、ConvMixer-1536/20 の精度は約 1% 低下します。
- パッチ サイズ: 小さいパッチの ConvMixer は基本的に優れており、大きいパッチにはより深い ConvMixers が必要になる場合があります; パッチ サイズを 7 から 14 に増やすことを除いて、すべて同じままで、ConvMixer-1536/20 は上位 -1 精度の 78.9% を達成します。しかし、約 4 倍高速です。
- アクティベーション関数: モデルを ReLU でトレーニングし、最近の等方性モデルで人気のある GELU が不要であることを証明しました。
3.3 比較
ConvMixer モデルと ResNet/DeiT/ResMLP を比較した結果を表 1 と図 1 に示します。
- 同じ量のパラメーターを使用すると、ConvMixer-1536/20 のパフォーマンスは ResNet-152 および ResMLP-B24 よりも優れています。
- ConvMixer は、おそらくパッチ サイズが小さいため、競合他社よりも推論がはるかに遅くなります; ハイパーパラメーターの調整と最適化により、このギャップを埋めることができます。詳細な説明と比較については、表 2 と付録 A を参照してください。