python中tf.keras.layers.Conv2D所用的卷积核是什么?

Conv2D里面的参数也只是设置了卷积核的大小和其余必要属性,并没有说卷积核是什么类型的(ps:类似拉普拉斯算子这些)
关注者
7
被浏览
11,974

2 个回答

有默认的初始化方式,例如: kernel_initializer="glorot_uniform",

当然也可以自定义初始化:

from tensorflow.keras import layers
from tensorflow.keras import initializers
layer = layers.Dense(
    units=64,
    kernel_initializer=initializers.RandomNormal(stddev=0.01),
    bias_initializer=initializers.Zeros()
)

自定义卷积核的形状

>>> # Standalone usage:  
>>> initializer = tf.keras.initializers.RandomNormal(mean=0., stddev=1.)
>>> values = initializer(shape=(2, 2))

卷积核刚开始当然是随机数

keras默认用Xavier的初始化策略

这里不是像拉普拉斯算子这种手工设计的卷积核

而是由网络训练逐渐训练出来

如果要手工设计卷积核并计算

可以用tf.nn.conv2d来传入一个初始化好的卷积核

tf.nn.conv2d(input, filter=None, strides=None, padding=None, use_cudnn_on_gpu=True, data_format='NHWC', dilations=[1, 1, 1, 1], name=None, filters=None)
Computes a 2-D convolution given 4-D `input` and `filter` tensors.
    Given an input tensor of shape `[batch, in_height, in_width, in_channels]`
    and a filter / kernel tensor of shape
    `[filter_height, filter_width, in_channels, out_channels]`, this op
    performs the following:
    1. Flattens the filter to a 2-D matrix with shape
       `[filter_height * filter_width * in_channels, output_channels]`.
    2. Extracts image patches from the input tensor to form a *virtual*
       tensor of shape `[batch, out_height, out_width,
       filter_height * filter_width * in_channels]`.
    3. For each patch, right-multiplies the filter matrix and the image patch
       vector.
'''

给个Tensorflow1.15的例子,这里我传入了一个拉普拉斯算子

from PIL import Image
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
tf.reset_default_graph()
inputs=1-np.array(Image.open("A.jpg").convert("L"),dtype="float32") #得到灰度图片
inputs=inputs.reshape([1]+list(inputs.shape)+[1])  #[1,400,400,1] #调整shape
filters=np.array([[0,-1,0],
                  [-1,4,-1],
                  [0,-1,0]])
filters=filters.reshape(list(filters.shape)+[1,1])
conv=tf.nn.conv2d(inputs,filters,strides=[1,1,1,1],padding="SAME")
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    result=sess.run(conv)
plt.imshow(inputs.squeeze(),cmap='binary')
plt.show()
plt.imshow(result.squeeze(),cmap='binary')
plt.show()

结果:

另一种方法就是用get_tensor_by_name来得到卷积核的Tensor,然后打印Tensor得到卷积核具体数值.

tf.keras.layers.Conv2D可以看成是对tf.nn.conv2d的封装.

class Conv(Layer):
  def __init__(self, rank,
               filters,
               kernel_size,
               strides=1,
               padding='valid',
               data_format=None,
               dilation_rate=1,
               activation=None,
               use_bias=True,
               kernel_initializer='glorot_uniform',
               bias_initializer='zeros',
               kernel_regularizer=None,
               bias_regularizer=None,
               activity_regularizer=None,
               kernel_constraint=None,
               bias_constraint=None,
               trainable=True,
               name=None,
               **kwargs):
    super(Conv, self).__init__(
        trainable=trainable,
        name=name,
        activity_regularizer=regularizers.get(activity_regularizer),
        **kwargs)
    self.filters = filters
    self._convolution_op = nn_ops.Convolution(
        input_shape,
        filter_shape=self.kernel.shape,
        dilation_rate=self.dilation_rate,
        strides=self.strides,
        padding=op_padding,
        data_format=conv_utils.convert_data_format(self.data_format,
                                                   self.rank + 2))
  def build(self, input_shape):
    ##这里为卷积核做了初始化
    self.kernel = self.add_weight(
        name='kernel',
        shape=kernel_shape,
        initializer=self.kernel_initializer,
        regularizer=self.kernel_regularizer,
        constraint=self.kernel_constraint,
        trainable=True,
        dtype=self.dtype)
    if self.use_bias:
      self.bias = self.add_weight(
          name='bias',
          shape=(self.filters,),
          initializer=self.bias_initializer,
          regularizer=self.bias_regularizer,
          constraint=self.bias_constraint,
          trainable=True,