梯度下降及其弊端

深夜博客又开始熬鸡汤了,这次鸡汤熬的是梯度下降!
不废话了,直接主题

什么是梯度下降
有这么一个比喻,现在有一座山,而你处在山顶要以最快的速度走到山脚,在步长固定的情况下,每一次应该选择往最峭的方向走(也就是坡度最大)。
参数优化的过程类似于下山的过程,初始化权值(weights)Θ是有一串随机数组成的向量,毫无疑问这时候预测值与真实值的loss(误差)会比较大,就像是人在山顶上。我们的目的是逐渐减小loss直到cost function收敛到最优解(不代表一定是全局最优解,这和被优化函数有关),类比于到达山底!最峭的方向即是cost function梯度的方向,每一次迭代更新权值,直到函数收敛。
tips: 梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。
梯度下降表达式为:
θ i : = θ i − s ∗ d J ( Θ ) d θ i θ_i := θ_i - s*\frac{dJ(Θ)}{dθ_i} θi:=θisdθidJ(Θ)

什么时候用梯度下降
但已经有了cost function(损失函数)时,下一步即是优化参数使得损失函数越小越好,损失函数的结果(也就是误差loss)越小说明预测结果与真实值越接近,也就是模型准确度越高。
Example:
假设已经有hypothesis h Θ ( x ) h_Θ(x) hΘ(x):
h Θ ( x ) = θ 1 x 1 + θ 2 x 2 + … … + θ m x m h_Θ(x) = θ_1x_1 +θ_2x_2 + ……+θ_mx_m hΘ(x)=θ1x1+θ2x2++θmxm
cost function:
J ( Θ ) = 1 2 ∑ i = 1 # s a m p l e s ( h Θ ( x i ) − y i ) 2 J(Θ) =\frac {1} {2} \sum_{i = 1}^{\#samples}{ (h_Θ(x^i) - y^i)^2} J(Θ)=21i=1#samples(hΘ(xi)yi)2
其中“#samples”代表训练样本总数,“ y i y^i yi”代表第i个训练样本的真实标签,“ h Θ ( x i ) h_Θ(x^i) hΘ(xi)”代表第i个训练样本的预测值。
OK, 接下来就是梯度下降来优化Θ(Θ是一个向量,维度与特征维度相同)使得J(Θ)最小!
梯度下降算法有一个参数: 步长"α",用于设置每一次迭代的步长(也可以理解为一次迭代下降的程度)
Tips:
"α"是一个超参数(hyperparameters),需要在训练前按经验设置.吴恩达教授给出的建议是从0.001开始尝试,每次以3为公乘数等乘,也就是0.003,0.01,0.03,0.1……,直到模型训练效果达到要求!

梯度下降算法:
重复迭代直到收敛:
{
i 从1到m: (m是Θ的维度){
θ i = θ i − α ∗ d J ( Θ ) d θ i θ_i = θ_i - α*\frac{dJ(Θ)}{dθ_i} θi=θiαdθidJ(Θ)} //注意这里是 J ( Θ ) 对 θ i J(Θ)对θ_i J(Θ)θi求偏导
}
在这里就不具体展开数学计算了。以以上J(Θ)为例,迭代公式为:
θ i = θ i − α ∗ ∑ j = 1 # s a m p l e s [ ( h Θ ( x j ) − y j ) ∗ x i j ] θ_i = θ_i - α*\sum_{j = 1}^{\#samples}{[(h_Θ(x^j)-y^j)*x^j_i]} θi=θiαj=1#samples[(hΘ(xj)yj)xij]
不知道读到这里有没有注意到一个问题,好像还算是挺严重的哈哈。
每次在一次迭代中更新一个θ, 都得计算 ∑ j = 1 # s a m p l e s [ ( h Θ ( x j ) − y j ) ∗ x i j ] \sum_{j = 1}^{\#samples}{[(h_Θ(x^j)-y^j)*x^j_i]} j=1#samples[(hΘ(xj)yj)xij],当样本量成千上万时,计算量会变得巨大,因此会损耗更多的时间!
因此有了另一种梯度下降算法称为增量梯度下降(Incremental Gradient Descent),该算法也称为随机梯度下降(Stochastic Gradient Descent) let’s take a look!
Incremental Gradient Descent:
重复迭代直到收敛:
{
j从1 到 #sampes{
i 从1到m: (m是Θ的维度){
θ i = θ i − α ∗ [ h Θ ( x j ) − y j ] ∗ x i j θ_i = θ_i - α*[h_Θ(x^j) - y^j]*x^j_i θi=θiα[hΘ(xj)yj]xij
}
}
对比两个算法很清楚可以看出增量梯度下降每次只计算一个样本的梯度,极大减小了时间成本,且结果能够极度接近最小值!因此实际应用中增量(随机)梯度下降更受欢迎!

梯度下降存在的问题
1.不能保证收敛到全局最优解
上面提到了梯度下降并不能保证找到全局最优解(最小值),它只能找到局部最优解(极小值),所以优化结果的好坏还与被优化函数有很大的关系!如图所示:梯度下降及其弊端_第1张图片
有一种情况当被优化函数是“凸函数”时,则可以保证得到的时全局最优解,如图所示:梯度下降及其弊端_第2张图片

2.[以下两种情况出现在神经网络反向传播中,如果对神经网络不熟悉的盆友可以跳过哈哈]
1.梯度爆炸(exploding gradient)
2.梯度消失/梯度为0(vanishing gradient)
梯度爆炸与梯度消失实际上是同一种网络模型下参数不同的两种结果,因此我放在这里一起讨论:
假设现在有n层神经网络,每个隐藏层都有两个neuron(输出单元),激活函数a = z,即每个神经元的输入等于输出。最终的结果
y ^ = W [ n ] W [ n − 1 ] W [ n − 2 ] ∗ . . . . . . . ∗ W [ 2 ] W [ 1 ] X \hat{y}= W^{[n]}W^{[n-1]}W^{[n-2]}*.......*W^{[2]}W^{[1]}X y^=W[n]W[n1]W[n2].......W[2]W[1]X
当n非常大时,相对应的就是网络深度特别深时,会有两种特殊的情况发生:
方便理解假设每层的权重矩阵都相同, W [ i ] W^{[i]} W[i] =
(2) { t 0 0 t } \left\{ \begin{matrix} t & 0 \\ 0 & t \\ \end{matrix} \right\} \tag{2} {t00t}(2)
可以得出 y ^ = t n X \hat{y} =t^{n}X y^=tnX
.若 W [ i ] < I ( W^{[i]}<I( W[i]<I(单位矩阵),即t<1, 则 y ^ \hat{y} y^将以指数级减小,当n非常大时, y ^ \hat{y} y^会变得特别小(Vanishing).
相反,若 W [ i ] > I W^{[i]}>I W[i]>I时,即t>1,则 y ^ \hat{y} y^以指数级增大,也称做爆炸增长(exploding);
这两种特殊的情况都会使得更新权重变得及其困难,实际上通常是靠近输出层的权重的训练效果比靠经输入层的权重好得多,因为权重更新是反向传播,而每向前传播一层,输出值都会是上一层的指数级(以上假设为例),因此反向传播的时候每反向传播一层都要乘上该指数。
Example:仍是假设同一神经元输入等于输出: a c t i v a t i o n ( Z ) = Z activation(Z) = Z activation(Z)=Z;
∂ l o s s ∂ W [ i ] = ∂ l o s s ∂ Z [ n ] ∂ Z [ n ] ∂ Z [ n − 1 ] ∂ Z [ n − 1 ] ∂ Z [ n − 2 ] … … ∂ Z [ i + 1 ] ∂ W [ i ] \frac{\partial loss}{\partial W^{[i]}} = \frac{\partial loss}{\partial Z^{[n]}}\frac{\partial Z^{[n]}}{\partial Z^{[n-1]}}\frac{\partial Z^{[n-1]}}{\partial Z^{[n-2]}}……\frac{\partial Z^{[i+1]}}{\partial W^{[i]}} W[i]loss=Z[n]lossZ[n1]Z[n]Z[n2]Z[n1]W[i]Z[i+1]
Z [ j + 1 ] = Z [ i ] W Z^{[j+1]} = Z^{[i]}W Z[j+1]=Z[i]W
因此不难看出,当W变大是,越靠近输入端的权重更新会变得越来越大;当W变小时,越靠近输入端的权重更新会变得越来越小!

解决方法:

  1. 从初始化权重的角度:
    为了不让梯度爆炸或梯度消失,在对权重初始化时要及其小心,实际操作中,通常初始化权重 W [ i ] = W^{[i]}= W[i]=随机数*上一层节点数倒数的开方使得初始权值在单位矩阵 I I I附近。python语言即: W [ i ] = n p . r a n d o m . r a n d n ( s h a p e ) ∗ n p . s q r t ( 1 / n [ i − 1 ] ) W^{[i]}=np.random.randn(shape)*np.sqrt(1/n^{[i-1]}) W[i]=np.random.randn(shape)np.sqrt(1/n[i1])
  2. 从激活函数选择的角度:
    Simoid函数对机器学习的发展有重大的意义,但实验证明它并不适合层数大的神经网络,实际中,更多会选择ReLU,tanh或LeakyReLU!

你可能感兴趣的:(ML)