How to correctly get layer weights from Conv2D in keras?

Vladimir Tsyshnatiy picture Vladimir Tsyshnatiy · Apr 9, 2017 · Viewed 13.1k times · Source

I have Conv2D layer defines as:

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')

This is the first layer in my network.
Input dimensions are 64 by 160, image is 1 channel.
I am trying to visualize weights from this convolutional layer but not sure how to get them.
Here is how I am doing this now:

1.Call

layer.get_weights()[0]

This returs an array of shape (5, 5, 1, 96). 1 is because images are 1-channel.

2.Take 5 by 5 filters by

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

Very ugly but I am not sure how to simplify this, any comments are very appreciated.

I am not sure in these 5 by 5 squares. Are they filters actually?
If not could anyone please tell how to correctly grab filters from the model?

Answer

John picture John · May 10, 2017

I tried to display the weights like so only the first 25. I have the same question that you do is this the filter or something else. It doesn't seem to be the same filters that are derived from deep belief networks or stacked RBM's.

Here is the untrained visualized weights:untrained weights

and here are the trained weights:

trained weights

Strangely there is no change after training! If you compare them they are identical.

and then the DBN RBM filters layer 1 on top and layer 2 on bottom: DBM RBM filters

If i set kernel_intialization="ones" then I get filters that look good but the net loss never decreases though with many trial and error changes: enter image description here

Here is the code to display the 2D Conv Weights / Filters.

  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()

---------------------------UPDATE------------------------

So I tried it again with a learning rate of 0.01 instead of 1e-6 and used the images normalized between 0 and 1 instead of 0 and 255 by dividing the images by 255.0. Now the convolution filters are changing and the output of the first convolutional filter looks like so: Untrained Weights

The trained filter you'll notice is changed (not by much) with a reasonable learning rate:Trained Convolution Filter

Here is image seven of the CIFAR-10 test set:Image 7 CIFAR-10 Car

And here is the output of the first convolution layer: Convolution Layer Output

And if I take the last convolution layer (no dense layers in between) and feed it to a classifier untrained it is similar to classifying raw images in terms of accuracy but if I train the convolution layers the last convolution layer output increases the accuracy of the classifier (random forest).

So I would conclude the convolution layers are indeed filters as well as weights.