gpt4 book ai didi

python - 如何将 RNN 输出反馈到 TensorFlow 中的输入

转载 作者:太空狗 更新时间:2023-10-29 21:38:55 24 4
gpt4 key购买 nike

假设我有一个训练有素的 RNN(例如语言模型),并且我想看看它会自己生成什么,我应该如何将它的输出反馈到它的输入?

我阅读了以下相关问题:

理论上我很清楚,在 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 单元组成,这些单元共享它们的参数,并且我只能将输入作为 时间序列 提供给它们em>。但是,当生成 样本时,网络明确取决于其先前的输出 - 这意味着我无法立即提供展开的模型。我尝试计算每一步的状态和输出:

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 = 结果

运行 1:input_feed = [res1, 0, 0 ... 0]; res2 = 结果

运行 1:input_feed = [res1, res2, 0 ... 0]; res3 = 结果

等...

如果我想使用这个经过训练的网络在接下来的时间步中使用它自己的输出作为它的输入怎么办?

最佳答案

如果我没理解错的话,你想找到一种方法将时间步 t 的输出作为时间步 t+1 的输入,对吧?为此,您可以在测试时间使用一个相对简单的解决方法:

  1. 确保您的输入占位符可以接受动态序列长度,即时间维度的大小为
  2. 确保您使用的是 tf.nn.dynamic_rnn(您在发布的示例中使用的)。
  3. 将初始状态传递给 dynamic_rnn
  4. 然后,在测试时,您可以遍历序列并单独输入每个时间步长(即最大序列长度为 1)。此外,您只需继承 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

请注意,这也适用于批处理,但是如果您在同一批处理中对不同长度的序列进行排序,则可能会稍微复杂一些。

如果你想不仅在测试时,而且在训练时进行这种预测,也是可以的,但实现起来有点复杂。

关于python - 如何将 RNN 输出反馈到 TensorFlow 中的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42440565/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com