如何正确从 keras 中的 Conv2D 获取层权重?

Posted

技术标签:

【中文标题】如何正确从 keras 中的 Conv2D 获取层权重?【英文标题】:How to correctly get layer weights from Conv2D in keras? 【发布时间】:2017-09-04 11:27:32 【问题描述】:

我将 Conv2D 层定义为:

Conv2D(96, kernel_size=(5, 5),
             activation='relu',
             input_shape=(image_rows, image_cols, 1),
             kernel_initializer=initializers.glorot_normal(seed),
             bias_initializer=initializers.glorot_uniform(seed),
             padding='same',
             name='conv_1')

这是我网络中的第一层。 输入尺寸为 64 x 160,图像为 1 通道。 我正在尝试从这个卷积层可视化权重,但不知道如何获得它们。 以下是我现在的做法:

1.调用

layer.get_weights()[0]

这会返回一个形状数组 (5, 5, 1, 96)。 1 是因为图像是 1 通道的。

2.采用 5 x 5 过滤器

layer.get_weights()[0][:,:,:,j][:,:,0]

非常难看,但我不知道如何简化这一点,非常感谢任何 cmets。

我不确定这些 5 x 5 的方格。它们实际上是过滤器吗? 如果不能,请告诉如何正确地从模型中抓取过滤器?

【问题讨论】:

【参考方案1】:

我试图只显示前 25 个的权重。我和你有同样的问题,这是过滤器还是其他东西。它似乎与源自深度信念网络或堆叠 RBM 的过滤器不同。

这是未经训练的可视化权重:

这里是训练好的权重:

奇怪的是训练后没有任何变化!如果你比较它们,它们是相同的。

然后 DBN RBM 在顶部过滤第 1 层,在底部过滤第 2 层:

如果我设置 kernel_initialization="ones" 那么我得到的过滤器看起来不错,但净损失永远不会减少,尽管有许多试验和错误的变化:

这是显示 2D Conv 权重/过滤器的代码。

  ann = Sequential()
  x = Conv2D(filters=64,kernel_size=(5,5),input_shape=(32,32,3))
  ann.add(x)
  ann.add(Activation("relu"))

...

  x1w = x.get_weights()[0][:,:,0,:]
  for i in range(1,26):
      plt.subplot(5,5,i)
      plt.imshow(x1w[:,:,i],interpolation="nearest",cmap="gray")
  plt.show()

  ann.fit(Xtrain, ytrain_indicator, epochs=5, batch_size=32)

  x1w = x.get_weights()[0][:,:,0,:]
  for i in range(1,26):
      plt.subplot(5,5,i)
      plt.imshow(x1w[:,:,i],interpolation="nearest",cmap="gray")
  plt.show()

---------------更新------- -----

所以我再次尝试使用 0.01 而不是 1e-6 的学习率,并通过将图像除以 255.0 来使用在 0 和 1 之间而不是 0 和 255 之间归一化的图像。现在卷积过滤器正在发生变化,第一个卷积过滤器的输出如下所示:

您会注意到经过训练的过滤器以合理的学习率发生了变化(变化不大):

这是 CIFAR-10 测试集的图片七:

这是第一个卷积层的输出:

如果我采用最后一个卷积层(中间没有密集层)并将其提供给未经训练的分类器,它类似于在准确性方面对原始图像进行分类,但如果我训练卷积层,最后一个卷积层输出会增加分类器的准确性(随机森林)。

所以我会得出结论,卷积层确实是过滤器和权重。

【讨论】:

感谢您的回答!这是一件非常奇怪的事情:在随机初始化的情况下,权重是相似的。我正在使用推荐用于转换层的 glorot 初始化。对我来说最困惑的问题是:我们正在训练网络,但权重相同。我们训练了什么?对此没有答案... 那么权重的第三维是什么?在x1w = x.get_weights()[0][:,:,0,:] 中,[:,:,0,:] 中的 0。我认为前两个维度是内核 x 和 y,最后一个是内核的数量——但我不知道第三维是什么。似乎是前一层输出的维度,但我不明白为什么或这究竟意味着什么。 0 是红色通道。三个维度是红绿蓝。第一个是x,第二个是y,第三个是channel,最后一个是第n个卷积层。【参考方案2】:

在layer.get_weights()[0][:,:,:,:]中,[:,:,:,:]中的维度是权重的x位置,权重的y位置,第n个输入到相应的卷积层(来自上一层,请注意,如果您尝试获得第一个卷积层的权重,则此数字为 1,因为只有一个输入被驱动到第一个卷积层)和第 k 个过滤器或内核分别对应的层。因此,layer.get_weights()[0] 返回的数组形状可以解释为只有一个输入被驱动到该层,并生成了 96 个 5x5 大小的过滤器。如果您想访问其中一个过滤器,您可以输入,比如说第 6 个过滤器 打印(layer.get_weights()[0][:,:,:,6].squeeze())。 但是,如果您需要第二个 conv 层的过滤器(请参阅下面附加的模型图像链接),那么请注意,对于 32 个输入图像或矩阵中的每一个,您将拥有 64 个过滤器。如果您想获得其中任何一个的权重,例如为第 8 个输入图像生成的第 4 个过滤器的权重,那么您应该输入 打印(layer.get_weights()[0][:,:,8,4].squeeze())。 enter image description here

【讨论】:

以上是关于如何正确从 keras 中的 Conv2D 获取层权重?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Conv2D 层中使用 keras 指定填充?

如何在 Tensorflow 2 中获取 Conv2D 内核值

具有 padding='SAME' 的 Tensorflow/Keras Conv2D 层表现异常

卷积层(CNN)如何在 keras 中工作?

Keras Conv2D 和输入通道

如何在一个图层模块中打包几个keras图层?