使用Conv1D

时间:2018-07-16 13:45:51

标签: python machine-learning keras

我目前在keras中拥有一个完全连接的自动编码器,如下所示:

model.add(Dense(4096, input_shape=(4096,), activation='relu'))
model.add(Dense(512, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(512, activation='relu'))
model.add(Dense(4096, activation='relu'))

数据由定时器序列数据组成,这些数据通过FFT转换为频域。

我的训练数据具有以下形状:(8000,4096),其中我有8000个样本,而4096个样本代表频率。这个模型工作正常。

我想要实现的是用Conv1d替换具有512个单位的两个密集层,以查看这是否可以改善我的结果,像这样:

model = Sequential()
model.add(Dense(4096, input_shape=(4096,), activation='relu'))
model.add(Conv1D(512,3, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Conv1D(512,3, activation='relu'))
model.add(Dense(4096, activation='relu'))

现在,这将不起作用,因为Conv1D期望我的数据具有3维:

Input 0 is incompatible with layer conv1d_12: expected ndim=3, found ndim=2

如何确保Conv1d图层获得正确的输入形状?

  1. 可能使用Model.add(Reshape(?,?,?)))?
  2. 以某种方式将输入数据重塑为3维?

我尝试将输入形状更改为“强制”第三维,然后在第一个Dense层和第一个Conv1D层之间重塑形状,但这似乎不起作用。

我意识到这里有很多关于Conv1D网络输入形状的问题,但是请注意,我不希望卷积滤波器跨越多个样本,而只是跨越频率值。

谢谢。

更新:在丹尼尔斯的建议下,我能够编译模型并开始训练(尽管我的GPU在向我尖叫)

Layer (type)                 Output Shape              Param #   
=================================================================
dense_132 (Dense)            (None, 4096)              16781312  
_________________________________________________________________
reshape_85 (Reshape)         (None, 4096, 1)           0         
_________________________________________________________________
conv1d_71 (Conv1D)           (None, 4096, 512)         2048      
_________________________________________________________________
reshape_86 (Reshape)         (None, 2097152)           0         
_________________________________________________________________
dense_133 (Dense)            (None, 64)                134217792 
_________________________________________________________________
reshape_87 (Reshape)         (None, 64, 1)             0         
_________________________________________________________________
conv1d_72 (Conv1D)           (None, 64, 512)           2048      
_________________________________________________________________
reshape_88 (Reshape)         (None, 32768)             0         
_________________________________________________________________
dense_134 (Dense)            (None, 4096)              134221824 
=================================================================
Total params: 285,225,024
Trainable params: 285,225,024
Non-trainable params: 0
_________________________________________________________________

但是,我希望我的Conv1d图层具有以下输出形状:

conv1d_71 (Conv1D)           (None, 512, 1)

我是在错误尺寸上进行卷积吗?如果是这样,我该如何更改呢?还是我误解了卷积层的工作原理?

1 个答案:

答案 0 :(得分:1)

方法1-通过密集层保持长度

这对于作为自动编码器来说不是很有用,因为它不会真正压缩数据,因为长度仍然为4096。

这应该是自动运行的,但是您似乎有一个旧的keras版本。

与您一样,在第一次卷积之前将其重塑为(4096,1)
然后Dense层应该可以正常工作。如果没有,请使用TimeDistributed(Dense(...))

为简便起见,请考虑在卷积中使用padding='same'

最后一层应类似于Conv1D(1,...),而不是Dense。 最后用(4096,)重塑。

方法2-不要保持篇幅

第一次转换后,您应该对其进行重塑以删除3D尺寸,但是请注意,您已经:

  • 频道:512
  • 长度:
    • 如果使用padding='same':4096
    • 其他:4094

然后,您应该将其重塑为(4096*512,),这相当大,并且将大大增加模型中可训练参数的数量。

在下一次转换之前,再次到达(64,1),然后到(64*512,)(如果不使用填充则为62)。

您可以探索其中的混合。始终记住,如果使用最新的keras版本,则conv会像(batch, length, channels)一样工作,dens会像(batch, ...whatever..., units)一样工作。否则,您必须正确处理此...whatever...