TensorFlow MNIST のコード解説【隠れ層のある場合】

前回の記事([TensorFlow MNIST のコード解説【初心者向け】](https://qiita.com/yneo918/items/7846c720428ecee30536))に続き、次は隠れ層を含むものを解説していく。自分自身大学生の学習者であるため、似たような人向けである。
前回の記事で解説済みのものはそちらを参照のこと。
今回は[落ちこぼれないためのTensorFlow Tutorialコード](https://qiita.com/TomokIshii/items/92a266b805d7eee02b1d)を引用させてもらった。
以下では、

```
# 定義
image_size = 28*28
output_num = 10
learning_rate = 0.001
loop_num = 20001
loop_rate = (loop_num-1)/10
batch_size = 100
H = 625

# Variables
# x=入力値
# y_=正解
x = tf.placeholder("float", [None, image_size])
y_ = tf.placeholder("float", [None, 10])
w_h = tf.Variable(tf.random_normal([image_size, H], mean=0.0, stddev=0.05))
w_o = tf.Variable(tf.random_normal([H, output_num], mean=0.0, stddev=0.05))
b_h = tf.Variable(tf.zeros([H]))
b_o = tf.Variable(tf.zeros([output_num]))
```
と宣言している。

# def model()
```
def 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)

    return pyx
```
pythonでの関数宣言である。関数modelはシグモイド関数h、ソフトマックス関数pyxで構成されている。
前回の記事でソフトマックス関数を説明したため、ここではシグモイド関数を説明する。
シグモイド関数とは、
$$sigmoid(x)=\frac{1}{1+e^{-x}}$$
で表される関数である。こちらは、
$$sigmoid(0)=\frac{1}{2}$$
$$\lim_{x \to \infty} sigmoid(x)=1$$
$$\lim_{x \to -\infty} sigmoid(x)=0$$
$$sigmoid(x) + sigmoid(-x)=1$$
$$sigmoid(x)は単調増加$$
という性質がある。

# tf.nn.l2_loss()
```
L2_sqr = tf.nn.l2_loss(w_h) + tf.nn.l2_loss(w_o)
```
l2_lossとは、2乗誤差を計算するものである。
2乗誤差とは、
$$\frac{\sum w_i^2}{2}$$
である。
この部分では、シグモイド関数とソフトマックス関数の重みの2乗誤差の和をL2_sqrとしている。
# train_step
前回とは違い、今回は、

```
lambda_2 = 0.01
loss = cross_entropy + lambda_2 * L2_sqr
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
```

となっている。
ここで、lossは、前回用いたクロスエントロピーと、2乗誤差*0.01である。これにより、2乗誤差も最小化の対象となっている。
2乗誤差を小さくすることで、なめらかなデータとなる。

# 今回扱ったコード

```python:mlp_tutorial.py
import tensorflow as tf

# Import data
import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# 定義
image_size = 28*28
output_num = 10
learning_rate = 0.001
loop_num = 20001
loop_rate = (loop_num-1)/10
batch_size = 100
H = 625

# Variables
# x=入力値
# y_=正解
x = tf.placeholder("float", [None, image_size])
y_ = tf.placeholder("float", [None, 10])

#r andomval で正規分布、標準偏差0.05で小さい値を発生
w_h = tf.Variable(tf.random_normal([image_size, H], mean=0.0, stddev=0.05))
w_o = tf.Variable(tf.random_normal([H, output_num], mean=0.0, stddev=0.05))
b_h = tf.Variable(tf.zeros([H]))
b_o = tf.Variable(tf.zeros([output_num]))

# シグモイド関数とソフトマックス関数
#　tf.matmul = 行列の積
def 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)

    return pyx
#y_hypo=予測値
y_hypo = model(x, w_h, b_h, w_o, b_o)

# クロスエントロピー計算
#　tf.reduce_sum=Σ
cross_entropy = -tf.reduce_sum(y_*tf.log(y_hypo))

# 正則化の項計算 ２乗ノルム=tf.nn.l2_loss
L2_sqr = tf.nn.l2_loss(w_h) + tf.nn.l2_loss(w_o)
lambda_2 = 0.01

# tf.train.GradientDescentOptimizer=勾配降下法
loss = cross_entropy + lambda_2 * L2_sqr
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
correct_prediction = tf.equal(tf.argmax(y_hypo,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

# Train
init = tf.initialize_all_variables()

with tf.Session() as sess:
    sess.run(init)
    print('Training...')
    for i in range(loop_num):
        batch_xs, batch_ys = mnist.train.next_batch(batch_size)
        train_step.run({x: batch_xs, y_: batch_ys})
        if i % loop_rate == 0:
            train_accuracy = accuracy.eval({x: batch_xs, y_: batch_ys})
            print('  step, accurary = %6d: %6.3f' % (i, train_accuracy))
    print('accuracy = ', accuracy.eval({x: mnist.test.images, y_: mnist.test.labels}))
```