python - 将时间序列数据提供给有状态 LSTM 的正确方法?
问题描述
假设我有一个整数序列:
0,1,2, ..
并希望在给定最后 3 个整数的情况下预测下一个整数,例如:
[0,1,2]->5
, [3,4,5]->6
, 等
假设我像这样设置我的模型:
batch_size=1
time_steps=3
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, time_steps, 1), stateful=True))
model.add(Dense(1))
据我了解,模型具有以下结构(请原谅粗图):
第一个问题:我的理解正确吗?
注意我已经绘制了C_{t-1}, h_{t-1}
进入图片的先前状态,因为这是在指定时暴露的stateful=True
。在这个简单的“下一个整数预测”问题中,性能应该通过提供这些额外信息来提高(只要前一个状态来自前 3 个整数)。
这让我想到了我的主要问题: 似乎标准做法(例如参见这篇博文和TimeseriesGenerator keras 预处理实用程序)是在训练期间向模型提供一组交错的输入。
例如:
batch0: [[0, 1, 2]]
batch1: [[1, 2, 3]]
batch2: [[2, 3, 4]]
etc
这让我很困惑,因为这似乎需要第一个 Lstm 单元的输出(对应于第一个时间步)。看这个图:
从张量流文档:
stateful:布尔值(默认为 False)。如果为 True,则批次中索引 i 处每个样本的最后状态将用作下一批中索引 i 的样本的初始状态。
似乎这种“内部”状态不可用,所有可用的都是最终状态。看这个图:
所以,如果我的理解是正确的(显然不是),我们不应该在使用时向模型提供不重叠的样本窗口stateful=True
吗?例如:
batch0: [[0, 1, 2]]
batch1: [[3, 4, 5]]
batch2: [[6, 7, 8]]
etc
解决方案
答案是:取决于手头的问题。对于您的一步预测的情况 - 是的,您可以,但您不必这样做。但无论你是否这样做,都会对学习产生重大影响。
批处理与样本机制(“参见 AI”=参见“附加信息”部分)
所有模型都将样本视为独立示例;一批 32 个样品就像一次喂 1 个样品,32 次(有差异 - 见 AI)。从模型的角度来看,数据分为批量维度batch_shape[0]
和特征维度batch_shape[1:]
——两者“不说话”。两者之间的唯一关系是通过梯度(参见 AI)。
重叠与无重叠批次
也许理解它的最好方法是基于信息的。我将从时间序列二进制分类开始,然后将其与预测联系起来:假设您有 10 分钟的 EEG 记录,每个记录有 240000 个时间步长。任务:扣押还是不扣押?
- 由于 240k 对 RNN 来说太多了,我们使用 CNN 进行降维
- 我们可以选择使用“滑动窗口”——即一次输入一个子段;让我们使用 54k
取 10 个样品,定型(240000, 1)
。如何喂养?
(10, 54000, 1)
,包括所有样品,切片为sample[0:54000]; sample[54000:108000]
...(10, 54000, 1)
,包括所有样品,切片为sample[0:54000]; sample[1:54001]
...
以上两个你选哪个?如果 (2),您的神经网络将永远不会混淆这 10 个样本的癫痫发作与非癫痫发作。但它也会对任何其他样本一无所知。即,它会大量过拟合,因为它每次迭代看到的信息几乎没有什么不同(1/54000 = 0.0019%)——所以你基本上是连续多次喂它同一批。现在假设(3):
(10, 54000, 1)
,包括所有样品,切片为sample[0:54000]; sample[24000:81000]
...
更合理;现在我们的窗口有 50% 的重叠,而不是 99.998%。
预测:重叠不好?
如果您正在进行一步预测,那么信息格局现在会发生变化:
- 很有可能,您的序列长度从 240000 开始,因此任何类型的重叠都不会受到“同一批次多次”的影响
- 预测从根本上不同于分类,因为您输入的每个子样本的标签(下一个时间步长)都不同;分类对整个序列使用一个
这极大地改变了您的损失函数,以及将其最小化的“良好做法”:
- 预测器必须对其初始样本具有鲁棒性,尤其是对于 LSTM - 因此我们通过滑动序列来训练每个这样的“开始”,如您所示
- 由于标签在时间步之间存在差异,因此损失函数在时间步之间发生显着变化,因此过度拟合的风险要小得多
我应该怎么办?
首先,确保你理解了整篇文章,因为这里没有什么是真正“可选的”。然后,这是关于每批次重叠与不重叠的关键:
- 一个样本移位:模型学习更好地预测每个起始步骤的前一步 - 含义:(1)LSTM 对初始细胞状态的鲁棒性;(2) LSTM 对任何领先一步的预测都很好,因为落后 X 步
- 许多样本,在后面的批次中转移:模型不太可能“记住”训练集和过度拟合
你的目标:平衡两者;1 相对于 2 的主要优势是:
- 2 可以通过让它忘记看到的样本来阻碍模型
- 1允许模型通过检查多个开始和结束(标签)的样本来提取质量更好的特征,并相应地平均梯度
我应该在预测中使用(2)吗?
- 如果您的序列长度很长,并且您可以负担得起其长度约为 50% 的“滑动窗口”,则可能,但这取决于数据的性质:信号(EEG)?是的。股票,天气?怀疑。
- 多对多预测;更常见的是(2),每个更长的序列。
LSTM 有状态:实际上可能对您的问题完全没用。
当 LSTM 无法一次处理整个序列时使用有状态的,因此它被“拆分” - 或者当反向传播需要不同的梯度时。对于前者,想法是——LSTM 在评估后者时考虑前一个序列:
t0=seq[0:50]; t1=seq[50:100]
说得通;t0
逻辑上导致t1
seq[0:50] --> seq[1:51]
没有意义;t1
没有因果关系源自t0
换句话说:不要在有状态的不同批次中重叠。同一批是可以的,同样,独立性 - 样本之间没有“状态”。
何时使用有状态:当 LSTM 在评估下一个批次时考虑前一批时受益。这可以包括一步预测,但前提是您不能一次提供整个序列:
- 期望:100 个时间步长。可以做到:50。所以我们
t0, t1
按照上面的第一个项目符号进行设置。 - 问题:以编程方式实现并不简单。您需要找到一种在不应用梯度的情况下提供给 LSTM 的方法 - 例如冻结重量或设置
lr = 0
。
LSTM 何时以及如何在有状态的情况下“传递状态”?
- 何时:仅批次到批次;样本完全独立
- 如何:在 Keras 中,只有批样本到批样本:
stateful=True
需要您指定batch_shape
而不是input_shape
- 因为,Kerasbatch_size
在编译时构建了 LSTM 的单独状态
根据上述,您不能这样做:
# sampleNM = sample N at timestep(s) M
batch1 = [sample10, sample20, sample30, sample40]
batch2 = [sample21, sample41, sample11, sample31]
这意味着21
因果关系10
- 并且会破坏训练。而是这样做:
batch1 = [sample10, sample20, sample30, sample40]
batch2 = [sample11, sample21, sample31, sample41]
批次与样品:附加信息
“批次”是一组样本 - 1 个或更大(假设此答案总是后者)。迭代数据的三种方法:批量梯度下降(一次整个数据集)、随机 GD(一次一个样本)和 Minibatch GD(中间)。(然而,在实践中,我们也称最后一个 SGD 并且只区分 vs BGD - 假设这个答案是这样。)差异:
- SGD 从未真正优化过训练集的损失函数——只是它的“近似值”;每个批次都是整个数据集的一个子集,计算的梯度仅与最小化该批次的损失有关。批量越大,它的损失函数越接近训练集。
- 以上可以扩展到拟合批次与样本:样本是批次的近似值 - 或者,数据集的近似值较差
- 首先拟合 16 个样本,然后再拟合 16 个样本与一次拟合 32 个样本不同 - 因为权重在两者之间更新,所以后半部分的模型输出会改变
- 实际上,选择 SGD 而不是 BGD 的主要原因不是计算限制——而是它在大多数情况下更优越。简单解释:使用 BGD 更容易过度拟合,并且 SGD 通过探索更多样化的损失空间来收敛到更好的测试数据解决方案。
奖金图:
推荐阅读
- android - otp 自动填充的 Firebase 身份验证是否需要 SMS Retriever API?
- javascript - 从结果php中多次保存
- php - 如何单独回显foreach
- swift - 使用 Core Image 缩放图像是裁剪而不是缩放
- javascript - 将json对象推送到数组时如何省略特定键?
- multithreading - ncurses 多线程读写的解决方法
- ruby-on-rails - 如何仅禁用为特定路由发送 cookie?
- docker - Swagger UI 在使用 https 和 Traefik 作为反向代理时向请求 url 添加 :80
- tensorflow - 训练和测试模型时指标值相等
- javascript - 我如何制作一个会重复自身并继续从数据库中提取新值的函数?