如何在Keras中正确获取Conv2D的层权重?

18

我有一个被定义为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')

这是我的网络中的第一层。
输入尺寸为64x160,图像为1通道。
我正在尝试可视化这个卷积层中的权重,但不确定如何获取它们。
这是我现在的方法:

1.调用

layer.get_weights()[0]

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

2.通过取5乘5的过滤器

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

这个看起来很丑陋,但我不确定如何简化它,非常欢迎任何评论。

我不确定这5 x 5的方块是不是滤镜?
如果不是,请问如何正确地从模型中获取滤镜?

2个回答

20

我试图仅显示前25个权重。与你一样,我也有同样的疑问,这是过滤器还是其他内容。它似乎不是从深度置信网络或叠加RBM中得出的相同过滤器。

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

这是经过训练的权重:

trained weights

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

然后是DBN RBM过滤层1在上面,层2在下面: DBM RBM filters

如果我设置kernel_intialization="ones",那么我会得到看起来很好的过滤器,但是遗憾的是损失函数永远不会减少,尽管做出了许多试错性的更改:

enter image description here

这是显示二维卷积权重/过滤器的代码。

  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,并且使用图像在0到1之间经过归一化,而不是通过将图像除以255.0来使其在0到255之间。现在卷积滤波器正在改变,第一个卷积滤波器的输出如下所示: 未训练的权重

你会注意到,经过合理的学习率训练后,训练后的滤波器发生了变化(虽然变化不大):经过训练的卷积滤波器

这是CIFAR-10测试集中的第七张图片:Image 7 CIFAR-10 Car

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

如果我将最后一个卷积层(中间没有稠密层)提取出来并将其馈送给未经训练的分类器,它与原始图像的分类准确率相似,但是如果我训练卷积层,则最后一个卷积层的输出会提高分类器(随机森林)的准确性。

因此,我得出结论,卷积层不仅是权重,还是滤波器。


感谢您的回答!这里真是个奇怪的事情:在随机初始化的情况下,权重非常相似。我正在使用Glorot初始化方法,这是卷积层推荐的方法。对于我最困惑的问题是:我们正在训练网络,但是却遇到了相同的权重。那么我们到底训练了什么?这个问题我无法回答... - Vladimir Tsyshnatiy
那么权重的第三个维度是什么?在x1w = x.get_weights()[0][:,:,0,:]中,[:,:,0,:]中的0。我认为前两个维度是卷积核的x和y,最后一个是卷积核的数量-但我不知道第三个维度是什么。它似乎是上一层输出的维度,但我不明白为什么或者这真正意味着什么。 - wordsforthewise
0 是红色通道。三个维度分别是红、绿和蓝。第一个是 x,第二个是 y,第三个是通道,最后一个是第 n 个卷积层。 - John

2
在layer.get_weights()[0][:,:,:,:]中,[:,:,:,:]中的维度分别表示权重的x位置,y位置,对应卷积层的第n个输入(来自前一层,注意如果你想获取第一个卷积层的权重,则该数字为1,因为只有一个输入被驱动到第一个卷积层),以及相应层中的第k个过滤器或内核。因此,由layer.get_weights()[0]返回的数组形状可以解释为只有一个输入被驱动到该层,并生成了96个大小为5x5的过滤器。如果你想要访问其中一个过滤器,例如第6个过滤器,你可以键入print(layer.get_weights()[0][:,:,:,6].squeeze())。然而,如果你需要第二个卷积层的过滤器(请参见下面附加的模型图像链接),则需要注意每个32个输入图像或矩阵都会有64个过滤器。如果你想获取其中任何一个的权重,例如第8个输入图像生成的第4个过滤器的权重,则应键入print(layer.get_weights()[0][:,:,8,4].squeeze())。enter image description here

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接