2016-06-30 10 views
2

他のLSTMの重みの指数移動平均をテンソルフローのLSTMにしたいとします。指数移動平均を置くので、私が今やりたい何Tensorflow:別のLSTMの重みの移動平均を持つLSTM

def test_lstm(input_ph, init_ph, scope): 
     cell = tf.nn.rnn_cell.LSTMCell(128, use_peepholes=True) 
     input_ph = tf.transpose(input_ph, [1, 0, 2]) 
     input_list = tf.unpack(input_ph) 

     with tf.variable_scope(scope) as vs: 
      outputs, states = tf.nn.rnn(cell, input_list, initial_state=init_ph) 

     theta = [v for v in tf.all_variables() if v.name.startswith(vs.name)] 

     return outputs, theta 

lstm_1, theta_1 = test_lstm(input_1, state_init_1, scope="lstm_1") 

が実際に動作しませんこれらの線(一緒に類似した何かがある:だから基本的に私はいくつかの入力プレースホルダと、いくつかの初期状態のプレースホルダを使用してこのコードを持っていますtheta_2_1がtheta_2_2に等しくなり、最終的

ema = tf.train.ExponentialMovingAverage(decay=1-self.tau, name="ema") 

with tf.variable_scope("lstm_2"): 
     maintain_averages_theta_1 = ema.apply(theta_1) 
     theta_2_1 = [ema.average(x) for x in theta_1] 

lstm_2 , theta_2_2 = test_lstm(input_2, state_init_2, scope="lstm_2" 

を(または例外をスロー:タグ重みの変数名の後ろに「絵馬」と彼らがtf.get_variableで作成されなかったため)、変数のスコープに表示されません。変数が既に存在するため)。

答えて

1

少し遅れそうですが、これが役立つことを願っています。 TF-RNNシリーズの重大な問題は、プレーンフィードフォワードまたは畳み込みNNとは異なり、RNNの変数を直接指定することができないため、EMAed varsを取​​得してネットワークに接続するという簡単な作業はできません。

本当のことを考えてみましょう(これを参照するための練習コードが添付されていますので、EMA_LSTM.pyを参照してください)。

我々はLSTMを含むネットワーク機能がある、と言うものとする。そして、あなたは必要な入力のためのtf.placeholderを宣言

def network(in_x,in_h): 
    # Input: 'in_x' is the input sequence, 'in_h' is the initial hidden cell(c,m) 
    # Output: 'hidden_outputs' is the output sequence(c-sequence), 'net' is the list of parameters used in this network function 
    cell = tf.nn.rnn_cell.BasicLSTMCell(3, state_is_tuple=True) 
    in_h = tf.nn.rnn_cell.LSTMStateTuple(in_h[0], in_h[1]) 
    hidden_outputs, last_tuple = tf.nn.dynamic_rnn(cell, in_x, dtype=tf.float32, initial_state=in_h) 
    net = [v for v in tf.trainable_variables() if tf.contrib.framework.get_name_scope() in v.name] 
    return hidden_outputs, net 

in_x = tf.placeholder("float", [None,None,6]) 
in_c = tf.placeholder("float", [None,3]) 
in_m = tf.placeholder("float", [None,3]) 
in_h = (in_c, in_m) 

最後に、私たちはセッションを実行します指定された入力でnetwork()関数を実行します:

init_cORm = np.zeros(shape=(1,3)) 
input = np.ones(shape=(1,1,6)) 

print '========================new-1(beh)==============================' 
with tf.Session() as sess:  
    with tf.variable_scope('beh', reuse=False) as beh: 
     result, net1 = network(in_x,in_h) 
     sess.run(tf.global_variables_initializer()) 
     list = sess.run([result, in_x, in_h, net1], feed_dict={ 
      in_x : input, 
      in_c : init_cORm, 
      in_m : init_cORm 
     }) 
    print 'result:', list[0] 
    print 'in_x:' , list[1] 
    print 'in_h:', list[2] 
    print 'net1:', list[3][0][0][:4] 

ここでは、 e 'net1'のExponentialMovingAverage(EMA)で指定された値を含む 'net4'と呼ばれるvar_listは、上記のセッションで最初に割り当てられた元の 'net1'と、各要素に1を加えて新たに割り当てられます。 NET1でない変数もなる場合、我々は唯一、自分の名前の変数が「ExponentialMovingAverage」を含む(宣言ジョブを実行し、「init_new_vars_op」を宣言することによって)初期化

ema = tf.train.ExponentialMovingAverage(decay=0.5) 
target_update_op = ema.apply(net1) 
init_new_vars_op = tf.initialize_variables(var_list=[v for v in tf.global_variables() if 'ExponentialMovingAverage' in v.name]) # 'initialize_variables' will be replaced with 'variables_initializer' in 2017 
sess.run(init_new_vars_op) 

len_net1 = len(net1) 
net1_ema = [[] for i in range(len_net1)] 
for i in range(len_net1): 
    sess.run(net1[i].assign(1. + net1[i])) 

sess.run(target_update_op) 

  • こと

    新たに初期化されました。

  • 'net1'の変数のすべての要素に対して 'net1'に+1が割り当てられました。 'net1'の要素が-0.5で+1になった場合、EMAの減衰率が0.5のとき 'net4'を0にします。

  • 最後に、 sess.run(target_update_op)() '関数、次いで&はEMA(NET1)はに値を実行割り当てる 'ネットワーク 'と第' NET4を」

最終的には、我々は宣言' NET4'。 'sess.run(result)'を実行すると、EMA(net1)の変数を持つものになります。

with tf.variable_scope('tare', reuse=False) as tare: 
    result, net4 = network(in_x,in_h) 
    len_net4 = len(net4) 

    target_assign = [[] for i in range(len_net4)] 
    for i in range(len_net4): 
     target_assign[i] = net4[i].assign(ema.average(net1[i])) 
     sess.run(target_assign[i].op) 
    list = sess.run([result, in_x, in_h, net4], feed_dict={ 
     in_x : input, 
     in_c : init_cORm, 
     in_m : init_cORm 
    }) 

ここには何が起こっていますか?あなたは 'network()'関数でLSTM変数を 'net4'として間接的に宣言します。次に、forループでは、を指摘しています。実際には 'net4'は 'net1'と 'net1 + 1'のEMAです。 。最後に、net4が( 'network()'を介して)何をするのか('assass(ema.average())のループを介して)どのような値をとるのかを指定して、プロセスを実行します。

「結果」を最初に宣言し、パラメータの値を2番目に指定するのはやや直感的です。しかし、それは、変数、プロセス、それらの関係を最初に設定してから値を割り当て、その後プロセスを実行することが常に論理的であるため、TFが正確に探しているものの性質です。実際の機械学習のコードのために、さらにどこへ行く

最後に、いくつかのこと:ここで

  • は、私はちょうど2番目の「NET1 + 1」で「NET1」を割り当てられました。実際には、これは「+1」です。ステップはあなたのオプティマイザが実行された後に実行されます(どこかで宣言した後)。だから、毎回あなたが 'sess.run(optimiser)'、 'sess.run(target_update_op)'とthen'sess.run(target_assign [i] .op) 'のEMAに沿ってあなたの' net4 'を更新する必要があります'net1'。 Conceretly、あなたは以下のような異なる順序でこの仕事を行うことができます。あなたには、いくつかの実際の実装スニペットを見たい場合は

ema = tf.train.ExponentialMovingAverage(decay=0.5) 
target_update_op = ema.apply(net1) 

with tf.variable_scope('tare', reuse=False) as tare: 
    result, net4 = network(in_x,in_h) 
    len_net4 = len(net4) 
    target_assign = [[] for i in range(len_net4)] 
    for i in range(len_net4): 
     target_assign[i] = net4[i].assign(ema.average(net1[i])) 

init_new_vars_op = tf.initialize_variables(var_list=[v for v in tf.global_variables() if 'ExponentialMovingAverage' in v.name]) # 'initialize_variables' will be replaced with 'variables_initializer' in 2017 
sess.run(init_new_vars_op) 

len_net1 = len(net1) 
net1_ema = [[] for i in range(len_net1)] 
for i in range(len_net1): 
    sess.run(net1[i].assign(1. + net1[i])) 
sess.run(target_update_op) 

for i in range(len_net4): 
    sess.run(target_assign[i].op) 
list = sess.run([result, in_x, in_h, net4], feed_dict={ 
    in_x : input, 
    in_c : init_cORm, 
    in_m : init_cORm 
}) 

、私はディープ強化学習の仕事のための1つを作りました。あなたが興味があるなら、私に返信してください。 Chrs。

+0

詳細な回答ありがとうございます。実際、私の修士論文の中でこれを調べていたのはちょっと遅かったです(これはDeep RLでした)。あなたの実装には間違いありません。 –

関連する問題