パターン認識

(8) 畳み込みニューラル・ネットワーク ( Convolutional Neural Network )

神経生理学者の「デイヴィッド・ヒューベル ( David Hunter Hubel )」と「トルステン・ウィーセル ( Torsten Nils Wiesel )」は、大脳皮質視覚野のニューロンがスリットや棒、エッジに反応し、さらに各ニューロンが特定の傾きだけに反応することを発見しました。彼らは、この業績によって 1981 年にノーベル生理学・医学賞を受賞しています。このニューロンをモデルとした人工ニューラル・ネットワークとして、1982 年に「福島邦彦」が提唱したのが「ネオコグニトロン ( Neocognitron )」で、これが「畳み込みニューラル・ネットワーク ( Convolutional Neural Network )」の起源と言われています。
ネオコグニトロンの学習に誤差逆伝播法を採用し、1989 年に「ヤン・ルカン ( Yan Andre LeCun )」が「LeNet」を発表、その後しばらくは下火になったものの、「アレックス・クリジェフスキー ( Alex Krizhevsky )」「イリヤ・スツケヴェル ( Ilya Sutskever )」「ジェフェリー・ヒントン ( Geoffrey Everest Hinton )」が共同で設計した「AlexNet」が ImageNet を使った画像認識コンテストの「ILSVRC ( The ImageNet Large Scale Visual Recognition Challenge )」の 2012 年大会で従来の画像認識手法を大きく上回る成績を収めたことで、一気に注目度が上がりました。今回は、畳み込みニューラル・ネットワークについて紹介したいと思います。

(注) 数式などの記法について (ドキュメントの中で使用している数式の表現方法に関する注意点です)

1) 畳み込みニューラル・ネットワーク ( Convolutional Neural Network ; CNN )

まずは「ニューラル・ネットワーク ( Neural Network )」を使い、画像を分類するモデルの構築を検討してみましょう。画像の幅を W、高さを H とします。もし、グレースケールの画像なら、ピクセルの数は HW ですが、RGB 成分を扱うときは全部で 3HW になります。これを直列に並べて入力層とし、あとは隠れ層 1 つと出力層を用意すれば、識別用の単純なモデルが完成します。さらに具体的な場合として、0 から 9 までの数字を手で書いた 20 x 20 のグレースケールの画像データを分類することにすれば、入力層の数は定数項を含めて 401、出力層の数は 10 と定義できます。隠れ層は定数項を含めて 21 個としたとき、全ての重み係数及びバイアス・パラメータの数は、

401 x 20 + 1 + 21 x 10 = 8231

になります。この程度なら、通常の PC を使っても処理は可能なレベルです。ところが、画像サイズが大きくなると状況は一変します。今度は、200 x 200 の RGB 画像を 1000 種類に分割する処理を考えてみましょう。隠れ層は一つだけで、ユニット数は定数項を含めて 10001 としておきます。このときの全重み係数及びバイアスパラメータの数は

( 200 x 200 x 3 + 1 ) x 10000 + 1 + 10001 x 1000 = 1,210,011,001

となって、12 億以上必要になります。隠れ層のユニット数は適当に決めたものですが、例えばユニット数を 100 まで減らしたとしても 1200 万くらいの数になりますから、たくさんの重み係数を学習しなければならない状況は変わりません。

一般に、ニューラル・ネットワークは層を多くするほど表現力が上がり、より精度の高い識別が可能になります。しかし、層やユニットの数が増えれば、学習が必要な重み係数の数も爆発的に増大し、リソース的な問題が発生するようになります。画像データの場合、ピクセル数は非常に大きくなる傾向があるため、入力層のユニット数も多くなり、結果として巨大なネットワークを形成する必要が生じます。ユニット数に応じて爆発的に重み係数が増えるのは、前後の層において全てのユニットを結合しているからです。このような層は「全結合層 ( Fully-connected Layer )」といいます。全結合層の場合、前の層のユニット数が Ni 個、現在の層のユニット数がバイアス・パラメータを除いて Nj 個あったとき、必要な重み係数の数は NiNj 個になります。両方が 100 個のユニットを持っていれば、実に 10000 個の重み係数が必要になるのです。

そこで、画像特有の特徴を利用して、この重み係数を減らすことを検討します。一般に、画像は近隣の画素間で強い相関を持ちます。そこで、前の層すべてのユニットを重み係数で一度に線形結合するのではなく、一回の計算対象を局所領域だけに限定します。例えば、最初の 3 画素分だけを線型結合してから活性化関数を作用させ、次は 1 ピクセル分だけずらして、2 番目から 4 番目の 3 画素分を線形結合するわけです。さらに、重み係数を共通で使うようにすれば、その数を劇的に減らすことが可能になります。

図 1-1. 重み係数の共通化
三つのユニットで線型結合した後、一つずらして同様の処理を行う

ところで、今回は画像を入力データとして処理を行うため、重み係数も画像に合わせて 2 次元で表現したほうが、局所領域を扱う分には都合がいいです。例えば、先の例では 3 x 3 ピクセルを一つの重み係数とするわけです。すると、重み係数による線型結合処理は、画像の畳み込み処理と一致します。畳み込み処理を利用することで、ガウシアンぼかしなどの画像加工やエッジ抽出コーナー検出などの特徴抽出を行うことができるのでした。今までは、使われる重み係数は固定でしたが、ニューラル・ネットワークでは学習によって重み係数を更新することができます。つまり、例えば犬の画像を判別したいのであれば、犬に特化した重み係数を学習によって作ってしまうわけです。この二次元の重み係数は「カーネル ( Kernel )」と呼ばれます。また、畳み込み処理を利用した層のことを「畳み込み層 ( Convolutional Layer )」といいます。

画像の特徴を抽出するとき、一つだけで足りることはまずあり得ません。犬の特徴を抽出するなら、目や鼻や口、耳、尻尾、足など、複数の専用カーネルが必要になります。カーネルによって畳み込み処理された結果も複数になり、それは「特徴マップ ( Feature Map )」といいます。よって、全体を一つにまとめると、カーネルや特徴マップは三次元構造を持つことになります。

図 1-2. 特徴マップとカーネル
3枚の特徴マップを2つのカーネルで処理した結果、2枚の特徴マップが出力される

2) 畳み込み層 ( Convolutional Layer )

入力する p 番目 ( 0 ≤ p < P ) の特徴マップのデータを sp,w,v、出力される q 番目 ( 0 ≤ q < Q ) の特徴マップのデータを dq,j,i としたとき、カーネルは P・Q 枚必要になります。カーネルを kp,q,h,g ( 0 ≤ g < G, 0 ≤ h < H ) で表すと、dq,j,i は次の計算式で求めることができます。

dq,j,i = η( Σp{0→P-1}( Σh{0→H-1}( Σg{0→G-1}( kp,q,h,gsp,j+h,i+g ) ) ) + bq )

bq はバイアス・パラメータです。また、dq,j,i は、ニューラル・ネットワーク同様、活性化関数 η(・) によって変換されることに注意してください。

畳み込みニューラル・ネットワークにおいては、通常のニューラル・ネットワークにはない独特のパラメータがあります。まず、ストライド ( Stride ) は、畳み込み処理を行った後、カーネルを移動する幅と高さを表します。通常、畳み込み処理におけるストライドは 1 になりますが、このとき出力される特徴マップの大きさは、カーネルのサイズ - 1 分だけ小さくなります。一般に、ストライドを t としたとき、入力する特徴マップの大きさが I、カーネルの大きさが K ならば、出力される特徴マップの大きさは

( I - K ) / t + 1

で求めることができます。但し、割り切れない場合、その余剰分も畳み込み処理をするならば、大きさは 1 だけ大きくなります。

図 2-1. ストライド
上図はストライド1、下図はストライド2でのカーネルの移動の様子

例えば、幅が 8 の大きさの特徴マップに幅が 3 のカーネルを使って畳み込みを行う場合、ストライド 1 のときに出力される特徴マップの幅は 8 - 3 + 1 = 6 になります。また、ストライドを 2 にすると ( 8 - 3 ) / 2 + 1 = 3.5 になって、整数にはなりません。ちょうど割り切れるようにするには、入力サイズが 1 だけ足りないわけですが、この場合に余剰分を無視するかどうかは実装に依存します。

もう一つのパラメータはパディング ( Padding ) です。特徴マップ上の各点は、通常はカーネルの大きさと同じ回数分だけ計算に使われます。しかし、端のほうにある点に関してはその回数が少なくなります。特に、頂点に位置する四つの点に至っては一回しか使われません。そこで、端にある点も計算に寄与させるために、特徴マップの周囲に数ピクセル分の余分な領域を追加します。これがパディングです。

図 2-2. パディング ( 赤枠はカーネル )
パディングの様子

パディングには、出力結果のサイズを通常より大きくするという特徴もあります。ストライドを 1 にしても、出力結果が入力データより小さくなるのは先程見たとおりです。入出力のサイズを等しくするためにパディングを利用することもあります。また、余剰をなくすためにもパディングを用いることができます。
通常、追加された領域はゼロで埋められます。これを「ゼロ・パディング ( Zero Padding )」といいます。いろいろと調べてみましたが、ゼロ・パディング以外のやり方は見つかりませんでした。


3) プーリング層 ( Pooling Layer )

畳み込みニューラル・ネットワークには、畳み込み層の他に重要な層があと二つ存在します。その一つが「プーリング層 ( Pooling Layer )」です。プーリング層では、特徴マップを小領域に分割し、領域ごとに集約処理を行います。

図 3-1. プーリング処理
サイズ3の小領域に分けて集約処理を行う

集約方法としては、主に「最大値プーリング ( Max Pooling )」と「平均値プーリング ( Average Pooling )」が挙げられます。前者は小領域から最大値を抽出し、後者は小領域の各値の平均を計算することで集約値として用います。

プーリング処理後の結果を pq,n,m としたとき、最大値プーリングの場合は

pq,n,m(max) = max{ mx≤i≤(m+1)x-1, ny≤j≤(n+1)y-1 }( dq,j,i )

と表されます。但し、max{R}(・) で領域 R 内の最大値を表すとし、( x, y ) は小領域の大きさです。平均値プーリングは

pq,n,m(avg) = Σj{ny→(n+1)y-1}( Σi{mx→(m+1)x-1}( dq,j,i ) ) / xy

であり、特別に複雑な計算をしているわけではありません。また、この二つの重み付け和

pq,n,m(hybrid) = αpq,n,m(avg) + ( 1 - α )pq,n,m(max)

が使われる場合もあります。但し、α は 0 から 1 までの間を取る定数です。

プーリング処理においても畳み込み層と同様にストライドの概念を取り入れる場合があります。通常はストライド = 小領域のサイズになるわけですが、それよりも小さい値をストライドとして使うわけです。このとき、各小領域は重なる箇所が生じるため、これは「重複プーリング ( Overlapping Pooling )」と呼ばれます。
重複プーリングは、後述する AlexNet で利用されました。重複しない場合と比較して、誤認識率は 0.3 から 0.4% 改善し、また過学習しにくいことが観察されたと論文では報告されています。
単に移動幅が変わるだけで処理に変化はないので、難しいところは特にありませんが、誤差逆伝播のときに若干の注意が必要になります。


プーリング処理が行っていることは、単なる特徴マップのリサイズです。例えば、小領域を ( 2, 2 ) の大きさにした場合、プーリング処理の結果は縦横ともに元の半分の大きさに縮小されます。集約値が何であれ、これは画像縮小処理と同等と考えられるので、元の情報はある程度保持できます。
プーリング処理によって得られる恩恵としてすぐに思いつくのがデータ量や処理量の削減でしょう。先の例では、特徴マップの大きさは 1 / 4 にまで削減できるので、次の層で畳み込み処理を行う回数も大きく減少します。しかし、プーリング処理の利点はそれだけではありません。例えば、あるカーネルによって得られる特徴的な形によって識別ができる画像があったと仮定します。この画像を何ピクセルか横にシフトすると、畳み込み結果も同様に横へずれてしまうことは容易に想像できます。当然、ある特徴を持った形状も位置がずれてしまうので、認識ができなくなってしまうのです。プーリング処理は、このような位置変化に対する頑強性 ( Robustness ) を持たせることができます。なぜなら、位置の変化もまた縮小されるので、多少の差異に対しては影響を受けなくなるからです。

図 3-2. 位置変化に対する頑強性
サイズが小さくなれば、位置変化への影響も小さくなる

もう一つの重要な層は「全結合層」です。畳み込み層とプーリング層を何層か重ねた後、最後は全結合層を使って処理をするのが一般的です。画像分類を行うのなら、出力層はソフトマックス関数を利用することになります。畳み込み層やプーリング層が出力する値は通常は三次元になるので、全結合層で処理できるように値を一次元に並べ直します。この処理は「フラット化 ( Flatten )」と呼ばれます。

以上が、畳み込みニューラル・ネットワークに必要な層の全てになります。畳み込み層とプーリング層は必ずセットにしなければいけないというわけではなく、プーリング処理を省略するような場合もあり、その形はモデルによって異なります。


4) 誤差逆伝播 ( Backpropagation )

畳み込みニューラル・ネットワークにおいて複雑で厄介なのが「誤差逆伝播 ( Backpropagation )」です。全結合層でも理解するのは容易ではありませんが、特に畳み込み層は入力値・カーネル・出力値の依存関係がややこしいので、注意深く見ていく必要があります。

まずは、比較的簡単なプーリング層について確認します。最大値プーリングの順伝播での式をもう一度見てみましょう。

pq,n,m(max) = max{ mx≤i≤(m+1)x-1, ny≤j≤(n+1)y-1 }( dq,j,i )

逆伝播によって、∂J / ∂pq,n,m(max) までは計算済みとします。なお、J は出力層で得られた予測値と教師信号との誤差関数の値です。求めたいのは ∂J / ∂dq,j,i なので、連鎖法則から

∂J / ∂dq,j,i = ( ∂J / ∂pq,n,m(max) )( ∂pq,n,m(max) / ∂dq,j,i )

であり、

∂pq,n,m(max) / ∂dq,j,i=∂dq,jmax,imax / ∂dq,j,i
=1 ( i = imax ∩ j = jmax )
=0 ( i ≠ imax ∪ j ≠ jmax )

と計算できます。つまり、小領域の最大値があった場所だけ ∂J / ∂pq,n,m(max) を置いて、その他は計算結果に依存していないので、すべてゼロにしてしまうのです。処理としては非常に簡単ですね。

平均値プーリングの場合

pq,n,m(avg) = Σj{ny→(n+1)y-1}( Σi{mx→(m+1)x-1}( dq,j,i ) ) / xy

となります。これも偏微分の結果は非常に簡単で

∂pq,n,m(avg) / ∂dq,j,i = 1 / xy

なので、今度は ∂J / ∂pq,n,m(avg) を小領域のデータ数 xy で割って、均等に配分するだけで済みます。

問題は、重複プーリングの場合です。重複は複数回発生する場合があります。dq,j,i に対して、L 回の重複が発生したとしましょう。すると L 個の pq,nk,mk ( 0 ≤ k ≤ L - 1 ) が dq,j,i に依存することになるので、

∂J / ∂dq,j,i = Σk{0→L-1}( ∂J / ∂pq,nk,mk )( ∂pq,nk,mk / ∂dq,j,i )

を計算する必要があります。ややこしそうに見えますが、処理自体は簡単で、誤差逆伝播を行うとき、計算結果を代入するのではなく加算するようにすれば、重複した箇所は自然に和が求められます。これは、最大値プーリングも平均値プーリングも同様です。


プーリング層にはパラメータがないので、次はバイアス・パラメータ bq に対する微分係数 ∂J / ∂bq を求めることになります。

dq,j,i = η( Σp{0→P-1}( Σh{0→H-1}( Σg{0→G-1}( kp,q,h,gsp,j+h,i+g ) ) ) + bq )

より yq,j,i = Σp{0→P-1}( Σh{0→H-1}( Σg{0→G-1}( kp,q,h,gsp,j+h,i+g ) ) ) + bq としたとき

∂dq,j,i / ∂bq=( ∂dq,j,i / ∂yq,j,i )( ∂yq,j,i / bq )
=η'( yq,j,i )

なので

∂J / ∂bq = Σj( Σi( ( ∂J / ∂dq,j,i )η'( yq,j,i ) ) ) ≡ Σj( Σi( δq,j,i ) )

で求めることができます。このとき、bq が dq,j,i 全てに加算されているので、連鎖法則は和の形になることに注意してください。また、後で利用することになるので、和の項を δq,j,i としました。

カーネルに対する微分係数 ∂J / ∂kp,q,h,g に移りましょう。畳み込み処理にはストライドを用いる場合があるので、ストライドを t として畳み込み処理の式を一般化すると

dq,j,i = η( Σp{0→P-1}( Σh{0→H-1}( Σg{0→G-1}( kp,q,h,gsp,jt+h,it+g ) ) ) + bq )

という式が得られます。kp,q,h,g はバイアス・パラメータと同様にすべての dq,j,i に依存することになるので、連鎖法則は

∂J / ∂kp,q,h,g=Σj( Σi( ( ∂J / ∂dq,j,i )( ∂dq,j,i / ∂yq,j,i )( ∂yq,j,i / ∂kp,q,h,g ) ) )
=Σj( Σi( ( ∂J / ∂dq,j,i )η'( yq,j,i )sp,jt+h,it+g ) )
=Σj( Σi( δq,j,isp,jt+h,it+g ) )

です。ここで、バイアス・パラメータの計算に登場した δq,j,i を利用することができます。
パディングがある場合、その幅分だけカーネルは左上側にはみ出た形で畳み込み処理が行われているので、入力値の座標は、パディングの幅を a としたとき ( it + g - a, jt + h - a ) になります。当然、その座標値がパディングの領域内にある場合、ゼロ・パディングなら sp,jt+h-a,it+g-a = 0 にしなければなりません。但し、入力値のマップに実際にパディングがあるのなら一切考慮不要になるので、最初からゼロで周囲を埋めるようにしておいたほうがプログラムも単純になります。なお、余剰がある場合、パディングを含む領域からはみ出る場合もあるので、その場合は計算処理をスキップするよう配慮が必要です。

最も複雑な計算になるのが、入力値 sp,w,v による偏微分係数 ∂J / ∂sp,w,v です。ストライドが 1 ならば、ある入力値に着目したとき、カーネルは右下端の値と最初に掛け合わされ、左上端の値を最後にカーネルの領域外へ出てしまいます。つまり、出力結果 dq,j,i に対して、カーネルの作用が反転していることになります。

図 4-1. 入力値・カーネル・畳み込み結果の関係
カーネルは上下左右が反転して作用する

連鎖法則は

∂J / ∂sp,w,v = Σq( Σj( Σi( ( ∂J / ∂dq,j,i )( ∂dq,j,i / ∂yq,j,i )( ∂yq,j,i / ∂sp,w,v ) ) )

と表すことができます。( ∂J / ∂dq,j,i )( ∂dq,j,i / ∂yq,j,i ) = δq,j,i であり、ストライドを t とすれば

yq,j,i = Σp{0→P-1}( Σh{0→H-1}( Σg{0→G-1}( kp,q,h,gsp,jt+h,it+g ) ) ) + bq

より v = it + g、w = jt + h とおくと、和の項は kp,q,w-jt,v-itsp,w,v と表せることから

∂yq,j,i / ∂sp,w,v = kp,q,w-jt,v-it

なので、求める微分係数 ∂J / ∂sp,w,v

∂J / ∂sp,w,v = Σq{0→Q-1}( Σj( Σi( δq,j,ikp,q,w-jt,v-it ) ) )

となります。ここで、( v, w ) は入力側、すなわち前の層に対する座標値、( i, j ) は出力側、すなわち後続層に対する座標値です。ここでは誤差逆伝播ですから、( i, j ) から読み込んで ( v, w ) に書き込むことになります。この二つの座標の関係を、カーネル上の座標を利用して調べてみましょう。

図 4-2. ストライドが 1 より大きい場合の入力値・カーネル・畳み込み結果の関係
カーネルの左端は t の整数倍に位置する

カーネルの左上端は、入力値 sp,w,v 上をストライド t の倍数の位置にシフトします。そして、その位置は処理結果 yq.j.i と一対一に対応します。そのカーネル内にある sp,w,v が全て、yq,j,i と連鎖しているので、誤差逆伝播のときは、その誤差が逆にカーネル内の全 sp,w,v に配分されることになります。また、( v, w ) = ( it, jt ) が成り立つこともすぐに分かります。
( v, w ) の位置を始点として、入力値とカーネルの値は各々の位置で掛け合わされ、その和が yq,j,i になります。カーネル内の位置が ( g, h ) のとき、その位置と重なる入力値の座標は ( v + g, w + h ) なので、∂J / ∂sp,w+h,v+g に対して δq,w/t,v/tkp,q,h,g を加算することを繰り返せば、目的の誤差が計算できます。

前述の通り、パディングを考慮する場合、カーネルは幅 a 分だけ sp,w,v からはみ出た位置から処理が開始されます。誤差を計算するマップに対しても同じ大きさのパディングを用意するのなら、特に何も考える必要はありません。しかし、パディングがない場合は、入力値の座標を補正する必要があります。これは簡単で、単に a を減算すればいいので ( v + g - a, w + h - a ) にするだけです。この処理は、入力値にパディングがあらかじめ入っていても必要なことに注意してください。ここでは、誤差の計算結果を書き込む領域についての補正を意味しています。
最後に、余剰分の扱いについては、畳み込み処理のときの処理方法に依存して、余剰を無視するのであれば、カーネルの右端または下端がパディングを含む領域外に飛び出たら処理を終了します。また、余剰も計算を行うのなら、カーネルの左上隅が領域内にある限り処理を続けます。後者の場合、カーネル内の各位置に対して処理を行う際に、その位置が領域内にあるかをチェックする必要があることは言うまでもありません。

以上をまとめると、次のようなアルゴリズムになります。

  1. δ(l)p,w,v = ∂J / ∂sp,w,v の全要素をゼロで初期化する。
  2. ( v, w ) を ( 0, 0 ) から ( V + 2a - 1, W + 2a - 1 ) までループしながら以下の処理を繰り返す。但し、v, w はストライド分インクリメントするものとする。
  3. ( g, h ) を ( 0, 0 ) から ( G - 1, H - 1 ) までループしながら以下の処理を繰り返す。
  4. カーネル kp,q,h,g 上の位置 ( g, h ) と重なる入力値の座標 ( x, y ) = ( v + g - a, w + h - a ) を求める。
  5. 後続層からの誤差成分 δ(l+1)q,j,i を取得する位置 ( i, j ) = ( v / t, w / t ) を求める。
  6. ( x, y ) が ( 0, 0 ) から ( V - 1, W - 1 ) の範囲内なら δ(l)p,y,x に δ(l+1)q,j,i・kp,q,h,g を加算する。
  7. 3 へ戻る。
  8. 2 へ戻る。

( V, W ) は入力値の大きさ、( G, H ) はカーネルの大きさを表します。また、余剰分の処理も行うものとしてあります。


パディングを利用する時、実際の特徴マップにその領域を埋め込むかどうか、という点においては、埋め込んだほうが圧倒的に処理が楽になります。畳み込み処理においても、擬似的にパディングを埋め込む形にすると場合分けが必要になる上、誤差逆伝播の処理がややこしくなるのは今まで説明した通りです。パディングの幅だけデータ量が増えることになりますが、何倍にも膨れ上がるわけではありません。最初の入力値である画像データにパディングを追加する処理が必要になる点についても、画像に対して何の前処理も行わないということはまずないので、前処理時に一緒にパディングを行ってしまえば、パフォーマンスにも影響はありません。注意点としては、次の層に渡す結果を書き込む際に、あらかじめパディングを考慮する必要があることくらいでしょうか。
また、余剰分の処理をなくすために、余剰がなくなるようにパディングを利用するのはよく使われるテクニックです。


5) AlexNet

画像認識用のデータセットを保持するサイトとして有名なものに ImageNet があります。ImageNet は、2010 年から 2017 年の間、画像認識の能力を競うコンテスト ImageNet Large Scale Visual Recognition Challenge ( ILSVRC ) を開催していました。
2010 年と 2011 年は、SIFT などの特徴量を利用した分類が主流でした。その状況を塗り替えたのが、2012 年に登場した AlexNet です。

図 5-1. ILSVRC の優勝チームの誤認識率
2012年に誤認識率は一気に低下した

上のグラフは、毎年の優勝チームが記録した誤認識率の推移を表しています。2012 年に登場した AlexNet が、それまでの記録を一気に 10% 以上更新したことが分かります。この結果は当時、その分野の関係者にかなりの衝撃を与えたのではないでしょうか。

AlexNet が持つ主な特徴は以下の通りです。

  1. 二つの GPU ( Graphics Processing Unit ) を利用した並列処理
  2. 活性化関数に ReLU を活用
  3. ドロップアウト ( Dropout ) を全結合層に適用
  4. 局所応答正規化 ( Local Response Normalization ; LRN )
  5. 重複プーリング ( Overlapping Pooling)

今でこそ、ニューラル・ネットワークに対しては GPU を用いるのが一般的ですが、当時はまだメモリも小さかったので ( NVIDIA GTX 580 3GB )、二つの GPU に半分ずつカーネルを用意して、並列に処理するという荒業を使っています。 基本的には両 GPU で独立に処理を行いますが、2 層目の特徴マップは相互に送信して、3 層目で全体を畳み込み処理するような設計になっています。
CNN では通常、活性化関数に ReLU を用います。これを広めたのは AlexNet が最初であろうと思います。論文の中では、活性化関数に tanh を用いた場合に比べて 6 倍速く誤認識率が下がったと述べています。

図 5-2. AlexNet の構成図 ( 論文より抜粋 )
処理が二つに分離されている

一般に、学習したいパラメータの数に対して教師信号が少ないと、過剰適合 ( Overfitting ) の状態になります。ILSVRC では学習用に 120 万枚の画像セットが用意されていますが、対する AlexNet のパラメータ数は 6000 万あります。これでは圧倒的に学習用データが足りないので、画像を加工することでかさ増しを行っています。ILSVRC で用意された画像データは 256 x 256 のサイズです。これを 224 x 224 のサイズでランダムに切り取り、さらにその水平反転も使って学習を行います。なので、入力画像のサイズが 224 x 224 になっているわけです。
論文では、もう一つ、RGB 成分の強度を変化させる方法も紹介されています。まず、学習用の画像セット全ての画素にある RGB 成分を使い、主成分分析を行います。主成分分析は、次元削減などが目的ではなく、単に共分散行列の固有値と固有ベクトルを求めたいために使われます。その結果、3 つの固有値と対応する固有ベクトルが得られるので、それらを λipi ( i = 0, 1, 2 ) とします。
こうして得られた固有値と固有ベクトルを使い、以下の式で δi を計算します。

δi = [ p1, p2, p3 ][ α1λ1, α2λ2, α3λ3 ]T

上式において、αi は平均ゼロ、標準偏差 0.1 の正規分布に従う乱数を表しますが、同じ学習用画像が再度使われるまでは変更しません。こうして得られた δi を、画像の全画素の RGB 成分それぞれに加算します。

pi を列ベクトルとする行列を P とすると、P は直交行列になります。[ α1λ1, α2λ2, α3λ3 ]T は、固有値 λi を対角成分とする対角行列を Λ、[ α1, α2, α3 ]T = α としたとき Λα なので、結局、上式は PΛα と表すことができます。α はいわばノイズであり、それを固有値倍するのは、分散の大きさに応じて値を調整する処理とみなすことができます。最後に直交行列を掛けることによって、主軸を元に戻します。今回は三次元なので、RGB 成分の分布から作られる楕円体が空間上にあって、その向きにノイズの方向を合わせると考えればいいでしょうか。そのとき、楕円体の長く伸びた方向ほど大きな固有値を掛けてノイズの値を大きくするわけです。
この手法は「PCA Color Augmentation」または「Fancy PCA」と一般には呼ばれています。物体の持つ特徴は、明度や色彩の変化に対して影響を受けないので、このような変換を行っても画像認識能力には影響を及ぼしません。

しかし、こうして得られた画像は当然、相互依存性が高いので、十分な効果は得られません。そこで利用されたのが「ドロップアウト ( Dropout )」という手法です。一般的に、複数の学習モデルを使って予測を行い、その平均や多数決などを採用する「アンサンブル学習 ( Ensemble Learning )」は過剰適合に有効であることが知られています。例えば、決定木のアンサンブル学習である「ランダム・フォレスト (Random Forest)」は、その代表的なアルゴリズムです。よって、複数の CNN で学習をして、その分類結果から多数決をとって結果を出力するのも有効なのですが、単体でも学習に時間がかかることから、簡単に実現できる方法ではありません。そこで、学習を行う度に、一部のニューロンを無効にする手法が考案されました。具体的には、ある確率 p でニューロンを無効にしてから学習を行います。無効にされたニューロンは、順伝播と誤差逆伝播のいずれにも利用されません。そのため、学習の度に異なるネットワークが形成されるわけです。テスト時には、全てのニューロンを有効にする代わりに、重みベクトルに 1 - p を掛けて処理します。なぜ、1 - p を掛ける必要があるかというと、順伝播の時に残るニューロンの数は平均で全体の 1 - p 倍になるので、これを補う形で学習時に重みベクトルの値が 1 / ( 1 - p ) 倍されることになるからです。この状態で全てのニューロンを使って推論を行うと、出力値も 1 / ( 1 - p ) 倍されることになります。よって、重みベクトルを 1 - p 倍して補正するわけです。しかし、このやり方では推論時に重みベクトルを 1 - p 倍する必要があるため、p を保持しておく必要があります。推論時には p がなくても済むように、入力値のほうをあらかじめ 1 / ( 1 - p ) 倍する方法もあり、通常はこちらのほうが多く用いられています。これは「Inverted Dropout」と呼ばれています。AlexNet では、全結合層に対して p = 0.5 としてドロップアウトを適用し、過剰適合を防いでいます。

局所応答正規化 ( Local Response Normalization ; LRN ) は、活性化関数を適用した結果 dq,j,i に対して、以下の式によって行われる正規化処理です。

eq,j,i = dq,j,i / ( κ + αΣr{max(0,q-n)→min(N-1,q+n)}( dr,j,i2 ) )β

式の中で、κ、α、β は定数で、n は計算対象の q 番目の特徴マップに対して、その前後について和を取る特徴マップの枚数、N は全特徴マップの枚数を表します。複雑そうな式ですが、簡単に言えば前後にある特徴マップの同じ座標のデータを使って正規化処理を行っているだけです。もし、dq,j,i が大きい値であっても、その前後の特徴マップの同じ位置に大きな値があれば、計算結果は小さくなります。つまり、近隣のカーネルによる畳み込み結果が互いに抑制し合う効果があるわけです。AlexNet では、κ = 2、α = 10-4、β = 0.75、n = 2 として処理を行い、これによって誤認識率が 1% 以上減少したと報告されています。


6) 性能評価

最後に、サンプル・プログラムを使った評価を行ってみます。さすがに AlexNet はパラメータが多すぎて学習に時間がかかるので、ここではもっと単純なモデルを利用します。
まず、入力データは 28 x 28 のサイズのグレースケール画像で「THE MNIST DATABASE」から入手することができます。この中には 0 から 9 までの手書きの文字が学習用に 60000 枚、テスト用に 10000 枚用意されていて、これをそれぞれの数字に識別するために学習とテストを行います。
CNN のモデルは、畳み込み層とプーリング層のペアを 2 つ連ねたものに、全結合層として隠れ層を一つ、最後に Softmax で 10 個の出力値を得る構成です。活性化関数は、全てにおいて ReLU を使用しました。また、指定がない限り、パディングはなしで処理をしています。

このモデルは、参考サイトの「A gentle explanation of Backpropagation in Convolutional Neural Network (CNN)」をお手本にしています。ker はカーネルのサイズ、stride はストライドの幅、pool はプーリングのサイズで、1 層目と 2 層目で共通とします。
学習は、60000 枚の学習用データから無作為に 100000 回抽出して行いました。学習回数がデータ数より多いことから分かる通り、重複のチェックは行っていません。学習後、テスト用データを使って評価をします。計 10 個の各条件について、この操作を 3 回行い、その平均を示したのが以下の図表になります。

表 6-1. 正答率と処理時間
標準LRNありDropout=0.5LRN+Dropout=0.5stride=2ker=3ker=7pool=3padding=2l1=10,l2=16
学習後の正答率98.14%97.90%98.25%98.17%93.37%97.78%97.92%97.72%98.35%98.40%
学習時間(sec)11.52612.02611.64412.0582.4257.92912.3006.72025.74122.730
テスト後の正答率98.20%98.16%98.08%98.44%93.68%97.90%97.77%97.87%98.21%98.51%
テスト時間(sec)5.4955.8955.5875.9680.9973.5086.3843.30512.44510.668
図 6-1. 正答率 ( 棒グラフ ) と処理時間 ( 折れ線グラフ )
ストライド以外は正答率に大きな差はない

10 個の条件の中で「標準」と書いてあるのが参考サイトと全く同じ条件 ( l1 = 6、l2 = 12、ker = 5、stride = 1、pooling = 2 ) で行った結果です。「LRN あり」は AlexNet で使われた局所応答正規化を活性化関数適用後に追加したものです。両方の層に対して適用し、パラメータは AlexNet と同じく κ = 2、α = 10-4、β = 0.75、n = 2 としています。「Dropout=0.5」は全結合層にドロップアウト ( p = 0.5 ) を用いたもので、さらに「LRN+Dropout=0,5」が局所応答正規化とドロップアウトを両方使った結果です。
その他の条件は局所応答正規化やドロップアウトは用いず、パラメータだけを変化させたときの結果です。畳み込みのストライドを 2 にした「stride=2」、カーネルのサイズを 3, 7 にした「ker=3」「ker=7」、プーリングのサイズを 3 にした「pool=3」、パディングを 2 にした「padding=2」、最後に各層の特徴マップ数を 4 増やした「l1=10,l2=16」を使って評価を行っています。

パラメータの更新は、誤差逆伝播を 1 回行う度に実行します。学習率は 0.005 固定としているのも参考サイト通りの条件です。

グラフの左軸は正答率、右軸は処理時間を表し、それぞれ棒グラフと折れ線グラフを使っています。ストライドを変更した場合を除き、正答率には大きな差異はありませんが、カーネルサイズやプーリングサイズを変えると若干正答率が下がっていることから、参考サイトにあった条件は最適であったことが読み取れます。学習時とテスト時で正答率に大きな違いはないので、学習不足や過剰適合が発生している様子は見られません。非常に単純なモデルながら、正答率 98% というのは凄いものですね。

正答率が最も高いのは、特徴マップの数を増やした条件「l1=10,l2=16」ですが、その差は僅かであり、処理時間は大幅に増大しているので、劇的な改善というものではありません。パディングを増やしたときに処理時間が最大になっているのは、パディングに対する処理の部分があまりいい出来ではなく、効率が悪いからだと推測しています。実際には、ここまで大幅なパフォーマンスの低下はないでしょう。なお、処理時間はあくまでも目安と考えてください。最適化は何も行っていないので、CPU を使っても処理時間はもっと短縮できるでしょうし、GPU を使って並列処理を行えば劇的に改善するでしょう。今回のテストでは、CPU に AMD Ryzen9 5900X 3.70GHz (12C) を用い、VirtualBox 上の Xubuntu 23.10 上で評価しました。

局所応答正規化やドロップアウトの効果は、今回はあまり感じられませんでした。どの場合も過剰適合が発生していないので、ドロップアウトの必要性があまりないこと ( しかも全結合層が 2 層なので場合分けの数が限られていること )、それから局所応答正規化についてはパラメータの調整を行っていないことが原因だと思います。


さて、上記の結果だけでは、学習の効率性が分からないので、今度は学習を 500 回行う毎に正解率を計算する操作を 10 回行い、最後にテストデータ 10000 枚で最終判定を行います。よって、学習は計 5000 回しか行いません。このテストにおいても、各条件について 3 回試行し、その平均を示しています。

表 6-2. 学習回数と正答率の関係
標準LRNありDropout=0.5LRN+Dropout=0.5stride=2ker=3ker=7pool=3padding=2l1=10,l2=16
train116.47%16.00%17.20%18.20%10.20%10.67%20.33%11.33%19.00%21.93%
train241.60%46.33%47.80%50.93%12.40%14.27%50.40%15.20%49.00%59.07%
train374.67%74.07%75.27%76.33%11.87%25.27%74.80%26.53%75.87%79.93%
train483.80%82.87%84.07%84.27%12.73%53.47%84.13%37.27%84.93%84.40%
train584.60%87.53%87.60%86.53%13.00%71.07%85.80%56.87%88.20%88.33%
train689.27%89.53%88.20%89.47%14.33%80.67%87.00%70.60%89.53%91.67%
train788.07%89.33%90.47%89.80%17.67%83.60%88.73%77.93%90.13%90.73%
train890.40%89.20%90.00%91.33%21.33%85.67%89.80%83.73%92.73%92.53%
train991.20%92.00%91.80%91.13%26.53%88.27%89.80%85.40%92.73%93.40%
train1091.60%90.87%92.27%90.53%34.40%88.87%91.60%87.40%92.33%91.87%
学習時間(sec)5.8695.9905.7946.0501.1763.9066.1773.33412.95811.384
テスト後の正答率93.66%92.95%92.38%92.38%42.28%88.88%92.26%88.31%94.10%93.61%
テスト時間(sec)5.5375.9785.5325.9840.9973.4506.4143.33312.47410.718
図 6-2. 学習による正答率の変化
三つのグループに分けられる

ストライドを 2 にした場合、他と比べて学習が進んでいない様子がはっきりと分かります。これは考えてみれば当然の結果で、畳み込みとプーリングによって半分のサイズに縮小されるので、全結合層には一つしかデータが伝播されません。それで 10 個に分類するわけなので、学習が遅くなってしまうわけです。プーリングのサイズを 3 にした場合も、全結合層に渡されるデータは 3 個なので、やはり不利になります。しかし、カーネルサイズを 3 にしたときの学習の遅さは、ちょっと原因が思いつきません。
学習が最も速いのは、やはり特徴マップを増やしたときのようです。層を深くするほど、特徴マップを多くするほど表現力は向上するので認識率も速く上昇します。それが結果として反映されているということですね。

学習を速くする、すなわち収束を速くするための手法がいろいろ提案されています。今回は、最適化は一切行っていないので、学習率を向上させる余地は十分にあります。例えば、学習率を進捗度合いに従って適正に変化させる方法や、学習の進み具合を調整する方法などが知られています。また、学習を安定させるために、ミニバッチと呼ばれるやり方も存在します。


AlexNet が登場してから、ILSVRC での優勝モデルは CNN が独占することになります。2017 年に登場した SENet は誤認識率が 2.251 % と、もはや人間の識別能力を超えたと考えられています。次回から、その中の代表的なモデルとして、GoogLeNetResNetSENet を紹介する予定です。


<参考文献>
  1. ImageNet Classification with Deep Convolutional Neural Networks
  2. A gentle explanation of Backpropagation in Convolutional Neural Network (CNN)
  3. 【やさしく解説】ドロップアウト (Dropout) を理解する
  4. Wikipedia

[Go Back]前に戻る [Back to HOME]タイトルに戻る
inserted by FC2 system