Python 如何在Keras中为有状态LSTM准备数据?

Python 如何在Keras中为有状态LSTM准备数据?,python,keras,lstm,Python,Keras,Lstm,我想为二进制分类开发一种时间序列方法,在Keras中使用有状态LSTM 下面是我的数据的外观。我得到了很多录音,比如说N。每个记录由22个长度为M_i(i=1,…N)的时间序列组成。我想在Keras中使用有状态模型,但我不知道如何重塑数据,特别是如何定义我的批处理大小 下面是我如何处理无状态LSTM的。我为所有录音创建了长度序列look\u back,这样我就有了大小数据(N*(M\u I-look\u back),look\u back,22=N\u特征) 以下是我用于此目的的函数: def

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

下面是我的数据的外观。我得到了很多录音,比如说
N
。每个记录由22个长度为M_i(i=1,…N)的时间序列组成。我想在Keras中使用有状态模型,但我不知道如何重塑数据,特别是如何定义我的
批处理大小

下面是我如何处理
无状态
LSTM的。我为所有录音创建了长度序列
look\u back
,这样我就有了大小数据
(N*(M\u I-look\u back),look\u back,22=N\u特征)

以下是我用于此目的的函数:

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个样本,n个特征)
(每个记录)的二维数据数组,
targ
是目标向量

因此,我的问题是,基于上面解释的数据,如何为一个有状态的模型重塑数据,并考虑批处理的概念?有预防措施吗

我想做的是能够将每个录音的每一个时间步分类为“发作/未发作”

编辑:我想的另一个问题是:我有包含不同长度序列的录音。我的状态模型可以了解每个记录的长期依赖性,这意味着不同记录的批量大小不同。。。如何处理?当在完全不同的序列(测试集)上测试时,它不会导致泛化问题吗


谢谢

我认为您不需要一个有状态的层

如果你想长期学习,就不要创建这些滑动窗口。将您的数据塑造为:

(number_of_independent_sequences, length_or_steps_of_a_sequence, variables_or_features_per_step)
我不确定我是否正确理解了你问题中的措辞。如果“录音”类似于“电影”或“歌曲”、“语音剪辑”或类似内容,则:

  • 序列数量=录制数量
按照“录制”的想法,时间步长将是“视频中的帧”,或音频文件中的“采样”(1个通道的时间x采样率)。(请注意,keras中的“样本”是“序列/录音”,而音频处理中的“样本”是keras中的“步骤”)

  • 时间步长=帧数或音频采样数
最后,功能/变量的数量。在电影中,它就像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\u sequences=True
,重复层可以选择输出所有时间步长

如果您有一个带有shape
(批处理、步骤、特征)
的输入,则需要带有shape
(批处理、步骤1)
的目标,即每个步骤一个类

简而言之,您需要:

  • 具有
    return\u sequences=True的LSTM层
  • X\u列车
    带形状
    (文件,总长度,22)
  • Y\u序列
    带形状
    (文件,总长度,1)
提示:由于LSTM从不很好地对开始进行分类,您可以尝试使用
双向(LSTM(..)

不同长度的输入 要使用不同长度的输入,需要设置
input\u shape=(无,特征)
。考虑到我们在聊天中的讨论,
features=22

然后你可以:

  • 分别加载每个EEG:

    • X\u列车
      as
      (1,eeg\u长度,22)
    • Y\u序列
      as
      (1,eeg\u长度,1)
    • 使用
      模型分别训练每个脑电图。批量训练(阵列、目标)
    • 您需要手动管理历元,并对验证数据使用
      test\u on\u batch
  • 用零或另一个虚拟值填充较短的脑电图,直到它们都达到
    max_eeg_length
    并使用:

    • 模型开头的
      掩蔽
      层,用于丢弃带有虚拟值的步骤
    • X\u列车
      as
      (脑电图,最大脑电图长度,22)
    • Y\u序列
      as
      (脑电图,最大脑电图长度,1)
    • 您可以使用常规的
      型号进行训练。fit(X\U系列,Y\U系列,…)

使用stateful有什么特殊原因吗?(它在计算上与常规层没有什么不同,也不适用于回望窗口。)a
stateful=False
学习的东西与a
stateful=True
学习的东西完全相同。没有区别。唯一的区别是:
stateful=False
认为“这一批输入独立于前一批输入”,而
stateful=True
则认为“这一批输入与上一批输入序列相同,我假设没有中断”。我认为“stateful”这个名称选择得非常糟糕。“无状态”一词表示没有内存状态,但事实并非如此。它应该被称为类似于
keep_states=True
(因为不要在每个批处理后重置状态)。这种冗余(滑动窗口)是不必要的,我不知道他们为什么要教它。这完全违背了LSTM可以学到的“长期依赖性”。我必须更好地理解您的数据才能回答。见下面我的答案。你不知道