ロゴ

プログラミング初心者がアプリ開発を目指すブログ

ニューラルネットワークについて – Pythonでディープラーニング-002

前回は機械学習の基本を見ていきました。

簡単に復習しますと
機械学習は既存のデータを用いて、回帰問題(明日の昼の長さを予想する)や分類問題(リンゴかオレンジか判定する)を解くものです。

その手順は、
1. 実測値をもとにして、予測を行う数式を考える
2. 誤差を表す数式を考える
3. 誤差が最小になるように係数を調整する
の3つでした。

ということで、機械学習を行おうとする人はまず、「実測値をもとにして、予測を行う数式を考える」を行わなければなりません。
この作業は数学が専門でない人にはとても難しいものですし、たとえ数学者でも4つ以上の変数を用いると、データの分布を表す数式を想像することは難しいでしょう。
そこで複雑な問題に対しても、柔軟に対応できる「数式」の一つの形としてニューラルネットワークが生み出されました。

ニューラルネットワークの仕組み

ニューラルネットワークの考え方は「複数の数式を組み合わせることで、複雑な関数を表現しよう」というものです。
下図がニューラルネットワークの例です。

\begin{align}
f_1(x_1,x_2) = w_{10} + w_{11}x_1 + w_{12}x_2\\f_2(x_1,x_2) = w_{20} + w_{21}x_1 + w_{22}x_2\\f(z_1,z_2) = w_0 + w_1z_1 + w_2z_2
\end{align}
左から\(x_1,x_2\)を\(f_1(x_1,x_2)\)に渡して出てきた値をシグモイド関数\(\sigma(x)\)で0〜1の値に変化したものが変数\(z_1\)として次の関数へ渡しています。
一つ一つの丸はノードと呼ばれ、このノードの数を増やし、何層かに重ねることで複雑な曲線を表現します。数学的には、ノードの数を増やしていくことでどれほど複雑な関数でも表現できるそうです。(一部特異な例を除く)

図のニューラルネットワークは\(w_{10},w_{11},w_{12},w_{20},w_{21},w_{22},w_{0},w_{1},w_{2}\)の9つのパラメータが含まれています。
この9つのパラメータを調整することで曲線を表現していくわけですが、
ノードを増やせば増やすほどこのパラメータの数が増えコンピューターの計算が膨大となり、果てには計算不可能となってしまします。
結局、ニューラルネットワークでも機械学習の困難さは解決しきれませんでした。

そこで、単純にノードの数を増やして複雑化するのではなく、
解くべき問題に合わせて工夫がなされた特別なニューラルネットワークを用いて機械学習を行うことをディープラーニングと呼びます。

例えば、画像データを用いて手書き画像認識を行う場合はCNN(畳み込みニューラルネットワーク)を使います。
また、時系列データを扱う際はRNN(再帰型ニューラルネットワーク)を使います。
これらの詳細については今後また解説していきます。

パラメータ調整の仕組み

ニューラルネットワークを使って関数を作った後は、誤差を表す関数をつくりパラメータを調整していきます。
ここからはパラメータ調整の仕組みを見ていきましょう。
偏微分など数学的な話が少し出てきますが、あまり考えすぎずになんとなく読んでみてください。

話を簡単にするために前回の月別の昼の長さを予測する問題に話を戻します。
この問題では現象を予測する式・誤差を表す式として以下の2式を用意しました。
\begin{align}
y = w_0 + w_1x + w_2x^2 + w_3x^3 + w_4x^4\\E = \frac{1}{2}\sum_{n=1}^{12}(y_n-t_n)^2
\end{align}
\(n\)月の昼の長さを\(y_n\)とすると\(x\)に\(n\)を代入して
\begin{align}
y = w_0 + w_1x + w_2x^2 + w_3x^3 + w_4x^4 = \sum_{m=0}^{4}w_0n^m
\end{align}
と表すことができます。これを誤差の式に入れるとEは\(w_0,w_1,w_2,w_3,w_4\)の関数になり
\begin{align}
E(w_0,w_1,w_2,w_3,w_4) = \frac{1}{2}\sum_{n=1}^{12}(\sum_{m=0}^{4}w_0n^m-t_n)^2
\end{align}
mには0〜4が入り、nには1〜12が入ります。
ということで結局、未知の変数は\(w_0,w_1,w_2,w_3,w_4\)だけとなり、Eはこれらの2次関数になります。

このEを\(w_0,w_1,w_2,w_3,w_4\)のそれぞれで偏微分した値を0とした連立方程式を解くことでパラメータを最小化することができます。
\begin{align}
\frac{\partial E}{\partial w_m}(w_0,w_1,w_2,w_3,w_4) = 0 \ (m=0,…4)
\end{align}
なぜ、このようになるのかを図形的に考えるために次のような2変数関数を考えます。
\begin{align}
f(x_1,x_2) = x_1^2 + x_2^2
\end{align}
これを偏微分すると
\begin{align}
\frac{\partial f}{\partial x_1}(x_1,x_2) = 2x_1,\ \frac{\partial f}{\partial x_2}(x_1,x_2) = 2x_2
\end{align}
この2つの偏微分を並べたベクトルを勾配ベクトル\(\nabla f\)と呼びます。
この勾配ベクトル\(\nabla f\)の方向はこの関数fの壁を登っていく方向に一致し、勾配ベクトル\(\nabla f\)の大きさは壁を登る傾きに一致します。
図示すると以下のような感じです。(だいぶ雑ですが)
図からわかる通り、勾配ベクトルと逆向きに進むことで、関数fの最小値に向かい、勾配ベクトルの大きさはだんだん0に近づいていきます。
そして勾配ベクトルの大きさが0になると、関数fは最小値をとります。

勾配ベクトルを逆向きにたどることで関数fを最小にする\(x_1,x_2\)を見つけることができます。
現在の位置を\(x^k=(x_1,x_2)\)として、新しい位置を\(x^{k+1}\)とすると
\begin{align}
x^{k+1} = x^k – \varepsilon\nabla f
\end{align}
このように関数fを最小化する\(x_1,x_2\)を見つける方法を勾配降下法と言います。
\(\varepsilon\)を学習率と呼び、通常0.01や0.001などの小さい値を入れます。
学習率が大きすぎると行ったり来たりしてしまい、最終的に値が発散してしまいます。
しかし、あまりに小さすぎると学習に非常に長い時間がかかります。このへんは問題に合わせて試行錯誤を行う必要があります。

先ほどまでの5変数関数の話に戻ると、誤差を表す関数Eを最小にする\(w_0,w_1,w_2,w_3,w_4\)を決定するには、
これらを並べたベクトルを\(w^k = (w_0,w_1,w_2,w_3,w_4)\)として、
\begin{align}
w^{k+1} = w^k – \varepsilon\nabla E(w)
\end{align}
ここで
\begin{align}
\nabla E(w)=( \frac{\partial E}{\partial w_0}(w),…,\frac{\partial E}{\partial w_4}(w))
\end{align}
これで、誤差を最小化するパラメータ\(w_0,w_1,w_2,w_3,w_4\)を決定することができました。

ニューラルネットワークでは、一番右側の層(出力側の層)から左側の層(入力側の層)に向けて誤差を伝播させてパラメータを最適化させます。
これを誤差逆伝播法と言います。(誤差逆伝播法については気が向いたら書きます。普通にニューラルネットワークを利用する分にはあまり意識する必要はありません。)

次回からディープラーニングのライブラリであるChainerの使い方を見ていきましょう。

スポンサード リンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA