2017-11-09 7 views
0

TensorFlowでデータセットを訓練する回帰モデルを構築しようとしました。 W1 * x^2 + W2 * x + bのとき、それはナノを示す。 W2 * x + bのとき、数値を出力することができます。なぜW1 = 0を見つけることができないのですか?モデルビルドロジックに何か間違いはありますか?GradientDescentOptimizerでゼロの重みを見つけることができません

import tensorflow as tf 
import csv 
import re 
import datetime 
import numpy 
import matplotlib.pyplot as plt 

# Parameters 
learning_rate = 0.01 
training_epochs = 2000 

# Training Data 
data_X = [ 0., 2., 5., 6., 7., 8., 9., 12., 13., 14.] 
data_Y = [ 2568.300049, 2540.100098, 2552.399902, 2583.899902, 2607.100098, 
    2603.300049, 2561.699951, 2614.899902, 2590.800049, 2578.199951] 
train_X = numpy.asarray(data_X) 
train_Y = numpy.asarray(data_Y) 
n_samples = train_X.shape[0] 

# Model parameters 
rng = numpy.random 
W1 = tf.Variable([rng.randn()], dtype=tf.float32, name="weight1") 
# OK when W1 = tf.constant(0.) 
W2 = tf.Variable([rng.randn()], dtype=tf.float32, name="weight2") 
b = tf.Variable([rng.randn()], dtype=tf.float32, name="bias") 
# Model input and output 
x = tf.placeholder(tf.float32) 
y = tf.placeholder(tf.float32) 
linear_model = W1*tf.square(x) + W2*x + b 

# loss 
loss = tf.reduce_sum(tf.square(linear_model - y))/(2*n_samples) 
# optimizer 
optimizer = tf.train.GradientDescentOptimizer(learning_rate) 
train = optimizer.minimize(loss) 

# training loop 
init = tf.global_variables_initializer() 
# Start training 
with tf.Session() as sess: 
    sess.run(init) # reset values to wrong 
    for i in range(training_epochs): 
     sess.run(train, {x: train_X, y: train_Y}) 
    # evaluate training accuracy 
    curr_W1, curr_W2, curr_b, curr_loss = sess.run([W1, W2, b, loss], {x: train_X, y: train_Y}) 
    print("W1: %s W2: %s b: %s loss: %s"%(curr_W1, curr_W2, curr_b, curr_loss)) 

    # Graphic display 
    plt.plot(train_X, train_Y, 'ro', label='Original data') 
    plt.plot(train_X, sess.run(W1) * numpy.square(train_X) + sess.run(W2) * train_X + sess.run(b), label='Fitted line') 
    plt.legend() 
    plt.show() 

答えて

1

短い回答:学習率が大きすぎます。より小さなもの(〜0.0001)を使用し、より多くのエポック(〜2000000)を使用します。

長い答え:W1はNaNです。なぜなら、トレーニング中に数値の問題が発生してNaNになるまで、その大きさが大きくなったからです。 sess.run()に渡すフェッチリストにW1を追加すると、それを見ることができます。

さらに、記号が変化し続けていることがわかります。これはオーバーシュートの兆候です。実際に、エラーlinear_model - yをフェッチリストに追加すると、その記号も変更され続けます。これはあなたの学習率が大きすぎる場合に起こります。

W1が0に固定されている場合:異なる学習レートで遊んで(よりエポックで補償)した後、私は次のように得

W1:0.0 W2:4.70993948] B:[2539.71435547]損失:237.369 これが私たちのベースラインになります。

learning_rate = 0.001:
まだNaNです。

learning_rate = 0.0001
training_epochs = 200000
W1:-2.63166738] W2:50.53411484] B:[2375.20996094]損失:2317.36

learning_rate = 0.0001
training_epochs = 2000000
W1:[ -0.3543286] W2:[8.49937725] b:[2541.46655273]損失:189.766

損失がベースラインに匹敵するので、最後の方が望ましいかもしれません。しかし、それを試して、最良の値を見つける必要があります。

+0

ご返信ありがとうございます。ソリューションは機能しますが、実行には時間がかかります。 –

1

ヨエルゼルデスが正しいです。しかし、このような単純な問題は、2000000のトレーニングステップを必要とすべきではありません。二次モデルが明らかに線形データに適していないため、最良の解は大きなバイアス値を必要とするため、bへの変更の影響が矮小であるため、学習に長い時間がかかります。 W1への変更の影響によって。

これに対処する良い方法は、データを再スケーリングすることです。あなたがライン

train_X = (train_X - numpy.mean(train_X))/(numpy.amax(train_X) - numpy.amin(train_X)) 
train_Y = (train_Y - numpy.mean(train_Y))/(numpy.amax(train_Y) - numpy.amin(train_Y))` 

が含まれている場合は、あなたのデータは、0の平均と1の範囲を持つことになり、モデルのいずれかを訓練する方がはるかに簡単になります。訓練を受けたモデルを新しいデータポイントでテストする場合は、同じ量だけスケールを調整する必要があります。

+0

ご返信ありがとうございます。あなたのソリューションは速く動くことができます。質問:Xは時間ベースの系列なので、その後の値は増加します。 Yは、訓練データよりも大きな値を持つと想定されます(必ずしもそうとは限りません)。スケーリングをどのように調整できますか? –

+0

あなたが何を求めているのか分かっていれば、何もする必要はありません。あなたのモデルは、将来のデータに役立つパラメータを学習しています。トレーニングデータはほとんどありませんので、将来のデータではモデルの精度はあまり高くありません。 – Stephen

関連する問題