第3回 多層パーセプトロン

levelfour edited this page Nov 30, 2014 · 7 revisions

単純パーセプトロンは線形分離可能なデータしか分類できなかった。線形分離でないデータの例に、XOR演算がある。

data[0] data[1] label
0 0 1
0 1 0
1 0 0
1 1 1

2次元でプロットすると線形分離可能ではないことがわかると思う。

しかし実はXOR演算も次のようにdata[2]=data[0]*data[1]というデータを追加してやれば線形分離可能になる。

data[0] data[1] data[2] label
0 0 0 1
0 1 0 0
1 0 0 0
1 1 1 1

よって識別平面がひけるようになる。

ちなみにこの識別面はz=0.7x+0.7y-1.5でひいている。

これは次のように表すことができる。

すなわち、入力データは2次元だが、それを3次元の中間データに変換し、最終的に出力を得るという形になっている。 単純パーセプトロンは入力層と出力層の2層のみから構成されるが、このように中間層を挟んだ形のパーセプトロンを多層パーセプトロンという。(中間層は隠れ層とも呼ばれる。)

多層パーセプトロンにおける中間層のノード数(M)や中間層の層数は実験的に定められることが多い。一般的にノード数や層数が多いほど表現能力は上がるが、過学習してしまう傾向がある。多層パーセプトロンを数式で表すと以下のようになる。

z=\mathbf{v^{\mathrm{T}}}\begin{pmatrix}g(\mathbf{w_1^{\mathrm{T}}x})\\g(\mathbf{w_2^{\mathrm{T}}x})\\:\\:\\g(\mathbf{w_M^{\mathrm{T}}x})\end{pmatrix}=\sum_{i=1}^Mv_ig(\sum_{j=1}^Nw_{ij}x_j)

学習の目的は、シナプス荷重v,w_1,w_2,...w_Mを得ることである。また、出力層はこの例では1ノードのみになっているが、ノード数を増やすことによって多クラス分類に対応させることができる(例えばz_i=1,z_j=0(j≠i)のときクラスiに分類する、など)。

gとして非線形関数を用意する。なぜならgが線形写像ならば中間層を挟んだ2層の回路も縮約して1層で表せてしまうからである。gとしてよく使われるのはtan^(-1)やシグモイド関数である。ここではシグモイド関数を扱うことにする。

シグモイド関数

シグモイド関数は以下のような関数である。

g(\mathbf{w^{\mathrm{T}}x})=\frac{1}{1+\exp(-\beta{\mathbf{w^{\mathrm{T}}x})}

ただしβは正の定数値。βの大きさによって以下のようなグラフになる。

0付近で線形に動作し、0から離れるにつれて非線形に動作する。またβが小さいほど緩やかになり、βが大きいほどステップ関数に近づく。 (アークタンジェントが用いられることがあるのも、挙動がこの関数に似ているからである)

多層パーセプトロンの学習規則

多層パーセプトロンも単純パーセプトロンと同様にオンライン学習を行う。その学習規則は以下のようにする。ただし評価関数Jは二乗誤差関数とし、この学習規則によって最小化される。また、tは学習データのラベルである。

J(\mathbf{w_1},,...\mathbf{w_M};\mathbf{v})=\{z(\mathbf{w_1},...,\mathbf{w_M},\mathbf{v},\mathbf{x})-t\}^2

\mathbf{w_m}^{\mathrm{new}}=\mathbf{w_m}^{\mathrm{old}}-\eta\frac{\partial J}{\partial \mathbf{w_m}}

\mathbf{v}^{\mathrm{new}}=\mathbf{v}^{\mathrm{old}}-\eta\frac{\partial J}{\partial \mathbf{v}}

このようにある関数を最小化(最大化)するのにその関数の一階微分を用いる手法を__最急降下法__という。 なぜこのようにすれば関数を最小化できるのかというアルゴリズムについては割愛して説明を譲りたい。

【参考】最急降下法

【追記】最急降下法の解説も書きました→第4回 - 勾配法(最急降下法)

少し詳しく見るために、実際に一階微分を計算してみる。

\frac{\partial J}{\partial \mathbf{v}}=\frac{\partial}{\partial\mathbf{v}}(z-t)^2=2(z-t)\begin{pmatrix}g(\mathbf{w_1^{\mathrm{T}}x})\\:\\g(\mathbf{w_M^{\mathrm{T}}x})\end{pmatrix}

最右辺のz-tは最終出力と学習データのラベルの差であるから、誤差を表している。(g(w_1 x), ... , g(w_M x))は中間層の出力ベクトルである。つまりvについての学習規則は__vを中間層出力ベクトルの方向に修正し、修正の大きさは誤差が大きいほど大きく、小さいほど小さい__ということになる。一見わかりにくいが、単純パーセプトロンの固定誤り増分法とのアナロジーで理解してほしい。(固定誤り増分法は__wベクトルを出力が間違っていた場合に、入力ベクトルの方向に修正する__)

\frac{\partial J}{\partial\mathbf{w_m}}=\frac{\partial}{\partial\mathbf{w_m}}(z-t)^2=2(z-t)\frac{\partial}{\partial\mathbf{w_m}}v_mg(\mathbf{w_m^{\mathrm{T}}x})=2(z-t)v_mg'\mathbf{x}

w_mの学習規則についても同様である。vの場合と異なるのはz-tが(z-t)(v_m)g'に置き換わっていることである。これは次のように解釈するとよい。

  1. v_mが小さいとき⇔中間層第mノードが出力に与える影響は小さい
  2. v_mが大きいとき⇔中間層第mノードが出力に与える影響は大きい
  3. g'が小さいとき⇔中間層第mノードが出力に与える影響は小さい
  4. g'が大きいとき⇔中間層第mノードが出力に与える影響は大きい

つまり、中間層第mノードが出力に与える影響が小さいならw_mを更新する意味はあまりないし、与える影響が大きいなら更新する必要性が高いということである。 このように出力層の誤差を中間層に差し戻し、中間層の各ノードがどれくらいクリティカルかによって係数ベクトルを更新していくという手法を__誤差逆伝播法(Error Back Propagation, BP法)__と呼ぶ。

(補足)「3. g'が小さいとき⇔中間層第mノードが出力に与える影響は小さい」の理由がわかりにくいかもしれないので、詳しく説明しておく。g'が小さいということは入力データxが変化してもgの値はあまり変化しない(導関数が小さいから)ということである。つまり、このノードに対してどのような入力データを流し込んでも出力はあまり変わらないということになる。

実装

これまでの説明を素直に実装したのがこのソースコードになる。

重みの初期ベクトルはランダムにしてある。初期値によって収束の速度が変わるし、精度も変わってしまう。

またシグモイド関数の値を計算するときにβの値によっては関数値が簡単にオーバーフローしてしまうので、βは小さめに設定してある。

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.