第三章:深度学习基础
3.1 局部极小值与鞍点
3.1.1 临界点及其种类
优化神经网络时,使用梯度下降法,遇到梯度为0的点,训练就停了下来,损失也不再下降。
这个梯度为0的点,可以称为临界点
。
临界点
可以细分为局部极小值
、局部极大值
和鞍点
。
如下图,左侧是局部极小值
,右侧是鞍点
。
鞍点
的特点是,它在某些方向上是极小值,在某些方向上是极大值。形似马鞍面。
3.1.2 判断临界值种类的方法
根据泰勒级数近似,我们可以得到损失函数
L
(
θ
)
L(\theta)
L(θ)在临界点
θ
′
\theta'
θ′附近的函数表示:
L
(
θ
)
≈
L
(
θ
′
)
+
(
θ
−
θ
′
)
T
g
+
1
2
(
θ
−
θ
′
)
T
H
(
θ
−
θ
′
)
L(\boldsymbol{\theta}) \approx L\left(\boldsymbol{\theta}^{\prime}\right)+\left(\boldsymbol{\theta}-\boldsymbol{\theta}^{\prime}\right)^{\mathrm{T}} \boldsymbol{g}+\frac{1}{2}\left(\boldsymbol{\theta}-\boldsymbol{\theta}^{\prime}\right)^{\mathrm{T}} \boldsymbol{H}\left(\boldsymbol{\theta}-\boldsymbol{\theta}^{\prime}\right)
L(θ)≈L(θ′)+(θ−θ′)Tg+21(θ−θ′)TH(θ−θ′)
由于临界点的梯度为0,这个式子进一步可以化简为:
L
(
θ
)
≈
L
(
θ
′
)
+
1
2
(
θ
−
θ
′
)
T
H
(
θ
−
θ
′
)
L(\boldsymbol{\theta}) \approx L\left(\boldsymbol{\theta}^{\prime}\right)+\frac{1}{2}\left(\boldsymbol{\theta}-\boldsymbol{\theta}^{\prime}\right)^{\mathrm{T}} \boldsymbol{H}\left(\boldsymbol{\theta}-\boldsymbol{\theta}^{\prime}\right)
L(θ)≈L(θ′)+21(θ−θ′)TH(θ−θ′)
根据高等代数的知识:
- 当海森矩阵 H \boldsymbol{H} H的特征值全为正,即 H \boldsymbol{H} H是正定矩阵,则右侧第二项为正,此时 θ ′ \theta' θ′是周围领域中对应 L ( θ ) L(\theta) L(θ)值最小的,即 θ ′ \theta' θ′是局部极小值点。
- 当海森矩阵 H \boldsymbol{H} H的特征值全为负,即 H \boldsymbol{H} H是负定矩阵,则右侧第二项为负,此时 θ ′ \theta' θ′是周围领域中对应 L ( θ ) L(\theta) L(θ)值最大的,即 θ ′ \theta' θ′是局部极大值点。
- 当海森矩阵 H \boldsymbol{H} H的特征值有正有负,则右侧第二项也会有正有负,此时 θ ′ \theta' θ′是鞍点。
值得注意的是,如果我们得到了 H \boldsymbol{H} H的一个负特征向量 u u u,就可以沿着 u u u的方向更新参数,例如 θ = θ ′ + u \theta=\theta'+u θ=θ′+u,这样损失会变小。
算海森矩阵和海森矩阵的特征值/向量的运算量会非常大,所以一般不会这么做来逃离鞍点。
3.1.3 逃离鞍点的方法
鞍点往往比局部极小值更常见
。这是因为在一个高维空间中,要让一个函数在某个点处,其每个方向上都是极小值是不容易的。往往存在一些维度方向上,这个点并非极小值。
这个结论也可以通过一些实验来得到验证,详细见书。
3.2 批量和动量
实际计算梯度时,考虑到显存。
一般会将
N
N
N个样本数据分为
L
L
L个批次。每个批次有
B
B
B个样本(这里假设
N
=
B
L
N=BL
N=BL)。
在一次迭代(iteration)更新中,只会取一批次的
B
B
B个样本计算损失和梯度,并更新参数。
一个回合(epoch)更新包含
L
L
L次这样的迭代更新,才会将所有
N
N
N个样本遍历一遍。
另外,数据分批的时候还会进行shuffle。有时甚至在每个回合更新前,都会进行shuffle。
3.2.1 批量大小对梯度下降法的影响
- 如果
B
=
N
,
L
=
1
B=N, L=1
B=N,L=1,即一次迭代更新使用全部样本,则称为
批量梯度下降法(Batch Gradient Descent, BGD)
。 - 如果
B
=
1
,
L
=
N
B=1, L=N
B=1,L=N,即一次迭代更新只使用1个样本,则称为
随机梯度下降法(Stochastic Gradient Descent, SGD)
。 - 如果
B
B
B是介于
1
1
1和
N
N
N之间的数,则称为
小批量梯度下降(Mini-batch Gradient Descent,MBGD)
。
在效率上
在一次迭代更新中,使用更多的样本,即使用更大的批量大小,是否会让这一次迭代花费的时间变长呢?
答案是当批量大小不大的时候,这并不会增加一次迭代花费的时间
。这是因为GPU有并行计算的能力。
从下面的图可以看出。当
B
=
1000
B=1000
B=1000以前时,一次迭代花费的时间并没有增加太多。
当 B B B继续增加时,一次迭代花费的时间会增加。这可能是因为GPU已经满负荷运行了。因此数据的处理并不是完全的并行。
但是在一个回合更行中,更大的批量大小
意味着遍历所有样本需要更少的迭代次数,这会导致更少的回合时间。
在性能上
大的
B
B
B意味着更新稳定,而小的
B
B
B则意味着梯度方向会有噪声。
但噪声一定程度上有利于算法逃离局部最小值点。
因为不同批次的损失函数有差异。某个点可能对某些批次的损失函数而言是局部最小值点,但对另外一些点而言并不是局部最小值点,这导致梯度下降算法能进一步寻找更小的损失
。
所以小的
B
B
B在训练集上会有更好的表现。
一些实验和论文表明小的
B
B
B在测试集上也有更好的表现。
一个可能的解释是误差表面有不同的局部极小值点,有些平坦,有些尖锐。平坦的局部极小值点附近,泛化性较好,即在训练集和测试集上的表现差不多(前提是测试集和训练集的分布差不多)。但是尖锐的局部极小值点附近,一点点的偏离都会使损失变大很多,这表现为泛化性差,即使测试集和训练集的分布差不多,在测试集上仍会有较大的损失
。
最后总结一下:
- 在一次迭代更新中,如果批量大小 B B B不大时,大 B B B对应的梯度下降算法耗时和小 B B B对应耗时基本相同。
- 但在一个回合的更新中,大 B B B对应的梯度下降算法耗时比小 B B B少很多。
- 训练中, B B B小意味着噪声更多, B B B大意味着更稳定。
- B B B小,在训练集和测试集上的表现都会更好。
3.2.2 动量法
动量法是另外一个可以对抗鞍点或局部最小值点的方法。它的核心是每次参数更新,不仅仅考虑梯度负方向,还考虑前一次参数更新方向。即第
i
i
i次参数更新向量
m
i
m_i
mi
m
i
=
λ
m
i
−
1
−
η
g
i
−
1
m_i=\lambda m_{i-1}-\eta g_{i-1}
mi=λmi−1−ηgi−1
可以看到,这种方法更新的方法,不仅仅考虑了现在的梯度,还考虑了考虑过去所有梯度的总和。
3.3 自适应学习率
临界点其实不一定是在训练一个网络的时候会遇到的最大的障碍。损失不再下降的原因,可能因为梯度不够小,导致整体的参数在误差表面的山谷间来回震荡。
那么调小学习率怎么样?这并不一定合适。因为不同的参数可能需要不同的学习率。因此考虑引入“自适应学习率”。
3.3.1 AdaGrad
AdaGrad的参数更新公式为:
θ
t
+
1
i
←
θ
t
i
−
η
σ
t
i
g
t
i
,
σ
t
i
=
1
t
+
1
∑
j
=
0
t
(
g
j
i
)
2
\boldsymbol{\theta}_{t+1}^i \leftarrow \boldsymbol{\theta}_t^i-\frac{\eta}{\sigma_t^i}\boldsymbol{g}_t^i, \quad \sigma_t^i=\sqrt{\frac{1}{t+1} \sum_{j=0}^t\left(\boldsymbol{g}_j^i\right)^2}
θt+1i←θti−σtiηgti,σti=t+11j=0∑t(gji)2
其中
i
i
i表示第
i
i
i个参数,
t
t
t表示第
t
t
t次参数更新迭代。
AdaGrad能根据累计梯度的大小,改变分母
σ
t
i
\sigma_t^i
σti,从而动态调整参数更新的步幅。
3.3.2 RMSProp
但是AdaGrad在考虑累计梯度时,是将过去所有的梯度平等对待。如果要重视最新迭代算出的梯度,AdaGrad就做不到。因此考虑引入RMSProp,它的更新公式为:
θ
t
+
1
i
←
θ
t
i
−
η
σ
t
i
g
t
i
,
σ
t
i
=
α
(
σ
t
−
1
i
)
2
+
(
1
−
α
)
(
g
t
i
)
2
\boldsymbol{\theta}_{t+\mathbf{1}}^i \leftarrow \boldsymbol{\theta}_t^i-\frac{\eta}{\sigma_t^i} \boldsymbol{g}_t^i, \quad \sigma_t^i=\sqrt{\alpha\left(\sigma_{t-1}^i\right)^2+(1-\alpha)\left(\boldsymbol{g}_t^i\right)^2}
θt+1i←θti−σtiηgti,σti=α(σt−1i)2+(1−α)(gti)2
σ
0
i
\sigma_0^i
σ0i的计算和AdaGrad一致。
3.3.3 Adam
最常用的优化的策略或者优化器(optimizer)是Adam(Adaptive moment estimation)。Adam 可以看作 RMSprop 加上动量,其使用动量作为参数更新方向,并且能够自适应调整学习率。
3.4 学习率调度
AdaGrad和RMSProp都是在调整迭代更新的分母 σ t i \sigma_t^i σti。学习率 η \eta η其实也可以调整。对应的策略有:
- 学习率衰减:对应的更新公式变为 θ t + 1 i ← θ t i − η t σ t i g t i \boldsymbol{\theta}_{t+1}^i \leftarrow \boldsymbol{\theta}_t^i-\frac{\eta_t}{\sigma_t^i} \boldsymbol{g}_t^i θt+1i←θti−σtiηtgti
- 学习率预热:即将学习率先变大,再变小。如 η : 0.01 − > 0.1 \eta: 0.01->0.1 η:0.01−>0.1。这种技术被用在残差网络,BERT 和 Transformer 的训练中。
3.5 优化总结
现在参数的更新公式为:
θ
t
+
1
i
←
θ
t
i
−
η
t
σ
t
i
m
t
i
\boldsymbol{\theta}_{t+1}^i \leftarrow \boldsymbol{\theta}_t^i-\frac{\eta_t}{\sigma_t^i} \boldsymbol{m}_t^i
θt+1i←θti−σtiηtmti
这个是目前优化的完整的版本,这种优化器除了 Adam 以外,还有各种变形。但其实各种变形是使用不同的方式来计算
m
t
i
\boldsymbol{m}_t^i
mti或
σ
t
i
\sigma_t^i
σti,或者是使用不同的学习率调度的方式。
3.6 分类
3.6.1 分类与回归的关系
一般分类问题,不同类别并没有远近关系,所以采用独热向量
表示类。如果用独热向量计算距离的话,类两两之间的距离都是一样的。
3.6.2 带softmax的分类
输入
x
x
x经过模型会得到
y
^
\hat{y}
y^,然后经过softmax函数(如下)归一化得到
y
′
y'
y′。
y
i
′
=
exp
(
y
i
)
∑
j
exp
(
y
i
)
y_i^{\prime}=\frac{\exp \left(y_i\right)}{\sum_j \exp \left(y_i\right)}
yi′=∑jexp(yi)exp(yi)
对于二分类问题,只需要输出一个标量,所以使用sigmoid函数(它和二个元素向量的softmax是等价的)
σ
(
x
)
=
1
1
+
e
−
x
\sigma(x)=\frac{1}{1+e^{-x}}
σ(x)=1+e−x1
3.6.3 分类损失
y
′
y'
y′是预测标签,最后要和真实标签计算损失。
分类问题的损失函数是交叉熵
e
=
−
∑
i
y
i
ln
y
i
′
e=-\sum_i y_i \ln y_i^{\prime}
e=−i∑yilnyi′
从优化角度看,交叉熵损失函数比均方误差更容易优化(详见书P62页)。
这说明改变损失函数可以改变优化的难度
。分类任务更适合使用交叉熵损失
。
3.7 批量归一化
为了使特征向量在不同维度上数值分布差异变小,以构造更容易训练的误差表面,可以引入特征归一化
方法。特征归一化
方法有很多具体形式,其中一种是Z值归一化
,即标准化。它的公式是
x
~
i
r
←
x
i
r
−
m
i
σ
i
\tilde{x}_{i}^r \leftarrow \frac{x_i^r-m_i}{\boldsymbol{\sigma}_i}
x~ir←σixir−mi
其中
x
i
r
x^r_i
xir表示第
r
r
r个样本的第
i
i
i个分量。
m
i
m_i
mi表示在第
i
i
i个分量上的均值,
σ
i
\sigma_i
σi表示第
i
i
i个分量上的标准差。
经过特征归一化,在进行梯度下降时,收敛能快一点。
3.7.1 考虑深度学习
深度学习中间层也需要做特征归一化。因为经过第一层之后,特征可能又在不同维度上有一定差异了。
由于深度学习数据量巨大,GPU显存无法把整个数据集加载进去。因此每次迭代训练使用的是批量数据。于是也是基于批量数据进行特征归一化。这种技巧被称为批量归一化
。
批量归一化要求又一个够大的批量,因为这样,批量的数据才足以表示整个数据集的分布。
此外,在做批量归一化的时候,还会进行如下操作:
z
^
i
=
γ
⊙
z
~
i
+
β
\hat{\boldsymbol{z}}^i=\boldsymbol{\gamma} \odot \tilde{\boldsymbol{z}}^i+\boldsymbol{\beta}
z^i=γ⊙z~i+β
其中
γ
\gamma
γ和
β
\beta
β可以看成网络的参数,需要被学习。
3.7.2 测试时的批量归一化
测试,或说推断时候也需要对数据进行归一化。但是采用的是移动平均计算得到的均值和标准差来进行归一化。具体地,考虑均值,假设每个批次计算得到
μ
1
、
μ
2
、
μ
3
、
.
.
.
、
μ
t
\mu^1、\mu^2、\mu^3、... 、\mu^t
μ1、μ2、μ3、...、μt,则它们的移动平均为
μ
‾
←
p
μ
‾
+
(
1
−
p
)
μ
t
\overline{\boldsymbol{\mu}} \leftarrow p \overline{\boldsymbol{\mu}}+(1-p) \boldsymbol{\mu}^t
μ←pμ+(1−p)μt
其中
p
p
p是一个超参数,需要自己调整。
批归一化原始论文展示了使用批归一化能加快模型训练。甚至可以将学习率调的大一些。
3.7.3 内部协变量偏移
原始的批量归一化论文里面提出内部协变量偏移解释批归一化的好处。但是后续被质疑可能存在问题。但不可否认的是,批归一化确实改变了误差表面,以让模型更容易训练了。
其实批量归一化不是唯一的归一化,还有很多归一化方法,比如:
- 批量重归一化(batchrenormalization)
- 层归一化(layer normalization
- 实例归一化(instance normalization)
- 组归一化(group normalization)
- 权重归一化(weight normalization)
- 谱归一化(spectrum normalization)
第四章:卷积神经网络
图像识别任务:给机器一张图像,由机器去判断这张图像里面有什么样的东西。
输入:一张三维图片,维度分别是图像的宽,图像的高,图像的通道数(例如RGB就有三个通道)。
输出:独热向量。
损失函数:分类问题,所以用交叉熵损失。
4.1-4.2 观察1: 检测模式不需要整张图像 - 感受野
对图像分类,只需要观察一些局部的模式即可。可以用神经网络来检测图像中的模式。并且不需要输入整张图像到网络中。
因此引入感受野
。它只会守备一个局部范围。一般是33通道数。其中3*3称为感受野的核大小。
每隔几个位置就需要一个感受野,因此有步幅的概念。
为了能不漏掉检测边界,在边界范围外会进行填充,一般使用0填充。
4.3-4.4 观察2:同样的模式可能会出现在图像的不同区域 - 共享参数
感受野的任务是检测一种模式。由于模式可能出现在图像的任何地方,而检测的功能是相同的。因此如果是为了检测一种模式是否出现在图像中,可以共用一套感受野(参数)。这就引入了滤波器
。滤波器
是参数共享的一批感受野。
4.5 简化1和2的总结
全连接网络能力最强,可以关注全局,也可以关注局部,它可以退化成感受野。
感受野只关注局部的模式,在不同位置的感受野可以不相同。
不同位置的感受野一旦共享权重,这些感受野就是一个滤波器。
使用滤波器的网络层就是卷积层,对应的网络就是卷积神经网络。
滤波器的大小一般是33通道数,即感受野的大小。但是为了检测多种各不相同的模式,在一个层上,可能会有多个滤波器,例如64个滤波器,图像经过64个滤波器会得到64组数字,这可以看成通道为64的一个新的图像,进入下一个网络层。
下一个网络层可以继续是卷积层,即卷积层可以堆叠。
4.6-4.7 观察3:下采样不影响模式检测 - 池化
把一张比较大的图像做下采样(downsampling),把图像偶数的列都拿掉,奇数的行都拿掉,图像变成为原来的 1/4,但是不会影响里面是什么东西。例如,把一张大的鸟的图像缩小,这张小的图像还是一只鸟。
这引出了’池化’技术。
最大池化:在一组数中选一个最大值用来代表这组数。例如2*2最大池化,就会在4个数里找1个最大数代表这4个数。
平均池化:在一组数中计算平均值用来代表这组数。
池化的好处是将图像变小,能减少模型训练的时间。但是它一定程度上会降低模型的性能。在模型不变,算力提高的情况下,池化越来越被弃用了。
另外,对一些不适合下采样的任务(例如下围棋),池化操作应该被禁用。
4.8 卷积神经网络的应用:下围棋
AlphaGo就是采用卷积神经网络训练的,因为下围棋的任务和图像分类有一定的共同之处。
- 只需要看局部模式
- 同样的局部模式可以在棋盘不同的地方出现
详见书本。
卷积神经网络不太能处理图像放大缩小和旋转的问题。即即使只是将图像旋转,放大缩小一下。卷积神经网络可能就无法分类正确。
这个问题可以有两种方向解决:
1.进行数据增强,构造旋转数据,放大缩小的数据。
2.使用其他网络架构,例如SpecialTransformer Layer。