ResNet に関する細かい話の備忘録です。
ResNet
ResNetの提案論文は以下になります。
PreAct ResNet
最初の提案論文では以下の構造のブロックを積層していました。
この構造の場合、入力を加算した後に活性関数(ReLU)があります。
ReLU関数では負の値の場合勾配が0になります。
したがって、入力を加算する構造にして勾配がそのまま伝播するようにしているのに ReLU の部分で徐々に勾配が消えてしまいます。
これを解決したのが pre-activation(PreAct) と呼ばれる構造です。
具体的には以下の形になっています。
加算した後の活性関数が残差を計算するパスの一番最初に移動しています。
これにより、スキップコネクション側には変換処理が一切適用されなくなり、勾配がそのまま伝播されていきます。
この構造を提案した以下の論文の実験では 164 層のネットワークを 1001 層に拡張した場合、
オリジナルの構造では精度が低下していますが、PreAct 版では精度が向上しています。
なお、この論文では様々な変更を ResNet に加えて性能を確認しています。
また、最後の Convolution の後、加算の前に BatchNormalization をさらに加える亜種もあります。
さらに最初の ReLU を削除してブロック内の活性関数を1つにする構造も提案されています(SingleReLU)。
初期化
ニューラルネットでは Xavier の初期値や He の初期値が使われます。
これらの目的は初期値の状態で出力の平均と分散が、入力とほぼ同じになるようにすることです(加えて、Xavierの初期化では重み行列の勾配の平均と分散も考慮されます)。
また、BatchNormalization 等の Normalization は出力の平均と分散を強制的に一定の値にします(正確には出力の平均と分散を強制的に一定の値にする処理を Normalization と呼んでいます)。
しかし、ResNet では出力値に入力を加算する処理が加わるため、層が深くなるほど出力値の分散が大きくなっていきます。
そのあたりの問題をきちんと整理したのが以下の論文になります。
上記の論文では以下のことが示されています。
- Normalization がある場合は、入力の加算により、出力値の標準偏差は深さに比例して増加する
- Normalization がない場合は、入力の加算により、出力値の標準偏差は深さに対する指数関数的に増加する
その上で残差を学習する関数側に「初期値0の学習パラメータとの積算」を加えるSkipInitという手法を提案しています。
これにより Normalization がなくとも学習が可能であることが示されています。
以下の論文でも同様の手法が提案されています。
こちらは Multi-Head Attention での実験結果も記載されています。
Down Sampling
畳み込みニューラルネットワークで分類問題を処理する場合、一般に変換処理の中で徐々に空間的な大きさを減らしていきます。
ResNetでも空間的な大きさを半分にするブロックがあります。このブロックの構造についていくつか改善手法が提案されています。
ResNetのブロックでは出力値に入力を加算します。
しかし、空間的な大きさを減らす場合、入力と出力の要素数が異なるため、どうしても何らかの変換を行う必要があります。
オリジナルの ResNet では stride=2 の 1x1 Conv を使っています。この場合、要素数の3/4を使いません。
そこで代わりに、2x2のAveragePooling + 1x1 Conv を利用する手法が提案されています。
個人的には AveragePooling だけでいいのではないかと思っているのですが、一般的には(チャンネル数を変えるのもあって)1x1 Conv が使う場合が多いです。
なお、これらの変換では活性関数を利用しません。非線形性は残差を計算する側が担当します。
つぎに残差を計算する側についてです。
ResNet-50より深いネットワークでは BottleNeck と呼ばれるモジュールが利用されています。
これは 1x1 Conv - 3x3 Conv - 1x1 Conv の3つの畳込み演算で構成されています。
このときに、空間的な大きさを減らすために最初の1x1 Conv の stride を 2 にすると先程と同様に入力値の3/4が利用されません。
そのため、stride=2 を挿入する位置を最初の 1x1 Conv から 2番目の 3x3 Conv に変更する手法が提案されています。
なお、解像度を減らす処理で以下のページで提案されている BlurPooling を使う手もありますが、計算量的にペイするのかはよくわかりません。
STEM
本筋とは関係のない部分ですが、ResNetには最初に7x7 Conv(stride=2) を行い次に3x3 MaxPooling(stride=2) を行う STEM(幹) と呼ばれる部分があります。
Down Sampling の際にも参照した以下の論文では、7x7 Conv を 3x3 Conv 3つで代替することにより計算コストを削減しています。
また、以下の論文では最初に4x4の領域を一つのピクセル?にまとめてしまい、画像サイズが1/4、チャンネル数がが3(RGB)x4x4=48の形に変換した後、3x3 Conv を適用するという手法で計算コストと性能の改善を行っています。
この処理は SpaceToDepth と呼ばれます。
空間サイズを減らして、チャンネル数を増やすという手法は ViT でも利用されています。
以上