是否建议保存 RNN 训练的最终状态以在测试期间对其进行初始化?
Is it advisable to save the final state from training of an RNN to initialize it during testing?
在训练 RNN 之后,保存最终 state
以便它成为测试的初始状态是否有意义?
我正在使用:
stacked_lstm = rnn.MultiRNNCell([rnn.BasicLSTMCell(n_hidden,state_is_tuple=True) for _ in range(number_of_layers)], state_is_tuple=True)
state
具有非常具体的含义和目的。这不是“可取”与否的问题,这里有正确和错误的答案,这取决于你的数据。
考虑数据序列中的每个时间步长。在第一步,您的 state
应该初始化为全零。这个值有特定的含义,它告诉网络这是你序列的开始。
在每个时间步,RNN 都在计算一个新状态。 tensorflow 中的 MultiRNNCell 实现对您隐藏了这一点,但在该函数内部,每个时间步都会计算一个新的隐藏状态并向前传递。
第2步state
的值是第1步state
的输出,依此类推。
所以你的问题的答案是肯定的只有如果下一批从上一批及时继续。让我用几个例子来解释这一点,分别执行和不执行此操作。
示例 1: 假设您正在训练角色 RNN,这是一个常见的教程示例,您的输入是莎士比亚作品中的每个角色。这个序列中有数百万个字符。你不能训练那么长的序列。因此,您将序列分成 100 个片段(如果您不知道为什么要这样做,则将序列限制在大约 100 个时间步)。在此示例中,每个训练步骤都是 100 个字符的序列,并且是最后 100 个字符的延续。所以你必须将状态推进到下一个训练步骤。
示例 2: 在训练 RNN 以识别 MNIST 手写数字时不使用它。在这种情况下,您将图像分成 28 行,每行 28 个像素,每次训练只有 28 个时间步长,图像中每行一个。在这种情况下,每次训练迭代都从该图像序列的开头开始,并进行全面训练,直到该图像序列结束。在这种情况下,您不会将隐藏状态向前推进,您的隐藏状态必须以零开头,以告诉系统这是新图像序列的开始,而不是您训练的最后一张图像的延续。
我希望这两个例子能说明其中的重要区别。知道如果你有很长的序列长度(比如超过 ~100 个时间步长),你需要将它们分解并考虑适当地推进状态的过程。您无法有效地训练无限长的序列长度。如果你的序列长度低于这个粗略的阈值,那么你就不必担心这个细节并且总是将你的状态初始化为零。
还知道即使您一次只训练 100 个时间步长,RNN 仍然可以预期学习在更长序列上运行的模式,Karpathy 的精彩 paper/blog 关于“RNN 的不合理有效性”很好地展示了这一点。那些字符级别的 RNN 可以跟踪重要的细节,比如一个引号是否在数百个字符上是开放的,远远超过在一批中训练的数量,特别是因为隐藏状态以适当的方式进行。
在训练 RNN 之后,保存最终 state
以便它成为测试的初始状态是否有意义?
我正在使用:
stacked_lstm = rnn.MultiRNNCell([rnn.BasicLSTMCell(n_hidden,state_is_tuple=True) for _ in range(number_of_layers)], state_is_tuple=True)
state
具有非常具体的含义和目的。这不是“可取”与否的问题,这里有正确和错误的答案,这取决于你的数据。
考虑数据序列中的每个时间步长。在第一步,您的 state
应该初始化为全零。这个值有特定的含义,它告诉网络这是你序列的开始。
在每个时间步,RNN 都在计算一个新状态。 tensorflow 中的 MultiRNNCell 实现对您隐藏了这一点,但在该函数内部,每个时间步都会计算一个新的隐藏状态并向前传递。
第2步state
的值是第1步state
的输出,依此类推。
所以你的问题的答案是肯定的只有如果下一批从上一批及时继续。让我用几个例子来解释这一点,分别执行和不执行此操作。
示例 1: 假设您正在训练角色 RNN,这是一个常见的教程示例,您的输入是莎士比亚作品中的每个角色。这个序列中有数百万个字符。你不能训练那么长的序列。因此,您将序列分成 100 个片段(如果您不知道为什么要这样做,则将序列限制在大约 100 个时间步)。在此示例中,每个训练步骤都是 100 个字符的序列,并且是最后 100 个字符的延续。所以你必须将状态推进到下一个训练步骤。
示例 2: 在训练 RNN 以识别 MNIST 手写数字时不使用它。在这种情况下,您将图像分成 28 行,每行 28 个像素,每次训练只有 28 个时间步长,图像中每行一个。在这种情况下,每次训练迭代都从该图像序列的开头开始,并进行全面训练,直到该图像序列结束。在这种情况下,您不会将隐藏状态向前推进,您的隐藏状态必须以零开头,以告诉系统这是新图像序列的开始,而不是您训练的最后一张图像的延续。
我希望这两个例子能说明其中的重要区别。知道如果你有很长的序列长度(比如超过 ~100 个时间步长),你需要将它们分解并考虑适当地推进状态的过程。您无法有效地训练无限长的序列长度。如果你的序列长度低于这个粗略的阈值,那么你就不必担心这个细节并且总是将你的状态初始化为零。
还知道即使您一次只训练 100 个时间步长,RNN 仍然可以预期学习在更长序列上运行的模式,Karpathy 的精彩 paper/blog 关于“RNN 的不合理有效性”很好地展示了这一点。那些字符级别的 RNN 可以跟踪重要的细节,比如一个引号是否在数百个字符上是开放的,远远超过在一批中训练的数量,特别是因为隐藏状态以适当的方式进行。