神经网络基础篇:详解逻辑回归 & m个样本梯度下降

逻辑回归中的梯度下降

本篇讲解怎样通过计算偏导数来实现逻辑回归的梯度下降算法。它的关键点是几个重要公式,其作用是用来实现逻辑回归中梯度下降算法。但是在本博客中,将使用计算图对梯度下降算法进行计算。必须要承认的是,使用计算图来计算逻辑回归的梯度下降算法有点大材小用了。但是,认为以这个例子作为开始来讲解,可以使更好的理解背后的思想。从而在讨论神经网络时,可以更深刻而全面地理解神经网络。接下来让开始学习逻辑回归的梯度下降算法。

假设样本只有两个特征x1x2,为了计算z,需要输入参数w1w2b,除此之外还有特征值x1x2。因此z的计算公式为:
z=w1x1+w2x2+b
回想一下逻辑回归的公式定义如下:
y^=a=σ(z)
其中z=wTx+b
σ(z)=11+ez
损失函数:
L(y^(i),y(i))=y(i)logy^(i)(1y(i))log(1y^(i))
代价函数:
J(w,b)=1mimL(y^(i),y(i))
假设现在只考虑单个样本的情况,单个样本的代价函数定义如下:
L(a,y)=(ylog(a)+(1y)log(1a))
其中a是逻辑回归的输出,y是样本的标签值。现在让画出表示这个计算的计算图。
这里先复习下梯度下降法,wb的修正量可以表达如下:

w:=waJ(w,b)wb:=baJ(w,b)b

如图:在这个公式的外侧画上长方形。然后计算:
y^=a=σ(z)
也就是计算图的下一步。最后计算损失函数L(a,y)
有了计算图,就不需要再写出公式了。因此,为了使得逻辑回归中最小化代价函数L(a,y),需要做的仅仅是修改参数wb的值。前面已经讲解了如何在单个训练样本上计算代价函数的前向步骤。现在让来讨论通过反向计算出导数。
因为想要计算出的代价函数L(a,y)的导数,首先需要反向计算出代价函数L(a,y)关于a的导数,在编写代码时,只需要用da 来表示dL(a,y)da
通过微积分得到:
dL(a,y)da=y/a+(1y)/(1a)
如果非常熟悉微积分,建议主动推导前面介绍的代价函数的求导公式,使用微积分直接求出L(a,y)关于变量a的导数。如果不太了解微积分,也不用太担心。现在已经计算出da,也就是最终输出结果的导数。
现在可以再反向一步,在编写Python代码时,只需要用dz来表示代价函数L关于z 的导数dLdz,也可以写成dL(a,y)dz,这两种写法都是正确的。
dLdz=ay
因为dL(a,y)dz=dLdz=(dLda)(dadz)
并且dadz=a(1a)
dLda=(ya+(1y)(1a)),因此将这两项相乘,得到:

dz=dL(a,y)dz=dLdz=(dLda)(dadz)=(ya+(1y)(1a))a(1a)=ay

博客中为了简化推导过程,假设nx 这个推导的过程就是之前提到过的链式法则。如果对微积分熟悉,放心地去推导整个求导过程,如果不熟悉微积分,只需要知道dz=(ay)已经计算好了。

现在进行最后一步反向推导,也就是计算wb变化对代价函数L的影响,特别地,可以用:
dw1=1mimx1(i)(a(i)y(i))
dw2=1mimx2(i)(a(i)y(i))
db=1mim(a(i)y(i))
博客中,
dw1 表示Lw1=x1dz
dw2 表示Lw2=x2dz
db=dz
因此,关于单个样本的梯度下降算法,所需要做的就是如下的事情:
使用公式dz=(ay)计算dz
使用dw1=x1dz 计算dw1dw2=x2dz计算dw2
db=dz 来计算db
然后:
更新w1=w1adw1
更新w2=w2adw2
更新b=bαdb
这就是关于单个样本实例的梯度下降算法中参数更新一次的步骤。

现在已经知道了怎样计算导数,并且实现针对单个训练样本的逻辑回归的梯度下降算法。但是,训练逻辑回归模型不仅仅只有一个训练样本,而是有m个训练样本的整个训练集。因此在下面讲解中,将这些思想应用到整个训练样本集中,而不仅仅只是单个样本上。

m个样本的梯度下降

在之前的博客中,已经看到如何计算导数,以及应用梯度下降在逻辑回归的一个训练样本上。现在想要把它应用在m个训练样本上。

首先,让时刻记住有关于损失函数J(w,b)的定义。

J(w,b)=1mi=1mL(a(i),y(i))

当的算法输出关于样本ya(i)a(i)是训练样本的预测值,即:σ(z(i))=σ(wTx(i)+b)
所以在前面是对于任意单个训练样本,如何计算微分当只有一个训练样本。因此dw1dw2db 添上上标i表示求得的相应的值。如果面对的是之前的那种情况,但只使用了一个训练样本(x(i),y(i))
现在知道带有求和的全局代价函数,实际上是1到m项各个损失的平均。 所以它表明全局代价函数对w1的微分,对w1的微分也同样是各项损失对w1微分的平均。

但之前已经演示了如何计算这项,即之前是如何对单个训练样本进行计算。所以真正需要做的是计算这些微分,如在之前的训练样本上做的。并且求平均,这会给全局梯度值,能够把它直接应用到梯度下降算法中。

所以这里有很多细节,但让把这些装进一个具体的算法。同时需要一起应用的就是逻辑回归和梯度下降。

初始化J=0,dw1=0,dw2=0,db=0

代码流程:

J=0;dw1=0;dw2=0;db=0;
for i = 1 to m
    z(i) = wx(i)+b;
    a(i) = sigmoid(z(i));
    J += -[y(i)log(a(i))+(1-y(i))log(1-a(i));
    dz(i) = a(i)-y(i);
    dw1 += x1(i)dz(i);
    dw2 += x2(i)dz(i);
    db += dz(i);
J/= m;
dw1/= m;
dw2/= m;
db/= m;
w=w-alpha*dw
b=b-alpha*db

这里只应用了一步梯度下降。因此需要重复以上内容很多次,以应用多次梯度下降。看起来这些细节似乎很复杂,但目前不要担心太多。希望明白,当继续尝试并应用这些在编程作业里,所有这些会变的更加清楚。

但这种计算中有两个缺点,也就是说应用此方法在逻辑回归上需要编写两个for循环。第一个for循环是一个小循环遍历m个训练样本,第二个for循环是一个遍历所有特征的for循环。这个例子中只有2个特征,所以n等于2并且nx 等于2。 但如果有更多特征,开始编写的因此dw1dw2,有相似的计算从dw3一直下去到dwn。所以看来需要一个for循环遍历所有n个特征。

当应用深度学习算法,会发现在代码中显式地使用for循环使的算法很低效,同时在深度学习领域会有越来越大的数据集。所以能够应用的算法且没有显式的for循环会是重要的,并且会帮助适用于更大的数据集。所以这里有一些叫做向量化技术,它可以允许的代码摆脱这些显式的for循环。

想在先于深度学习的时代,也就是深度学习兴起之前,向量化是很棒的。可以使有时候加速的运算,但有时候也未必能够。但是在深度学习时代向量化,摆脱for循环已经变得相当重要。因为越来越多地训练非常大的数据集,因此真的需要的代码变得非常高效。所以在接下来的几个博客中,会谈到向量化,以及如何应用向量化而连一个for循环都不使用。所以学习了这些,希望有关于如何应用逻辑回归,或是用于逻辑回归的梯度下降,事情会变得更加清晰。当进行编程练习,但在真正做编程练习之前让先谈谈向量化。然后可以应用全部这些东西,应用一个梯度下降的迭代而不使用任何for循环。

posted @   Oten  阅读(256)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示