2017-03-07 7 views
0

whileループがテンソルフローでどのように機能するかを理解しようとしています。特に私はwhileループで更新する変数x sayを持っていますが、xに依存するいくつかの値がありますが、whileループを実行すると、xが変化したときに値が更新されないようです。whileループの依存関係を再評価する

私は私が何を意味するか説明するかもしれない、単純な勾配まともなオプティマイザを実装しようとした次のコード:1.0は私にとって、この結果得られtensorflow

import tensorflow as tf 

x = tf.Variable(initial_value=4, dtype=tf.float32, trainable=False) 
y = tf.multiply(x,x) 

grad = tf.gradients(y, x) 

def update_g(): 
    with tf.control_dependencies(grad): 
     return tf.identity(grad[0]) 

iterations = tf.placeholder(tf.int32) 
i = tf.constant(0, dtype=tf.int32) 
g = tf.Variable(initial_value=grad[0], dtype=tf.float32, trainable=False) 
c = lambda i_loop, x_loop, g_loop: i_loop < iterations 
b = lambda i_loop, x_loop, g_loop: [i_loop+1, tf.assign(x, x_loop - 10*g_loop), update_g()] 
l = tf.while_loop(c, b, [i, x, g], back_prop=False, parallel_iterations=1) 

with tf.Session() as sess: 
    sess.run(tf.global_variables_initializer()) 
    res_g = sess.run(grad) 
    res_l = sess.run(l, feed_dict={iterations: 10}) 
    res_x = sess.run(x) 


print(res_g) 
print(res_l) 
print(res_x) 

でこれを実行:

[8.0] 
[10, -796.0, 8.0] 
-796.0 

をし、問題は、xが変化すると勾配の値が更新されないということです。

私は上記のコードにさまざまなバリエーションを試しましたが、動作するバージョンが見つからないようです。基本的に私の質問は、上記のことができるかどうか、または私はアプローチを再考する必要があるかどうかです。

(たぶん私は勾配まともなオプティマイザを書くことに興味がないことを追加する必要があり、私はちょうどで動作するようにシンプルで理解しやすいものを持って、これを構築しました。)

答えて

1

ループしている間用のループ変数としてtf.Variableオブジェクトを持ちますサポートされておらず、不思議で非決定的なやり方で行動します。 tf.assignと友だちを使用して、tf.Variableの値を更新してください。

+0

私はループ内で 'g'の使用を参照していると思います。なぜなら、私は' x'に対して 'tf.assign'を使用しているか、' x'を非可変ヘルプとして使用しているからでしょうか? 私は前に 'g'を使わずに、単に' tf.assign(x、x_loop - 10 * grad [0]) 'を実行しました。また、 'update_g'関数を下に移動し、戻り値を' return tf.assign(g、grad [0]) 'に変更しようとしました。どちらの場合も同じ結果が得られます。 –

+0

whileループの中でxにtf.assignを使用しても、ループ変数としてxがあります。これにより、実行時に不思議な不一致が発生します。変数としてxを持たないこと、またはループ変数としてxを持たないことをお勧めします。 –

1

他の回答の助けを借りて、私はこの作業を行うことができました。二答えとしてここに完全なコードを投稿する:

[8.0] 
[100000, 5.1315068e-38] 
4.0 

動作しているようだ:

x = tf.constant(4, dtype=tf.float32) 
y = tf.multiply(x,x) 

grad = tf.gradients(y, x) 

def loop_grad(x_loop): 
    y2 = tf.multiply(x_loop, x_loop) 
    return tf.gradients(y2, x_loop)[0] 

iterations = tf.placeholder(tf.int32) 
i = tf.constant(0, dtype=tf.int32) 
c = lambda i_loop, x_loop: i_loop < iterations 
b = lambda i_loop, x_loop: [i_loop+1, x_loop - 0.1*loop_grad(x_loop)] 
l = tf.while_loop(c, b, [i, x], back_prop=False, parallel_iterations=1) 

gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.05) 
with tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) as sess: 
    sess.run(tf.global_variables_initializer()) 
    res_g = sess.run(grad) 
    res_l = sess.run(l, feed_dict={iterations: 100000}) 
    res_x = sess.run(x) 


print(res_g) 
print(res_l) 
print(res_x) 

は、問題のコードからの学習率を変更し、反復回数を増やすと、出力を提供します。それは高い反復回数でもかなり速く実行されるので、whileループの各反復でグラフを更新することで実際に恐ろしいことが起こるようには見えません。おそらく恐怖がこの選択をしなかったのでしょう最初からアプローチ。

関連する問題