逻辑回归中的梯度下降

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

假设样本只有两个特征\({{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个样本梯度下降的更多相关文章

  1. JavaScript基础篇详解

    全部的数据类型: 基本数据类型: undefined Number Boolean null String 复杂数据类型: object ①Undefined: >>>声明但未初始化 ...

  2. 走向DBA[MSSQL篇] 详解游标

    原文:走向DBA[MSSQL篇] 详解游标 前篇回顾:上一篇虫子介绍了一些不常用的数据过滤方式,本篇详细介绍下游标. 概念 简单点说游标的作用就是存储一个结果集,并根据语法将这个结果集的数据逐条处理. ...

  3. RabbitMQ基础知识详解

    什么是MQ? MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中 ...

  4. Scala进阶之路-Scala函数篇详解

    Scala进阶之路-Scala函数篇详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传值调用和传名调用 /* @author :yinzhengjie Blog:http: ...

  5. Cisco路由技术基础知识详解

    第一部分 请写出568A的线序(接触网络第一天就应该会的,只要你掐过,想都能想出来) .网卡MAC地址长度是(  )个二进制位(16进制与2进制的换算关系,只是换种方式问,不用你拿笔去算) A.12  ...

  6. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ基础知识详解,RabbitMQ布曙

    消息队列及常见消息队列介绍 2017-10-10 09:35操作系统/客户端/人脸识别 一.消息队列(MQ)概述 消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以 ...

  7. Python基础知识详解 从入门到精通(七)类与对象

    本篇主要是介绍python,内容可先看目录其他基础知识详解,欢迎查看本人的其他文章Python基础知识详解 从入门到精通(一)介绍Python基础知识详解 从入门到精通(二)基础Python基础知识详 ...

  8. I2C 基础原理详解

    今天来学习下I2C通信~ I2C(Inter-Intergrated Circuit)指的是 IC(Intergrated Circuit)之间的(Inter) 通信方式.如上图所以有很多的周边设备都 ...

  9. PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明

    PHP函数篇详解十进制.二进制.八进制和十六进制转换函数说明 作者: 字体:[增加 减小] 类型:转载   中文字符编码研究系列第一期,PHP函数篇详解十进制.二进制.八进制和十六进制互相转换函数说明 ...

  10. python 3.x 爬虫基础---Urllib详解

    python 3.x 爬虫基础 python 3.x 爬虫基础---http headers详解 python 3.x 爬虫基础---Urllib详解 前言 爬虫也了解了一段时间了希望在半个月的时间内 ...

随机推荐

  1. python接口自动化 之excel读取测试数据

    一.当你拥有一个excel版的接口用例 excel中有用例名称.url.请求方式和请求参数 二.获取excel的Url.请求方式和请求参数 # 单独获取某个单元格的值,第二行第二列# 第二行数据 ro ...

  2. 如何编写难以维护的 React 代码?耦合通用组件与业务逻辑

    在众多项目中,React代码的维护经常变得棘手.其中一个常见问题是:将业务逻辑直接嵌入通用组件中,导致通用组件与业务逻辑紧密耦合,使其失去"通用性".这种做法使通用组件过于依赖具体 ...

  3. ApiPost发送请求报错UT000036: Connection terminated parsing multipart data

    发送请求报错Caused by: java.io.IOException: UT000036: Connection terminated parsing multipart data 这个报错是因为 ...

  4. Speex详解(2019年09月25日更新)

    Speex详解 整理者:赤勇玄心行天道 QQ号:280604597 微信号:qq280604597 QQ群:511046632 博客:www.cnblogs.com/gaoyaguo 大家有什么不明白 ...

  5. Nacos源码阅读心得

    Nacos注册中心(1.4.1)源码解读心得 一丶Nacos介绍 Nacos是阿里巴巴推出的一款新开源项目,是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台.它致力于帮助您发现.配置和 ...

  6. CSP-2023 初赛游记

    9.16 上午 今天就不早读了. 去前做了个 2019 的题,60 多分,感觉挺危. 去比赛前 30min 发现没带身份证,去宿舍拿的. 前 10min 发现没有笔,借了一些,但是发现还有一个小时才开 ...

  7. JavaScript 语法:变量、数据类型及数据类型转换

    作者:WangMin 格言:努力做好自己喜欢的每一件事 变量 赋值变量用 var 关键字,情况如下: 1)先声明变量再赋值 var varName; varName="你好~"; ...

  8. "拍牌神器"是怎样炼成的(三)---注册全局热键

    要想在上海拍牌的超低中标率中把握机会.占得先机,您不仅需要事先准备好最优的竞拍策略,还要制定若干套应急预案,应对不时之需.既定策略交给计算机自动执行,没有问题.可是谁来召唤应急预案呢?使用全局热键应该 ...

  9. 01_实验一_操作系统的启动start

    实验一 操作系统的启动 从源代码到可运行的操作系统(前置知识) API 与 SDK 以 C 语言编写的操作系统为背景进行介绍,EOS 是由 C 语言编写的 操作系统和应用程序之间一个重要的纽带就是应用 ...

  10. 2023 11月 AtCoder 做题记录

    AGC037F 题目传送门 第一步,考虑判断序列是否合法. 通过对于属于等级 $k$ 的定义将定义反推:$s$ 中最小的元素 $x$,找到所有 $x$ 的连续段.设一个连续段的长度是 $len$,若 ...