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モデルを使用します。具体的に 、私は次のように変数のスコープのコントロールを使用して上記画像内のコードの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へのリンクがあります。これが参考になることを願っています。
スコープ内のすべての変数に対して1つの初期化子を使用することはできますか。独自の次元で各重み行列の初期化子を与えてはいけませんか? – yoki
get_variableは、変数(およびそのdtype)の形状を指定し、初期化子に渡されます。仕様は切り離されていますが、イニシャライザは形状情報に依存することがあります([uniform_unit_scaling_initializer]など)(https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/init_ops.py#L230 ))。 –