gpt4 book ai didi

python - 为什么在Tensorflow上的PTB教程中运行纪元时构造feed_dict?

转载 作者:太空宇宙 更新时间:2023-11-03 13:58:49 24 4
gpt4 key购买 nike

问题1:我在递归神经网络上关注this tutorial,我想知道为什么需要在代码的以下部分中创建feed_dict

def run_epoch(session, model, eval_op=None, verbose=False):

state = session.run(model.initial_state)

fetches = {
"cost": model.cost,
"final_state": model.final_state,
}
if eval_op is not None:
fetches["eval_op"] = eval_op

for step in range(model.input.epoch_size):
feed_dict = {}
for i, (c, h) in enumerate(model.initial_state):
feed_dict[c] = state[i].c
feed_dict[h] = state[i].h

vals = session.run(fetches, feed_dict)


我测试了一下,看来如果删除了这部分代码,该代码也会运行:

def run_epoch(session, model, eval_op=None, verbose=False):

fetches = {
"cost": model.cost,
"final_state": model.final_state,
}
if eval_op is not None:
fetches["eval_op"] = eval_op

for step in range(model.input.epoch_size):
vals = session.run(fetches)


所以我的问题是,为什么在喂入一批新数据后需要将初始状态重置为零?

Q2:另外,据我了解,使用 feed_dict被认为很慢。因此,建议使用 tf.data API馈送数据。在这种情况下,使用 feed_dict是否也是一个问题?如果是这样,在本示例中如何避免使用 feed_dict

UPD:非常感谢@jdehesa的详细答复。它有很大帮助!在我结束这个问题并接受您的答案之前,您能否澄清您提到的回答问题一。

我现在看到 feed_dict的目的。但是,我不确定该教程中是否已实现。从你说的:


  在每个时期的开始,代码首先采用默认的“零状态”,然后继续执行循环,在该循环中,将当前状态设为初始状态,运行模型,并将输出状态设置为下一个新的当前状态迭代。


我只是再次查看了本教程的 the source code,没有看到输出状态在哪里设置为下一次迭代的新当前状态。它是隐式完成的还是我错过了什么?

我也许在理论上也缺少一些东西。为了确保我理解正确,这里有一个简单的例子。假设输入数据是一个存储从0到120的整数值的数组。我们将批处理大小设置为 5,将一个批处理中的数据点数设置为 24,并将展开的RNN中的时间步数设置为< cc>。在这种情况下,您只能在 100的时间点使用数据点。然后,分两个步骤( 20)处理数据。当您遍历 model.input.epoch_size = 2时:

state = session.run(model.initial_state)
# ...
for step in range(model.input.epoch_size):
feed_dict = {}
for i, (c, h) in enumerate(model.initial_state):
feed_dict[c] = state[i].c
feed_dict[h] = state[i].h

vals = session.run(fetches, feed_dict)


您可以输入以下数据:

> Iteration (step) 1:
x:
[[ 0 1 2 3 4 5 6 7 8 9]
[ 24 25 26 27 28 29 30 31 32 33]
[ 48 49 50 51 52 53 54 55 56 57]
[ 72 73 74 75 76 77 78 79 80 81]
[ 96 97 98 99 100 101 102 103 104 105]]
y:
[[ 1 2 3 4 5 6 7 8 9 10]
[ 25 26 27 28 29 30 31 32 33 34]
[ 49 50 51 52 53 54 55 56 57 58]
[ 73 74 75 76 77 78 79 80 81 82]
[ 97 98 99 100 101 102 103 104 105 106]]

> Iteration (step) 2:
x:
[[ 10 11 12 13 14 15 16 17 18 19]
[ 34 35 36 37 38 39 40 41 42 43]
[ 58 59 60 61 62 63 64 65 66 67]
[ 82 83 84 85 86 87 88 89 90 91]
[106 107 108 109 110 111 112 113 114 115]]
y:
[[ 11 12 13 14 15 16 17 18 19 20]
[ 35 36 37 38 39 40 41 42 43 44]
[ 59 60 61 62 63 64 65 66 67 68]
[ 83 84 85 86 87 88 89 90 91 92]
[107 108 109 110 111 112 113 114 115 116]]


在每次迭代中,您将用递归单位的初始状态为零构造一个新的 model.input.epoch_size。因此,您假设在每一步都从头开始处理序列。这是对的吗?

最佳答案

Q1。在这种情况下,使用feed_dict设置循环单元的初始状态。默认情况下,每次调用run循环单元时,处理的数据都处于初始“零”状态。但是,如果序列很长,则可能需要将其分为几个步骤。在每个步骤之后,请务必保存循环单元的最终状态,并输入下一步的初始状态,这一点很重要,否则,就好像下一步又是序列的开始一样(尤其是如果输出只是处理完整个序列后网络的最终输出,就像丢弃最后一步之前的所有数据一样。在每个时期的开始,代码首先采用默认的“零状态”,然后继续执行循环,在该循环中,将当前状态设为初始状态,运行模型,并将输出状态设置为下一个新的当前状态迭代。
Q2。一般说来,“ feed_dict慢”的说法可能会产生误导(我并不是怪您这么说,我也已经看过很多次了)。 feed_dict的问题在于其功能是将非TensorFlow数据(通常为NumPy数据)带入TensorFlow世界。并不是说这很可怕,仅仅是需要花费一些额外的时间来移动数据,尤其是在涉及大量数据的情况下。例如,如果您想通过feed_dict输入一批图像,则需要从磁盘加载它们,对其进行解码,将其转换为大的NumPy数组并将其传递给feed_dict,然后TensorFlow将复制所有数据进入会话(GPU内存或其他);因此您将在内存中复制两个数据,并进行其他内存交换。 tf.data之所以有帮助,是因为它在TensorFlow中完成了所有工作(这也减少了Python / C行程的次数,并且有时通常更方便)。在您的情况下,通过feed_dict馈送的是循环单元的初始状态。除非您有几个相当大的循环层,否则我会说对性能的影响可能很小。不过,有可能在这种情况下也要避免feed_dict,您需要拥有一组保存当前状态的TensorFlow变量,设置循环单元以将其输出用作初始状态(使用initial_state参数并使用其最终状态来更新变量值;那么在每个新批次上,您将不得不再次将变量重新初始化为“零”状态。但是,我会确保在走那条路线之前这将有很大的好处(例如,即使结果不正确,也可以使用tf.nn.dynamic_rnn和不使用feed_dict来测量运行时间)。


编辑:

为了澄清更新,我在此处复制了代码的相关行:

state = session.run(model.initial_state)

fetches = {
"cost": model.cost,
"final_state": model.final_state,
}
if eval_op is not None:
fetches["eval_op"] = eval_op

for step in range(model.input.epoch_size):
feed_dict = {}
for i, (c, h) in enumerate(model.initial_state):
feed_dict[c] = state[i].c
feed_dict[h] = state[i].h

vals = session.run(fetches, feed_dict)
cost = vals["cost"]
state = vals["final_state"]

costs += cost
iters += model.input.num_steps


在纪元开始时, state取值为 model.initial_state,除非给出 feed_dict替换其值,否则它将为默认的“零”初始状态值。 fetches是稍后将传递给 session.run的词典,因此它返回另一个词典,其中 "final_state"键将保存最终状态值。然后,在每个步骤上,创建一个 feed_dict,用 initial_state中的数据替换 state张量值,并使用该 run调用 feed_dict以检索 fetches中的张量值。 ,然后 vals保存 run调用的输出。 state = vals["final_state"]行用上次运行的输出状态替换了当前状态值 state的内容;因此,在下一次迭代中, feed_dict将保留先前最后一个状态的值,因此网络将继续“好像”一次就给出了整个序列。在下一次对 run_epoch的调用中, state将再次初始化为 model.initial_state的默认值,并且该过程将再次从“零”开始。

关于python - 为什么在Tensorflow上的PTB教程中运行纪元时构造feed_dict?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49405965/

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