梯度下降法的作用是:在测试集上,通过最小化代价函数 J ( w , b ) J(w,b) J(w,b)来训练的参数 w w w和 b b b。
w : = w − a ∂ J ( w , b ) ∂ w w:=w-a\frac{\partial J(w,b)}{\partial w} w:=w−a∂w∂J(w,b)
b : = w − a ∂ J ( w , b ) ∂ b b:=w-a\frac{\partial J(w,b)}{\partial b} b:=w−a∂b∂J(w,b)
: = := :=表示更新参数
a a a 表示学习率(learning rate),用来控制步长(step)
∂ \partial ∂ 表示求偏导符号
∂ J ( w , b ) ∂ w \frac{\partial J(w,b)}{\partial w} ∂w∂J(w,b) 是 J ( w , b ) J(w,b) J(w,b) 对 w w w 求偏导,代码使用 d w dw dw 表示
∂ J ( w , b ) ∂ b \frac{\partial J(w,b)}{\partial b} ∂b∂J(w,b) 是 J ( w , b ) J(w,b) J(w,b)对 b b b 求偏导,代码使用 d b db db 表示
回想逻辑回归的公式定义:
z = w T x + b z={{w}^{T}}x+b z=wTx+b
y ^ = a = σ ( z ) = 1 1 + e − z \hat{y}=a=\sigma (z)=\frac{1}{1+{{e}^{-z}}} y^=a=σ(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 1 {{x}_{1}} x1和 x 2 {{x}_{2}} x2,只考虑一个样本,为了计算 z z z,我们需要输入参数 w 1 {{w}_{1}} w1、 w 2 {{w}_{2}} w2 和 b b b,还有特征值 x 1 {{x}_{1}} x1和 x 2 {{x}_{2}} x2。
z = w 1 x 1 + w 2 x 2 + b z={{w}_{1}}{{x}_{1}}+{{w}_{2}}{{x}_{2}}+b z=w1x1+w2x2+b
L ( a , y ) = − ( y log ( a ) + ( 1 − y ) log ( 1 − a ) ) L(a,y)=-(y\log (a)+(1-y)\log (1-a)) L(a,y)=−(ylog(a)+(1−y)log(1−a))
其中 a a a是逻辑回归的输出, y y y是样本的标签值。
根据导数链式法则进行反向传播
d a = d L ( a , y ) d a = − y / a + ( 1 − y ) / ( 1 − a ) da=\frac{dL(a,y)}{da}=-y/a+(1-y)/(1-a) da=dadL(a,y)=−y/a+(1−y)/(1−a)
d a d z = a ⋅ ( 1 − a ) \frac{da}{dz}=a\cdot (1-a) dzda=a⋅(1−a)
所以:
d z = d L ( a , y ) d z = ( d L d a ) ⋅ ( d a d z ) = a − y dz=\frac{dL(a,y)}{dz}=(\frac{dL}{da})\cdot (\frac{da}{dz})=a-y dz=dzdL(a,y)=(dadL)⋅(dzda)=a−y
d w 1 = ∂ L ∂ w 1 = x 1 ⋅ d z d{{w}_{1}}=\frac{\partial L}{\partial {{w}_{1}}}={{x}_{1}}\cdot dz dw1=∂w1∂L=x1⋅dz
d w 2 = ∂ L ∂ w 2 = x 2 ⋅ d z d{{w}_{2}}=\frac{\partial L}{\partial {{w}_{2}}}={{x}_{2}}\cdot dz dw2=∂w2∂L=x2⋅dz
d b = d z db=dz db=dz
更新 w 1 = w 1 − a d w 1 {{w}_{1}}={{w}_{1}}-a d{{w}_{1}} w1=w1−adw1,
更新 w 2 = w 2 − a d w 2 {{w}_{2}}={{w}_{2}}-a d{{w}_{2}} w2=w2−adw2,
更新 b = b − α d b b=b-\alpha db b=b−αdb。
这就是关于单个样本实例的梯度下降算法中参数更新一次的步骤。
向量化是非常基础的去除代码中for循环的艺术,在深度学习安全领域、深度学习实践中是提高代码运行速度非常关键的技巧。
python中向量化使用的常用指令
import numpy as np
w= np.array(n(x), 1)
u=np.zeros(n(x), 1)
c= np.dot(a,b) #a和b矩阵乘法
u=np.log #计算对数函数($log$)
u=np.abs() #计算数据的绝对值
u=np.maximum(v, 0) #按元素计算$v$中每个元素和和0相比的最大值
矩阵乘法的定义就是: u i = ∑ j A ij v i u_{i} =\sum_{j}^{}{A_{\text{ij}}v_{i}} ui=∑jAijvi,这取决于你怎么定义 u i u_{i} ui值。同样使用非向量化实现, u = n p . z e r o s ( n , 1 ) u=np.zeros(n,1) u=np.zeros(n,1), 并且通过两层循环 f o r ( i ) : f o r ( j ) : for(i):for(j): for(i):for(j):,得到 u [ i ] = u [ i ] + A [ i ] [ j ] ∗ v [ j ] u[i]=u[i]+A[i][j]*v[j] u[i]=u[i]+A[i][j]∗v[j] 。现在就有了 i i i 和 j j j 的两层循环,这就是非向量化。向量化方式就可以用 u = n p . d o t ( A , v ) u=np.dot(A,v) u=np.dot(A,v),右边这种向量化实现方式,消除了两层循环使得代码运行速度更快。
z = w T x + b z={{w}^{T}}x+b z=wTx+b, w w w、 x x x都是列向量
z = w T X + b = n p . d o t ( w . T , X ) + b z= w^{T}X + b = np.dot( w.T,X)+b z=wTX+b=np.dot(w.T,X)+b
A = σ ( Z ) A = \sigma( Z ) A=σ(Z)
d Z = A − Y dZ = A - Y dZ=A−Y
d w = 1 m ∗ X ∗ d z T {{dw} = \frac{1}{m}*X*dz^{T}\ } dw=m1∗X∗dzT
d b = 1 m ∗ n p . s u m ( d Z ) db= \frac{1}{m}*np.sum( dZ) db=m1∗np.sum(dZ)
w : = w − a ∗ d w w: = w - a*dw w:=w−a∗dw
b : = b − a ∗ d b b: = b - a*db b:=b−a∗db
利用前五个公式完成了前向和后向传播,实现了对所有训练样本进行预测和求导,利用后两个公式,梯度下降更新参数。不使用for循环,通过一次迭代实现一次梯度下降,但如果你希望多次迭代进行梯度下降,那么仍然需要for循环,放在最外层。