理解梯度首先要理解导数、偏导数、方向导数。
导数:
指的是一元函数 y = f ( x ) y = f(x) y=f(x) 在某一点处沿x轴正方向的变化率。若导数大于0,说明函数值在该点处沿x轴正方向是递增的,若导数小于0,说明函数值在该点处沿x轴正方向是递减的。
偏导数:
∂ ∂ x j f ( x 0 , x 1 , . . . , x n ) = lim Δ x j → 0 Δ y Δ x = lim Δ x j → 0 f ( x 0 , . . . x j + Δ x j , . . . x n ) − f ( x 0 , . . . x j , . . . x n ) Δ x j \frac{\partial }{{\partial {x_j}}}f({x_0},{x_1},...,{x_n}) = \mathop {\lim }\limits_{\Delta {x_j} \to 0} \frac{{\Delta y}}{{\Delta x}} = \mathop {\lim }\limits_{\Delta {x_j} \to 0} \frac{{f({x_0},...{x_j} + \Delta {x_j},...{x_n}) - f({x_0},...{x_j},...{x_n})}}{{\Delta {x_j}}} ∂xj∂f(x0,x1,...,xn)=Δxj→0limΔxΔy=Δxj→0limΔxjf(x0,...xj+Δxj,...xn)−f(x0,...xj,...xn)
偏导数指的是当某一自变量的变化量趋于0且其他自变量不变时,函数值的变化量与该自变量变化量比值的极限。偏导数就是多元函数 y = f ( x 0 , x 1 , . . . , x n ) y = f({x_0},{x_1},...,{x_n}) y=f(x0,x1,...,xn)在某一点处沿某一坐标轴 ( x 0 , x 1 , . . . , x n ) ({x_0},{x_1},...,{x_n}) (x0,x1,...,xn)正方向的变化率。
以二元函数为例,偏导数 f x ( x , y ) {f_x}(x,y) fx(x,y)指的是函数在y轴方向上不变,函数值沿着x轴方向的变化率, f y ( x , y ) {f_y}(x,y) fy(x,y)指的是函数在x轴方向上不变,函数值沿着y轴方向的变化率。
方向导数:
偏导数只描述了多元函数沿坐标轴方向的变化率,但多元函数除坐标轴外,还有很多个方向,想要得到函数在任意方向变化率,就需要用到方向导数。方向导数可衡量多元函数在任意方向的变化率,不管这个方向是不是坐标轴的方向。
梯度:
理解梯度要先理解神经网络的训练过程,简单来说,神经网络的训练过程是通过最小化损失函数来进行参数更新。神经网络训练的目的就是通过不断迭代,获得预测效果最好的参数(w和b),什么时候预测效果最好呢,当然就是预测值和真实值之间差异最小的时候效果最好啦,这个差异就是损失函数,那么训练的最终目的就是最小化这个损失函数。当损失函数最小时网络中的各参数就是预测效果最好的状态。
以常见的均方误差损失函数为例:
L ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 L(\theta ) = \frac{1}{{2m}}{\sum\limits_{i = 1}^m {({h_\theta }({x^{(i)}}) - {y^{(i)}})} ^2} L(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
可见损失函数是一个多元函数,要想最小化这个多元函数,就要找到其下降的方向让它不断减少直至最低点即可。多元函数有无数个方向,其下降方向也有很多,那自然是沿着其下降最快的方向不断接近最小值是最好的。那么哪个方向是其下降最快的方向呢,就是方向导数最大方向的反方向。
在XOY平面上有一点 p 0 ( a , b ) {p_0}(a,b) p0(a,b),L为以 P 0 {P_0} P0为起始点的一条射线, e ( cos θ , sin θ ) e(\cos \theta ,\sin \theta ) e(cosθ,sinθ)是与L同方向的单位向量(e就是上图中的u), θ \theta θ为x轴正向与射线L的夹角。在曲面z=f(x,y)上,从点 ( ( a , b ) , f ( a , b ) ) ((a,b),f(a,b)) ((a,b),f(a,b))出发,沿单位向量e的方向走t个单位长度后,函数值为 z = f ( a + t cos θ , b + t sin θ ) z = f(a + t\cos \theta ,b + t\sin \theta ) z=f(a+tcosθ,b+tsinθ)
f(x,y)在点 ( ( a , b ) , f ( a , b ) ) ((a,b),f(a,b)) ((a,b),f(a,b))处,L方向的方向导数为:
D = d f ( a + t cos θ , b + t sin θ ) d t ∣ t = 0 = lim t → 0 f ( a + t cos θ , b + t sin θ ) t = lim t → 0 f ( a + t cos θ , b + t sin θ ) − f ( a , b + t sin θ ) t + f ( a , b + t sin θ ) − f ( a , b ) t = ∂ f ( a , b ) ∂ t + ∂ f ( a , b ) ∂ t = ∂ f ( a , b ) ∂ x d x d t + ∂ f ( a , b ) ∂ y d y d t = f x ( a , b ) cos θ + f y ( a , b ) sin θ = ( f x ( a , b ) , f y ( a , b ) ) ( cos θ , sin θ ) = A E = ∣ A ∣ ∣ E ∣ cos φ \begin{array}{l} D = \frac{{df(a + t\cos \theta ,b + t\sin \theta )}}{{dt}}{|_{t = 0}} = \mathop {\lim }\limits_{t \to 0} \frac{{f(a + t\cos \theta ,b + t\sin \theta )}}{t}\\ = \mathop {\lim }\limits_{t \to 0} \frac{{f(a + t\cos \theta ,b + t\sin \theta ) - f(a,b + t\sin \theta )}}{t} + \frac{{f(a,b + t\sin \theta ) - f(a,b)}}{t}\\ = \frac{{\partial f(a,b)}}{{\partial t}} + \frac{{\partial f(a,b)}}{{\partial t}}\\ = \frac{{\partial f(a,b)}}{{\partial x}}\frac{{dx}}{{dt}} + \frac{{\partial f(a,b)}}{{\partial y}}\frac{{dy}}{{dt}}\\ = {f_x}(a,b)\cos \theta + {f_y}(a,b)\sin \theta \\ = ({f_x}(a,b),{f_y}(a,b))(\cos \theta ,\sin \theta )\\ = AE\\ = \left| A \right|\left| E \right|\cos \varphi \end{array} D=dtdf(a+tcosθ,b+tsinθ)∣t=0=t→0limtf(a+tcosθ,b+tsinθ)=t→0limtf(a+tcosθ,b+tsinθ)−f(a,b+tsinθ)+tf(a,b+tsinθ)−f(a,b)=∂t∂f(a,b)+∂t∂f(a,b)=∂x∂f(a,b)dtdx+∂y∂f(a,b)dtdy=fx(a,b)cosθ+fy(a,b)sinθ=(fx(a,b),fy(a,b))(cosθ,sinθ)=AE=∣A∣∣E∣cosφ
其中 f x ( a , b ) {f_x}(a,b) fx(a,b), f y ( a , b ) {f_y}(a,b) fy(a,b)分别是函数z=f(x,y)在点 ( ( a , b ) , f ( a , b ) ) ((a,b),f(a,b)) ((a,b),f(a,b))的偏导数。 φ \varphi φ是向量A 和向量E之间的夹角。
如果想要方向导数D达到最大,就必须使向量A和E的夹角为0度,那么函数值上升最快的方向就是向量A的方向。把向量A: ( f x ( a , b ) , f y ( a , b ) ) ({f_x}(a,b),{f_y}(a,b)) (fx(a,b),fy(a,b))定义成梯度,梯度的方向就是最大方向导数的方向,即函数在梯度方向具有最大的变化率,那么梯度的反方向就是函数减小最快的方向。梯度的大小就是函数最大方向导数的值。可见,梯度是函数各偏导数的组合。
根据上述推导可知,函数在变量空间的某一点处,沿梯度方向具有最大的变化率,那么在最小化目标函数时,沿着梯度相反的方向减小函数,更新参数。具体是怎么进行参数更新的呢?
举个例子:下图是一个简单的三层神经网络示意图,激活函数都是线性的,每次迭代使用一个样本计算梯度,那么参数更新的过程如下。
损失函数:
l o s s = L = 1 2 ( y − t ) 2 = 1 2 [ ( θ 1 f 1 ( x ) + θ 0 ) − t ] 2 = 1 2 [ ( θ 1 ( w 1 x + w 0 ) + θ 0 ) − t ] 2 \begin{array}{l} loss = L = \frac{1}{2}{(y - t)^2}\\ = \frac{1}{2}{\left[ {\left( {{\theta _1}{f_1}(x) + {\theta _0}} \right) - t} \right]^2}\\ = \frac{1}{2}{\left[ {\left( {{\theta _1}\left( {{w_1}x + {w_0}} \right) + {\theta _0}} \right) - t} \right]^2} \end{array} loss=L=21(y−t)2=21[(θ1f1(x)+θ0)−t]2=21[(θ1(w1x+w0)+θ0)−t]2
其中y是预测值,t是实际值。
损失函数的梯度为: g r a d = ( ∂ L ∂ θ 1 , ∂ L ∂ θ 0 , ∂ L ∂ W 1 , ∂ L ∂ W 0 ) grad = (\frac{{\partial L}}{{\partial {\theta _1}}},\frac{{\partial L}}{{\partial {\theta _0}}},\frac{{\partial L}}{{\partial {W_1}}},\frac{{\partial L}}{{\partial {W_0}}}) grad=(∂θ1∂L,∂θ0∂L,∂W1∂L,∂W0∂L)
更新隐藏层和输出层之间的网络参数 θ 1 , θ 0 {\theta _1},{\theta _0} θ1,θ0:
θ 1 n e w = θ 1 o l d − α ∂ L ∂ θ 1 \theta _1^{new} = \theta _1^{old} - \alpha \frac{{\partial L}}{{\partial {\theta _1}}} θ1new=θ1old−α∂θ1∂L
θ 0 n e w = θ 0 o l d − α ∂ L ∂ θ 0 \theta _0^{new} = \theta _0^{old} - \alpha \frac{{\partial L}}{{\partial {\theta _0}}} θ0new=θ0old−α∂θ0∂L
更新输入层和隐藏层之间的网络参数 w 1 , w 0 {w_1},{w_0} w1,w0,这里用到了导数的链式法则: w 1 n e w = w 1 o l d − α ∂ L ∂ w 1 = w 1 o l d − α ∂ L ∂ y ∂ y ∂ h ∂ h ∂ w 1 w 0 n e w = w 0 o l d − α ∂ L ∂ w 0 = w 0 o l d − α ∂ L ∂ y ∂ y ∂ h ∂ h ∂ w 0 \begin{array}{l} w_1^{new} = w_1^{old} - \alpha \frac{{\partial L}}{{\partial {w_1}}} = w_1^{old} - \alpha \frac{{\partial L}}{{\partial y}}\frac{{\partial y}}{{\partial h}}\frac{{\partial h}}{{\partial {w_1}}}\\ w_0^{new} = w_0^{old} - \alpha \frac{{\partial L}}{{\partial {w_0}}} = w_0^{old} - \alpha \frac{{\partial L}}{{\partial y}}\frac{{\partial y}}{{\partial h}}\frac{{\partial h}}{{\partial {w_0}}} \end{array} w1new=w1old−α∂w1∂L=w1old−α∂y∂L∂h∂y∂w1∂hw0new=w0old−α∂w0∂L=w0old−α∂y∂L∂h∂y∂w0∂h其中α步长,步长表示每一步沿梯度反方向前进的长度。
梯度下降分为三种:批量梯度下降(BGD),随机梯度下降(SGD),小批量梯度下降(miniBGD)
批量梯度下降(BGD): 每一次迭代时,使用训练集中全部样本来计算梯度,从而实现参数的更新。
这种方法的好处在于每次迭代都使用训练集中的全部样本计算梯度,这样所确定的梯度的方向更加准确,更容易使损失函数达到最小,不需要太多次迭代就会收敛。但是当训练集中样本数量很大时,用这种方式训练速度比较慢。
随机梯度下降(SGD): 每一次迭代时,使用训练集中一个样本来计算梯度,从而实现参数的更新。这种方式使每次迭代的速度加快,参数更新的速度加快,但是由于单个样本不能很好地代表样本整体的变化趋势,所以用一个样本计算的梯度不一定就是整体样本下降最快的方向。而且这种方法要达到收敛,迭代次数会很多,也不会像BGD收敛性能那么好。
小批量梯度下降: 是上面两种放式的折中,每次迭代时使用若干个样本,计算梯度,更新参数。这若干个样本就是一批数据,也就是常说的一个batch。这若干个样本的个数就是batch size。使用一批数据计算梯度,找函数下降最快的方向比SGD要准,可以减轻损失函数的震荡,减少达到收敛所需的迭代次数。训练速度也会比BGD快。常用的梯度下降的方式就是这个mini-BGD。使用 Mini Batch gradient descent,batchsize是一个重要的参数,如果batchsize选的好,那么网络就可以又快又好的收敛。关于batchsize的选择一般有这样的共识,如果训练集中样本数量小于2000,就直接使用 BGD。如果大于2000,使用小批量梯度下降batchsize一般为,常用的有64,128,256,512,1024等。不过实际操作时,还是根据训练数据的情况多试几个batchsize看看吧。
1.计算损失函数:
for x in 1 to batchsize, L x ( w 0 , w 1 , . . . , w n ) {L_x}({w_0},{w_1},...,{w_n}) Lx(w0,w1,...,wn)
2.对每个样本计算当前位置损失函数的梯度:
∂ L x ( w 0 , w 1 , . . . , w n ) ∂ w i \frac{{\partial {L_x}({w_0},{w_1},...,{w_n})}}{{\partial {w_i}}} ∂wi∂Lx(w0,w1,...,wn)
3.计算batchsize个样本的梯度的均值,用batchsize个样本的梯度的总和除以batchsize,用此均值作为本次迭代,损失函数的梯度:
g r a d = ∑ x = 1 b a t c h s i z e ∂ L x ( w 0 , w 1 , . . . , w n ) ∂ w i b a t c h s i z e = ( ∑ x = 1 b a t c h s i z e ∂ L x ( w 0 , w 1 , . . . , w n ) ∂ w 0 b a t c h s i z e , ∑ x = 1 b a t c h s i z e ∂ L x ( w 0 , w 1 , . . . , w n ) ∂ w 1 b a t c h s i z e , . . . , ∑ x = 1 b a t c h s i z e ∂ L x ( w 0 , w 1 , . . . , w n ) ∂ w n b a t c h s i z e ) grad = \frac{{\sum\limits_{x = 1}^{batchsize} {\frac{{\partial {L_x}({w_0},{w_1},...,{w_n})}}{{\partial {w_i}}}} }}{{batchsize}} = (\frac{{\sum\limits_{x = 1}^{batchsize} {\frac{{\partial {L_x}({w_0},{w_1},...,{w_n})}}{{\partial {w_0}}}} }}{{batchsize}},\frac{{\sum\limits_{x = 1}^{batchsize} {\frac{{\partial {L_x}({w_0},{w_1},...,{w_n})}}{{\partial {w_1}}}} }}{{batchsize}},...,\frac{{\sum\limits_{x = 1}^{batchsize} {\frac{{\partial {L_x}({w_0},{w_1},...,{w_n})}}{{\partial {w_n}}}} }}{{batchsize}}) grad=batchsizex=1∑batchsize∂wi∂Lx(w0,w1,...,wn)=(batchsizex=1∑batchsize∂w0∂Lx(w0,w1,...,wn),batchsizex=1∑batchsize∂w1∂Lx(w0,w1,...,wn),...,batchsizex=1∑batchsize∂wn∂Lx(w0,w1,...,wn))
4.用步长α乘以上一步计算的梯度,确定在当前位置沿着负梯度方向下降的距离:
α ∑ x = 1 b a t c h s i z e ∂ L x ( w 0 , w 1 , . . . , w n ) ∂ w i b a t c h s i z e \alpha \frac{{\sum\limits_{x = 1}^{batchsize} {\frac{{\partial {L_x}({w_0},{w_1},...,{w_n})}}{{\partial {w_i}}}} }}{{batchsize}} αbatchsizex=1∑batchsize∂wi∂Lx(w0,w1,...,wn)
5.确定对于所有的参数 w 0 , w 1 , . . . , w n {w_0},{w_1},...,{w_n} w0,w1,...,wn,其下降的距离是否都小于ε:
是:如果是的话,迭代停止。此时所有的参数值 w 0 , w 1 , . . . , w n {w_0},{w_1},...,{w_n} w0,w1,...,wn就是训练得到的最终结果。
否:用以下公式更新参数,参数更新后回到步骤1。
w i n e w = w i o l d − α ∑ x = 1 b a t c h s i z e ∂ L x ( w 0 , w 1 , . . . , w n ) ∂ w i b a t c h s i z e w_i^{new} = w_i^{old} - \alpha \frac{{\sum\limits_{x = 1}^{batchsize} {\frac{{\partial {L_x}({w_0},{w_1},...,{w_n})}}{{\partial {w_i}}}} }}{{batchsize}} winew=wiold−αbatchsizex=1∑batchsize∂wi∂Lx(w0,w1,...,wn)