卷积神经网络——卷积层

卷积层

卷积神经网络中,最重要的就是卷积层,它负责从图片中提取特征信息。
先考虑一种最为简单的图片,一张二维的图片,那么卷积核也是二维的。

卷积运算

听上去挺高大上的,实际上就是乘积的求和。
举个例子:
假设图片是这样的

1 2 4
3 5 4

卷积核是

6 1
4 4

那么卷积运算的结果就是:
6 × 1 + 1 × 2 + 4 × 3 + 4 × 5 = 40 6 × 2 + 1 × 4 + 4 × 5 + 4 × 4 = 52 6\times 1+1\times 2 + 4\times 3 + 4\times 5 =40 \newline 6\times 2 + 1\times 4 + 4\times 5+4\times 4 =52 6×1+1×2+4×3+4×5=406×2+1×4+4×5+4×4=52

填充

通过上面简单的例子,不难发现,在经过卷积运算之后,矩阵的大小变化了。这样就会带来一个严重的问题,当不断进行卷积运算后,图片越来越小,以至于最后无法进行卷积运算。
为了解决这个问题,我们希望在进行卷积运算之后,图片的大小不发生改变,这个时候就需要往图片的边缘填充相应的值。

矩阵大小

往图片边缘填充多少,这与卷积核的大小密切相关。那么这个大小变化是否存在关系呢。答案是肯定的。
不妨设 H , W H,W HW表示原来矩阵的长和高, O H , O W OH,OW OHOW表示经过卷积运算结果的长、高, F H , F W FH,FW FHFW表示卷积核的长、高, P P P表示填充, S S S表示步幅。
O H = H + 2 ⋅ P − F H S + 1 O W = W + 2 ⋅ P − F W S + 1 OH =\frac{H + 2\cdot P - FH}{S}+1 \newline OW = \frac{W + 2\cdot P - FW}{S}+ 1 OH=SH+2PFH+1OW=SW+2PFW+1

代码实现

卷积运算的原理非常简单,而且代码实现也非常简单。
通过几个for循环就可以轻松解决,但是还有更高效的方法。
我们可以将图片中对应同一个卷积核的数字变为一行,将卷积核变为一列。然后运用矩阵乘法,就可以完美实现卷积运算,而且一次矩阵乘法就可以算出整张图片的结果。
具体如何变为一行,代码已经在下面给出。

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
    """

    Parameters
    ----------
    input_data : 由(数据量, 通道, 高, 长)的4维数组构成的输入数据
    filter_h : 滤波器的高
    filter_w : 滤波器的长
    stride : 步幅
    pad : 填充

    Returns
    -------
    col : 2维数组
    """
    N, C, H, W = input_data.shape
    out_h = (H + 2*pad - filter_h)//stride + 1
    out_w = (W + 2*pad - filter_w)//stride + 1

    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

    for y in range(filter_h):
        y_max = y + stride*out_h
        for x in range(filter_w):
            x_max = x + stride*out_w
            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
    return col


def col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0):
    """

    Parameters
    ----------
    col :
    input_shape : 输入数据的形状(例:(10, 1, 28, 28))
    filter_h :
    filter_w
    stride
    pad

    Returns
    -------

    """
    N, C, H, W = input_shape
    out_h = (H + 2*pad - filter_h)//stride + 1
    out_w = (W + 2*pad - filter_w)//stride + 1
    col = col.reshape(N, out_h, out_w, C, filter_h, filter_w).transpose(0, 3, 4, 5, 1, 2)

    img = np.zeros((N, C, H + 2*pad + stride - 1, W + 2*pad + stride - 1))
    for y in range(filter_h):
        y_max = y + stride*out_h
        for x in range(filter_w):
            x_max = x + stride*out_w
            img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :]

    return img[:, :, pad:H + pad, pad:W + pad]

你可能感兴趣的:(#,神经网络,笔记,cnn,深度学习,机器学习)