前回まで
第1回
http://qiita.com/mochizukikotaro/items/5258b4857fa6a78f9ed5
第2回
http://qiita.com/mochizukikotaro/items/1632d3417d6d662beb81
今回
多層パーセプトロンを用いると何が嬉しいのかを説明したいと思います。
※ 今回も。初心者による、初心者のための勉強会資料となっています。
簡単な問題をかんがえる
train_x = np.array([
[1, 0, 1, 0],
[0, 1, 0, 1],
[1, 0, 0, 1],
[0, 1, 1, 0],
[0, 1, 1, 0],
])
train_y = np.array([
[1,0],
[1,0],
[0,1],
[0,1],
[0,1],
])
前回使ったモデルで考える
x = tf.placeholder("float", [None, 4])
y_ = tf.placeholder("float", [None, 2])
W = tf.Variable(tf.zeros([4, 2]))
b = tf.Variable(tf.zeros([2]))
y = tf.nn.softmax(tf.matmul(x, W) + b)
うごかしてみると
% python mnist_beginner_sample.py (git)-[test]
Step: 0
誤差: 2.48534
Step: 800
誤差: 2.30793
Step: 3200
誤差: 2.30793
# 全然収束しない
[[ 0.43708152 0.56291848]
[ 0.43708152 0.56291848]
[ 0.56291795 0.43708208]
[ 0.31885403 0.68114597]
[ 0.31885403 0.68114597]]
ここで層を増やしてみる
i_dim = 4
h_dim = 7
x = tf.placeholder("float", [None, i_dim])
y_ = tf.placeholder("float", [None, 2])
w_h = tf.Variable(tf.random_normal([i_dim, h_dim], mean=0.0, stddev=0.05))
w_o = tf.Variable(tf.random_normal([h_dim, 2], mean=0.0, stddev=0.05))
b_h = tf.Variable(tf.zeros([h_dim]))
b_o = tf.Variable(tf.zeros([2]))
def model(X, w_h, b_h, w_o, b_o):
h = tf.sigmoid(tf.matmul(X, w_h) + b_h)
y = tf.nn.softmax(tf.matmul(h, w_o) + b_o)
return y
y = model(x, w_h, b_h, w_o, b_o)
ポイントはここです
h = tf.sigmoid(tf.matmul(X, w_h) + b_h)
pyx = tf.nn.softmax(tf.matmul(h, w_o) + b_o)
前回 $softmax$ を無視したように、今回も $sigmoid$ については無視しましょう。
するとこんな感じになります
% python mlp.py (git)-[test]
Step: 1000
誤差3.33253
Step: 4000
誤差1.20457
# だいたいOKでしょう
[[ 0.83402312 0.16597687]
[ 0.83378381 0.16621622]
[ 0.26640555 0.73359448]
[ 0.06264886 0.93735111]
[ 0.06264886 0.93735111]]
ちょっと注意
じつは、上のモデルでも上手くいくようにデータの個数を5個にして、ちょっと歪にしています。最後の要素を取り除いてキレイな左右対称だと上手くいきません。が、例えば層を2層にして、relu
メソッドや、adam
オプティマイザーを使えばその場合も上手くいます。
なぜ層を増やすとうまくいくのでしょうか?
{\tiny
\begin{pmatrix}
1&0&1&0 \\
0&1&0&1 \\
1&0&0&1 \\
0&1&1&0
\end{pmatrix}
}
\cdot
W
\to
{\tiny
\begin{pmatrix}
1&0 \\
1&0 \\
0&1 \\
0&1
\end{pmatrix}
}
まず、上の変換となるような $W$ を考えてみてください。
※前回の例と似たようで違う行列です。
じつは上手くいきません
※文字だけで上手くいかない理由を説明することは僕にはできません。
では、今度は次の変換を与える $W$ を考えてみてください。
{\tiny
\begin{pmatrix}
1&0&1&0 \\
0&1&0&1 \\
1&0&0&1 \\
0&1&1&0
\end{pmatrix}
}
\cdot
W
\to
{\tiny
\begin{pmatrix}
1&0&1&0&1 \\
0&1&0&1&0 \\
1&0&0&1&0 \\
0&1&1&0&0
\end{pmatrix}
}
正確には作れないとおもいますが
例えば、こんな感じが近いかと思います。
{\tiny
\begin{pmatrix}
1&0&1&0 \\
0&1&0&1 \\
1&0&0&1 \\
0&1&1&0
\end{pmatrix}
}
\cdot
{\tiny
\begin{pmatrix}
1&0&0&0&0.4 \\
0&1&0&0&0 \\
0&0&1&0&0.4 \\
0&0&0&1&0
\end{pmatrix}
}
\to
{\tiny
\begin{pmatrix}
1&0&1&0&0.8 \\
0&1&0&1&0 \\
1&0&0&1&0.4 \\
0&1&1&0&0.4
\end{pmatrix}
}
おしいです。この惜しい状態から、0.8を1に近づけ、0.4を0に近づける役割を担うのが、sigmoid
や relu
などの関数なんだとおもいます。(要勉強)
同じことをもう一回繰り返します。
繰り返すと以下のイメージ。
{\tiny
\begin{pmatrix}
1&0&1&0 \\
0&1&0&1 \\
1&0&0&1 \\
0&1&1&0
\end{pmatrix}
}
\to
{\tiny
\begin{pmatrix}
1&0&1&0&1 \\
0&1&0&1&0 \\
1&0&0&1&0 \\
0&1&1&0&0
\end{pmatrix}
}
\to
{\tiny
\begin{pmatrix}
1&0&1&0&1&0 \\
0&1&0&1&0&1 \\
1&0&0&1&0&0 \\
0&1&1&0&0&0
\end{pmatrix}
}
\to
{\tiny
\begin{pmatrix}
1&0 \\
0&1 \\
0&0 \\
0&0
\end{pmatrix}
}
※ まあ。あくまでイメージです。
つまり
層を増やすことで、どんなトレーニングデータに対しても、一応正解に近づけることができます。
サンプル
https://gist.github.com/mochizukikotaro/e368328b10bf6b5bff4454264367be59