0.绪论
0.1课程介绍
本课程是斯坦福大学的课程,鲁鹏老师搬运发扬光大。北邮的计算机视觉有研究生和本科两版,本笔记是研究生版。
CS131:Computer Vision:Foundations and Applications
主要介绍了计算机视觉的基础(2012年之前的基础技术方法思路)对应的是北邮本科生的机器视觉课程。
CS231a:Computer Vision,from 3D Reconstruction, segmentation, object recognition
本课程主要介绍了三维重建的相关内容。
CS230:Deep Learning
吴恩达教授的深度学习课程。
CS231n:Convolutional Neural NetWorks for Visual Recognition
2012年以后以卷积神经网络为主的计算机视觉技术,也就是本课程的来源。
本课程具体内容:

0.2什么是计算机视觉和机器视觉

对于我们人类来说,我们可以看到一只小狗并知道它是一只小狗,需要以下过程,如上图所示,我们的眼睛先获取光源,在我们的视网膜上成像,然后视网膜上的信号传入到大脑,大脑进行分析,最终解释出这是一只小狗。
计算机视觉也同样是这个道理,由照相机捕获光源,得到图片,然后通过计算机处理计算解释出语义。
另外我们经常可以听到计算机视觉和机器视觉两个概念。实际上,计算机视觉和机器视觉所使用的技术都是相同的,但是用途上有一些区别。机器视觉主要是应用在机器系统上,例如机器人。而计算机视觉应用广泛,如网络上的图像分类,人脸识别等都是计算机视觉。
0.3计算机视觉的目标
照相机拍出来的图片在计算机上是以矩阵的形式表示的。每个像素点对应着矩阵中的一个元素,如果图片是黑白的,那么该元素就记录着对应像素点的灰度值,如果是彩色的,那么该元素就记录着对应像素点的彩色值(RGB值)。
具体可以如下图所示:

可以看出,计算机“看到”的是一个矩阵,这个矩阵人类是看不懂的。也就是用人类的大脑来处理计算机看到的东西,是理解不了的,所以就要用计算机的方式来处理。那么就引出了计算机视觉的目标:跨越语义鸿沟,建立像素到语义的映射。
例如,当计算机看到这个矩阵时,就知道这是一个出轨的火车。
那么一张图像中究竟有什么信息呢?这大致分为两类信息:
- 空间结构信息
- 语义信息
计算机视觉的目标还可以理解为,从图像上获取这两类信息。
0.4计算机视觉的历史
- 1959年,Hubel 和 Wiesel
两个人率先做了一个实验,让一只小猫来看各种各样的图片,来看小猫的大脑哪个地方来处理这个信号。

当给猫看到鱼的图片时,发现小猫的大脑并没有什么反应。看其他的东西的时候,也是没有反应。
但当给小猫看一些简单的图形时,如直线,点,此时小猫的大脑皮层是有反应的。
因此他们得到了一个结论,就是人类视觉系统处理信息是分层的,处理图片的时候是从最简单的图形开始,如图片中物体的边沿。他们的这项工作后来获得了诺贝尔医学奖。
- 1963,Larry Roberts
从图片中计算出三维实体。

- 1966,MIT暑期视觉项目
将计算机视觉和图像处理独立出来。
- David Marr
计算机视觉的先驱,成为计算机视觉之父。
他将计算机问题分为三个层次:
计算理论:计算的目的是什么,该问题的已知和可以施加的约束是什么。
表达和算法:输入、输出和中间信息是如何表达的。使用哪些算法来计算所期望的结果。
硬件实现:表达和算法是如何映射到实际硬件上来进行处理的。
然后他又将视觉表达分为了三个阶段

输入一个图像,先提取出边缘图,然后到2.5D的简图,最后再恢复出3D图。
- 后续的研究
0.5计算机视觉的应用
-
动画产业
-
三维建模
-
摄影
-
生物识别(如人脸识别,指纹识别)
-
光学字符识别(OCR)
-
机器人和无人驾驶
-
增强现实
-
医学图像
……
0.6计算机视觉和其他学科的关系
此处就要放一张神图了
计算机视觉和许多学科都有着密不可分的关系。如上图所示。
物理学:光学传感器的研究设计为计算机视觉提供了图片输入。而图像处理领域也是为计算机视觉提供输入,可以先将照相机拍下来的图片进行预处理。
生物学:该学科主要通过研究人类的大脑来为计算机视觉的研究提供启发。
计算机科学:计算机科学为计算机视觉提供方法。如机器学习的方法。
工程学:给计算机视觉提供应用平台,如计算机视觉可以应用在机器人上,可以用在语义识别上。
1.分类问题
1.0介绍
1.0.1什么是图像分类任务
图像分类任务是计算机视觉中的核心任务,目的是根据图像内容的不同,将图像分为不同的类别。
就是在已知类别标签集合的时候,为给定的输入图片选定一个类别标签。
1.0.2分类任务的难点
(1)语义鸿沟
跨越语义鸿沟是十分困难的。
(2)视角
(3)光照
(4)遮挡
(5)多形态
(6)背景杂波

(7)类内形变

(8)运动模糊

(9)尺度
(10)种类众多
成百上千种类别很难区分开来。
1.0.3数据驱动的图像分类方法
如果基于规则的方法,先进行边缘检测,找到角点,然后计算特征,这是很难实现的。比如一只猫,形态各异,不可能有一个确定的特征,若分为多个特征,那么如此巨大数量的特征,是不可能实现的。

所以就要采用数据驱动的方法,通过机器学习来完成。
a.数据驱动分类器的结构
一个数据驱动分类器的结构如上图所示,数据驱动分类器就是需要通过数据训练才能设计出一个分类器。
b.分类器设计过程(有监督条件下)
在整个分类器的设计中,首先我们要有一个分类器模型,然后使用该模型对输入图像进行预测,得到预测值,再将该预测值和该图像在数据集中对应的真实值进行对比,来计算出损失函数得到损失值。再依据损失值来进行优化,使分类模型的参数得到更新。如此往复,直到所得到的分类器性能达到要求为止。
设计一个分类器,最关键的步骤就是设计分类模型、损失函数和训练过程。
常用的分类模型在后面(2)中列出。损失函数在(3)中列出。
而训练过程比较复杂,包括了训练要用到的数据集的划分,数据的预处理,数据增强,欠拟合和过拟合,超参数调整等问题。在后面会一一说明。
(1)图像表示
- 像素表示(一般该方法就可以)
- 全局特征表示(如GIST)
- 局部特征表示(如SIFT特征+词袋模型)
(2)分类模型
- 近邻分类器
- 贝叶斯分类器
- 线性分类器
- 支撑向量机分类器
- 神经网络分类器
- 随机森林
(3)损失函数
- 0-1损失
- 多类支撑向量机损失
- 交叉熵损失
(4)优化方法
一阶优化方法
- 梯度下降
- 随机梯度下降
- 小批量随机梯度下降
二阶方法
- 牛顿法
- BFGS
- L-BFGS
1.0.4数据集介绍
CIFAR10数据集:包含50000张训练样本,10000张测试样本,共有10个类别的彩色图像,每张图像的大小是32*32。
1.1线性分类器
1.1.1图像的表示方法
a.二进制图像

b.灰度图
每一个像素点有一个灰度值,其范围为0-255,就是对应二进制的00000000-11111111

c.彩色图
每一个像素点由三个深度,分别是红色,绿色和蓝色,每一个深度方向上的数值范围为0-255,也就是用三个颜色叠加来表示出一种颜色。

在线性分类器处理的过程中,我们将图片用向量的形式来表示。在CIFAR10数据集中,每一张图片是32*32的彩色图,因此用向量来表示就是将每一个像素点的RGB值依次排列成一个列向量。

1.1.2线性分类器模型
a.线性分类器的定义
ques为什么从线性分类器开始?
因为线性分类器的形式简单易于理解,其次通过层级结构(后面说的神经网络)可以形成功能强大的非线性模型。
线性分类器最主要的就是其分类模型,分类模型如下:
f
i
(
x
,
w
i
)
=
w
i
T
x
+
b
i
i
=
1
,
⋯
,
c
(1.1)
\begin{gathered} f_{i}\left(\boldsymbol{x}, \boldsymbol{w}_{i}\right)=\boldsymbol{w}_{i}^{T} \boldsymbol{x}+b_{i} \\ \mathrm{i}=1, \cdots, c \end{gathered}\tag{1.1}
fi(x,wi)=wiTx+bii=1,⋯,c(1.1)
其中,
x
x
x 表示输入的图像的向量,
c
c
c 为类别个数,
w
i
w_i
wi 表示第
i
i
i 个类别的权值向量,
b
i
b_i
bi 为第
i
i
i 类的偏置。
决策规则为当输入一个图像后,每一个类通过自己的权值向量对其打分,得到 f i ( x , w i ) f_i(x,w_i) fi(x,wi) ,谁的得分高,就属于哪一个类别。
eg: f i ( x ) > f j ( x ) f_i(x)>f_j(x) fi(x)>fj(x) ,那么该图片就属于第 i i i 类。

通过上图的过程,可以知道该图片为猫类。
b.矩阵表示分类器模型
f ( x , W ) = W x + b (1.2) f(x,W)=Wx+b\tag{1.2} f(x,W)=Wx+b(1.2)
其中, x x x 为图片向量,其维度为d(例如CIFAR10数据集, d = 32 × 32 × 3 = 3072 d=32\times32\times3=3072 d=32×32×3=3072 )
W是权值矩阵,它的每一行都是一个类的权值向量,因此W的维数为共有c(类别数)行,d(图片维数)列。
b是一个c维的列向量,每一个元素是每一类的偏置。
最后的得分 f f f 是一个c维的列向量,它的每一个元素代表着每一类别的得分。
c.线性分类器的权值
我们将训练好的线性分类器的权值向量 w i w_i wi 拿出来,因为其维数和图片向量是一样的,所以我们也将其表现成图像的形式。可以发现一个很有意思的现象。
所以权值向量是有其物理意义的,它可以看作是一个模板,如果输入图像与评估模板的匹配程度越高,那么分类器在该类上的输出分数就越高。
d.线性分类器的决策分界面
实际上,线性分类器和我们高中学习的线性规划一样,可以用图来表示:
当分数为0时,就是决策的分界面,其中权值向量w控制着线的方向,偏置b控制着线的偏移。上图中箭头的方向代表分类器的正方向,沿着箭头的方向距离分界面越远的图片,得分越高,就说明线性分类器越肯定的知道该图片属于哪一类。但由于这个分界面是“直线”,所以,线性分类器并不能完全的将一些特殊的图片区分出来,这就是线性分类器的局限性,但后面会继续说明如何解决这类问题(要用到神经网络)
1.1.3损失函数
前面我们说了分类器的权值向量,为图片进行打分,但是这个权值向量具体的数值是需要通过训练来得到的。那么如何用数学语言来描述该权值向量的性能呢,这就需要损失函数来描述。
损失函数搭建了模型性能和模型参数之间的桥梁,指导模型参数优化。
a.损失函数的特点
- 损失函数是一个函数,用于度量给定分类器的预测值和真实值的不一致程度,其输出通常是一个非负实值。
- 其输出的非负实值可以作为反馈信号,用来对分类器参数进行调整,从而降低当前的损失值,以提高分类效果。
b.损失函数的定义
L = 1 N ∑ i L i ( f ( x i , W ) , y i ) (1.3) L=\frac{1}{N} \sum_{i} L_{i}\left(f\left(x_{i}, W\right), y_{i}\right)\tag{1.3} L=N1i∑Li(f(xi,W),yi)(1.3)
N为样本图片数量。
i i i 表示输入的第 i i i 张图片, f ( x i , W ) f(x_i,W) f(xi,W) 是分类器对第 i i i 张图片的打分, y i y_i yi 是第 i i i 张图片真实类别标签。
L i L_i Li 是对第 i i i 张图片的损失当前预测值,也就是预测值与真实值之间的差距。
不同的损失函数,其 L i L_i Li 的具体形式不同。
c.多类支撑向量机损失
对于同某一个样本图片i,分类器对其打分得到了一个分数向量
f
(
x
i
,
W
)
=
[
s
i
1
s
i
2
…
s
i
j
]
T
f(x_i,W)=[s_{i1}\ s_{i2} …s_{ij}]^T
f(xi,W)=[si1 si2…sij]T ,那么
s
i
j
s_{ij}
sij 就是第i张图片在第j类上的分数。
s
i
j
=
f
j
(
x
i
,
w
j
,
b
j
)
=
w
j
T
x
i
+
b
j
(1.4)
s_{i j}=f_{j}\left(x_{\mathrm{i}}, w_{j}, b_{j}\right)=w_{j}^{T} x_{i}+b_{j}\tag{1.4}
sij=fj(xi,wj,bj)=wjTxi+bj(1.4)
下面定义多类支撑向量机损失:
L
i
=
∑
j
≠
y
{
0
if
s
i
y
≥
s
i
j
+
1
s
i
j
−
s
i
y
+
1
otherwise
=
∑
j
≠
y
max
(
0
,
s
i
j
−
s
i
y
+
1
)
(1.5)
\begin{aligned} L_{i}=& \sum_{j \neq y}\left\{\begin{array}{l} 0 & \text { if } s_{iy} \geq s_{i j}+1 \\ s_{ij}-s_{iy}+1 & \text { otherwise } \end{array}\right.\\ &=\sum_{j \neq y} \max \left(0, s_{i j}-s_{iy}+1\right) \end{aligned}\tag{1.5}
Li=j=y∑{0sij−siy+1 if siy≥sij+1 otherwise =j=y∑max(0,sij−siy+1)(1.5)
这里,
y
y
y 表示样本图像 i 所在的真实类别。式(1.5)的意义就是,用图片在各个类别上的打分和其所在的真实类别上的打分进行比较,当真实类别上的打分
s
i
y
s_{iy}
siy 比其他类别的打分
s
i
j
s_{ij}
sij 高出1时,损失为0,如果不高出1,则损失
s
i
j
+
1
−
s
i
y
s_{ij}+1-s_{iy}
sij+1−siy 。该损失函数也称为折页损失(hingeloss)。

损失函数的范围是0到无穷,当损失函数很小时就说明所得到的参数性能很好了。
现在再来看一下线性分类器模型,有以下这种情况:

这个例子可以看出,可以使最终损失函数为0的参数W并不唯一,那么如何在这些参数之间进行选择呢?
d.正则项
在损失函数中加入正则项
L
(
W
)
=
1
N
∑
i
L
i
(
f
(
x
i
,
W
)
,
y
i
)
+
λ
R
(
W
)
(1.6)
L(W)=\frac{1}{N} \sum_{i} L_{i}\left(f\left(x_{i}, W\right), y_{i}\right)+\lambda R(W)\tag{1.6}
L(W)=N1i∑Li(f(xi,W),yi)+λR(W)(1.6)
前面原来的项,称为数据损失,根据数据损失训练出来的参数和训练集相匹配。
后面的项,称为正则项,它是一个仅与权值有关,而与训练集无关的函数,它的作用就是防止模型在训练集上训练得太好。
如果训练的太好,只能说明对该训练集可以准确的分类,但对于未知的图片,性能可能会很差。
(1)L2正则项
R ( W ) = ∑ k ∑ l W k , l 2 (1.7) R(W)=\sum_{k} \sum_{l} W_{k, l}^{2}\tag{1.7} R(W)=k∑l∑Wk,l2(1.7)
L2正则项是将所有的权值的平方相加到一起。

由该例子可以看出,分类器所打的分数相同,此时数据损失是相同的,但是正则损失不同,便可以选出更合适的权值参数。
L2正则损失对大数值权值进行惩罚,喜欢分散权值,鼓励分类器将所有维度特征都用起来,而不是强烈的依赖其中少数几维特征。
(2)L1正则项
R ( W ) = ∑ k ∑ l ∣ W k , l ∣ (1.8) R(W)=\sum_{k} \sum_{l}\left|W_{k, l}\right|\tag{1.8} R(W)=k∑l∑∣Wk,l∣(1.8)
(3)Elastic net(L1+L2)
R ( W ) = Σ k ∑ l β W k , l 2 + ∣ W k , l ∣ (1.9) R(W)=\Sigma_{k} \sum_{l} \beta W_{k, l}^{2}+\left|W_{k, l}\right|\tag{1.9} R(W)=Σkl∑βWk,l2+∣Wk,l∣(1.9)
该损失函数就是将L1和L2损失函数结合起来,式中的 β \beta β 是一个超参数。
e.超参数
在式(1.6)中的 λ \lambda λ 是一个超参数,它控制着正则损失在总损失中所占的比重。
超参数就是在开始学习过程之前,人为设置的参数,而不是学习得到的。
1.1.4优化算法
损失函数搭建了模型性能和模型参数之间的桥梁,有了这个桥梁就需要用优化算法来进行优化了。
优化算法的目标就是找到使损失函数达到最优的那组参数。
a.直接法
对损失函数直接求导,一般这种方法用不了,因为很难直接解出W。
b.梯度下降算法
梯度下降算法是一种简单而高效的迭代优化算法。就是求出损失函数的梯度来,这就确定了参数更新的方向,然后给定一个步长(步长也叫做学习率),来更新参数。
更新后的权值=原权值-学习率*损失函数梯度
梯度下降算法的核心就是如何计算出梯度。
方法有以下两种:
(1)数值法
d L ( w ) d w = lim h → 0 L ( w + h ) − L ( w ) h (1.10) \frac{d L(w)}{d w}=\lim _{h \rightarrow 0} \frac{L(w+h)-L(w)}{h}\tag{1.10} dwdL(w)=h→0limhL(w+h)−L(w)(1.10)
这种方法计算量大,不精确。
(2)解析法
对损失函数求导,求出梯度。
c.随机梯度下降算法
如果把所有的样本图片都代入到分类器中,计算损失函数,然后再求导,计算量过大,速度很慢。因此我们可以只代入一个样本图片。这就是随机梯度下降算法。
每次随机的抽取一个图片 i ,然后计算出损失函数和损失函数的梯度。
L
(
W
)
=
L
i
(
x
i
,
y
i
,
W
)
+
λ
R
(
W
)
∇
W
L
(
W
)
=
∇
W
L
i
(
x
i
,
y
i
,
W
)
+
λ
∇
W
R
(
W
)
(1.11)
\begin{aligned} &L(W)=L_{i}\left(x_{i}, y_{i}, W\right)+\lambda R(W) \\ &\nabla_{W} L(W)=\nabla_{W} L_{i}\left(x_{i}, y_{i}, W\right)+\lambda \nabla_{W} R(W) \end{aligned}\tag{1.11}
L(W)=Li(xi,yi,W)+λR(W)∇WL(W)=∇WLi(xi,yi,W)+λ∇WR(W)(1.11)
更新权值参数,再进行下一轮的训练。
这样速度会大大提升,但是单样本训练会带来很多的噪声,不是每次迭代都向着整体最优化方向的。
d.小批量梯度下降算法
既然单个样本可能会含有噪声,那么就用一个折中的办法,小批量随机选取m(超参数)个样本,计算损失函数和其梯度。
L
(
W
)
=
1
N
∑
i
=
1
N
L
i
(
x
i
,
y
i
,
W
)
+
λ
R
(
W
)
∇
W
L
(
W
)
=
1
N
∑
i
=
1
N
∇
W
L
i
(
x
i
,
y
i
,
W
)
+
λ
∇
W
R
(
W
)
(1.12)
\begin{aligned} &L(W)=\frac{1}{N} \sum_{i=1}^{N} L_{i}\left(x_{i}, y_{i}, W\right)+\lambda R(W) \\ &\nabla_{W} L(W)=\frac{1}{N} \sum_{i=1}^{N} \nabla_{W} L_{i}\left(x_{i}, y_{i}, W\right)+\lambda \nabla_{W} R(W) \end{aligned}\tag{1.12}
L(W)=N1i=1∑NLi(xi,yi,W)+λR(W)∇WL(W)=N1i=1∑N∇WLi(xi,yi,W)+λ∇WR(W)(1.12)
在小批量处理中,有几个名词需要知道:
- iteration:表示1次迭代
- batch-size:1次迭代所使用的样本量
- epoch:1个epoch表示过了1遍训练集中的所有样本
通常使用2的幂次方来作为样本数量。
1.1.5数据集划分
通常的数据集划分为两部分

但当存在超参数时,如何找到泛化能力最好的超参数呢,要用验证集。

- 训练集:用于 给定 的超参数时分类器参数的学习。
- 验证集:用于选择超参数。
- 测试集:用于评估泛化能力。
如果数据很少,那么可能验证集里的样本太少,从而无法在统计上代表数据。接下来介绍一种方法。
K折交叉验证:

过程是这样的,首先确定一个超参数,然后将数据分为K份(k折就是k份)。如上图所示,先用训练集训练,然后验证,得到一个分数。依此类推,最终得到K个分数,然后将其相加取平均,便得到了在该超参数的分值。
1.1.6数据预处理
就与我们考试一样,看绝对的分数是没有用的,因为不同的题难易程度也不同。而看我们与平均分的差距才能体现出我们的真实水平。
图像也正是如此,例如当有许多张猫和狗的图片,我们可以先将这些向量去均值,只需知道每两张图片间的相对差异即可。
另外为了避免数量级的影响,还需要将数据进行归一化
Z
=
X
−
X
ˉ
σ
(1.13)
Z=\frac{X-\bar{X}}{\sigma}\tag{1.13}
Z=σX−Xˉ(1.13)
其中
X
ˉ
\bar{X}
Xˉ 为数据的均值,
σ
\sigma
σ 为数据的方差。
数据去相关可以达到降维的作用。
1.2全连接神经网络分类器
1.2.1全连接神经网络的提出
当出现较为复杂的图片时,单纯依靠线性分类器就很难划分分界面了(因为线性分类器的分界面只能是直的),所以需要建立一个非线性模型。那么全连接神经网络模型就是具有代表性的非线性模型。
如下图所示,分为线性可分和线性不可分:
全连接神经网络级联了多个变换来实现输入到输出的映射。
如两层神经网络模型:
f
=
W
2
max
(
0
,
W
1
x
+
b
1
)
+
b
2
(1.14)
f=W_{2} \max \left(0, W_{1} x+b_{1}\right)+b_{2}\tag{1.14}
f=W2max(0,W1x+b1)+b2(1.14)
两层神经网络结构有一层隐层。
三层神经网络模型:
f
=
W
3
max
(
0
,
W
2
max
(
0
,
W
1
x
+
b
1
)
+
b
2
)
(1.15)
f=\mathrm{W}_{3} \max \left(0, \mathrm{~W}_{2} \max \left(0, \mathrm{~W}_{1} \mathrm{x}+\mathrm{b}_{1}\right)+\mathrm{b}_{2}\right)\tag{1.15}
f=W3max(0, W2max(0, W1x+b1)+b2)(1.15)
上面两式和线性分类模型形式十分相似,但稍稍有一些不同,其中在线性模型中,是权值向量直接乘以图片向量,而神经网络中出现了一个
m
a
x
(
)
max()
max() 函数,这是一个激活函数,我们后面会详细说明,那么为什么要加上激活函数呢?
如果不加上激活函数,如式(1.15),将其一层一层的乘开,最后该模型又会退化到线性模型上去,因此这里的激活函数是关键,正是因为激活函数的存在,才可以使神经网络称为一个非线性模型。
f
=
W
3
(
W
2
(
W
1
x
+
b
1
)
+
b
2
)
+
b
3
=
W
3
W
2
W
1
x
+
(
W
3
W
2
b
1
+
W
3
b
2
+
b
3
)
=
W
′
x
+
b
′
(1.16)
\begin{aligned} f&=W_{3}\left(W_{2}\left(W_{1} x+b_{1}\right)+b_{2}\right)+b_{3} \\ &=W_{3} W_{2} W_{1} x+\left(W_{3} W_{2} b_{1}+W_{3} b_{2}+b_{3}\right) \\ &=W^{\prime} x+b^{\prime} \end{aligned}\tag{1.16}
f=W3(W2(W1x+b1)+b2)+b3=W3W2W1x+(W3W2b1+W3b2+b3)=W′x+b′(1.16)
至于整个神经网络有多少个隐层,每一层隐层有多少个神经元比较合适,这都没有统一的答案,但有一点可以证明:神经元的数量越多,分界面就可以越复杂,在这个集合上的分类能力就越强。
在设计神经网络的时候,所面对的任务越复杂,神经网络结构就应该越深,越宽。但也要注意,并不是越复杂的神经网络越好,因为在真实场景下未必是最好的,只是在训练集上的效果较好(过拟合)。
1.2.2全连接神经网络的物理意义
通过1.1.2c的学习,我们知道线性分类器的分类模型是通过一个权值向量乘以图片向量加上偏置得出分数。其权值向量的物理意义是每一个权值向量都是一个图片模板。模版数量取决于类别的数量,即假如有10个类别,那么就有10个模板。
用一个模板来筛选一类未免太难了,如下图所示
可以隐约的看出,这个模板中,有两个马头,这就是因为只用一个模板来表示整个类,那么这个模板就是该类的一个平均。但当有一个极其特殊的马时,那么便识别不出来了。而想要多用几个模板,又用不了,因为线性分类器的结构就是这样,有多少个类就有多少个模板。
然而在神经网络中,模板的数量可以人为的规定,为什么会这样呢?
f
=
W
2
max
(
0
,
W
1
x
+
b
1
)
+
b
2
(1.14)
f=W_{2} \max \left(0, W_{1} x+b_{1}\right)+b_{2}\tag{1.14}
f=W2max(0,W1x+b1)+b2(1.14)
现在以两层神经网络为例,如果共有10类,那么
W
2
W_2
W2 的行数应该为10,而至于
W
2
W_2
W2 的列数,等于
W
1
W_1
W1 的行数,对于
W
1
W_1
W1 的行数,并没有什么限制,我们可以随意的规定。
W
1
W_1
W1 的列数,是等于图像向量的维数的。再反过来看,和线性分类器一样,
W
1
W_1
W1 的行向量也是一个权值向量,它的物理意义也是一样的,转化成图片也是一个模板,我们可以规定
W
1
W_1
W1 的某几行都是某一类的模板,然后再通过
W
2
W_2
W2 的权值对该类的这几个模板进行叠加。例如我们规定
W
1
W_1
W1 的前100行都是马的模板,有站着的马,跑着的马,吃饭的马,汗血宝马等等。当输入一个图像向量后,分别与这一百个模板进行比较打分,得到一个100维的分数向量,然后再将这个分数向量代入到第二层神经网络,进行权值叠加,得出各类的分数。
所以说,全连接神经网络的描述能力更强,因为调整 W 1 W_1 W1 行数等于增加模板数量。
1.2.3常用的激活函数
a.Sigmoid
1 / ( 1 + e − x ) (1.17) 1 /\left(1+e^{-x}\right)\tag{1.17} 1/(1+e−x)(1.17)
函数图像:
值域为0到1。
b.tanh
e x − e − x e x + e − x (1.18) \frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}\tag{1.18} ex+e−xex−e−x(1.18)
函数图像:
值域为-1到1。
c.ReLU
m a x ( 0 , x ) (1.19) max(0,x)\tag{1.19} max(0,x)(1.19)
函数图像:
值域为0到正无穷。
d.Leaky ReLU
m a x ( 0.1 x , x ) (1.20) max(0.1x,x)\tag{1.20} max(0.1x,x)(1.20)
函数图像:
值域负无穷到正无穷。
1.2.4损失函数
在这里,我们换一种损失函数的定义方法,使用SOFTMAX和交叉熵的方法。
a.SOFTMAX
我们先对神经网络关于输入图片所打的分数进行一个处理,如下图所示

SOFTMAX就是对神经网络的输出值求指数得到 t i t_i ti,然后将其求和,再用 t i t_i ti 比上这个总和,便得到了 p i p_i pi 。
经过这个处理,就可以转化成概率分布的形式,即神经网络分类器对某一张图片进行分类,输出结果是图片为各个类别的概率。

b.交叉熵损失
然后我们来定义损失函数,和线性分类器类似,我们这里也用概率的形式定义真实值,例如一张图片的标签是鸟,那么我们就用其在鸟类的概率为1来定义。如下图所示

这种形式也叫做one-hot形式。
然后我们要想办法来描述预测值和真实值之间的差距,从而构建损失函数。
定义:
- 熵: H ( p ) = − ∑ x p ( x ) log p ( x ) H(p)=-\sum_{x} p(x) \log p(x) H(p)=−∑xp(x)logp(x)
- 交叉熵: H ( p , q ) = − ∑ x p ( x ) log q ( x ) H(p, q)=-\sum_{x} p(x) \log q(x) H(p,q)=−∑xp(x)logq(x)
- 相对熵: K L ( p ∥ q ) = − ∑ x p ( x ) log q ( x ) p ( x ) K L(p \| q)=-\sum_{x} p(x) \log \frac{q(x)}{p(x)} KL(p∥q)=−∑xp(x)logp(x)q(x)
在概率中,用相对熵的概念来度量两个分布间的不相似性。相对熵也叫做KL散度。
这三者之间的关系为:
H
(
p
,
q
)
=
−
∑
x
p
(
x
)
log
q
(
x
)
=
−
∑
x
p
(
x
)
log
p
(
x
)
−
∑
x
p
(
x
)
log
q
(
x
)
p
(
x
)
=
H
(
p
)
+
K
L
(
p
∥
q
)
(1.21)
\begin{aligned} H(p, q) &=-\sum_{x} p(x) \log q(x) \\ &=-\sum_{x} p(x) \log p(x)-\sum_{x} p(x) \log \frac{q(x)}{p(x)} \\ &=H(p)+K L(p \| q) \end{aligned}\tag{1.21}
H(p,q)=−x∑p(x)logq(x)=−x∑p(x)logp(x)−x∑p(x)logp(x)q(x)=H(p)+KL(p∥q)(1.21)
即交叉熵等于熵加上相对熵。
那么我们现在想要描述分类器预测的分布
q
(
x
)
q(x)
q(x) 和真实的分布
p
(
x
)
p(x)
p(x) 间的关系,我们将其带入到式(1.21)中,得到:
H
(
p
,
q
)
=
−
∑
i
=
1
c
p
(
x
i
)
log
(
q
(
x
i
)
)
(1.22)
H(p, q)=-\sum_{i=1}^{c} \mathrm{p}\left(x_{i}\right) \log \left(\mathrm{q}\left(x_{i}\right)\right)\tag{1.22}
H(p,q)=−i=1∑cp(xi)log(q(xi))(1.22)
因为真实值p(x)是one-hot形式,只有x等于真实类别的时候才为1,那么
H
(
p
)
=
0
H(p)=0
H(p)=0 ,此时P(x)和q(x)的概率分布的交叉熵和相对熵相等。
所以:
L
i
=
−
l
o
g
(
q
j
)
j
为
真
实
类
别
(1.23)
L_i=-log(q_j)\tag{1.23}\ \ \ j为真实类别
Li=−log(qj) j为真实类别(1.23)
式(1.23)表明,在真实值为one-hot的形式时,第i张图片所得到的损失为预测值SOFTMAX形式在真实类别上的负对数。
为什么要引入交叉熵损失呢?看下面这个例子,有三组预测分数,其中第一个元素为真实类别所对应的预测分数

可以看到,此时的多类支撑向量机损失函数都是0,而交叉熵损失并不全是0。可以看出交叉熵损失更加精确。它们的意义是不一样的。多类支撑向量机损失是只要我自己高,那么损失就是0,而交叉熵损失是我自己高的同时,别人还要低。
1.2.5计算图
计算图是一种有向图,它用来表达输入和输出以及中间变量之间的计算关系,图中的每个节点代表着一种数学运算。

a.计算图的前向和反向计算

- 任意的复杂函数,都可以用计算图来表示。
- 在整个计算图中,每个门都会得到一个输入,然后需要计算两个东西,一个是这个门的输出值,另一个是计算这个输出值关于输入值的局部导数
- 利用链式求导法则,门单元可以将回传梯度和其上一个门单元的梯度进行相乘,从而得到整个网络的输出对每个输入值的梯度。

反向计算时,先让各个门单元进行求导,得到局部导数,再将各个门单元的输入带入到局部导数中,得到导数具体数值,最后将所有局部导数相乘,便得到最后的输出对出入的导数。
b.计算图的颗粒度
计算图的各个门单元可以是最基本的数学运算,但也可以由基本的数学运算合成的复杂数学运算,此时就是大颗粒度。当颗粒度较大时,计算速度较快,但是求导比较麻烦。而小颗粒度运算速度慢,但是求导很简单。
c.梯度爆炸和梯度消失
现在我们再重新看激活函数
当输入的数值较大时,sigmoid函数的梯度都为0,非常不利于梯度流在计算图中的反向传播,同样tanh函数也是如此。
而ReLU函数在较大时,梯度永远不会为0,比较有利于梯度的反向传播。
Leakly ReLU函数的梯度永远不会为0,但在输入为0处没有导数。
如果某一个门的局部梯度为0或者是某几个门的梯度都很小,此时相乘下去,就会造成输出对输入的梯度为0,这就是梯度消失,这就回造成参数无法获得更新。这就好比,损失函数是一座山,这个山有一个高海拔平原,生活在平原上的人就不知道还有比这个平原低的地方。这就会造成训练失败。
相反,梯度爆炸就是因为链式相乘,梯度越乘越大,这就会导致参数更新时学习率过大,从而导致算法不收敛。如果把步长限制到某一范围内,便可以解决这个问题,这种方法也称为梯度裁剪。
1.2.6改进梯度算法
a.之前的算法存在的问题
对于损失函数来说,有可能在一个维度上变化的缓慢,在另一个维度上又震荡,导致不能收敛。
就像这幅图所描述的那样。因此需要将原来的算法进行改进。
b.动量法
利用累加历史梯度信息更新梯度。
为什么这种方法有效呢?
因为在震荡方向上,梯度可以相互抵消,在平坦方向上,梯度可以累加。
这里的 μ \mu μ 是一个超参数,取值范围是0到1。它的作用是,当梯度为0时,它可以作为一个衰减系数,让速度更新值变为0 。
另外,在优化的过程中,经常会遇到局部最小值的问题,动量法还可以使其冲出局部最小值点或者是鞍点。
c.自适应梯度与RMSProp
自适应梯度法就是改变学习率(注意是改变学习率,也就是步长,根据梯度的幅值平方来调整学习率),通过减小震荡方向步长,增大平坦方向步长来使算法收敛的。
是如何区分震荡和平坦方向的呢?
梯度幅值的平方较大的方向是震荡方向,幅值的平方较小的方向是平坦方向。
RMSProp就是一种自适应梯度算法。
对于陡峭的时候,r就会很大,r作为分母,此时会使步长变得很小。对于平坦区域,r就会很小,此时的步长就会变得很大。
此处加上超参数 ρ \rho ρ ,就是防止r无限增大, ρ \rho ρ 的取值范围为0到1,当 ρ \rho ρ 很大时,就表示历史的 r 考虑的较多。当 ρ \rho ρ 很小时,表示历史的r
的影响较少。
d.Adam方法
将动量法和自适应梯度方法结合在一起。

在这里有一个修正操作,是防止初始的时候的梯度过小。
1.2.7权值初始化
a.不好的初始化
(1)全零初始化
如果将所有权值参数都初始化为0或者是同一个常数,那么所有的神经元都是一样的。这是不可以的。
(2)随机权值初始化
例如:有10个隐层,1个输出层,每个隐层包含500个神经元,使用双曲正切激活函数。
此时我们采用随机初始化,权值参数的数值采样自 N ( 0 , 0.01 ) N(0,0.01) N(0,0.01) 的高斯分布。
我们输入一组符合正态分布的向量。
现在看个层的输出,第一层的时候,还可以看到也是一个正态分布,但是当过了3层之后,每一层的输出都为0。
这就导致了信息无法正确的传到神经网络的最后面,就不会有反向的梯度来更新我们的权值参数。
现在我们把权值参数的采样更改一下,变为 N ( 0 , 1 ) N(0,1) N(0,1) ,但是此时各层的输出如下:
几乎所有的神经元都饱和了,此时神经元的局部梯度都是0,最终参数也得不到更新。
所以初始化不好,网络是没有办法被训练的。有效的初始化方法就是正向的信息流能传到后面,反向的梯度能传回来。
b.Xavier初始化
我们的目标就是使网络各层的激活值和局部梯度的 方差 在传播过程中尽量保持一致,也就是寻找权值 w 的分布,使得输出 y 和输入 z 的方差一致。
现在假设:
一个神经元的输入为 z 1 , z 2 , ⋯ , z n z_1,z_2,\cdots,z_n z1,z2,⋯,zn , z i z_i zi 是一个数。它们是独立同分布的。
这个神经元的权值
w
1
,
w
2
,
⋯
,
w
n
w_1,w_2,\cdots,w_n
w1,w2,⋯,wn ,他们也是独立同分布的。且w和z是独立的,均值为0。其激活函数为
f
f
f ,最终的输出值为y。
y
=
f
(
w
1
∗
z
1
+
⋯
+
w
n
∗
z
n
)
(1.24)
y=f\left(w_{1} * z_{1}+\cdots+w_{n} * z_{n}\right)\tag{1.24}
y=f(w1∗z1+⋯+wn∗zn)(1.24)
继续假设激活函数
f
f
f 为tanh,(1.24)括号内的值域为-2到2,此时
f
f
f 就是一个正比例函数,即
y
=
w
1
∗
z
1
+
⋯
+
w
n
∗
z
n
(1.25)
y=w_{1} * z_{1}+\cdots+w_{n} * z_{n}\tag{1.25}
y=w1∗z1+⋯+wn∗zn(1.25)
那么 y 的方差为:
Var
(
y
)
=
Var
(
∑
i
=
1
n
w
i
z
i
)
=
∑
i
=
1
n
Var
(
w
i
z
i
)
=
∑
i
n
[
E
(
w
i
)
]
2
Var
(
z
i
)
+
[
E
(
z
i
)
]
2
Var
(
w
i
)
+
Var
(
w
i
)
Var
(
z
i
)
=
∑
i
n
Var
(
w
i
)
Var
(
z
i
)
=
n
Var
(
w
i
)
Var
(
z
i
)
(1.26)
\begin{aligned} \operatorname{Var}(y) &=\operatorname{Var}\left(\sum_{i=1}^{n} w_{i} z_{i}\right)=\sum_{i=1}^{n} \operatorname{Var}\left(w_{i} z_{i}\right) \\ &=\sum_{i}^{n}\left[E\left(w_{i}\right)\right]^{2} \operatorname{Var}\left(\mathrm{z}_{i}\right)+\left[E\left(z_{i}\right)\right]^{2} \operatorname{Var}\left(w_{i}\right)+\operatorname{Var}\left(w_{i}\right) \operatorname{Var}\left(z_{i}\right) \\ &=\sum_{i}^{n} \operatorname{Var}\left(w_{i}\right) \operatorname{Var}\left(z_{i}\right) \\ &=n \operatorname{Var}\left(\mathrm{w}_{i}\right) \operatorname{Var}\left(z_{i}\right) \end{aligned}\tag{1.26}
Var(y)=Var(i=1∑nwizi)=i=1∑nVar(wizi)=i∑n[E(wi)]2Var(zi)+[E(zi)]2Var(wi)+Var(wi)Var(zi)=i∑nVar(wi)Var(zi)=nVar(wi)Var(zi)(1.26)
此时,如果想要使y的方差和输入z一样,就令w的方差为1/n。
所以,我们令权值的采样分布更改为 N ( 0 , 1 / n ) N(0,1/n) N(0,1/n) ,那么就可以让输入和输出同分布。这就是Xavier初始化。
但是对ReLU激活函数,Xavier的效果不是很好。
此时用何凯明研究员提出的初始化方法。
权值的采样分布更改为 N ( 0 , 2 / n ) N(0,2/n) N(0,2/n) 。效果如下:
1.2.8批归一化(BN)
之前的权值初始化是为了在训练时,网络可以正常传递输入信息,现在我们试着改变一下网络的结构,来保证信息可以安全的传递。
批归一化的思想不是从权值初始化考虑的,而是对数据输出数据进行处理,因为我们最终的目标是使输出和输入同分布。
批归一化就是对神经元的输出(也就是下一层神经元的输入)直接进行批归一化,批归一化就是对输出减均值,除标准差。
例如,小批量梯度下降算法,每次迭代会输入一批数据,假如有32个样本,经过神经元后,会有32个输出值。我们求出这32个输出值的平均值和标准差,然后对每个输出值进行减平均值,除标准差的操作。然后处理后的数据作为下一层神经元的输入。
批归一化操作通常会插入到全连接层之后,非线性激活之前,这样效果更好。

这里的FC就是加权计算,BN是批归一化操作。

因为,输入数据经过正常全连接加权后,为进行激活函数计算之前,通常落在上面左图红色的区域,这个区域的数值输入到激活函数中,会得到-1或1,那么此时的局部梯度为0,不利于神经网络的反向梯度传播。而通过批归一化后,数据会落在上面右图中间的红色区域,激活函数在此处的梯度不为0。

上面的 x i x_i xi 是上一层神经元的加权输出(还未经过激活函数处理),然后进行批归一化处理,但是请注意还有一步,就是对批归一化后的数据进行平移和放缩(也就是改变其均值和方差),然后通过训练,让神经网络自己找出合适的参数 γ 和 β \gamma 和\beta γ和β 。因为0均值,1方差不一定对训练好,让网络自己选择。
上面都是在批量数据的计算时,可以计算出数据的均值和方差,但是当预测的时候,只输入一个样本,均值和方差该如何取呢?
这个均值和方差就是在训练时,每一次迭代所产生的均值和方差,进行累加求平均。
1.2.9欠拟合和过拟合
欠拟合表示模型太简单,就好比一个小学生,去学大学数学,如果小学生能学明白,就幼儿园小朋友,他的大脑还没有发育完全,所以是学不了的。
而过拟合表示训练的太好,仅对训练集中的数据进行处理,可以获得较准确的数据。这就好比有两个学生,小李只会死记硬背,小蔡会学习做题方法。这样,在考试的时候,如果出了过去出过的题,小李就肯定占优势了,小蔡不一定能考过小李,但是当出过未出过的题,那么小李就傻了,因为他没有见过,所以铁定不会。小李就是过拟合现象,只记下了每张图片的样子,而没有学习到这些图片共同的特征。
在实际的应用中,欠拟合很好解决,只需要提高模型的复杂程度。而过拟合就不那么好解决了。
机器学习最根本的问题就是优化和泛化问题。
- 优化—是指调节模型参数以在训练数据上得到最佳性能。
- 泛化—是指训练好的模型在未见过的数据上性能好坏。

通常情况下,在训练初期,优化和泛化是相关的,训练集上的误差越小,验证集上的误差也小。这表明模型的泛化能力在增强。
但是到了后期,模型在验证集上的错误率开始增加,而在训练集上的误差仍在降低。此时就说明模型出现了过拟合,模型开始学习仅和训练数据有关的模式。
那么应对过拟合,从大方向来说有两种办法:
- 最优方案:增加训练集规模。
- 次优方案:调节模型允许存储信息量或对模型允许存储的信息加以约束,该方法也称为正则化。
a.调节模型大小
比如可以减少神经网络的层数或者是神经元的数量。
b.约束模型权重
也就是在损失函数中引入正则化项,鼓励模型的权重更加分散。
c.随机失活(Dropout)
就是在训练的时候,让某一层的一部分神经元不被激活,也就是该神经元的输出值为0。
这里有一个超参数,即随机失活比率,失活神经元所占的比例,通常为0.2—0.5。
那么随机失活为什么可以解决过拟合呢?
(1)随机失活可以使得每次更新梯度时,参与计算的网络参数减少,降低了模型容量,所以防止了过拟合。
(2)随机失活鼓励权重分散,就和损失函数引入正则项一样。当某一些神经元失活后,剩下的神经元就要记住更多的信息。
(3)一块神经网络,相当于多个神经网络。在神经元总数不变的情况下,分别训练不同的组合,使的每一个拿出来都可以起到全部的作用,这样在预测的时候,就相当于多个神经网络在做决策。
但在使用的时候,还需注意一些东西,例如有如下结构:

假设失活比率为0.5,那么此时有可能会有x失活,y失活,x和y都失活。那么a的均值就为:
E
[
a
]
=
1
4
(
w
1
x
+
w
2
y
)
+
1
4
(
w
1
x
+
0
y
)
+
1
4
(
0
x
+
w
2
y
)
+
1
4
(
0
x
+
0
y
)
=
1
2
(
w
1
x
+
w
2
y
)
(1.27)
\begin{aligned} E[a]&= \frac{1}{4}\left(w_{1} x+w_{2} y\right)+\frac{1}{4}\left(w_{1} x+0 y\right)+\frac{1}{4}\left(0 x+w_{2} y\right)+\frac{1}{4}(0 x+0 y) \\ &=\frac{1}{2}\left(w_{1} x+w_{2} y\right) \end{aligned}\tag{1.27}
E[a]=41(w1x+w2y)+41(w1x+0y)+41(0x+w2y)+41(0x+0y)=21(w1x+w2y)(1.27)
此时,在测试的时候,是没有失活的,因此测试的均值为:
E
[
a
]
=
w
1
x
+
w
2
y
(1.28)
E[a]=w_{1} x+w_{2} y \tag{1.28}
E[a]=w1x+w2y(1.28)
测试时的输出值和训练时的输出值的范围是不一样的,所以在测试的时候,还需要将输出值乘上0.5。
1.2.10超参数选取
超参数就是我们需要设置的参数。
对于网络结构—有隐层神经元个数,网络层数,激活函数的选择等参数。
对于优化相关—有学习率,失活比率,正则化强度等参数。
我们就以学习率为例,来说明如何选参数。

学习率要适中,才能快速收敛,性能良好。如果太大,不能收敛。偏大,最小值附近震荡。偏小,收敛时间太长。
a.搜索方法

对于两个超参数,可以用规范的网格进行选取。带到模型中,比较性能。

也可在某一范围随机选取几个点。
b.搜索策略
先粗略,后精细。

c.参数的标尺空间
学习率通常在0.00001到1之间,如果在正常的数轴下,由于量级相差太大,意义不大,所以要在log空间中,进行标尺。

2.卷积神经网络
2.0补充知识
2.0.1卷积与图像去噪

去除图像中的噪点,一个最直接的办法就是和周围的像素点的灰度值进行加权求和。如下图:

每一个像素点都经过该操作后,就得到了一张新的去噪后的图片。这里的操作就叫作卷积操作。
而卷积操作中的加权的权值,我们将其存储在一个模版中,我们称其为卷积核。
卷积操作的示意图:
其中,下面蓝色的为输入图片,绿色的为卷积后的图片,下面灰色阴影部分即为卷积核。
a.卷积的定义
H为卷积核,F为输入图像,R为卷积操作后的图像,输出图像每一个像素点的灰度值为:
R
i
j
=
∑
u
,
v
H
i
−
u
,
j
−
v
F
u
,
v
(2.1)
R_{ij}=\sum_{u,v}H_{i-u,j-v}F_{u,v}\tag{2.1}
Rij=u,v∑Hi−u,j−vFu,v(2.1)
式(2.1)表示,输出图像中的一个像素点的灰度值的计算方法。其中
i
,
j
i,j
i,j 为输出图像中的像素点坐标,
u
,
v
u,v
u,v 为
i
,
j
i,j
i,j 点和其周围
n
×
n
n\times n
n×n (n为卷积核阶数)个点的坐标。
特别这里要注意的是,卷积操作是将卷积核旋转180度后,在与对应的像素点的灰度值相乘求和,如下图:

但实际过程中,我们的卷积核往往是对称的,我们常常忽略这个旋转,或者说,我们所说的卷积核是旋转过后的,但实际上是要经过一个旋转的,后面所说的卷积核就都为旋转后的。
b.卷积的性质
- 叠加性:两个图像求和以后的卷积等于两个图像分别卷积再求和。
- 平移不变性:对于一张图片先平移再卷积和先卷积再平移的结果是一样的。(所有的平移操作都可以用卷积来实现)
- 交换律
- 结合律
- 分配律
- 标量
卷积是一种基础的图像操作。
c.边界填充
在计算卷积的时候,边上的像素点的周围没有像素,所以要进行边界填充。如果不进行边界填充,卷积过后的图像会比原图像小一圈。

(1)零填充(Zero padding)
填充周围像素点的值为0。在深度学习中常用。

(2)拉伸和镜像

拉伸填充就是把现有的图像边上拉出去一点,让扩充的像素点的值和图像的边缘的值相同。
镜像拉伸就是让左边的扩充像素值等于右边图片边界像素的值,右边和上下也是一样。
d.卷积示例
(1)单位脉冲核
(2)移动卷积核
(3)平滑卷积核
相当于磨皮,可以去噪,但是边缘也变得不明显了。
(4)锐化卷积核
因为卷积的性质有分配律,所以该相减的两个卷积核的结果和图像卷积=这两个卷积核分别与图像卷积后再相减。
那么为什么会锐化呢?
我们先来看原图减去平滑图等于什么。
以灰度图为例:假设图像中某一像素点A的灰度值为100,周围其他点的灰度值为25。A点的灰度值相较于周围点明显不同。当卷积核为3*3,那么平滑后的图像A点的灰度值会变为 300 ÷ 9 = 30 300\div9=30 300÷9=30,周围其他点的灰度值会稍稍变大,也为30,当原图减去平滑后的图像后,A点的灰度值为 100 − 30 = 70 100-30=70 100−30=70 ,周围其他点的灰度值为 25 − 30 = − 5 25-30=-5 25−30=−5 。
而一像素点B,灰度值为100,周围点灰度值为90,平滑后B点灰度值为90多,其他点的灰度值也差不多,所以原图减去平滑后的图,B点的灰度值不到10,其他点的灰度值也很小。
此可见,整张图像的灰度值都降低,灰度值相较于周围其他点明显不同的地方,会将周边的灰度值降到很小,而灰度值原本很高的地方稍稍降低。但当灰度值变化不明显的地方,整体的灰度值都降到很低。因此,原图减去平滑后的图像得到的是边缘图像。
当边缘图再加上原图后,就可以让图像边缘的地方再次加深,得到锐化效果。
因此锐化卷积核的过程如下:
e.高斯卷积核

左边这幅图经过平滑卷积后,得到右边这幅图,但看右边的图,可以发现有上下左右的横线的感觉,这种现象叫做振铃,造成这种现象的原因是,在加权的时候,各个部分的权值都一样,即使远的地方,权值也一样。为了改变这种情况,引入高斯卷积核。
高斯卷积核就是让中心位置的权值最大,越往边缘,权值越小。
G
σ
=
1
2
π
σ
2
e
−
(
x
2
+
y
2
)
2
σ
2
(2.2)
G_{\sigma}=\frac{1}{2 \pi \sigma^{2}} e^{-\frac{\left(x^{2}+y^{2}\right)}{2 \sigma^{2}}}\tag{2.2}
Gσ=2πσ21e−2σ2(x2+y2)(2.2)
(1)生成步骤
- 确定卷积核的大小
- 设置高斯函数的标准差
- 通过式(2.2)计算卷积核各个位置的权值
- 对权重进行归一化,也就是所有权值之和为1
为什么权重要进行归一化?
例如一张图,所有灰度值为255,如果权重没有归一化,之和为0.1,那么会对整张图片的灰度降低为原来的0.1,如果权重和为2,就会对整张图片的灰度值增长为原来的2倍。归一化的目的就是保证图像的灰度值在原来的范围内。
(2)方差变化的影响
当窗口大小一样时:
方差较小时,中间自身的权重较大,所以平滑的就不厉害。
而方差越大,中间自身的权重值较小,所以平滑的就不厉害。
(3)窗口变化的影响
当方差一样时:
中间的高斯函数值虽然相同。但是窗口越大,归一化后,中间所占的权重越小,所以周围的影响较大,平滑效果越明显。
反之,窗口越小,归一化后,中间所占的权重越大,周围的影响越小,平滑效果越弱。
有一个经验法则:通常卷积模版的尺寸为 2 × 3 σ + 1 2\times3\sigma+1 2×3σ+1 ,如标准差为1,那么高斯卷积核的大小为 7 × 7 7\times7 7×7 。
(4)高斯卷积核的性质
- 高斯卷积核的功能是一个低通滤波器,低通滤波器的意思就是可以过滤到高频噪声(高频噪声可以理解为噪点)。
- 两个高斯卷积核卷积后得到的还是高斯卷积核。

- 可分离性,可分解两个一维高斯的乘积(该性质可以极大减少计算量)。
eg:不考虑扩充
为什么说可以减少计算量呢?
用尺寸为 m × m m\times m m×m 的卷积核卷积一个尺寸为 n × n n\times n n×n 的图像,其计算复杂度为 n 2 m 2 n^2m^2 n2m2 。
如果用小方差的小模板来卷积,例如,两个卷积核的标准差为1,模板的尺寸为 2 × 3 × 1 + 1 = 7 2\times3\times1+1=7 2×3×1+1=7 ,此时的计算复杂度为 49 n 2 49n^2 49n2。
而如果直接用标准差为 2 \sqrt{2} 2 的卷积模板,模板尺寸为 2 × 3 × 2 + 1 = 9 2\times3\times\sqrt{2}+1=9 2×3×2+1=9 ,此时计算复杂度为 81 n 2 81n^2 81n2 。这两个卷积核的计算效果完全一样。
另外,如果将卷积核分离为两个一维的核,计算复杂度为 n 2 m n^2m n2m 。
f.图像噪声

椒盐噪声:黑色像素核白色像素随机出现。
脉冲噪声:白色像素随机出现。
高斯噪声:噪声强度变化服从高斯分布。
f
^
(
x
,
y
)
=
f
(
x
,
y
)
+
η
(
x
,
y
)
其
中
η
(
x
,
y
)
→
N
(
μ
,
σ
)
(2.3)
\hat f(x,y)=f(x,y)+\eta(x,y)\quad\quad其中\eta(x,y)\rightarrow N(\mu,\sigma)\tag{2.3}
f^(x,y)=f(x,y)+η(x,y)其中η(x,y)→N(μ,σ)(2.3)
那么如何减少高斯噪声呢,当然是用高斯卷积核卷它了。
通过上图可以看出,方差越大,高斯噪声越明显。所以也需要方差更大的卷积核来平滑(当然方差增大,窗口也变大)。
g.中值滤波
但是对于椒盐噪声和脉冲噪声,高斯卷积核的去噪效果就不好了。
此时需要使用中值滤波来处理。
中值滤波卷积核是空的,它是将窗口大小的数据都取出来,从小到大排列,然后取中间值为该像素点的灰度值。

2.0.2卷积与边缘提取
边缘是图像中亮度明显而急剧变化的点。
为什么要研究边缘呢?
- 是图像中的语义与形状信息。
- 相对于像素表示,边缘表示显然更加紧凑。
a.边缘的种类
b.图像的导数

2维函数的求偏导公式为:
∂
f
(
x
,
y
)
∂
x
=
lim
ε
→
0
f
(
x
+
ε
,
y
)
−
f
(
x
,
y
)
ε
(2.4)
\frac{\partial f(x, y)}{\partial x}=\lim _{\varepsilon \rightarrow 0} \frac{f(x+\varepsilon, y)-f(x, y)}{\varepsilon}\tag{2.4}
∂x∂f(x,y)=ε→0limεf(x+ε,y)−f(x,y)(2.4)
因为这样求比较麻烦,要考虑无穷小量,所以图像求导公式为:
∂
f
(
x
,
y
)
∂
x
=
f
(
x
+
1
,
y
)
−
f
(
x
,
y
)
1
(2.5)
\frac{\partial f(x, y)}{\partial x}= \frac{f(x+1, y)-f(x, y)}{1}\tag{2.5}
∂x∂f(x,y)=1f(x+1,y)−f(x,y)(2.5)
也就是右边的像素值减去左边的像素值。也可以用卷积核来表示:

对x方向求导,得到的是y方向的边,对y方向求导,得到的是x方向的边。

c.图像的梯度
图像的梯度指向灰度变化最快的方向(也就是从暗到亮)。

梯度方向和边缘垂直。
梯度的模值越大,该点为边缘点的可能性越高。

我们用梯度的模值来表示边缘信息,也就是边缘检测。
d.噪声的影响
如果图像存在噪声,边缘检测就会很难。所以需要先将图像平滑。根据噪声的种类选择平滑方法。
例如,如果是高斯噪声,就用高斯卷积核来处理。

因为图像的微分操作也是一个卷积,卷积符合交换律,所以可以将其处理顺序颠倒一下。
d
(
f
∗
g
)
d
x
=
f
∗
d
g
d
x
(2.6)
\frac{d(f*g)}{dx}=f*\frac{dg}{dx}\tag{2.6}
dxd(f∗g)=f∗dxdg(2.6)
e.高斯一阶偏导卷积核
(2.6)也叫做高斯一阶偏导卷积核。

高斯一阶导只有一个参数,即标准差 σ \sigma σ ,下面来看该参数对边缘提取的影响。

当标准差不同时,提取的边缘的粒度不同,如果小粒度细节,就采用标准差小的卷积核。
但是高斯一阶卷积核所提取的边缘有一个缺点,就是边缘过粗,这是因为像素灰度值变化通常是连续的,因此求导后,在一定范围内都有较大的导数值。如下图所示:

此时引入一种方法,非最大值抑制。
f.非最大值抑制
沿着边缘的梯度方向,保留边缘上值最大的点。
例如:


找到边缘上的三个点p,q,r。现在就比较这三个点的梯度强度,保留梯度强度最大的点。
注意:通常情况下,q,r的坐标不是整数,需要插值。
g.Canny边缘检测器
非最大值抑制以后,还有一个问题。
如果存在噪声,我们需要设置一个门限来过滤一下,如果门限过高, 许多细节边就显现不出来了;如果门限过低,就有太多的细节都出来。

所以这个门限不太好设置。Canny算法选取双域值,先用高域值提取出主要的边缘,在用低域值,找出细节,保留和之前高域值提取出的边缘相连的边缘。
2.0.3纹理表示
纹理分为规则纹理和随机纹理。

想要表示这些纹理,规则的还好,形状大小都几乎相同。但是对于随机纹理的提取,就十分困难了。
有一个思路,就是用卷积核组来提取图像中的纹理,然后用基元的统计信息来表示图像中的纹理。
a.卷积核组
由多个卷积核组成的一个卷积核组。
前面学过,高斯一阶卷积核,如上图左边,它可以提取出x方向的边缘。其他的卷积核也类似。特别的,最后一个卷积核可以提取出环形的边缘。


b.基于卷积核组的图像表示
在设计出一组卷积核组后,我们用这组卷积核来对图像进行卷积操作,获得对应的特征响应图组。然后再用特征响应图组的统计信息,来表示图像中的纹理。
eg:
r i r_i ri 是将得到的一幅特征响应图拉成的向量,例如原图为 100 × 100 100\times 100 100×100的尺寸,卷积后得到的特征响应图也为 100 × 100 100\times 100 100×100 ,拉成向量就是10000维的向量。在这个向量中,包括了提取出的边缘形状信息,也包括边缘所处的位置信息。但是我们是要表现出纹理特征,从而制定一种描述纹理特征的方式,所以位置信息是不重要的。因此采取的办法是将这个10000维的向量各个元素求平均,用平均值来表达该种边缘“有多少”。

eg:有下面三幅图,分别用卷积核组进行上述处理,该卷积核组共有7个卷积核。卷积后得到了一个7维的向量。这个向量中的每一个元素都表示对应的边缘有多少。

在这里,白色的代表值越大,就说明该种边缘在图中占据最多。
c.卷积核组的设计
卷积核组的设计要尽量包括各种边缘的类型,各种尺度,还有各个方向。
设计重点:
- 卷积核类型
- 卷积核尺度
- 卷积核方向
实际的例子:


这样我们便可以将一张图的纹理特征表示出来。
从图像的纹理表示可以隐隐的知道,卷积神经网络的原理了,就是通过卷积核组,将一张图片的纹理描述出来(也就是各种边缘的统计信息),然后通过对纹理特征,来进行分类。
2.1卷积神经网络结构
包括四个部分:
- CONV——卷积层
- RELU——激活层
- POOL——池化层
- FC——全连接层
2.1.1全连接神经网络的瓶颈
当图像太大时,需要训练的权值参数太多。
例如,CIFAR10图像尺寸为 32 × 32 × 3 32\times32\times3 32×32×3 ,隐层中的每个神经元的权值个数就为 3072个。
如果图像是 200 × 200 × 3 200\times200\times3 200×200×3 ,那么隐层中的每个神经元的权值个数就为120000个。
如果权值参数过多,计算量大不说,也很容易造成过拟合。
所以全连接神经网络仅适合处理小的图像。
怎么才能获得小图像呢,可以看到,当图像经过卷积核组卷积后,对输出值进行加权,就可以得到一个维度很小的向量,所以我们想将图像先经过卷积核组处理,然后得到一个维数较低的向量,在把这个向量作为全连接神经网络的输入。
2.1.2卷积层
a.卷积网络中的卷积核
与前面所学的卷积核不同的是,卷积神经网络中的卷积核是一个“立体的”。
因为图像通常是彩色的,每个像素点有RGB三个通道,所以卷积核需要对每个通道进行卷积操作,因此卷积核是一个立体的。

另外一个不同时,卷积核还有一个偏置。也就是卷积过后,对得到的结果再加上一个偏置值。

b.卷积网络中的卷积操作

一个三通道图经过卷积核卷积后,就得到了一个特征响应图,该响应图为1个通道,在没有边界补充的情况下,得到的特征响应图是 28 × 28 × 1 28\times28\times1 28×28×1 。

如果用6个卷积核,卷积后就得到6个特征响应图。

总结:
- 特征响应图组深度等于卷积核的个数。
- 不同特征响应图反映了输入图像对不同卷积核的响应结果
- 同一特征响应图上不同位置的值表示输入图像上不同位置对同一卷积核的响应结果。
c.卷积步长
卷积神经网络中,卷积核可以按照指定的间隔进行卷积操作,这个间隔就是卷积步长。
卷积步长可以影响输出的特征响应图的大小。


eg:输入图像为7,卷积核大小为3,步长为1。
输出图像大小=(7-3)/1 +1=5
d.边界填充
如果没有边界填充,如前面的例子,卷积操作后会使图像变小。
而卷积神经网络中常用的填充方式是零值填充。

边界填充与输入输出图像大小还有卷积步长之间的关系为:
W
2
=
(
W
1
−
F
+
2
P
)
/
S
+
1
H
2
=
(
H
2
−
F
+
2
P
)
/
S
+
1
(2.8)
\begin{aligned} &W 2=(W 1-F+2 P) / S+1 \\ &H 2=(H 2-F+2 P) / S+1 \end{aligned}\tag{2.8}
W2=(W1−F+2P)/S+1H2=(H2−F+2P)/S+1(2.8)
这里P是一边填充的层数,如上图就是填充了1层。
通过式(2.8)还可以已知输入和输出图像,反求出填充层数。
e.特征响应图尺寸计算
由前面的学习,可知特征响应图的尺寸大小主要与以下几个参数有关:
- 卷积核的宽,高;
- 是否采用边界填充操作;
- 卷积步长;
- 该层的卷积核个数(主要影响特征响应图的深度)
以上这四个参数是超参数。
2.1.3池化层
卷积神经网络的结构如上图所示,先一层卷积层,然后接一个RELU激活函数层,就是让卷积后的图像每一个像素点的值都经过RELU激活函数。然后再经过一层POOL层,也就是池化层。
a.池化层的作用
之前的卷积操作时,每张图片有三个通道,所以一个卷积核也是3维的,对三个通道一同处理。当有n个卷积核组成一个卷积核组时,得到n个特征响应图,因此这个特征响应图是有n个通道的。
池化操作是对每一个特征响应图独立进行,降低特征响应图组中每个特征响应图的宽度和高度,减少后续卷积层的参数的数量,降低计算资源耗费,控制过拟合。因此池化操作后,仍然有n个特征响应图。
另外一点,缩小图像,卷积核大小不变,此时就相当于卷积核变大,就可以看到更大的纹理。
b.池化操作
对特征响应图某个区域进行池化就是在该区域上指定一个值来代表整个区域。
常见的池化操作:
最大池化:使用区域内的最大值来代表这个区域。
平均池化:采用区域内所有值的均值作为代表。

最大池化就相当于之前讲的非最大化值抑制,我们只保留一个区域的最大值,就是把最明显的特征表示出来。因此上图的最大池化操作后,特征响应图中的75%的响应信息都丢掉,但不改变特征响应图的个数。
在池化操作中,池化的步长和窗口大小是两个超参数。
在训练后的卷积神经网络中,前面的卷积层记录的是纹理基元信息,如边缘,圆环等等形状基元。越往后的卷积层记录的是高层的基元,可能是一个人脸的模版,只要图片中有人脸,它就会响应。
2.2图像增强
2.2.1图像增强的提出
存在问题:过拟合的原因是学习样本太少,导致无法训练出能够泛化到新数据的模型。
于是采用数据增强的办法,就是从现有的训练样本中生成更多的训练数据,其方法是利用多种能够生成可信图片的随机变换来增加样本。
数据增强的目标:模型在训练时不会两次查看完全相同的图像。这能够让模型观察到数据的更多内容,从而具有更好的泛化能力。
2.2.2样本增强的方法
a.翻转

b.随机缩放和抠图
得到一张图以后,对其进行缩放再截取抠图。相当于从多个视角看原有的图像中的内容。
以残差网络中的样本增强方法为例:
输入要求: 224 × 224 224\times224 224×224 的彩色图片。
在训练的时候:在不同尺度、不同区域随机扣取。
对于现有的训练数据集,有很多的图片,我们这样做:
- 先在[256,480]之间随机选择一个尺寸L。
- 将训练数据集中的图拍呢缩放至短边为L的图像。
- 在该缩放后的样本图像中,随机采样一个 224 × 224 224\times224 224×224 的图像区域。
在测试的时候:按照一套预先定义的方式扣取
- 将图像缩放成5种尺寸:{224,256,384,480,640}。
- 对每一个尺度的图像及其镜像图片,分别在四个角和中间位置扣取 224 × 224 224\times224 224×224 区域。
c.色彩抖动
3.经典网络分析
按照时间的顺序,介绍5种经典的卷积神经网络。这5种卷积神经网络在ImageNet大赛上都取得了跨越式的成绩。
3.1AlexNet
2012年提出的该网络。其主要贡献有:
- 提出了一种卷积层和全连接层的神经网络结构
- 首次使用ReLU函数作为激活函数
- 首次提出Dropout正则化来控制过拟合
- 使用加入动量的小批量梯度下降算法加速了训练过程的收敛
- 使用数据增强策略极大的抑制了训练过程的过拟合
- 利用GPU并行计算,加速了网络的训练和推断
网络结构

AlexNet共有卷积层,池化层,局部响应归一化层,全连接层四部分组成,如上图所示。
补充:在计算神经网络层数时,仅统计卷积层和全连接层,因为池化层与归一化层仅对前面的卷积层的输出的特征图进行后处理,不单独算做一层。
AlexNet共有5个卷积层和3个全连接层。
3.1.1卷积层
第一层卷积(CONV1):96个 11 × 11 11\times11 11×11 的卷积核,步长为4,没有零填充。
ques:如果输入的是 227 × 227 × 3 227\times227\times3 227×227×3 的图像,输出的特征响应图的个数和尺寸?
( 227 − 11 ) / 4 + 1 = 96 (227-11)/4+1=96 (227−11)/4+1=96 个,因此输出的特征响应图是 96 × 96 × 1 96\times96\times1 96×96×1 ,共有96个。
ques:这层共有多少个参数?
96 × ( 11 × 11 × 3 + 1 ) = 35 k 96\times(11\times11\times3+1)=35k 96×(11×11×3+1)=35k ,因为每一个卷积核还有一个偏置。
所以经过该层卷积后,得到96个 96 × 96 96\times96 96×96 的特征响应图,然后特征响应图的每一个元素经过ReLU激活函数处理。
第二层卷积(CONV2):256个 5 × 5 5\times5 5×5 的卷积核,步长为1,使用零填充p=2。
另外需要注意的是,第二层卷积层处理的图像大小相对于第一层处理的图像大小,小了很多,这样就好比第二层的卷积层在原图上有着更大的视野。
第三层和第四层(CONV3,CONV4):384个 3 × 3 3\times3 3×3 卷积核,步长为1,使用零填充p=1。
第五层卷积(CONV5):256个 3 × 3 3\times3 3×3 的卷积核,步长为1,使用零填充p=1。
然后通过最大池化层进一步缩小特征图尺寸。
3.1.2池化层
Max POOL1:窗口大小为 3 × 3 3\times3 3×3 ,步长为2
它的作用是降低特征响应图的尺寸,对抗轻微的目标偏移带来的影响。这个对抗目标偏移就是在一定的区域内,选择数值最大的数作为该像素点的值,因为即使这个最大值偏移到该区域的别的像素,也会被采集,作为该点的值。
还要注意的是,窗口大小为 3 × 3 3\times3 3×3 ,步长是2,这在池化的过程中,会使窗口产生重叠,这样能够对抗过拟合。
ques:输入图片为
55
×
55
55\times55
55×55 ,池化后的尺寸?
(
55
−
3
)
/
2
+
1
=
27
(55-3)/2+1=27
(55−3)/2+1=27 ,特征响应图的个数不变。
该层的参数个数为0。
3.1.3局部归一化层
作用:
- 对局部神经元的活动创建竞争机制
- 响应比较大的值变得相对更大
- 抑制其他反馈小的神经元
- 增强模型的泛化能力
该方法现在的网络通常不用。
3.1.4全连接层
全连接神经网络分类器。
输入是特征响应图组,输出为图像类别概率。

将特征响应图组中的每一个特征响应图展开成一个向量,然后作为输入,输入到全连接层。
注意:卷积层和全连接层是共同训练的
3.1.5卷积层的作用
卷积层的作用就是提取图像的特征,低层的卷积层提取的是低等的结构基元,越高层的卷积层越具有语义信息,将这些基元进行组合,得到某种类别的结构信息。然后输入到全连接层进行分类。

3.2 ZFNet
ZFNet神经网络的结构与AlexNet的结构基本一致。
主要的改进有:
- 将第一个卷积层的卷积核大小改为7
- 将第二和第三个卷积层的卷积步长都设置为2
- 增加了第三和第四个卷积层的卷积核数量
第一层的卷积核改小,是防止细粒度信息丢失。
步长改小,防止图像的尺寸降低过快。
因为在后面的卷积层已经出现了语义信息,所以增加卷积核个数,有助于增强描述能力。
3.3 VGG

VGG卷积神经网络主要有两种结构,一个是16层,一个是19层。19层的精度略高,但是会占用计算资源,所以VGG16常用。
VGG16共有13个卷积层,3个全连接层。
共分为5段,CONV1——CONV5,每段的卷积层的卷积核个数都相同。
卷积层均采用大小为3的卷积核核ReLU激活函数。
池化层采用最大池化,窗口大小为2,步长为2。
每经过一次池化,后层的卷积核个数就增大一倍,直到512。
全连接层中采用了Dropout策略。
ques:小卷积核有哪些优势?
多个小尺寸卷积核串联可以得到与大尺寸卷积核相同的感受野。

同时,使用小卷积核串联,构建的神经网络更深,非线性更强,参数也更少。
假设,输入和输出的图像的个数均为C,这个C也就是深度值。
那么3个小卷积核串联的总参数为: ( 3 × 3 × C ) × C × 3 = 27 C 2 (3\times3\times C)\times C\times3=27C^2 (3×3×C)×C×3=27C2 ,就是尺寸 × \times × 尺寸 × \times × 深度 × \times × 卷积核个数 × \times × 3。
而用一个尺寸为7的大卷积核的参数个数为: ( 7 × 7 × C ) × C = 49 C 2 (7\times7\times C)\times C=49C^2 (7×7×C)×C=49C2 。
ques:为什么前四段的卷积层,每经过一次池化操作,卷积核个数就增加一倍?
池化操作可以减少特征图尺寸,降低显存占用。
增加卷积核个数有助于学习更多的结构特征,但会增加网络参数数量以及内存消耗。
一增一减的设计平衡了识别精度与存储计算的开销。
ques:为什么卷积核个数增加到512后就不再增加了?
最后一层卷积层与全连接层相连,第一层全连接层的参数个数为102M,占总参数的75%。
全连接网络第一层的参数个数是最后一层卷积层输出的特征图尺寸乘以个数。
3.4 GoogleNet
GoogleNet的创新点:
-
提出了一种Inception结构,它能保留输入信号中的更多特征信息。
-
去掉了AlexNet的前两个全连接层,并采用了平均池化,这一设计可以使参数大大减少。
-
在网络中引入辅助分类器,克服了训练过程中的梯度消失问题。

首先说一下纯串联结构的问题:
就是后层的卷积层只能处理前层输出的特征响应图,前层可能因为某些原因(比如感受野受限)丢失重要的信息,后层无法找回。
所以GoogleNet提出的Inception结构可以尽量保留输入信号更多的信息。

这个模块就是在该层设置不同尺寸大小的卷积核组,对输入图像进行处理,来提取不同尺度的特征,从而获得更多的信息。而MaxPOOL的作用是对原图数值比较大的地方进行扩张,就是让那一像素点周围的像素值都和它相同。
在该网络中,这个模块的结构如下图所示:

在大尺寸的卷积核前加上一层尺寸为1的卷积核组,对图像进行压缩处理,使图像的深度变为1。如下图:

可以看出,参数数量大约下降3倍。所以该结构的优点是层数更深,参数更少,计算效率更高,非线性表达能力更强。
GoogleNet共堆叠了9个Inception V1模块。
然后再卷积层核全连接层链接的地方,加入了一个平均池化模块,可以有效的降低全连接层的参数。

另外,在该神经网络中,还加入了辅助分类损失。如下图:

虽然ReLU激活函数可以一定程度的解决梯度消失的问题,但并不能完全解决深层网络难以训练的问题。离输出远的层就不如离输出近的层训练得好。所以让低层的卷积层也有损失函数,可以让低层的卷积层更好的被训练,也能加速整个网络的收敛速度。
在预测时,仅利用网络的最后的输出作为预测结果,忽略辅助分类器的输出。
ques:平均池化向量核直接展开向量化有什么区别?
特征响应图上的每个位置的值反映了图像对应位置的结构与卷积核记录的语义结构的相似程度。平均池化丢失了语义结构的空间位置信息。这样有利于提升卷积层提取到的特征的平移不变性。
ques:利用尺寸为1的卷积核进行压缩会损失信息么?

3.5 ResNet
首先考虑一个问题:持续的向一个基础的神经网络结构上面叠加更深的层数会发生什么?

如上图所示:测试集的误差增多,是因为过拟合造成的。但是训练集的误差不应该增加呀。
原因是当网络的层数增加,会造成正向信息流核反向梯度流传播不顺畅,使一些参数得不到训练。
ResNet卷积神经网络就是主要解决这样一个问题。
主要贡献:
- 提出了一种残差模块,通过堆叠残差模块可以构建任意深度的神经网络,而不会出现退化的情况。
- 提出了批归一化方法来对抗梯度消失,该方法降低了网络训练过程对于权重初始化的依赖。
- 提出了一种针对ReLU激活函数的初始化方法。
后两个问题前面都已经讲过,现在主要说第一点。
研究人员考虑这样一个问题,就是浅层网络学习了有效的分类模式后,如何有效的向上堆积新层来建立更深的网络,使其满足即使不能提升浅层网络的性能,深层网络也不应该降低性能。
这就引出了残差模块:

就是对输入图像进行卷积处理,然后与未经处理的输入图像进行叠加,这样做即使卷积操作后的输出是0,但是仍可以保证X继续输入到下一层。这样就保证了信息流的正向传递。这就有点像锐化操作,在保留原图的基础上,把感兴趣的特征再次叠加到原图上。
卷积层学习的变换为F(X),残差结构的输出为 H(X)。
H
(
X
)
=
F
(
X
)
+
X
(3.1)
H(X)=F(X)+X\tag{3.1}
H(X)=F(X)+X(3.1)
在反向梯度传递时:
∂
H
(
X
)
∂
X
=
∂
F
(
X
)
∂
X
+
1
(3.2)
\frac{\partial{H(X)}}{\partial{X}}=\frac{\partial{F(X)}}{\partial X}+1\tag{3.2}
∂X∂H(X)=∂X∂F(X)+1(3.2)
即使前面一项为0,但是梯度也不为0。
F
(
X
)
=
H
(
X
)
−
X
(3.3)
F(X)=H(X)-X\tag{3.3}
F(X)=H(X)−X(3.3)
其中 F(X) 为残差项,训练就是对该项进行训练。所以叫做残差模块。
ques:残差网络为什么性能这么好?
残差网络可以看作是一种集成模型。

残差网络和Inception V4是公认的推广性能最好的两个分类模型
4.其他任务
前面我们学习的都是针对图像分类任务提出的解决方案,现在讨论在应对其他任务时的解决方案。
- 分类问题:分类问题是对每一张图片进行分类,是整张图片的类别。
- 语义分割:本质上也是分类问题,与分类问题不同的是,需要对一张图片上的每一个像素点都进行分类,是像素级别的分类问题。
- 目标检测:是一个区域级别的分类问题。
- 实例分割: 对实例进行分割。类似于语义分割,但不同的是语义分割中,同一个类别的东西,标签都一样,例如有两只猫,这两只猫的标签是一样的。而实例分割中,这两只猫的标签是不同的。
4.1语义分割

4.1.1滑动窗口

该方法是,取一个滑动窗口,让每一个像素点和其周围的像素点作为一张图片,进行分类。
但是该方法有一个问题,就是滑动窗口,有很多重叠的区域的特征被反复计算,因此效率太低。
4.1.2 全卷积
采用全卷积神经网络进行学习。在卷积层中,卷积操作不改变图像的大小,即对每个像素点都进行分类,特征响应图的深度等于类别的数量。

但是该方法也存在一个弊端,那就是在卷积操作中,因为不改变图像的大小,所以会占用大量的显存,导致硬件条件不允许。
改进的方法就是改变卷积的结构,采用下采样和上采样过程。

所谓下采样,就是我们之前所说的,每经过一次卷积或者是池化,都会使图像的尺寸减小。
而上采样,与这个过程正好相反。上采样就是经过一次这样的处理,使图像尺寸变大。
经过这样的操作,就可以在中间层减小图像尺寸,从而降低显存的占用。而有可以满足对每个像素点进行分类。
4.1.3上采样方法
a.反池化操作
(1)Nearest Neighbor

就是对周围的像素赋予一样的值。
(2)Bed of Nails

对周围像素补0。
(3)Max Unpooling
这个与(2)不同的是,在池化时,记住每一个值的位置。反池化时,把这个值填到原来的位置上,其余的补0。

以上的方法在程序中,程序是固定的,也没有什么参数。
我们就想,可不可以通过加权的方式对周围的像素赋值,使其尺寸变大呢?加权的参数可不可以通过训练的方法得到呢?
这就引出了转置卷积的方法。
b.转置卷积
现在我们回顾一下卷积操作:
尺寸为3的卷积核,步长为2,零填充为1,输入一个尺寸为4的图像。

可以看到中间有两个窗口重叠的地方。
那么现在反过来,输入图像尺寸为2,输出为4。

可以知道,在卷积中,红色方块的值是从红色窗口中来的,蓝色方框的值是从蓝色窗口来的。重叠部分就表明,该部分的值既参与了红色方块值的计算,也参加了蓝色方块的计算。
所以重叠部分的值要经过这两个方块值的加权,才能还原回来,这个加权的参数就可以通过训练得到。
eg:一个一维的例子

还是一维的例子,假设有一个向量
[
a
,
b
,
c
,
d
]
T
[a,b,c,d]^T
[a,b,c,d]T ,现在有一个一维的卷积核
x
⃗
=
[
x
,
y
,
z
]
\vec x=[x,y,z]
x=[x,y,z] ,步长为1,零填充为1, 对其卷积,写成矩阵的形式为
[
x
y
z
0
0
0
0
x
y
z
0
0
0
0
x
y
z
0
0
0
0
x
y
z
]
[
0
a
b
c
d
0
]
=
[
a
y
+
b
z
a
x
+
b
y
+
c
z
b
x
+
c
y
+
d
z
c
x
+
d
y
]
(4.1)
\left[\begin{array}{cccccc} x & y & z & 0 & 0 & 0 \\ 0 & x & y & z& 0 & 0 \\ 0 & 0 & x & y & z & 0 \\ 0 & 0 & 0 & x & y & z \end{array}\right]\left[\begin{array}{l} 0 \\ a \\ b \\ c \\ d \\ 0 \end{array}\right]=\left[\begin{array}{c} a y+b z \\ a x+b y+c z \\ b x+c y+d z \\ c x+d y \end{array}\right]\tag{4.1}
⎣⎢⎢⎡x000yx00zyx00zyx00zy000z⎦⎥⎥⎤⎣⎢⎢⎢⎢⎢⎢⎡0abcd0⎦⎥⎥⎥⎥⎥⎥⎤=⎣⎢⎢⎡ay+bzax+by+czbx+cy+dzcx+dy⎦⎥⎥⎤(4.1)
(4.1)还可以写成:
X
∗
a
⃗
=
b
⃗
(4.2)
X*\vec a=\vec b\tag{4.2}
X∗a=b(4.2)
当我们想上采样时,只需要将(4.1)左边的矩阵进行转置,就可以得到大尺寸的图像。
[
x
0
0
0
y
x
0
0
z
y
x
0
0
z
y
x
0
0
z
y
0
0
0
z
]
[
a
b
c
d
]
=
[
a
x
a
y
+
b
x
a
z
+
b
y
+
c
x
b
z
+
c
y
+
d
x
c
z
+
d
y
d
z
]
(4.3)
\left[\begin{array}{cccc} x & 0 & 0 & 0 \\ y & x & 0 & 0 \\ z & y & x & 0 \\ 0 & z & y & x \\ 0 & 0 & z & y \\ 0 & 0 & 0 & z \end{array}\right]\left[\begin{array}{c} a \\ b \\ c \\ d \end{array}\right]=\left[\begin{array}{c} a x \\ a y+b x \\ a z+b y+c x \\ b z+c y+d x \\ c z+d y \\ d z \end{array}\right]\tag{4.3}
⎣⎢⎢⎢⎢⎢⎢⎡xyz0000xyz0000xyz0000xyz⎦⎥⎥⎥⎥⎥⎥⎤⎣⎢⎢⎡abcd⎦⎥⎥⎤=⎣⎢⎢⎢⎢⎢⎢⎡axay+bxaz+by+cxbz+cy+dxcz+dydz⎦⎥⎥⎥⎥⎥⎥⎤(4.3)
eg:二维的例子
就是我们图像处理的卷积核,有一个图像大小为4,卷积核大小为3,步长为1,零填充为1。
卷积核可以写成:
C
=
[
x
1
x
2
x
3
y
1
y
2
y
3
z
1
z
2
z
3
]
=
[
v
⃗
1
v
⃗
2
v
⃗
3
]
(4.4)
C=\left[\begin{array}{ccc} x_1&x_2&x_3\\ y_1&y_2&y_3\\ z_1&z_2&z_3 \end{array}\right]=[\vec v_1\ \vec v_2\ \vec v_3]\tag{4.4}
C=⎣⎡x1y1z1x2y2z2x3y3z3⎦⎤=[v1 v2 v3](4.4)
零填充后的图像可以写成:
I
=
[
0
0
0
0
0
0
0
a
1
a
2
a
3
a
4
0
0
b
1
b
2
b
3
b
4
0
0
c
1
c
2
c
3
c
4
0
0
d
1
d
2
d
3
d
4
0
0
0
0
0
0
0
]
=
[
i
⃗
1
i
⃗
2
i
⃗
3
i
⃗
4
i
⃗
5
i
⃗
6
]
(4.5)
I=\left[\begin{array}{cccccc} 0&0&0&0&0&0 \\ 0&a_1&a_2&a_3&a_4&0 \\ 0&b_1&b_2&b_3&b_4&0 \\ 0&c_1&c_2&c_3&c_4&0 \\ 0&d_1&d_2&d_3&d_4&0 \\ 0&0&0&0&0&0 \end{array}\right]=[\vec i_1\ \vec i_2\ \vec i_3\ \vec i_4\ \vec i_5\ \vec i_6]\tag{4.5}
I=⎣⎢⎢⎢⎢⎢⎢⎡0000000a1b1c1d100a2b2c2d200a3b3c3d300a4b4c4d40000000⎦⎥⎥⎥⎥⎥⎥⎤=[i1 i2 i3 i4 i5 i6](4.5)
那么卷积核中的向量
v
⃗
i
\vec v_i
vi 对应的卷积矩阵为
X
i
是
4
×
6
X_i是{4\times 6}
Xi是4×6维 ,所以图像的卷积可以表示成:
C
∗
I
=
[
X
1
i
⃗
n
+
X
2
i
⃗
n
+
1
+
X
3
i
⃗
n
+
2
]
4
×
4
=
[
X
1
X
2
X
3
]
4
×
18
[
i
⃗
n
i
⃗
n
+
1
i
⃗
n
+
2
]
18
×
1
n
=
1
,
2
,
3
,
4
(4.6)
\begin{aligned}{} C*I&=[X_1\vec i_n+X_2\vec i_{n+1}+X_3\vec i_{n+2}]_{4\times4}\\ &=[X_1\quad X_2\quad X_3]_{4\times 18} \left[\begin{array}{l} \vec i_n\\\vec i_{n+1}\\ \vec i_{n+2} \end{array}\right]_{18\times1} \end{aligned} \quad n=1,2,3,4\tag{4.6}
C∗I=[X1in+X2in+1+X3in+2]4×4=[X1X2X3]4×18⎣⎡inin+1in+2⎦⎤18×1n=1,2,3,4(4.6)
4.2目标检测
4.2.1单目标检测
目标检测包含了两个问题,一个是分类问题,就是知道图像中有什么东西,另一个是定位问题,确定这个东西在哪。

如上图的例子,卷积层输出一个4096维的向量,将其连接在全连接层,输出一个1000维的向量,进行分类。
另外一个方向,将4096维向量映射为一个4维的向量,进行定位,和标出方框大小。
在这里,损失函数由两部分组成,一个是分类的损失函数,另一个是预测坐标和正确坐标的损失函数。
4.2.2多目标检测
目标个数不确定,不知道输出多少个坐标。所以不能提前给定神经网络应该输出多少维的向量。
所以采用滑动窗口的思路,把每个窗口都当成一张图片。就相当于穷举一张图片所有的区域,分别进行计算。但是这种方法计算了巨大,神经网络不能正常运行。

a.区域建议
提前对图像处理,找出所有潜在可能包含目标的区域。然后再进行分类。

区域建议的方法叫做Selective Search 。这种方法的主要思想如下:
- 使用一种过分割手段,将图像分割成小区域(1k-2k个)
- 查看现有的小区域,按照合并规则合并出可能性最高的相邻的两个区域。直至合并成整张图大小的一个区域。
- 输出所有曾经合并过程的区域,成为候选区域。
b.R-CNN

主要思路如上图所示:
- 先通过Selective Search方法选出候选区域,大约2k左右个。
- 由于各个区域大小不同,对各个区域进行缩放,得到尺寸为224的图片。
- 将尺寸一样的各区域图片输入到卷积神经网络中,进行特征提取。
- 卷积输出的特征图输入到SVMs线性分类器中进行分类。
- 特征图还输入到Bbox reg中,可以对之前Selective Search得到的特征框进行修正,从而输出正确的特征框。
但是R-CNN的弊病就是计算效率低下,在一张图像中,需要对许多区域都进行特征提取。
所以后来进行改进。
c.Fast R-CNN
与之前的R-CNN不同,该方法是先提取图像的特征,然后再进行Selective Search。

这样就可以避免多次进行特征提取。将特征进行裁剪缩放后,输入到全连接层,进行分类和特征框修正。
在这里需要对特征进行裁剪缩放,是很重要的,为了保证整个神经网络前向信息和反向信息正常传递。全连接层的输入大小应该是一样的。
(1)区域裁剪:Rol Pool

首先将候选区域映射到特征图上(此处也可以理解为在特征图上直接选择候选区域)
但是候选区域往往不是在整数像素点上,可能是在两个像素点之间。Rol Pool方法就是将这些区域进行微调,调整到像素点上。

然后将候选区域粗略的分成面积相等的 2 × 2 2\times2 2×2 个子区域。然后对每个子区域做最大池化。

最终可以使所有区域的特征尺寸一样。
但是该方法会使特征区域有一点对不齐,会影响效率。
(2)区域裁剪:Rol Align

与Rol Pool方法不同的是,不进行归整,利用插值求出个点的值。
也是平均分成4块,每块选取4个点,每个点的值利用插值来计算,在每个点周围选取四个整数像素点,然后通过下面公式进行计算:
f
x
y
=
∑
i
,
j
=
1
2
f
i
,
j
max
(
0
,
1
−
∣
x
−
x
i
∣
)
max
(
0
,
1
−
∣
y
−
y
j
∣
)
(4.7)
f_{x y}=\sum_{i, j=1}^{2} f_{i, j} \max \left(0,1-\left|x-x_{i}\right|\right) \max \left(0,1-\left|y-y_{j}\right|\right)\tag{4.7}
fxy=i,j=1∑2fi,jmax(0,1−∣x−xi∣)max(0,1−∣y−yj∣)(4.7)
然后在进行最大池化。
d.Faster R-CNN
在中间特征层后加入区域建议网络RPN(Region Proposal Network),产生候选区域。其他部分保持不变。

区域建议:

一个直接的思路是,在特征图上直接进行分类。因为特征图尺寸很小,即使每个点都计算,也就是对 20 × 15 = 300 20\times15=300 20×15=300 个位置进行分类。但是又有一个问题,就是这个框选取多大。
在每一个位置选取k个不同的尺寸框,共有 20 × 15 k 20\times 15k 20×15k 个,分别进行预测,然后对这300k个区域进行是不是目标打分,选取前300个区域作为输入,再输入到全连接层,得到分类结果和预测位置。
这个过程就可以用不同尺寸的卷积核来完成。对特征图的各个锚点进行不同尺度的卷积,得到一个高维的向量,然后将这个高维的向量输入到另一个全连接层,进行打分,判断是否是目标区域。

在该网络结构中,共有四个损失:
- RPN分类损失(目标/非目标)
- RPN边界框坐标回归损失
- 候选区域分类损失
- 最终边界框坐标回归损失
4.2.3总结
主干网络(特征提取):
- VGG
- ResNet-101
- Inception V2
- Inception V3
- Iception
- ResNet
- MobileNet
基础框架:
- 两阶段:Faster R-CNN
- 一阶段:YOLO,SSD
- 混合:R-FCN
一些经验结论:
- Faster R-CNN的速度偏慢,但精度更高
- SSD速度快,相对于Faster R-CNN精度较低
- 主干网络越宽,深度越深,对性能帮助就越大
4.3实例分割
相对于目标检测,更精确。相对于语义分割,多了实例的概念。
Mask R-CNN
就是对目标检测的区域再进行一次卷积,然后上采样,对每一个像素点进行分类。

5.可视化
本章是弄清楚卷积神经网络在干什么。
5.1第一层卷积核
第一层卷积核从图像上抽取了许多基元。
由于网络第一层的卷积核深度是3维的,因此我们可以将其作为RGB图来看待,而对于深层的网络,卷积核深度不止是3维,那么我们只能将其作为灰度图处理,对于高维特征,我们可能就比较难看出它在原图中寻找什么东西了,因为它是许多低维特征的集合
第一层卷积核可视化:

5.2最后一层
对于网络的最后一层的特征往往就是一副图像整体的特征,如果我们对于一副测试的图片,寻找在特征空间最相近的图,那么我们一般能得到同一类的物体。假设卷积网络最后一层输出的是一个4096维的向量,然后我们在数据集中,把和一张图片向量相近的图片放在一起,如下图所示
可以看到都是同一类东西。然后再通过降维的方法,把这个4096向量降为2维,在平面上用坐标轴表示出来
我们可以看出色调偏绿的图像都集中在了左下角,偏蓝的图像都集中在了右上角,这也意味着网络确实学习到了图像中的某些特征,并能利用特征进行分类。
5.3 探究中间层的卷积
如果我们取网络中某一层某一个特征图的某一个特定神经元比较大的值,那么它会对应一个作用域,如果我们将这个作用域对应在原图的部分取出来,我们会发现这些部分是类似的,原因就是这个神经元是在图像中寻找某些特定的特征

除此以外我们还能做遮挡实验,将一副图像进行遮挡,然后观察最后分类值的变化。

不同的卷积核关注图像中不同的部分。上面这幅图说明了,卷积核是感受大象的面部信息。
5.3.1输出对输入求导
为了求得不同像素对图像分类的影响,我们可以求显著图,也就是改变一个像素点,看其对分类结果有多大的影响(实际的方法是求出分类输出值对每个像素的梯度),然后将这些点用二值化图标注出来。

我们不仅可以求最终分类值对每个像素的梯度,还可以求某个神经元对作用域内所有像素的梯度,代表着像素对神经元输出值的影响程度。
5.3.2改变输入值
前面的方法是求输出值对输入值的梯度,来可视化梯度。但是这种方法的可视化还是不那么明显。现在我们用输出值对输入值求导,得到梯度,然后按照梯度方向改变输入值,这样可以得到当某个神经元输出最大值时,输入图像的样子。
具体的方法是应用梯度上升:输出函数是某个神经元的输出值加上正则项,求出它对每个像素的梯度,然后按梯度上升的方向改变像素的值。正则化的作用是使得图像能更加像真实的图。


如果我们最大化最终的分类值,可以得到以下结果,我们可以看到图像确实具有一些该分类的形状。

5.4改变图像风格
另外我们还可以求出一副图像的分类,然后改变像素值,最大化其他分类的值,我们期望的是图像能够由一个分类变为另外一个分类。


如上图所示,最大化其他分类,就是让这幅图像中包含其他类别的信息,在原图的基础上,就可以得到上图的效果。
想变成这种效果有两种方法。
5.4.1特征反演
特征反演与上述方法不同,这种方法针对某个特定特征,会寻找一副图像,使得其特征向量与给定的特征向量距离最小。

下面是这种方法的结果。

5.4.2纹理合成
纹理合成是计算机视觉中一个经典的算法,随着深度学习的发展,我们也有了更好的解决方案,我们取某一层网络中纵向的两个向量,每个向量代表同一个位置的不同特征,再将这两个向量相乘得到一个矩阵。

我们两两遍历特征图中的向量,再取平均值,得到的矩阵叫做Gram矩阵,由于我们的矩阵是所有位置的向量相乘取平均的结果,因此我们消除了空间位置信息,保留了特征之间的相关关系(特征数为C)。
人工纹理合成算法与特征反演不同的地方就在此。特征转换的目标是让两个图像的特定层特征最相似,而人工纹理合成是将特征转换为Gram矩阵,然后使得两张图像Gram矩阵最相似。在实际应用的过程中,我们往往会将多层网络的Gram矩阵相似性都考虑进最终结果。
一旦有了神经网络上进行纹理合成,就可以通过梯度上升来合成与原始图像纹理相匹配的新的图像。
5.4.3风格转换
结合了以上两点我们就能做风格转换了。
当把格拉姆矩阵匹配的纹理合成方法与特征匹配的特征反演法结合起来会产生非常棒的风格迁移算法;在风格迁移中,把两张图像作为输入图像,第一步选取其中一张图像作为内容图像,它引导我们生成图像的主体,同样的风格图像负责生成图像的纹理或风格,然后共同做特征识别,通过最小化内容图像的特征重构损失以及风格图像的格拉姆矩阵损失,就能得到非常棒的图像。

6.生成网络
6.1有监督学习与无监督学习
有监督学习我们都很熟悉了,我们有数据x和标签y,我们在有监督学习中学习到一个函数可以将数据x映射到标签y,标签可以有很多形式。典型的监督学习有:分类问题中输入一张图片,输出图片的分类;目标检测中输入一张图片,输出目标物体的边框;语义分割中,给每个像素都打上标签。下面说一下无监督学习。
无监督学习在我们只有一些没有标签的训练数据的情况下,学习数据中隐含的结构。
6.1.1聚类
聚类是找到数据的分组,组内数据在某种度量方式下是相似的。

6.1.2降维
把高维数据降到低维。在低维空间中保留高维空间中的主要信息。
常用方法,主成分分析:

左图可以看见,在3D空间中,有一些数据在平面垂直方向变化不大。因此可以将该方向的数据忽略掉,仅保留一些显著变化的数据。
另一种方法,特征学习,采用自编码器的结构

在这里前半部分和神经网络类似,提取出特征。不同的是,还可以把低维数据还原回去。该方法可以进行非线性的降维,之前主成分分析是线性的降维。
6.1.3密度估计
通过样本数据,来估计数据的内在概率分布情况。

6.2生成模型
给定训练集,产生与训练集同分布的新样本。

我们希望可以学到一个模型 p m o d e l ( x ) p_{model}(x) pmodel(x) ,其与样本的分布 p d a t a ( x ) p_{data}(x) pdata(x) 相近。
无监督学习里的一个核心问题就是密度估计问题。
有两种思路:
- 显示的密度估计:显示的定义并求解分布 p m o d e l ( x ) p_{model}(x) pmodel(x) 。
- 隐式的密度估计:学习一个模型 p m o d e l ( x ) p_{model}(x) pmodel(x) ,而无需显示的定义它。