卷积神经网络(CNN)是deep learning的基础。传统的全连接神经网络(fully connected networks) 以数值作为输入。
如果要处理图像相关的信息的话,要另外从图像中提取特征并采样。而CNN把提特征、下采样和传统的神经网络整合起来,形成一个新的网络。
本博文已经假设你已经有了简单神经网络的概念,如“层”、“神经元”。
1. 理论基础
图1
如图1所示,这是一个简单的卷积神经网络 CNN。其中C层代表对输入图像进行滤波后得到的所有组成的层,也称“卷积层”。S层代表对输入图像进行下采样(subsampling,现在一般说max-pooling)得到的层。其中C1和C3是卷积层 ,S2和S4则是下采样层。
C、S层中的每一层都由多个二维平面组成,每一个二维平面是一个特征图 (feature map)。
以图1所示的CNN为例,讲讲图像的处理流程:、
图像输入网络后,通过三个滤波器(filter) 进行卷积,得到C1层的三个特征图(feature map)。C1层的三个特征图分别通过下采样得到S2层的三个特征图。这三个特征图通过一个滤波器卷积得到C3层的三个特征图,然后和前面类似,下采样得到S4层的三个特征图。最后,S4层的特征图光柵化后,变成向量。这个向量输入到传统的全连接神经网络(fully connected networks)中进行进一步的分类。
图中的C1、S2 、C3、S4层中的所有特征图都可以用 “像素 x 像素” 定义图像大小。你会说,图像的大小不就是用像素x像素定义的么? 没错,但这里有点特殊,由于这些特征图组成了神经网络的卷积层和下采样层,而在神经网络(neural networks)中,每一层都有“神经元” (neurons) 的概念。这些特征图中的每一个像素恰恰旧就代表了一个神经元。每一层所有特征图的像素个数,就是当层网络的神经元个数,这是可以算出来的,怎么算? 再往后面看一看。
隐层(hidden layer):
提到了神经元的概念之后,就可以讲述CNN中C-S部分的隐层(hidden layer)(NN部分的隐层就不在这里讲了) 还有层与层之间,神经元的连接数(connections)的概念了。
1. 别的层和卷积层之间的隐层:
滤波器也在这两层之间,滤波器一般是这样定义的:
其中filter_width、filter_height 分别指滤波器滤波范围的宽和高。filter_channels指滤波器过滤图像的通道数。filter_types就是指滤波器的种类。
如 5x5x3 → 20: 滤波器宽高各为5个像素,过滤(卷积)通道数为3,共20种这样的滤波器
下面会涉及局部感受野的概念和权值共享的概念
一般来说,如果C层中的所有神经元都和输入图像上的每一个像素点建立连接,那么这个连接数目是极其庞大的。需要学习的参数个数也另人瞠目结舌。
举个例子,若输入图像大小为 200x200,C1层由6个特征图,每个特征图大小为20x20(神经元数目为20x20=400个)。并且,使滤波器为10x10的单通道滤波器(channel = 1),且步长为10---相当于相邻的两个滤波区域恰好不重叠,这样便于计算啦。 那么总共的连接数目是 200x200x(6x20x20) = 96000000。天哪,九千多万个连接,如果每个连接一个参数的话,那就九千多万的可训练参数(learnable parameters),如此复杂的网络,根本就没有计算的可能,地球都毁灭了,参数还没训练好。。。
在我们的生活中。看见一样东西,通常都是先看到它的局部,一般不会一下就能看到一件物品的全部内容。“局部感受野”说的就是这种现象,CNN中,使用了局部感受野。因为这个原因,卷积层中的每一个神经元都只和输入图像中的一个局部区域中的像素点相连接。(而这个局部区域的大小就是滤波器的大小 filter_width x filter_height)。
C层的一个特征图(feature map) 是输入图像通过一种滤波器(filter) 得到的。假设这中滤波器提取 “Tiga” 特征。特征图上面的每一个神经元都通过这个滤波器和原图像上面自己对应的那个局部区域相关联(和局部区域中的像素点相连)。这样一来啊,每个神经元获得了自己对应区域的 “Tiga” 特征后,把大家的那份都整起来,不就相当于获得原图的 “Tiga” 特征了吗 ? 这就是“局部感受野” 莫大的好处哇!
让我们来算算,现在连接的数目是多少!每个神经元只和一个10x10的区域相连,那就是 10x10x(6x20x20) = 240000。天啦噜!现在最多只有24w个可训练参数了。 你没看错,是最多只有,后面CNN还会更牛逼的策略使得许多重复的参数出现,那么实际需要训练的参数就更少了!
ps: 每一个神经元都对应一个值,这个值由它指向的原图的区域里的所有像素点值通过滤波器(filter)卷积算出!
下面,我们来谈谈权值共享的概念。我们已经知道啊,输入图像通过一种滤波器卷积得到一张特征图。特征图上的每个神经元都与原图上的一个矩形滤波区域上的像素点连接,上例就是10x10。辣么每一神经元和原图上的10x10个输入神经元有连接。由于这些神经元想要的是同一种特征,所以它们通过同一个滤波器来滤波。因此,每一个神经元上的这10x10的连接上的参数是 一毛一样的。没错,是一毛一样的 !!! 解释是不是很有道理的样子 ?! 实际上,这10x10个参数被这张特征图上的所有神经元共享。这就是权值共享啊! 那么即使6张特征图,也只有6x10x10 = 600 个需要训练的参数啊啊啊 !!!
进一步地,这10x10的参数仿佛只和滤波有关,就像是6个滤波器,每个都自带100个参数一样。而且这些参数需要训练。就像是自学习的滤波器一样!!! 突然觉得非常魔性。
现在我们已经知道了:
可训练参数个数 = (滤波器大小 + 可加偏置数目) x 滤波器种类
其中,I. 滤波器大小 = filter_width x filter_height x filter_channels,即滤波器的大小
II. bias: 可加偏置,一般为1
III. filter_types: 滤波器的种类
e.g. 如果隐层的滤波器定义为 5x5x3 -> 20,那么可训练参数 = (5x5x3 + 1) x 20 = 1520个
卷积层上神经元的个数 = 特征图的数目 x 每张特征图上神经元的数目
每张特征图上神经元的数目和 输入图的宽高、滤波器的宽高、滤波器的步长均有关。
设特征图的宽高分别是 n 和 m:
可以推出公式:
神经元的个数 = nxm
推导过程很简单:
...
next:
一张 feature map 上神经元个数 = 输入图可放滤波器的个数 (和输入图的宽高,滤波器的宽高,滤波器的步长有关) 并给出具体公式
连接数 = 神经元个数 x 滤波区域的大小
神之效果图
2. 卷积层和下采样层之间的隐层:
next:
下采样层做什么? 怎么做?
下采样层的参数个数、神经元个数、连接个数
2. 计算实践
下面以Yann LeCun的手写数字识别CNN “LeNet-5” 为例,算算里面的一些参数:
图2
(论文本身里的图就这么模糊,不是我截图姿势的原因,大家就将就着看吧)