2016-10-29 23 views
4

私はbidirectional_rnnGRUCellを使用していますが、これはTensorflowのRNNに関する一般的な質問です。Tensorflow RNN重み行列の初期化

重み行列をどのように初期化するかを見つけることができませんでした(非表示にする、非表示にする)。それらはランダムに初期化されていますか?ゼロに?私が作成するLSTMごとに異なって初期化されていますか?

EDIT:この質問のもう一つの動機は、いくつかのLSTMを事前トレーニングし、後続モデルでその重みを使用することです。私は現在、すべての状態を保存せずにモデル全体を復元することなく、現在その方法を知りません。

ありがとうございました。

答えて

5

RNNの重み行列を初期化するにはどうすればよいですか?

私は人々がRNNの重み行列に対してランダムな正規初期化を使用していると信じています。 example in TensorFlow GitHub Repoをチェックしてください。ノートブックは少し長いので、彼らはtf.truncated_normalを使って重みを初期化し、tf.zerosを使ってバイアスを初期化する単純なLSTMモデルを持っています(前にバイアスを初期化するためにtf.onesを使ってみましたが動作します)。私は標準偏差があなた自身を調整できる超パラメータであると信じています。ときどきウェイトの初期化が勾配フローにとって重要です。私が知る限り、LSTM自体はグラニュラの消滅問題(グラジエントクリッピングはグラデーションの爆発問題を助けるためのものです)を扱うように設計されていますが、おそらくスーパーの設定に注意する必要はありませんか?LSTMのstd_dev?私はConvolution Neural Networkの文脈でXavier初期化(TF API doc for Xavier initializer)を推奨する論文を読んだ。人々がRNNでそれを使用しているかどうかは分かりませんが、RNNで役立つかどうかを確認したい場合はRNNでそれらを試すこともできます。

@アレンの答えとあなたのフォローアップの質問をコメントに残しておいてください。

可変スコープで初期化を制御するにはどうすればよいですか?

例としてリンクされているTensorFlow GitHub python notebookの単純なLSTMモデルを使用します。具体的に enter image description here 、私は次のように変数のスコープのコントロールを使用して上記画像内のコードのLSTMの一部を再因数分解、私がコードすることができる何かをしたい場合は...

import tensorflow as tf 
def initialize_LSTMcell(vocabulary_size, num_nodes, initializer): 
    '''initialize LSTMcell weights and biases, set variables to reuse mode''' 
    gates = ['input_gate', 'forget_gate', 'memory_cell', 'output_gate'] 
    with tf.variable_scope('LSTMcell') as scope: 
     for gate in gates: 
      with tf.variable_scope(gate) as gate_scope: 
       wx = tf.get_variable("wx", [vocabulary_size, num_nodes], initializer) 
       wt = tf.get_variable("wt", [num_nodes, num_nodes], initializer) 
       bi = tf.get_variable("bi", [1, num_nodes, tf.constant_initializer(0.0)]) 
       gate_scope.reuse_variables() #this line can probably be omitted, b.z. by setting 'LSTMcell' scope variables to 'reuse' as the next line, it'll turn on the reuse mode for all its child scope variables 
     scope.reuse_variables() 

def get_scope_variables(scope_name, variable_names): 
    '''a helper function to fetch variable based on scope_name and variable_name''' 
    vars = {} 
    with tf.variable_scope(scope_name, reuse=True): 
     for var_name in variable_names 
      var = tf.get_variable(var_name) 
      vars[var_name] = var 
    return vars 

def LSTMcell(i, o, state): 
    '''a function for performing LSTMcell computation''' 
    gates = ['input_gate', 'forget_gate', 'memory_cell', 'output_gate'] 
    var_names = ['wx', 'wt', 'bi'] 
    gate_comp = {} 
    with tf.variable_scope('LSTMcell', reuse=True): 
     for gate in gates: 
      vars = get_scope_variables(gate, var_names) 
      gate_comp[gate] = tf.matmul(i, vars['wx']) + tf.matmul(o, vars['wt']) + vars['bi'] 
    state = tf.sigmoid(gate_comp['forget_gate']) * state + tf.sigmoid(gate_comp['input_gate']) * tf.tanh(gate_comp['memory_cell']) 
    output = tf.sigmoid(gate_comp['output_gate']) * tf.tanh(state) 
    return output, state 

再因数分解のコードの使用refactorizedコードは以下に簡単に見えますが、スコープ変数コントロールを使用すると、スコープのカプセル化を確保し、(少なくとも私の意見では)柔軟な変数の制御を可能にするかもしれないが、次のようなもの...

initialize_LSTMcell(volcabulary_size, num_nodes, tf.truncated_normal_initializer(mean=-0.1, stddev=.01)) 
#...Doing some computation... 
LSTMcell(input_tensor, output_tensor, state) 

だろう。

一部のLSTMを事前トレーニングし、後続モデルでその重みを使用します。すべての状態を保存せずに、モデル全体を復元する方法。

凍結された 'wx'、 'wt'、 'bi'を使用する場合は、事前に訓練されたモデルをフリーズしてロードすると仮定すると、親スコープ名と変数名を見つけてフェッチできます変数はget_scope_variablesで同様の構造を使用しています。

with tf.variable_scope(scope_name, reuse=True): 
    var = tf.get_variable(var_name) 

ここにはunderstanding variable scope and sharing variablesへのリンクがあります。これが参考になることを願っています。

4

RNNモデルはget_variableで変数を作成し、variable_scopeとpassing a default initializer to itでこれらの変数を作成するコードをラップすることで初期化を制御できます。 RNNが明示的に指定しない限り(looking at the code)、uniform_unit_scaling_initializer is used

また、モデルの重みを共有するには、2番目のモデルを宣言し、その変数_スコープにreuse = Trueを渡します。名前空間が一致する限り、新しいモデルは最初のモデルと同じ変数を取得します。

+0

スコープ内のすべての変数に対して1つの初期化子を使用することはできますか。独自の次元で各重み行列の初期化子を与えてはいけませんか? – yoki

+1

get_variableは、変数(およびそのdtype)の形状を指定し、初期化子に渡されます。仕様は切り離されていますが、イニシャライザは形状情報に依存することがあります([uniform_unit_scaling_initializer]など)(https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/init_ops.py#L230 ))。 –

0

特定のイニシャライザですべてのカーネルウェイトを初期化する簡単な方法は、イニシャライザをtf.variable_scope()のままにすることです。たとえば、

with tf.variable_scope('rnn', initializer=tf.variance_scaling_initializer()): 
    basic_cell= tf.contrib.rnn.BasicRNNCell(num_units=n_neurons) 
    outputs, state= tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32) 
関連する問題