神经网络基础篇:详解逻辑回归 & m个样本梯度下降
逻辑回归中的梯度下降
本篇讲解怎样通过计算偏导数来实现逻辑回归的梯度下降算法。它的关键点是几个重要公式,其作用是用来实现逻辑回归中梯度下降算法。但是在本博客中,将使用计算图对梯度下降算法进行计算。必须要承认的是,使用计算图来计算逻辑回归的梯度下降算法有点大材小用了。但是,认为以这个例子作为开始来讲解,可以使更好的理解背后的思想。从而在讨论神经网络时,可以更深刻而全面地理解神经网络。接下来让开始学习逻辑回归的梯度下降算法。
假设样本只有两个特征\({{x}_{1}}\)和\({{x}_{2}}\),为了计算\(z\),需要输入参数\({{w}_{1}}\)、\({{w}_{2}}\) 和\(b\),除此之外还有特征值\({{x}_{1}}\)和\({{x}_{2}}\)。因此\(z\)的计算公式为:
\(z={{w}_{1}}{{x}_{1}}+{{w}_{2}}{{x}_{2}}+b\)
回想一下逻辑回归的公式定义如下:
\(\hat{y}=a=\sigma (z)\)
其中\(z={{w}^{T}}x+b\)
\(\sigma \left( z \right)=\frac{1}{1+{{e}^{-z}}}\)
损失函数:
\(L( {{{\hat{y}}}^{(i)}},{{y}^{(i)}})=-{{y}^{(i)}}\log {{\hat{y}}^{(i)}}-(1-{{y}^{(i)}})\log (1-{{\hat{y}}^{(i)}})\)
代价函数:
\(J\left( w,b \right)=\frac{1}{m}\sum\nolimits_{i}^{m}{L( {{{\hat{y}}}^{(i)}},{{y}^{(i)}})}\)
假设现在只考虑单个样本的情况,单个样本的代价函数定义如下:
\(L(a,y)=-(y\log (a)+(1-y)\log (1-a))\)
其中\(a\)是逻辑回归的输出,\(y\)是样本的标签值。现在让画出表示这个计算的计算图。
这里先复习下梯度下降法,\(w\)和\(b\)的修正量可以表达如下:
\(w:=w-a \frac{\partial J(w,b)}{\partial w}\),\(b:=b-a\frac{\partial J(w,b)}{\partial b}\)

如图:在这个公式的外侧画上长方形。然后计算:
\(\hat{y}=a=\sigma(z)\)
也就是计算图的下一步。最后计算损失函数\(L(a,y)\)。
有了计算图,就不需要再写出公式了。因此,为了使得逻辑回归中最小化代价函数\(L(a,y)\),需要做的仅仅是修改参数\(w\)和\(b\)的值。前面已经讲解了如何在单个训练样本上计算代价函数的前向步骤。现在让来讨论通过反向计算出导数。
因为想要计算出的代价函数\(L(a,y)\)的导数,首先需要反向计算出代价函数\(L(a,y)\)关于\(a\)的导数,在编写代码时,只需要用\(da\) 来表示\(\frac{dL(a,y)}{da}\) 。
通过微积分得到:
\(\frac{dL(a,y)}{da}=-y/a+(1-y)/(1-a)\)
如果非常熟悉微积分,建议主动推导前面介绍的代价函数的求导公式,使用微积分直接求出\(L(a,y)\)关于变量\(a\)的导数。如果不太了解微积分,也不用太担心。现在已经计算出\(da\),也就是最终输出结果的导数。
现在可以再反向一步,在编写Python代码时,只需要用\(dz\)来表示代价函数\(L\)关于\(z\) 的导数\(\frac{dL}{dz}\),也可以写成\(\frac{dL(a,y)}{dz}\),这两种写法都是正确的。
\(\frac{dL}{dz}=a-y\) 。
因为\(\frac{dL(a,y)}{dz}=\frac{dL}{dz}=(\frac{dL}{da})\cdot (\frac{da}{dz})\),
并且\(\frac{da}{dz}=a\cdot (1-a)\),
而 \(\frac{dL}{da}=(-\frac{y}{a}+\frac{(1-y)}{(1-a)})\),因此将这两项相乘,得到:
\({dz} = \frac{{dL}(a,y)}{{dz}} = \frac{{dL}}{{dz}} = \left( \frac{{dL}}{{da}} \right) \cdot \left(\frac{{da}}{{dz}} \right) = ( - \frac{y}{a} + \frac{(1 - y)}{(1 - a)})\cdot a(1 - a) = a - y\)
博客中为了简化推导过程,假设\({{n}_{x}}\) 这个推导的过程就是之前提到过的链式法则。如果对微积分熟悉,放心地去推导整个求导过程,如果不熟悉微积分,只需要知道\(dz=(a-y)\)已经计算好了。
现在进行最后一步反向推导,也就是计算\(w\)和\(b\)变化对代价函数\(L\)的影响,特别地,可以用:
\(d{{w}_{1}}=\frac{1}{m}\sum\limits_{i}^{m}{x_{1}^{(i)}}({{a}^{(i)}}-{{y}^{(i)}})\)
\(d{{w}_{2}}=\frac{1}{m}\sum\limits_{i}^{m}{x_{2}^{(i)}}({{a}^{(i)}}-{{y}^{(i)}})\)
\(db=\frac{1}{m}\sum\limits_{i}^{m}{({{a}^{(i)}}-{{y}^{(i)}})}\)
博客中,
\(d{{w}_{1}}\) 表示\(\frac{\partial L}{\partial {{w}_{1}}}={{x}_{1}}\cdot dz\),
\(d{{w}_{\text{2}}}\) 表示\(\frac{\partial L}{\partial {{w}_{2}}}={{x}_{2}}\cdot dz\),
\(db=dz\)。
因此,关于单个样本的梯度下降算法,所需要做的就是如下的事情:
使用公式\(dz=(a-y)\)计算\(dz\),
使用\(d{{w}_{1}}={{x}_{1}}\cdot dz\) 计算\(d{{w}_{1}}\), \(d{{w}_{2}}={{x}_{2}}\cdot dz\)计算\(d{{w}_{2}}\),
\(db=dz\) 来计算\(db\),
然后:
更新\({{w}_{1}}={{w}_{1}}-a d{{w}_{1}}\),
更新\({{w}_{2}}={{w}_{2}}-a d{{w}_{2}}\),
更新\(b=b-\alpha db\)。
这就是关于单个样本实例的梯度下降算法中参数更新一次的步骤。

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

首先,让时刻记住有关于损失函数\(J(w,b)\)的定义。
\(J(w,b)=\frac{1}{m}\sum\limits_{i=1}^{m}{L({{a}^{(i)}},{{y}^{(i)}})}\)
当的算法输出关于样本\(y\)的\({{a}^{(i)}}\),\({{a}^{(i)}}\)是训练样本的预测值,即:\(\sigma ( {{z}^{(i)}})=\sigma( {{w}^{T}}{{x}^{\left( i \right)}}+b)\)。
所以在前面是对于任意单个训练样本,如何计算微分当只有一个训练样本。因此\(d{{w}_{1}}\),\(d{{w}_{\text{2}}}\)和\(db\) 添上上标\(i\)表示求得的相应的值。如果面对的是之前的那种情况,但只使用了一个训练样本\(({{x}^{(i)}},{{y}^{(i)}})\)。
现在知道带有求和的全局代价函数,实际上是1到\(m\)项各个损失的平均。 所以它表明全局代价函数对\({{w}_{1}}\)的微分,对\({{w}_{1}}\)的微分也同样是各项损失对\({{w}_{1}}\)微分的平均。

但之前已经演示了如何计算这项,即之前是如何对单个训练样本进行计算。所以真正需要做的是计算这些微分,如在之前的训练样本上做的。并且求平均,这会给全局梯度值,能够把它直接应用到梯度下降算法中。
所以这里有很多细节,但让把这些装进一个具体的算法。同时需要一起应用的就是逻辑回归和梯度下降。
初始化\(J=0,d{{w}_{1}}=0,d{{w}_{2}}=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并且\({{n}_{x}}\) 等于2。 但如果有更多特征,开始编写的因此\(d{{w}_{1}}\),\(d{{w}_{2}}\),有相似的计算从\(d{{w}_{3}}\)一直下去到\(d{{w}_{n}}\)。所以看来需要一个for循环遍历所有\(n\)个特征。
当应用深度学习算法,会发现在代码中显式地使用for循环使的算法很低效,同时在深度学习领域会有越来越大的数据集。所以能够应用的算法且没有显式的for循环会是重要的,并且会帮助适用于更大的数据集。所以这里有一些叫做向量化技术,它可以允许的代码摆脱这些显式的for循环。
想在先于深度学习的时代,也就是深度学习兴起之前,向量化是很棒的。可以使有时候加速的运算,但有时候也未必能够。但是在深度学习时代向量化,摆脱for循环已经变得相当重要。因为越来越多地训练非常大的数据集,因此真的需要的代码变得非常高效。所以在接下来的几个博客中,会谈到向量化,以及如何应用向量化而连一个for循环都不使用。所以学习了这些,希望有关于如何应用逻辑回归,或是用于逻辑回归的梯度下降,事情会变得更加清晰。当进行编程练习,但在真正做编程练习之前让先谈谈向量化。然后可以应用全部这些东西,应用一个梯度下降的迭代而不使用任何for循环。
神经网络基础篇:详解逻辑回归 & m个样本梯度下降的更多相关文章
- JavaScript基础篇详解
全部的数据类型: 基本数据类型: undefined Number Boolean null String 复杂数据类型: object ①Undefined: >>>声明但未初始化 ...
- 走向DBA[MSSQL篇] 详解游标
原文:走向DBA[MSSQL篇] 详解游标 前篇回顾:上一篇虫子介绍了一些不常用的数据过滤方式,本篇详细介绍下游标. 概念 简单点说游标的作用就是存储一个结果集,并根据语法将这个结果集的数据逐条处理. ...
- RabbitMQ基础知识详解
什么是MQ? MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中 ...
- Scala进阶之路-Scala函数篇详解
Scala进阶之路-Scala函数篇详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传值调用和传名调用 /* @author :yinzhengjie Blog:http: ...
- Cisco路由技术基础知识详解
第一部分 请写出568A的线序(接触网络第一天就应该会的,只要你掐过,想都能想出来) .网卡MAC地址长度是( )个二进制位(16进制与2进制的换算关系,只是换种方式问,不用你拿笔去算) A.12 ...
- RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙
消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...
- Python基础知识详解 从入门到精通(七)类与对象
本篇主要是介绍python,内容可先看目录其他基础知识详解,欢迎查看本人的其他文章Python基础知识详解 从入门到精通(一)介绍Python基础知识详解 从入门到精通(二)基础Python基础知识详 ...
- I2C 基础原理详解
今天来学习下I2C通信~ I2C(Inter-Intergrated Circuit)指的是 IC(Intergrated Circuit)之间的(Inter) 通信方式.如上图所以有很多的周边设备都 ...
- PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明
PHP函数篇详解十进制.二进制.八进制和十六进制转换函数说明 作者: 字体:[增加 减小] 类型:转载 中文字符编码研究系列第一期,PHP函数篇详解十进制.二进制.八进制和十六进制互相转换函数说明 ...
- python 3.x 爬虫基础---Urllib详解
python 3.x 爬虫基础 python 3.x 爬虫基础---http headers详解 python 3.x 爬虫基础---Urllib详解 前言 爬虫也了解了一段时间了希望在半个月的时间内 ...
随机推荐
- 探索Redis与MySQL的双写问题
本文已收录至GitHub,推荐阅读 Java随想录 微信公众号:Java随想录 原创不易,注重版权.转载请注明原作者和原文链接 目录 双写一致问题 缓存读写策略 Cache-Aside Pattern ...
- CF755C
题目简化和分析: 这题不用说怎么分析了吧,这一看就是个并查集求连通分量个数的经典模板. 我们需要将 \(i\) 和 \(p_i\) 进行合并. 遍历每个 \(i\) 与 \(i+1\) 是否属于同一个 ...
- Linux 本地部署私有Stackedit Markdown编辑器远程访问
StackEdit是一个受欢迎的Markdown编辑器,在GitHub上拥有20.7k Star!,它支持将Markdown笔记保存到多个仓库,包括Gitee.GitHub和Gitea.此在线笔记工具 ...
- Chromium Command Buffer原理解析
Command Buffer 是支撑 Chromium 多进程硬件加速渲染的核心技术之一.它基于 OpenGLES2.0 定义了一套序列化协议,这套协议规定了所有 OpenGLES2.0 命令的序列化 ...
- SpringBoot数据响应、分层解耦、三层架构
响应数据 @ResponseBody 类型:方法注解.类注解 位置:Controller方法.类上 作用:将方法返回值直接响应,如果返回值类型是 实体对象/集合 ,将会转换为json格式响应 说明:@ ...
- 【pwn】[SDCTF 2022]Horoscope--栈溢出,atoi函数绕过
checksec检查一下,发现只开了nx,然后ida打开直接看主函数 发现fgets函数往s里面读入320个字节的数据,此处可造成溢出,再看看test和debug函数 void debug(){ t ...
- Kubernetes:kube-apiserver 之鉴权
kubernetes:kube-apiserver 系列文章: Kubernetes:kube-apiserver 之 scheme(一) Kubernetes:kube-apiserver 之 sc ...
- 栈与队列应用:迷宫问题(DFS非最短路径)
//先输入行列,在输入迷宫 以-1 -1 结束 #include<stdio.h> #include<stdlib.h> #define MAXSIZE 100 #define ...
- 🔥🔥Java开发者的Python快速进修指南:控制之if-else和循环技巧
简单介绍 在我们今天的学习中,让我们简要了解一下Python的控制流程.考虑到我们作为有着丰富Java开发经验的程序员,我们将跳过一些基础概念,如变量和数据类型.如果遇到不熟悉的内容,可以随时查阅文档 ...
- Cassandra中的MerkleTree反熵机制
构建MerkleTree Cassandra 是一个分布式数据库系统,它使用 Merkle 树来实现数据一致性和数据完整性的验证. 在 Cassandra 中,每个节点都维护着自己的数据副本.为了确保 ...