四、logistic 回归中的梯度下降

我们一般可以通过图中的方式来进行损失函数的求解,而损失函数是怎么反向影响(ω,b)的值的变化的呢?这就要用到导数的知识了,首先我们把损失函数对a求导:
d(a)=dL(a,y)d(a)=−ya+1−y1−a
然后再对z求导:
d(z)=dL(a,y)d(z)=dL(a,y)d(a)d(a)d(z)=a−y
最后我们分别对各个参数求导就可以得到:
d(ω1)=∂L∂ω1=x1d(z)
d(ω2)=∂L∂ω2=x2d(z)
d(b)=∂L∂b=d(z)
由此可知,这样一个样本的一次梯度更新的步骤就是这样,更新函数为:
⎧⎩⎨⎪⎪ω1:=ω1−αd(ω1)ω2:=ω2−αd(ω2)b:=b−αd(b)⎫⎭⎬⎪⎪
现在我们如果把样本扩展到m个的话,那么对应的各个函数就会变为:
J(ω,b)=1m∑mi=1L(a(i),y(i))
a(i)=y^(i)=σ(z(i))=σ(ωTx(i)+b)
∂J(ω,b)∂ωi=1m∑mi=1∂L(a(i),y(i))∂ωi
接下来,我们将会通过实例的代码来做出这一系列的运算,首先我们把我们要写的代码的顺序理一下:
J=0 d(ω1)=0 d(ω2)=0 d(b)=0
for i=1 to m:
z(i)=ωTx(i)+b (1)
a(i)=σ(z(i)) (2)
J+=−[y(i)loga(i)+(1−y(i))log(1−a(i))] (3)
d(z(i))=a(i)−y(i) (4)
d(ω1)+=x(i)1d(z(i)) (5)
d(ω2)+=x(i)2d(z(i)) (6)
d(b)+=d(z(i)) (7)
J/=m d(ω1)/=m d(ω2)/=m d(b)/=m
更新函数同上面的更新函数,这里我们只有三个参数,但是实际上是有非常多的参数的,在实际中我们肯定要对(4)-(7)式进行循环求解的,循环次数取决于参数个数,因为这里只有三个,所以我们就分别罗列出来了。实际的编写中我们多采用向量化来统一存储参数值和样本值,下一节将会讲解。
五、向量化求解
其实向量化求解就是减少循环的一种方式,这样减少循环不仅能够节省时间,还会得到一模一样的值出来,并且这样的方式能够缩短到循环的1/50的时间,这个就是python的numpy库,相信向量都知道是怎么回事,这个库的具体使用可以参照网上的使用手册。这里我就写出向量化之后代码的实现过程:
这里初始化的参数、变量都是一个向量:ω,b是一个0向量;X,Y是一个样本给定的值向量
z=ωTX+b=np.dot(ω.T,x)+b
A=σ(z)
dz=A−Y
dw=1mXdzT
db=1mnp.sum(dz)
ω:=ω−αdw
b:=b−αdb
这就是一次迭代的过程,但是如果要进行多次迭代的话,我们还是要运用循环的方式,这是不可避免的。