文章目录

  • 1.CNN介绍
  • 1.1CNN模型基本概念
  • 1.1.1卷积层(Convolution)
  • 1.1.1.1滑动窗口(过滤器filter/卷积核)
  • 1.1.1.2 Padding操作
  • 1.1.1.3 卷积步长(stride)
  • 1.1.1.4彩色图像的卷积
  • 1.1.2池化层(Pooling)
  • 1.1.2.1 最大池化(Max pooling)
  • 1.1.2.2平均池化
  • 1.1.3激励层(activation function)
  • 1.1.4全连接层(fully connected layer,简称FC)
  • 2.主流CNN模型
  • 3.使用 Pytorch构建CNN模型
  • 3.1 CNN的一般结构
  • 3.2 代码
  • 4.优缺点
  • 参考资料


1.CNN介绍

  • 卷积神经网络的创始人是着名的计算机科学家Yann LeCun,目前在Facebook工作,他是第一个通过卷积神经网络在MNIST数据集上解决手写数字问题的人。
  • CNN是解决图像分类、图像检索、物体检测和语义分割的主流模型。
  • 其每一层由众多的卷积核组成,每个卷积核对输入的像素进行卷积操作,得到下一次的输入。随着网络层的增加,卷积核会逐渐扩大感受野,并缩减图像的尺寸。
  • CNN是一种端到端(End to End)思路,输入的是图像像素。并不涉及到具体的特征提取和构建模型的过程,也不需要人工参与。

1.1CNN模型基本概念

1.1.1卷积层(Convolution)

1.1.1.1滑动窗口(过滤器filter/卷积核)

1.卷积核具有长、宽、深三个维度,在,在CNN的每一个卷积层中,长、宽都是人为指定的,长X宽也被称为卷积核的尺寸,常用的尺寸为3X3、5X5等;
2.卷积核的深度与当前图像的深度(feature map的张数)相同,所以指定卷积核时,只需要指定长和宽两个参数。灰度图像的feature map张数为1;图像为grb格式,feature map为3.

如下图所示,我们创建一个用于边缘检测的3X3卷积核:

在CNN中加入位置编码_池化


假设目标为6X6的灰度图像,如下图所示,

在CNN中加入位置编码_卷积核_02


则当进行卷积计算时,卷积核先从图像像素矩阵的从左至右,然后逐排进行卷积运算。卷积核每移动一次,卷积核就会与feature map上对应的区域进行卷积运算,每次都会得到一个数字。这里会涉及到卷积核每次移动的步长,如下图所示:卷积核每次移动的步长为1。图中,绿色框、红色框、蓝色框、黄色框分别代表卷积核在feature map第一行移动时的示意图。最终来到右下角

在CNN中加入位置编码_卷积_03


上述过程完之后,可以得到一张4X4的图像。以左上角的-5为例,说明一下计算过程。该值对应于上图中的绿色框区域与卷积核卷积计算所得。则 3x1+1x1+2x1+0x0+5x0+7x0+1x(-1)+8x(-1)+2x(-1)=-5

其余同理

在CNN中加入位置编码_在CNN中加入位置编码_04


如上所示,通过一个3x3的过滤器来对6x6的图像进行卷积,得到了一幅4x4的图像。假设输入的图像大小为在CNN中加入位置编码_卷积_05,过滤器的大小为在CNN中加入位置编码_卷积核_06,输出的图像大小为在CNN中加入位置编码_池化_07

这样做有如下缺点:

  1. 可以看到,这样做,卷积图像的大小会不断缩小,
  2. 图像左上角的元素只被一个输出所使用,所以图像的边缘像素在输出中采用较少,也就意味着我们丢掉了很多图像边缘的信息。
    为了解决以上两个问题,引入了Padding操作
1.1.1.2 Padding操作

也就是在图像卷积操作之前,沿着图像边缘用0进行填充。这里面会涉及到填充的宽度。

对于上面那个例子,卷积核3x3,图像6x6,卷积出来4x4。如果进行padding,宽度为1,则图像就会变为8x8,如下所示(绿色部分代表padding层)

在CNN中加入位置编码_卷积_08


这样我们就可以保证卷积之后的输出图像和输入图像一样大。

panding有两种模式:

1) Valid: no padding

2) Same: 输出图像和输入图像一样大。此时计算公式为:

在CNN中加入位置编码_卷积核_09

1.1.1.3 卷积步长(stride)

卷积步长是指过滤器在图像上滑动的距离,前面计算输出图像尺寸时,默认步长都是1。如果卷积步长为2,则卷积计算过程为:

在CNN中加入位置编码_在CNN中加入位置编码_10


在CNN中加入位置编码_在CNN中加入位置编码_11


在CNN中加入位置编码_卷积核_12


加入步长在CNN中加入位置编码_卷积核_13之后,卷积后图像大小的通用计算公式为:

输出图像大小为:在CNN中加入位置编码_卷积核_14在CNN中加入位置编码_卷积核_15表示向下取整

1.1.1.4彩色图像的卷积

上面讲的都是灰度图像,feature map为1.当需要在RGB图像上进行卷积,卷积核的大小不再是3x3,而是3x3x3,最后的3为通道数(channels)。卷积生成图像中每个像素值为333过滤器对应位置和图像对应位置相乘累加,过滤器依次在RGB图像上滑动,最终生成图像大小为44。

在CNN中加入位置编码_池化_16


另外一个问题是,如果我们在不仅仅在图像总检测一种类型的特征,而是要同时检测垂直边缘、水平边缘、45度边缘等等,也就是多个过滤器的问题。如果有两个过滤器,最终生成图像为4
42的立方体,这里的2来源于我们采用了两个过滤器。如果有10个过滤器那么输出图像就是44*10的立方体。

在CNN中加入位置编码_在CNN中加入位置编码_17

1.1.2池化层(Pooling)

池化层夹在连续的卷积层中间,用于压缩数据和参数的量,减小过拟合。

具体展开:

在CNN中加入位置编码_在CNN中加入位置编码_18

1.1.2.1 最大池化(Max pooling)

最大池化思想很简单,以下图为例,把44的图像分割成4个不同的区域,然后输出每个区域的最大值,这就是最大池化所做的事情。其实这里我们选择了22的过滤器,步长为2。在一幅真正的图像中提取最大值可能意味着提取了某些特定特征,比如垂直边缘、一只眼睛等等。

在CNN中加入位置编码_池化_19


以下是一个过滤器大小为3*3,步长为1的池化过程,具体计算和上面相同,最大池化中输出图像的大小计算方式和卷积网络中计算方法一致,如果有多个通道需要做池化操作,那么就分通道计算池化操作。

在CNN中加入位置编码_卷积_20

1.1.2.2平均池化

其计算的是区域内的平均值,日常应用中,使用UI多的还是最大池化。

在CNN中加入位置编码_在CNN中加入位置编码_21


池化的超参数:步长、过滤器大小、池化类型最大池化or平均池化

1.1.3激励层(activation function)

即非线性激活函数(non-linear activation function),把卷积层输出的结果作出非线性映射

在CNN中加入位置编码_卷积核_22


CNN采用的激励函数一般为ReLU(The Rectified Linear Unit/修正线性单元),它的特点是收敛快,求梯度简单,但较脆弱,图像如下。

在CNN中加入位置编码_卷积_23


激励层的实践经验:

①不要用sigmoid!不要用sigmoid!不要用sigmoid!

② 首先试RELU,因为快,但要小心点

③ 如果2失效,请用Leaky ReLU或者Maxout

④ 某些情况下tanh倒是有不错的结果,但是很少

1.1.4全连接层(fully connected layer,简称FC)

两层之间所有神经元都有权重连接,通常全连接层在卷积神经网络尾部。也就是跟传统的神经网络神经元的连接方式是一样的:

在CNN中加入位置编码_卷积_24

2.主流CNN模型

•LeNet,这是最早用于数字识别的CNN
•AlexNet, 2012 ILSVRC比赛远超第2名的CNN,比
•LeNet更深,用多层小卷积层叠加替换单大卷积层。
•ZF Net, 2013 ILSVRC比赛冠军
•GoogLeNet, 2014 ILSVRC比赛冠军
•VGGNet, 2014 ILSVRC比赛中的模型,图像识别略差于GoogLeNet,但是在很多图像转化学习问题(比如object detection)上效果奇好

3.使用 Pytorch构建CNN模型

3.1 CNN的一般结构

  1. 输入层 Input
  2. 【 【卷积层Conv -> RELU】* N ->池化POOl】
  3. 【FC -> RELU】*K
  4. FC

3.2 代码

#导入需要的包
import torch.nn as nn

#定义网络结构
class MyCNN(nn.Module):
    def __init__(self):
        super(MyCNN,self).__init__()
        ##CNNq提取特征模块
        self.cnn = nn.Sequential(
            nn.Conv2d(3,16,kernel_size=(3,3),stride=(2,2)),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(16,32,kernel_size=(3,3),stride=(2,2)),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.fc1 = nn.Linear(32*3*7,11)
        self.fc2 = nn.Linear(32*3*7,11)
        self.fc3 = nn.Linear(32 * 3 * 7, 11)
        self.fc4 = nn.Linear(32 * 3 * 7, 11)
        self.fc5 = nn.Linear(32 * 3 * 7, 11)
        self.fc6 = nn.Linear(32 * 3 * 7, 11)
        def forward(self,img):
            feat = self.cnn(img)
            feat = feat.view(feat.shape[0],-1)
            c1 = self.fc1(feat)
            c2 = self.fc2(feat)
            c3 = self.fc3(feat)
            c4 = self.fc4(feat)
            c5 = self.fc5(feat)
            c6 = self.fc6(feat)
            return c1,c2,c3,c4,c5,c6
model = MyCNN()
print(model)

输出网络结构

MyCNN(
  (cnn): Sequential(
    (0): Conv2d(3, 16, kernel_size=(3, 3), stride=(2, 2))
    (1): ReLU()
    (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (3): Conv2d(16, 32, kernel_size=(3, 3), stride=(2, 2))
    (4): ReLU()
    (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (fc1): Linear(in_features=672, out_features=11, bias=True)
  (fc2): Linear(in_features=672, out_features=11, bias=True)
  (fc3): Linear(in_features=672, out_features=11, bias=True)
  (fc4): Linear(in_features=672, out_features=11, bias=True)
  (fc5): Linear(in_features=672, out_features=11, bias=True)
  (fc6): Linear(in_features=672, out_features=11, bias=True)
)

4.优缺点

CNN一个非常重要的特点就是头重脚轻(越往输入权值越小,越往输出权值越多),呈现出一个倒三角的形态,这就很好地避免了BP神经网络中反向传播的时候梯度损失得太快。

优点
  •共享卷积核,对高维数据处理无压力
  •无需手动选取特征,训练好权重,即得特征分类效果好
缺点
  •需要调参,需要大样本量,训练最好要GPU
  •物理含义不明确(也就说,我们并不知道没个卷积层到底提取到的是什么特征,而且神经网络本身就是一种难以解释的“黑箱模型”)

参考资料

  1. CNN中feature map、卷积核、卷积核个数、filter、channel的概念解释,以及CNN 学习过程中卷积核更新的理解
  2. 吴恩达deeplearning之CNN—卷积神经网络入门
  3. 一文让你理解什么是卷积神经网络