Pythonによるニューラルネットワークの実装➁

機械学習 Python R

Python でニューラルネットワークを実装してみましょう。前回は、データが与えられた時に0~9のラベルを出力する関数と、正解率を求める関数を実装しました。作ろうとしているモデルは以下のグラフで表されます。下の方に書いている小文字が、コードで使われる文字と対応しています。

ニューラルネットワークモデル
実装するモデル

今回の目標は、誤差関数の計算と勾配の計算を行うことです。勾配が必要な理由や、計算の仕方については以下の記事をご覧ください。

ニューラルネットワークの話
ニューラルネットワークについての小話です。計算グラフを用いて、ニューラルネットワークモデルを表します。分類問題をニューラルネットワークで解く実験もしています。
誤差逆伝搬法
誤差逆伝搬法の解説記事です。連鎖律と微分の定義を知ってれば当たり前だね~と納得できます。知らなくても何とかなります。

記事で使っているソースコードはgithub に置いてあります。
https://github.com/msamunetogetoge

誤差関数(交差エントロピー)の実装

softmax 関数と、交差エントロピー誤差は以下の式で定義されます。
$$\begin{eqnarray}
L( \vec{y}, \vec{t} ) &=& – \sum t_i \log y_i
\end{eqnarray}$$
ラベルが2つの場合はロジスティック回帰で出てきました。
pythonでの実装コードは以下になります。ただし、ラベルがone hot encording 1 済みの場合は、正解ラベルに対応する成分だけ1なので、yの成分一つだけ取り出すという形で実装しています。

誤差関数の計算をしてみましょう。0から10までの画像に対して計算します。計算できるという事が大事で、値の大きさは全く気にしません。

関数の勾配の計算

関数の勾配 2 を計算しましょう。実装するには勾配の表式が必要です。softmax 関数と交差エントロピー誤差の合成の勾配を計算します。softmax 関数はfで表します。
$$\begin{eqnarray}
f(\vec{x} )&=& \left( \frac{\exp(x_1)}{\sum \exp(x_j)} , \cdots , \frac{\exp(x_N)}{\sum \exp(x_j)} \right) \\
L(\vec{y}, \vec{t}) &=& – \sum t_i \log y_i \\
\nabla L\left( f(\vec{x} ) , \vec{t} \right) _k &=&- \frac{ \partial}{\partial x_k } \sum t_i \left( x_i -\log \sum \exp(x_j ) \right) \\
&=& \frac{\exp(x_1)}{\sum \exp(x_j)} – t_k = f(x_k ) – t_k
\end{eqnarray}$$
ただし、ラベルのベクトルはone hot encordingされていると思っていて、\( \sum t_i =1 \)を使いました。ラベルは0~9の数字で表されていたので、one hot encording しておきます。

relu 関数の微分は以下のようにしておきます。数学的には微分出来ない点がありますが、気にしないことにします。
$$\begin{eqnarray}
\frac{d}{dx} relu(x) = \begin{cases} 1 & (x \geq 0 )\\
0 & (x<0 )
\end{cases}
\end{eqnarray}$$
python コードは以下です。

モデルの勾配計算の実装

実装する必要のある計算を列挙します。

  • 行列をベクトルに掛ける関数の,行列による微分
  • 定数ベクトルを足す演算のベクトルによる微分
  • relu の微分
  • softmax 関数との微分

それぞれのパーツでの勾配を求めておけば、後はそれを掛けるだけです。例えば、出力層の\( y=f( W_2 x +b_2 )=f(X) \)における、\(b_2 \)の勾配は、 \( \frac{\partial X }{\partial {b_2}_k }=\vec{e}_k \)であることを使うと以下のように計算出来ます。ただし、\( \vec{e}_{k} \)は第k成分が1でそれ以外は0のベクトルです。
$$\begin{eqnarray}
\nabla_{b_2} L &=& \sum_{i} \frac{\partial L} {\partial X_i } \nabla_{b2} X_i \\
&=& \left( \frac{\partial L} {\partial X_1 } , \cdots , \frac{\partial L} {\partial X_N } \right) \\
&=& \vec{y} -\vec{t}
\end{eqnarray}$$
と計算出来ます。
その辺りがピンと来ない人は、以下の記事をご覧ください。

誤差逆伝搬法
誤差逆伝搬法の解説記事です。連鎖律と微分の定義を知ってれば当たり前だね~と納得できます。知らなくても何とかなります。

これで、勾配の実装をする準備 3 が整いました。 前の記事で定義したクラスに、次の関数を書き加えます。本当は先ほど定義したcross_entropy_error 関数を使っても良いのですが、計算途中のパラメーターが必要なので同じ意味のことを書いています。

前回作った適当な行列やベクトルで計算させてみましょう。

上手く計算出来ているはずですが、エラーが出たら教えてください。

まとめ

・出力値から誤差関数を計算した。
・勾配を計算した。
・勾配は逆側から計算されるので、\(W_1 \) とかの誤差の計算を書き下そうとは思えない。
・python によるニューラルネットワークの実装➂はこちらから
https://masamunetogetoge.com/make-neuralnetwork3

  1. 正解の番号の成分だけ1で、他は0になっているベクトルに変換することです。
  2. 行列の積や、ベクトルを足す関数が出てきますが、そこは簡単なので最後のコードを見てください。
  3. データは2つ以上渡す前提での実装です。1つだけ渡したいときは、コメントアウトした所を使ってください。
タイトルとURLをコピーしました