深度学习之四:卷积神经网络基础

Posted zzulp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度学习之四:卷积神经网络基础相关的知识,希望对你有一定的参考价值。

计算机视觉在深度学习的帮助下取得了令人惊叹的进展,其中发挥重要作用的是卷积神经网络。本节总结了卷积神经的原理与实现方法。

1 卷积神经网络

1.1 计算机视觉与深度学习

计算机视觉要解决的问题是如何让机器理解现实世界的现象。目前主要处理的问题如图像分类,目标检测,风格变换等。

对于小型图片,如MNIST的图片处理,图像大小为64*64,使用全连接神经网络还可以处理。如果图像较大,如1000*1000*3时,单个输入层就需要3M的节点,全连接情况下,单层的权重就可能多达数十亿的待训练参数。这将导致神经网络无法进行有效训练。因此业界提出卷积神经网络解决参数过多的问题。

先看一个卷积神经网络的结构,在卷积神经网络中包括三种类型的层:卷积层,池化层和全连接层。下面几节介绍卷积神经网络的基本概念。

1.2 过滤器

在卷积神经网络中,过滤器也称为卷积核,通常是3*3或5*5的小型矩阵(先忽略每个点可能有多个通道)。过滤器的作用是和输入图像的各个区域逐次进行卷积。

所谓卷积运算是计算两个矩阵的对应元素(Element-wise)乘积的和。卷积本质是两个向量的内积,体现了两个向量的距离。

下图展示了过滤器在输入图像上的卷积计算的过程:

因此过滤器可以捕获图像中与之类似模式的图像区域。例如下图展示了一个过滤器的数值矩阵与图形。

当使用这个过滤器在图像上移动并计算卷积时,不同的区域会有不同的卷积结果。

在类似于的模式下过滤器与图像区域的卷积会产生较大的值。

不相似的区域则产生较小的值。

此外在一层上捕获的模式可以组合为更复杂的模式并输入到下一层,从而使得下一层能识别更复杂的图像模式。

训练CNN在一定意义上是在训练每个卷积层的过滤器,让其组合对特定的模式有高的激活,以达到CNN网络的分类/检测等目的。

1.3 Padding

对于一个shape为 [n,n] [ n , n ] 的图像,若过滤器的 shape为 [f,f] [ f , f ] ,在卷积时每次移动1步,则生成的矩阵shape为 [nf+1,nf+1] [ n − f + 1 , n − f + 1 ] 。这样如果经过多层的卷积后,输出会越来越小。另一方面图像边界的点的特征不能被过滤器充分捕获。

通过对原始图像四个边界进行padding,解决上面提到的两个问题。术语Same填充,会保证输出矩阵与输入矩阵大小相同,因此其需要对输入图像边界填充 f12 f − 1 2 个象素。另一个术语Valid填充表示不填充。

通过下图体会Padding对输出的影响

下面的代码展示了使用0填充,向X边界填充pad个像素的方法

def zero_pad(X, pad):
    X_pad = np.pad(X, ((0, 0), (pad, pad), (pad, pad), (0, 0)), 'constant', constant_values=0)

    return X_pad

1.4 卷积步长

另一个影响输出大小的因素是卷积步长(Stride)。
对于一个shape为 [n,n] [ n , n ] 的图像,若过滤器的 shape为 [f,f] [ f , f ] ,卷积步长为s,边界填充p个象素,则生成的矩阵shape为 [n+2pfs+1,n+2pfs+1] [ n + 2 p − f s + 1 , n + 2 p − f s + 1 ]

1.5 卷积层记法说明

对于第 l l 层的卷积层,nc[l]为该层的卷积核数,其输入矩阵的维度为

[n[l1]H,n[l1]W,n[l1]c] [ n H [ l − 1 ] , n W [ l − 1 ] , n c [ l − 1 ] ]

输出矩阵的维度以channel-last展示为 [n[l]H,n[l]W,n[l]c] [ n H [ l ] , n W [ l ] , n c [ l ] ] ,各维度值如下:
n[l]H=n[l1]H+2p[l]f[l]s[l]+1 n H [ l ] = n H [ l − 1 ] + 2 p [ l ] − f [ l ] s [ l ] + 1
n[l]W=n[l1]W+2p[l]f[l]s[l]+1 n W [ l ] = n W [ l − 1 ] + 2 p [ l ] − f [ l ] s [ l ] + 1

下面的代码展示了图像卷积计算的方法

def conv_single_step(a_slice_prev, W, b):
    """
    Apply one filter defined by parameters W on a single slice (a_slice_prev) of the output activation
    of the previous layer.

    Arguments:
    a_slice_prev -- slice of input data of shape (f, f, n_C_prev)
    W -- Weight parameters contained in a window - matrix of shape (f, f, n_C_prev)
    b -- Bias parameters contained in a window - matrix of shape (1, 1, 1)

    Returns:
    Z -- a scalar value, result of convolving the sliding window (W, b) on a slice x of the input data
    """
    s = np.multiply(a_slice_prev, W) + b
    Z = np.sum(s)
    return Z


def conv_forward(A_prev, W, b, hparameters):
    """
    Implements the forward propagation for a convolution function

    Arguments:
    A_prev -- output activations of the previous layer, numpy array of shape (m, n_H_prev, n_W_prev, n_C_prev)
    W -- Weights, numpy array of shape (f, f, n_C_prev, n_C)
    b -- Biases, numpy array of shape (1, 1, 1, n_C)
    hparameters -- python dictionary containing "stride" and "pad"

    Returns:
    Z -- conv output, numpy array of shape (m, n_H, n_W, n_C)
    cache -- cache of values needed for the conv_backward() function
    """

    (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape

    (f, f, n_C_prev, n_C) = W.shape

    stride = hparameters['stride']
    pad = hparameters['pad']

    n_H = int((n_H_prev - f + 2 * pad) / stride) + 1
    n_W = int((n_W_prev - f + 2 * pad) / stride) + 1

    # Initialize the output volume Z with zeros.
    Z = np.zeros((m, n_H, n_W, n_C))

    # Create A_prev_pad by padding A_prev
    A_prev_pad = zero_pad(A_prev, pad)

    for i in range(m):  # loop over the batch of training examples
        a_prev_pad = A_prev_pad[i]  # Select ith training example's padded activation
        for h in range(n_H):  
            for w in range(n_W): 
                for c in range(n_C):  # loop over channels (= #filters) of the output volume
                    # Find the corners of the current "slice"
                    vert_start = h * stride
                    vert_end = vert_start + f
                    horiz_start = w * stride
                    horiz_end = horiz_start + f
                    # Use the corners to define the (3D) slice of a_prev_pad (See Hint above the cell). 
                    a_slice_prev = a_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :]
                    # Convolve the (3D) slice with the correct filter W and bias b, to get back one output neuron.
                    Z[i, h, w, c] = conv_single_step(a_slice_prev, W[..., c], b[..., c])

    assert (Z.shape == (m, n_H, n_W, n_C))

    cache = (A_prev, W, b, hparameters)

    return Z, cache

1.6 池化层

有两种类型的池化层,一种是最大值池化,一种是均值池化。
下图体现了最大池化的作用,其过滤器大小为2,步幅为2:

均值池化与最大池化不同的是计算相应区域的均值,而不是取最大值。
对池化层各维度值如下:
深度学习之 TensorFlow:卷积神经网络

深度学习之卷积神经网络(13)DenseNet

深度学习之卷积神经网络(CNN)

深度学习之卷积神经网络(CNN)学习

深度学习之卷积神经网络理论详解

从软件工程的角度写机器学习6——深度学习之卷积神经网络(CNN)实现