#tensorflow
#tensorflow
Вопрос:
Я пытаюсь создать генеративную модель RNN в tensorflow. Что меня раздражает, так это то, что с новым переключением на state_is_tupe значение true по умолчанию в библиотеке RNN, мне трудно найти лучший способ сохранения состояния между пакетами. Я знаю, что могу изменить его обратно на значение False, но я не хочу этого делать, поскольку оно устарело. Когда я закончу обучение, мне нужно иметь возможность сохранять скрытые состояния между вызовами session.run, поскольку я буду генерировать последовательности по одному образцу за раз. Я понял, что могу вернуть состояние rnn следующим образом.
rnn = tf.nn.rnn_cell.MultiRNNCell(cells)
zero_state = rnn.zero_state(batch_size, tf.float32)
output, final_state = tf.nn.dynamic_rnn(rnn, self.input_sound, initial_state = zero_state)
sess = tf.Session()
sess.run(tf.initialize_all_variables())
state_output = sess.run(final_state, feed_dict = {self.input_sound: np.zeros((64, 32, 512))})
Это было бы здорово, но проблема возникает, когда я хочу передать state_output обратно в модель. Поскольку заполнителем может быть только тензорный объект, я не могу передать его обратно в тупель state_output .
Я ищу очень общее решение. Rnn может быть MultiRNNCell или одной LSTMCell или любой другой мыслимой комбинацией.
Ответ №1:
Я думаю, я понял это. Я использовал следующий код, чтобы сгладить кортежи состояний в один одномерный тензор. Я могу измельчить его, когда передам его обратно в модель в соответствии со спецификацией размера ячейки rnn.
def flatten_state_tupel(x):
result = []
for x_ in x:
if isinstance(x_, tf.Tensor) or not hasattr(x_, '__iter__'):
result.append(x_)
else:
result.extend(flatten_state_tupel(x_))
return result
def pack_state_tupel(state):
return tf.concat(0, [tf.reshape(s, (-1,)) for s in flatten_state_tupel(state)])
def unpack_state_tupel(state, size):
state = tf.reshape(state, (-1, tf.reduce_sum(flatten_state_tupel(size))))
def _make_state_tupel(sz, i):
if hasattr(sz, '__iter__'):
result = []
for s in sz:
base_index, y = _make_state_tupel(s, i)
result.append(y)
return base_index, tf.nn.rnn_cell.LSTMStateTuple(*result) if isinstance(sz, tf.nn.rnn_cell.LSTMStateTuple) else tuple(result)
else:
return i sz, state[..., i : i sz]
return _make_state_tupel(size, 0)[-1]
Я использую функции следующим образом.
rnn = tf.nn.rnn_cell.MultiRNNCell(cells)
zero_state = pack_state_tupel(rnn.zero_state(batch_size, tf.float32))
self.initial_state = tf.placeholder_with_default(zero_state, None)
output, final_state = tf.nn.dynamic_rnn(rnn, self.input_sound, initial_state = unpack_state_tupel(self.initial_state, rnn.state_size))
packed_state = pack_state_tupel(final_state)
sess = tf.Session()
sess.run(tf.initialize_all_variables())
state_output = sess.run(packed_state, feed_dict = {self.input_sound: np.zeros((64, 32, 512))})
print(state_output.shape)
state_output = sess.run(packed_state, feed_dict = {self.input_sound: np.zeros((64, 32, 512)), self.initial_state: np.zeros(state_output.shape[0])})
print(state_output)
Таким образом, состояние будет обнуляться, если я ничего не передам (что будет иметь место во время обучения), однако я могу сохранять и передавать состояние между пакетами во время генерации.