如果假设我有训练有素的RNN(例如语言模型),并且我想看看它会自己产生什么,我应该如何将其输出反馈给它的输入? < / p>
我阅读了以下相关问题:
理论上我很清楚,在tensorflow中我们使用截断的反向传播,所以我们必须定义我们想要“追踪”的最大步骤。我们还为批量保留了维度,因此如果我想训练正弦波,我必须输入[None, num_step, 1]
个输入。
以下代码有效:
tf.reset_default_graph()
n_samples=100
state_size=5
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(state_size, forget_bias=1.)
def_x = np.sin(np.linspace(0, 10, n_samples))[None, :, None]
zero_x = np.zeros(n_samples)[None, :, None]
X = tf.placeholder_with_default(zero_x, [None, n_samples, 1])
output, last_states = tf.nn.dynamic_rnn(inputs=X, cell=lstm_cell, dtype=tf.float64)
pred = tf.contrib.layers.fully_connected(output, 1, activation_fn=tf.tanh)
Y = np.roll(def_x, 1)
loss = tf.reduce_sum(tf.pow(pred-Y, 2))/(2*n_samples)
opt = tf.train.AdamOptimizer().minimize(loss)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
# Initial state run
plt.show(plt.plot(output.eval()[0]))
plt.plot(def_x.squeeze())
plt.show(plt.plot(pred.eval().squeeze()))
steps = 1001
for i in range(steps):
p, l, _= sess.run([pred, loss, opt])
LSTM的状态大小可以变化,我也尝试将正弦波馈入网络和零,并且在两种情况下它都在~500次迭代中收敛。到目前为止,我已经了解到,在这种情况下,图表包含n_samples
个共享其参数的LSTM单元格数量,我只能将输入作为时间序列提供给我。但是,当生成样本时,网络明确取决于其先前的输出 - 这意味着我无法立即提供展开的模型。我试图在每一步计算状态和输出:
with tf.variable_scope('sine', reuse=True):
X_test = tf.placeholder(tf.float64)
X_reshaped = tf.reshape(X_test, [1, -1, 1])
output, last_states = tf.nn.dynamic_rnn(lstm_cell, X_reshaped, dtype=tf.float64)
pred = tf.contrib.layers.fully_connected(output, 1, activation_fn=tf.tanh)
test_vals = [0.]
for i in range(1000):
val = pred.eval({X_test:np.array(test_vals)[None, :, None]})
test_vals.append(val)
然而,在这个模型中,似乎LSTM细胞之间没有连续性。这是怎么回事?
我是否必须使用100个时间步骤初始化零数组,并将每个运行的结果分配给数组?就像用网络喂养网络一样:
运行0:input_feed = [0, 0, 0 ... 0]; res1 = result
运行1:input_feed = [res1, 0, 0 ... 0]; res2 = result
运行1:input_feed = [res1, res2, 0 ... 0]; res3 = result
等...
如果我想使用这个经过培训的网络在下一个时间步骤中使用自己的输出作为输入,该怎么办?
答案 0 :(得分:6)
如果我理解正确,您希望找到一种方法来将时间步t
的输出作为时间步t+1
的输入,对吧?为此,您可以在测试时间使用相对简单的工作:
None
。tf.nn.dynamic_rnn
(您在发布的示例中执行此操作)。dynamic_rnn
。即,将模型的定义更改为:
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(state_size, forget_bias=1.)
X = tf.placeholder_with_default(zero_x, [None, None, 1]) # [batch_size, seq_length, dimension of input]
batch_size = tf.shape(self.input_)[0]
initial_state = lstm_cell.zero_state(batch_size, dtype=tf.float32)
def_x = np.sin(np.linspace(0, 10, n_samples))[None, :, None]
zero_x = np.zeros(n_samples)[None, :, None]
output, last_states = tf.nn.dynamic_rnn(inputs=X, cell=lstm_cell, dtype=tf.float64,
initial_state=initial_state)
pred = tf.contrib.layers.fully_connected(output, 1, activation_fn=tf.tanh)
然后你可以像这样进行推理:
fetches = {'final_state': last_state,
'prediction': pred}
toy_initial_input = np.array([[[1]]]) # put suitable data here
seq_length = 20 # put whatever is reasonable here for you
# get the output for the first time step
feed_dict = {X: toy_initial_input}
eval_out = sess.run(fetches, feed_dict)
outputs = [eval_out['prediction']]
next_state = eval_out['final_state']
for i in range(1, seq_length):
feed_dict = {X: outputs[-1],
initial_state: next_state}
eval_out = sess.run(fetches, feed_dict)
outputs.append(eval_out['prediction'])
next_state = eval_out['final_state']
# outputs now contains the sequence you want
请注意,这也适用于批次,但如果您在同一批次中使用不同长度的序列,则可能会有点复杂。
如果您不仅要在测试时进行此类预测,还要在训练时进行此类预测,也可以这样做,但实施起来要复杂一些。
答案 1 :(得分:1)
您可以使用自己的输出(最后状态)作为下一步输入(初始状态)。 一种方法是:
第二种方法可以通过以下方式完成:
答案 2 :(得分:1)
我知道我参加聚会有点晚了,但是我认为这个要点可能会有用:
https://gist.github.com/CharlieCodex/f494b27698157ec9a802bc231d8dcf31
它使您可以通过过滤器自动输入输入,并作为输入返回网络。要使形状匹配,可以将processing
设置为tf.layers.Dense
层。
请问任何问题!
编辑:
在您的特定情况下,创建一个lambda来执行对dynamic_rnn
输出到字符向量空间的处理。例如:
# if you have:
W = tf.Variable( ... )
B = tf.Variable( ... )
Yo, Ho = tf.nn.dynamic_rnn( cell , inputs , state )
logits = tf.matmul(W, Yo) + B
...
# use self_feeding_rnn as
process_yo = lambda Yo: tf.matmul(W, Yo) + B
Yo, Ho = self_feeding_rnn( cell, seed, initial_state, processing=process_yo)