【tensorflow2.0】22.卷积层和池化层

    今天的内容对做计算机视觉的同学可以说是最重要的一部分,因为对于卷积的介绍、作用以及算法网上已经有太多太多的资料可以让大家学习,所以本篇文章就介绍一下卷积层和池化层的函数以及如何通过代码实现卷积。

#2维卷积(这也是我们做视觉最常用的卷积块)
tf.keras.layers.Conv2D(
    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 : 输出空间的维数(即卷积中输出滤波器的数量)。
kernel_size : 过滤器的大小(一个整数或2个整数的元组/列表)。
strides :横向和纵向的步长。
padding :valid表示不够卷积核大小的块,则丢弃; same表示不够卷积核大小的块就补0,所以输出和输入形状相同。
activation : 激活函数。
data_format :一个字符串,表示输入中维度的顺序.支持channels_last(默认)和channels_first。channels_last对应于具有形状
(batch, height, width, channels)的输入,而channels_first对应于具有形状(batch, channels, height, width)的输入。

dilation_rate :表示使用扩张卷积时的扩张率, 注意:strides 不等于1 和dilation_rate 不等于1 这两种情况不能同时存在。(一般扩张卷积中使用)
use_bias :是否使用偏置。
kernel_initializer :卷积核的初始化。
bias_initializer :偏差向量的初始化。

"""

#tf实现conv2D
def corr2d(x, w, b, pad, stride):
	#输入数据的数量,高,宽,通道数
    N, H, W, C = tf.shape(x)
    #卷积核的数量,高,宽,通道数
    F, HH, WW, C = tf.shape(w)
	#对数据进行0填充
    x = tf.pad(x, ((0, 0),(pad, pad), (pad, pad), (0, 0) ), 'constant')
    #计算卷积后的高和宽(也可以说长和宽。。我习惯这样说)
    Hn = 1 + int((H + 2 * pad - HH) / stride[0])
    Wn = 1 + int((W + 2 * pad - WW) / stride[1])
    #建立一个全是0的输出Y,维度为(输出数据个数,高,宽,通道数,F在上边是卷积核的数量,运算后为通道数,不懂得同学可以自行学习一下卷积的具体运算)
    Y = tf.Variable(tf.zeros((N, Hn, Wn, F),dtype=tf.float32))
	#进行卷积运算,将卷积核和对应位置的数据进行点积然后求和,遍历完整个数据之后,返回卷积后的Y
    for m in range(F):
        for i in range(Hn):
            for j in range(Wn):
                data = x[:, i * stride[0]:i * 1 + HH, j * stride[1]:j * 1 + WW, :]
                filt = w[m,:,:,:]
                Y[:, i, j, m].assign(tf.reduce_sum(tf.multiply(data,filt),axis=(1,2,3))+b[m])

    return Y
#还有通过numpy实现的,计算方法和上边的tf基本相同
def conv_numpy(x, w, b, pad,strides):
    out = None
    
    N, H, W, C = x.shape
    F,  HH, WW, C = w.shape
  
    X = np.pad(x, ((0, 0),(pad, pad), (pad, pad), (0, 0) ), 'constant')

    Hn = 1 + int((H + 2 * pad - HH) / strides[0])
    Wn = 1 + int((W + 2 * pad - WW) / strides[1])
    
    out = np.zeros((N, Hn, Wn, F))
    
    for n in range(N):
        for m in range(F):
            for i in range(Hn):
                for j in range(Wn):
                    data = X[n, i * strides[0]:i * strides[0] + HH, j * strides[1]:j * strides[1] + WW, :].reshape(1, -1)
                    filt = w[m].reshape(-1, 1)
                    out[n, i, j, m] = data.dot(filt) + b[m]

    return out

下边是2维的最大池化

tf.keras.layers.MaxPool2D(
    pool_size=(2, 2), strides=None, padding='valid', data_format=None, **kwargs
)
"""
pool_size:2个整数的元组/列表:(pool_height,pool_width),用于指定池窗口的大小。可以是单个整数,这样所有空间维度具有相同值。
strides:2个整数的元组/列表,用于指定池操作的步幅.可以是单个整数,这样所有空间维度具有相同值。注意:当strides=None,大小和pool_size一样
padding:一个字符串,表示填充方法,“valid”或“same”,不区分大小写.
data_format:一个字符串,表示输入中维度的顺序.支持channels_last(默认)和channels_first;channels_last对应于具
有形状(batch, height, width, channels)的输入,而channels_first对应于具有形状(batch, channels, height, width)的输入.

"""
#最大值池化tf实现,由于池化操作就是对于数据进行简单的维度变化,所以不需要通道数和卷积核个数这两个参数,计算也较为简单,看懂上边的代码,这个肯定没问题的!
def max_pool_forward_naive(x, pool_size=(2,2),strides=(1,1)):

    N, H, W, C = x.shape
    h_p, w_p = pool_size
    h_s, w_s = strides
    
    
    Hn = 1 + int((H - h_p) / h_s)
    Wn = 1 + int((W - w_p) / w_s)
    out = np.zeros((N, Hn, Wn, C))
    for i in range(Hn):
        for j in range(Wn):
            out[:, i, j, :] = np.max(x[:, i*h_s:i*h_s+h_p, j*w_s:j*w_s+w_p, :], axis=(1,2))
    return out

其实计算机视觉真的非常有意思,还有一些非常经典的网络能让你见识到卷及网络的神奇之处,例如LeNet、AlexNet、VGG等,后边的文章我们将会通过tf2.0对这些网络进行复现,请继续关注我!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值