【问题标题】:Replacing one layer in a Dense autoencoder with Conv1D用 Conv1D 替换密集自动编码器中的一层
【发布时间】:2018-07-17 15:17:33
【问题描述】:

我目前在 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 转换为频域的 timerseries 数据组成。

我的训练数据具有以下形状:(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)

我是否在错误的维度上进行卷积?如果是这样,我该如何改变呢?还是我误解了卷积层的工作原理?

【问题讨论】:

  • 将您的输入重塑为 3D:model.add(Reshape(input_shape=(4096,), target_shape=(4096, 1)))
  • 谢谢 Primusa,但您在这里展示的鳕鱼不会提供 2D 输出吗?例如,目标形状必须是 (4096,1,) 或可能是 (4096,1,1) ?无论如何,我试着让你知道
  • keras 将第一个维度推断为批量大小,您实际上正在重塑为 (batch_size, 4096, 1)
  • @Primusa 啊,我明白了,那是有道理的。您将在哪里添加此方法?我尝试在第一个 conv1d 之前进行整形,但随后 Dense 层抛出了尺寸错误,我似乎不允许在第一个 conv1d 之后更改形状。 (新的数组大小必须相同)
  • 第一层,这就是指定 input_shape 的原因。您可能需要在输出期间将其重新整形为 2D 输入

标签: python machine-learning keras


【解决方案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 版本,convs 将作为 (batch, length, channels) 工作,而 denses 将作为 (batch, ...whatever..., units) 工作。如果不是,你必须正确对待这个...whatever...。

【讨论】:

  • 感谢丹尼尔的彻底回答。我现在正试图解决这个问题,对我来说,我似乎在错误的轴上应用了卷积滤波器。我可能误解了卷积网络的工作原理,我将用一些额外的信息更新我原来的问题。
猜你喜欢
  • 2019-05-14
  • 2020-12-03
  • 2018-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 2021-09-07
  • 2017-05-18
相关资源
最近更新 更多