CNN(Convolutional Neural Network)の歴史 - LeNetからResNetまで
この記事では機械学習の画像分野の基礎となっている畳み込み層について解説し、畳み込み層を用いて設計されたニューラルネットワーク(CNN)を幾つか紹介する。
目次
畳み込み層
畳み込み層はニューラルネットワークの層の一種。
\(C_i\)チャンネルの入力画像に対して、それより大きさの小さい\(C_i\)個のフィルター(=重みパラメーター)があり、フィルターを入力に重ね合わせたときに重なった部分を要素ごとに掛けて総和を取った値を計算し、その値を重ね合わせた位置の出力とする。この操作をフィルターをずらして全ての位置に対して行うことで出力全体を得る。
畳み込み層を用いたニューラルネットワークのことをCNN(Convolutional Neural Network)と言い、主に機械学習の画像分野で活用されている。
基本形
\(C_i\)は入力画像のチャンネル数。
出力の各チャンネルに対して、入力のチャンネルと同じ数のフィルターが存在する。つまり、出力のチャンネル数を\(C_o\)、フィルターの大きさを\(H_k, W_k\)とすると、畳み込み層の(バイアスを除く)重みパラメーターの数は\(C_i\times C_o\times H_k\times W_k\)となる。
出力画像の高さは以下のようになる。幅も同様。
\begin{align} H_o = H_i - (H_k - 1) \end{align}
Stride
Strideのある畳み込み層は、フィルターの移動幅が基本形より大きくなる。
出力画像の高さは以下のようになる。幅も同様。
\begin{align} H_o = \left\lfloor \frac{H_i - (H_k - 1) - 1}{Stride_y} \right\rfloor + 1 \end{align}
Strideの後に更に畳み込みを重ねていくことで、元の入力の遠い画素の情報を取り込む効果が得られることになる
特にStride=2として後述のPaddingを併用することで画像のサイズを丁度半分にすることができる。この仕組みを用いた画像の縮小は、様々なCNNで多用されている。
Padding
Paddingのある畳み込み層は、畳み込みを実行する前に入力画像の周囲に画素を追加する。
Paddingの方式には、入力画像の端の画素を繰り返す方法や、上下あるいは左右を反転させて繋げるなどの方法などがあるが、最もよく使われるのは0で埋めるZero Paddingという方式。
出力画像の高さは以下のようになる。幅も同様。
\begin{align} H_o = H_i + 2\times Padding_y - (H_k - 1) \end{align}
フィルターの大きさに応じて適切なPaddingを選択することで、入力と出力の画像サイズを揃えることができる。
層の深いCNNでは同じ構造のブロックを何度も繰り返すという設計になっていることが多く、Paddingによって画像サイズが変わらないことはそのような設計の前提になっている。
Dilation
Dilationのある畳み込み層は、入力画像の隣接した画素領域に対して畳み込みを行うのではなく、入力画像から飛び飛びに画素を取った集合に対して畳み込みを行う。
Atrous Convolutionなどとも呼ばれる。
出力画像の高さは以下のようになる。幅も同様。
\begin{align} H_o = H_i - (H_k - 1)\times Dilation_y \end{align}
Paddingと併用することで画像サイズを維持したまま遠い画素の情報を集約することができる。その性質から、Strideの代わりに使われることがある。
全て併用した場合
これら全てを併用した場合、出力画像の高さは以下のようになる。幅も同様。
\begin{align} H_o = \left\lfloor \frac{H_i + 2\times Padding_y - (H_k - 1)\times Dilation_y - 1}{Stride_y} \right\rfloor + 1 \end{align}
LeNet
LeNetは1989年にYann LeCunが発表した最初のCNN。後に広く使われることとなる畳み込み層を最初に導入した画期的なネットワークだが、当時はコンピューターの演算能力が高くなかったのであまり注目されなかった。
構造
LeNet-5は全7層で、3つの畳み込み層(C)、2つのサブサンプリング層(S)、1つの全結合層(F)、そしてRadial Basis Functionという特殊な層(OUTPUT)で構成される。
入力は32x32x1のグレースケール画像。手書きの文字の認識に使うことを想定していた。
C3層
2つ目の畳み込み層C3は単純に6チャンネルから16チャンネルへの畳み込みを行うのではなく、出力の各層に対して入力の6チャンネルの一部のみを使って畳み込みを行う。
単純に計算量を削減する目的だが、出力の対称性(非一意性)をある程度解消する狙いもある。
出力の各チャンネルに対して、入力のチャンネルは以下の表のXの部分のみを取り出して使う。
サブサンプリング層
サブサンプリング層は画像の縦横の幅を縮める役割を果たす。
現在CNNでよく使われるプーリング層とは異なり、LeNetのサブサンプリング層は重みを持つ。例えば2x2のサブサンプリング層の場合、入力画像を2x2の領域に分割して各領域の値を合計し、チャンネル毎に重みを掛けてバイアスを足したものが出力となる。チャンネルごとに重みとバイアスのパラメーターを持つので、パラメーター数はチャンネル数の2倍になる。
PyTorchで実装するなら、AvgPool2d(2)→x4→Conv2d(1, 1, 1, groups=channel_size)という風になる。
Radial Basis Function
全結合層の出力\(x\)は84次元で、これは7x12画素の大きさの2次元画像に相当している。
出力層RBF(Radial Basis Function)では、予め用意された(クラス数)x12x7のパラメーター\(w\)と全結合層の出力\(x\)との差を取り、二乗して全画素で合計した値\(y\)を出力する。パラメーターは(少なくとも初期値は)フォント図形から生成された12x7の値である。
\begin{align} y_i = \sum_{j=1}^{84}(x_j - w_{ij})^2 \end{align}
こうすることで、全結合層の出力は入力画像が意味する文字に対応するフォント図形に近付くように学習されることになる。
出力の中で最も値の小さいクラスが、入力画像に対する予測クラスになる。
tanh活性化層
tanhの定数は以下の値を取る。
\begin{align} S&=\frac{2}{3} \\ A&=1.7159=\frac{1}{1-\frac{2}{e^{4/3}+1}} \end{align}
AlexNet
AlexNetは2012年にAlex Krizhevskyらが考案したCNN。
ILSVRC 2012(ImageNet Large Scale Visual Recognition Challenge)という画像認識コンテストで2位に大差を付けて優勝し、画像認識の分野に大きな影響を与えた。
データ拡張、正規化、ReLU、Dropoutなど、現在でもCNNでよく使われる概念が導入されている。
構造
入力は224x224x3のカラー画像。ILSVRCで使われるImageNetデータセットを使った画像分類タスクを想定。
当時のハードウェアの限界により、モデルは途中まで2枚のGPU(GeForce GTX 580)に分散して実行される。
損失関数にはlog probability (cross entropy)を用い、SGD(momentum=0.9, weight_decay=0.0005)で学習された。
Local Response Normalize
テンソル全体で正規化を行うのではなく、隣接したチャンネル間でのみ正規化を行う。
\(i\)をチャンネル、\(x,y\)をピクセル位置としたとき、入力\(x\)に対して出力\(y\)は以下のように定義される。
\begin{align} y^i_{x,y} = \frac{x^i_{x,y}}{\left(k+\alpha\sum_{i-n/2\leqq j\leqq i+n/2}(x^j_{x,y})^2\right)^\beta} \end{align}
ここで、\(k=2, n=5, \alpha=10^{-4}, \beta=0.75\)。
VGG
VGGは、2014年にOxford大学のVGG(Visual Geometry Group)グループが考案したCNN。
ILSVRC 2014で準優勝。(優勝はGoogLeNet(Inception))
構造
VGGには以下の表のように6つの設定があり、層の深さ(=使用メモリーと演算時間)がそれぞれ異なる。
例えばVGG-16(設定D)の全体図は以下のようになっている。
特筆すべき新しい構造はないが、CNNの層を深くすることでモデルの表現力を上げることができることが実証された。
現在では大規模モデルの一部に学習済みのVGGをBackboneとして組み込むような使い方で活用されることがある。
ResNet
ResNetは、2015年に当時Microsoft Researchに所属していた何恺明(Kaiming He)らが考案したCNN。
ILSVRC 2015で優勝。
このモデルもBackboneとしてよく使われる。
構造
以下の表の通り、ResNetにも複数の設定がある。
Skip Connection
ResNetでは以下の図のようなskip connectionというアイデアが導入された。
入力に対する出力を学習するのではなく、入力と出力の差を学習する仕組み。
CNNは層を深くしすぎると、入力側に近い層ほど逆伝播される勾配のスケールが小さくなり、入力側の層の学習が進みにくくなる「勾配消失」という問題がある。しかしskip connectionを入れることで、逆伝播時に微分が右側の経路を通って入力側に伝わり、勾配消失を抑制する効果があるらしい。
ResNet-18, ResNet-34では上図と同様の残差ブロックを使う。ResNet-50以上ではパラメーター数を節約するために、まず1x1の畳み込みでチャンネル数を減らし、次に3x3の畳み込みを行い、最後に1x1の畳み込みでチャンネル数を復元するというボトルネック残差ブロックを使う。
バッチ正規化
ResNetの正規化は、バッチ全体に対する正規化を行う。
バッチサイズ方向の次元を\(b\in {1, ... , B}\)、画像(テンソル)の高さと幅方向の次元を\(y \in {1, ... , H}, x \in {1, ... , W}\)、チャンネル方向の次元を\(i \in {1, ... , C}\)とすると、バッチ正規化は以下のように定義される。
\begin{align} E(x_i) &:= \frac{1}{BHW}\sum_{b, x, y}x^{b,x,y}_i \\ Var(x_i) &:= \frac{1}{BHW}\sum_{b, x, y}\left( x^{b,x,y}_i-E(x_i)\right)^2 \\ y^{b,x,y}_i &:= \gamma_i \cdot \frac{x^{b,x,y}_i-E(x_i)}{\sqrt{\epsilon + Var(x_i)}} + \beta_i \end{align}
ここで、\(\gamma, \beta \in R^C\)は学習可能なパラメーター。
バッチ正規化には通常の正規化と同様に、入力データ次第で中間層の平均と分散に大きな差がある場合であっても平均と分散を揃える操作を行うことで、中間層の入力の定義域を実質的に狭めて学習を効率化するという効果がある。更にバッチ正規化では、特徴量次元の2倍という僅かなパラメーターの追加を行うことで、中間層が本来表現したかった偏りを維持する仕組みを組み込んだ。
一方、この仕組みはバッチサイズの選択が学習により大きな影響を与える原因にもなっている。