概要
ディープラーニングの画像認識モデルである ResNeXt を解説し、Pytorch の実装例を紹介します。
ResNet
ResNet は、画像認識のコンテスト ILSVRC 2015 にて、top5 error rate で3.57%を記録し、優勝した CNN ネットワークモデルです。その後、いくつか改良したモデルが出てきて、今回紹介する ResNeXt もその亜種になります。
[blogcard url=”https://pystyle.info/pytorch-resnet”]
ResNeXt
Aggregated Residual Transformations for Deep Neural Networks で紹介された ResNet の改良モデルです。
cardinality の定義
入力数が 、出力数がのシンプルなニューロンの計算について考えます。 入力を 、全結合層の重みを としたとき、全結合層の計算は
で計算できます。

この処理は次の組み合わせとして解釈できます。
- を という低い次元に分割する (分割)
- それぞれ を計算する。(変換)
- すべての変換結果を足し合わせる (集計)
これを一般化すると、
は任意の関数で、必要に応じてより低い次元に次元削減したあと、変換を行います。 は を構成する変換の数で、大きいほど複雑な変換を表せます。論文では、 の値を 基数 (cardinality) とよんでいます。
Bottleneck Block を使用した変換
論文では、簡単にするために はすべて同じ変換とし、これを ResNet の Bottleneck Block にします。Bottleneck Block ブロックの最初の 1×1 の畳み込み層ではチャンネル数が の入力をより少ないチャンネル数に次元削減します。各 Bottleneck Block の出力を集計し、 とします。最後に Shortcut Connection と結合し、 を出力します。
分割のパラメータについて
Bottleneck の in_channels、out_channels を割り切れる値で分割する必要があります。Bottleneck の in_channels、out_channels がとり得る値は であり、これらの公約数は です。
次にモデルのパラメータ数は同等に維持しつつ、分割後の畳み込みの出力チャンネル数 を決めます。
- 通常の Bottleneck のパラメータ数は
in_channels * channels + 3 * 3 * channels * channels + channels * 4 * channels
と計算できます。 - 分割版の Bottleneck のパラメータ数は
C * (in_channels * d + 3 * 3 * d * d + d * 4 * channels)
と計算できます。
分割数 C をある値にしたとき、通常の Bottleneck のパラメータ数と変わらないように を決めるには、この2つが同じ値になる の値を求めればよいことがわかります。
例えば、in_channels = 256, channels=64 の Bottleneck の場合は次のように求められます。
C=1, d=64 C=2, d=40 C=4, d=24 C=8, d=14 C=16, d=8 C=32, d=4 C=64, d=2
論文では、この に対して、ResNet-50 及び ResNet-101 の分割したバージョンの精度の検証を行いました。 その結果、いずれも が最もよい精度がでることがわかりました。

C=32
の場合、各 in_channels, channels
の場合において、通常の Bottleneck のパラメータ数と変わらない を求めると次のようになります。
in_channels=64, channels=64, n_params=57344, C=32, d=5 in_channels=256, channels=64, n_params=69632, C=32, d=4 in_channels=256, channels=128, n_params=245760, C=32, d=9 in_channels=512, channels=128, n_params=278528, C=32, d=8 in_channels=512, channels=256, n_params=983040, C=32, d=18 in_channels=1024, channels=256, n_params=1114112, C=32, d=16 in_channels=1024, channels=512, n_params=3932160, C=32, d=36 in_channels=2048, channels=512, n_params=4456448, C=32, d=32
d
は channels
を割り切れる必要があるので、通常の Bottleneck より多少パラメータが少くなりますが、
- channels=64 のとき、d=4
- channels=128 のとき、d=8
- in_channels=256 のとき、d=16
- in_channels=512 のとき、d=32
つまり、d = channels * 4 / 64
とします。このモデルは cardinary=32、width=4
なので、ResNext 32x4d と表記します。
cardinary を増やした場合
cardinary=64、width=4
とした場合、Bottleneck Block のパラメータ数は元の ResNet の倍になりますが、cardinary
を倍にした場合の精度の検証も論文では行っています。

その結果、パラメータ数がほぼ同等である ResNet-200 と ResNeXt-101 64x4d において、ResNeXt のほうが精度がいいことがわかりました。
Grouped Convolution への置き換え

これまで考えてきた分割した Bottleneck (上図 a) は下図 b, c と等価です。そのため、実装上は Grouped Convolution を使用することにします。

torchvision の ResNeXt の実装
torchvision.models の ResNeXt の実装について解説します。ResNet の実装を一部変更したものなので、ResNet の実装については下記記事で解説し、その変更点のみこの記事で解説します。
[blogcard url=”https://pystyle.info/pytorch-resnet”]
Bottleneck Block の実装
Bottleneck クラスで Bottleneck Block を定義しています。順伝搬時の処理は以下のようになっています。分割後のチャンネル数は int(channels * (width / 64))
なので、Grouped Convolution のチャンネル数は int(channels * (width / 64)) * cardinary
で計算します。width=64, cardinary=1
のとき、通常の Bottleneck Block と同じになります。
ResNet を定義する
ResNext クラスで ResNeXt 全体のモデルを作成します。こちらの実装は cardinality, width
のパラメータをとるようになった点以外は ResNet と同じです。
torchvision では、ResNet-50 の 32x4d のバージョンと、ResNet-101 の 32x8d のバージョンが提供されています。
ResNet、ResNext のモデル一覧
モデル名 | 関数 | パラメータ数 | Top-1 エラー率 | Top-5 エラー率 |
---|---|---|---|---|
ResNet-18 | resnet18() | 11689512 | 30.24 | 10.92 |
ResNet-34 | resnet34() | 21797672 | 26.7 | 8.58 |
ResNet-50 | resnet50() | 25557032 | 23.85 | 7.13 |
ResNet-101 | resnet101() | 44549160 | 22.63 | 6.44 |
ResNet-152 | resnet152() | 60192808 | 21.69 | 5.94 |
ResNeXt-50-32x4d | resnext50_32x4d() | 25028904 | 22.38 | 6.3 |
ResNeXt-101-32x8d | resnext101_32x8d() | 88791336 | 20.69 | 5.47 |
Wide ResNet-50-2 | wide_resnet50_2() | 68883240 | 21.49 | 5.91 |
Wide ResNet-101-2 | wide_resnet101_2() | 126886696 | 21.16 | 5.72 |
コメント