Инициализация весовых матриц Tensorflow RNN
Я использую bidirectional_rnn
с GRUCell
но это общий вопрос относительно RNN в Tensorflow.
Я не мог найти, как инициализировать весовые матрицы (вход в скрытый, скрытый в скрытый). Инициализируются ли они случайным образом? в нули? инициализируются ли они по-разному для каждого LSTM, который я создаю?
EDIT: другой мотивацией для этого вопроса является предварительная подготовка некоторых LSTMs и использование их весов в последующей модели. В настоящее время я не знаю, как это сделать в настоящее время без сохранения всех состояний и восстановления всей модели.
спасибо.
3 ответов
как инициализировать весовые матрицы для RNN?
Я считаю, что люди используют случайную нормальную инициализацию для весовых матриц для RNN. Проверьте пример в TensorFlow GitHub Repo. Поскольку ноутбук немного длинный, у них есть простая модель LSTM, где они используют tf.truncated_normal
для инициализации Весов и tf.zeros
для инициализации предубеждений (хотя я попытался использовать tf.ones
чтобы инициализировать предубеждения раньше, похоже, также работает). Я считаю, что стандарт отклонение-это hyperparameter вы могли настроиться. Иногда инициализация Весов важна для градиентного потока. Хотя, насколько я знаю, сама LSTM предназначена для обработки проблемы исчезновения градиента (и отсечение градиента для помощи проблеме взрыва градиента), поэтому, возможно, вам не нужно быть супер осторожно с установкой std_dev
в LSTM? Я читал статьи, рекомендующие инициализацию Xavier (TF API doc для инициализатора Xavier) в свертке Контекст нейронной сети. Я не знаю, используют ли люди это в RNN, но я думаю, вы даже можете попробовать их в RNN, если хотите увидеть, помогает ли это.
теперь, чтобы следить за ответом @Allen и вашим последующим вопросом, оставленным в комментариях.
как управлять инициализацией с переменной областью?
использование простой модели LSTM в TensorFlow GitHub python ноутбук , С которым я связался в качестве примера. В частности, если я хочу повторно факторизовать часть 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
использование ре-факторизуемая код будет что-то вроде следующего...
initialize_LSTMcell(volcabulary_size, num_nodes, tf.truncated_normal_initializer(mean=-0.1, stddev=.01))
#...Doing some computation...
LSTMcell(input_tensor, output_tensor, state)
даже если рефакторизованный код может выглядеть менее простым, но использование управления переменной области обеспечивает инкапсуляцию области и позволяет гибким переменным элементам управления (на мой взгляд, наименьший.)
в предварительной подготовке некоторых LSTMs и использовании их весов в последующей модели. Как это сделать без сохранения и восстановления всей модели.
предполагая, что у вас есть предварительно обученная модель, замороженная и загруженная, если вы хотите использовать их замороженные "wx", " wt " и "bi", вы можете просто найти их имена родительских областей и имена переменных, а затем получить переменные, используя аналогичную структуру в get_scope_variables
func.
with tf.variable_scope(scope_name, reuse=True):
var = tf.get_variable(var_name)
вот ссылка к понимание области переменных и переменных обмена. Надеюсь, это поможет.
модели RNN создадут свои переменные с get_variable, и вы можете управлять инициализацией, обертывая код, который создает эти переменные с variable_scope и передача ему инициализатора по умолчанию. Если только RNN не указывает один явно (глядя на код, но это не так), используется uniform_unit_scaling_initializer.
вы также должны иметь возможность делиться весами модели, объявляя вторую модель и передавая reuse=True для его variable_scope. Пока пространства имен совпадают, новая модель получит те же переменные, что и первая модель.
простой способ инициализации всех Весов ядра с определенным инициализатором-оставить инициализатор в 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)