[論文読み] Bag of Tricks for Image Classification with CNNs

[元論文](https://arxiv.org/abs/1812.01187)

## 論文概要

2018年の終わりに出版された論文であり、画像分類で使用されるテクニックの紹介を行っています。ResNet50のモデルにてモデル自体の構造を大きく変化させることなく、ImageNetでの分類精度を75.3%から79.29%に向上させています。

また近年Kaggleなどでの多く見られるFastaiのモジュールでもこれらのテクニックがふんだんに使用されており、分類精度を向上させることができています。

この記事では、論文中で紹介されているテクニックがどういったものなのかを紹介します。

![](https://paper-attachments.dropbox.com/s_A6FFC5F667CD23AF0DC91C20F45AAA96FB6AB09803A81864009EABE03C72C5E7_1564329930387_file.png)

## テクニック

論文中で言及されているテクニックは以下になります。

### [1] Large-Batch Training

ミニバッチ確率的勾配法を大きなバッチサイズで行う場合、小さなバッチサイズのときと比較して、学習の進捗が遅れるときがあります。
そのため大きなバッチサイズで学習させる際は、より長い時間をかけて学習させる必要が出てきます。

この問題に関して、大きなバッチサイズで学習を早めるために以下の4つの経験的知見が存在しています。

### [1-1] Linear Scaling Learning Rate

バッチサイズを大きくすることで、確率的勾配法によって計算される勾配の期待値を変化させることなく、勾配の分散を抑えることができます。
そのため、感覚的には学習率を上昇させても、勾配の逆方向に学習を進めることができます（？）。

初期の学習率を0.1、バッチサイズを256にした場合、学習率を$0.1\times b/256$で上昇させれば、学習がうまくいくと報告されています。しかしあくまでImageNetの場合なので検討は必要です。

### [1-2] Learning Rate Warmup

パラメータがランダムに選択されているため、学習初期は最終的に得られるパラメータからかけ離れています。
そこで提案されたものが、学習率を0の状態から、徐々に設定した値に近づけていくという方法です。具体的には、初期の学習率を$\eta$とした場合、最初の$m$バッチまでは$i\eta / m, 1 \ge i \ge m$の比率で学習率を上昇させていく形になります。

### [1-3] Zero γ

ResNetの構造では、1つの処理のブロックの最終層の出力を $block(x)$ と表現した場合、全体の出力は $x + block(x)$ と表現されます。
最終層の処理はバッチ正則化になっており、$\gamma x + \beta$ の計算を行い出力結果の安定化させる役割があります。
ここでブロックの最後にあるバッチ正則化層をすべて $\gamma=0$ で初期化させると残差ブロックとしては入力をただ返すのみであり、初期段階での学習が簡単なネットワークを模倣することができます（？）。

### [1-4] No bias Decay

通常weight decayは学習するパラメータのすべてに適用し、これはパラメータにL2正則化をかけていることと同等です。
経験則として提案されていることは、過適合を防ぐために重みにのみweight decayを適用させることで、ほかのバイアス項やバッチ正則化のパラメータには、何も適用しません。

### [1-5] Low-Precision Training

通常モデルの学習は32ビット浮動小数点型で実行されるが、NVIDIA V100のようなTensorCoreを採用した、VoltaやTuringのアーキテクチャを使用することで、16ビットでの計算も可能になりました。

16ビットでの計算に変更することで、V100の場合はおおよそ2倍から3倍にまで計算速度が向上しています。

![](https://paper-attachments.dropbox.com/s_A6FFC5F667CD23AF0DC91C20F45AAA96FB6AB09803A81864009EABE03C72C5E7_1564330012679_file.png)

## Model Tweaks

どのようなモデルであっても、畳み込み層のストライドを変更するなどの、小さな変化を加えることで、精度の向上につながることがあります。
今回はResNetの構造をいくつか見ていきます。

![図1　通常のResNet構造](https://media.arxiv-vanity.com/render-output/994982/x1.png)

ResNetの基本構造は図1で表現され、最初の層で画像のサイズを4分の1に縮小させ、チャンネルサイズを64まで増加させます（なぜこの数値？）。

ResNetのstage2からは、ダウンサンプリングブロックから始まります。
残差ブロックは2つの計算経路から構成されます。

- path A
    - 1x1 Conv(stride=2) → 3x3 Conv → 1x1 Conv(4x channels)
- path B
    - 1x1 Conv(stride=2)

最終的に両者の経路からの出力を足し合わせることで、最終的な出力を得ます。

ResNetの残差ブロックの派生を見ていく。


![](https://media.arxiv-vanity.com/render-output/994982/x2.png)


これはTorchによる実装で初めて提案されて物で、残差ブロックの中でもダウンサンプリング部分の変更になっています。
初期のResNetのPath Aでは、畳み込みのカーネルサイズは1であるにもかかわらず、ストライドが2であるため、$3/4$の情報が抜け落ちてしまいます。
そこで3x3畳み込みの部分でストライドを2に設定することで、情報の抜け落ちを防ぐようにしています。

![](https://media.arxiv-vanity.com/render-output/994982/x3.png)

これはInception-V2で提案された構造であり、SENet・PSPNet・DeepLabV3・ShuffleNetV2の実装にも見られます。
もともと入力の部分では7x7畳み込みが使用されていましたが、7x7畳み込み層の計算コストは3x3と比較すると5.4倍になってしまいます。そこで7x7の代わりに、3x3を3層重ねる構成にしています。
1層目と2層目の畳み込みの出力チャンネルを32、3層目の畳み込みの出力チャンネルを64に設定します。

![](https://media.arxiv-vanity.com/render-output/994982/x4.png)

ResNet-Bから着想を得た構造です。ダウンサンプリングブロックのPath Bでは、1x1畳み込みによって、情報が$3/4$抜け落ちてしまっています。
そこで畳み込み層でストライドを2に設定するのではなく、直前に2x2平均プーリングをストライド2で採用することで、情報の抜け落ちを防ぐことができます。

![](https://paper-attachments.dropbox.com/s_A6FFC5F667CD23AF0DC91C20F45AAA96FB6AB09803A81864009EABE03C72C5E7_1564329988834_file.png)

## Cosine Learning Rate Decay

初期の学習率を0に設定し、最初の$m$バッチ目の計算で設定した学習率にまで戻した後は、徐々に学習率を下げていく方法がよく使用されます。

その中でも広く採用されているものが、Exponentially Decayであったり、Step Decayになります。また2エポックごとに0.94の比率で落としていく手法も存在します。

最近提案されたものの一つが、Cosine Annealingであり、cos関数に従って学習率を徐々に下げていく方法です。全体のバッチ数を$T$と設定した場合、計算しているバッチが$t$の場合に、以下の計算式で表現されます。

$$\eta_t = \frac 12 \left(1 + \textrm{cos}\left(\frac{t\pi}{T}\right)\right)\eta$$

![](https://paper-attachments.dropbox.com/s_A6FFC5F667CD23AF0DC91C20F45AAA96FB6AB09803A81864009EABE03C72C5E7_1564330049980_file.png)

## Label Smoothing

通常分類タスクのモデルの最終層は、出力ユニット数がクラス数に応じた線形結合層になっています。確率スコアは、以下のようにあるクラスに対する予測スコア（logits）$z_i$をSoftMaxして計算します。

$$q_i = \frac{\exp(z_i)}{\sum_{j=1}^K \exp(z_j)}$$

ラベルの値は、$p_{i}=1 \ \ (if \ \ i=y)$なので以下のように変形できます。

$$\ell(p, q) = - \sum_{i=1}^K p_i \log q_i = -z_{y}+\log{\sum_{i=1}^{K} \exp{z_{i}}}$$

第2項目が十分小さい場合、この関数の最適解は $z_{y}^{*}=Inf$ になります。
予測するlogitsが無限大になるため、過剰適合につながってしまう出力スコアを計算するようになってしまう可能性があります。

label smoothing とはInception-V2で導入されたアイデアであり、正解のラベルを以下の式を使用して定義します。

$$q_i = \begin{cases}   1-\varepsilon & \quad\textrm{if } i = y, \\    \varepsilon / (K-1) & \quad\textrm{otherwise,} \end{cases}$$

こうすることで最適を以下のように変換することができます。

$$z_i^* = \begin{cases}   \log( (K-1)(1-\varepsilon)/\varepsilon) + \alpha & \quad\textrm{if } i = y, \\    \alpha & \quad\textrm{otherwise,} \end{cases}$$

$\epsilon=1, \ \ K=1000$ の条件で計算すると理論上のギャップは9.1になります。
実際の計算結果を確認すると、分布の中心が理論値に近づいていき、極端なギャップが発生することがなくなります。


![](https://paper-attachments.dropbox.com/s_A6FFC5F667CD23AF0DC91C20F45AAA96FB6AB09803A81864009EABE03C72C5E7_1564330074151_file.png)

## Knowledge Distilation

知識の蒸留では、事前学習済みの複雑で深いネットワークを使用して、より軽量なモデルの学習精度を向上させることです。
例としてはResNet152で事前学習させた予測確率を使用して、ResNet50の学習を進めます。

distillation損失を導入します。ここで$T$という温度パラメータをを導入し、ソフトマックスの出力をより滑らかにし、教師モデルの予測値からラベルの分布に関する情報を使用します。

$$\ell(p, \textrm{softmax}(z)) + T^2 \ell(\textrm{softmax}(r/T), \textrm{softmax}(z/T))$$

## Mixup Training 

画像のAugmentationの際にMixUpという手法を採用します。
MixUpでは、毎回2つのサンプルを抽出し、それらを重み付けた線形補間を行って新しいサンプルを作成します。

$$\hat x = \lambda x_i + (1-\lambda) x_j$$
$$\hat y = \lambda y_i + (1-\lambda) y_j$$

このときの$\lambda$がベータ分布 $Beta(\alpha, \alpha)$ から抽出します。

## 結果

セクション3で導入したテクニックをベースラインとして、最終的に導入したテクニックの効果は以下であらわされます。

![](https://paper-attachments.dropbox.com/s_A6FFC5F667CD23AF0DC91C20F45AAA96FB6AB09803A81864009EABE03C72C5E7_1564330112088_file.png)


なお計算条件は以下になります。

- $\epsilon=1$
- $T=20$
- $\alpha=0.2$


## 感想

ここまでで画像分類に関するテクニックのおおよそは確認できました。
このほかにも、最新手法のCutMixや損失関数自体を変更することで精度を向上させることができます。

次回は実際のデータセットを使用して、これらのテクニックの効果を確認していこうと思います。