卷积层和池化层的实现(使用 im2col )

卷积

为什么卷积神经网络的能力更强?以 mnist 数据集为例,在普通的神经网络中,输入的数据是长度为 784 784 784 的像素。但实际上图像本身 28 × 28 28 \times 28 28×28 的的二维结构已经被破坏了,每个像素与之上下更多像素之间的位置关系都消失了。神经网络所看见的世界是由一维向量构成的,自然无法与现实形成更好的拟合

神经网络中的卷积是通过一个个滤波器对原始图像提取特征来实现的。不妨以二维单通道的图像数据为例,看看卷积的作用方式。(左侧为原始图像数据,中间为滤波器,右侧为特征图像)

卷积作用的方式

原始图像的每个灰色部分都被提取出来,并与滤波器进行按位置的乘法(不是矩阵乘法),将其结果的和作为特征图像的一部分。这样就以滤波器为参照获取到了原始图像的特征,如果图像的某一部分和滤波器越相似,则获得的特征值就越大。

填充

值得注意的是,特征图像与原始图像相比小了一圈,如果经过多次卷积运算,边缘的像素可能会被忽略,同时图像的面积也在不断减小,这时可以通过一种名为**填充(padding)**的处理扩大图像,也就是在图像的四周填充 0 值。如下:
填充一圈0

可以得到填充后的特征图像

特征值

步幅

应用滤波器的间隔称为步幅(stride),上述的例子步幅都是 1,也就是说灰色的区域移动的长度是 1,不过也可以选取其他值。

输出大小

如果取原始图像大小为 ( H , W ) (H,W) (H,W),滤波器大小为 ( F H , F W ) (FH,FW) (FH,FW),填充为 P P P,步幅为 S S S,输出的特征图像大小为 ( O H , O W ) (OH,OW) (OH,OW),则有
O H = H + 2 P − F H S + 1 , O W = W + 2 P − F W S + 1. OH = \frac{H + 2P - FH}{S} + 1, \\ OW = \frac{W + 2P - FW}{S} + 1. OH=SH+2PFH+1,OW=SW+2PFW+1.

池化

池化是一种缩小特征图像大小的运算。

池化的好处主要有两个:一是在不大幅改变数据特征的情况下减少数据量,可以提高运算速度;二是将大的范围映射到小的范围可以减少扰动引起的误差。

在这里插入图片描述

image_to_column() 的实现

N N N 为批处理数量, C C C 为图像通道数量。

实现卷积和池化有一个相当重要的函数需要实现,这个函数可以将 ( N , C , H , W ) (N, C, H, W) (N,C,H,W) 形状的四维数据转化为 ( C × F H × F W , N × O H × O W ) (C \times FH \times FW, N \times OH \times OW) (C×FH×FW,N×OH×OW) 形状的数据,第一个轴与滤波器大小相同,第二个轴与输出的特征图像大小相同。

之所以要使用 image_to_column() 是为了减少 for 循环的使用,提高计算速度。

def image_to_column(data: np.ndarray, filter_h: int, filter_w: int,
                    stride: int = 1, padding: int = 0) -> np.ndarray:
    """
    assert that data.shape is (batch_num, channel, height, width)
    @params data: 4D input array
    @params filter_h, filter_w: the height and width of the filter
    @returns: the column of input array
    """
    N, C, H, W = data.shape
    assert (H + 2 * padding - filter_h) % stride == 0
    assert (W + 2 * padding - filter_w) % stride == 0
    out_h = (H + 2 * padding - filter_h) // stride + 1
    out_w = (W + 2 * padding - filter_w) // stride + 1

    im = np.pad(data, ((0, 0), (0, 0), (padding, padding), (padding, padding)),
                mode="constant")

    i0 = np.tile(np.repeat(np.arange(filter_h), filter_w), C)
    i1 = np.repeat(np.arange(out_h), out_w) * stride
    j0 = np.tile(np.arange(filter_w), filter_h * C)
    j1 = np.tile(np.arange(out_w), out_h) * stride

    i = i0.reshape(-1, 1) + i1.reshape(1, -1)
    j = j0.reshape(-1, 1) + j1.reshape(1, -1)
    k = np.repeat(np.arange(C), filter_h * filter_w).reshape(-1, 1)

    col = im[:, k, i, j]
    col = col.transpose(1, 2, 0).reshape(filter_h * filter_w * C, -1)
    return col

卷积的过程

我们通过矩阵的维数和轴来观察卷积的过程:

( N , C , H , W ) ⏞ 原始数据 i m a g e _ t o _ c o l → ( C × F H × F W , N × O H × O W ) ⏞ col , ( F N , C , F H , F W ) ⏞ 滤波器 r e s h a p e → ( F N , C × F H × F W ) ⏞ col_f , ( F N , C × F H × F W ) ⏟ col_f ⋅ ( C × F H × F W , N × O H × O W ) ⏟ col ⏞ 矩阵乘法 + b → ( F N , N × O H × O W ) ⏞ 特征图像(2维) r e s h a p e →

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值