神经网络
1. 感知机
2. 多层感知机与反向传播
卷积神经网络
1. 全连接神经网络的2大缺陷
2. 卷积神经网络的崛起
卷积神经网络的基本网络层
1. 什么是卷积?
2. 填充(Padding)
3. 步长(Stride)
4. 池化
5. 卷积和池化输出尺寸计算
6. 为什么要用卷积来学习呢?
7. 卷积神经网络的优势在哪?
本训练营以理论结合实战的方式,帮助大家从 0 完成一个人脸常见表情的识别,接下来是本训练营的理论部分。不要觉得理论枯燥哦,万丈高楼平地起,基础打牢了,后面学什么都容易,让我们开始吧~
感知机(Perceptron)是 Frank Rosenblatt 在1957年提出的概念,其结构与MP模型类似,一般被视为最简单的人工神经网络,也作为二元线性分类器被广泛使用。通常情况下指单层的人工神经网络,以区别于多层感知机(Multilayer Perceptron)。尽管感知机结构简单,但能够学习并解决较复杂问题。
假设我们有一个n维输入的单层感知机,1x1 至 xn 为 n 维输入向量的各个分量,1w1j 至 wnj为各个输入分量连接到感知机的权量(或称权值),theta 为阈值,f 为激活函数(又称为激励函数或传递函数),o 为标量输出。理想的激活函数通常为阶跃函数或者sigmoid函数。感知机的输出是输入向量x与权重向量w求得内积后,经激活函数f所得到的标量。
单层感知器类似一个逻辑回归模型,可以做线性分类任务,但是不能做更复杂的任务。第二次AI浪潮中马文·明斯基在其著作中证明了感知机本质上是一种线性模型,只能处理线性分类问题,就连最简单的 XOR(异或)问题都无法正确解决。作为人工智能领域的开创者之一,这一声明也直接或间接促使神经网络的研究陷入了近 20 年的停滞。
不过就算在低谷期,1974 年哈佛大学的 Paul Werbos 仍然证明增加一个网络层,利用反向传播算法可以搞定 XOR 问题。到了后来 Rummelhart,McClelland 以及 Hinton 在 1986 年正式在多层感知器 (MLP) 中使用 BP 算法,采用 Sigmoid 进行非线性映射,有效解决了非线性分类和学习的问题。
多层感知机(Multi-Layer Perceptron)是由单层感知机推广而来,最主要的特点是有多个神经元层。一般将 MLP 的第一层称为输入层,中间的层为隐藏层,最后一层为输出层。MLP 并没有规定隐藏层的数量,因此可以根据实际处理需求选择合适的隐藏层层数,且对于隐藏层和输出层中每层神经元的个数也没有限制。
多层感知机的关键问题在于如何训练其中各层间的连接权值,方法有一些不过大家最熟知的就是反向传播BP算法了。
反向传播算法的具体推导涉及大量的公式,因此我们就不写了,大家随便找一本书都能找到资料,勤快的可以自己推导一遍。
这里给大家一个实际的案例来体会:
输出为y,损失函数为E。
=ℎ1ℎ1+ℎ2ℎ2=111+212+221+222=12(−)2y=h1wh1+h2wh2=x1w11+x2w12+x2w21+x2w22E=12(y−t)2
假如某一时刻值如下:
x1=1,x2=−1,w11=0.1,w21=−0.1,w12=−0.1w22=0.1,wh1=0.8,wh2=0.9,t=0x1=1,x2=−1,w11=0.1,w21=−0.1,w12=−0.1w22=0.1,wh1=0.8,wh2=0.9,t=0
ℎ1=111+122=0.2ℎ2=211+222=−0.2=ℎ1ℎ1+ℎ2ℎ2=−0.02h1=w11x1+w12x2=0.2h2=w21x1+w22x2=−0.2y=h1wh1+h2wh2=−0.02
那么我们可以计算E对ℎ1Wh1的误差传播值为:
∂E∂ℎ1=∂E∂y∂∂ℎ1=(−)ℎ1=−0.004∂E∂wh1=∂E∂y∂y∂wh1=(y−t)h1=−0.004
下次更新ℎ1Wh1这个参数的时候就可以采用:
ℎ1=ℎ1−∂∂ℎ1wh1=wh1−η∂E∂wh1
η就是学习率了,原理就是这样,一层一层推导下去就行了。
反向传播算法让多层感知机,或者说传统的全连接神经网络有了训练的手段,引发了神经网络的第二次热潮,虽然为期不长,毕竟当时算力和数据都很有限,但是全连接神经网络总算是正式起来了。
传统的BP神经网络在20世纪80年代左右流行,但是很快因为SVM等核方法的诞生而黯然失色。这是因为传统的BP神经网络有几个重大的缺陷。
也就是说,不过是在最后面将SVM或者其他分类器换成神经网络,在大部分情况下其实没有什么优势,甚至增加了问题的复杂度。
提取的特征虽然是研究者们经过反复实验证明有效的特征,但仍然会一定程度上丢失了图像中的结构信息,从而丢失了一些对旋转扭曲等的不变性。而且要求输入的大小是固定的。为了学习到如偏移等微小的变化,需要有足够多的参数和足够多丰富的样本,最终学习到的权重,很可能在不同的位置处还会有非常相似的权重。
有人可能会说,直接把图像作为输入而不提取特征行不行?请接着往下看。
全连接神经网络从BP算法提出开始,发展于90年代,那时候的计算机属于CPU时代,根本就无法撑起海量参数的计算。
如果一个隐藏层特征图像大小为100×100,输入层的特征图像大小为100×100,这意味着学习这一层需要100×100×100×100=108108的参数。如果以32位的浮点数进行存储,就需要4×1084×108的字节的存储量,约等于400MB的参数量。仅仅这样的一个网络层,其模型参数量已经超过了AlexNet网络的参数量,而100×100的特征图像分辨率,已经低于很多任务能够成功解决的下限。除了计算过程中需要存储的海量的参数,还有海量的计算,这些都超过了当时硬件的能力,因此大大限制了网络的大小,尤其是对于一些大的图像输入。
不管是历史局限性也好,还是神经网络有种种毛病,总之80年代后的20年间它不是主流。
不过在上个世纪90年代研究神经网络的学者们没有停止,经典的诸如LeNet5这样的网络被提出。
LeNet5,1999年由深度学习三巨头中LeCun, Bengi的提出,成功用于银行支票上的手写数字识别,最重要的两个概念(局部连接+池化)
为什么是卷积神经网络呢?首先自然是要知道什么是卷积神经网络。
卷积神经网络:英文全称:Convolutional Neural Networks、简称:CNN
CNN 主要包含卷积层、池化层和全连接层
卷积在工程和数学上有非常多的应用,在信号处理领域中,任意一个线性系统的输出,就是输入信号和系统激励函数的卷积。放到数字图像处理领域,卷积操作一般指图像领域的二维卷积。
一个二维卷积的案例如上,在图像上滑动,取与卷积核大小相等的区域,逐像素做乘法然后相加。 例如原始图像大小是5×5,卷积核大小是3×3。首先卷积核与原始图像左上角3×3对应位置的元素相乘求和,得到的数值作为结果矩阵第一行第一列的元素值,然后卷积核向右移动一个单位(即步长stride为1),与原始图像前三行第2、3、4列所对应位置的元素分别相乘并求和,得到的数值作为结果矩阵第一行第二列的元素值,以此类推。
故卷积就是:一个核矩阵在一个原始矩阵上从上往下、从左往右扫描,每次扫描都得到一个结果,将所有结果组合到一起得到一个新的结果矩阵。 注意这里我们不区分卷积和互相关,它们的区别只在于权重算子是否进行了翻转。之所以不重视,是因为在机器学习中,卷积核是否翻转,并不影响算法学习。
以下的代码可以帮助理解:
import torch
from torch import nn
def corr2d(X, K): # X 是输入,K是卷积核
h, w = K.shape # 获取卷积核的大小
Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
Y[i, j] = (X[i: i + h, j: j + w] * K).sum() # 累加
return Y
X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) # 模拟一个输入
K = torch.tensor([[0, 1], [2, 3]]) # 模拟一个卷积核
corr2d(X, K)
下图就是上面程序的模拟图
填充(padding)是指在输入高和宽的两侧填充元素(通常是0元素)。下图我们在原输入高和宽的两侧分别添加了值为0的元素,使得输入高和宽从3变成了5,并导致输出高和宽由2增加到4。下图阴影部分为第一个输出元素及其计算所使用的输入和核数组元素:0×0+0×1+0×2+0×3=0。
卷积窗口从输入数组的最左上方开始,按从左往右、从上往下的顺序,依次在输入数组上滑动。我们将每次滑动的行数和列数称为步幅或步长(stride)。
下图展示了在高上步幅为3、在宽上步幅为2的卷积运算。可以看到,输出第一列第二个元素时,卷积窗口向下滑动了3行,而在输出第一行第二个元素时卷积窗口向右滑动了2列。当卷积窗口在输入上再向右滑动2列时,由于输入元素无法填满窗口,无结果输出。下图阴影部分为输出元素及其计算所使用的输入和核数组元素:0×0+0×1+1×2+2×3=8、0×0+6×1+0×2+0×3=6。
对图像进行下采样,降低图像分辨率。
池化层的作用:使特征图变小,简化网络计算复杂度;压缩特征,提取主要特征
常见的池化操作可以分为:最大池化(Max Pool)、平均池化(Avg Pool),示意图如下:
假设输入图片的高和宽一致,卷积核的宽和高一致,那么输入图像的尺寸与输出图像的尺寸有如下关系:
其中,Fin 是输入图像、k 是卷积核的大小、p 是图像填充的大小、s 是卷积核的步幅、Fo 是输出、⌊6.6⌋⌊6.6⌋ 是向下取整的意思,比如结果是 6.6,那么向下取整就是 6
=⌊in −+2⌋+1Fo=⌊Fin −k+2ps⌋+1
除此之外,卷积神经网络还包括许多优化技术,大家可以参考相关资料。
图像都是用方形矩阵来表达的,学习的本质就是要抽象出特征,以边缘检测为例。它就是识别数字图像中亮度变化明显的点,这些点连接起来往往是物体的边缘。
传统的边缘检测常用的方法包括一阶和二阶导数法,本质上都是利用一个卷积核在原图上进行滑动,只是其中各个位置的系数不同,比如3×3的sobel算子计算x方向的梯度幅度,使用的就是下面的卷积核算子。
如果要用sobel算子完成一次完整的边缘检测,就要同时检测x方向和y方向,然后进行融合。这就是两个通道的卷积,先用两个卷积核进行通道内的信息提取,再进行通道间的信息融合。 这就是卷积提取特征的本质,而所有基于卷积神经网络来学习的图像算法,都是通过不断的卷积来进行特征的抽象,直到实现网络的目标。
前面说了全连接神经网络的原理和结构上的缺陷,而这正好是卷积的优势。
卷积神经网络不再是有监督学习了,不需要从图像中提取特征,而是直接从原始图像数据进行学习,这样可以最大程度的防止信息在还没有进入网络之前就丢失。
前面说了全连接神经网络一层的结果是与上一层的节点全部连接的,100×100的图像,如果隐藏层也是同样大小(100×100个)的神经元,光是一层网络,就已经有 10^8 个参数。要优化和存储这样的参数量,是无法想象的,所以经典的神经网络,基本上隐藏层在一两层左右。而卷积神经网络某一层的结点,只与上一层的一个图像块相连。
用于产生同一个图像中各个空间位置像素的卷积核是同一个,这就是所谓的权值共享。对于与全连接层同样多的隐藏层,假如每个神经元只和输入10×10的局部patch相连接,且卷积核移动步长为10,则参数为:100×100×10×10,降低了2个数量级。 又能更好的学习,参数又低,卷积神经网络当然是可以成功了。