Подача выходных данных из тензорного потока dynamic_rnn на последующий слой - PullRequest
0 голосов
/ 13 мая 2018

Я начал использовать RNN в тензорном потоке и получил общий принцип, но некоторые аспекты реализации не совсем ясны.

Что я понимаю: допустим, я тренируюсь в последовательности-последовательность сети, в которой размер входных данных совпадает с размером выходных данных (это может быть что-то вроде предсказания следующего символа в фрагменте текста на каждом временном шаге).Мой рекуррентный слой использует ячейку LSTM, и я хочу, чтобы впоследствии полностью подключенный слой добавил немного глубины в прогноз.

В статическом RNN, согласно соглашению TF, вы должны разложить свои входные данные по временному измерению и передать их в метод static_rnn в виде списка, например:

import tensorflow as tf

num_input_features = 32
num_output_features = 32

lstm_size = 128
max_seq_len = 5

# input/output:
x = tf.placeholder(tf.float32, [None, max_seq_len, num_input_features])

x_series = tf.unstack(x, axis=1) # a list of length max_seq_len

# recurrent layer:
lstm_cell = tf.contrib.rnn.BasicLSTMCell(lstm_size)
rnn_outputs, final_state = tf.nn.static_rnn(lstm_cell, x_series, dtype=tf.float32)

Это дает вам список выходов, один для каждого временного шага.Затем, если вы хотите выполнить некоторые дополнительные вычисления на выходах RNN на каждом шаге, вы можете просто сделать это для каждого элемента списка вывода:

# output layer:

w = tf.Variable(tf.random_normal([lstm_size, num_output_features]))
b = tf.Variable(tf.random_normal([num_output_features]))

z_series = [tf.matmul(out, w) + b for out in rnn_outputs]
yhat_series = [tf.nn.tanh(z) for z in z_series]

И тогда я могу составить yhat_seriesеще раз и сравните его с некоторыми метками y для моей функции стоимости.

Вот что я не получаю: В динамическом RNN вход, который вы передаете методу dynamic_rnn, вместо этого является тензором с егособственное измерение времени (по умолчанию ось 1):

# input/output:
x = tf.placeholder(tf.float32, [None, max_seq_len, num_input_features])

# x_series = tf.unstack(x, axis=1) # dynamic RNN does not need this

# recurrent layer:
lstm_cell = tf.contrib.rnn.BasicLSTMCell(lstm_size)
dyn_rnn_outputs, dyn_final_state = tf.nn.dynamic_rnn(lstm_cell, x, dtype=tf.float32)

Тогда dyn_rnn_output - это не список, а тензор формы (?, max_seq_len, lstm_size).Какой лучший способ справиться с подачей этого тензора в последующий плотный слой?Я не могу умножить выходы RNN на свою матрицу весов, и разбор выводов RNN выглядит как неуклюжий взлом, которого был разработан API dynamic_rnn, чтобы его избежать.

Есть ли хороший подход, который мне не хватает?

1 Ответ

0 голосов
/ 14 мая 2018

Обновление для тех, кто пытается это выяснить:

Существует функция тензорного потока, tf.contrib.rnn.OutputProjectionWrapper, которая, кажется, специально предназначена для присоединения плотного слоя к выходу ячейки RNN, но упаковывает его как часть самой ячейки RNN, которую затем можно развернуть с помощью вызова. до tf.nn.dynamic_rnn:

lstm_cell = tf.contrib.rnn.BasicLSTMCell(lstm_size)
proj = tf.contrib.rnn.OutputProjectionWrapper(lstm_cell, num_output_features)
dyn_rnn_outputs, dyn_final_state = tf.nn.dynamic_rnn(proj, x, dtype=tf.float32)

Но в более общем плане, если вы хотите работать с выходами RNN, обычная практика, как представляется, заключается в изменении формы rnn_outputs путем развертывания измерений в пакетном и временном режимах, выполнения операций с этим тензором и их прокручивания. резервное копирование для окончательного вывода.

...