文章目录
- 请写出常用的损失函数,平方损失、交叉熵损失、softmax损失函数和hinge
- 交叉熵函数与最大似然函数的联系和区别?
- 在用 sigmod 作为激活函数的时候,为什么要用交叉熵损失函数,而不用均方差损失函数?
- 在深度学习中引入非线性激活函数的作用是什么?
- 列举常用的激活函数、图像、特点,以及如何选择激活函数。
- 请说明Softmax激活函数的定义及其作用?Softmax激活函数如何应用于多分类?
- 为什么深层神经网络的训练的难度很大?梯度消失和梯度爆炸。
- 深度学习中有哪些防止过拟合的方法?
- ?为什么无监督预训练可以帮助深度学习?
- 在深度模型训练时,为什么需要batch size?如何选择合适的batch size,对结果有何影响?
- 深度学习中如何平衡方差与偏差?如果偏差过大我们应该怎么做?方差过大呢?
- 请说明dropout的原理,在训练与测试的时候dropout会有什么区别?
- 什么是模型微调 fine-tune?为什么要微调?请说明 fine-tune 模型的三种状态,各自的特点是什么?
- 迁移学习和微调的关系?
- 权重偏差初始化有哪些方法?分别说明他们的特点.
- 设置学习率的作用是什么?常用的学习率衰减方法有哪些?说明他们各自的特点.
- 请说出几种常用的优化算法,以及他们各自的特点。
- 请你用实例说明一下前向传播和反向传播。
- 白化是什么?
- 请说明BN的原理,为什么要进行批归一化?
- 为什么BN层一般用在线性层和卷积层后面,而不是放在非线性单元后?
- 神经网络分类
请写出常用的损失函数,平方损失、交叉熵损失、softmax损失函数和hinge
1. 0-1 损失函数
0-1 损失函数是指预测指和目标值不相等为1,否则为 0:
L
(
Y
,
f
(
X
)
)
=
{
1
,
Y
≠
f
(
X
)
0
,
Y
=
f
(
x
)
\text{L}(Y,f(X))=\left\{ \begin{matrix} 1,Y\ne f(X) \\ 0,Y=f(x) \\ \end{matrix} \right.
L(Y,f(X))={1,Y=f(X)0,Y=f(x)
特点:
(1)0-1损失函数直接对应分类判断错误的个数,但是它是一个非凸函数,不太实用。
(2)感知机就是用的这种损失函数u。但是相等这个条件太过严格,因此可以放宽条件,即满足
∣
Y
−
f
(
x
)
∣
<
T
|Y-f(x)| < T
∣Y−f(x)∣<T 时认为相等,
L
(
Y
,
f
(
X
)
)
=
{
1
,
∣
Y
−
f
(
x
)
∣
≥
T
0
,
∣
Y
−
f
(
x
)
∣
<
T
\text{L}(Y,f(X))=\left\{ \begin{matrix} 1,|Y-f(x)| ≥ T \\ 0,|Y-f(x)| < T \\ \end{matrix} \right.
L(Y,f(X))={1,∣Y−f(x)∣≥T0,∣Y−f(x)∣<T
2. 绝对值损失函数
绝对值损失函数是计算预测值与目标值的差的绝对值:
L
(
Y
,
f
(
x
)
)
=
∣
Y
−
f
(
x
)
∣
L(Y, f(x)) = |Y-f(x)|
L(Y,f(x))=∣Y−f(x)∣
3. 平方损失函数
平方损失函数标准形式如下:
L
(
Y
,
f
(
X
)
)
=
∑
N
(
Y
−
f
(
X
)
)
2
\text{L}(Y,f(X))=\sum\limits_{N}^{{}}{{{(Y-f(X))}^{2}}}
L(Y,f(X))=N∑(Y−f(X))2
(1)经常应用于回归问题
4. log 对数损失函数
对数损失函数的标准形式如下:
L
(
Y
,
P
(
Y
∣
X
)
)
=
−
l
o
g
P
(
Y
∣
X
)
L(Y, P(Y|X)) = -logP(Y|X)
L(Y,P(Y∣X))=−logP(Y∣X)
特点:
(1)log 对数损失函数能非常好的表征概率分布,在很多场景中尤其是多分类,如果需要知道结果属于每个类别的置信度,那它非常适合。
(2)健壮性不强,相比于 hiinge loss 对噪声更敏感。
(3)逻辑回归的损失函数就是 log 对数损失函数。
在概率模型里面,一般常用的是负对数似然函数:
L
(
θ
)
=
L
(
θ
;
x
1
,
x
2
,
.
.
.
,
x
n
)
=
−
∑
k
=
1
n
l
o
g
(
p
(
x
k
,
θ
)
)
L(θ) = L(θ;x_1,x_2,...,x_n) = -\sum_{k=1}^n log(p(x_k, θ))
L(θ)=L(θ;x1,x2,...,xn)=−k=1∑nlog(p(xk,θ))
5. 指数损失函数(exponential loss)
指数损失函数的标准形式如下:
L
(
Y
∣
f
(
x
)
∣
=
e
x
p
[
−
y
f
(
x
)
]
L(Y|f(x)|=exp[-yf(x)]
L(Y∣f(x)∣=exp[−yf(x)]
特点:
(1)对离群点、噪声非常敏感。经常用在 AdaBoost 算法中。
6. Hinge 损失函数
Hinge 损失函数标准形式如下:
L
(
y
,
f
(
x
)
)
=
m
a
x
(
0
,
1
−
y
f
(
x
)
)
L(y,f(x)) = max(0, 1-yf(x))
L(y,f(x))=max(0,1−yf(x))
特点:
(1)Hinge 损失函数表示如果被分类正确,损失为0,否则损失就为
1
−
y
f
(
x
)
1-yf(x)
1−yf(x)。SVM 就是使用这个损失函数。
(2)一般的
f
(
x
)
f(x)
f(x) 是预测值,在 -1 到 1 之间,y 是目标值(-1或1)。其含义是,
f
(
x
)
f(x)
f(x) 的值在 -1 和 +1 之间就可以了,并不鼓励
∣
f
(
x
)
∣
>
1
|f(x)| > 1
∣f(x)∣>1,即并不鼓励分类器过度自信,让某个正确分类的样本距离分割线超过 1 并不会有任何奖励,从而使分类器可以更专注于整体的误差。
(3)健壮性相对较高,对异常点,噪声不敏感,但它没太好的概率解释。
7. 感知损失(preceptron loss)函数
感知损失函数的标准形式如下:
L
(
y
,
f
(
x
)
)
=
m
a
x
(
0
,
−
f
(
x
)
)
L(y,f(x)) = max(0, -f(x))
L(y,f(x))=max(0,−f(x))
特点:
(1)是 Hinge 损失函数的一个变种,Hinge loss 对判定边界附近的点(正确端惩罚力度很高。而 preceptron loss 只要样本的判定类别正确的话,它就满意,不管其判定边界的距离。它比 Hinge loss 简单,因为不是 max-margin boundary,所以模型的泛化能力没 hinge loss 强
8. 交叉熵损失函数(cross-etropy loss function)
交叉熵损失函数的标准形式如下:
L
=
−
1
n
∑
i
[
y
i
log
p
i
+
(
1
−
y
i
)
log
(
1
−
p
i
)
]
L=-\frac{1}{n}\sum\limits_{i}{[y_i\log p_i+(1-y_i)\log (1-p_i)]}
L=−n1i∑[yilogpi+(1−yi)log(1−pi)]
注意公式中x表示样本,y表示实际的标签,a表示预测的输出,n表示样本总数量。
特点:
(1)本质上也是一种对数似然函数,可以哦那个与二分类和多酚类任务中。
二分类问题中的 loss 函数如上式。
多分类问题中的 loss 函数(输入数据是softmax或者sigmod函数的输出):
L
=
−
1
n
∑
i
y
i
log
a
i
L=-\frac{1}{n}\sum\limits_{i}{y_i\log a_i}
L=−n1i∑yilogai
(2)当使用 sigmod 作为激活函数的时候,常用交叉熵损失函数而不用均方差损失函数,因为它可以完美解决平方损失函数权重更新过慢的问题,具有“误差大的时候,权重更新快;误差小的时候,权重更新慢”的良好性质。
对数损失函数和交叉熵损失函数应该是等价的!!
9. softmax 交叉熵损失函数
softmax 的形式如下:
f
(
z
k
)
=
e
z
k
∑
j
e
z
j
(
1
)
f(z_k) = \frac{e^{z_{k}}}{\sum_je^{z_j}} (1)
f(zk)=∑jezjezk(1)
全连接输出向量 z 的每个值没有大小限制,显然通过 (1) 后强制限制在 0-1 之间了,变成了概率值。
softmax 损失函数的形式如下:
L
(
y
,
z
)
=
−
∑
k
=
0
C
y
c
l
o
g
(
f
(
z
c
)
)
(
2
)
L(y, z) = -\sum^C_{k = 0}y_clog(f(z_c))(2)
L(y,z)=−k=0∑Cyclog(f(zc))(2)
f ( z c ) f(z_c) f(zc)就是上面的softmax, y c y_c yc 为真值。
与真实越接近,损失函数越小,与真值越远,损失函数越大。
相比于一般的交叉熵,就是在预测的输出结果上套了一层 softmax
参考资料:常见的损失函数(loss function)总结
交叉熵函数与最大似然函数的联系和区别?
区别:交叉熵函数使用来描述模型预测值和真实值的差距大小,越大代表越不相近;似然函数的本质就是衡量在某个参数下,整体的估计和真实的情况一样的概率,越大代表越相近。
联系:交叉熵函数可以由最大似然函数在伯努利分布的条件下推导出来,或者说最小化交叉熵函数的本质就是对数似然函数的最大化。
在用 sigmod 作为激活函数的时候,为什么要用交叉熵损失函数,而不用均方差损失函数?
结论:
在使用均方差损失函数更新参数 w,b 的时候,导数项带有 σ ′ ( z ) \sigma '(z) σ′(z) ,因为 sigmod 的形式,在z的绝大部分取值的时候 σ ′ ( z ) \sigma '(z) σ′(z) 都很小,会使得参数更新非常慢。而交叉熵损失函数不会,并且交叉熵损失函数有一个很好的特性,在误差大的时候,参数更新快,误差小的时候,参数更新慢。
证明如下:
对于均方误差损失函数,常常定义为:
C
=
1
2
n
∑
x
(
a
−
y
)
2
C = \frac{1}{2n}\sum_x(a-y)^2
C=2n1x∑(a−y)2
其中 y 是我们期望的输出,a为神经元的实际输出。在训练神经网络的时候我们使用梯度下降的党法来更新 w 和 b,因此需要计算代价函数对于 w 和 b 的导数,然后更新参数 w 和 b:
w
=
w
−
η
∂
C
∂
w
=
w
−
η
(
a
−
y
)
σ
′
(
z
)
x
w=w-\eta \frac{\partial C}{\partial w}=w-\eta (a-y)\sigma '(z)x
w=w−η∂w∂C=w−η(a−y)σ′(z)x
b
=
b
−
η
∂
C
∂
b
=
b
−
η
(
a
−
y
)
σ
′
(
z
)
b=b-\eta \frac{\partial C}{\partial b}=b-\eta (a-y)\sigma '(z)
b=b−η∂b∂C=b−η(a−y)σ′(z)
因为 sigmod 的形式,导致
σ
′
(
z
)
\sigma '(z)
σ′(z) 在 z 取大部分值时会很小,这样会使得
η
(
a
−
y
)
\eta (a-y)
η(a−y) 很小,导致参数 w 和 b 更新非常慢。
同样的对于交叉熵损失函数,计算一下参数更新的梯度公式就会发现原因。交叉熵损失函数一般定义为:
L
=
−
1
n
∑
x
[
y
log
a
+
(
1
−
y
)
log
(
1
−
a
)
]
L=-\frac{1}{n}\sum\limits_{x}{[y\log a+(1-y)\log (1-a)]}
L=−n1x∑[yloga+(1−y)log(1−a)]
其中 y 是我们期望的输出,a 为神经元实际输出(
a
=
σ
(
z
)
,
z
=
w
x
+
b
a=\sigma(z), z = wx + b
a=σ(z),z=wx+b)。求导过程如下:
∂
C
∂
a
=
−
1
n
∑
x
[
y
1
a
+
(
y
−
1
)
1
1
−
a
]
=
−
1
n
∑
x
[
1
a
(
1
−
a
)
y
−
1
1
−
a
]
=
−
1
n
∑
x
[
1
σ
(
x
)
(
1
−
σ
(
x
)
)
y
−
1
1
−
σ
(
x
)
]
\begin{aligned} \frac{\partial C}{\partial a}&=-\frac{1}{n}\sum\limits_{x}{[y\frac{1}{a}+(y-1)\frac{1}{1-a}]} \\ &=-\frac{1}{n}\sum\limits_{x}{[\frac{1}{a(1-a)}y-\frac{1}{1-a}]} \\ &=-\frac{1}{n}\sum\limits_{x}{[\frac{1}{\sigma (x)(1-\sigma (x))}y-\frac{1}{1-\sigma (x)}]} \\ \end{aligned}
∂a∂C=−n1x∑[ya1+(y−1)1−a1]=−n1x∑[a(1−a)1y−1−a1]=−n1x∑[σ(x)(1−σ(x))1y−1−σ(x)1]
另外,
∂
C
∂
z
=
∂
C
∂
a
∂
z
∂
a
=
∂
C
∂
a
⋅
σ
′
(
x
)
=
−
∂
C
∂
a
⋅
σ
(
x
)
(
1
−
σ
(
x
)
)
=
−
1
n
∑
x
[
1
σ
(
x
)
(
1
−
σ
(
x
)
)
y
−
1
1
−
σ
(
x
)
]
⋅
σ
(
x
)
(
1
−
σ
(
x
)
)
=
−
1
n
∑
x
(
y
−
a
)
\begin{aligned} \frac{\partial C}{\partial z}&=\frac{\partial C}{\partial a}\frac{\partial z}{\partial a}=\frac{\partial C}{\partial a}\centerdot \sigma '(x) \\ & =-\frac{\partial C}{\partial a}\centerdot \sigma (x)(1-\sigma (x)) \\ & =-\frac{1}{n}\sum\limits_{x}{[\frac{1}{\sigma (x)(1-\sigma (x))}y-\frac{1}{1-\sigma (x)}]}\centerdot \sigma (x)(1-\sigma (x)) \\ & =-\frac{1}{n}\sum\limits_{\text{x}}{(y-a)} \\ \end{aligned}
∂z∂C=∂a∂C∂a∂z=∂a∂C⋅σ′(x)=−∂a∂C⋅σ(x)(1−σ(x))=−n1x∑[σ(x)(1−σ(x))1y−1−σ(x)1]⋅σ(x)(1−σ(x))=−n1x∑(y−a)
所以有:
∂
C
∂
w
=
∂
C
∂
z
∂
z
∂
w
=
(
a
−
y
)
x
∂
C
∂
b
=
∂
C
∂
z
∂
z
∂
b
=
(
a
−
y
)
\begin{aligned} & \frac{\partial C}{\partial w}=\frac{\partial C}{\partial z}\frac{\partial z}{\partial w}=(a-y)x \\ & \frac{\partial C}{\partial b}=\frac{\partial C}{\partial z}\frac{\partial z}{\partial b}=(a-y) \\ \end{aligned}
∂w∂C=∂z∂C∂w∂z=(a−y)x∂b∂C=∂z∂C∂b∂z=(a−y)
所以参数更新公式为:
w
=
w
−
η
∂
C
∂
w
=
w
−
η
(
a
−
y
)
x
b
=
b
−
η
∂
C
∂
b
=
b
−
η
(
a
−
y
)
\begin{aligned} & w=w-\eta \frac{\partial C}{\partial w}=w-\eta (a-y)x \\ & b=b-\eta \frac{\partial C}{\partial b}=b-\eta (a-y) \\ \end{aligned}
w=w−η∂w∂C=w−η(a−y)xb=b−η∂b∂C=b−η(a−y)
可以看到参数更新公式中没有
σ
′
(
x
)
\sigma'(x)
σ′(x) 这一项,权重的更新受 (a-y) 影响,受到误差的影响,所以当误差大的时候,权重更新快;当误差小的时候,权重更新慢。这是一个很好的性质。
在深度学习中引入非线性激活函数的作用是什么?
激活函数是用来加入非线性因素的,因为线性模型的表达能力不够。
在不引入激活函数的神经网络中,多层神经网络经过线性变换,仍然等价于一个单层的神经网络。例如:只有一层的全连接神经网络公式为:
H
=
X
W
o
+
b
o
H = X W_o + b_o
H=XWo+bo
在增加一层隐藏层后:
H
=
X
W
o
+
b
h
H = X W_o + b_h
H=XWo+bh
O
=
H
W
o
+
b
o
O = H W_o + b_o
O=HWo+bo
将上面两个公式联立起来,可以得到:
O
=
(
X
W
h
+
b
h
)
W
o
+
b
o
=
X
W
h
W
o
+
b
h
W
o
+
b
o
.
O=(XW_h + b_h)W_o + b_o = XW_h W_o + b_h W_o + b_o.
O=(XWh+bh)Wo+bo=XWhWo+bhWo+bo.
我们可以发现,虽然仍引入了一层隐藏层,但是还是可以通过线性变换,转换成一个单层的神经网络。添加更多的隐藏层,只是让系数更加复杂而已。
解决上述问题就是引入激活函数,将线性变换转变为非线性变换。
同时,激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。
列举常用的激活函数、图像、特点,以及如何选择激活函数。
1. sigmod 函数
sigmoid函数可以将元素的值变换到0和1之间:
s i g m o d ( x ) = 1 1 + e − x sigmod(x) = \frac{1}{1+e^{-x}} sigmod(x)=1+e−x1
sigmoid函数在早期的神经网络中较为普遍,但它目前逐渐被更简单的ReLU函数取代。在后面“循环神经网络”一章中我们会介绍如何利用它值域在0到1之间这一特性来控制信息在神经网络中的流动。下面绘制了sigmoid函数。当输入接近0时,sigmoid函数接近线性变换。
依据链式法则,sigmoid函数的导数
s i g m o d ′ ( x ) = s i g m o d ( x ) ( 1 − s i g m o d ( x ) ) sigmod'(x) = sigmod(x)(1 - sigmod(x)) sigmod′(x)=sigmod(x)(1−sigmod(x))
下面绘制了sigmoid函数的导数。当输入为0时,sigmoid函数的导数达到最大值0.25;当输入越偏离0时,sigmoid函数的导数越接近0。
优点:
- Sigmoid函数的输出在(0,1)之间,输出范围有限,优化稳定,可以用作输出层。
- 连续函数,便于求导。
缺点:
- sigmoid函数在变量取绝对值非常大的正值或负值时会出现饱和现象,意味着函数会变得很平,并且对输入的微小改变会变得不敏感。在反向传播时,当梯度接近于0,权重基本不会更新,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练。
- sigmoid函数的输出不是0均值的,会导致后层的神经元的输入是非0均值的信号,这会对梯度产生影响。
- 计算复杂度高,因为sigmoid函数是指数形式。
2. tanh 函数
tanh(双曲正切)函数可以将元素的值变换到-1和1之间:
t a n h ( x ) = 1 − e x p ( − 2 x ) 1 + e x p ( − 2 x ) tanh(x) = \frac{1-exp(-2x)}{1+exp(-2x)} tanh(x)=1+exp(−2x)1−exp(−2x)
绘制tanh函数。当输入接近0时,tanh函数接近线性变换。虽然该函数的形状和sigmoid函数的形状很像,但tanh函数在坐标系的原点上对称。
依据链式法则,tanh函数的导数
t a n h ′ ( x ) = 1 − t a n h 2 ( x ) tanh'(x) = 1-tanh^2(x) tanh′(x)=1−tanh2(x)
下面绘制了tanh函数的导数。当输入为0时,tanh函数的导数达到最大值1;当输入越偏离0时,tanh函数的导数越接近0。
优缺点:
- Tanh函数是 0 均值的,因此实际应用中 Tanh 会比 sigmoid 更好。
- 但是仍然存在梯度饱和与exp计算的问题。
3. relu 函数
ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素xx,该函数定义为
可以看出,ReLU函数只保留正数元素,并将负数元素清零。
r e l u ( x ) = { 0 x <= 0 x x > 0 relu(x)= \begin{cases} 0& \text{x <= 0}\\ x& \text{x > 0} \end{cases} relu(x)={0xx <= 0x > 0
当输入为负数时,ReLU函数的导数为0;当输入为正数时,ReLU函数的导数为1。尽管输入为0时ReLU函数不可导,但是我们可以取此处的导数为0。下面绘制ReLU函数的导数。
优点:
- 使用ReLU的SGD算法的收敛速度比 sigmoid 和 tanh 快。
- 在x>0区域上,不会出现梯度饱和、梯度消失的问题。
- 计算复杂度低,不需要进行指数运算,只要一个阈值就可以得到激活值。
缺点:
- ReLU的输出不是0均值的。
- Dead ReLU Problem(神经元坏死现象):ReLU在负数区域被kill的现象叫做dead relu。ReLU在训练的时很“脆弱”。在x<0时,梯度为0。这个神经元及之后的神经元梯度永远为0,不再对任何数据有所响应,导致相应参数永远不会被更新。
产生这种现象的两个原因:参数初始化问题;learning rate太高导致在训练过程中参数更新太大。
解决方法:采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。
4. 如何选择正确的激活函数?
- sigmoid 激活函数:除了输出层是一个二分类问题基本不会用它。
- 由于梯度消失问题,有时要避免使用sigmoid和tanh函数。
- ReLU函数是一个通用的激活函数,目前在大多数情况下使用。
- 如果神经网络中出现死神经元,那么PReLU函数就是最好的选择。
- 请记住,ReLU函数只能在隐藏层中使用。
请说明Softmax激活函数的定义及其作用?Softmax激活函数如何应用于多分类?
softmax 是用于多分类问题的激活函数,在多分类问题中,超过两个类标签则需要类成员关系。softmax 可以将值压缩在(0,1)范围内,并且向量中元素的总和为 1。
softmax 的图像如下:
softmax 与正常的 max 函数不同:max 函数仅输出最大值,但 Softmax 确保较小的值具有较小的概率,并且不会直接丢弃。
softmax 激活函数的主要缺点是:
- 在零点不可微
- 负输入的梯度为零,这意味着对于该区域的激活,权重不会在反向传播期间更新,因此会产生永不激活的死亡神经元。
参考链接:深度学习领域最常用的10个激活函数,一文详解数学原理及优缺点
为什么深层神经网络的训练的难度很大?梯度消失和梯度爆炸。
1、梯度消失。梯度消失是指通过隐藏层从后向前看,梯度会变得越来越小,说明前面层的学习会显著慢于后面层的学习,所以学习会卡主,除非梯度变大。
梯度消失的原因:学习率的大小,网络参数的初始化,激活函数的边缘效应等。在深层神经网络中,每一个神经元计算得到的梯度都会传递给前一层,较浅层的神经元接收到的梯度受到之前所有层梯度的影响。如果计算得到的梯度值非常小,随着层数增多,求出的梯度更新信息将会以指数形式衰减,就会发生梯度消失。
2、梯度爆炸。在深度网络或循环神经网络(Recurrent Neural Network, RNN)等网络结构中,梯度可在网络更新的过程中不断累积,变成非常大的梯度,导致网络权重值的大幅更新,使得网络不稳定;在极端情况下,权重值甚至会溢出,变为None值,再也无法更新。
3、权重矩阵的退化导致模型的有效*度减少。
参数空间中学习的退化速度减慢,导致减少了模型的有效维数,网络的可用*度对学习中梯度范数的贡献不均衡,随着相乘矩阵的数量(即网络深度)的增加,矩阵的乘积变得越来越退化。在有硬饱和边界的非线性网络中(例如 ReLU 网络),随着深度增加,退化过程会变得越来越快。
参考链接:算法岗面试:Deep Learning 27 类常见问题 + 解析汇总
缓解梯度消失和梯度爆炸的方法有:
- 预训练+微调
- 梯度剪切、正则
- 改用激活函数
- batchnorm
- 使用其他神经网络结构,如:残差、LSTM等
深度学习中有哪些防止过拟合的方法?
一般来说有如下方法:
- 尽量减少特征的数量
- 数据集扩增
- 增加正则化参数 λ
- dropout
下面就比较难理解的正则化和 dropout 进行解释
1. 正则化
机器学习中几乎都可以看到损失函数后面会添加一个额外项,常用的额外项一般有两种,一般英文称作 l1-norm 或 l2-norm,中文称作 L1 正则化 和 L2 正则化,或者 L1 范数 和 L2 范数。
L1 正则化和 L2 正则化可以看做是损失函数的惩罚项。所谓『惩罚』是指对损失函数中的某些参数做一些限制。对于线性回归模型,使用 L1 正则化的模型叫做 Lasso 回归,使用 L2 正则化的模型叫做 Ridge 回归(岭回归)。
1.1 L1正则化
通常带有 L1 正则项的损失函数如下:
J = J 0 + λ ∑ i n ∣ ω i ∣ J = J_0 + λ\sum^n_i|ω_i| J=J0+λi∑n∣ωi∣
其中 J 0 J_0 J0 是原始的损失函数,加号后面一项是 L1 正则项,λ 是正则化参数,注意到:
- L1 正则项是权值的绝对值之和
我们在原始损失函数 J 0 J_0 J0 后添加 L1 正则项时,相当于对 J 0 J_0 J0 做了一个约束。令 L = α ∑ ω ∣ ω ∣ L = α\sum_ω|ω| L=α∑ω∣ω∣,则 J = J 0 + L J = J_0 + L J=J0+L,对此我们的任务变成在 L 约束下求出 J 0 J_0 J0 取最小值的解。考虑二维的情况,即只有两个权值 ω 1 ω^1 ω1 和 ω 2 ω^2 ω2。此时 L = ∣ ω 1 ∣ + ∣ ω 2 ∣ L = |ω^1| + |ω^2| L=∣ω1∣+∣ω2∣。对于梯度下降法,求解 J 0 J_0 J0 的过程可以画出等值线,同时 L1 正则化的函数 L 也可以在 ω 1 ω 2 ω^1ω^2 ω1ω2的二维平面上画出来。如下图所示:
其中彩色的圈圈是 J 0 J_0 J0 的等值线,黑色四边形是 L 函数图形。
在图中,当 J 0 J_0 J0 等值线与 L 图形首次相交的地方就是最优解。上图中 J 0 J_0 J0 与 L 的一个顶点处相交,这个顶点就是最优解,值为 ( ω 1 , ω 2 ) = ( 0 , ω ) (ω^1, ω^2) = (0, ω) (ω1,ω2)=(0,ω)。 J 0 J_0 J0 与这些角接触的机率会远大于其它部位接触的机率(这是很直觉的想象,突出的角比直线的边离等值线更近些),而在这些角上,会有很多权值等于 0(因为角就在坐标轴上),所以:
- L1 正则化可以产生稀疏权值矩阵,即产生一个稀疏模型,用于特征选择。
1.2 L2正则化
L2 正则化,也称为权重衰减。带有 L2 正则项的损失函数如下:
J = J 0 + λ ∑ i n ω i 2 J = J_0 + λ\sum^n_iω_i^2 J=J0+λi∑nωi2
- L2 正则项是权值的平方和
线性回归的损失函数为例:
J
(
ω
)
=
1
2
m
∑
i
=
1
m
(
h
ω
(
x
(
i
)
)
−
y
(
i
)
)
2
J(ω) = \frac{1}{2m} \sum^m_{i = 1}(h_ω(x^{(i)}) - y^{(i)}) ^ 2
J(ω)=2m1i=1∑m(hω(x(i))−y(i))2
在梯度下降算法中,需要先对损失函数求导,得到梯度。对于单个样本,先对某个参数
ω
j
ω_j
ωj 求导,最后得到下式:
∂
∂
ω
j
J
(
ω
)
=
1
m
∑
i
=
1
m
(
h
ω
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
\frac{\partial}{\partial ω_j}J(ω) = \frac{1} {m} \sum^m_{i = 1}(h_ω(x^{(i)}) - y^{(i)})x^{(i)}_j
∂ωj∂J(ω)=m1i=1∑m(hω(x(i))−y(i))xj(i)
最后再乘以一个系数α(学习率),得到没有添加正则项的
ω
j
ω_j
ωj 参数更新公式为:
ω
j
:
=
ω
j
−
α
1
m
∑
i
=
1
m
(
h
ω
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
ω_j := ω_j - α \frac{1} {m} \sum^m_{i = 1}(h_ω(x^{(i)}) - y^{(i)})x^{(i)}_j
ωj:=ωj−αm1i=1∑m(hω(x(i))−y(i))xj(i)
正则项 L2 对参数
ω
j
ω_j
ωj 求导:
∂
∂
ω
j
L
2
=
2
λ
ω
j
\frac{\partial}{\partial ω_j}L2 = 2 λ ω_j
∂ωj∂L2=2λωj
综合 L2 正则项之后参数
ω
j
ω_j
ωj 的更新公式为:
ω
j
:
=
ω
j
(
1
−
2
λ
)
−
α
1
m
∑
i
=
1
m
(
h
ω
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
ω_j := ω_j(1 - 2 λ) - α \frac{1} {m} \sum^m_{i = 1}(h_ω(x^{(i)}) - y^{(i)})x^{(i)}_j
ωj:=ωj(1−2λ)−αm1i=1∑m(hω(x(i))−y(i))xj(i)
其中 λ 就是正则化参数。从上式可以看到,与未添加L2正则化的迭代公式相比,每一次迭代, θ j \theta_j θj 都要先乘以一个小于1的因子,即 ( 1 − 2 λ ) (1 - 2 λ) (1−2λ),从而使得 θ j \theta_j θj 不断减小,因此总的来看, θ θ θ 是不断减小的。所以:
- L2 正则化可以产生参数值较小的模型,能适应不同的数据集,一定程度上防止过拟合,抗扰动能力强。
2. dropout
除了前面介绍的正则化方法以外,深度学习模型常常使用丢弃法(dropout)[4] 来应对过拟合问题。丢弃法有一些不同的变体。本节中提到的丢弃法特指倒置丢弃法(inverted dropout)。
描述一个单隐藏层的多层感知机。其中输入个数为 4,隐藏单元个数为 5,且隐藏单元
h
i
(
i
=
1
,
.
.
.
,
5
)
h_i (i=1,...,5)
hi(i=1,...,5) 的计算表达式为:
h
i
=
φ
(
x
1
ω
1
i
+
x
2
ω
2
i
+
x
3
ω
3
i
+
x
4
ω
4
i
+
b
i
)
h_i = φ(x_1ω_{1i} + x_2ω_{2i} + x_3ω_{3i} + x_4ω_{4i} + b_i)
hi=φ(x1ω1i+x2ω2i+x3ω3i+x4ω4i+bi)
这里 φ 是激活函数,
x
1
,
.
.
.
,
x
4
x_1,...,x_4
x1,...,x4 是输入,权重参数为
ω
1
i
,
.
.
.
,
ω
4
i
ω_{1i},...,ω_{4i}
ω1i,...,ω4i ,偏差参数为
b
i
b_i
bi。当对该隐藏层使用丢弃法时,该层的隐藏单元将有一定概率被丢弃掉。设丢弃概率为
p
p
p,那么有
p
p
p 的概率
h
i
h_i
hi 会被清零,有
1
−
p
1-p
1−p的概率
h
i
h_i
hi 会除以
1
−
p
1-p
1−p 做拉伸。丢弃概率是丢弃法的超参数。具体来说,设随机变量
ξ
i
\xi_i
ξi 为 0 和 1 的概率分别为
p
p
p 和
1
−
p
1-p
1−p。使用丢弃法时我们计算新的隐藏单元
h
i
′
=
ξ
i
1
−
p
h
i
h_i'= \frac{\xi_i}{1-p} h_i
hi′=1−pξihi
- 即丢弃法不改变其输入的期望值,而随机丢弃训练中隐藏层的神经元,从而应对过拟合。
- 在测试模型中,我们为了拿到更加确定性的结果,一般不使用丢弃法。
在上图中, h 2 h_2 h2 和 h 5 h_5 h5 被丢弃了,输出层的计算无法过度依赖 h 1 i , . . . , h 5 i h_{1i},...,h_{5i} h1i,...,h5i 中的任一个,从而在训练模型时起到正则化的作用,可以用来应对过拟合
参考资料:
[1]机器学习中正则化项L1和L2的直观理解
[2]《动手学深度学习》(PyTorch版)3.12 权重衰减
[3]数据预处理–特征选择-L1、L2正则化
[4]Srivastava, N., Hinton, G., Krizhevsky, A., Sutskever, I., & Salakhutdinov, R. (2014). Dropout: a simple way to prevent neural networks from overfitting. JMLR
[5]《动手学深度学习》(PyTorch版)3.13 丢弃法
?为什么无监督预训练可以帮助深度学习?
在深度模型训练时,为什么需要batch size?如何选择合适的batch size,对结果有何影响?
1. 为什么需要 batch size?
在没有使用 batch size 之前,这意味着网络在训练时,是一次把所有的数据(整个数据库)输入网络中,然后计算它们的梯度进行反向传播,由于在计算梯度时使用了整个数据库,所以计算得到的梯度方向更为准确。但在这情况下,计算得到不同梯度值差别巨大,难以使用一个全局的学习率,所以这时一般使用Rprop这种基于梯度符号的训练算法,单独进行梯度更新。
在小样本数的数据库中,不使用Batch Size是可行的,而且效果也很好。但是一旦是大型的数据库,一次性把所有数据输进网络,肯定会引起内存的爆炸。所以就提出Batch Size的概念。
2. 如何选择合适的 batch size?
我们可以一次性将整个数据集喂给神经网络,让神经网络利用全部样本来计算迭代时的梯度(即传统的梯度下降法),也可以一次只喂一个样本(即随机梯度下降法,也称在线梯度下降法),也可以取个折中的方案,即每次喂一部分样本让其完成本轮迭代(即batch梯度下降法)。
数学基础不太好的初学者可能在这里犯迷糊——一次性喂500个样本并迭代一次,跟一次喂1个样本迭代500次相比,有区别吗?
其实这两个做法就相当于:
第一种:
total = 旧参下计算更新值1+旧参下计算更新值2+…+旧参下计算更新值500 ;
新参数 = 旧参数 + total
第二种:
新参数1 = 旧参数 + 旧参数下计算更新值1;
新参数2 = 新参数1 + 新参数1下计算更新值1;
新参数3 = 新参数2 + 新参数2下计算更新值1;
…
新参数500 = 新参数500 + 新参数500下计算更新值1;
也就是说,第一种是将参数一次性更新500个样本的量,第二种是迭代的更新500次参数。
对于小样本数据集来说,batch size 可以设置为整个数据集,效果同样好。对于大数据集来说,batch size 一般设置为几十或者几百,通常为 2 的幂次。我们讨论的梯度下降, 默认是一阶的(只用了一阶导数去优化)。但是对于强大的二阶优化算法如共轭梯度算法、L-BFGS来说,往往需要更大的 batch,因此黑色盒子为几千甚至一两万才能发挥出最佳性能。
2.1 在合理范围内,增大 batch size 有何好处?
- 内存利用率提高了,大矩阵乘法的并行化效率提高。
- 跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
- 在一定范围内,一般来说 batch size 越大,其确定的下降方向越准,引起训练震荡越小。
2.2 盲目增大 batch size 有何坏处?
- 内存利用率提高了,但是内存容量可能撑不住了。
- 跑完一次 epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。
- batch size 增大到一定程度,其确定的下降方向已经基本不再变化。
深度学习中如何平衡方差与偏差?如果偏差过大我们应该怎么做?方差过大呢?
偏差,描述的是预测值(估计值)的期望f(x)与真实值y之间的差距。偏差越大,越偏离真实数据。
b
i
a
s
2
(
x
)
=
(
f
(
x
)
−
y
)
2
bias^2(x)=(f(x) - y)^2
bias2(x)=(f(x)−y)2
方差,描述的是预测值的变化范围,离散程度,也就是离期望值的距离。方差越大,数据的分布越分散。
通常,偏差高意味着欠拟合,方差高意味着过拟合。
偏差:避免欠拟合。
- 寻找更好的特征 – 具有代表性。
- 用更多的特征 – 增大输入向量的维度。(增加模型复杂度)
方差:避免过拟合
- 增大数据集合 – 使用更多的数据,减少数据扰动所造成的影响
- 减少数据特征 – 减少数据维度,减少模型复杂度
- 正则化方法
- 交叉验证法
- dropout
请说明dropout的原理,在训练与测试的时候dropout会有什么区别?
当对该隐藏层使用丢弃法时,该层的隐藏单元将有一定概率被丢弃掉。设丢弃概率为
p
p
p,那么有
p
p
p 的概率
h
i
h_i
hi 会被清零,有
1
−
p
1-p
1−p的概率
h
i
h_i
hi 会除以
1
−
p
1-p
1−p 做拉伸。丢弃概率是丢弃法的超参数。具体来说,设随机变量
ξ
i
\xi_i
ξi 为 0 和 1 的概率分别为
p
p
p 和
1
−
p
1-p
1−p。使用丢弃法时我们计算新的隐藏单元
h
i
′
=
ξ
i
1
−
p
h
i
h_i'= \frac{\xi_i}{1-p} h_i
hi′=1−pξihi
- 即丢弃法不改变其输入的期望值,而随机丢弃训练中隐藏层的神经元,从而应对过拟合。
- 在测试模型中,我们为了拿到更加确定性的结果,一般不使用丢弃法。
前面的过拟合问题有更具体的dropout介绍
什么是模型微调 fine-tune?为什么要微调?请说明 fine-tune 模型的三种状态,各自的特点是什么?
1. 什么是模型微调 fine-tune?
针对于某个任务,自己的训练数据不多,那怎么办? 没关系,我们先找到一个同类的别人训练好的模型,把别人现成的训练好了的模型拿过来,换成自己的数据,调整一下参数,再训练一遍,就是微调(fine-tune)
2. 为什么要微调?
- 对于数据集本身很小(几千张图片)的情况,从头开始训练具有几千万参数的大型神经网络是不现实的,因为越大的模型对数据量的要求越大,过拟合无法避免。这时候如果还想用上大型神经网络的超强特征提取能力,只能靠微调已经训练好的模型。
- 可以降低训练成本:如果使用导出特征向量的方法进行迁移学习,后期的训练成本非常低,用 CPU 都完全无压力,没有深度学习机器也可以做。
- 前人花很大精力训练出来的模型在大概率上会比你自己从零开始搭的模型要强悍,没有必要重复造*。
3. fine-tune 模型的三种状态
状态一:只预测,不训练。特点:相对较快、简单,针对那些已经训练好,现在需要实际对未知数据进行标注的项目,非常高效;
状态二:训练,但只训练最后分类层。 特点:fine-tune 的模型最终的分类以及符合要求,现在只是在他们的基础上进行类别降维。
状态三:完全训练,分类层+之前卷积层都训练 特点:跟状态二的差异很小,当然状态三比较耗时和需要训练GPU资源,不过非常适合fine-tune 到自己想要的模型里面,预测精度相比状态二也提高不少。
迁移学习和微调的关系?
举个例子,假设今天老板给你一个新的数据集,让你做一下图片分类,这个数据集是关于Flowers的。问题是,数据集中flower的类别很少,数据集中的数据也不多,你发现从零训练开始训练CNN的效果很差,很容易过拟合。怎么办呢,于是你想到了使用Transfer Learning,用别人已经训练好的Imagenet的模型来做。
做的方法有很多:
- 把Alexnet里卷积层最后一层输出的特征拿出来,然后直接用SVM分类。这是Transfer Learning,因为你用到了Alexnet中已经学到了的“知识”。
- 把Vggnet卷积层最后的输出拿出来,用贝叶斯分类器分类。思想基本同上。
- 甚至你可以把Alexnet、Vggnet的输出拿出来进行组合,自己设计一个分类器分类。这个过程中你不仅用了Alexnet的“知识”,也用了Vggnet的“知识”。
- 最后,你也可以直接使用fine-tune这种方法,在Alexnet的基础上,重新加上全连接层,再去训练网络。
综上,迁移学习它可以看作是一种学习体系,关注的核心问题是,如何将之前学习的得到的“知识”运用到其他领域中去。这可以有很多方法和手段,而fine-tune只是其中的一种手段。
权重偏差初始化有哪些方法?分别说明他们的特点.
1. 错误方法:全都初始化为 0 或者相同的数
如果权重初始化为同一个值,在进行反向传播时,所有权重将获得相同的梯度,从而进行相同的更新,网络就是对称的,即所有的节点都将学习相同的东西。
2. 随机初始化为小的随机数
一个权重矩阵的实现可能看起来像 w = 0.01 ∗ n p . r a n d o m . r a n d n ( D , H ) w = 0.01 * np.random.randn(D, H) w=0.01∗np.random.randn(D,H),其中 randn 是从均值为 0 的单位标准高斯分布进行取样。通过这个公式(函数),每个神经元的权重向量初始化为一个从多维高斯分布取样的随机向量,所以神经元在输入空间中指向随机的方向。其实也可以从均匀分布中来随机选取小数,但是在实际操作中看起来似乎对最后的表现并没有太大的影响。
警告:并不是数字越小就会表现的越好。比如,如果一个神经网络层的权重非常小,那么在反向传播算法就会计算出很小的梯度(因为梯度gradient是与权重成正比的)。在网络不断的反向传播过程中将极大地减少“梯度信号”,并可能成为深层网络的一个需要注意的问题。
3. 用 1\sqrt(n) 校验方差
上述建议的一个问题是,随机初始化神经元的输出的分布有一个随输入量增加而变化的方差。结果证明,我们可以通过将其权重向量按其输入的平方根(即输入的数量)进行缩放,从而将每个神经元的输出的方差标准化到1。也就是说推荐的启发式方法(heuristic)是将每个神经元的权重向量按下面的方法进行初始化 w = n p . r a n d o m . r a n d n ( n ) / s q r t ( n ) w = np.random.randn(n) / sqrt(n) w=np.random.randn(n)/sqrt(n),其中 n 表示输入的数量。这保证网络中所有的神经远最初的输出分布大致相同,并在经验上提高了收敛速度。
4. 稀疏初始化(Sparse Initialazation)
另一种解决未校准方差问题的方法是把所有的权重矩阵都设为零,但是为了打破对称性,每个神经元都是随机连接地(从如上面所介绍的一个小的高斯分布中抽取权重)到它下面的一个固定数量的神经元。一个典型的神经元连接的数目可能是小到10个。
5. Batch Normalization
具体原理在之后进行讲解
设置学习率的作用是什么?常用的学习率衰减方法有哪些?说明他们各自的特点.
1. 定义与作用
学习率是在梯度下降的过程中更新权重时的超参数,即下面公式中的 α
θ
=
θ
−
α
∂
∂
θ
J
(
θ
)
\theta =\theta -\alpha \frac{\partial }{\partial \theta }J(\theta )
θ=θ−α∂θ∂J(θ)
学习率越低,损失函数的变化速度就越慢,容易过拟合。虽然使用低学习率可以确保我们不会错过任何局部极小值,但也意味着我们将花费更长的时间进行收敛,特别是被困在局部最优点的时候。而学习率过高容易发生梯度爆炸,loss 震动幅度较大,模型难以收敛。
参考资料:一文看懂学习率Learning Rate,从入门到CLR
2. 衰减方法
2.1 分段常数衰减
分段常数衰减需要事先定义好的训练次数(epoch)区间,在对应区间置不同的学习率的常数值,一般情况刚开始的学习率要大一些,之后要越来越小,要根据样本量的大小设置区间的间隔大小,样本量越大,区间间隔要小一点。下图即为分段常数衰减的学习率变化图,横坐标代表训练次数,纵坐标代表学习率。
2.2 指数衰减
以指数衰减方式进行学习率的更新,学习率的大小和训练次数指数相关,其更新规则为:
d
e
c
a
y
e
d
_
l
e
a
r
n
i
n
_
r
a
t
e
=
l
e
a
r
n
i
n
g
_
r
a
t
e
∗
d
e
c
a
y
_
r
a
t
e
g
l
o
b
a
l
s
t
e
p
d
e
c
a
y
s
t
e
p
decayed\_learnin\_rate = learning\_rate * decay\_rate^{\frac{global_{step}}{decay_{step}}}
decayed_learnin_rate=learning_rate∗decay_ratedecaystepglobalstep
这种衰减方式简单直接,收敛速度快,是最常用的学习率衰减方式,如下图所示,绿色的为学习率随训练次数的指数衰减方式,红色的即为分段常数衰减,它在一定的训练区间内保持学习率不变。
2.3 自然指数衰减
它与指数衰减方式相似,不同的在于它的衰减底数是 e,故而其收敛的速度更快,一般用于相对比较容易训练的网络,便于较快的收敛,其更新规则如下:
d
e
c
a
y
e
d
_
l
e
a
r
n
i
n
_
r
a
t
e
=
l
e
a
r
n
i
n
g
_
r
a
t
e
∗
e
g
l
o
b
a
l
s
t
e
p
d
e
c
a
y
s
t
e
p
decayed\_learnin\_rate = learning\_rate * e^{\frac{global_{step}}{decay_{step}}}
decayed_learnin_rate=learning_rate∗edecaystepglobalstep
下图为为分段常数衰减、指数衰减、自然指数衰减三种方式的对比图,红色的即为分段常数衰减图,阶梯型曲线。蓝色线为指数衰减图,绿色即为自然指数衰减图,很明可以看到自然指数衰减方式下的学习率衰减程度要大于一般指数衰减方式,有助于更快的收敛。
2.4 多项式衰减
应用多项式衰减的方式进行更新学习率,这里会给定初始学习率和最低学习率取值,然后将会按照给定的衰减方式将学习率从初始值衰减到最低值,其更新规则如下式所示。
g
l
o
b
a
l
_
s
t
e
p
=
m
i
n
(
g
l
o
b
a
l
_
s
t
e
p
,
d
e
c
a
y
_
s
t
e
p
s
)
global\_step = min(global\_step, decay\_steps)
global_step=min(global_step,decay_steps)
d
e
c
a
y
_
l
e
a
r
n
i
n
g
_
r
a
t
e
=
(
l
e
a
r
n
i
n
g
_
r
a
t
e
−
e
n
d
_
l
e
a
r
n
i
n
g
_
r
a
t
e
)
∗
(
1
−
g
l
o
b
a
l
_
s
t
e
p
d
e
c
a
y
_
s
t
e
p
s
)
p
o
w
e
r
+
e
n
d
_
l
e
a
r
n
i
n
g
_
r
a
e
t
decay\_learning\_rate = (learning\_rate - end\_learning\_rate) * (1 - \frac{global\_step}{decay\_steps})^{power} + end\_learning\_raet
decay_learning_rate=(learning_rate−end_learning_rate)∗(1−decay_stepsglobal_step)power+end_learning_raet
需要注意的是,有两个机制,降到最低学习率后,到训练结束可以一直使用最低学习率进行更新,另一个是再次将学习率调高,使用 decay_steps 的倍数,取第一个大于 global_steps 的结果,如下式所示.它是用来防止神经网络在训练的后期由于学习率过小而导致的网络一直在某个局部最小值附近震荡,这样可以通过在后期增大学习率跳出局部极小值。
d
e
c
a
y
_
s
t
e
p
s
=
d
e
c
a
y
_
s
t
e
p
s
∗
c
a
i
l
(
g
l
o
b
a
l
_
s
t
e
p
s
e
c
a
y
_
s
t
e
p
s
)
decay\_steps = decay\_steps * cail(\frac{global\_step}{secay\_steps})
decay_steps=decay_steps∗cail(secay_stepsglobal_step)
如下图所示,红色线代表学习率降低至最低后,一直保持学习率不变进行更新,绿色线代表学习率衰减到最低后,又会再次循环往复的升高降低。
2.5 余弦衰减
余弦衰减就是采用余弦的相关方式进行学习率的衰减,衰减图和余弦函数相似。其更新机制如下式所示
g
l
o
b
a
l
_
s
t
e
p
=
min
(
g
l
o
b
a
l
_
s
t
e
p
,
d
e
c
a
y
_
s
t
e
p
s
)
cos
i
n
e
_
d
e
c
a
y
=
0.5
∗
(
1
+
cos
(
π
∗
g
l
o
b
a
l
_
s
t
e
p
d
e
c
a
y
_
s
t
e
p
s
)
)
d
e
c
a
y
e
d
=
(
1
−
α
)
∗
cos
i
n
e
_
d
e
c
a
y
+
α
d
e
c
a
y
e
d
_
l
e
a
r
n
i
n
g
_
r
a
t
e
=
l
e
a
r
n
i
n
g
_
r
a
t
e
+
d
e
c
a
y
e
d
\begin{aligned} & global\_step=\min (global\_step,decay\_steps) \\ & \cos ine\_decay=0.5*(1+\cos (\pi *\frac{global\_step}{decay\_steps})) \\ & decayed=(1-\alpha )*\cos ine\_decay+\alpha \\ & decayed\_learning\_rate=learning\_rate+decayed \\ \end{aligned}
global_step=min(global_step,decay_steps)cosine_decay=0.5∗(1+cos(π∗decay_stepsglobal_step))decayed=(1−α)∗cosine_decay+αdecayed_learning_rate=learning_rate+decayed
如下图所示,红色即为标准的余弦衰减曲线,学习率从初始值下降到最低学习率后保持不变。蓝色的线是线性余弦衰减方式曲线,它是学习率从初始学习率以线性的方式下降到最低学习率值。绿色噪声线性余弦衰减方式。
请说出几种常用的优化算法,以及他们各自的特点。
1. Batch Gradient Descent (BGD)
梯度更新规则:
BGD 采用整个训练集的数据了计算 cost function 对参数的梯度:
θ
=
θ
−
η
⋅
∇
θ
J
(
θ
)
\theta =\theta -\eta \cdot {{\nabla }_{\theta }}J(\theta )
θ=θ−η⋅∇θJ(θ)
缺点:
由于这种方法是在一次更新中,就对整个数据集计算梯度,所以计算起来非常慢,遇到很大量的数据集也会非常棘手,而且不能投入新数据实时更新模型。
2. Stochastic Gradient Descent (SGD)
梯度更新规则:
和 BGD 的一次用所有数据计算梯度相比,SGD 每次更新时对每个样本进行梯度更新,对于很大的数据集来说,可能会有相似的样本,这样 BGD 在计算梯度时会出现冗余,而 SGD 一次只进行一次更新,就没有冗余,而且比较快,并且可以新增样本。
θ
=
θ
−
η
⋅
∇
θ
J
(
θ
;
x
(
i
)
;
y
(
i
)
)
\theta =\theta -\eta \cdot {{\nabla }_{\theta }}J(\theta ;{{x}^{(i)}};{{y}^{(i)}})
θ=θ−η⋅∇θJ(θ;x(i);y(i))
随机梯度下降是通过每个样本来迭代更新一次,如果样本量很大的情况,那么可能只用其中部分的样本,就已经将theta迭代到最优解了,对比上面的批量梯度下降,迭代一次需要用到十几万训练样本,一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次。缺点是SGD的噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。所以虽然训练速度快,但是准确度下降,并不是全局最优。虽然包含一定的随机性,但是从期望上来看,它是等于正确的导数的。
缺点:
- SGD 因为更新比较频繁,会造成 cost function 有严重的震荡。
- BGD 可以收敛到局部极小值,当然 SGD 的震荡可能会跳到更好的局部极小值处。
- 当我们稍微减小 learning rate,SGD 和 BGD 的收敛性是一样的。
3. Mini-Batch Gradient Descent (MBGD)
梯度更新规则:
MBGD 每一次利用一小批样本,即 n 个样本进行计算,这样它可以降低参数更新时的方差,收敛更稳定,另一方面可以充分地利用深度学习库中高度优化的矩阵操作来进行更有效的梯度计算。
θ
=
θ
−
η
⋅
∇
θ
J
(
θ
;
x
(
i
:
i
+
n
)
;
y
(
i
:
i
+
n
)
)
\theta =\theta -\eta \cdot {{\nabla }_{\theta }}J(\theta ;{{x}^{(i:i+n)}};{{y}^{(i:i+n)}})
θ=θ−η⋅∇θJ(θ;x(i:i+n);y(i:i+n))
和 SGD 的区别是每一次循环不是作用于每个样本,而是具有 n 个样本的批次。
超参数设定值: n 一般取值在 50~256
缺点:(两大缺点)
- 不过 Mini-batch gradient descent 不能保证很好的收敛性,learning rate 如果选择的太小,收敛速度会很慢,如果太大,loss function 就会在极小值处不停地震荡甚至偏离。(有一种措施是先设定大一点的学习率,当两次迭代之间的变化低于某个阈值后,就减小 learning rate,不过这个阈值的设定需要提前写好,这样的话就不能够适应数据集的特点。)对于非凸函数,还要避免陷于局部极小值处,或者鞍点处,因为鞍点周围的error是一样的,所有维度的梯度都接近于0,SGD 很容易被困在这里。(会在鞍点或者局部最小点震荡跳动,因为在此点处,如果是训练集全集带入即BGD,则优化会停止不动,如果是mini-batch或者SGD,每次找到的梯度都是不同的,就会发生震荡,来回跳动。)
- SGD对所有参数更新时应用同样的 learning rate,如果我们的数据是稀疏的,我们更希望对出现频率低的特征进行大一点的更新。LR会随着更新的次数逐渐变小。
鞍点处,在某些方向上是峰顶,在其他方向上是谷底。
图片来源:https://blog.csdn.net/JNingWei/article/details/79801699
为了应对上面的两点挑战就有了下面这些算法:
4. Momentum
【应对上述挑战1】
SGD 在 ravines 的情况下容易被困住, ravines 就是曲面的一个方向比另一个方向更陡,这时 SGD 会发生震荡而迟迟不能接近极小值:
Momentum 通过加入
γ
v
t
−
1
γv_{t−1}
γvt−1 ,可以加速 SGD, 并且抑制震荡。
v
t
=
γ
v
t
−
1
+
η
∇
θ
J
(
θ
)
θ
=
θ
−
v
t
\begin{aligned} & {{v}_{t}}=\gamma {{v}_{t-1}}+\eta {{\nabla }_{\theta }}J(\theta ) \\ & \theta =\theta -{{v}_{t}} \\ \end{aligned}
vt=γvt−1+η∇θJ(θ)θ=θ−vt
当我们将一个小球从山上滚下来时,没有阻力的话,它的动量会越来越大,但是如果遇到了阻力,速度就会变小。
加入的这一项,可以使得梯度方向不变的维度上速度变快,梯度方向有所改变的维度上的更新速度变慢,这样就可以加快收敛并减小震荡。
超参数设定值: 一般 γ 取值 0.9 左右。
缺点:
这种情况相当于小球从山上滚下来时是在盲目地沿着坡滚,如果它能具备一些先知,例如快要上坡时,就知道需要减速了的话,适应性会更好。
【应对挑战2】
5. Adagrad(Adaptive gradient algorithm)
这个算法就可以对低频的参数做较大的更新,对高频的做较小的更新,也因此,对于稀疏的数据它的表现很好,很好地提高了 SGD 的鲁棒性,例如识别 Youtube 视频里面的猫,训练 GloVe word embeddings,因为它们都是需要在低频的特征上有更大的更新。
梯度更新规则:
θ
t
+
1
,
i
=
θ
t
,
i
−
η
G
t
,
i
i
+
ε
⋅
g
t
,
i
{{\theta }_{t+1,i}}={{\theta }_{t,i}}-\frac{\eta }{\sqrt{{{G}_{t,ii}}+\varepsilon }}\cdot {{g}_{t,i}}
θt+1,i=θt,i−Gt,ii+εη⋅gt,i
其中
g
t
,
i
g_{t,i}
gt,i 为 t 时刻参数
θ
i
θ_i
θi 的梯度
g
t
,
i
=
∇
θ
J
(
θ
i
)
{{g}_{t,i}}={{\nabla }_{\theta }}J({{\theta }_{i}})
gt,i=∇θJ(θi)
Adagrad 的优点是减少了学习率的手动调节。超参数设定值:一般η选取0.01
缺点:
它的缺点是分母会不断积累,这样学习率就会收缩并最终会变得非常小。
6. Adadelta
这个算法是对 Adagrad 的改进,
和 Adagrad 相比,就是分母的 G 换成了过去的梯度平方的衰减平均值,指数衰减平均值
Δ
θ
t
=
−
η
E
[
g
2
]
t
+
ε
g
t
\Delta {{\theta }_{t}}=-\frac{\eta }{\sqrt{E{{[{{g}^{2}}]}_{t}}+\varepsilon }}{{g}_{t}}
Δθt=−E[g2]t+εηgt
这个分母相当于梯度的均方根 root mean squared (RMS),在数据统计分析中,将所有值平方求和,求其均值,再开平方,就得到均方根值 ,所以可以用 RMS 简写:
Δ
θ
t
=
−
η
R
M
S
[
g
]
t
g
t
\Delta {{\theta }_{t}}=-\frac{\eta }{RMS{{[g]}_{t}}}{{g}_{t}}
Δθt=−RMS[g]tηgt
其中 E 的计算公式如下,t 时刻的依赖于前一时刻的平均和当前的梯度:
E
[
g
2
]
t
=
γ
E
[
g
2
]
t
−
1
+
(
1
−
γ
)
g
t
2
E{{[{{g}^{2}}]}_{t}}=\gamma E{{[{{g}^{2}}]}_{t-1}}+(1-\gamma )g_{t}^{2}
E[g2]t=γE[g2]t−1+(1−γ)gt2
梯度更新规则:
此外,将学习率
η
η
η 换称了
R
M
S
[
Δ
θ
]
RMS[\Delta θ]
RMS[Δθ],这样的话,我们甚至都不需要提前设置学习率了:
Δ
θ
t
=
−
R
M
S
[
Δ
θ
]
t
−
1
R
M
S
[
g
]
t
g
t
θ
t
+
1
=
θ
t
+
Δ
θ
t
\begin{aligned} & \Delta {{\theta }_{t}}=-\frac{RMS{{[\Delta \theta ]}_{t-1}}}{RMS{{[g]}_{t}}}{{g}_{t}} \\ & {{\theta }_{t+1}}={{\theta }_{t}}+\Delta {{\theta }_{t}} \\ \end{aligned}
Δθt=−RMS[g]tRMS[Δθ]t−1gtθt+1=θt+Δθt
超参数设定值: γ 一般设定为 0.9
7. RMSprop
RMSprop 是 Geoff Hinton 提出的一种自适应学习率方法。
RMSprop 和 Adadelta 都是为了解决 Adagrad 学习率急剧下降问题的,
梯度更新规则:
RMSprop 与 Adadelta 的第一种形式相同:(使用的是指数加权平均,旨在消除梯度下降中的摆动,与Momentum的效果一样,某一维度的导数比较大,则指数加权平均就大,某一维度的导数比较小,则其指数加权平均就小,这样就保证了各维度导数都在一个量级,进而减少了摆动。允许使用一个更大的学习率η)
E [ g 2 ] t = 0.9 E [ g 2 ] t − 1 + 0.1 g t 2 θ t + 1 = θ t − η E [ g 2 ] t + e \begin{aligned} & E{{[{{g}^{2}}]}_{t}}=0.9E{{[{{g}^{2}}]}_{t-1}}+0.1g_{t}^{2} \\ & {{\theta }_{t+1}}={{\theta }_{t}}-\frac{\eta }{\sqrt{E{{[{{g}^{2}}]}_{t}}+e}} \\ \end{aligned} E[g2]t=0.9E[g2]t−1+0.1gt2θt+1=θt−E[g2]t+eη
超参数设定值:
Hinton 建议设定 γ 为 0.9, 学习率 η 为 0.1。
8. Adam:Adaptive Moment Estimation
这个算法是另一种计算每个参数的自适应学习率的方法。相当于 RMSprop + Momentum
除了像 Adadelta 和 RMSprop 一样存储了过去梯度的平方
v
t
v_t
vt 的指数衰减平均值 ,也像 momentum 一样保持了过去梯度
m
t
m_t
mt 的指数衰减平均值:
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
g
t
2
\begin{aligned} & {{m}_{t}}={{\beta }_{1}}{{m}_{t-1}}+(1-{{\beta }_{1}}){{g}_{t}} \\ & {{v}_{t}}={{\beta }_{2}}{{v}_{t-1}}+(1-{{\beta }_{2}})g_{t}^{2} \\ \end{aligned}
mt=β1mt−1+(1−β1)gtvt=β2vt−1+(1−β2)gt2
如果 mt 和 vt 被初始化为 0 向量,那它们就会向 0 偏置,所以做了偏差校正,通过计算偏差校正后的 mt 和 vt 来抵消这些偏差:
m
^
t
=
m
t
1
−
β
1
t
v
^
t
=
v
t
1
−
β
2
t
\begin{aligned} & {{{\hat{m}}}_{t}}=\frac{{{m}_{t}}}{1-\beta _{1}^{t}} \\ & {{{\hat{v}}}_{t}}=\frac{{{v}_{t}}}{1-\beta _{2}^{t}} \\ \end{aligned}
m^t=1−β1tmtv^t=1−β2tvt
梯度更新规则:
θ
t
+
1
=
θ
t
−
η
v
^
i
+
ε
m
^
t
{{\theta }_{t+1}}={{\theta }_{t}}-\frac{\eta }{\sqrt{{{{\hat{v}}}_{i}}}+\varepsilon }{{\hat{m}}_{t}}
θt+1=θt−v^i+εηm^t
超参数设定值:
建议 β1 = 0.9,β2 = 0.999,ϵ = 10e−8
实践表明,Adam 比其他适应性学习方法效果要好。
效果比较
几种算法在鞍点的表现:
几种算法在等高线的表现:
上面两种情况都可以看出,Adagrad, Adadelta, RMSprop 几乎很快就找到了正确的方向并前进,收敛速度也相当快,而其它方法要么很慢,要么走了很多弯路才找到。由图可知自适应学习率方法即 Adagrad, Adadelta, RMSprop, Adam 在这种情景下会更合适而且收敛性更好。
如何选择优化算法
- 如果数据是稀疏的,就用自适用方法,即 Adagrad, Adadelta, RMSprop, Adam。
- RMSprop, Adadelta, Adam 在很多情况下的效果是相似的。
- Adam 就是在 RMSprop 的基础上加了 bias-correction 和 momentum,
- 随着梯度变的稀疏,Adam 比 RMSprop 效果会好。
- 整体来讲,Adam 是最好的选择。
- 很多论文里都会用 SGD,没有 momentum 等。SGD 虽然能达到极小值,但是比其它算法用的时间长,而且可能会被困在鞍点。
- 如果需要更快的收敛,或者是训练更深更复杂的神经网络,需要用一种自适应的算法。
参考资料:深度学习——优化器算法Optimizer详解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)
请你用实例说明一下前向传播和反向传播。
一定要把各项定义提前写好,包括 w、b、h、o、sigmod、E、η
定义一个只有一层隐藏层,每层有两个神经元的神经网络,初始化权重和偏差。
用如下公式计算隐藏层或输出层的值
h
=
w
11
∗
x
1
+
w
12
∗
x
2
+
b
1
h = w_{11} * x_1 + w_{12} * x_2 + b_1
h=w11∗x1+w12∗x2+b1
o
=
w
21
∗
h
1
+
w
22
∗
h
2
+
b
2
o = w_{21} * h_1 + w_{22} * h_2 + b_2
o=w21∗h1+w22∗h2+b2
每计算完一次,则用 sigmod 等激活函数做一次非线性变换。
用均方误差公式作为损失函数,计算预测值与真实值的差距,对所有误差求和:
E
=
1
2
∑
(
p
r
e
d
−
t
a
r
g
e
t
)
2
E = \frac{1}{2}\sum(pred - target)^2
E=21∑(pred−target)2
再做反向传播,根据计算图,从最后往前链式法则一项项推导,注意更新权重和偏差的时候,还要有学习率。
参考这篇博客,步骤写得非常详细!
BP原理 - 前向计算与反向传播实例
白化是什么?
白化(Whitening)是机器学习里面常用的一种规范化数据分布的方法,主要是PCA白化与ZCA白化。白化是对输入数据分布进行变换,进而达到以下两个目的:
- 使得输入特征分布具有相同的均值与方差。其中:
- PCA白化保证了所有特征分布均值为0,方差为1;
- ZCA白化则保证了所有特征分布均值为0,方差相同。
- 去除特征之间的相关性。
通过白化操作,我们可以减缓ICS的问题,进而固定了每一层网络输入分布,加速网络训练过程的收敛(LeCun et al.,1998b;Wiesler&Ney,2011)。
白化主要有一下两个问题:
- 白化过程计算成本太高,并且在每一轮训练中的每一层我们都需要做如此高成本计算的白化操作;
- 白化过程由于改变了网络每一层的分布,因而改变了网络层中本身数据的表达能力。底层网络学习到的参数信息会被白化操作丢失掉。
请说明BN的原理,为什么要进行批归一化?
1. 原理
在深度学习中,由于采用full batch的训练方式对内存要求较大,且每一轮训练时间过长;我们一般都会采用对数据做划分,用mini-batch对网络进行训练。因此,Batch Normalization也就在mini-batch的基础上进行计算。
BN一般置于每一层的激活层之前,通过如下公式,对数据进行规范化,保证数据变为均值为0、标准差为1的分布。这样使得激活输入值落在非线性函数对输入比较敏感的区域,网络的输出就不会很大,可以得到比较大的梯度,避免梯度消失问题产生,而且梯度变大意味着学习收敛速度快,能大大加快训练速度。
2. BN层的作用
BN层的作用主要有三个:
1.加快网络的训练和收敛的速度;
2.控制梯度爆炸防止梯度消失;
3.防止过拟合。
接下来就分析一下为什么BN层有着三个作用。
2.1 加快网络的训练和收敛的速度
在深度神经网络中中,如果每层的数据分布都不一样的话,将会导致网络非常难收敛和训练,而如果把 每层的数据都在转换在均值为零,方差为1 的状态下,这样每层数据的分布都是一样的训练会比较容易收敛。
2.2 控制梯度爆炸防止梯度消失
梯度消失:在深度神经网络中,如果网络的激活输出很大,其对应的梯度就会很小,导致网络的学习速率就会很慢,假设网络中每层的学习梯度都小于最大值0.25,网络中有n层,因为链式求导的原因,第一层的梯度将会小于0.25的n次方,所以学习速率相对来说会变的很慢,而对于网络的最后一层只需要对自身求导一次,梯度就大,学习速率就会比较快,这就会造成在一个很深的网络中,浅层基本不学习,权值变化小,而后面几层网络一直学习,后面的网络基本可以表征整个网络,这样失去了深度的意义。(使用BN层归一化后,网络的输出就不会很大,梯度就不会很小)
梯度爆炸:第一层偏移量的梯度=激活层斜率1x权值1x激活层斜率2x…激活层斜率(n-1)x权值(n-1)x激活层斜率n,假如激活层斜率均为最大值0.25,所有层的权值为100,这样梯度就会指数增加。(使用bn层后权值的更新也不会很大
2.3 防止过拟合
在网络的训练中,BN的使用使得一个minibatch中所有样本都被关联在了一起,因此网络不会从某一个训练样本中生成确定的结果,即同样一个样本的输出不再仅仅取决于样本的本身,也取决于跟这个样本同属一个batch的其他样本,而每次网络都是随机取batch,这样就会使得整个网络不会朝这一个方向使劲学习。一定程度上避免了过拟合。
为什么BN层一般用在线性层和卷积层后面,而不是放在非线性单元后?
原文中是这样解释的,因为非线性单元的输出分布形状会在训练过程中变化,归一化无法消除他的方差偏移,相反的,全连接和卷积层的输出一般是一个对称,非稀疏的一个分布,更加类似高斯分布,对他们进行归一化会产生更加稳定的分布。其实想想也是的,像relu这样的激活函数,如果你输入的数据是一个高斯分布,经过他变换出来的数据能是一个什么形状?小于0的被抑制了,也就是分布小于0的部分直接变成0了,这样不是很高斯了。
参考链接:神经网络中BN层的原理与作用
参考文献:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
神经网络分类
1. 卷积神经网络 CNN
卷积神经网络主要由这几类层构成:输入层、卷积层,ReLU层、池化(Pooling)层和全连接层(全连接层和常规神经网络中的一样)。通过将这些层叠加起来,就可以构建一个完整的卷积神经网络。
- 卷积操作:通常和filter对应位相乘
-
带padding的卷积操作:池化一般通过简单的最大值、最小值或平均值操作完成
-
池化操作
2. 循环神经网络 RNN
RNN 跟传统神经网络最大的区别在于每次都会将前一次的输出结果,带到下一次的隐藏层中,一起训练,每个神经元的输入是上一个神经元的输出。如下图所示:
3. 残差神经网络 ResNet
残差网络依旧让非线形层满足 H(x,wh) ,然后从输入直接引入一个短连接到非线形层的输出上,使得整个映射变为 y = H ( x , w h ) + x y = H(x, wh) + x y=H(x,wh)+x
y = H ( x , w h ) + x y = H(x, wh) + x y=H(x,wh)+x
这就是残差网路的核心公式,换句话说,残差是网络搭建的一种操作,任何使用了这种操作的网络都可以称之为残差网络。
结构的定义如下图:
- 残差网络的特点是容易优化,并且能够通过增加相当的深度来提高准确率。
- 其内部的残差块使用了跳跃链接,缓解了在深度神经网络中增加深度带来了梯度消失的问题。
- 通过直接将输入信息绕道传到输出,保护信息的完整性
- 整个网络只需要学习输入和输出有差别的那一部分,这样就简化了学习目标以及难度。