TensorFlow 之 keras.layers.Conv2D( ) 主要参数讲解

  keras.layers.Conv2D( ) 函数参数

    def __init__(self, filters,
                 kernel_size,
                 strides=(1, 1),
                 padding='valid',
                 data_format=None,
                 dilation_rate=(1, 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,
                 **kwargs):

参数:

filters 卷积核个数的变化,filters 影响的是最后输入结果的的第三个维度的变化,例如,输入的维度是 (600, 600, 3), filters 的个数是 64,转变后的维度是 (600, 600, 64)

>>> from keras.layers import (Input, Reshape)
>>> input = Input(shape=(600, 600, 3))
>>> x = Conv2D(64, (1, 1), strides=(1, 1), name='conv1')(input)
>>> x
<tf.Tensor 'conv1_1/BiasAdd:0' shape=(?, 600, 600, 64) dtype=float32>

kernel_size 参数 表示卷积核的大小,可以直接写一个数,影响的是输出结果前两个数据的维度,例如,(600, 600, 3)=> (599, 599, 64)

>>> from keras.layers import (Input, Conv2D)
>>> input = Input(shape=(600, 600, 3))
>>> Conv2D(64, (2, 2), strides=(1, 1), name='conv1')(input)
<tf.Tensor 'conv1/BiasAdd:0' shape=(?, 599, 599, 64) dtype=float32>

直接写 2 也是可以的

>>> from keras.layers import (Input, Conv2D)
>>> input = Input(shape=(600, 600, 3))
>>> Conv2D(64, 2, strides=(1, 1), name='conv1')(input)
<tf.Tensor 'conv1_2/BiasAdd:0' shape=(?, 599, 599, 64) dtype=float32>

strides  步长 同样会影响输出的前两个维度,例如,(600, 600, 3)=> (300, 300, 64),值得注意的是,括号里的数据可以不一致,分别控制横坐标和纵坐标,这里步长的计算公式为:

>>> from keras.layers import (Input, Conv2D)
>>> input = Input(shape=(600, 600, 3))
>>> Conv2D(64, 1, strides=(2, 2), name='conv1')(input)
<tf.Tensor 'conv1_4/BiasAdd:0' shape=(?, 300, 300, 64) dtype=float32>

padding 是否对周围进行填充,“same” 即使通过kernel_size 缩小了维度,但是四周会填充 0,保持原先的维度;“valid”表示存储不为0的有效信息。多个对比效果如下:

>>> Conv2D(64, 1, strides=(2, 2), padding="same", name='conv1')(input)
<tf.Tensor 'conv1_6/BiasAdd:0' shape=(?, 300, 300, 64) dtype=float32>
>>> Conv2D(64, 3, strides=(2, 2), padding="same", name='conv1')(input)
<tf.Tensor 'conv1_7/BiasAdd:0' shape=(?, 300, 300, 64) dtype=float32>
>>> Conv2D(64, 3, strides=(1, 1), padding="same", name='conv1')(input)
<tf.Tensor 'conv1_8/BiasAdd:0' shape=(?, 600, 600, 64) dtype=float32>
>>> Conv2D(64, 3, strides=(1, 1), padding="valid", name='conv1')(input)
<tf.Tensor 'conv1_9/BiasAdd:0' shape=(?, 598, 598, 64) dtype=float32>

通过这种最简单的方式,可以观察 ResNet50 的组成结构

 Conv Block 的架构:

def conv_block(input_tensor, kernel_size, filters, stage, block, strides):

    filters1, filters2, filters3 = filters  # filters1 64, filters3 256  将数值传入到filters。。。中
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'

    x = Conv2D(filters1, (1, 1), strides=strides, name=conv_name_base + '2a')(input_tensor)
    x = BatchNormalization(name=bn_name_base + '2a')(x)
    x = Activation('relu')(x)

    x = Conv2D(filters2, kernel_size, padding='same', name=conv_name_base + '2b')(x)
    x = BatchNormalization(name=bn_name_base + '2b')(x)
    x = Activation('relu')(x)

    x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)
    x = BatchNormalization(name=bn_name_base + '2c')(x)

    shortcut = Conv2D(filters3, (1, 1), strides=strides, name=conv_name_base + '1')(input_tensor)
    shortcut = BatchNormalization(name=bn_name_base + '1')(shortcut)

    x = layers.add([x, shortcut])
    x = Activation("relu")(x)
    return x

Identity Block 的架构:

def identity_block(input_tensor, kernel_size, filters, stage, block):
    filters1, filters2, filters3 = filters

    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'

    x = Conv2D(filters1, (1, 1), name=conv_name_base + '2a')(input_tensor)
    x = BatchNormalization(name=bn_name_base + '2a')(x)
    x = Activation('relu')(x)

    x = Conv2D(filters2, kernel_size, padding='same', name=conv_name_base + '2b')(input_tensor)
    x = BatchNormalization(name=bn_name_base + '2b')(x)
    x = Activation('relu')(x)

    x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(input_tensor)
    x = BatchNormalization(name=bn_name_base + '2c')(x)

    x = layers.add([x, input_tensor])
    x = Activation('relu')(x)
    return x  

最后是整体架构:

def ResNet50(inputs):
    #-----------------------------------#
    #   假设输入进来的图片是600,600,3
    #-----------------------------------#
    img_input = inputs

    # 600,600,3 -> 300,300,64
    x = ZeroPadding2D((3, 3))(img_input)
    x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x)
    x = BatchNormalization(name='bn_conv1')(x)
    x = Activation('relu')(x)

    # 300,300,64 -> 150,150,64
    x = MaxPooling2D((3, 3), strides=(2, 2), padding="same")(x)

    # 150,150,64 -> 150,150,256
    x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
    x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
    x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')

    # 150,150,256 -> 75,75,512
    x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')

    # 75,75,512 -> 38,38,1024
    x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')
    x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')

    # 最终获得一个38,38,1024的共享特征层
    return x

附上理论链接 Resnet-50网络结构详解  https://www.cnblogs.com/qianchaomoon/p/12315906.html

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`slim.conv2d`是TensorFlow中Slim框架中的卷积层函数,而`tensorflow.keras.layers.conv2d`是TensorFlowKeras框架中的卷积层函数。 两者所提供的功能都是实现2D卷积层,但是使用方式和参数设置不同: `slim.conv2d`: ```python slim.conv2d(inputs, num_outputs, kernel_size, stride=1, padding='SAME', activation_fn=tf.nn.relu, normalizer_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), biases_initializer=tf.zeros_initializer(), scope=None) ``` 其中各参数含义为: - `inputs`:输入的tensor - `num_outputs`:卷积核的数量,也就是输出的通道数 - `kernel_size`:卷积核大小 - `stride`:卷积核滑动步长,默认为1 - `padding`:卷积层补零的方式,可以设置为`SAME`或者`VALID` - `activation_fn`:激活函数,默认为ReLu - `normalizer_fn`:正则化函数,如BN层 - `weights_initializer`:权重初始化函数 - `biases_initializer`:偏置初始化函数 - `scope`:变量作用域 `tensorflow.keras.layers.conv2d`: ```python tf.keras.layers.Conv2D(filters, kernel_size, strides=(1, 1), padding='valid', 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, **kwargs) ``` 其中各参数含义为: - `filters`:输出的通道数 - `kernel_size`:卷积核的大小 - `strides`:卷积核滑动步长,默认为(1,1) - `padding`:卷积层补零方式,默认为`valid` - `activation`:激活函数,默认为`None` - `use_bias`:是否使用偏置 - `kernel_initializer`:权重初始化函数 - `bias_initializer`:偏置初始化函数 - `kernel_regularizer`:权重正则化函数 - `bias_regularizer`:偏置正则化函数 - `activity_regularizer`:输出正则化函数 - `kernel_constraint`:权重约束函数 - `bias_constraint`:偏置约束函数 总的来说,`tensorflow.keras.layers.conv2d`提供了更多的参数设置选项,控制更加细致,但对于简单的应用场景,`slim.conv2d`更简单方便。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值