Python 如何将多个时间序列输入keras中的LSTM

Python 如何将多个时间序列输入keras中的LSTM,python,keras,classification,lstm,Python,Keras,Classification,Lstm,我有大约1000个节点数据集,其中每个节点有4个时间序列。每个时间序列的长度正好为6。标签为0或1(即二进制分类) 更准确地说,我的数据集如下所示 node, time-series1, time_series2, time_series_3, time_series4, Label n1, [1.2, 2.5, 3.7, 4.2, 5.6, 8.8], [6.2, 5.5, 4.7, 3.2, 2.6, 1.8], …, 1 n2, [5.2, 4.5, 3.7, 2.2, 1.6, 0.8]

我有大约1000个节点数据集,其中每个节点有4个时间序列。每个时间序列的长度正好为6。标签为
0
1
(即二进制分类)

更准确地说,我的数据集如下所示

node, time-series1, time_series2, time_series_3, time_series4, Label
n1, [1.2, 2.5, 3.7, 4.2, 5.6, 8.8], [6.2, 5.5, 4.7, 3.2, 2.6, 1.8], …, 1
n2, [5.2, 4.5, 3.7, 2.2, 1.6, 0.8], [8.2, 7.5, 6.7, 5.2, 4.6, 1.8], …, 0
and so on.
# create the model
model = Sequential()
model.add(Embedding(5000, 32, input_length=24))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
因为我有时间序列,我假设它更像是序列分类,大多数博客文章都使用了LSTM。我以前从未使用过LSTMs,这将是我的第一个keras应用程序。因此,我开始使用最基本的
顺序LSTM
模板,如下所示

node, time-series1, time_series2, time_series_3, time_series4, Label
n1, [1.2, 2.5, 3.7, 4.2, 5.6, 8.8], [6.2, 5.5, 4.7, 3.2, 2.6, 1.8], …, 1
n2, [5.2, 4.5, 3.7, 2.2, 1.6, 0.8], [8.2, 7.5, 6.7, 5.2, 4.6, 1.8], …, 0
and so on.
# create the model
model = Sequential()
model.add(Embedding(5000, 32, input_length=24))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
但是,我很难理解如何使用
嵌入
层向LSTM输入四个时间序列。我是否可以使用四个
嵌入层
或有其他方法解决此问题


如果需要,我很乐意提供更多细节。

您可以将每个节点内的每个序列视为单独的通道。因此,首先,将数据重塑为n_样本(我认为您称之为节点)、n_步骤和n_通道。对于您拥有的数据集,
n_步骤=6
n_通道=4
。基本上,您是在每个样本(节点)上堆叠不同的时间序列数据

然后,您可以创建您的LSTM模型。大概是这样的:

model = Sequential()
model.add(LSTM(64, input_shape=(6, 4), activation='sigmoid'))
model.add(Dense(1))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model = Sequential()
model.add(LSTM(64, input_shape=(6, 4), return_sequences=True))
model.add(LSTM(1, input_shape=(6, 4)))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
请注意,可以使用LSTM进行不同的激活,并且不一定需要密集层。但密集层是一个额外的非线性层,可能会提高性能

您还可以堆叠LSTM层以获得更复杂的模型,如下所示:

model = Sequential()
model.add(LSTM(64, input_shape=(6, 4), activation='sigmoid'))
model.add(Dense(1))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model = Sequential()
model.add(LSTM(64, input_shape=(6, 4), return_sequences=True))
model.add(LSTM(1, input_shape=(6, 4)))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())

有几种方法可以构建此结构。首先,我可能只是将4个系列展平为24个数字的数组,并使用密集层

from keras.models import Sequential
from keras.layers import Dense

model = Sequential()
model.add(Dense(32, input_shape=24))
model.add(Dense(32))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

print(data.shape) # (1000, 24)
model.fit(data, target)
您可以有4个单独的输入,分别使用
LSTM
层处理4个系列。但是您需要使用函数式API。e、 g

input1 = Input(shape=(6,1))
x1 = LSTM(10)(input1)
input2 = Input(shape=(6,1))
x2 = LSTM(10)(input2)
input3 = Input(shape=(6,1))
x3 = LSTM(10)(input3)
input4 = Input(shape=(6,1))
x4 = LSTM(10)(input4)

x = concatenate([x1,x2,x3,x4])
x = Drouput(0.2)(x)
x = Dense(40)(x)
x = Drouput(0.2)(x)
output = Dense(1, activation='sigmoid')(x)

model = Model(inputs=[input1,input2,input3,input4], outputs=output)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

print(data1.shape) #(1000,6,1)
model.fit([data1,data2,data3,data4], target)
或者,如果数据的形状为
(1000,6,4)
,则可以使用一个LSTM,并将每个序列视为单独的特征

model = Sequential()
model.add(LSTM(10, input_shape=(6,4)))
model.add(Dense(32))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

print(data.shape) # (1000, 6, 4)
model.fit(data, target)
或者你可以用CNN代替RNN

model = Sequential()
model.add(Conv1D(10, kernel_size=3, input_shape=(6,4)))
model.add(Conv1D(10, kernel_size=2))
model.add(GlobalMaxPooling1D())
model.add(Dense(10))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

print(data.shape) # (1000, 6, 4)
model.fit(data, target)

非常感谢你的回答。这正是我想要的。我真的很喜欢你关于使用
functional
api的建议。顺便问一下,对于初始启动,您认为我的数据量小吗(即仅考虑1000个节点)?我的另一个问题是,在函数式api模型中是否可以有
退出
层?如果是,怎么做?:)我在第二个示例中添加了几个退出层。我还意识到它没有输出层。是的,数据可能不够。取决于问题,但我认为不使用LSTM的第一个和最后一个示例更有可能在数据较少的情况下成功。还要注意,如果使用函数示例,则序列中的每个数字都需要包装在其自己的数组中。e、 g.
[[1.2]、[2.5]、[3.7]、[4.2]、[5.6]、[8.8]
,因为LSTM期望一系列1D矢量对有价值的细节进行大量分析。我会在周末运行模型,如果我遇到任何问题,我会告诉你。再次非常感谢:)