チュートリアルの1次関数の予測をネタとしていろいろ試してみます。
環境
python 3.5.2
tensorflow 0.12.1
下記の1次関数を予測します
y = 0.5x + 10
予測する式が直線(y = ax + b)とわかっている上で
最終的にこの式の傾きaと切片bを求ます。
ソースコード(全文)
import tensorflow as tf
import numpy as np
## 学習データ作成(x座標をランダムに作成(0.0〜1.0を100個)
x_data = np.random.rand(100).astype(np.float32)
# y座標を生成 (y = 0.5x + 10)
y_data = 0.5 * x_data + 10
## モデルを作成(y_data = W * x_data + b となる W と b の適正値を見つけます。
W = tf.Variable(tf.zeros([1]))
b = tf.Variable(tf.zeros([1]))
y = W * x_data + b
## 損失関数を作成(最小二乗法を使用
loss = tf.reduce_mean(tf.square(y - y_data))
## 最適化アルゴリズムを指定(勾配降下法で損失関数を最小化
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
## パラメータを初期化(Variableを使用する場合必要らしい
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
## 学習する
for step in range(200):
sess.run(train)
if step % 20 == 0:
print(step, sess.run(W), sess.run(b))
Wが重み、bがバイアスです。
また、重みを傾きaに、バイアスを切片bに対応させています。
結果
0 [ 5.35188961] [ 10.25884247]
20 [ 1.46414196] [ 9.46684837]
40 [ 0.7577793] [ 9.85745335]
60 [ 0.56892151] [ 9.96188736]
80 [ 0.51842672] [ 9.98980999]
100 [ 0.50492722] [ 9.99727535]
120 [ 0.50131762] [ 9.99927139]
140 [ 0.50035214] [ 9.99980545]
160 [ 0.50009394] [ 9.99994755]
180 [ 0.50002551] [ 9.99998569]
トレーニングを重ねることで正解に近づいていくのがわかります。
学習データを変えてみる
下記は(0.0〜1.0)の間でランダムな数値を作成します。
x_data = np.random.rand(100).astype(np.float32)
これをもう少し大きい値に変えてみます。
下記は(0〜100)の間でランダムな数値を作成します。
x_data = np.random.randint(0, 100, 100).astype(np.float32)
実行してみます。
0 [ 2490.00512695] [ 37.44499969]
20 [ nan] [ nan]
40 [ nan] [ nan]
60 [ nan] [ nan]
80 [ nan] [ nan]
100 [ nan] [ nan]
120 [ nan] [ nan]
140 [ nan] [ nan]
160 [ nan] [ nan]
180 [ nan] [ nan]
壊れました。
値が発散してしまうと「Not A Number」になるようです。
学習データの値を大きくしたことで損失関数の微分値が大きくなったのだとおもわれます。
学習率を下げてみます。
optimizer = tf.train.GradientDescentOptimizer(0.0001)
いろいろ試しましたがあまりうまく行きません。
学習回数を増やしたりもしましたがこの結果です。
19900 [ 0.54181725] [ 7.06084156]
19920 [ 0.54176587] [ 7.06445599]
19940 [ 0.54171455] [ 7.06806087]
19960 [ 0.54166323] [ 7.07166576]
19980 [ 0.54161209] [ 7.07526255]
最適化アルゴリズムを変えてみます。
イケているらしいAdamで最適化してみます。
optimizer = tf.train.AdamOptimizer(0.5)
0 [ 0.5] [ 0.5]
20 [ 0.4940598] [ 1.87242627]
40 [ 0.65283048] [ 3.86862636]
60 [ 0.57364327] [ 5.61097527]
80 [ 0.54375488] [ 7.12018442]
100 [ 0.52782118] [ 8.26023579]
120 [ 0.51555306] [ 9.03210545]
140 [ 0.50718832] [ 9.50679207]
160 [ 0.5034216] [ 9.77309036]
180 [ 0.50139517] [ 9.90730953]
うまく予測できました。
学習データを(0.0〜1.0)に戻してみます。
x_data = np.random.rand(100).astype(np.float32)
0 [ 0.49999994] [ 0.5]
20 [ 7.49428892] [ 8.05118752]
40 [ 4.68005848] [ 7.44039011]
60 [ 3.54744887] [ 8.34731293]
80 [ 2.41113639] [ 8.924716]
100 [ 1.63474452] [ 9.39722347]
120 [ 1.08201456] [ 9.66472244]
140 [ 0.78602862] [ 9.84842777]
160 [ 0.61798155] [ 9.93378735]
180 [ 0.54255277] [ 9.97624016]
いい感じです。
まとめ
・学習データの大きさと学習率の関係は重要っぽい
・最適化アルゴリズムにAdamを使うことで様々な学習データに適応できた