CNN理论-卷积神经网络结构(Convolutional Neural Network)

CNN 的特点:

  1. 能够有效的将大数据量的图片降维成小数据量。
  2. 能够有效的保留图片特征,符合图片处理的原则。

CNN 解决了什么问题:

  1. 图像需要处理的数据量太大,导致成本很高,效率很低。
  2. 图像在数字化的过程中很难保留原有的特征,导致图像处理的准确率不高。

典型的 CNN 由 3 个部分构成:

  1. 卷积层
  2. 池化层
  3. 全连接层

卷积层负责提取图像中的局部特征;池化层用来大幅降低参数量级(降维);全连接层类似传统神经网络的部分,用来输出想要的结果。

卷积层

  • 卷积层是卷积核在上一级输入层上通过逐一滑动窗口计算而得,卷积核中的每一个参数都相当于传统神经网络中的权值参数,与对应的局部像素相连接,将卷积核的各个参数与对应的局部像素值相乘之和,(通常还要再加上一个偏置参数),得到卷积层上的结果。
  • 卷积层输出值越高,就说明匹配程度越高,越能表现该图片的特征。卷积层的作用其实就是通过不断的改变卷积核,来确定能初步表征图片特征的有用的卷积核是哪些,再得到与相应的卷积核相乘后的输出矩阵。我们其实就可以把卷积核就理解为特征提取器。
image.png

池化/采样层

  • 通过卷积层获得了图像的特征之后,理论上我们可以直接使用这些特征训练分类器(如softmax),但是这样做将面临巨大的计算量的挑战,而且容易产生过拟合的现象。为了进一步降低网络训练参数及模型的过拟合程度,我们对卷积层进行池化/采样(Pooling)处理。池化/采样的方式通常有以下两种:
  • Max-Pooling: 选择Pooling窗口中的最大值作为采样值;
  • Mean-Pooling: 将Pooling窗口中的所有值相加取平均,以平均值作为采样值;

经典CNN网络模型- -LeNet-5 网络详解:

image.png
  • C1 层是一个卷积层
    • 6个特征图,每个特征图中的神经元与输入 5 * 5 的领域相连(可重叠),特征图大小为 28 * 28.
    • 每个卷积神经元的参数数目:5*5 = 25 (还有一个bias参数)。
    • 网络连接数目: (5 * 5 + 1) * 6 * (28 * 28)
    • 参数共享:每个特征图内共享参数,既总参数:(5 * 5+1)* 6
  • S2 层是一个下采样层
    • 6个特征图,每个特征图中的神经元与 C1 输入 2 * 2 的领域相连(不可重叠),特征图大小为 14 * 14.
    • S2 层每个单元的4个输入采样(max_pool),乘以一个可训练的参数 w, 再加上一个可训练偏置 b ,结果通过激活函数 sigmoid 函数计算.
    • 网络连接数目:(1 + 1) * 6 * (14 * 14)
    • 参数共享:每个特征图内共享参数,既总参数:(1+1) * 6.
  • C3 层是一个卷积层
    • 16个卷积核,得到16张特征图,特征图大小为 10 * 10 .
    • 每个特征图中的每个神经元与 S2 输入某几层的多个 5 * 5 领域相连.
    • 例如:对于 C3 层第 0 张特征图,其中每一个节点与 S2 层的第 0、1、2 特征图连接,总共 (5 * 5) * 3.(这个是如何连接? 是否有理论可循?)
  • S4 层是一个下采样层
    • 由 16 个 5 * 5 大小的特征图构成,特征图中的每个单元与 C3 中相应特征图的 2 * 2 领域相连.
    • 网络连接数目: (1 + 1 ) * 5 * 5 * 16
    • 参数共享:每个特征图共享参数,既总参数:(1 + 1) * 16
  • C5 层是一个卷积层
    • 120 个神经元,可以看作 120 个特征图,每张特征图大小为 1 * 1.
    • 每个单元与 S4 层的全部 16 个单元的 5 * 5 领域相连(S4 和 C5 之间全连接).
    • 网络连接数目:(5 * 5 * 16 + 1) * 120
  • F6 层
    • 有 84 个单元(之所以选这个数字的原因是来自于输出层的设计),与 C5 层全连接。
    • F6 层计算输入向量和权重向量之间的点积,再加上一个偏置。
    • 网络连接数目:(120 + 1) * 84
  • 输出层
    • 输出层采用欧式径向基函数(Euclidean Radial Basic Function)单元
    • 给定一个输入模式,损失函数应使得 F6 的配置与 RBF 参数向量(既模式的期望分类)足够接近.
    • 每类一个单元,每个单元连接 84 个输入,每个输入 RBF 单元计算输入向量和参数向量之间的欧式距离.
    • RBF 输出可以理解为 F6 层配置空间的高斯分布的 [-log-likelihood]

Pytorch CNN 网络结构代码

  • 自定义网络必须继承 nn.Module, 并且在其构造函数需调用 nn.Module 的构造函数,既 super(Net, self).int
  • 在构造函数中必须自己定义可学习的参数.
  • forward 函数实现前向传播过程,其输入可以是一个或多个 tensor.
  • 不需要写反向传播函数,nn.Module能够利用 autograd 自动实现反向传播.
class conv_net(t.nn.Module):
    """
    卷积神经网络
    """
    def __init__(self):
        super(conv_net, self).__init__()
        # torch.nn.Sequential是一个Sequential容器,模块将按照构造函数中传递的顺序添加到模块中.
        self.conv1 = t.nn.Sequential(
            """
            卷积层
            Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
            in_channels: 输入通道数目/输入卷积层的图片厚度
            out_channels: 输出通道数目/输出卷积层的图片厚度
            kernel_size: 卷积核大小 n * n 
            stride: 步长
            padding: 填充,原来的输入层基础上,上下左右各加 n 行
            dilation: 内核元素之间的间距
            groups: 卷积核个数
            bias: 偏置项
            """
            t.nn.Conv2d(1, 10, 5),
            """
            池化层
            池化操作计算输出特征图大小默认是向下取整的,与我们平常理解向上取 整不一样,如果稍有不注意会使得池化过程中出现边缘信息丢失的情况.
            因此使用时需要注意ceil_mode参数设置。
            """
            t.nn.MaxPool2d(2),
            # 激活函数
            t.nn.ReLU(),
            # 标准化 BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True)
            t.nn.BatchNorm2d(10)
        )
        self.conv2 = t.nn.Sequential(
            t.nn.Conv2d(10, 20, 5),
            t.nn.MaxPool2d(2),
            t.nn.ReLU(),
            t.nn.BatchNorm2d(20)
        )
        self.fc1 = t.nn.Sequential(
            """
            原始输入:1 * 28 * 28 
            conv1 卷积之后:10 * 24 * 24  (24 = 28 - 5 + 1)
            conv1 池化之后:10 * 12 * 12   (12 = 24 / 2)
            conv2 卷积之后:20 * 8 * 8  (8 = 12 - 5 +1)
            conv2 池化之后:20 * 4 * 4  (4 = 8 / 2 )
            20 * 4 * 4 = 320
            60 为自定义参数
            """
            t.nn.Linear(320, 60),
            """
            Dropout 常常用来降低过拟合
            0.5 指的是随机有 50% 的神经元会被关闭/丢弃.
            """
            t.nn.Dropout(0.5),
            t.nn.ReLU()
        )
        self.fc2 = t.nn.Sequential(
            t.nn.Linear(60, 20),
            t.nn.Dropout(0.5),
            t.nn.ReLU()
        )
        self.fc3 = t.nn.Linear(20, 10)
    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(-1, 320)
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        return x

你可能感兴趣的:(CNN理论-卷积神经网络结构(Convolutional Neural Network))