畳み込みニューラルネットワークの勉強のまとめ その1

畳み込みニューラルネットワーク (Convolutional Neural Network) を勉強するため、MNISTのデータの識別をライブラリ(Caffecuda-convnetなど)を使用せず一から実装してみましたが、ここでは備忘録として書いていくことにします。

出来る限り理解し易いように書いていくように努力はします。(^_^;;

おかしな点があれば教えてください。お願いします。

 

まずは二値分類

多次元の入力データから、それが識別対象かそうでないか(例えば画像から人かそうでないか)といった二値分類の学習を考えます。

入力を\(n\)次元の\(\mathbf{x}=(x_1\ x_2\ \dots\ x_n)^\text{T}\)*1、重みを\(\mathbf{w}=(w_1\ w_2\ \dots\ w_n)^\text{T}\)とし、これら入力と重みを掛け合わせたものとバイアス\(b\)の総和\(a\)を、

\[a = \mathbf{x}^\text{T} \mathbf{w} + b = \sum_{i=1}^n x_i w_i + b \tag{1} \]

とします。この\(a\)の取り得る範囲は\( (-\infty,\infty)\)ですので、ここではSigmoid関数

\[f(u) = \frac{1}{1+e^{-u}} \tag{2} \]

を通して出力\(y\)を

\[y = f(a) \tag{3}\]

とし、出力の値の範囲を\([0,1]\)にします(Sigmoid関数のグラフはこんな感じです)。これを図にすると次のようになります。

f:id:hshinji:20150425001756p:plain

こうすることで識別対象の場合を\(1\)、それ以外を\(0\)とした時に出力\(y\)を「入力が識別対象である確率」と同じように扱えます。

 

さて、ちゃんと識別できるようにするためには重み\(\mathbf{w}\)を学習して決める必要があります。そのためにはまず、識別対象のサンプル(ポジティブサンプル)とそれ以外のサンプル(ネガティブサンプル)を用意し、それぞれのサンプルには教師ラベル\(t\)を割り当てて訓練用のデータとします。この教師ラベルは上記の出力\(y\)に合わせてポジティブサンプルの場合に\(t=1\)、ネガティブサンプルの場合に\(t=0\)としましょう。ポジティブ・ネガティブを含む訓練データが\(N\)個あるのなら\(\{\mathbf{x}_1, t_1\}, \{\mathbf{x}_2, t_2\}, \dots, \{\mathbf{x}_N, t_N\}\)という組み合わせとなります。

ここで一旦バイアス\(b\)は忘れます。バイアスについては後述します。

先に出力\(y\)は「入力が識別対象である確立と同じように扱える」と書きましたが、これを式で表すと

\[p(t=1|\mathbf{x}, \mathbf{w}) \approx y(\mathbf{x}, \mathbf{w}) \tag{4}\]

即ち\(\mathbf{x}\)と\(\mathbf{w}\)が与えられた時に\(t=1\)となる確率\(p\)と出力\(y\)がほぼ等しいということになります。また反対に\(t=0\)となる確率は、

\[p(t=0|\mathbf{x}, \mathbf{w}) \approx 1-y(\mathbf{x}, \mathbf{w}) \tag{5}\]

と書けます。\( (4)\)式、\( (5)\)式をまとめて一つの確率分布とすると、

\[p(t|\mathbf{x}, \mathbf{w}) = p(t=1|\mathbf{x}, \mathbf{w})^t p(t=0|\mathbf{x}, \mathbf{w})^{1-t} \tag{6}\]

となります。これをすべての訓練データに対して尤もらしい値を返すような\(\mathbf{w}\)を求めるために最尤法を用います。

\[\begin{align} L(\mathbf{w}) &= \prod_{d=1}^N p(t_d|\mathbf{x}_d, \mathbf{w}) \\ &= \prod_{d=1}^N p(t_d=1|\mathbf{x}_d, \mathbf{w})^{t_d} p(t_d=0|\mathbf{x}_d, \mathbf{w})^{1-t_d} \\ & \approx \prod_{d=1}^N y(\mathbf{x}_d, \mathbf{w})^{t_d} \{ 1-y(\mathbf{x}_d, \mathbf{w}) \}^{1-t_d} \\ &= \prod_{d=1}^N y_d^{t_d} (1-y_d)^{1-t_d} \qquad \text{where} \quad y_d = y(\mathbf{x}_d, \mathbf{w}) \tag{7} \end{align}\]

この\(L(\mathbf{w})\)が最大となる\(\mathbf{w}\)を求めることになります。ただしこの積の式では扱いにくいので対数を取り、

\[\text{log}~L(\mathbf{w}) \approx \sum_{d=1}^N \{ t_d \text{log}~y_d + (1-t_d)\text{log} (1-y_d) \} \tag{8}\]

といった和の式に変換できます。この式は\(-1\)をかけて

\[ E(\mathbf{w}) = -\sum_{d=1}^N \{ t_d \text{log}~y_d + (1-t_d)\text{log} (1-y_d) \} \tag{9} \]

とすることで、\(E(\mathbf{w})\)の最小化問題に置き換えることが出来ます。

ここで、\( (9)\)式内の\(-\text{log}~y_d\) と \(-\text{log}(1-y_d)\) は\( (2)\)、\( (3)\)式からSigmoid関数が含まれています。展開すると*2それぞれ

\[-\text{log}~y_d = -\text{log} \frac{1}{1+e^{-a_d}} = \text{log}(1+e^{-a_d}) \tag{10}\]

\[-\text{log}(1-y_d) = -\text{log} \frac{e^{-a_d}}{1+e^{-a_d}} = \text{log}(1+e^{-a_d})+a_d \tag{11}\]

となり、それぞれグラフはこんな感じこんな感じとなり、下に凸の関数となります。そのため\( (9)\)式も下に凸の関数となるため、微分して\(0\)になる\(\mathbf{w}\)が求めたい重みとなります。

\(E(\mathbf{w})\)を最小にする\(\mathbf{w}\)を求めるのに簡単な方法に勾配降下法があります。これは下の図のように\(\mathbf{w}\)での傾き\(\frac{\partial E}{\partial \mathbf{w}}\)の負の方向に少しずつ\(\mathbf{w}\)を移動させる方法です。

f:id:hshinji:20150430173541p:plain (横軸はイメージです…)

式にすると

\[\mathbf{w} \leftarrow \mathbf{w} - \epsilon \frac{\partial E}{\partial \mathbf{w}} \tag{12}\]

となり、これを何回も繰り返していくと上図の\(\hat{\mathbf{w}}\)へ近づいていきます。ただし\(\epsilon\)の値が大きいと収束せずに発散することがあるので注意が必要です(逆に小さいと時間がかかります…)。この\(\epsilon\)のことを学習係数と呼びます。

 

ではここで、偏微分\(\frac{\partial E}{\partial \mathbf{w}}\)を求めてみましょう。\( (9)\)式の右辺には直接\(\mathbf{w}\)が出てこないので、間に\(\partial y_d\)をはさんで次のようにします。

\[\frac{\partial E}{\partial \mathbf{w}} = \sum_{d=1}^N \frac{\partial E}{\partial y_d} \cdot \frac{\partial y_d}{\partial \mathbf{w}} \tag{13}\]

まずは\(\frac{\partial E}{\partial y_d}\)を求めましょう。\(t_d=1\)のときは\( (9)\)式から、

\[\frac{\partial E}{\partial y_d} = -\frac{\partial}{\partial y_d} \sum_{d=1}^N \text{log}~y_d = -\frac{1}{y_d} \tag{14}\]

また\(t_d=0\)のときは

\[\frac{\partial E}{\partial y_d} = -\frac{\partial}{\partial y_d}\sum_{d=1}^N \text{log}(1-y_d) = \frac{1}{1-y_d} = -\frac{1}{y_d-1} \tag{15}\]

\( (14)\)式と\( (15)\)式をまとめると

\[\frac{\partial E}{\partial y_d} = -\frac{1}{y_d + t_d -1} \tag{16}\]

となります。

次に\(\frac{\partial y_d}{\partial \mathbf{w}}\)を求めますが、\( (1)\)式と\( (3)\)式の間には\( (2)\)式のSigmoid関数がありますので間に\(\partial a_d\)をはさんで

\[\frac{\partial y_d}{\partial \mathbf{w}} = \frac{\partial y_d}{\partial a_d} \cdot \frac{\partial a_d}{\partial \mathbf{w}} \tag{17}\]

として今度は\( (2)\)式Sigmoid関数の偏微分\(\frac{\partial y_d}{\partial a_d}\)を求めます。

\[\begin{align} \frac{\partial y_d}{\partial a_d} &= \frac{\partial}{\partial a_d} \cdot \frac{1}{1+e^{-a_d}} \\ \\ &= \frac{e^{-a_d}}{(1+e^{-a_d})^2} \\ \\ &= \frac{1}{1+e^{-a_d}} \cdot \frac{e^{-a_d}}{1+e^{-a_d}} \\ \\ &= y_d (1-y_d) \tag{18} \end{align}\]

最後に\(\frac{\partial a_d}{\partial \mathbf{w}}\)は\( (1)\)式から

\[\frac{\partial a_d}{\partial \mathbf{w}} = \frac{\partial}{\partial \mathbf{w}}(\mathbf{x}_d^\text{T} \mathbf{w} + b) = \mathbf{x}_d \tag{19}\]

となるので、\(\frac{\partial E}{\partial \mathbf{w}}\)は\( (16)\)式、\( (18)\)式および\( (19)\)式から一旦

\[\frac{\partial E}{\partial \mathbf{w}} = \sum_{d=1}^N \frac{\partial E}{\partial y_d} \cdot \frac{\partial y_d}{\partial a_d} \cdot \frac{\partial a_d}{\partial \mathbf{w}} = \sum_{d=1}^N \frac{y_d (y_d - 1)}{y_d + t_d -1} \mathbf{x}_d \tag{20}\]

となります。ここで\(t_d=1\)のときは

\[\frac{\partial E}{\partial \mathbf{w}} = \sum_{d=1}^N \frac{y_d (y_d - 1)}{y_d} \mathbf{x}_d = \sum_{d=1}^N (y_d - 1) \mathbf{x}_d \tag{21}\]

\(t_d=0\)のときは

\[\frac{\partial E}{\partial \mathbf{w}} = \sum_{d=1}^N \frac{y_d (y_d - 1)}{y_d-1} \mathbf{x}_d = \sum_{d=1}^N y_d \mathbf{x}_d \tag{22}\]

となり、最終的に

\[\frac{\partial E}{\partial \mathbf{w}} = \sum_{d=1}^N (y_d - t_d) \mathbf{x}_d \tag{23}\]

とまとまります。出力結果から教師ラベルを引いた値を入力データに掛けたものの総和、といった単純な式になりましたね。この\( (23)\)式の値を使って重みを更新していくことになります。

 

ここで先ほど無視したバイアス\(b\)について思い出してみましょう。バイアスも重みと同じように計算します。\( (9)\)式に対して\(b\)で偏微分すると

\[\frac{\partial E}{\partial b} = \sum_{d=1}^N (y_d - t_d) \tag{24}\]

となり、これも出力結果から教師ラベルを引いた値の総和といった単純な式になります。また更新式は

\[b \leftarrow b - \epsilon \frac{\partial E}{\partial b} \tag{25}\]

となります。

 

上記の方法では、一旦すべての訓練データを用いて\(\frac{\partial E}{\partial \mathbf{w}}\)と\(\frac{\partial E}{\partial b}\)を計算し、その値で重みとバイアスを更新、そして再度すべての訓練データで\(\frac{\partial E}{\partial \mathbf{w}}\)と\(\frac{\partial E}{\partial b}\)を計算して重みとバイアスを更新…、というように繰り返していきますが、\( (23)\)式と\( (24)\)式をそれぞれ

\[\frac{\partial E_d}{\partial \mathbf{w}} = (y_d - t_d) \mathbf{x}_d \tag{26}\]

\[\frac{\partial E_d}{\partial b} = y_d - t_d \tag{27}\]

また\( (12)\)式と\( (25)\)式の更新式をそれぞれ

\[\mathbf{w} \leftarrow \mathbf{w} - \epsilon \frac{\partial E_d}{\partial \mathbf{w}} = \mathbf{w} - \epsilon (y_d - t_d) \mathbf{x}_d \tag{28}\]

\[b \leftarrow b - \epsilon \frac{\partial E_d}{\partial b} = b - \epsilon (y_d - t_d) \tag{29}\]

として訓練データひとつ毎に更新する方法があります*3。この方法を確率的勾配降下法といいます。

 

 

次回は多クラス分類について説明します。

 

参考文献 

深層学習 (機械学習プロフェッショナルシリーズ)

深層学習 (機械学習プロフェッショナルシリーズ)

*1:\(\text{T}\)は転置を表します

*2: \( (1)\)式は一次式なので、展開はSigmoid関数までとしました。

*3:または数個~数十個ずつ訓練データをまとめて更新する方法(ミニバッチ)もあります