由于您的问题有点混乱,我将采取以下假设。
- 您有一个包含 5000 个时间步长的时间序列,每一步都有一个特征。造型
(1, 5000, 1)
-
回答你的问题的主要部分:你想运行一个“滑动窗口”的情况,窗口的大小等于 3000,窗口的步幅是 1000。
- 您希望将窗口大小划分为 3 个内部时间序列,这 3 个序列中的每一个都有 1000 个步骤,每个步骤只有一个特征。这些系列中的每一个都进入与独立系列相同的LSTM(相当于拥有3个LSTM副本)-Shape
(slidingWindowSteps, 3, 1000, 1)
-
重要提示:从这 3 个系列中,您需要 3 个没有长度且具有 10 个特征的输出。形状
(1,3,10)。 (你的图片是 1x10,但你的文字是 10x1,我假设图片是正确的)。
- 您希望将这 3 个输出合并为一个包含 3 个步骤的序列,形状为
(1,3,10)
- 您希望处理此 3 步序列的 LSTM 也返回一个 3 步序列
为滑动窗口案例做准备:
在滑动窗口的情况下,重复数据是不可避免的。您需要首先处理您的输入。
采用初始时间序列(1,5000,1),我们需要将其拆分为包含 3 组 1000 个样本的批次。这里我只为 X 执行此操作,您必须对 Y 执行类似的操作
numberOfOriginalSequences = 1
totalSteps = 5000
features = 1
#example of original input with 5000 steps
originalSeries = np.array(
range(numberOfOriginalSequences*totalSteps*features)
).reshape((numberOfOriginalSequences,
totalSteps,
features))
windowSize = 3000
windowStride = 1000
totalWindowSteps = ((totalSteps - windowSize)//windowStride) + 1
#at first, let's keep these dimensions for better understanding
processedSequences = np.empty((numberOfOriginalSequences,
totalWindowSteps,
windowSize,
features))
for seq in range(numberOfOriginalSequences):
for winStep in range(totalWindowSteps):
start = winStep * windowStride
end = start + windowSize
processedSequences[seq,winStep,:,:] = originalSeries[seq,start:end,:]
#now we reshape the array to transform each window step in independent sequences:
totalSamples = numberOfOriginalSequences*totalWindowSteps
groupsInWindow = windowSize // windowStride
processedSequences = processedSequences.reshape((totalSamples,
groupsInWindow,
windowStride,
features))
print(originalSeries)
print(processedSequences)
创建模型:
关于你的第一个添加层的一些信息:
- 模型只考虑了一个
input_shape。这个形状是(groupsInWindow,windowStride,features)。它应该在最外部的包装器中:TimeDistributed。
- 您不想保留 1000 个时间步,只需要 10 个结果特征:
return_sequences = False。 (如果你想要更多的层,你可以在第一阶段使用许多LSTM。在这种情况下,第一个可以保留步骤,只有最后一个需要使用return_sequences=False)
- 你想要 10 个功能,所以
units=10
我将使用函数式 API 来查看摘要中的输入形状,这有助于理解事物。
from keras.models import Model
intermediateFeatures = 10
inputTensor = Input((groupsInWindow,windowStride,features))
out = TimeDistributed(
Bidirectional(
LSTM(intermediateFeatures,
return_sequences=False,
recurrent_dropout=0.1,
unit_forget_bias=True),
merge_mode='sum'))(inputTensor)
此时,您已经消除了 1000 个时间步。由于我们使用了return_sequences=False,因此不需要展平或类似的东西。数据已经形成(samples, groupsInWindow,intermediateFeatures) 的形式。 Dense 层也不是必需的。但是,如果您想按照自己的方式进行操作,就不会“错”,只要最终的形状相同。
arbitraryLSTMUnits = 12
n_classes = 17
out = Bidirectional(
LSTM(arbitraryLSTMUnits,
return_sequences=True,
recurrent_dropout=0.1,
unit_forget_bias=True),
merge_mode='sum')(out)
out = TimeDistributed(Dense(n_classes, activation='softmax'))(out)
如果要舍弃边框,可以添加这一层:
out = Lambda(lambda x: x[:,1,:])(out) #model.add(Lambda(lambda x: x[:,1,:]))
完成模型:
model = Model(inputTensor,out)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()
以下是维度在此模型中的流动方式。
我放在这里的第一个维度(totalSamples)在model.summary() 中显示为None。
- 输入:
(totalSamples,groupsInWindow,windowStride,features)
- 时间分布式 LSTM 的工作原理如下:
- TimeDistributed 允许第 4 个维度,即
groupsInWindow。
这个维度将被保留。
- 带有
return_sequences=False 的LSTM 将消除windowStride 并改变特征(windowStride,倒数第二个维度,位于此LSTM 的时间步长位置):
- 结果:
(totalSamples, groupsInWindow, intermadiateFeatures)
- 另一个没有时间分布的 LSTM,不会有第四维。这样,
groupsInWindow(倒数第二个)将是“时间步长”。但是return_sequences=True 不会像第一个 LSTM 那样消除时间步长。结果:(totalSamples, groupsInWindow, arbitraryLSTMUnits)
- 最后的
Dense 层,因为它接收 3D 输入,将把第二个维度解释为好像它是 TimeDistributed 并保持不变,仅将自身应用于特征维度。结果:(totalSamples, groupsInWindow, n_classes)