我想使用1D CONV层跟随LSTM层分类16通道400的时间步长信号。
输入形状由以下部分组成:X = (n_samples, n_timesteps, n_features)
,其中n_samples=476
,n_timesteps=400
,n_features=16
是信号的样本数量、时间步长和特征(或通道)。y = (n_samples, n_timesteps, 1)
每一个标记都被标记为0或1(二进制分类)。
我使用1d conv提取时间信息,如下图所示。F=32
和K=8
是过滤器和内核大小。在1D-CONV之后使用1D最大池。32单元LSTM用于信号分类。模型应该返回一个y_pred = (n_samples, n_timesteps, 1)
。
代码段如下所示:
input_layer = Input(shape=(dataset.n_timestep, dataset.n_feature))
conv1 = Conv1D(filters=32,
kernel_size=8,
strides=1,
activation='relu')(input_layer)
pool1 = MaxPooling1D(pool_size=4)(conv1)
lstm1 = LSTM(32)(pool1)
output_layer = Dense(1, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer)
模型概要如下:
但是,我得到了以下错误:
ValueError: Error when checking target: expected dense_15 to have 2 dimensions, but got array with shape (476, 400, 1).
我想问题是形状不对。请告诉我怎么修理它。
另一个问题是时间步长。因为在1D CONV中分配了
input_shape
,如何让LSTM知道时间步长必须是400?我想根据@today的建议添加模型图。在这种情况下,LSTM的时间步长为98。在这种情况下,我们需要使用时间分布吗?我没能应用在conv1d中分配的时间。
不管怎样,都要执行通道之间的卷积,而不是时间步长吗?例如,滤波器(2, 1)遍历每个时间步长,如下图所示。
谢谢。
最佳答案
如果你想为每一个时间步预测一个值,我会想到两个稍微不同的解决方案:
1)删除MaxPooling1D
层,将padding='same'
参数添加到Conv1D
层,并将return_sequence=True
参数添加到LSTM,使LSTM返回每一个时间步的输出:
from keras.layers import Input, Dense, LSTM, MaxPooling1D, Conv1D
from keras.models import Model
input_layer = Input(shape=(400, 16))
conv1 = Conv1D(filters=32,
kernel_size=8,
strides=1,
activation='relu',
padding='same')(input_layer)
lstm1 = LSTM(32, return_sequences=True)(conv1)
output_layer = Dense(1, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer)
model.summary()
模型总结将是:
Layer (type) Output Shape Param #
=================================================================
input_4 (InputLayer) (None, 400, 16) 0
_________________________________________________________________
conv1d_4 (Conv1D) (None, 400, 32) 4128
_________________________________________________________________
lstm_4 (LSTM) (None, 400, 32) 8320
_________________________________________________________________
dense_4 (Dense) (None, 400, 1) 33
=================================================================
Total params: 12,481
Trainable params: 12,481
Non-trainable params: 0
_________________________________________________________________
2)只需将密集层中的单元数更改为400,然后将
y
重新形状为(n_samples, n_timesteps)
:from keras.layers import Input, Dense, LSTM, MaxPooling1D, Conv1D
from keras.models import Model
input_layer = Input(shape=(400, 16))
conv1 = Conv1D(filters=32,
kernel_size=8,
strides=1,
activation='relu')(input_layer)
pool1 = MaxPooling1D(pool_size=4)(conv1)
lstm1 = LSTM(32)(pool1)
output_layer = Dense(400, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer)
model.summary()
模型总结将是:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_6 (InputLayer) (None, 400, 16) 0
_________________________________________________________________
conv1d_6 (Conv1D) (None, 393, 32) 4128
_________________________________________________________________
max_pooling1d_5 (MaxPooling1 (None, 98, 32) 0
_________________________________________________________________
lstm_6 (LSTM) (None, 32) 8320
_________________________________________________________________
dense_6 (Dense) (None, 400) 13200
=================================================================
Total params: 25,648
Trainable params: 25,648
Non-trainable params: 0
_________________________________________________________________
不要忘记,在这两种情况下,必须使用
'binary_crossentropy'
(而不是'categorical_crossentropy'
)作为损失函数。我希望这个解决方案的精度比解1的精度要低,但是你必须同时试验这两个参数并尝试改变参数,因为它完全取决于你要解决的具体问题和你所拥有的数据的性质。更新:
你需要一个卷积层,它只覆盖一个时间步长和k个相邻特征。是的,您可以使用conv2d层:
# first add an axis to your data
X = np.expand_dims(X) # now X has a shape of (n_samples, n_timesteps, n_feats, 1)
# adjust input layer shape ...
conv2 = Conv2D(n_filters, (1, k), ...) # covers one timestep and k features
# adjust other layers according to the output of convolution layer...
虽然我不知道为什么要这样做,但是要使用卷积层(即
(?, n_timesteps, n_features, n_filters)
)的输出,一个解决方案是使用一个封装在时间分布层中的lstm层。或者另一个解决方案是使最后两个轴变平。关于python - 如何在Keras中设置1D卷积和LSTM,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51344610/