【问题标题】:How to setup 1D-Convolution and LSTM in Keras如何在 Keras 中设置一维卷积和 LSTM
【发布时间】:2018-12-22 23:38:39
【问题描述】:

我想使用 1D-Conv 层和 LSTM 层来分类 16 通道 400 时间步长的信号。

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

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

  • 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)

sn-p代码如下:

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).

我猜问题是形状不正确。请告诉我如何解决它。

另一个问题是时间步数。因为input_shape是在1D-Conv中赋值的,怎么让LSTM知道timestep一定是400呢?


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

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

谢谢。

【问题讨论】:

  • 难道你需要使用“TimeDistributed(Dense(1”)而不是“Dense(1”)?
  • 回答您问题的最后一部分。由于数学运算的性质,理论上卷积将输入减少了一定的因素。为了解决这个问题,您需要使用填充。即在 CONV1D 中设置填充 padding='same'
  • @GurmeetSingh 要应用TimeDistributed,LSTM 层的return_sequences 参数必须等于True。即使在这样做之后TimeDistributed(Dense(1))Dense(1) 相同。

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


【解决方案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) 只需将 Dense 层中的单元数改为 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),一种解决方案是使用包裹在 TimeDistributed 层内的 LSTM 层。或者另一种解决方案是展平最后两个轴。

【讨论】:

  • 感谢您的回复。在模型 2 中,我假设 LSTM 的时间步长与 max_pooling1d_5 的大小相同,即 98。我们需要一个 400 单位的 Dense 来将 32 单位的 LSTM 的输出转换为对应于 y 的 (400, 1) 向量。您能否通过查看我在上面帖子中添加的图片来确认这一点?无论如何要在 16 个通道之间执行卷积,而不是 400 个时间步长?过滤器大小将是 (kernel_size, 1),它遍历每个时间步。请参阅添加的第二张图片。谢谢。
  • @ThuanN。你提到的一点是完全正确的。更准确地说,它被转换为形状(400,)(这就是为什么我说你需要重塑y 或者只是删除最后一个轴)。至于内核大小为 1 的卷积:是的,您绝对可以这样做。这在视觉 CNN 中很常见。甚至您可以在此之后添加另一个卷积层,其内核大小大于 1。它或多或少与视觉 CNN 中的“Inception”模块相同。至于 TimeDistributed 的使用:不,你不需要使用它,也不能在解决方案 #2 中使用它,因为 LSTM 的输出形状是(None, 32)
  • @ThuanN。阅读我的 comment 回复 GurmeetSingh。
  • 如果进行通道间的卷积,需要转置数据集,即(None, 400, 16) -> (None, 16, 400),还是需要使用conv2D?你能为这种方法展示一些sn-ps吗?谢谢。
  • @ThuanN。你的意思是如果有 16 个通道,那么你想要一个内核大小为 1 的卷积层(即只覆盖一个时间步长),并且 16 个通道中的每一个通道都有 16 个单独的过滤器?
【解决方案2】:

输入和输出形状是 (476, 400, 16) 和 (476, 1) - 这意味着每个完整序列只输出一个值。

您的 LSTM 没有返回序列(return_sequences = False)。但即使你在 LSTM 之前进行 Conv1D 和 MaxPooling 也会挤压输入。所以 LSTM 本身会得到一个 (98,32) 的样本。

我假设您希望每个输入步骤都有一个输出。

假设 Conv1D 和 MaxPooling 与输入数据相关,您可以尝试 seq to seq 方法,将第一个 N/w 的输出提供给另一个网络以获取 400 个输出。

我建议你看看下面的一些模型,如编码器解码器 seq2seq 网络

https://blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html

https://machinelearningmastery.com/define-encoder-decoder-sequence-sequence-model-neural-machine-translation-keras/

【讨论】:

    猜你喜欢
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 2018-06-16
    • 2016-12-04
    • 1970-01-01
    • 2018-10-04
    相关资源
    最近更新 更多