python - 如何在 Keras 中设置一维卷积和 LSTM

标签 python keras time-series conv-neural-network lstm

我想使用 1D-Conv 层和 LSTM 层对 16 channel 400 步信号进行分类。

输入形状由以下部分组成:

  • X = (n_samples, n_timesteps, n_features),其中 n_samples=476n_timesteps=400n_features =16 是信号的样本数、时间步长和特征(或 channel )。

  • y = (n_samples, n_timesteps, 1)。每个时间步长都标有 0 或 1(二进制分类)。

我使用 1D-Conv 来提取时间信息,如下图所示。 F=32K=8 是过滤器和 kernel_size。 1D-MaxPooling 在 1D-Conv 之后使用。 32 单元 LSTM 用于信号分类。该模型应返回 y_pred = (n_samples, n_timesteps, 1)

enter image description here

代码片段如下所示:

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) 

模型总结如下图:

enter image description here

但是,我得到了以下错误:

ValueError: Error when checking target: expected dense_15 to have 2 dimensions, but got array with shape (476, 400, 1).

我想问题是形状不正确。请让我知道如何修复它。

另一个问题是时间步数。因为 input_shape 是在 1D-Conv 中分配的,我们如何让 LSTM 知道时间步长必须是 400?


我想根据@today的建议添加模型图。在这种情况下,LSTM 的时间步长将为 98。在这种情况下我们需要使用 TimeDistributed 吗?我未能在 Conv1D 中应用 TimeDistributed。

enter image description here

有没有办法在 channel 之间执行卷积,而不是时间步长?例如,过滤器 (2, 1) 遍历每个时间步,如下图所示。 enter image description here

谢谢。

最佳答案

如果您想为每个时间步长预测一个值,我想到了两种略有不同的解决方案:

1) 移除MaxPooling1D层,将padding='same'参数添加到Conv1D层并向 LSTM 添加 return_sequence=True 参数,以便 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)只需将 Dense 层中的单元数更改为 400,并将 y reshape 为 (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 层它被包裹在 TimeDistributed 层内。或者另一种解决方案是展平最后两个轴。

关于python - 如何在 Keras 中设置一维卷积和 LSTM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51344610/

相关文章:

time-series - 在 Stata/SAS 中创建带有缺失值的运行平均值

Python 中止后无限循环

python - 将 pd.DataFrame Styler 对象的背景渐变色图居中

machine-learning - 如何在 Keras 上仅加载特定权重

python - Keras 嵌入, "weights"参数在哪里?

python - 是否有 pandas 自相关图方法的 Bokeh 版本?

python - key_name 中包含哪些字符?

python - Peewee CompressedField 在 MySQL 数据库上被截断

python - 如果 Keras 结果不可重复,比较模型和选择超参数的最佳实践是什么?

基于 Mysql json 的趋势​​标签实现