Markdown笔记原文链接
文章目录
- Markdown笔记原文链接
- 一、神经网络和深度学习
- 二、改善深层神经网络:超参数调试、正则化以及优化
- 2.1 深度学习的实践层面
- 2.1.1 训练,验证,测试集(Train / Dev / Test sets)
- 2.1.2 偏差,方差
- 2.1.3 机器学习基础
- 2.1.4 L2正则化(Regularization)
- 2.1.5 dropout 正则化
- 2.1.6 其他正则化方法
- 2.1.7 归一化输入(Normalizing inputs)
- 2.1.8 梯度消失/梯度爆炸(Vanishing / Exploding gradients)
- 2.1.9 神经网络的权重初始化(Weight Initialization for Deep NetworksVanishing / Exploding gradients)
- 2.1.10 梯度检验
- 2.2优化算法 (Optimization algorithms)
- 2.3 超参数调试、Batch归一化和Softmax
基于Andrew Ng教授的deeplearning.ai课程及邱锡鹏教授所著的《神经网络与深度学习》整理,对应于第一、二节课
一、神经网络和深度学习
1.1 神经网络基础
符号定义 :
-
x x x:表示一个 n x n_x nx维特征的输入样本数据,维度为 ( n x , 1 ) (n_x,1) (nx,1);
-
y y y:表示输出结果,取值为 ( 0 , 1 ) (0,1) (0,1);
-
( x ( i ) , y ( i ) ) (x^{(i)},y^{(i)}) (x(i),y(i)):表示第 i i i组数据,可能是训练数据,也可能是测试数据;
-
X = [ x ( 1 ) , x ( 2 ) , . . . , x ( m ) ] X=[x^{(1)},x^{(2)},...,x^{(m)}] X=[x(1),x(2),...,x(m)]:表示所有的训练数据集的输入值,放在一个 n x × m n_x×m nx×m的矩阵中,其中 m m m表示样本数目;
-
Y = [ y ( 1 ) , y ( 2 ) , . . . , y ( m ) ] Y=[y^{(1)},y^{(2)},...,y^{(m)}] Y=[y(1),y(2),...,y(m)]:对应表示所有训练数据集的输出值,维度为 1 × m 1×m 1×m。
1.1.1 逻辑回归(Logistic Regression)
该算法适用于二分类问题
对于二元分类问题,给一个输入特征向量 X X X,可能对应一张图片,通过这张图片识别是否是一只猫,需要一个算法能够输出预测 y ^ \hat{y} y^, y ^ \hat{y} y^是对于实际值 y y y 的估计。
如果用 n x n_x nx维向量 w w w来表示逻辑回归的一个参数( w w w实际上是特征的权重),另一个参数 b b b是一个实数(表示偏差)。如果让 y ^ = w T x + b \hat{y}={{w}^{T}}x+b y^=wTx+b,形成一个关于输入 x x x的线性函数,这对于二元分类问题来讲不是一个好的算法,因为 y ^ \hat{y} y^ 应该在0到1之间,而 w T x + b {{w}^{T}}x+b wTx+b可能比1要大得多,或者甚至为负值。
因此在逻辑回归中,可以将上式作为sigmoid函数的自变量,将线性函数转换为非线性函数,sigmoid函数将值域变换到了(0,1)。
sigmoid函数公式:
σ
(
z
)
=
1
1
+
e
−
z
\sigma \left( z \right)=\frac{1}{1+{{e}^{-z}}}
σ(z)=1+e−z1
当实现逻辑回归时,需要让机器学习参数 w w w和 b b b这样使得 y ^ \hat{y} y^成为对 y = 1 y=1 y=1这一情况的概率的一个好的估计
1.1.2 逻辑回归的代价函数(Logistic Regression Cost Function)
损失函数:
损失函数又叫做误差函数,用来衡量算法的预测值和实际值的偏差情况
Loss function: L ( y ^ , y ) L\left( \hat{y},y \right) L(y^,y)
逻辑回归中通常不使用平方损失函数,其优化目标不是凸优化。
![img](https://i-blog.csdnimg.cn/blog_migrate/a1cdb2b6324e09c1c8b84d756bc2f1d8.jpeg)
在逻辑回归中用到的损失函数是交叉熵损失函数: L ( y ^ , y ) = − y log ( y ^ ) − ( 1 − y ) log ( 1 − y ^ ) L\left( \hat{y},y \right)=-y\log(\hat{y})-(1-y)\log (1-\hat{y}) L(y^,y)=−ylog(y^)−(1−y)log(1−y^)
损失函数是在单个训练样本中定义的,它衡量的是算法在单个训练样本中表现如何,为了衡量算法在全部训练样本上的表现如何,需要定义一个算法的代价函数。
代价函数:
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
=
1
m
∑
i
=
1
m
(
−
y
(
i
)
log
y
^
(
i
)
−
(
1
−
y
(
i
)
)
log
(
1
−
y
^
(
i
)
)
)
J\left( w,b \right)=\frac{1}{m}\sum\limits_{i=1}^{m}{L\left( {{{\hat{y}}}^{(i)}},{{y}^{(i)}} \right)}=\frac{1}{m}\sum\limits_{i=1}^{m}{\left( -{{y}^{(i)}}\log {{{\hat{y}}}^{(i)}}-(1-{{y}^{(i)}})\log (1-{{{\hat{y}}}^{(i)}}) \right)}
J(w,b)=m1i=1∑mL(y^(i),y(i))=m1i=1∑m(−y(i)logy^(i)−(1−y(i))log(1−y^(i)))
**为什么需要代价函数:**为了训练逻辑回归模型的参数 w w w和 b b b,需要一个代价函数,通过调整参数 w w w和 b b b来降低代价函数。
1.1.3 梯度下降法(Gradient Descent)
梯度下降法的作用:
在训练集上通过最小化代价函数 J ( w , b ) J(w,b) J(w,b)来训练参数 w w w和 b b b, 前提是必须定义代价函数为凸函数。
假设样本只有两个特征 x 1 {{x}_{1}} x1和 x 2 {{x}_{2}} x2
z z z的计算公式为: z = w 1 x 1 + w 2 x 2 + b z={{w}_{1}}{{x}_{1}}+{{w}_{2}}{{x}_{2}}+b z=w1x1+w2x2+b
逻辑回归的公式定义: y ^ = a = σ ( z ) \hat{y}=a=\sigma (z) y^=a=σ(z), z = w T x + b z={{w}^{T}}x+b z=wTx+b , σ ( z ) = 1 1 + e − z \sigma \left( z \right)=\frac{1}{1+{{e}^{-z}}} σ(z)=1+e−z1
损失函数: L ( y ^ ( i ) , y ( i ) ) = − y ( i ) log y ^ ( i ) − ( 1 − y ( i ) ) log ( 1 − y ^ ( i ) ) L( {{{\hat{y}}}^{(i)}},{{y}^{(i)}})=-{{y}^{(i)}}\log {{\hat{y}}^{(i)}}-(1-{{y}^{(i)}})\log (1-{{\hat{y}}^{(i)}}) L(y^(i),y(i))=−y(i)logy^(i)−(1−y(i))log(1−y^(i))
代价函数: J ( w , b ) = 1 m ∑ i m L ( y ^ ( i ) , y ( i ) ) J\left( w,b \right)=\frac{1}{m}\sum\nolimits_{i}^{m}{L( {{{\hat{y}}}^{(i)}},{{y}^{(i)}})} J(w,b)=m1∑imL(y^(i),y(i))
单个样本的梯度下降
假设现在只考虑单个样本 x ( i ) x^{(i)} x(i)的情况,单个样本的代价函数定义如下: J ( w , b ) = L ( a ( i ) , y ( i ) ) = − y ( i ) log a ( i ) − ( 1 − y ( i ) ) log ( 1 − a ( i ) ) J\left( w,b \right)=L(a^{(i)},y^{(i)})=-{{y}^{(i)}}\log {a^{(i)}}-(1-{{y}^{(i)}})\log (1-{{a}^{(i)}}) J(w,b)=L(a(i),y(i))=−y(i)loga(i)−(1−y(i))log(1−a(i))
![](https://i-blog.csdnimg.cn/blog_migrate/268e883631562a2fef04d6d7a0454d2c.jpeg)
下面计算代价函数 L ( a , y ) L(a,y) L(a,y)的导数
d L ( a ( i ) , y ( i ) ) d a ( i ) = − y ( i ) / a ( i ) + ( 1 − y ( i ) ) / ( 1 − a ( i ) ) \frac{dL(a^{(i)},y^{(i)})}{da^{(i)}}=-y^{(i)}/a^{(i)}+(1-y^{(i)})/(1-a^{(i)}) da(i)dL(a(i),y(i))=−y(i)/a(i)+(1−y(i))/(1−a(i))
d L d z ( i ) = a ( i ) − y ( i ) \frac{dL}{dz^{(i)}}=a^{(i)}-y^{(i)} dz(i)dL=a(i)−y(i) ,由链式法则及 d a ( i ) d z ( i ) = a ( i ) ⋅ ( 1 − a ( i ) ) \frac{da^{(i)}}{dz^{(i)}}=a^{(i)}\cdot (1-a^{(i)}) dz(i)da(i)=a(i)⋅(1−a(i))导出
∂ L ∂ w = x ( i ) ( a ( i ) − y ( i ) ) = x ( i ) d L d z ( i ) \frac{\partial L}{\partial {{w}}}=x^{(i)}(a^{(i)}-y^{(i)})=x^{(i)}\frac{dL}{dz^{(i)}} ∂w∂L=x(i)(a(i)−y(i))=x(i)dz(i)dL
∂ L ∂ b = a ( i ) − y ( i ) \frac{\partial L}{\partial {b}}={a^{(i)}-y^{(i)}} ∂b∂L=a(i)−y(i)
然后更新模型参数
w : = w − α ∂ J ( w , b ) ∂ w w:=w-\alpha \frac{\partial J(w,b)}{\partial w} w:=w−α∂w∂J(w,b), b : = b − α ∂ J ( w , b ) ∂ b b:=b-\alpha\frac{\partial J(w,b)}{\partial b} b:=b−α∂b∂J(w,b), α \alpha α为学习率
之后用新的参数继续训练
m 个样本的梯度下降
代价函数: J ( w , b ) = 1 m ∑ i = 1 m L ( a ( i ) , y ( i ) ) J(w,b)=\frac{1}{m}\sum\limits_{i=1}^{m}{L({{a}^{(i)}},{{y}^{(i)}})} J(w,b)=m1i=1∑mL(a(i),y(i))
∂ L ∂ w = 1 m ∑ i m x ( i ) d L d z ( i ) \frac{\partial L}{\partial {{w}}}=\frac{1}{m}\sum\nolimits_{i}^{m}x^{(i)}\frac{dL}{dz^{(i)}} ∂w∂L=m1∑imx(i)dz(i)dL
∂ L ∂ b = 1 m ∑ i m d L d z ( i ) \frac{\partial L}{\partial {b}}=\frac{1}{m}\sum\nolimits_{i}^{m}\frac{dL}{dz^{(i)}} ∂b∂L=m1∑imdz(i)dL
向量化表示如下,对于m个样本,dw和db应当对每个样本求平均,而 d a ( i ) da^{(i)} da(i)和 d z ( i ) dz^{(i)} dz(i)和样本一对一, d A = [ d a ( 1 ) , d a ( 2 ) , . . . , d a ( m ) ] dA=[da^{(1)},da^{(2)},...,da^{(m)}] dA=[da(1),da(2),...,da(m)], d Z = [ d z ( 1 ) , d z ( 2 ) , . . . , d z ( m ) ] dZ=[dz^{(1)},dz^{(2)},...,dz^{(m)}] dZ=[dz(1),dz(2),...,dz(m)],因此 d A dA dA和 d Z dZ dZ不用除m
d A = − Y / A + ( 1 − Y ) / ( 1 − A ) dA=-Y/A+(1-Y)/(1-A) dA=−Y/A+(1−Y)/(1−A)
d Z = A − Y dZ=A-Y dZ=A−Y
d w = 1 m ⋅ d Z ⋅ X T dw=\frac{1}{m}\cdot dZ\cdot X^T dw=m1⋅dZ⋅XT
d b = 1 m ⋅ n p . s u m ( d Z ) db=\frac{1}{m}\cdot np.sum(dZ) db=m1⋅np.sum(dZ)
然后更新模型参数
w : = w − α d w w:=w-\alpha dw w:=w−αdw, b : = b − α d b b:=b-\alpha db b:=b−αdb
1.2浅层神经网络(Shallow neural networks)
1.2.1 神经网络的表示(Neural Network Representation)
![](https://i-blog.csdnimg.cn/blog_migrate/423a3e4a48064a71449d77a3b44af757.png)
上图中有输入特征
x
1
x_1
x1、
x
2
x_2
x2、
x
3
x_3
x3,它们被竖直地堆叠起来,叫做神经网络的输入层。
a
a
a表示激活的意思,意味着网络中不同层的值会传递到它们后面的层中。可以统一将输入层记为
a
[
0
]
a^{[0]}
a[0]
a
[
0
]
=
[
a
1
[
0
]
a
2
[
0
]
a
3
[
0
]
]
a^{[0]} = \left[ \begin{array}{ccc} a^{[0]}_{1}\\ a^{[0]}_{2}\\ a^{[0]}_{3} \end{array} \right]
a[0]=⎣
⎡a1[0]a2[0]a3[0]⎦
⎤
下一层是隐藏层,激活值记为
a
[
1
]
=
[
a
1
[
1
]
a
2
[
1
]
a
3
[
1
]
a
4
[
1
]
]
a^{[1]} = \left[ \begin{array}{ccc} a^{[1]}_{1}\\ a^{[1]}_{2}\\ a^{[1]}_{3}\\ a^{[1]}_{4} \end{array} \right]
a[1]=⎣
⎡a1[1]a2[1]a3[1]a4[1]⎦
⎤
最后只有一个结点的层被称为输出层,负责产生预测值,取为
a
[
2
]
a^{[2]}
a[2]。在神经网络中,使用上标指出这些值来自于哪一层
在计算网络的层数时,输入层不算入总层数内,上图为两层的神经网络
各层也有与之相关联的参数。
a
[
0
]
W
[
1
]
b
[
1
]
}
⟹
z
[
1
]
=
W
[
1
]
x
+
b
[
1
]
⟹
a
[
1
]
=
σ
(
z
[
1
]
)
\left. \begin{array}{r} {a^{[0]}}\\ {W^{[1]}}\\ {b^{[1]}} \end{array} \right\} \implies{z^{[1]}=W^{[1]}x+b^{[1]}} \implies{a^{[1]} = \sigma(z^{[1]})}
a[0]W[1]b[1]⎭
⎬
⎫⟹z[1]=W[1]x+b[1]⟹a[1]=σ(z[1])
a [ 1 ] = σ ( z [ 1 ] ) W [ 2 ] b [ 2 ] } ⟹ z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] ⟹ a [ 2 ] = σ ( z [ 2 ] ) ⟹ L ( a [ 2 ] , y ) \left. \begin{array}{r} \text{$a^{[1]} = \sigma(z^{[1]})$}\\ \text{$W^{[2]}$}\\ \text{$b^{[2]}$}\\ \end{array} \right\} \implies{z^{[2]}=W^{[2]}a^{[1]}+b^{[2]}} \implies{a^{[2]} = \sigma(z^{[2]})}\\ \implies{{L}\left(a^{[2]},y \right)} a[1]=σ(z[1])W[2]b[2]⎭ ⎬ ⎫⟹z[2]=W[2]a[1]+b[2]⟹a[2]=σ(z[2])⟹L(a[2],y)
1.2.2 计算一个神经网络的输出
神经网络中每个神经元内部类似于一个逻辑回归的计算
因此隐藏层的计算如下:
z 1 [ 1 ] = w 1 [ 1 ] T x + b 1 [ 1 ] , a 1 [ 1 ] = σ ( z 1 [ 1 ] ) z^{[1]}_1 = w^{[1]T}_1x + b^{[1]}_1, a^{[1]}_1 = \sigma(z^{[1]}_1) z1[1]=w1[1]Tx+b1[1],a1[1]=σ(z1[1])
z 2 [ 1 ] = w 2 [ 1 ] T x + b 2 [ 1 ] , a 2 [ 1 ] = σ ( z 2 [ 1 ] ) z^{[1]}_2 = w^{[1]T}_2x + b^{[1]}_2, a^{[1]}_2 = \sigma(z^{[1]}_2) z2[1]=w2[1]Tx+b2[1],a2[1]=σ(z2[1])
z 3 [ 1 ] = w 3 [ 1 ] T x + b 3 [ 1 ] , a 3 [ 1 ] = σ ( z 3 [ 1 ] ) z^{[1]}_3 = w^{[1]T}_3x + b^{[1]}_3, a^{[1]}_3 = \sigma(z^{[1]}_3) z3[1]=w3[1]Tx+b3[1],a3[1]=σ(z3[1])
z 4 [ 1 ] = w 4 [ 1 ] T x + b 4 [ 1 ] , a 4 [ 1 ] = σ ( z 4 [ 1 ] ) z^{[1]}_4 = w^{[1]T}_4x + b^{[1]}_4, a^{[1]}_4 = \sigma(z^{[1]}_4) z4[1]=w4[1]Tx+b4[1],a4[1]=σ(z4[1])
如果通过向量化将神经网络中的一层神经元参数纵向堆积起来,例如隐藏层中的 w w w纵向堆积起来变成一个 ( 4 , 3 ) (4,3) (4,3)的矩阵,用符号 W [ 1 ] W^{[1]} W[1]表示。则可以表示为
Z [ 1 ] = W [ 1 ] A [ 0 ] + B [ 1 ] , A [ 1 ] = σ ( Z [ 1 ] ) Z^{[1]} = W^{[1]}A^{[0]} + B^{[1]},A^{[1]}=\sigma(Z^{[1]}) Z[1]=W[1]A[0]+B[1],A[1]=σ(Z[1])
输出层的计算可以表达为相同的形式:
Z [ 2 ] = W [ 2 ] A [ 1 ] + B [ 2 ] , A [ 2 ] = σ ( Z [ 2 ] ) Z^{[2]} = W^{[2]}A^{[1]} + B^{[2]},A^{[2]}=\sigma(Z^{[2]}) Z[2]=W[2]A[1]+B[2],A[2]=σ(Z[2])
对于m个样本的计算,此时 A [ 0 ] A^{[0]} A[0].shape=(3,m), W [ 1 ] W^{[1]} W[1].shape=(4,3), Z [ 1 ] Z^{[1]} Z[1].shape=(4,m); A [ 2 ] A^{[2]} A[2].shape=(4,m), W [ 2 ] W^{[2]} W[2].shape=(1,4), Z [ 2 ] Z^{[2]} Z[2].shape=(1,m)。通过矩阵运算,此时m个预测值横向堆叠存储在 A [ 2 ] A^{[2]} A[2]中。
1.2.3 激活函数
使用一个神经网络时,需要决定使用哪种激活函数用隐藏层上,哪种用在输出节点上。有时不同的激活函数效果会更好
sigmoid函数:
- a = σ ( z ) = 1 1 + e − z a = \sigma(z) = \frac{1}{{1 + e}^{- z}} a=σ(z)=1+e−z1
tanh函数:
- a = t a n h ( z ) = e z − e − z e z + e − z a= tanh(z) = \frac{e^{z} - e^{- z}}{e^{z} + e^{- z}} a=tanh(z)=ez+e−zez−e−z
- tanh函数是sigmoid的向下平移和伸缩后的结果。对它进行了变形后,穿过了 ( 0 , 0 ) (0,0) (0,0)点,并且值域介于+1和-1之间。实验表明在隐藏层上使用tanh函数效果总是优于sigmoid函数。因为其函数值域为(-1,1),均值更接近零,这会使下一层的学习简单一点。
- 例外是:在二分类的问题中,对于输出层,因为 y y y的值是0或1,所以想让 y ^ \hat{y} y^的数值介于0和1之间,而不是在-1和+1之间。需要使用sigmoid激活函数。
sigmoid函数和tanh函数两者共同的缺点是,在 z z z特别大或者特别小的情况下,导数的梯度或者函数的斜率会变得特别小,最后就会接近于0,导致降低梯度下降的速度。
修正线性单元函数ReLu:
- $ a =max( 0,z) $
- 采用ReLU 的神经元只需要进行加、乘和比较的操作,计算上更加高效.
- 相比于Sigmoid 型函数的两端饱和,ReLU 函数为左饱和函数,且在𝑥 > 0时导数为1,在一定程度上缓解了神经网络的梯度消失问题,加速梯度下降的收敛速度.
Leaky Relu函数
- a = m a x ( γ z , z ) , γ 为一较小值如 0.01 a = max( \gamma z,z),\gamma为一较小值如0.01 a=max(γz,z),γ为一较小值如0.01
- Relu进入负半区的时候,梯度为0,神经元此时不会训练,产生所谓的稀疏性,而Leaky ReLu不会有这问题
1.2.4 为什么需要非线性激活函数?
如果只用线性激活函数,那么神经网络只是把输入线性组合再输出。如:
(1) a [ 1 ] = z [ 1 ] = W [ 1 ] x + b [ 1 ] a^{[1]} = z^{[1]} = W^{[1]}x + b^{[1]} a[1]=z[1]=W[1]x+b[1]
(2) a [ 2 ] = z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] a^{[2]} = z^{[2]} = W^{[2]}a^{[1]}+ b^{[2]} a[2]=z[2]=W[2]a[1]+b[2]
(1)(2)式合并得
(3) $a^{[2]} = z^{[2]} = W{[2]}W{[1]}x + W{[2]}b{[1]} + b^{[2]} $
简化多项式得
$a^{[2]} = z^{[2]} = W^{‘}x + b^{’} $
对于深度网络,如果只使用线性激活函数那么无论神经网络有多少层,整体复杂度相当于只有一层,因此无法模拟比较复杂的函数。
1.2.5 激活函数的导数
sigmoid函数: g ( z ) ′ = d d z g ( z ) = a ( 1 − a ) g{{(z)}^{'}}=\frac{d}{dz}g(z)=a(1-a) g(z)′=dzdg(z)=a(1−a)
Tanh函数: d d z g ( z ) = 1 − a 2 \frac{d}{{d}z}g(z) = 1 - a^{2} dzdg(z)=1−a2
ReLU函数:
g
(
z
)
′
=
{
0
if z < 0
1
if z > 0
u
n
d
e
f
i
n
e
d
if z = 0
g(z)^{'}= \begin{cases} 0& \text{if z < 0}\\ 1& \text{if z > 0}\\ undefined& \text{if z = 0} \end{cases}
g(z)′=⎩
⎨
⎧01undefinedif z < 0if z > 0if z = 0
Leaky ReLU:
g
(
z
)
′
=
{
0.01
if z < 0
1
if z > 0
u
n
d
e
f
i
n
e
d
if z = 0
g(z)^{'}= \begin{cases} 0.01& \text{if z < 0}\\ 1& \text{if z > 0}\\ undefined& \text{if z = 0} \end{cases}
g(z)′=⎩
⎨
⎧0.011undefinedif z < 0if z > 0if z = 0
1.2.6 神经网络的梯度下降
以二分类问题为例,
Cost function:
J ( W [ 1 ] , b [ 1 ] , W [ 2 ] , b [ 2 ] ) = 1 m ∑ i = 1 m L ( y ^ , y ) J(W^{[1]},b^{[1]},W^{[2]},b^{[2]}) = {\frac{1}{m}}\sum_{i=1}^mL(\hat{y}, y) J(W[1],b[1],W[2],b[2])=m1∑i=1mL(y^,y)
forward propagation:
(1) z [ 1 ] = W [ 1 ] x + b [ 1 ] z^{[1]} = W^{[1]}x + b^{[1]} z[1]=W[1]x+b[1]
(2) a [ 1 ] = σ ( z [ 1 ] ) a^{[1]} = \sigma(z^{[1]}) a[1]=σ(z[1])
(3) z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] z^{[2]} = W^{[2]}a^{[1]} + b^{[2]} z[2]=W[2]a[1]+b[2]
(4) a [ 2 ] = g [ 2 ] ( z [ z ] ) = σ ( z [ 2 ] ) a^{[2]} = g^{[2]}(z^{[z]}) = \sigma(z^{[2]}) a[2]=g[2](z[z])=σ(z[2])
back propagation:
(1)$ dz^{[2]} = A^{[2]} - Y , Y = \begin{bmatrix}y^{[1]} & y^{[2]} & \cdots & y^{[m]}\ \end{bmatrix} $
(2)$ dW^{[2]} = {\frac{1}{m}}dz{[2]}A{[1]T} $
(3)$ {\rm d}b^{[2]} = {\frac{1}{m}}np.sum({d}z^{[2]},axis=1,keepdims=True)$
(4)$ dz^{[1]} = \underbrace{W^{[2]T}{\rm d}z{[2]}}_{dA{[1]}}\quad*\underbrace{{g{[1]}{(z{[1]})}}^{'}}_{activation ; function ; of ; hidden ; layer}$
(5) d W [ 1 ] = 1 m d z [ 1 ] x T dW^{[1]} = {\frac{1}{m}}dz^{[1]}x^{T} dW[1]=m1dz[1]xT
(6) d b [ 1 ] ⏟ ( n [ 1 ] , 1 ) = 1 m n p . s u m ( d z [ 1 ] , a x i s = 1 , k e e p d i m s = T r u e ) {\underbrace{db^{[1]}}_{(n^{[1]},1)}} = {\frac{1}{m}}np.sum(dz^{[1]},axis=1,keepdims=True) (n[1],1) db[1]=m1np.sum(dz[1],axis=1,keepdims=True)
1.2.7 随机初始化
对于一个神经网络,如果把权重w都初始化为0,那么梯度下降将不会起作用。
对于上图的神经网络,假设 W [ 1 ] , b [ 1 ] , W [ 2 ] , b [ 2 ] W^{[1]},b^{[1]},W^{[2]},b^{[2]} W[1],b[1],W[2],b[2]初始化为0,则 a 1 [ 1 ] a_{1}^{[1]} a1[1] 和 a 2 [ 1 ] a_{2}^{[1]} a2[1]相等,反向传播时,导致 dz 1 [ 1 ] \text{dz}_{1}^{[1]} dz1[1] 和 dz 2 [ 1 ] \text{dz}_{2}^{[1]} dz2[1]也会一样,那么这两个隐含单元就会完全一样,最终经过每次训练的迭代,这两个隐含单元仍然是同一个函数,这导致同一隐藏层所有神经元的输出都一致,因此在同一层放多个神经元变得没有意义。
所以必须随机的初始化神经网络参数的值,以打破这种对称性。
1.3 深层神经网络
1.3.1前向传播和反向传播(Forward and backward propagation)
对一个L层的神经网络(带输入层)
前向传播:
f o r l i n r a n g e ( 1 , L ) : for\quad l\quad in\quad range(1,L): forlinrange(1,L):
Z [ l ] = W [ l ] ⋅ A [ l − 1 ] + b [ l ] {Z}^{[l]}={W}^{[l]}\cdot {A}^{[l-1]}+{b}^{[l]} Z[l]=W[l]⋅A[l−1]+b[l]
A [ l ] = g [ l ] ( Z [ l ] ) {A}^{[l]}={g}^{[l]}({Z}^{[l]}) A[l]=g[l](Z[l])
输入上一层的激活值 A [ l − 1 ] {A}^{[l-1]} A[l−1],输出是 A [ l ] {A}^{[l]} A[l],需要为反向传播缓存: A [ l ] , Z [ l ] , W [ l ] , b [ l ] {A}^{[l]},{Z}^{[l]},{W}^{[l]},{b}^{[l]} A[l],Z[l],W[l],b[l];
反向传播:
f o r l i n r e v e r s e d ( r a n g e ( 1 , L ) ) : for\quad l\quad in\quad reversed(range(1,L)): forlinreversed(range(1,L)):
d Z [ l ] = d A [ l ] ∗ g [ l ] ′ ( Z [ l ] ) d{{Z}^{[l]}}=d{{A}^{[l]}}*{{g}^{\left[ l \right]}}'\left({{Z}^{[l]}} \right)~~ dZ[l]=dA[l]∗g[l]′(Z[l])
d W [ l ] = 1 m d Z [ l ] ⋅ A [ l − 1 ] T d{{W}^{[l]}}=\frac{1}{m}\text{}d{{Z}^{[l]}}\cdot {{A}^{\left[ l-1 \right]T}} dW[l]=m1dZ[l]⋅A[l−1]T
d b [ l ] = 1 m n p . s u m ( d z [ l ] , a x i s = 1 , k e e p d i m s = T r u e ) d{{b}^{[l]}}=\frac{1}{m}\text{ }np.sum(d{{z}^{[l]}},axis=1,keepdims=True) db[l]=m1 np.sum(dz[l],axis=1,keepdims=True)
d A [ l − 1 ] = W [ l ] T . d Z [ l ] d{{A}^{[l-1]}}={{W}^{\left[ l \right]T}}.d{{Z}^{[l]}} dA[l−1]=W[l]T.dZ[l]
1.3.2 为什么使用深层表示
深层的网络隐藏单元数量相对较少,隐藏层层数较多,如果浅层的网络想要达到同样的计算结果则需要指数级增长的单元数量才能达到。
以逻辑门为例,假设要对输入特征计算异或
x
1
X
O
R
x
2
X
O
R
x
3
X
O
R
…
…
x
n
x_{1}XOR x_{2} XOR x_{3} XOR ……x_{n}
x1XORx2XORx3XOR……xn,如果允许一个异或的树图,对应网络的深度是
O
(
l
o
g
(
n
)
)
O(log(n))
O(log(n)),那么节点的数量并不会很大。
但是如果不能使用多隐层的神经网络的话,那么要计算异或关系函数就需要这一隐层(上图右方框部分)的单元数呈指数增长才行。隐藏层单元数目为 O ( 2 n ) O(2^{n}) O(2n)。
二、改善深层神经网络:超参数调试、正则化以及优化
2.1 深度学习的实践层面
2.1.1 训练,验证,测试集(Train / Dev / Test sets)
对于小数据量(100,1000或者1万条数据),常见做法是70%训练集,30%测试集。如果设置了验证集,也可以按照60%训练集,20%验证集和20%测试集来划分。
对于百万级别数据量,验证集和测试集占数据总量的比例会趋向于变得更小。因为验证集的目的就是验证不同的算法,检验哪种算法更有效,因此,验证集只要足够大到能评估不同的算法,并迅速判断出哪种算法更有效。可能不需要拿出20%的数据作为验证集。同样地,根据最终选择的分类器,测试集的主要目的是正确评估分类器的性能。可以训练集占98%,验证集和测试集各占1%。对于数据量过百万的应用,训练集可以占到99.5%,验证和测试集各占0.25%,或者验证集占0.4%,测试集占0.1%。
确保验证集和测试集的数据来自同一分布
2.1.2 偏差,方差
欠拟合:偏差高,弱模型
过拟合:偏差低,方差高,强模型
2.1.3 机器学习基础
初始模型训练完成后,首先要知道算法的偏差,如果偏差较高,试着评估训练集或训练数据的性能。如果偏差的确很高,甚至无法拟合训练集,那么要做的就是选择一个新的网络,比如含有更多隐藏层或者隐藏单元的网络,或者花费更多时间来训练网络,或者尝试更先进的优化算法。
一旦偏差降低到可以接受的数值,检查方差有没有问题,为了评估方差,需要查看验证集性能,如果方差高,最好的解决办法就是采用更多数据,如果无法获得更多数据,也可以尝试通过正则化来减少过拟合
总之需要不断重复尝试,直到找到一个低偏差,低方差的模型
2.1.4 L2正则化(Regularization)
正则化是机器学习中一种常用的技术,其主要目的是控制模型复杂度,减小过拟合。最基本的正则化方法是在原目标(代价)函数 中添加惩罚项,对复杂度高的模型进行“惩罚”。
2.1.4.1 范数
范数(Norm)是一个表示向量“长度”的函数,常见的范数函数为L𝑝 范数,p=1,2,…∞
L p = ∑ 1 n x i p p , x = ( x 1 , x 2 , ⋯ , x n ) Lp=\sqrt[p]{\sum\limits_{1}^n x_i^p},x=(x_1,x_2,\cdots,x_n) Lp=p1∑nxip,x=(x1,x2,⋯,xn)
L-1范数:向量中所有元素的绝对值之和。可用于去除没有取值的信息,又称稀疏规则算子。
L-2范数:欧式距离。可用于优化正则化项,避免过拟合。
2.1.4.2 在神经网络中实现L2正则化
使用L2范数时,为方便后续处理,对L2范数进行平方。
在代价函数中添加正则项:
λ
2
m
∑
1
L
∣
∣
W
[
l
]
∣
∣
2
2
\frac{\lambda }{2m}{{\sum\nolimits_{1}^{L}{||{{W}^{[l]}}||_2}}^{2}}
2mλ∑1L∣∣W[l]∣∣22,
λ
\lambda
λ是正则化参数。
在backprop中
d W [ l ] = 1 m d Z [ l ] ⋅ A [ l − 1 ] T + λ m W [ l ] d{{W}^{[l]}}=\frac{1}{m}\text{}d{{Z}^{[l]}}\cdot {{A}^{\left[ l-1 \right]T}}+\frac{\lambda }{m}{{W}^{[l]}} dW[l]=m1dZ[l]⋅A[l−1]T+mλW[l]
更新参数时
W [ l ] = W [ l ] − d W [ l ] = 1 m d Z [ l ] ⋅ A [ l − 1 ] T + ( 1 − λ m ) W [ l ] {{W}^{[l]}}={{W}^{[l]}}-d{{W}^{[l]}}=\frac{1}{m}\text{}d{{Z}^{[l]}}\cdot {{A}^{\left[ l-1 \right]T}}+(1-\frac{\lambda }{m}){{W}^{[l]}} W[l]=W[l]−dW[l]=m1dZ[l]⋅A[l−1]T+(1−mλ)W[l]
该正则项说明,不论 W [ l ] W^{[l]} W[l]是什么,都试图让它变得更小,因此 L 2 L2 L2范数正则化也被称为“权重衰减”。
2.1.4.3 为什么L2正则化有利于预防过拟合
添加正则项可以避免数据权值矩阵过大
直观上理解如果正则化 λ \lambda λ设置得足够大,权重矩阵 W W W被设置为接近于0的值,就是把多隐藏单元的权重设为0,于是基本上消除了这些隐藏单元的影响。在这种情况,这个被大大简化了的神经网络会变成一个很小的网络,小到如同一个逻辑回归单元,可是深度却很大,它会使这个网络从过度拟合的状态更接近高偏差状态。
但是 λ \lambda λ会存在一个中间值,于是会有一个接近“Just Right”的中间状态。
从另一种角度看,假设用的是双曲线激活函数。
g ( z ) g(z) g(z)表示 t a n h ( z ) tanh(z) tanh(z),如果 z 非常小,就位于双曲正切函数的线性部分,而_z_如果变得更大或者更小,激活函数开始变得非线性。
如果 W W W很小,相对来说, z z z也会接近0。如果 z z z的值最终在图上圈中范围内,, g ( z ) g(z) g(z)大致呈线性,和线性回归函数一样,因此整个模型被简化了。
2.1.5 dropout 正则化
![](https://i-blog.csdnimg.cn/blog_migrate/2c7703ad5790eaa7872cde0d72ca607c.png)
对于图中的网络,dropout会遍历网络的每一层,并设置消除神经网络中节点的概率。假设网络中的每一层,每个节点得以保留和消除的概率都是0.5,设置完节点概率会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个节点更少,规模更小的网络,然后用backprop方法进行训练。
2.1.5.1 如何实施dropout?inverted dropout(反向随机失活)
对于一个四层网络,首先定义向量 d d d, d [ 3 ] d^{[3]} d[3]表示网络第三层的dropout向量:
d3 = np.random.rand(a3.shape[0],a3.shape[1])
设置该层的keep-prob,表示该层任一隐藏单元被保留的概率
d3 = d3<keep_prob
d
[
3
]
d^{[3]}
d[3]是一个布尔型数组,乘法运算依然有效,python会把true和false翻译为1和0
接下来要对 a [ 3 ] a^{[3]} a[3]进行随机失活操作,让 d [ 3 ] d^{[3]} d[3]中0元素对应的 a [ 3 ] a^{[3]} a[3]元素归零
a3=np.multiply(a3,d3)
最后还要用 a [ 3 ] a^{[3]} a[3]除以keep-prob参数,保证 z [ 4 ] z^{\lbrack4]} z[4]期望值不变
a3 = a3/keep_prob
2.1.5.2 dropout是怎样起作用的
直观上理解:dropout导致单个神经元不依赖于任何一个上一层神经元的输出,因为该神经元的输入可能随时被清除,因此该神经元不会给任何一个输入太多权重,因为它可能会被删除,所以该神经元会分配给其所有输入一点权重,通过传播所有权重,dropout将产生收缩权重的平方范数的效果,和 L 2 L2 L2正则化类似。实施dropout的结果是它会压缩权重,并完成一些预防过拟合的外层正则化。
实施dropout的另一个细节是,不同层的keep-prob也可以变化。如果某些层比其它层更容易发生过拟合,可以把keep-prob值设置得更低
dropout一大缺点就是代价函数 J J J不再被明确定义
2.1.6 其他正则化方法
-
数据扩增
假设需要拟合猫咪图片分类器,如果扩增数据代价高,可以通过水平翻转图片,随意裁剪图片,增大数据集,来额外生成假训练数据。
-
早停止early stopping
随着训练代数增加,验证集误差通常会先呈下降趋势,然后在某个节点处开始上升,early stopping的作用是提早停止训练神经网络,以得到一个偏差和方差都可以接受的模型。
2.1.7 归一化输入(Normalizing inputs)
训练神经网络,其中一个加速训练的方法就是归一化输入。归一化需要两个步骤:
-
零均值
μ = 1 m ∑ i = 1 m x ( i ) \mu = \frac{1}{m}\sum_{i =1}^{m}x^{(i)} μ=m1∑i=1mx(i)
x : = x − μ x:=x-\mu x:=x−μ
-
归一化方差
σ 2 = 1 m ∑ i = 1 m ( x ( i ) ) 2 \sigma^{2}= \frac{1}{m}\sum_{i =1}^{m}{({x^{(i)})}^{2}} σ2=m1∑i=1m(x(i))2
x / = σ x/=\sigma x/=σ
这样做的作用是:
代价函数: J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ ( i ) , y ( i ) ) J(w,b)=\frac{1}{m}\sum\limits_{i=1}^{m}{L({{{\hat{y}}}^{(i)}},{{y}^{(i)}})} J(w,b)=m1i=1∑mL(y^(i),y(i))
假设要训练模型
y
=
w
1
x
1
+
w
2
x
2
+
b
y=w_1x_1+w_2x_2+b
y=w1x1+w2x2+b,如果使用非归一化的输入特征,代价函数会像这样:
如果特征值在不同范围,假如 x 1 x_{1} x1取值范围从1到1000,特征 x 2 x_{2} x2的取值范围从0到1,结果是参数 w 1 w_{1} w1和 w 2 w_{2} w2值的范围或比率将会非常不同,上图数轴应为 w 1 w_{1} w1和 w 2 w_{2} w2,代价函数会是这样一个狭长的函数。
而如果归一化特征,代价函数平均起来看更对称,如果在非归一化的代价函数上运行梯度下降法,必须使用一个非常小的学习率。因为如果是在这个位置,梯度下降法可能需要多次迭代过程,直到最后找到最小值。但如果函数是一个更圆的球形轮廓,那么不论从哪个位置开始,梯度下降法都能够更直接地找到最小值,可以在梯度下降法中使用较大步长,而不需要像在左图中那样反复执行。
2.1.8 梯度消失/梯度爆炸(Vanishing / Exploding gradients)
两种情况下梯度消失经常出现,一是在深层网络中,二是采用了不合适的损失函数,比如sigmoid。梯度爆炸一般出现在深层网络和权值初始化值太大的情况下
对于一个四层的全连接网络
(1) d A [ l ] = W [ l + 1 ] T ⋅ d Z [ l + 1 ] d{{A}^{[l]}}={{W}^{\left[ l+1 \right]T}}\cdot d{{Z}^{[l+1]}} dA[l]=W[l+1]T⋅dZ[l+1]
(2) d Z [ l ] = d A [ l ] ∗ g [ l ] ′ ( Z [ l ] ) d{{Z}^{[l]}}=d{{A}^{[l]}}*{{g}^{\left[ l \right]}}'\left({{Z}^{[l]}} \right) dZ[l]=dA[l]∗g[l]′(Z[l])
(3) d W [ l ] = 1 m d Z [ l ] ⋅ A [ l − 1 ] T d{{W}^{[l]}}=\frac{1}{m}\text{}d{{Z}^{[l]}}\cdot {{A}^{\left[ l-1 \right]T}} dW[l]=m1dZ[l]⋅A[l−1]T
结合上面的公式可得:
d W [ l ] = 1 m W [ l + 1 ] T ⋅ d Z [ l + 1 ] ∗ g [ l ] ′ ( Z [ l ] ) ⋅ A [ l − 1 ] T d{{W}^{[l]}}=\frac{1}{m}{{W}^{\left[ l+1 \right]T}}\cdot d{{Z}^{[l+1]}}*{{g}^{\left[ l \right]}}'\left({{Z}^{[l]}} \right)~~\cdot {{A}^{\left[ l-1 \right]T}} dW[l]=m1W[l+1]T⋅dZ[l+1]∗g[l]′(Z[l]) ⋅A[l−1]T
如果再用公式(2)替换 d Z [ l + 1 ] d{{Z}^{[l+1]}} dZ[l+1],得到: d A [ l + 1 ] ∗ g [ l + 1 ] ′ ( Z [ l + 1 ] ) d{{A}^{[l+1]}}*{{g}^{\left[ l+1 \right]}}'\left({{Z}^{[l+1]}} \right) dA[l+1]∗g[l+1]′(Z[l+1])
d W [ l ] = 1 m W [ l + 1 ] T ⋅ d A [ l + 1 ] ∗ g [ l + 1 ] ′ ( Z [ l + 1 ] ) ∗ g [ l ] ′ ( Z [ l ] ) ⋅ A [ l − 1 ] T d{{W}^{[l]}}=\frac{1}{m}{{W}^{\left[ l+1 \right]T}}\cdot d{{A}^{[l+1]}}*{{g}^{\left[ l+1 \right]}}'\left({{Z}^{[l+1]}} \right)*{{g}^{\left[ l \right]}}'\left({{Z}^{[l]}} \right)\cdot {{A}^{\left[ l-1 \right]T}} dW[l]=m1W[l+1]T⋅dA[l+1]∗g[l+1]′(Z[l+1])∗g[l]′(Z[l])⋅A[l−1]T
最终对于 d W [ 1 ] d{{W}^{[1]}} dW[1],可以得到一串包含 g [ 4 ] ′ ( Z [ 4 ] ) ⋅ g [ 3 ] ′ ( Z [ 3 ] ) ⋅ g [ 2 ] ′ ( Z [ 2 ] ) ⋅ g [ 1 ] ′ ( Z [ 1 ] ) {{g}^{\left[ 4 \right]}}'\left({{Z}^{[4]}} \right)\cdot {{g}^{\left[ 3 \right]}}'\left({{Z}^{[3]}} \right)\cdot{{g}^{\left[ 2 \right]}}'\left({{Z}^{[2]}} \right)\cdot{{g}^{\left[ 1 \right]}}'\left({{Z}^{[1]}} \right) g[4]′(Z[4])⋅g[3]′(Z[3])⋅g[2]′(Z[2])⋅g[1]′(Z[1])的式子
如果激活函数使用的是sigmoid函数,其导数为 g ′ ( z ) = g ( z ) ( 1 − g ( z ) ) g′(z)=g(z)(1−g(z)) g′(z)=g(z)(1−g(z))
由于 g ( z ) ∈ ( 0 , 1 ) g(z)\in(0,1) g(z)∈(0,1),两个0到1之间的数相乘,得到的结果 g ′ ( z ) g′(z) g′(z)就会变得更小。因此当神经网络层数非常深的时候,最后一层产生的梯度因为乘了很多的小于1的数而越来越小,接近0,从而导致层数比较浅的权重没有更新,这就是梯度消失。
如果使用其它激活函数,而且初始化权值过大,浅层的权值梯度有更多的 g [ l ] ′ ( Z [ l ] ) {{g}^{\left[l\right]}}'\left({{Z}^{[l]}} \right) g[l]′(Z[l])累乘,反向传播的梯度将以指数形式增加,发生梯度爆炸。导致模型权重更新幅度过大,会造成模型不稳定,无法有效学习,还会出现无法再更新的 NaN 权重值。
2.1.9 神经网络的权重初始化(Weight Initialization for Deep NetworksVanishing / Exploding gradients)
对于只有一个神经元的情况,假设单个神经元有4个输入特征,从 x 1 x_{1} x1到 x 4 x_{4} x4,经过 a = g ( z ) a=g(z) a=g(z),最终得到 y ^ \hat{y} y^, z = w 1 x 1 + w 2 x 2 + … + w n x n z = w_{1}x_{1} + w_{2}x_{2} + \ldots +w_{n}x_{n} z=w1x1+w2x2+…+wnxn, b = 0 b=0 b=0,为了预防 z z z值过大或过小, n n n越大,希望 w i w_{i} wi越小,因为 z z z是 w i x i w_{i}x_{i} wixi的和,如果把很多此类项相加,希望每项值更小,最合理的方法就是设置 w i = 1 n w_{i}=\frac{1}{n} wi=n1, n n n表示神经元的输入特征数量
w [ l ] = n p . r a n d o m . r a n d n ( shape ) ∗ np.sqrt ( 1 n [ l − 1 ] ) w^{[l]} = np.random.randn( \text{shape})*\text{np.}\text{sqrt}(\frac{1}{n^{[l-1]}}) w[l]=np.random.randn(shape)∗np.sqrt(n[l−1]1), n [ l − 1 ] n^{[l - 1]} n[l−1]是第 l − 1 l-1 l−1层神经元数量
对于Relu激活函数,方差设置为 2 n \frac{2}{n} n2,效果会更好
一篇由Herd等人撰写的论文曾介绍过, 1 n [ l − 1 ] \sqrt{\frac{1}{n^{[l-1]}}} n[l−1]1适用于tanh激活函数,被称为Xavier初始化。Yoshua Bengio和他的同事还提出另一种方法,使用的是公式 2 n [ l − 1 ] + n [ l ] \sqrt{\frac{2}{n^{[l-1]} + n^{\left[l\right]}}} n[l−1]+n[l]2。
2.1.10 梯度检验
在实施backprop时,有一个测试叫做梯度检验,它的作用是确保梯度公式是正确的。
可以使用双边误差来验证函数 f f f的偏导是否正确,即 f ′ ( θ ) − f ( θ + ε ) − f ( θ − ε ) 2 ε < λ f^{'}(\theta) - \operatorname{}\frac{f( \theta + \varepsilon) -f(\theta -\varepsilon)}{2\varepsilon}<\lambda f′(θ)−2εf(θ+ε)−f(θ−ε)<λ
假设网络中含有下列参数, W [ 1 ] W^{[1]} W[1]和 b [ 1 ] b^{[1]} b[1]…… W [ l ] W^{[l]} W[l]和 b [ l ] b^{[l]} b[l],首先把所有参数转换成一个巨大的向量 θ \theta θ,该向量表示为参数 θ \theta θ,现在得到了一个 θ \theta θ的代价函数 J J J(即 J ( θ ) J(\theta) J(θ))。接着同样把 d W [ 1 ] dW^{[1]} dW[1]和 d b [ 1 ] {db}^{[1]} db[1]…… d W [ l ] {dW}^{[l]} dW[l]和 d b [ l ] {db}^{[l]} db[l]转换成一个新的向量 d θ d\theta dθ
将J函数展开为 J ( θ 1 , θ 2 , θ 3 , … … ) J(\theta_{1},\theta_{2},\theta_{3},\ldots\ldots) J(θ1,θ2,θ3,……),循环执行对每个 θ i \theta_{i} θi计算 d θ approx [ i ] d\theta_{\text{approx}}[i] dθapprox[i]的值,使用双边误差 d θ approx [ i ] = J ( θ 1 , θ 2 , … θ i + ε , … ) − J ( θ 1 , θ 2 , … θ i − ε , … ) 2 ε d\theta_{\text{approx}}\left[i \right] = \frac{J\left( \theta_{1},\theta_{2},\ldots\theta_{i} + \varepsilon,\ldots \right) - J\left( \theta_{1},\theta_{2},\ldots\theta_{i} - \varepsilon,\ldots \right)}{2\varepsilon} dθapprox[i]=2εJ(θ1,θ2,…θi+ε,…)−J(θ1,θ2,…θi−ε,…)
使用 ε = ∣ ∣ d θ approx − d θ ∣ ∣ 2 ∣ ∣ d θ approx ∣ ∣ 2 + ∣ ∣ d θ ∣ ∣ 2 \varepsilon=\frac{{||d\theta_{\text{approx}} -d\theta||}_{2}}{{||d\theta_{\text{approx}}||}_{2}+{||d\theta||}_{2}} ε=∣∣dθapprox∣∣2+∣∣dθ∣∣2∣∣dθapprox−dθ∣∣2衡量2个向量的接近程度。如果 ε \varepsilon ε为 1 0 − 7 10^{-7} 10−7或更小就意味着导数逼近很有可能是正确的
梯度检验应用的注意事项:
- 不要在训练中使用梯度检验,它只用于调试。算所有 i i i值的 d θ approx [ i ] d\theta_{\text{approx}}\left[i\right] dθapprox[i]是一个非常漫长的计算过程
- 梯度检验不能与dropout同时使用
2.2优化算法 (Optimization algorithms)
2.2.1 Mini-batch 梯度下降(Mini-batch gradient descent)
如果样本数量很大,对整个训练集执行梯度下降法处理速度会很慢。可以把训练集分割为小的子集mini-batch训练,引入大括号来代表不同的mini-batch,所以有 X { t } X^{\{ t\}} X{t}和 Y { t } Y^{\{ t\}} Y{t},这样在执行中一次只对一个mini-batch进行处理
如果训练集分成了5000个mini-batch,使用batch梯度下降法,一次遍历训练集只能做一个梯度下降,使用mini-batch梯度下降法,一次遍历训练集,能做5000个梯度下降。
使用batch梯度下降法时,每次迭代都需要历遍整个训练集,几乎每次迭代成本都会下降,如果 J J J在某次迭代中增加了,可能是因为学习率太大。
使用mini-batch梯度下降法,则并不是每次迭代都是下降的。在每次迭代中,成本函数 J { t } J^{\{t\}} J{t}只和 X { t } X^{\{ t\}} X{t}, Y { t } Y^{\{t\}} Y{t}有关,也就是每次迭代下都在训练不同的样本集,成本函数 J J J的图很可能会看到这样的结果:走向朝下,但有更多的噪声。
需要决定的变量之一是mini-batch的大小m,如果mini-batch的大小等于 m m m,就是batch梯度下降法,假设mini-batch大小为1,就叫做随机梯度下降法
一般的mini-batch大小为64到512,取决于应用方向以及训练集的大小,mini-batch大小一般是2的 n n n次方。
2.2.2 指数加权平均数
以温度为例,有n日的温度 θ t , t = 1... n {{\theta }_{t}},t=1...n θt,t=1...n,求每日温度的指数加权平均值 v t {{v}_{t}} vt
v t = β v t − 1 + ( 1 − β ) θ t , v 0 = 0 {{v}_{t}}=\beta {{v}_{t-1}}+(1-\beta ){{\theta }_{t}},{{v}_{0}}=0 vt=βvt−1+(1−β)θt,v0=0
该公式可以写成
v t = ( 1 − β ) θ t + ( 1 − β ) β θ t − 1 + ( 1 − β ) β 2 θ t − 2 + . . . + ( 1 − β ) β n − 1 θ 1 {{v}_{t}}=(1-\beta ){{\theta }_{t}}+(1-\beta )\beta {{\theta }_{t-1}}+(1-\beta )\beta^{2} {{\theta }_{t-2}}+...+(1-\beta )\beta^{n-1} {{\theta }_{1}} vt=(1−β)θt+(1−β)βθt−1+(1−β)β2θt−2+...+(1−β)βn−1θ1
其实就是将每日温度与指数衰减函数相乘,求和
( 1 − ε ) ( 1 ε ) {(1-\varepsilon)}^{(\frac{1}{\varepsilon})} (1−ε)(ε1)约等于 1 e \frac{1}{e} e1,大约是0.34,权重小于 ( 1 − ε ) ( 1 ε ) {(1-\varepsilon)}^{(\frac{1}{\varepsilon})} (1−ε)(ε1)的温度影响比较小,用 ε \varepsilon ε代替 1 − β 1-\beta 1−β,因此可以将 v t {{v}_{t}} vt看作是平均了大约 1 ( 1 − β ) \frac{1}{(1-\beta)} (1−β)1天的温度
β \beta β设得高则移动平均值曲线更平滑
β \beta β设得低则曲线能够更快适应变化。
指数加权平均的偏差修正:
因为在计算移动平均的时候,初始化 v 0 = 0 v_{0} = 0 v0=0,所以 v 1 = 0.02 θ 1 v_{1} =0.02\theta_{1} v1=0.02θ1,前几天的温度会小很多。
因此需要使用 v t 1 − β t \frac{v_{t}}{1- \beta^{t}} 1−βtvt代替 v t v_{t} vt作为指数加权平均的修正值
2.2.3 动量梯度下降法(Gradient descent with Momentum)
动量梯度下降法(Momentum),运行速度几乎总是快于标准的梯度下降算法.简该算法的基本思想是计算梯度的指数加权平均数,并利用该梯度更新权重
假设成本函数的形状如图,红点代表最小值的位置,假设从蓝色点开始梯度下降,如果进行梯度下降法的一次迭代,无论是batch或mini-batch下降法,可能会出现上下波动,减慢了梯度下降法的速度。并且无法使用更大的学习率,否则可能会无法收敛。
从另一个角度讲,在纵轴上,希望学习慢一点,从而去除这些摆动,但是在横轴上,希望加快学习,最好能快速从左向右移,移向最小值,移向红点。
所以使用动量梯度下降法,需要在第 t t t次迭代的过程中,计算 d W dW dW, d b db db。然后计算 v d W = β v d W + ( 1 − β ) d W v_{{dW}}= \beta v_{{dW}} + \left( 1 - \beta \right)dW vdW=βvdW+(1−β)dW,即 d W dW dW的移动平均数,接着同样地计算 v d b v_{db} vdb, v d b = β v d b + ( 1 − β ) d b v_{db} = \beta v_{{db}} + ( 1 - \beta){db} vdb=βvdb+(1−β)db,然后重新赋值权重, W : = W − a v d W W:= W -av_{{dW}} W:=W−avdW, b : = b − a v d b b:= b - a v_{db} b:=b−avdb,这样就可以减缓梯度下降的幅度。
通过指数加权平均,纵向的分量基本可以抵消,原因是锯齿状存在一上一下的配对向量,方向基本反向。
2.2.4 RMSprop算法
RMSprop算法,全称是root mean square prop算法,也可以加速梯度下降
在之前的例子中,执行梯度下降,纵轴方向会有大幅度摆动
所以,需要减缓纵轴方向b的学习,同时加快横轴方向w的学习,RMSprop算法可以实现这一点。
在第 t t t次迭代中,该算法会计算当下mini-batch的微分 d W dW dW, d b db db,并且用到新符号 S d W S_{dW} SdW,而不是 v d W v_{dW} vdW
S d W = β S d W + ( 1 − β ) ( d W ) 2 S_{dW}= \beta S_{dW} + (1 -\beta)({dW})^{2} SdW=βSdW+(1−β)(dW)2, S d b = β S d b + ( 1 − β ) ( d b ) 2 S_{db}= \beta S_{db} + (1 - \beta)({db})^{2} Sdb=βSdb+(1−β)(db)2
接着RMSprop会这样更新参数值, W : = W − a d W S d W W:= W -a\frac{dW}{\sqrt{S_{dW}}} W:=W−aSdWdW, b : = b − α d b S d b b:=b -\alpha\frac{db}{\sqrt{S_{db}}} b:=b−αSdbdb
其原理是:因为需要减缓纵轴方向b的学习,同时加快横轴方向w的学习,即希望 S d W S_{dW} SdW会相对较小,所以要除以一个较小的数,而希望 S d b S_{db} Sdb又较大,这里要除以较大的数字,这样就可以减缓纵轴上的变化。又因为斜率在 b b b方向特别大,所以 d b db db较大, d W dW dW较小,所以 S d b S_{db} Sdb也会较大,而相比之下, d W dW dW会小一些,因此 S d W S_{dW} SdW会小一些,结果就是纵轴上的更新要被一个较大的数相除,就能消除摆动,而水平方向的更新则被较小的数相除。
2.2.5 Adam 优化算法(Adam optimization algorithm)
Adam优化算法基本是将Momentum和RMSprop结合在一起
-
首先要初始化, v d W = 0 v_{dW} = 0 vdW=0, S d W = 0 S_{dW} =0 SdW=0, v d b = 0 v_{db} = 0 vdb=0, S d b = 0 S_{db} =0 Sdb=0
-
在第 t t t次迭代中,用当前的mini-batch计算 d W dW dW, d b db db
-
接下来计算Momentum指数加权平均数, v d W = β 1 v d W + ( 1 − β 1 ) d W v_{dW}= \beta_{1}v_{dW} + ( 1 - \beta_{1})dW vdW=β1vdW+(1−β1)dW, v d b = β 1 v d b + ( 1 − β 1 ) d b v_{db}= \beta_{1}v_{db} + ( 1 -\beta_{1} ){db} vdb=β1vdb+(1−β1)db。
-
接着用RMSprop进行更新, S d W = β 2 S d W + ( 1 − β 2 ) ( d W ) 2 S_{dW}=\beta_{2}S_{dW} + ( 1 - \beta_{2}){(dW)}^{2} SdW=β2SdW+(1−β2)(dW)2, S d b = β 2 S d b + ( 1 − β 2 ) ( d b ) 2 S_{db} =\beta_{2}S_{db} + \left( 1 - \beta_{2} \right){(db)}^{2} Sdb=β2Sdb+(1−β2)(db)2。
-
计算偏差修正 v d W corrected = v d W 1 − β 1 t v_{dW}^{\text{corrected}}= \frac{v_{dW}}{1 - \beta_{1}^{t}} vdWcorrected=1−β1tvdW, v d b corrected = v d b 1 − β 1 t v_{db}^{\text{corrected}} =\frac{v_{db}}{1 -\beta_{1}^{t}} vdbcorrected=1−β1tvdb
-
S S S也使用偏差修正 S d W corrected = S d W 1 − β 2 t S_{dW}^{\text{corrected}} =\frac{S_{dW}}{1 - \beta_{2}^{t}} SdWcorrected=1−β2tSdW, S d b corrected = S d b 1 − β 2 t S_{db}^{\text{corrected}} =\frac{S_{db}}{1 - \beta_{2}^{t}} Sdbcorrected=1−β2tSdb
-
最后更新权重,
W : = W − a v d W corrected S d W corrected + ε W:= W - \frac{a v_{dW}^{\text{corrected}}}{\sqrt{S_{dW}^{\text{corrected}}} +\varepsilon} W:=W−SdWcorrected+εavdWcorrected
b : = b − α v db corrected S db corrected + ε b:=b - \frac{\alpha v_{\text{db}}^{\text{corrected}}}{\sqrt{S_{\text{db}}^{\text{corrected}}} +\varepsilon} b:=b−Sdbcorrected+εαvdbcorrected 为避免除0添加了微小量 ε \varepsilon ε
Adam是一种极其常用的学习算法,被证明能有效适用于不同神经网络,适用于广泛的结构。
本算法中有很多超参数,超参数学习率 a a a很重要,也经常需要调试,可以尝试一系列值,然后看哪个有效。 β 1 \beta_{1} β1常用的缺省值为0.9。 β 2 \beta_{2} β2推荐使用0.999, ε \varepsilon ε的选择没那么重要,Adam论文的作者建议 ε \varepsilon ε为 1 0 − 8 10^{-8} 10−8
2.2.6 学习率衰减(Learning rate decay)
从经验上看,学习率在一开始要保持大些来保证收敛速度,在收敛到最优
点附近时要小些以避免来回振荡.
比较简单的学习率调整可以通过学习率衰减(Learning Rate Decay)的方式来实现,也称为学习率退火(Learning Rate Annealing):
a = 1 1 + d e c a y r a t e ∗ epoch-num a 0 a= \frac{1}{1 + decayrate * \text{epoch}\text{-num}}a_{0} a=1+decayrate∗epoch-num1a0(decay-rate称为衰减率,是一个超参数,epoch-num为代数, α 0 \alpha_{0} α0为初始学习率)
指数衰减:
a = β epoch-num a 0 a ={\beta}^{\text{epoch-num}} a_{0} a=βepoch-numa0(其中 β \beta β为衰减率)
2.2.7 局部最优的问题
对于一个具有高维度空间的函数,如果梯度为0,那么在每个方向,可能是凸函数,也可能是凹函数。如果是2万维,想要得到局部最优,所有的2万个方向都需要是这样,因此发生的机率也许很小,也许是
2
−
20000
2^{-20000}
2−20000,更有可能遇到有些方向的曲线会这样向上弯曲,另一些方向曲线向下弯,而不是所有的都向上弯曲,因此在高维度空间,更可能碰到鞍点。
而平稳段是一个问题,其使得学习十分缓慢,这也是像Momentum或是RMSprop,Adam这样的算法,能够加速学习算法的地方。在这些情况下,更成熟的优化算法,如Adam算法,能够加快速度,尽早往下走出平稳段。
2.3 超参数调试、Batch归一化和Softmax
2.3.1 调试处理
神经网络的调整会涉及到许多不同超参数的设置。需要调试的重要超参数一般包括:学习率、Momentum或Adam优化算法的参数, β 1 \beta_{1} β1, β 2 {\beta}_{2} β2和 ε \varepsilon ε、mini-batch size、隐藏单元数量、层数、学习率衰减。
结果证实一些超参数比其它的更为重要,学习速率是需要调试的最重要的超参数。
超参值的搜索过程可以随机取值和精确搜索,考虑使用由粗糙到精细的搜索过程。
超参数搜索的过程
- 没有足够计算资源的前提下,只能一次试验一个模型,逐渐改良。
- 如果拥有足够的计算资源,平行试验大量模型
2.3.2 归一化网络的激活函数(Normalizing activations in a network)
在神经网络训练中,只是对输入层数据进行归一化处理,却没有在中间层进行归一化处理。虽然对输入数据进行了归一化处理,但是输入数据经过线性及非线性运算之后,其数据分布很可能被改变,而随着深度网络的多层运算之后,数据分布的变化将越来越大。如果能在网络的中间也进行归一化处理,可以对网络的训练起到改进作用。
这种在神经网络中间层也进行归一化处理,使训练效果更好的方法,就是批归一化Batch Normalization(BN)。BN在神经网络训练中会有以下一些作用:
- 加快训练速度
- 可以省去dropout,L1, L2等正则化处理方法
- 提高模型训练精度
为了提高优化效率,要使得
z
[
l
]
z^{[l]}
z[l]的分布一致,比如都归一化到标准
正态分布.虽然归一化操作也可以应用在输入
a
[
l
]
a^{[l]}
a[l] 上,但归一化𝒛(𝑙) 更加有利
于优化.因此,在实践中归一化操作一般应用在线性计算之后、激活函数之前
一般使用标准化将 z [ l ] z^{[l]} z[l]的每一维都归一到标准正态分布
z norm ( i ) = z ( i ) − μ σ 2 + ε z_{\text{norm}}^{(i)} = \frac{z^{(i)} -\mu}{\sqrt{\sigma^{2} +\varepsilon}} znorm(i)=σ2+εz(i)−μ
对
z
[
l
]
z^{[l]}
z[l]的标准归一化会使得其取值集中到0 附近,如果使用Sigmoid
型激活函数时,这个取值区间刚好是接近线性变换的区间,减弱了神经网络的非
线性性质.因此,为了使得归一化不对网络的表示能力造成负面影响,可以通过
一个附加的缩放和平移变换改变取值区间
z ~ ( i ) = γ z norm ( i ) + β {\tilde{z}}^{(i)}= \gamma z_{\text{norm}}^{(i)} +\beta z~(i)=γznorm(i)+β
这里 γ \gamma γ和 β \beta β是模型的学习参数,使用梯度下降更新 γ \gamma γ和 β \beta β
批量归一化操作可以看作一个特殊的神经层,加在每一层非线性激活函数
之前
2.3.3 Softmax 回归
Softmax回归用于多分类问题
在神经网络的最后一层,会像之前一样计算各层的线性部分, z [ L ] z^{[L]} z[L]是最后一层的 z z z变量
算出了 z z z之后,需要应用Softmax激活函数。首先计算临时变量 t = e z [ L ] t=e^{z^{[L]}} t=ez[L]即对所有元素求幂,然后对t归一化,输出 a [ l ] = e z [ l ] ∑ j = 1 4 t i a^{[l]} = \frac{e^{z^{[l]}}}{\sum_{j =1}^{4}t_{i}} a[l]=∑j=14tiez[l], a i [ l ] = t i ∑ j = 1 4 t i a_{i}^{[l]} = \frac{t_{i}}{\sum_{j =1}^{4}t_{i}} ai[l]=∑j=14titi,代表第i类别的概率
在Softmax分类中,一般用到的损失函数是 L ( y ^ , y ) = − ∑ j = 1 n y j l o g y ^ j L(\hat y,y ) = - \sum_{j = 1}^{n}{y_{j}log\hat y_{j}} L(y^,y)=−∑j=1nyjlogy^j
d z [ l ] = y ^ − y dz^{[l]} = \hat{y} -y dz[l]=y^−y