如何将TimeDsitributed层用于神经网络集成(特别是CNN + LSTM)?

时间:2020-05-29 11:44:35

标签: python keras deep-learning lstm cnn

这是我尝试的两种方法中的第一种:

inputs=Input(shape=(frames, 103*4, 1))

z=TimeDistributed(Conv2D(32, (5,25), padding='same', activation='relu'), input_shape=(frames, 103*4, 1))(inputs)
z=TimeDistributed(BatchNormalization())(z)
z=TimeDistributed(ReLU())(z)
z=TimeDistributed(Dropout(0.2))(z)
z=TimeDistributed(MaxPooling2D(pool_size=(1,2)))(z)

z=TimeDistributed(Conv2D(32, (3,5), padding='same', activation='relu'))(z)
z=TimeDistributed(BatchNormalization())(z)
z=TimeDistributed(ReLU())(z)
z=TimeDistributed(Dropout(0.2))(z)
z=TimeDistributed(MaxPooling2D(pool_size=(1,2)))(z)

z=TimeDistributed(Flatten())(z)

z=LSTM(1000, dropout=0.1, recurrent_dropout=0.2, return_sequences=True)(z)
z=LSTM(1000, dropout=0.1, recurrent_dropout=0.2, return_sequences=True)(z)
z=LSTM(1000, dropout=0.1, recurrent_dropout=0.2, return_sequences=True)(z)

z=Flatten()(z)

z=Dense(1000, activation='relu')(z)
z=Dropout(0.5)(z)

z=Dense(500, activation='relu')(z)
z=Dropout(0.5)(z)

z=Dense(200, activation='relu')(z)
z=Dropout(0.5)(z)

outputs=Dense(88, activation='sigmoid')(z)

我遇到此错误(尽管我在代码中的任何地方都没有2个跨度的大步):

ValueError: strides should be of length 1, 1 or 3 but was 2

我已经看过this question,并且似乎已经实现了代码中给出的建议。但是有什么问题呢?我无法理解。

最后,我通过Keras的FunctionalAPI设法将CNN和LSTM相结合:

inputs=Input(shape=(frames, 103*4, 1))

z=Conv2D(32, (5,25), padding='same', activation='relu')(inputs)
z=BatchNormalization()(z)
z=ReLU()(z)
z=Dropout(0.2)(z)
z=MaxPooling2D(pool_size=(1,2))(z)

z=Conv2D(32, (3,5), padding='same', activation='relu')(z)
z=BatchNormalization()(z)
z=ReLU()(z)
z=Dropout(0.2)(z)
z=MaxPooling2D(pool_size=(1,2))(z)

z=TimeDistributed(Flatten())(z)

z=LSTM(1000, dropout=0.1, recurrent_dropout=0.2, return_sequences=True)(z)
z=LSTM(1000, dropout=0.1, recurrent_dropout=0.2, return_sequences=True)(z)
z=LSTM(1000, dropout=0.1, recurrent_dropout=0.2, return_sequences=True)(z)

z=Flatten()(z)

z=Dense(1000, activation='relu')(z)
z=Dropout(0.5)(z)

z=Dense(500, activation='relu')(z)
z=Dropout(0.5)(z)

z=Dense(200, activation='relu')(z)
z=Dropout(0.5)(z)

outputs=Dense(88, activation='sigmoid')(z)


model=Model(inputs=inputs, outputs=outputs)

它可以工作,但是如果这是正确的方法,我仍然很茫然。我可以通过model.summary()看到我的TimeDstributed包装器具有输出形状(None, 7, 3296),并且所有LSTM层都具有输出形状(None, 7, 1000)。我应该怎么做才能使其居中而不是7帧?

说到我的数据集,我给出了7个频率值幅度的帧,以预测中心帧中的值。

2 个答案:

答案 0 :(得分:0)

我假设您要在帧维度上应用TimeDistributed层,这将使我们的输入为2维,并将其发送到卷积层。 如果是这种情况,则应使用Conv1D而不是Conv2D。相应地更改内核大小。 还要相应地将Maxpooling2D更改为Maxpooling1D。

例如。

z=TimeDistributed(Conv1D(32, 2, padding='same', activation='relu'))(inputs)

答案 1 :(得分:0)

@priyach你是对的,但是正如我所看到的,我对我的数据集的解释有些糟糕。我有2d数组,x轴上有时间,y轴上有频率(试图根据给定的频率信息来预测正在演奏的音符)

因此,如果我将2d阵列的列(每个列代表给定时间的所有频率)馈入网络,那么Conv1D和MaxPooling1D将是正确的选择

但是我不是将列作为输入,而是将每列分别填充到其左侧的3个列和右侧的3个列(或者使用零填充则无法获取列)。因此,我的输入基本上是2d,并将其视为图像。

我设法创建了另一个网络(CNN + DNN + LSTM + DNN),并在第一个LSTM层之前使用了Reshape层(而不是TimeDistributed)。

问题仍然存在(出于好奇和出于将来的编程考虑)。我对TimeDistributed层的使用有什么问题?

相关问题