TensorFlowで数列の平均を求めてみた

Tensorflowが機械学習ライブラリという誤解がまかり通っているので，理解を深めるために平均を求めるコードを書いてみた．

- 0から100までの一様乱数を100個生成．とうぜん平均は50．
- 学習係数をいつくか変更

# Gradient decent

```python:

import matplotlib.pylab as plt
%matplotlib inline
import numpy as np
import tensorflow as tf

x_train = np.random.randint(0,100, size=100)

n_itr = 100

m = tf.Variable([30.0], tf.float32) # 推定する変数
x = tf.placeholder(tf.float32)      # 与えるデータ

loss = tf.reduce_sum(tf.square(x - m)) # 二乗誤差和

for lr in [0.009, 0.001, 0.0001]:

    optimizer = tf.train.GradientDescentOptimizer(lr) # ベタな勾配法
    train = optimizer.minimize(loss)

    init = tf.global_variables_initializer()
    sess = tf.Session()
    sess.run(init)

    est = []
    for i in range(n_itr):
        _, est_m = sess.run([train, m], {x:x_train})
        est.append(est_m)

    est = np.array(est)
    plt.plot(est.reshape(n_itr), label="lr={}".format(lr))

plt.title("batch gradient decent")
plt.legend()
plt.show();
```

真の平均に収束しているけど

- 学習係数が大きいと，とうぜん振動する
 - 0.01よりも大きいと発散
- 学習係数が小さいと，収束も遅い

![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/44835/6ffbf509-2038-802c-658c-583b8065b385.png)

# RMS Prop

optimizerと
学習率の範囲を変えただけ．

```python:
for lr in [5, 1, 0.1, 0.01]:

    optimizer = tf.train.RMSPropOptimizer(lr)
    train = optimizer.minimize(loss)

    init = tf.global_variables_initializer()
    sess = tf.Session()
    sess.run(init)

    est = []
    for i in range(n_itr):
        _, est_m = sess.run([train, m], {x:x_train})
        est.append(est_m)

    est = np.array(est)
    plt.plot(est.reshape(n_itr), label="lr={}".format(lr))

plt.title("batch RMS Prop")
plt.legend()
plt.show();
```

![Unknown-1.png](https://qiita-image-store.s3.amazonaws.com/0/44835/0f6f76b2-2ccd-34ee-1712-dd041dfa6f60.png)

- 学習率が大きすぎると，収束した後に振動する．
- gradient decentに比べて学習率がかなり大きい


# Adam

```python:
for lr in [5, 1, 0.1, 0.01]:

    optimizer = tf.train.AdamOptimizer(lr)
    train = optimizer.minimize(loss)

    init = tf.global_variables_initializer()
    sess = tf.Session()
    sess.run(init)

    est = []
    for i in range(n_itr):
        _, est_m = sess.run([train, m], {x:x_train})
        est.append(est_m)

    est = np.array(est)
    plt.plot(est.reshape(n_itr), label="lr={}".format(lr))

plt.title("batch Adam")
plt.legend()
plt.show();
```

![Unknown-2.png](https://qiita-image-store.s3.amazonaws.com/0/44835/30eeb6a7-959a-42fe-de12-004e78cde941.png)

- 振動が緩やか．過渡現象の振動グラフを思い出す．
- 学習率が大きいとオーバーシュートする．



# AdaGrad

```python:
for lr in [20, 10, 5, 1, 0.1, 0.01]:

    optimizer = tf.train.AdagradOptimizer(lr)
    train = optimizer.minimize(loss)

    init = tf.global_variables_initializer()
    sess = tf.Session()
    sess.run(init)

    est = []
    for i in range(n_itr):
        _, est_m = sess.run([train, m], {x:x_train})
        est.append(est_m)

    est = np.array(est)
    plt.plot(est.reshape(n_itr), label="lr={}".format(lr))

plt.title("batch AdaGrad")
plt.legend()
plt.show();
```

![Unknown-3.png](https://qiita-image-store.s3.amazonaws.com/0/44835/ef24889d-acfb-d192-7be4-bf58ad6ba308.png)

- 優秀．学習率を大きくすると良い．大きくても発散せず，急速に収束する．（100を試してみると面白い）



# AdaDelta

```python:
for lr in [20000, 10000, 1000, 100, 10]:

    optimizer = tf.train.AdadeltaOptimizer(lr)
    train = optimizer.minimize(loss)

    init = tf.global_variables_initializer()
    sess = tf.Session()
    sess.run(init)

    est = []
    for i in range(n_itr):
        _, est_m = sess.run([train, m], {x:x_train})
        est.append(est_m)

    est = np.array(est)
    plt.plot(est.reshape(n_itr), label="lr={}".format(lr))

plt.title("batch AdaDelta")
plt.legend()
plt.show();
```

![Unknown-4.png](https://qiita-image-store.s3.amazonaws.com/0/44835/d271fda3-b450-b4c9-0816-8e3650af15a7.png)


- 振る舞いはAdaGradとほとんど同じ．
- 学習率がかなり大きい．