为 Keras 有状态 RNN 将数据拆分为批次的正确方法
Correct way to split data to batches for Keras stateful RNNs
正如 documentation 所述
the last state for each sample at index i in a batch will be used as
initial state for the sample of index i in the following batch
这是否意味着要将数据分成批次我需要按以下方式进行
例如让我们假设我正在训练一个有状态的 RNN 来预测 range(0, 5) 中给定前一个整数的下一个整数
# batch_size = 3
# 0, 1, 2 etc in x are samples (timesteps and features omitted for brevity of the example)
x = [0, 1, 2, 3, 4]
y = [1, 2, 3, 4, 5]
batches_x = [[0, 1, 2], [1, 2, 3], [2, 3, 4]]
batches_y = [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
那么在 x[0, 0] 上学习后的状态将是 x[1, 0] 的初始状态
x[0, 1] 代表 x[1, 1](0 代表 1,1 代表 2 等等)?
这样做正确吗?
基于,为此我进行了一些测试。
有状态=假:
通常(stateful=False),你有一批有很多序列:
batch_x = [
[[0],[1],[2],[3],[4],[5]],
[[1],[2],[3],[4],[5],[6]],
[[2],[3],[4],[5],[6],[7]],
[[3],[4],[5],[6],[7],[8]]
]
形状是(4,6,1)
。这意味着您有:
- 1 批
- 4 个单独的序列 = 这是批量大小,它可以变化
- 每个序列 6 个步骤
- 每步 1 个特征
每次训练时,无论是重复这批还是通过新的一批,它都会看到单独的序列。每个序列都是一个独特的条目。
状态=真:
当您转到有状态层时,您将不再传递单个序列。您将传递分成小批量的非常长的序列。您将需要更多批次:
batch_x1 = [
[[0],[1],[2]],
[[1],[2],[3]],
[[2],[3],[4]],
[[3],[4],[5]]
]
batch_x2 = [
[[3],[4],[5]], #continuation of batch_x1[0]
[[4],[5],[6]], #continuation of batch_x1[1]
[[5],[6],[7]], #continuation of batch_x1[2]
[[6],[7],[8]] #continuation of batch_x1[3]
]
两个形状都是(4,3,1)
。这意味着您拥有:
- 2 批次
- 4 个单独的序列 = 这是批量大小,它必须是常数
- 每个序列 6 个步骤(每批 3 个步骤)
- 每步 1 个特征
有状态层适用于庞大的序列,其长度足以超出您的记忆力或您完成某些任务的可用时间。然后将序列切片并分成几部分进行处理。结果没有区别,该层没有更智能或具有其他功能。它只是不认为序列在它处理了一批之后就结束了。它期待这些序列的延续。
在这种情况下,您自己决定序列何时结束并手动调用 model.reset_states()
。
正如 documentation 所述
the last state for each sample at index i in a batch will be used as initial state for the sample of index i in the following batch
这是否意味着要将数据分成批次我需要按以下方式进行 例如让我们假设我正在训练一个有状态的 RNN 来预测 range(0, 5) 中给定前一个整数的下一个整数
# batch_size = 3
# 0, 1, 2 etc in x are samples (timesteps and features omitted for brevity of the example)
x = [0, 1, 2, 3, 4]
y = [1, 2, 3, 4, 5]
batches_x = [[0, 1, 2], [1, 2, 3], [2, 3, 4]]
batches_y = [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
那么在 x[0, 0] 上学习后的状态将是 x[1, 0] 的初始状态 x[0, 1] 代表 x[1, 1](0 代表 1,1 代表 2 等等)?
这样做正确吗?
基于
有状态=假:
通常(stateful=False),你有一批有很多序列:
batch_x = [
[[0],[1],[2],[3],[4],[5]],
[[1],[2],[3],[4],[5],[6]],
[[2],[3],[4],[5],[6],[7]],
[[3],[4],[5],[6],[7],[8]]
]
形状是(4,6,1)
。这意味着您有:
- 1 批
- 4 个单独的序列 = 这是批量大小,它可以变化
- 每个序列 6 个步骤
- 每步 1 个特征
每次训练时,无论是重复这批还是通过新的一批,它都会看到单独的序列。每个序列都是一个独特的条目。
状态=真:
当您转到有状态层时,您将不再传递单个序列。您将传递分成小批量的非常长的序列。您将需要更多批次:
batch_x1 = [
[[0],[1],[2]],
[[1],[2],[3]],
[[2],[3],[4]],
[[3],[4],[5]]
]
batch_x2 = [
[[3],[4],[5]], #continuation of batch_x1[0]
[[4],[5],[6]], #continuation of batch_x1[1]
[[5],[6],[7]], #continuation of batch_x1[2]
[[6],[7],[8]] #continuation of batch_x1[3]
]
两个形状都是(4,3,1)
。这意味着您拥有:
- 2 批次
- 4 个单独的序列 = 这是批量大小,它必须是常数
- 每个序列 6 个步骤(每批 3 个步骤)
- 每步 1 个特征
有状态层适用于庞大的序列,其长度足以超出您的记忆力或您完成某些任务的可用时间。然后将序列切片并分成几部分进行处理。结果没有区别,该层没有更智能或具有其他功能。它只是不认为序列在它处理了一批之后就结束了。它期待这些序列的延续。
在这种情况下,您自己决定序列何时结束并手动调用 model.reset_states()
。