梯度下降算法和向量化
逻辑回归中的梯度下降
梯度下降法的作用是:在测试集上,通过最小化代价函数
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循环,放在最外层。