使用卷积神经网络进行图片分类

https://blog.csdn.net/oxuzhenyi/article/details/73480448

卷积神经网络原理

一、实验介绍

1.1 实验内容

本课程将会先带你理解卷积神经网络的原理,了解卷积神经网络的一些特性。然后动手使用caffe深度学习框架训练一个卷积神经网络模型,并用训练好的模型进行图片分类。

学习本课程之前,请先学习课程814 使用python实现深度神经网络以了解必要的基本概念,本实验中涉及到的深度学习基本概念将不会再次阐述。同时建议学习课程744 深度学习初探——入门DL主流框架(该课为训练营课程)中的caffe相关部分,但本课程中涉及到caffe的内容也会尽量讲解。  

本实验作为本课程的第一次实验,将会向大家讲解卷积神经网络的相关基本原理。除非你已经知道什么是卷积神经网络,否则我强烈建议你仔细学习本次实验,理解原理将非常有助于你在实际问题中合理地使用卷积神经网络。

1.2 实验知识点

  • 卷积神经网络的结构

1.3 先学课程

  • 814 使用python实现深度神经网络(必学,否则可能无法理解本课程中的一些概念)
  • 744 深度学习初探——入门DL主流框架(选学)

1.4 实验环境

  • python 2.7
  • caffe 1.0.0 (实验楼环境中已经预先安装)

二、实验步骤

2.1 什么是“卷积”

在课程814 使用python实现深度神经网络中,我们已经构建过深度神经网络,注意在那个网络中,除了激活函数层和损失函数层之外,发挥主要作用的是全连接层,我们的网络参数全部都在全连接层中。那么既然使用全连接层构成的神经网络就已经实现了对图片的分类,为什么我们还需要“卷积神经网络”呢?为了回答这个问题,我们先来了解到底什么是卷积(convolution)

2.1.1 卷积操作

“卷积”这一词在多个领域里都有定义(比如信号处理领域的傅里叶变换中也有卷积)。具体在图像处理领域,卷积操作是指使用一个小的“模板窗口”对一个图片中的所有与模板大小相同的区域进行“卷积运算”。“卷积运算”其实很简单,就是将模板中的每一个数字与图片中相同大小区域的对应数字(像素值)进行相乘,再求和。具体操作如下图:

此处输入图片的描述
“模板窗口”每移动到一个位置,就和图片中的对应元素进行一次卷积运算,注意我们一般把“模板窗口”称为卷积核(kernel)

比如在第一个位置,图片上的四个像素值为[[0,0],[1,1]], 而卷积核中的数值为[[-1,1],[-1,1]], 对应元素相乘再求和,得到0*-1+0*1+1*-1+1*1=0
比如在第二个位置,图片上的四个像素值为[[0,0],[1,0]], 对应元素相乘再求和,得到0*-1+0*1+1*-1+0*1=-1

对图片中的所有可能位置进行卷积操作,就得到了最终的卷积结果。

2.1.2 为什么卷积操作适合用来处理图像

上图中的卷积核,其实是经过精心设置的。观察被卷积的图像和卷积结果你会发现,该卷积核其实可以用来检测图片中的垂直边缘。如果卷积后得到的数字绝对值大,就说明图片上的对应地方有一条垂直方向的边缘(即像素数值变化较大)。如果卷积后得到的数字绝对值很小,则说明图片上的对应地方像素值变化不大,没有边缘存在。同样的道理,你可以构造一个检测水平方向边缘的卷积核:
此处输入图片的描述
你可以尝试用这个卷积核去对上面的图片进行卷积操作,验证这个卷积核是不是检测出了水平方向的图片边缘。
卷积操作还可以有更多强大的功能,在数字图像处理中经常会用到。

说到这里,你也许已经能够体会为什么我们需要卷积神经网络。对于将整个图片视为一个向量的全连接层来说,它忽略了图像本身所具有的的“二维空间特性”,或者说局部特性。而卷积操作则十分擅长处理这种局部特性,能够更有效地提取出图片中的更多有用信息(比如图片中的边缘)。实际上,卷积神经网络几乎已经成为了神经网络中处理图像的标配。

2.2 神经网络中的卷积层

在具体的将卷积操作运用到神经网络的过程当中,有许多细节需要注意(包括很多超参数)。首先需要明确的是,和课程814 使用python实现深度神经网络中介绍的一样,卷积层中的参数(即卷积核中的每个数字)也是通过学习算法(随机梯度下降算法)学习得到的,不需要手工设定。

2.2.1 特征个数

一个卷积核,只能检测一种特征(feature)(比如垂直方向的边缘),而图片中的信息往往很复杂,一个卷积核显然不够。所以神经网络中,一个卷积层往往会有多个卷积核,这样卷积层的输出就会有多层。如下图:
此处输入图片的描述

为了简便,在一些深度学习框架(比如本课程会用到的caffe)中,在运算时可以将特征个数与图像通道数等同看待。所以对于一个通道数为1的图片,若卷积层特征个数为3,则可将输出的卷积结果视为通道数为3的图片。对于一个通道数为3的图片(此时,卷积核是一个三维的“体”),若卷积层特征个数为16,则可将输出的卷积结果视为通道数为16的图片。

2.2.2 stride

上面的示意图中,卷积核在水平和垂直方向上每次都移动一个像素的距离,在实际的卷积神经网络中,卷积核可能一次移动不止一个像素。卷积核每次移动的“步长”被称为stridestride的大小会影响最后卷积结果的大小。比如将水平和垂直方向的stride都从1改成2,原来的示意图就会变成这样:
此处输入图片的描述

2.2.3 卷积核尺寸(kernel size)

上面的示意图中卷积核的尺寸是2x2, 但在实际当中,很少见到边长为偶数的卷积核。且一般卷积核的最小边长为3(也存在边长为1的卷积核,你也许会觉得奇怪,边长为1的卷积层与全连接层岂不是几乎没有区别了,这个问题保留在这里,我们以后也许会来回答这个问题)。

2.2.4 padding

观察上面的图片你会发现,卷积操作得到的卷积结果与原来的图片相比尺寸变小了。这样会带来一个问题,有的卷积神经网络会非常“深”(比如几十层,甚至上百上千层)如果每经过一个卷积层我们的图片都变小一点,那到最后,有可能我们的图片都没有卷积核大,没办法继续卷积下去了。为了解决这个问题,人们对卷积层引入了边缘填充(padding):在卷积前,先将图片扩大一点点,然后再进行卷积。对于扩大部分,一般会填入0值。如下图(为了作图方便,卷积核与卷积结果之间只使用了一个箭头进行指示):
此处输入图片的描述

2.2.5 计算卷积结果的尺寸

对于一个尺寸为w*w的正方形图片,卷积结果的尺寸(假设其尺寸是o*o),会受到上面的特征个数feature步长stride卷积核尺寸kernel边缘padding四个超参数的影响。你可以尝试一下推导卷积结果尺寸的公式,其实很简单:

o=(w+2*padding-kernel)/stride+1 且输出结果的通道数等于feature

这个公式只适合于输入图片为正方形,卷积核也为正方形,步长在水平和垂直方向一致,padding在四个方向都一样的情况(不满足这些条件的情况你可以自己推导)。比如对于尺寸为17*17的输入图片,padding为1,kernel的尺寸为3*3, stride为1,则卷积之后的输出边长为:(17+2*1-3)/1+1=17,没有变化。

注意根据上面的公式,你会发现卷积层的几个超参数之间需要满足如下关系:
(w+2*padding-kernel)%stride==0
其中的%为取模符号,即(w+2*padding-kernel)需要是stride的整数倍,不然无法除尽。

2.3 卷积层的实现

卷积层相对全连接层来说比较复杂(从其中超参数的个数很多你就能看出来)。你可以接着课程814尝试自己使用python实现卷积层,其实原理都是一样的,关键都是运用链式法则去求梯度。不过除非你有特别的兴趣,不然不推荐自己“造轮子”(作者自己造了一个,如果你对代码有兴趣,请到Github查看)。幸运的是好多现有的深度学习框架已经帮我们实现好了卷积层(比如本课程会用到的caffe),直接拿过来用就好了。

三、实验总结

本次实验我们学习了卷积操作的基本概念。掌握了这些基本概念,之后的实验对你来说会非常容易。如果你对其中的一些概念还感到困惑,不用感到受挫,刚开始接触新东西都会有这种感觉。请你再仔细思考一遍这些概念的含义,然后去继续做之后的实验,当碰到相应的概念时就回过头来看一看,相信这些对你来说都不难掌握。

本次实验,我们学习了:

  • 对于图像处理,卷积层比全连接层更有优势。
  • 可以将使用卷积核对图像进行的卷积操作视作对图像提取特征的过程。
  • 卷积层中含有多个超参数,包括特征数feature、卷积核尺寸kernel、边缘填充padding、卷积步长stride。

四、课后作业

以下的作业都能根据上面的文档推测出答案。

  1. 请你设计一个卷积核,用来检测图片对角线方向的边缘。
  2. 请你计算,对于一个3*100*100(3通道图片)尺寸的图片,使用padding=1(四个方向都填充一个像素的长度), kernel=7(kernel为正方形), stride=5(水平和垂直方向的stride相同)的卷积层进行卷积后,得到的输出的尺寸。

猜你喜欢

转载自my.oschina.net/tantexian/blog/1798184