【问题标题】:How to prepare data for stateful LSTM in Keras?如何为 Keras 中的有状态 LSTM 准备数据?
【发布时间】:2019-02-03 21:45:38
【问题描述】:

我想开发一种用于二进制分类的时间序列方法,在 Keras 中使用有状态 LSTM

这是我的数据的外观。我得到了很多,比如N,录音。每个记录包含 22 个长度为 M_i(i=1,...N) 的时间序列。我想在 Keras 中使用有状态模型,但我不知道如何重塑我的数据,尤其是关于我应该如何定义我的 batch_size

这是我为stateless LSTM 进行的操作。我为所有录音创建了长度为 look_back 的序列,这样我就有了大小为 (N*(M_i-look_back), look_back, 22=n_features) 的数据

这是我为此目的使用的函数:

def create_dataset(feat,targ, look_back=1):
    dataX, dataY = [], []
#     print (len(targ)-look_back-1)
    for i in range(len(targ)-look_back):
        a = feat[i:(i+look_back), :]
        dataX.append(a)
        dataY.append(targ[i + look_back-1])
    return np.array(dataX), np.array(dataY)

其中feat 是大小为(n_samples, n_features)(针对每个记录)的二维数据数组,targ 是目标向量。

所以,我的问题是,根据上面解释的数据,如何为有状态模型重塑数据并考虑批处理概念?有什么预防措施吗?

我想要做的是能够将每个记录的每个 time_step 分类为癫痫发作/非癫痫发作。

编辑:我想到的另一个问题是:我的录音包含不同长度的序列。我的有状态模型可以学习对每个记录的长期依赖关系,这意味着 batch_size 从一个记录到另一个记录不同......如何处理?在完全不同的序列(test_set)上测试会不会造成泛化问题?

谢谢

【问题讨论】:

  • 使用有状态的有什么特殊原因吗? (它在计算上与常规层没有什么不同,它也不适合回溯窗口)。
  • stateful=False 学习与 stateful=True 完全相同的东西。没有区别。唯一的区别是:stateful=False 认为“这批输入独立于前一批输入”,而 stateful=True 事情“这批输入与最后一批输入的序列相同,我会假设没有中断”。
  • 我认为“有状态”这个名字选得非常糟糕。 “无状态”一词表明没有记忆状态,这是不正确的。它应该被称为 keep_states=True (因为不要在每批之后重置状态)。
  • 不需要冗余(滑动窗口),我不知道他们为什么教这个。这完全违背了 LSTM 可以学习的“长期依赖”。
  • 我必须更好地理解您的数据才能回答。请看下面我的回答。你不需要“切断信号”。但是“如果你削减”,那么你需要 stateful=True。 (但如果你没有理由削减,就不要削减)。

标签: python keras lstm


【解决方案1】:

我认为您不需要有状态层。

如果您想长期学习,请不要创建这些滑动窗口。将您的数据定型为:

(number_of_independent_sequences, length_or_steps_of_a_sequence, variables_or_features_per_step)

我不确定我是否正确理解了您问题中的措辞。如果“录音”类似于“电影”或“歌曲”、“语音剪辑”或类似的东西,那么:

  • 序列数 = 记录数

遵循“录制”的理念,时间步长将是“视频中的帧”,或音频文件中的“样本”(时间 x 1 个通道的样本速率)。 (注意,keras 中的“样本”是“序列/录音”,而音频处理中的“样本”是 keras 中的“步骤”)。

  • time_steps = 帧数或音频样本数

最后,特征/变量的数量。在电影中,它就像 RGB 通道(3 个特征),在音频中,还有通道数(在立体声中为 2 个)。在其他类型的数据中,它们可能是温度、压力等。

  • 特征 = 每一步测量的变量数

让您的数据形成这样的形状适用于 stateful = True 和 False。

这两种训练方法是等价的:

#with stateful=False
model.fit(X, Y, batch_size=batch_size)

#with stateful=True
for start in range(0, len(X), batch_size):
    model.train_on_batch(X[start:start+batch_size], Y[start:start+batch_size])
    model.reset_states()

可能只有优化器的更新方式有变化。

对于您的情况,如果您可以创建上述形状的输入数据并且您不会递归地预测未来,我认为没有理由使用stateful=True

对每一步进行分类

对于每一步的分类,你不需要创建滑动窗口,也不需要使用stateful=True

通过设置return_sequences=True,循环层可以选择输出所有时间步长。

如果您有一个形状为(batch, steps, features) 的输入,您将需要形状为(batch, steps, 1) 的目标,即每步一个类

简而言之,你需要:

  • 具有return_sequences=True 的 LSTM 层
  • X_train 与形状 (files, total_eeg_length, 22)
  • Y_train 与形状 (files, total_eeg_length, 1)

提示:由于 LSTM 不能很好地对开头进行分类,您可以尝试使用 Bidirectional(LSTM(....)) 层。

不同长度的输入

要使用不同长度的输入,您需要设置input_shape=(None, features)。考虑到我们在聊天中的讨论,features = 22

然后你可以:

  • 单独加载每个脑电图:

    • X_train(1, eeg_length, 22)
    • Y_train(1, eeg_length, 1)
    • 使用 model.train_on_batch(array, targets) 分别训练每个 EEG。
    • 您将需要手动管理 epoch 并使用 test_on_batch 验证数据。
  • 用零或其他虚拟值填充较短的 EEG,直到它们都到达max_eeg_length 并使用:

    • 模型开头的Masking 层以丢弃具有虚拟值的步骤。
    • X_train(eegs, max_eeg_length, 22)
    • Y_train(eegs, max_eeg_length, 1)
    • 您可以使用普通的model.fit(X_train, Y_train,...) 进行训练

【讨论】:

  • 如果我有多类分类怎么办?只需将Y_train 的最后一个参数设置为nb_classes 或最后一个参数(在您的答案中设置为1)只是“目标”的变量数量,无论每个目标可用的类数量是多少?此外,我猜验证数据和 test_data 的大小应该与训练数据相同?
  • 此外,在我的模型结束时,我该怎么做才能获得诸如confusion_matrix,...之类的指标?我不确定如何对每个 test_data 求和...
  • 对于目标形状的多类(批次、长度、类)。没有必要有“相同的大小”。不过,您需要“相同数量的课程”。
  • 其余的都是自定义的。
  • 适合class_weight={0: weight_for_0, 1: weight_for_1}
猜你喜欢
  • 1970-01-01
  • 2016-07-05
  • 1970-01-01
  • 2017-08-31
  • 2018-04-04
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
相关资源
最近更新 更多