微积分的应用:神经网络
原文:
machinelearningmastery.com/calculus-in-action-neural-networks/
人工神经网络是一个计算模型,用于逼近输入和输出之间的映射。
它的灵感来自于人脑的结构,因为它类似地由一个互联的神经元网络组成,这些神经元在接收到来自邻近神经元的一组刺激后传播信息。
训练神经网络涉及一个过程,该过程同时使用反向传播和梯度下降算法。正如我们将看到的,这两个算法都广泛使用微积分。
在本教程中,你将发现微积分的各个方面如何应用于神经网络。
完成本教程后,你将了解:
-
人工神经网络被组织成神经元和连接的层次结构,其中后者赋予每个权重值。
-
每个神经元实现一个非线性函数,将一组输入映射到一个输出激活。
-
在训练神经网络时,反向传播和梯度下降算法广泛使用微积分。
让我们开始吧。
微积分的应用:神经网络
图片由Tomoe Steineck提供,保留部分版权。
教程概述
本教程分为三个部分,它们是:
-
神经网络简介
-
神经元的数学
-
训练网络
先决条件
对于本教程,我们假设你已经知道以下内容:
你可以通过点击上面给出的链接来复习这些概念。
神经网络简介
人工神经网络可以被视为函数逼近算法。
在监督学习环境中,当提供多个输入观察值表示关注的问题,以及相应的目标输出时,人工神经网络将尝试逼近这两者之间存在的映射。
神经网络是一个计算模型,灵感来自于人脑的结构。
– 第 65 页,深度学习,2019 年。
人脑由一个庞大的互联神经元网络组成(约有一百亿个神经元),每个神经元包括一个细胞体、一组称为树突的纤维和一个轴突:
人脑中的神经元
树突作为神经元的输入通道,而轴突则作为输出通道。因此,神经元通过其树突接收输入信号,这些树突又连接到其他邻近神经元的(输出)轴突。通过这种方式,一个足够强的电信号(也称为动作电位)可以沿着一个神经元的轴突传递到所有连接到它的其他神经元。这允许信号在大脑结构中传播。
因此,神经元充当全或无的开关,接受一组输入并输出一个动作电位或没有输出。
– 第 66 页,深度学习,2019 年。
人工神经网络类似于人脑的结构,因为(1)它由大量互联的神经元组成,(2)这些神经元通过(3)接收来自邻近神经元的一组刺激并将其映射到输出,从而在网络中传播信息,以便传递到下一层神经元。
人工神经网络的结构通常组织成神经元的层级(回顾树状图的描述)。例如,以下图示例展示了一个完全连接的神经网络,其中一层中的所有神经元都连接到下一层的所有神经元:
完全连接的前馈神经网络
输入位于网络的左侧,信息向右传播(或流动)到对侧的输出端。由于信息在网络中以前馈方向传播,因此我们也将这种网络称为前馈神经网络。
输入层和输出层之间的神经元层称为隐藏层,因为它们无法直接访问。
每两个神经元之间的连接(在图中由箭头表示)被赋予一个权重,该权重作用于通过网络的数据,正如我们稍后将看到的。
想要开始学习机器学习中的微积分吗?
现在就获取我的免费 7 天邮件速成课程(包括示例代码)。
点击注册并获得课程的免费 PDF 电子书版本。
神经元的数学
更具体地说,假设一个特定的人工神经元(或弗兰克·罗森布拉特最初称之为感知器)接收 n 个输入,[x[1], …, x[n]],每个连接都有一个对应的权重[w[1], …, w[n]]。
执行的第一个操作是将输入值乘以其相应的权重,并将偏置项 b 加到它们的总和中,生成输出 z:
z = ((x[1] × w[1]) + (x[2] × w[2]) + … + (x[n] × w[n])) + b
我们可以将这个操作以更紧凑的形式表示如下:
到目前为止,我们执行的加权和计算是一个线性操作。如果每个神经元必须单独实现这种特定的计算,那么神经网络将被限制于仅学习线性输入输出映射。
然而,我们可能希望建模的许多世界中的关系是非线性的,如果我们尝试使用线性模型来建模这些关系,那么模型将非常不准确。
– 第 77 页,深度学习,2019 年。
因此,每个神经元执行第二个操作,通过应用非线性激活函数 a(.) 转换加权和:
如果我们将偏置项作为另一个权重* w *[0](注意总和现在从 0 开始)集成到和中,我们可以更紧凑地表示每个神经元执行的操作:
每个神经元执行的操作可以如下所示:
神经元实现的非线性函数
因此,每个神经元可以被视为实现一个将输入集映射到输出激活的非线性函数。
训练网络
训练人工神经网络涉及寻找最佳建模数据模式的权重集的过程。这是一个同时使用反向传播和梯度下降算法的过程。这两种算法都大量使用微积分。
每当网络向前(或向右)方向遍历时,可以通过损失函数(如平方误差的总和(SSE))计算网络的误差,即网络输出与预期目标之间的差异。然后,反向传播算法计算此误差对权重变化的梯度(或变化率)。为了做到这一点,它需要使用链式法则和偏导数。
为了简单起见,考虑一个由单条激活路径连接的两个神经元组成的网络。如果我们需要打开它们,我们会发现神经元按照以下级联操作进行:
两个神经元级联执行的操作
链式法则的第一个应用将网络的整体误差连接到激活函数a[2]的输入z[2],随后连接到权重w[2],如下所示:
你可能注意到链式法则的应用涉及到神经元激活函数关于其输入z[2]的偏导数乘积,还有其他项。有不同的激活函数可供选择,例如 sigmoid 或 logistic 函数。如果我们以 logistic 函数为例,那么其偏导数将如下计算:
因此,我们可以如下计算t[2]:
这里,t[2]是期望的激活,通过计算t[2]和a[2]之间的差异,我们因此计算了网络生成的激活与预期目标之间的误差。
由于我们正在计算激活函数的导数,因此它应在整个实数空间上是连续且可微的。在深度神经网络的情况下,误差梯度向后传播经过大量隐藏层。这可能导致误差信号迅速减少到零,尤其是如果导数函数的最大值已经很小(例如,logistic 函数的倒数最大值为 0.25)。这被称为梯度消失问题。ReLU 函数在深度学习中非常流行,以减轻这个问题,因为其在其正部分的导数等于 1。
接下来的权重反向传播到网络的深层,因此链式法则的应用也可以类似地扩展,以将整体误差与权重 w[1] 连接起来,如下所示:
如果我们再次以逻辑函数作为激活函数,那么我们将如下计算 ???[1]:
一旦我们计算了网络误差相对于每个权重的梯度,就可以应用梯度下降算法来更新每个权重,以进行下一个时间点 t+1 的 前向传播。对于权重 w[1],使用梯度下降的权重更新规则如下:
即使我们这里考虑的是一个简单的网络,我们经历的过程也可以扩展到评估更复杂和更深的网络,例如卷积神经网络(CNNs)。
如果考虑的网络具有来自多个输入的多个分支(并可能流向多个输出),则其评估将涉及对每条路径的不同导数链的求和,类似于我们之前推导的广义链式法则。
进一步阅读
本节提供了更多关于这个主题的资源,如果你想深入了解。
书籍
总结
在本教程中,你发现了微积分在神经网络中的应用。
具体来说,你学到了:
-
人工神经网络被组织成由神经元和连接层组成,后者每个都分配一个权重值。
-
每个神经元实现一个非线性函数,将一组输入映射到输出激活值。
-
在训练神经网络时,反向传播和梯度下降算法广泛使用微积分。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
机器学习中的微积分:为什么它有效
原文:
machinelearningmastery.com/calculus-in-machine-learning-why-it-works/
微积分是机器学习中的核心数学概念之一,它使我们能够理解不同机器学习算法的内部工作原理。
微积分在机器学习中的一个重要应用是梯度下降算法,它与反向传播一起使我们能够训练神经网络模型。
在本教程中,你将发现微积分在机器学习中的关键作用。
完成本教程后,你将知道:
-
微积分在理解机器学习算法的内部工作原理中发挥着重要作用,例如用于最小化误差函数的梯度下降算法。
-
微积分为我们提供了优化复杂目标函数以及具有多维输入的函数所需的工具,这些函数代表了不同的机器学习应用。
让我们开始吧。
机器学习中的微积分:为什么它有效
图片由 Hasmik Ghazaryan Olson 提供,保留部分权利。
教程概述
本教程分为两部分,它们是:
-
机器学习中的微积分
-
为什么微积分在机器学习中有效
机器学习中的微积分
神经网络模型,无论是浅层还是深层,都会实现一个将一组输入映射到期望输出的函数。
神经网络实现的函数通过训练过程学习,该过程迭代地搜索一组权重,以使神经网络能够最好地模拟训练数据的变化。
一种非常简单的函数类型是从单一输入到单一输出的线性映射。
《深度学习》第 187 页,2019 年。
这样的线性函数可以用一个具有斜率 m 和 y 截距 c 的直线方程表示:
y = mx + c
变化每个参数 m 和 c 会产生定义不同输入输出映射的不同线性模型。
通过变化斜率和截距产生的不同线性模型的线图
取自《深度学习》
因此,学习映射函数的过程涉及到这些模型参数或 权重 的近似,这些参数会导致预测输出与目标输出之间的最小误差。这个误差通过损失函数、成本函数或误差函数(通常可以互换使用)来计算,而最小化损失的过程称为 函数优化。
我们可以将微分计算应用于函数优化过程。
为了更好地理解如何将微分计算应用于函数优化,我们回到具有线性映射函数的具体示例。
假设我们有一些单输入特征的数据显示,x,以及它们对应的目标输出,y。为了衡量数据集上的误差,我们将计算预测输出和目标输出之间的平方误差和(SSE),作为我们的损失函数。
对模型权重的不同值进行参数扫描,w[0] = m 和 w[1] = c,生成了形状为凸形的个别误差轮廓。
错误(SSE)轮廓的线图,当在斜率和截距的范围内进行扫描时生成
摘自《深度学习》
结合个别误差轮廓生成了一个三维误差面,该面也呈凸形。这个误差面位于一个权重空间内,该空间由模型权重的扫掠范围定义,w[0] 和 w[1]。
当斜率和截距都变化时生成的误差(SSE)面三维图
摘自《深度学习》
在这个权重空间中移动相当于在不同线性模型之间移动。我们的目标是识别在所有可能的备选模型中最适合数据的模型。最佳模型的特征是数据集上的最低误差,这与误差面的最低点相对应。
一个凸形或碗状的误差面对于学习线性函数以建模数据集是非常有用的,因为这意味着学习过程可以被框定为在误差面上寻找最低点。用来寻找这个最低点的标准算法被称为梯度下降。
第 194 页,《深度学习》,2019 年。
梯度下降算法作为优化算法,将通过沿着误差面的梯度下坡来寻求达到误差面的最低点。这种下降是基于对误差面梯度或斜率的计算。
这就是微分计算发挥作用的地方。
微积分,特别是微分,是处理变化率的数学领域。
第 198 页,《深度学习》,2019 年。
更正式地说,我们可以将我们希望优化的函数表示为:
error = f(weights)
通过计算误差相对于权重的变化率或斜率,梯度下降算法可以决定如何改变权重以继续减少误差。
为何微积分在机器学习中有效
我们考虑优化的误差函数相对简单,因为它是凸的,且具有单一的全局最小值。
尽管如此,在机器学习的背景下,我们通常需要优化更复杂的函数,这使得优化任务变得非常具有挑战性。如果函数的输入也是多维的,优化可能会变得更加困难。
微积分为我们提供了解决这两种挑战所需的工具。
假设我们有一个更通用的函数,希望将其最小化,该函数接受一个实数输入x,并产生一个实数输出y:
y = f(x)
在不同的x值处计算变化率是有用的,因为这能指示我们需要对x进行的变化,以获得y的相应变化。
由于我们在最小化函数,我们的目标是找到一个使 f(x)值尽可能低且具有零变化率的点;因此,这是一个全局最小值。根据函数的复杂性,这可能不一定可行,因为可能存在许多局部最小值或鞍点,优化算法可能会被困在其中。
在深度学习的背景下,我们优化的函数可能有许多局部最小值,这些局部最小值并不理想,还有许多被非常平坦区域包围的鞍点。
第 84 页,《深度学习》,2017 年。
因此,在深度学习的背景下,我们通常接受一个可能不一定对应全局最小值的次优解,只要它对应一个非常低的 f(x)值。
成本函数的折线图显示局部和全局最小值
摘自《深度学习》
如果我们处理的函数有多个输入,微积分还为我们提供了偏导数的概念;或者更简单地说,计算y相对于每一个输入*x**[i]*变化的变化率,同时保持其他输入不变的方法。
这就是为什么在梯度下降算法中,每个权重独立更新的原因:权重更新规则依赖于每个权重的 SSE 偏导数,由于每个权重都有不同的偏导数,因此每个权重都有单独的更新规则。
第 200 页,《深度学习》,2019 年。
因此,如果我们再次考虑误差函数的最小化,计算误差相对于每个特定权重的偏导数允许每个权重独立于其他权重进行更新。
这也意味着梯度下降算法可能不会沿着误差表面沿直线下降。相反,每个权重将根据误差曲线的局部梯度进行更新。因此,一个权重可能比另一个权重更新得更多,以便梯度下降算法达到函数的最小值。
进一步阅读
本节提供了更多关于该主题的资源,如果你想深入了解。
书籍
总结
在本教程中,你了解了微积分在机器学习中的核心作用。
具体来说,你学到了:
-
微积分在理解机器学习算法的内部机制中扮演着重要角色,例如,梯度下降算法根据变化率的计算来最小化误差函数。
-
微积分中变化率的概念也可以用来最小化更复杂的目标函数,这些函数不一定是凸形的。
-
偏导数的计算是微积分中的另一个重要概念,它使我们能够处理多个输入的函数。
你有任何问题吗?
在下面的评论中提问,我会尽力回答。*****
轻松介绍连续函数
微积分的许多领域需要了解连续函数。连续函数的特性以及对不连续点的研究对数学界非常感兴趣。由于其重要的属性,连续函数在机器学习算法和优化方法中有实际应用。
在本教程中,你将发现什么是连续函数,它们的性质,以及在优化算法研究中两个重要的定理,即中间值定理和极值定理。
完成本教程后,你将了解到:
-
连续函数的定义
-
中间值定理
-
极值定理
让我们开始吧。
轻松介绍连续函数 由 Jeeni Khala 拍摄,版权所有。
教程概述
本教程分为 2 部分,它们是:
-
连续函数的定义
-
非正式定义
-
正式定义
-
-
定理
-
中间值定理
-
极值定理
-
先决条件
本教程需要了解极限的概念。为了刷新你的记忆,你可以查看 极限与连续性,其中也简要定义了连续函数。在本教程中,我们将深入探讨。
我们还将使用区间。因此,方括号表示闭区间(包括边界点),而圆括号表示开区间(不包括边界点),例如,
-
[a,b] 意味着 a<=x<=b
-
(a,b) 意味着 a<x<b
-
[a,b) 意味着 a<=x<b
从上面你可以注意到,一个区间可以在一侧是开区间,在另一侧是闭区间。
最后,我们将仅讨论定义在实数上的实函数。我们不会讨论复数或定义在复平面上的函数。
连续函数的非正式定义
假设我们有一个函数 f(x)。如果我们可以在不抬起手的情况下绘制 f(x) 的图形,那么我们可以很容易地检查它在两个点 a 和 b 之间是否是连续的。例如,考虑一个定义为:
f(x)=2x+1
我们可以在 [0,1] 之间绘制这条直线而不抬起手。事实上,我们可以在任何两个 x 值之间绘制这条直线而不需要抬起手(见下图)。因此,这个函数在整个实数域上是连续的。现在让我们看看当我们绘制 ceiling 函数时会发生什么:
连续函数(左),以及非连续函数(右)
例如,ceil 函数在区间 (0,1] 上的值为 1,比如 ceil(0.5)=1,ceil(0.7)=1,等等。因此,该函数在区间 (0,1] 上是连续的。如果我们将区间调整为 (0,2],那么当 x>1 时,ceil(x) 跳跃到 2。为了在区间 (0,2] 上绘制 ceil(x),我们现在必须抬起手,并从 x=2 开始重新绘制。因此,ceil 函数不是一个连续函数。
如果函数在整个实数域上是连续的,那么它就是一个整体连续函数;否则,它不是整体连续的。对于后者类型的函数,我们可以检查它们在什么区间上是连续的。
一个正式的定义
函数 f(x) 在点 a 处是连续的,如果当 x 接近 a 时,函数的值接近 f(a)。因此,为了测试函数在点 x=a 处的连续性,请检查以下内容:
-
f(a) 应该存在
-
f(x) 在 x 接近 a 时有一个极限
-
f(x) 在 x->a 时的极限等于 f(a)
如果上述所有条件都成立,那么该函数在点 a 处是连续的。
示例
一些示例列在下面,并在图中显示:
-
f(x) = 1/x 在 x=0 处未定义,因此不连续。然而,函数在 x>0 的区间内是连续的。
-
所有多项式函数都是连续函数。
-
三角函数 sin(x) 和 cos(x) 是连续的,并在 -1 和 1 之间振荡。
-
三角函数 tan(x) 不是连续的,因为它在 x=???/2, x=-???/2 等处未定义。
-
sqrt(x) 在 x<0 时未定义,因此不连续。
-
|x| 在任何地方都是连续的。
连续函数和具有不连续性的函数的示例
连续性与函数导数的关系
从极限的连续性定义出发,我们有一个替代定义。f(x) 在 x 处是连续的,如果:
当 (h→0) 时,f(x+h)-f(x)→ 0
让我们看一下导数的定义:
f’(x) = lim(h→0) (f(x+h)-f(x))/h
因此,如果 f’(x) 在点 a 处存在,则函数在 a 处是连续的。反之则不总是成立。一个函数可能在点 a 处是连续的,但 f’(a) 可能不存在。例如,在上面的图中 |x| 在任何地方都是连续的。我们可以在不抬起手的情况下绘制它,但在 x=0 处,由于曲线的急剧转折,其导数并不存在。
中间值定理
中间值定理表明:
如果:
-
函数 f(x) 在 [a,b] 上是连续的
-
并且 f(a) <= K <= f(b)
那么:
- 在 a 和 b 之间存在一个点 c,即 a<=c<=b,使得 f© = K
用非常简单的话来说,这个定理表明,如果一个函数在 [a,b] 上是连续的,那么该函数在 f(a) 和 f(b) 之间的所有值都会存在于这个区间内,如下图所示。
中间值定理的插图(左)和极值定理(右)
极值定理
该定理表明:
如果:
- 函数 f(x)在[a,b]上是连续的
那么:
-
在区间[a,b]内有点 x_min 和 x_max,即:
-
a<=x_min<=b
-
a<=x_max<=b
-
-
并且函数 f(x)具有最小值 f(x_min)和最大值 f(x_max),即:
- 当 a<=x<=b 时,f(x_min)<=f(x)<=f(x_max)
简单来说,连续函数在一个区间内总是有最小值和最大值,如上图所示。
连续函数与优化
连续函数在优化问题的研究中非常重要。我们可以看到,极值定理保证了在一个区间内,总会有一个点使得函数具有最大值。最小值也是如此。许多优化算法源自这一基本属性,并能执行惊人的任务。
扩展
本节列出了一些你可能希望探索的扩展教程的想法。
-
收敛和发散序列
-
基于无穷小常数的 Weierstrass 和 Jordan 连续函数定义
如果你探索了这些扩展内容,我很想知道。请在下面的评论中分享你的发现。
进一步阅读
本节提供了更多关于该主题的资源,如果你想深入了解。
教程
资源
- 关于机器学习的微积分书籍的额外资源
书籍
-
托马斯微积分,第 14 版,2017 年(基于 George B. Thomas 的原著,由 Joel Hass、Christopher Heil、Maurice Weir 修订)
-
微积分,第 3 版,2017 年(Gilbert Strang)
-
微积分,第 8 版,2015 年(James Stewart)
总结
在本教程中,你发现了连续函数的概念。
具体来说,你学到了:
-
什么是连续函数
-
连续函数的正式和非正式定义
-
不连续点
-
中间值定理
-
极值定理
-
为什么连续函数很重要
你有任何问题吗?
在下面的评论中提出你的问题,我会尽力回答。
正弦和余弦的导数
原文:
machinelearningmastery.com/derivative-of-the-sine-and-cosine/
许多机器学习算法涉及不同目的的优化过程。优化是指通过改变输入值来最小化或最大化目标函数的问题。
优化算法依赖于导数来理解如何改变(增加或减少)目标函数的输入值,以最小化或最大化目标函数。因此,考虑中的目标函数必须是可导的。
两个基本的三角函数,即正弦和余弦,为理解求导的操作提供了良好的机会。这两个函数变得特别重要,如果我们将它们视为更复杂函数的基本构建块。
在本教程中,你将发现如何找到正弦和余弦函数的导数。
完成本教程后,你将了解:
-
如何通过应用代数、三角学和极限中的几个规则来找到正弦和余弦函数的导数。
-
如何在 Python 中求正弦函数和余弦函数的导数。
让我们开始吧。
正弦和余弦的导数
图片由 Tim Marshall 提供,部分版权保留。
教程概述
本教程分为三部分,它们是:
-
正弦函数的导数
-
余弦函数的导数
-
在 Python 中求导
正弦函数的导数
某个函数 f 在特定点 x 的导数 f’(x) 可以定义为:
我们将从考虑正弦函数开始。因此,首先将 f(x) = sin x 代入:
如果我们查看三角恒等式,我们发现可以应用加法公式来展开 sin(x + h) 项:
sin(x + y) = sin x cos y + cos x sin y
确实,通过将 y 替换为 h,我们可以定义 sin x 的导数为:
我们可以通过应用限制法则进一步简化表达式,该法则指出函数和的极限等于其极限的和:
我们可以进一步简化,通过提取任何与 x 相关的共同因子。这样,我们可以将表达式因式分解以得到两个不依赖于 x 的独立极限的和:
求解这两个极限中的每一个将给出sin x的导数。
让我们从处理第一个极限开始。
回顾 我们可以在单位圆上以弧度表示角度 h。则 h 的正弦值由垂直于 x 轴的 BC 表示,该点与单位圆相交:
在单位圆上表示角度 h
我们将比较不同扇形和三角形的面积,边缘与角h相对,以推测当h的值接近零时,((sin h) / h) 的行为。为此,首先考虑扇形 OAB 的面积:
计算扇形 OAB 的面积
扇形的面积可以用圆的半径 r 和弧长 AB,即 h,来定义。由于考虑的圆是 单位 圆,因此 r = 1:
area_of_sector_OAB = r h / 2 = h / 2
我们可以将我们刚刚找到的扇形 OAB 的面积与同一扇形内的 三角形 OAB 的面积进行比较。
计算三角形 OAB 的面积
这个三角形的面积是以其高度 BC = sin h 和底边长度 OA = 1 为定义的:
area_of_triangle_OAB = (BC) (OA) / 2 = (sin h) / 2
由于我们可以清楚地看到,我们刚才考虑的三角形 OAB 的面积小于它所包含的扇形的面积,因此我们可以说:
(sin h) / 2 < h / 2
(sin h) / h < 1
这是我们获得的关于((sin h) / h)的行为的第一条信息,这告诉我们它的上限值不会超过 1。
现在我们考虑第二个三角形 OAB’,其面积大于扇形 OAB 的面积。我们可以使用这个三角形来提供关于((sin h) / h) 的第二条信息,即它的下限值:
比较相似的三角形 OAB 和 OAB’
应用相似三角形的性质将 OAB’ 关联到 OCB,提供了计算三角形面积所需的长度 B’A 的信息:
B’A / OA = BC / OC = (sin h) / (cos h)
因此,三角形 OAB’ 的面积可以计算为:
area_of_triangle_OAB’ = (B’A) (OA) / 2 = (sin h) / (2 cos h)
比较三角形 OAB’ 和扇形 OAB 的面积,我们可以看到前者现在更大:
h / 2 < (sin h) / (2 cos h)
cos h < (sin h) / h
这是我们所需的第二条信息,它告诉我们 ((sin h) / h) 的下界值不会低于 cos h。我们还知道,随着 h 趋近于 0,cos h 的值趋近于 1。
因此,将这两条信息结合起来,我们发现随着 h 越来越小,((sin h) / h) 的值被其上下界限 挤压 到 1。这实际上被称为 挤压 或 夹挤 定理。
现在我们继续解决第二个极限。
通过应用标准的代数规则:
我们可以如下操作第二个极限:
我们可以通过应用三角学中的毕达哥拉斯恒等式 sin² h = 1 – cos² h 来用正弦表达这个极限:
随后应用另一种极限法则,该法则指出乘积的极限等于各个极限的乘积:
我们已经解决了这个乘积的第一个极限,并发现其值为 1。
这个乘积的第二个极限的特征是分母中有一个 cos h,随着 h 的减小,cos h 接近 1。因此,第二个极限的分母随着 h 趋近于 0,接近值 2。另一方面,分子中的正弦项在 h 趋近于 0 时达到 0。这不仅使第二个极限,也使整个乘积极限趋向于 0:
综合考虑所有因素,我们最终可以得出以下结论:
sin’(x) = (1) (cos x) + (0) (sin x)
sin’(x) = cos x
这最终告诉我们 sin x 的导数就是 cos x。
余弦函数的导数
同样,我们可以通过重新利用找到正弦函数导数的知识来计算余弦函数的导数。将 f(x) = cos x 代入:
现在应用加法公式来展开 cos(x + h) 项,如下所示:
cos(x + y) = cos x cos y + sin x sin y
这又导致了两个极限的求和:
我们可以很快发现,我们已经在寻找正弦函数导数的过程中评估了这两个极限;第一个极限趋近于 1,而第二个极限趋近于 0,随着 h 的值变小:
cos’(x) = (1) (-sin x) + (0) (cos x)
cos’(x) = -sin x
这最终告诉我们余弦函数的导数恰好是 -sin x。
我们刚刚找到的导数的重要性在于它们定义了函数在某个特定角度 h 下的变化率。例如,如果我们回顾周期性正弦函数的图形,我们可以观察到它的第一个正峰值恰好与 π / 2 弧度的角度重合。
周期性正弦函数的线性图
我们可以利用正弦函数的导数来直接计算图表上这个峰值处切线的变化率或斜率:
sin’(π / 2) = cos(π / 2) = 0
我们发现这一结果与正弦函数的峰值确实是一个变化率为零的静止点这一事实相符。
类似的练习可以很容易地进行,以计算不同角度下切线的变化率,适用于正弦和余弦函数。
在 Python 中求导
在这一部分,我们将使用 Python 计算正弦和余弦函数的导数。
为此,我们将利用 SymPy 库,它允许我们以符号形式处理数学对象的计算。这意味着 SymPy 库将使我们能够定义和操作未评估变量的正弦和余弦函数。我们可以通过使用 Python 中的 symbols 来定义变量为符号,而求导则使用 diff 函数。
在进一步操作之前,我们首先加载所需的库。
from sympy import diff
from sympy import sin
from sympy import cos
from sympy import symbols
现在,我们可以定义一个符号形式的变量 x,这意味着我们可以使用 x 而不需要为其赋值。
# define variable as symbol
x = symbols('x')
接下来,我们可以使用diff
函数找出正弦和余弦函数关于x的导数。
# find the first derivative of sine and cosine with respect to x
print('The first derivative of sine is:', diff(sin(x), x))
print('The first derivative of cosine is:', diff(cos(x), x))
我们发现diff
函数正确地返回了cos(x)作为正弦的导数,以及–sin(x)作为余弦的导数。
Python
The first derivative of sine is: cos(x)
The first derivative of cosine is: -sin(x)
diff
函数也可以进行多次导数。例如,我们可以通过将x传递两次来找出正弦和余弦的第二导数。
# find the second derivative of sine and cosine with respect to x
print('The second derivative of sine is:', diff(sin(x), x, x))
print('The second derivative of cosine is:', diff(cos(x), x, x))
这意味着,在寻找第二导数时,我们实际上是在计算每个函数的导数的导数。例如,要找出正弦函数的第二导数,我们需要对cos(x),即它的第一次导数,进行导数计算。我们也可以通过类似的方式计算余弦函数的第二导数,即对–sin(x),它的第一次导数,进行导数计算。
The second derivative of sine is: -sin(x)
The second derivative of cosine is: -cos(x)
我们还可以将数字 2 传递给diff
函数,以指示我们感兴趣于找到第二导数。
# find the second derivative of sine and cosine with respect to x
print('The second derivative of sine is:', diff(sin(x), x, 2))
print('The second derivative of cosine is:', diff(cos(x), x, 2))
将这些内容结合起来,下面列出了寻找正弦和余弦函数导数的完整示例。
# finding the derivative of the sine and cosine functions
from sympy import diff
from sympy import sin
from sympy import cos
from sympy import symbols
# define variable as symbol
x = symbols('x')
# find the first derivative of sine and cosine with respect to x
print('The first derivative of sine is:', diff(sin(x), x))
print('The first derivative of cosine is:', diff(cos(x), x))
# find the second derivative of sine and cosine with respect to x
print('\nThe second derivative of sine is:', diff(sin(x), x, x))
print('The second derivative of cosine is:', diff(cos(x), x, x))
# find the second derivative of sine and cosine with respect to x
print('\nThe second derivative of sine is:', diff(sin(x), x, 2))
print('The second derivative of cosine is:', diff(cos(x), x, 2))
进一步阅读
本节提供了更多的资源,如果你希望深入了解这个主题。
书籍
总结
在本教程中,你发现了如何找出正弦和余弦函数的导数。
具体来说,你学到了:
-
如何通过应用代数、三角学和极限的一些规则来找出正弦和余弦函数的导数。
-
如何在 Python 中找到正弦和余弦函数的导数。
你有任何问题吗?
在下面的评论中提出你的问题,我会尽力回答。
微分与积分学 – 针对任何事物进行微分
积分学是牛顿和莱布尼茨的伟大发现之一。他们的工作独立地证明了微积分基本定理的重要性,并认可了它将积分与导数联系起来。通过积分的发现,之后可以研究面积和体积。
积分学是我们将要探索的微积分旅程的第二部分。
在本教程中,你将发现微分与积分学之间的关系。
完成本教程后,你将了解:
-
微分和积分学的概念通过微积分基本定理相互关联。
-
通过应用微积分基本定理,我们可以计算积分来找到曲线下的面积。
-
在机器学习中,积分学的应用可以为我们提供一个评估分类器性能的指标。
让我们开始吧。
微分与积分学 – 针对任何事物进行微分
照片由Maxime Lebrun提供,版权所有。
教程概述
本教程分为三部分,它们是:
-
微分与积分学 – 什么是联系?
-
微积分基本定理
-
扫描面积类比
-
微积分基本定理 – 第一部分
-
微积分基本定理 – 第二部分
-
-
积分示例
-
积分在机器学习中的应用
微分与积分学 – 什么是联系?
在我们到目前为止的微积分旅程中,我们了解到微分学涉及变化率的测量。我们还发现了微分,并将其应用于从基本原理出发的不同函数。我们甚至理解了如何运用规则更快地得到导数。
但我们才刚刚走到一半。
从 21 世纪的视角看,微积分通常被视为变化的数学。它使用两个主要概念来量化变化:导数和积分。导数建模变化率…… 积分建模变化的积累……
– 第 141 页,《无限的力量》,2020 年。
回顾计算包括两个阶段:切割和重建。
切割阶段将曲线形状分解为极其小且直的片段,这些片段可以单独研究,例如,通过应用导数来建模其变化率或斜率。
微积分之旅的这一部分被称为微分微积分,我们已经详细研究过。
重建阶段将极其小且直的片段汇总,试图重新组合以研究原始整体。通过这种方式,我们可以在将其切割成无限薄的片段后,确定规则和不规则形状的面积或体积。我们接下来将探讨微积分之旅的第二部分。它被称为积分微积分。
将这两个概念联系在一起的重要定理被称为微积分基本定理。
微积分基本定理
为了更好地理解微积分基本定理,让我们回顾一下汽车位置和速度示例:
汽车位置随时间变化的线图
汽车速度随时间变化的线图
在计算导数时,我们解决了前向问题,即通过位置图的斜率找到了速度。t。但如果我们想解决后向问题,即给定速度图v(t),希望找到行驶的距离呢?解决这个问题的方法是计算曲线下的面积(阴影区域),直到时间t:
阴影区域是曲线下的面积
我们没有具体的公式来直接定义阴影区域的面积。但我们可以应用微积分的数学,将曲线下的阴影区域切割成许多无限薄的矩形,对于这些矩形我们有一个公式:
将阴影区域划分为许多宽度为Δt 的矩形
如果我们考虑第i个矩形,它被任意选择来覆盖时间间隔Δt,我们可以将其面积定义为其长度乘以宽度:
area_of_rectangle = v(t*[i]) Δt**[i]*
我们可以拥有足够多的矩形来覆盖感兴趣的区间,在这种情况下,就是曲线下的阴影区域。为简便起见,我们将这个闭区间表示为[a, b]。找出这个阴影区域的面积(因此也是行进的距离),就等于求数量为 n的矩形的和:
total_area = v(t[0]) Δt[0] + v(t[1]) Δt[1] + … + v(t[n]) Δt[n]
我们可以通过应用带有 sigma 符号的黎曼和来更紧凑地表达这个总和:
如果我们通过有限数量的矩形来切分(或划分)曲线下方的区域,我们会发现黎曼和给出了这个区域的近似值,因为这些矩形无法完全贴合曲线下的区域。如果我们需要将矩形的左上角或右上角放置在曲线上,黎曼和将分别给出真实面积的低估或高估。如果每个矩形的中点必须接触曲线,那么矩形超出曲线的部分大致补偿了曲线与相邻矩形之间的间隙:
用左和法来近似曲线下的面积
用右和法来近似曲线下的面积
用中点和法来近似曲线下的面积
找到曲线下确切面积的解决方法是将矩形的宽度减少到无限薄(回想一下微积分中的无穷大原则)。这样,矩形将覆盖整个区域,求和它们的面积就可以得到定积分。
定积分(“简单”定义):曲线在 t = a 和 t = b 之间的确切面积由定积分给出,该积分被定义为黎曼和的极限……
– 第 227 页, 《傻瓜微积分》, 2016.
因此,定积分可以通过黎曼和在矩形的数量n趋近于无穷大时定义。我们也将曲线下的区域表示为A(t)。然后:
注意符号现在变成了积分符号∫,取代了西格玛Σ。这一变化的原因只是为了表示我们在对大量薄切矩形进行求和。左侧的表达式读作,从a到b的v(t)的积分,找到积分的过程称为积分。
扫动区域类比
也许一个更简单的类比来帮助我们将积分与微分联系起来,是想象拿着一片薄切片,并在曲线下以极小的步幅向右拖动。当它向右移动时,薄切片将在曲线下扫过一个更大的区域,同时其高度会根据曲线的形状变化。我们想要回答的问题是,当薄片向右扫过时,区域积累的速率是多少?
让dt表示扫动切片所经过的每个无穷小步长,而v(t)表示任何时间t的高度。那么,这个薄片的无穷小区域dA(t)可以通过将其高度v(t)乘以其无穷小宽度dt来找到:
dA(t) = v(t) dt
将方程除以dt,我们得到A(t)的导数,并告诉我们区域积累的速率等于曲线的高度,v(t),在时间t:
dA(t) / dt = v(t)
我们终于可以定义微积分基本定理。
微积分基本定理 – 第一部分
我们发现一个区域,A(t),在一个函数v(t)下扫过,可以定义为:
我们还发现区域被扫过的速率等于原始函数v(t):
dA(t) / dt = v(t)
这引出了微积分基本定理的第一部分,它告诉我们如果v(t)在区间[a,b]上是连续的,并且它也是A(t)的导数,那么A(t)是v(t)的原函数:
A’(t) = v(t)
或者更简单地说,积分是微分的逆操作。因此,如果我们首先对v(t)进行积分,然后对结果进行微分,我们将得到原始函数v(t):
微积分基本定理 – 第二部分
定理的第二部分给出了计算积分的捷径,而不必通过计算黎曼和的极限来走更长的路。
它指出,如果函数v(t)在区间[a,b]上是连续的,那么:
这里,F(t) 是v(t)的任意一个不定积分,积分被定义为在a和b处的不定积分值的差。
因此,定理的第二部分通过从某个起始点C和下限a处的曲线下面积减去相同起始点C和上限b处的面积来计算积分。这有效地计算了a到b之间感兴趣的区域的面积。
由于常数C定义了扫描开始时x轴上的点,最简单的不定积分考虑的是C = 0 的情况。然而,任何带有C任意值的不定积分都可以使用,这只是将起始点设置在x轴上不同位置而已。
积分示例
考虑函数v(t) = x³。通过应用幂函数法则,我们可以轻松找到其导数,v’(t) = 3x²。3x²的不定积分再次是x³ — 我们执行反向操作以获得原始函数。
现在假设我们有一个不同的函数,g(t) = x³ + 2。它的导数也是 3x²,同样另一个函数h(t) = x³ – 5 也是如此。这些函数(以及其他类似的函数)都有x³作为它们的不定积分。因此,我们通过不定积分指定了所有 3x²的不定积分的家族:
不定积分不定义计算曲线下面积的界限。常数C被包括在内是为了补偿对界限或扫描起始点缺乏信息的情况。
如果我们知道界限,那么我们可以简单地应用第二基本定理来计算定积分:
在这种情况下,我们可以将C简单地设置为零,因为这不会改变结果。
在机器学习中应用积分
我们考虑了汽车的速度曲线v(t)作为一个熟悉的例子,以理解积分和导数之间的关系。
但是,你可以使用这种矩形面积累加方案来累加任何微小的部分 —— 距离、体积或能量,例如。换句话说,曲线下的面积不一定代表实际的面积。
– 第 214 页,《Dummies 的微积分》,2016 年。
成功应用机器学习技术的一个重要步骤是选择适当的性能度量。例如,在深度学习中,常见的做法是衡量精度和召回率。
精确度是模型报告的检测中正确的分数,而召回率是检测到的真实事件的分数。
– 第 423 页,《深度学习》,2017 年。
这也是一种常见做法,然后在精确-召回(PR)曲线上绘制精确度和召回率,将召回率放在x轴上,精确度放在y轴上。希望分类器既有高召回率又有高精确度,这意味着分类器能够正确检测许多真实事件。这样的良好分类性能将通过 PR 曲线下的较大面积来描述。
你可能已经能够猜到接下来会发生什么。
PR 曲线下的面积确实可以通过应用积分微积分来计算,从而允许我们描述分类器的性能。
深入阅读
如果你希望更深入地了解这个主题,本节提供了更多资源。
书籍
-
《单变量与多变量微积分》,2020 年。
-
《微积分入门》,2016 年。
-
《无限的力量》,2020 年。
-
《求学者的微积分指南》,2019 年。
-
《深度学习》,2017 年。
总结
在本教程中,你发现了微积分的微分和积分之间的关系。
具体来说,你学到了:
-
微积分的微分和积分概念由微积分基本定理联系在一起。
-
通过应用微积分基本定理,我们可以计算积分以找到曲线下的面积。
-
在机器学习中,应用积分微积分可以为我们提供一个度量标准,用来评估分类器的性能。
你有什么问题吗?
在评论区留言您的问题,我将尽力回答。
使用 ChatGPT 生成图示
原文:
machinelearningmastery.com/generating-graphics-with-chatgpt/
经过适当内容训练的大型语言模型可以生成的不仅仅是英文文本。例如,ChatGPT 已知能够生成多种编程语言的代码。事实上,你还可以让 ChatGPT 生成其他内容,如图片。在这篇文章中,你将学习到
-
如何让 ChatGPT 生成块图和序列图
-
制作 ChatGPT 为你创建图示的一般规则
开始使用并应用 ChatGPT,可以参考我的书籍《最大化生产力与 ChatGPT》。它提供了实际使用案例和提示示例,旨在帮助你快速使用 ChatGPT。
使用 ChatGPT 生成图示
图片由作者使用 Stable Diffusion 生成。保留部分权利。
概述
本文分为三部分;它们是
-
构建系统设计块图
-
构建序列图
-
图形生成的限制和技巧
构建系统设计块图
在今天的软件行业中,考虑可扩展性是不可避免的。这意味着一个相当大的系统必须被拆分成更小的部分,并在分隔的硬件上运行。这些部分将通过网络协作完成任务。这与互联网前时代的情况形成对比,当时软件设计是为了在单一计算机上安装和运行的。
让我们考虑一个可以与移动应用交互的基于云的文件存储系统。如果你在互联网搜索,不难发现如何构建这样一个系统以支持大量用户。但是,一图胜千言。你可以向 ChatGPT 描述这样的系统,并要求它生成一张图片。提示可以是:
一个云文件存储服务包含以下组件:
一个包含本地数据库、索引控制器、块控制器和监视器组件的移动客户端
控制器和监视器组件通过负载均衡器与服务器端进行交互。
服务器端有一个通知服务器,向客户端推送如文件更新的消息,客户端的监视组件将处理这些消息。
文件的上传和下载由一个文件处理服务器处理,这些文件被索引并拆分成块。这些块存储在云存储中。
文件的元数据由元数据服务器处理,并存储在元数据数据库中。
所有这些操作都通过基于 Kafka 构建的消息队列进行流畅处理。
请使用 Mermaid 语法为此创建一个块图。
构建这样的提示有两个关键属性:
-
你明确列出系统组件及其如何相互作用。
-
你请求使用 Mermaid 语法来生成图示。
详细说明组件应该包括哪些内容以及如何交互对于获得准确的图示是重要的。然而,ChatGPT 可以生成文本,但不能生成图形。为了获得图示,你需要一种图形生成语言,它可以以纯文本形式呈现。Mermaid.js就是一个例子。
ChatGPT 的回应如下:
当然!这是一个表示云文件存储服务中组件及其交互的块图:
在这个图示中,移动客户端包括本地数据库、索引控制器、块控制器和观察者组件。这些组件通过负载均衡器与服务器端组件交互。服务器端包括控制器、文件处理服务器、元数据服务器和通知服务器。文件处理服务器处理文件的上传和下载,将其拆分成块并存储在云存储中。元数据服务器处理文件的元数据,并将其存储在元数据库中。通知服务器将消息(如文件更新)推送到客户端,由观察者组件处理。所有这些操作都通过基于 Kafka 的消息队列进行流线化。
请注意,这只是一个简化的表示,具体的云文件存储服务可能会有额外的组件或交互。
响应中的代码块是 Mermaid.js 语法的图示。如果你将其复制到Mermaid Live Editor在线编辑器中,结果如下:
Mermaid 是一个 JavaScript 库,可以在网页上呈现各种图形。你可以进一步润色 Mermaid 代码,以添加颜色或将块移动到画布上的不同位置。然而,如果你需要系统的可视化,ChatGPT 已经提供了很大的帮助。
实际上,你可以将这种技术与其他技术结合使用,例如向 ChatGPT 提供系统的高层目标,并让它告诉你系统组件。然后在后续提示中,请求 ChatGPT 将其转换成图示。
你可以尝试以下提示作为示例:
社交媒体如 Twitter 背后的系统组件是什么,它们如何交互?
然后在后续提示中,
请提供上述内容的 Mermaid 语法块图。
构建时序图
作为另一个示例,让我们让 ChatGPT 生成一个时序图。这是软件工程中另一种常用的图形,用于描述不同组件在时间线中的交互。
与上述相对,让我们让 ChatGPT 在同一提示中找出组件和交互并生成图示:
用户如何与 web 应用程序交互并使用 OAuth2 登录?请生成一个 PlantUML 语法的时序图进行解释。
OAuth2 是一种常见的网页应用认证方式,网页应用服务器无需你创建账户,而是使用其他平台的账户。例如,你可以使用你的 Google 账户登录 ChatGPT。Google 检查你的密码,但应用程序(ChatGPT)并不属于 Google。这个过程涉及多个参与方。
以下是 ChatGPT 如何向你解释这个过程的:
当然!我可以帮助你生成一个 PlantUML 语法的时序图,以说明用户如何与网页应用互动并使用 OAuth2 登录。这里是图示:
在这个图中,步骤如下:
1. 用户访问网页应用。
2. 网络应用向用户展示登录按钮。
3. 用户点击登录按钮。
4. 网络应用将用户重定向到 OAuth2 提供者。
5. 用户在 OAuth2 提供者的登录页面上输入凭据。
6. OAuth2 提供者验证用户的凭据。
7. OAuth2 提供者将用户重定向回网络应用,并附带授权码。
8. 网络应用将授权码发送给 OAuth2 提供者。
9. OAuth2 提供者将授权码兑换为访问令牌。
10. OAuth2 提供者将访问令牌发送回网络应用。
11. 网络应用使用访问令牌登录用户。
请注意,这张图提供了 OAuth2 登录过程的高级概述,可能没有包含协议或具体实现细节的所有复杂性。它作为一般流程的简化表示。
在这里,你要求使用不同的“语言”来表示图形语法:PlantUML。你可以复制上面的代码并在 PlantUML 在线服务器 上运行。你得到的图像如下:
时序图解释了登录和认证是如何发生的以及访问令牌是如何创建的。
请注意,这之所以有效,是因为 ChatGPT 能准确说明这个过程如何运作。如果你的过程过于复杂或 ChatGPT 不熟悉,你应在提示中提供不同组件如何互动的详细信息,并要求 ChatGPT 将你的描述转换为图形语言。
图形生成的限制和提示
作为一种语言模型,其训练数据在很大程度上限制了其能力。生成图形可能不是构建 ChatGPT 的主要兴趣。众所周知,ChatGPT 在某些图形方面表现较弱,例如电子电路的原理图。
还要注意,如果你要求 ChatGPT 给你一个图示,它默认假设你指的是某种“ASCII 艺术”,这通常看起来不对。因此,指定使用某种图形语言并将输出渲染为图形是至关重要的。以下是一些示例:
-
Mermaid,正如你在上面的第一个示例中看到的,可以制作流程图、时序图、实体-关系图、甘特图和思维导图。
-
如上例所示,PlantUML 可以制作许多 UML 图,包括时序图、状态图和类图。
-
对于其他简单图形(例如仅包含节点和箭头的图形),你可以询问 Graphviz 语法,也称为“dot 语言”。
-
对于通用图形,你可以询问 TikZ 语法,它是 LaTeX 中的一个包。
-
对于电路图,有 circuitikz 这是 TikZ 的一个专门版本。
概要
在这篇文章中,你了解到 ChatGPT 不仅可以生成文本,还可以生成图形,尽管是以某种图形语言的形式。具体来说,你看到 ChatGPT 可以
-
生成一个块图,根据你的描述描绘不同方的互动。
-
生成一个时序图来解释复杂的逻辑,以回答你的问题。
最重要的是,使 ChatGPT 生成图形的关键是提供足够的图形生成细节。你应该指定格式(例如,使用 Mermaid 语法),并提供关于可视化内容的足够细节。
高阶导数
高阶导数能够捕捉一阶导数无法捕捉到的信息。
一阶导数可以捕捉重要信息,例如变化率,但单独使用时无法区分局部最小值或最大值,在这些点的变化率为零。若干优化算法通过利用高阶导数来解决这一限制,例如在牛顿法中,使用二阶导数来达到优化函数的局部最小值。
在本教程中,你将学习如何计算高阶的单变量和多变量导数。
完成本教程后,你将了解:
-
如何计算单变量函数的高阶导数。
-
如何计算多变量函数的高阶导数。
-
二阶导数如何通过二阶优化算法在机器学习中得到利用。
让我们开始吧。
高阶导数
图片由Jairph提供,保留部分权利。
教程概述
本教程分为三个部分,它们是:
-
单变量函数的高阶导数
-
多变量函数的高阶导数
-
在机器学习中的应用
单变量函数的高阶导数
除了一阶导数,我们已经看到它能提供有关函数的重要信息,例如其瞬时变化率,更高阶的导数也同样有用。例如,二阶导数可以测量一个移动物体的加速度,或者它可以帮助优化算法区分局部最大值和局部最小值。
计算单变量函数的高阶(第二阶、第三阶或更高阶)导数并不难。
函数的二阶导数只是其一阶导数的导数。三阶导数是二阶导数的导数,四阶导数是三阶导数的导数,以此类推。
– 第 147 页,傻瓜微积分,2016 年。
因此,计算高阶导数只是涉及到对函数的重复微分。为了做到这一点,我们可以简单地应用我们对幂规则 的知识。以函数 f(x) = x³ + 2x² – 4x + 1 为例:
一阶导数:f’(x) = 3x² + 4x – 4
二阶导数:f’’(x) = 6x + 4
三阶导数:f’’’(x) = 6
第四阶导数:f^((4))(x) = 0
第五阶导数:f^((5))(x) = 0 等
我们所做的是首先对 f(x) 应用幂规则以获得其一阶导数 f’(x),然后对一阶导数应用幂规则以获得二阶导数,如此继续。导数最终会因为重复微分而趋于零。
乘积和商的规则 的应用在求取高阶导数时仍然有效,但随着阶数的增加,其计算会变得越来越复杂。一般的莱布尼兹规则在这方面简化了任务,将乘积规则推广为:
这里,术语 n! / k!(n – k)! 是来自二项式定理的二项式系数,而 f(*k*^) 和 g(*k*^) 表示函数 f 和 g 的 k^(th) 导数。
因此,按照一般的莱布尼兹规则,找到一阶和二阶导数(因此,分别替代 n = 1 和 n = 2),我们得到:
(fg)^((1)) = (fg)’ = f^((1)) g + f g^((1))
(fg)^((2)) = (fg)’’ = f^((2)) g + 2f^((1)) g^((1)) + f g^((2))
注意到乘积规则定义的一阶导数。莱布尼兹规则也可以用来寻找有理函数的高阶导数,因为商可以有效地表达为形式为 f g^(-1) 的乘积。
多变量函数的高阶导数
高阶偏导数 的定义对于多变量函数 类似于一变量情况:n^(th) 阶偏导数对于 n > 1,是计算 (n – 1)^(th) 阶偏导数的偏导数。例如,对具有两个变量的函数进行二阶偏导数运算,会得到四个二阶偏导数:两个 自身 偏导数 f*[xx]* 和 f*[yy],以及两个交叉偏导数 f*[xy] 和 f*[yx]*。
为了进行“导数”,我们必须对 x 或 y 进行偏导数,并且有四种方式:先对 x,然后对 x,先对 x,然后对 y,先对 y,然后对 x,先对 y,然后对 y。
– 第 371 页,单变量和多变量微积分,2020 年。
让我们考虑多元函数,f(x, y) = x² + 3xy + 4y²,我们希望找到其二阶偏导数。该过程始于找到其一阶偏导数,首先:
然后通过重复找到偏导数的过程,找到四个二阶偏导数。自己的偏导数是最简单找到的,因为我们只需再次针对x或y进行偏导数过程的重复:
先前找到的f[x](即相对于x的偏导数)的交叉偏导数通过取其结果相对于y的偏导数得到,给出f[xy]。类似地,相对于x的偏导数取f[y]的结果,给出f[yx]:
交叉偏导数给出相同结果并非偶然。这由克莱罗定理定义,其表明只要交叉偏导数连续,则它们相等。
想要开始学习机器学习的微积分吗?
现在就参加我的免费 7 天电子邮件快速课程(附带示例代码)。
点击注册并获得该课程的免费 PDF 电子书版本。
在机器学习中的应用
在机器学习中,主要使用二阶导数。我们此前提到过,二阶导数可以提供第一阶导数无法捕捉的信息。具体来说,它可以告诉我们临界点是局部最小值还是最大值(基于二阶导数大于或小于零的情况),而在这两种情况下第一阶导数都将为零。
有几种利用此信息的二阶优化算法,其中之一是牛顿法。
另一方面,二阶信息使我们能够对目标函数进行二次近似,并近似计算出达到局部最小值的正确步长……
– 第 87 页,优化算法,2019 年。
在单变量情况下,牛顿法使用二阶泰勒级数展开式在目标函数的某一点进行二次近似。牛顿法的更新规则是通过将导数设为零并解出根得到的,这涉及到对二阶导数进行除法运算。如果牛顿法扩展到多变量优化,导数将被梯度取代,而二阶导数的倒数将被 Hessian 矩阵的逆矩阵取代。
我们将在不同的教程中涵盖 Hessian 矩阵和泰勒级数近似方法,这些方法利用了高阶导数。
进一步阅读
如果你想深入了解该主题,本节提供了更多资源。
书籍
-
单变量与多变量微积分,2020 年。
-
傻瓜微积分,2016 年。
-
深度学习,2017 年。
-
优化算法,2019 年。
总结
在本教程中,你学会了如何计算单变量和多变量函数的高阶导数。
具体来说,你学到了:
-
如何计算单变量函数的高阶导数。
-
如何计算多变量函数的高阶导数。
-
如何通过二阶优化算法在机器学习中利用二阶导数。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
微积分中的关键概念:变化率
原文:
machinelearningmastery.com/key-concepts-in-calculus-rate-of-change/
变化率的测量是微分积分中的一个重要概念,它涉及变化和无穷小量的数学。它使我们能够找出两个变化变量之间的关系以及它们如何相互影响。
变化率的测量对于机器学习也至关重要,例如在训练神经网络模型时应用梯度下降优化算法。
在本教程中,你将发现变化率作为微积分中的关键概念之一,以及测量它的重要性。
完成本教程后,你将了解:
-
线性和非线性函数的变化率如何测量。
-
变化率测量在不同领域的重要性。
让我们开始吧。
微积分中的关键概念:变化率
照片由Spencer Everett提供,版权所有。
教程概述
本教程分为两部分;它们是:
-
变化率
-
测量变化率的重要性
变化率
变化率定义了一个变化变量与另一个变量之间的关系。
考虑一个在垂直方向上位移是水平位移两倍的移动物体,垂直方向用y表示,水平方向用x表示。在数学术语中,这可以表示为:
???y = 2???x
希腊字母delta,???,通常用来表示差异或变化。因此,上述方程定义了移动物体中x位置变化与y位置变化之间的关系。
在x和y方向的变化可以通过x–y坐标系中的一条直线来绘制。
线性函数的线图
在这个物体运动的图形表示中,变化率由直线的斜率或其梯度表示。由于这条线可以看到每向右跑一个单位,上升2 个单位,因此它的变化率或斜率等于 2。
速率和斜率有一个简单的联系。前面的速率示例可以在 x-y 坐标系中绘制,其中每个速率都表现为一个斜率。
第 38 页,《小白的微积分基础》,2019 年。
综合来看,我们可以看到:
变化率 = ???y / ???x = 上升 / 跑动 = 斜率
如果我们考虑这条直线上的两个特定点,P*[1]* = (2, 4) 和 P*[2]* = (8, 16),我们可以确认斜率为:
斜率 = ???y / ???x = (y*[2]* – y*[1]) / (x*[2] – x*[1]*) = (16 – 4) / (8 – 2) = 2
对于这个特定的例子,变化率由斜率表示是正的,因为直线的方向向右增加。然而,变化率也可以是负的,如果直线的方向减小,这意味着 y 的值会随着 x 的值增加而减少。此外,当 y 的值在 x 增加时保持不变时,我们会说变化率为 零。如果相反,当 y 增加时 x 的值保持不变,我们会认为变化范围为 无限,因为垂直线的斜率被认为是未定义的。
到目前为止,我们考虑的是具有恒定斜率的直线,因此是一个线性函数。然而,并非所有函数都是如此简单,如果它们都很简单,那就没有微积分的必要了。
微积分是变化的数学,因此现在是转向抛物线,即斜率变化的曲线的好时机。
第 39 页,《傻瓜微积分精要》,2019 年。
让我们考虑一个简单的非线性函数——抛物线:
y = (1 / 4) x²
与直线特征的常数斜率相比,我们可以注意到抛物线如何在右移时变得越来越陡峭。
抛物线的线图
摘自《傻瓜微积分精要》
请记住,微积分方法允许我们通过将曲线形状切割成许多无穷小的直线段并将其并排排列来进行分析。如果我们考虑抛物线曲线上的某一点 P 的一段这样的直线,我们会发现我们再次计算变化率作为直线的斜率。重要的是要记住,抛物线上的变化率取决于我们首先考虑的特定点 P。
例如,如果我们考虑经过点 P = (2, 1) 的直线,我们发现这个点在抛物线上的变化率为:
变化率 = ???y / ???x = 1 / 1 = 1
如果我们考虑在同一抛物线上的另一个点 P = (6, 9),我们发现此点的变化率为:
变化率 = ???y / ???x = 3 / 1 = 3
与曲线在某个特定点 P 处“接触”的直线被称为 切线,而计算函数变化率的过程也被称为求其 导数。
导数 简单地说,是衡量一个事物与另一个事物相比变化多少——这就是一个变化率。
第 37 页,《傻瓜微积分精要》,2019 年。
虽然我们考虑了一个简单的抛物线作为这个例子,但我们也可以类似地使用微积分来分析更复杂的非线性函数。计算曲线上不同切点的瞬时变化率的概念保持不变。
我们在使用梯度下降算法训练神经网络时会遇到这样的一个例子。作为优化算法,梯度下降通过迭代下降误差函数以接近其全局最小值,每次更新神经网络权重以更好地拟合训练数据。误差函数通常是非线性的,可能包含许多局部最小值和鞍点。为了找到下坡路,梯度下降算法计算误差函数不同点的瞬时斜率,直到找到误差最低且变化率为零的点。
变化率测量的重要性
到目前为止,我们考虑了在x–y坐标系统中每单位的变化率。
但变化率可以是任何东西对任何东西的比率。
第 38 页,《傻瓜计算学基础》,2019。
在训练神经网络的背景下,我们已经看到误差梯度是计算相对于神经网络中某个特定权重的误差变化。
许多不同的领域中,变化率的测量也是一个重要的概念。一些例子包括:
- 在物理学中,速度是计算每单位时间的位置变化。
** 在信号数字化中,采样率是每秒信号样本的数量。** 在计算中,比特率是计算机每单位时间处理的比特数。** 在金融中,汇率指的是一种货币相对于另一种货币的价值。***
**> 无论如何,每个变化率都是导数,每个导数都是变化率。
第 38 页,《傻瓜计算学基础》,2019。
*## 进一步阅读
本节提供了更多资源,如果你想深入了解这个主题。
书籍
总结
在本教程中,你发现了变化率作为微积分中的关键概念之一,并了解了其测量的重要性。
具体来说,你学到了:
-
变化率的测量是微分学中的一个基本概念,它允许我们找出一个变化变量与另一个变量的关系。
-
这是一个重要的概念,可以应用于许多领域,其中之一是机器学习。
你有任何问题吗?
在下面的评论中提问,我会尽力回答。*****
具有不等式约束的拉格朗日乘子法
原文:
machinelearningmastery.com/lagrange-multiplier-approach-with-inequality-constraints/
在之前的文章中,我们介绍了拉格朗日乘子法用于寻找具有等式约束的函数的局部最小值或最大值。同样的方法也可以应用于具有不等式约束的情况。
在本教程中,您将发现拉格朗日乘子法应用于当存在不等式约束时寻找函数的局部最小值或最大值的方法,也可以与等式约束一起使用。
完成本教程后,您将了解
-
如何找到具有等式约束的函数的局部最大值或最小值
-
具有等式约束的拉格朗日乘子法
让我们开始吧。
具有不等式约束的拉格朗日乘子法
图片由 Christine Roy 提供,保留所有权利。
前提条件
对于本教程,我们假设您已审阅:
以及
您可以通过点击上述链接来回顾这些概念。
受限优化和拉格朗日函数
从我们之前的帖子扩展,受限优化问题通常可以看作是
$$
\begin{aligned}
\min && f(X) \
\textrm{subject to} && g(X) &= 0 \
&& h(X) &\ge 0 \
&& k(X) &\le 0
\end{aligned}
$$
其中 X X X 是标量或向量值。这里, g ( X ) = 0 g(X)=0 g(X)=0 是等式约束,而 h ( X ) ≥ 0 h(X)\ge 0 h(X)≥0, k ( X ) ≤ 0 k(X)\le 0 k(X)≤0 是不等式约束。请注意,我们在优化问题中总是使用 ≥ \ge ≥ 和 ≤ \le ≤,而不是 > \gt > 和 < \lt <,因为前者定义了数学中的闭集,我们应该从中寻找 X X X 的值。这些约束在优化问题中可以有很多种。
等式约束易于处理,但不等式约束则不然。因此,简化处理的一种方法是将不等式转化为等式,引入松弛变量:
$$
\begin{aligned}
\min && f(X) \
\textrm{subject to} && g(X) &= 0 \
&& h(X) – s² &= 0 \
&& k(X) + t² &= 0
\end{aligned}
$$
当某些事物是负的时候,向其添加一定的正量将使其等于零,反之亦然。这个量就是松弛变量;上述的 s 2 s² s2和 t 2 t² t2就是例子。我们特意将 s 2 s² s2和 t 2 t² t2项放在那里以表示它们不能为负。
引入松弛变量后,我们可以使用拉格朗日乘子法来解决问题,其中拉格朗日函数定义如下:
$$
L(X, \lambda, \theta, \phi) = f(X) – \lambda g(X) – \theta (h(X)-s²) + \phi (k(X)+t²)
$$
了解对于问题的最优解 X ∗ X^* X∗来说,不等式约束要么等式成立(此时松弛变量为零),要么不成立是很有用的。这些等式成立的不等式约束被称为激活约束。否则,是非激活约束。从这个意义上说,你可以认为等式约束总是激活的。
互补松弛条件
我们需要知道约束条件是否处于激活状态,这是因为克拉斯-库恩-塔克 (KKT) 条件。准确地说,KKT 条件描述了在 X ∗ X^* X∗是受约束优化问题的最优解时会发生什么:
-
拉格朗日函数的梯度为零
-
所有约束条件均满足
-
不等式约束满足互补松弛条件
最重要的是互补松弛条件。虽然我们了解到,通过等式约束的优化问题可以使用拉格朗日乘子来解决,即拉格朗日函数的梯度在最优解处为零,互补松弛条件通过说在最优解 X ∗ X^* X∗处,要么拉格朗日乘子为零,要么对应的不等式约束是激活的,将此扩展到不等式约束的情况。
使用互补松弛条件有助于我们探索解决优化问题的不同情况。最好通过一个例子来解释。
示例 1:均值-方差组合优化
这是一个来自金融领域的例子。如果我们有 1 美元并且打算进行两种不同的投资,其中它们的回报被建模为双变量高斯分布。我们应该如何分配资金以最小化整体回报的方差?
此优化问题,也称为马尔科维茨均值-方差组合优化,可以表述为:
$$
\begin{aligned}
\min && f(w_1, w_2) &= w_1²\sigma_1²+w_2²\sigma_2²+2w_1w_2\sigma_{12} \
\textrm{subject to} && w_1+w_2 &= 1 \
&& w_1 &\ge 0 \
&& w_1 &\le 1
\end{aligned}
$$
其中最后两个约束用于将每项投资的权重限制在 0 到 1 美元之间。假设 σ 1 2 = 0.25 \sigma_1²=0.25 σ12=0.25, σ 2 2 = 0.10 \sigma_2²=0.10 σ22=0.10, σ 12 = 0.15 \sigma_{12} = 0.15 σ12=0.15,那么拉格朗日函数定义为:
$$
\begin{aligned}
L(w_1,w_2,\lambda,\theta,\phi) =& 0.25w_1²+0.1w_2²+0.3w_1w_2 \
&- \lambda(w_1+w_2-1) \
&- \theta(w_1-s²) – \phi(w_1-1+t²)
\end{aligned}
$$
我们有梯度:
$$
\begin{aligned}
\frac{\partial L}{\partial w_1} &= 0.5w_1+0.3w_2-\lambda-\theta-\phi \
\frac{\partial L}{\partial w_2} &= 0.2w_2+0.3w_1-\lambda \
\frac{\partial L}{\partial\lambda} &= 1-w_1-w_2 \
\frac{\partial L}{\partial\theta} &= s²-w_1 \
\frac{\partial L}{\partial\phi} &= 1-w_1-t²
\end{aligned}
$$
从这一点开始,必须考虑互补松弛条件。我们有两个松弛变量 s s s 和 t t t,相应的拉格朗日乘子是 θ \theta θ 和 ϕ \phi ϕ。现在我们需要考虑一个松弛变量是否为零(对应的不等式约束是激活的)或拉格朗日乘子是否为零(约束是不激活的)。有四种可能的情况:
-
θ = ϕ = 0 \theta=\phi=0 θ=ϕ=0 和 s 2 > 0 s²>0 s2>0, t 2 > 0 t²>0 t2>0
-
θ ≠ 0 \theta\ne 0 θ=0 但 ϕ = 0 \phi=0 ϕ=0,并且 s 2 = 0 s²=0 s2=0, t 2 > 0 t²>0 t2>0
-
θ = 0 \theta=0 θ=0 但 ϕ ≠ 0 \phi\ne 0 ϕ=0,并且 s 2 > 0 s²>0 s2>0, t 2 = 0 t²=0 t2=0
-
θ ≠ 0 \theta\ne 0 θ=0 和 ϕ ≠ 0 \phi\ne 0 ϕ=0,并且 s 2 = t 2 = 0 s²=t²=0 s2=t2=0
对于案例 1,使用 ∂ L / ∂ λ = 0 \partial L/\partial\lambda=0 ∂L/∂λ=0, ∂ L / ∂ w 1 = 0 \partial L/\partial w_1=0 ∂L/∂w1=0 和 ∂ L / ∂ w 2 = 0 \partial L/\partial w_2=0 ∂L/∂w2=0 我们得到
$$
\begin{align}
w_2 &= 1-w_1 \
0.5w_1 + 0.3w_2 &= \lambda \
0.3w_1 + 0.2w_2 &= \lambda
\end{align}
$$
我们得到 w 1 = − 1 w_1=-1 w1=−1, w 2 = 2 w_2=2 w2=2, λ = 0.1 \lambda=0.1 λ=0.1。但通过 ∂ L / ∂ θ = 0 \partial L/\partial\theta=0 ∂L/∂θ=0,我们得到 s 2 = − 1 s²=-1 s2=−1,这没有解 ( s 2 s² s2 不能为负)。因此这个案例不可行。
对于案例 2,通过 ∂ L / ∂ θ = 0 \partial L/\partial\theta=0 ∂L/∂θ=0 我们得到 w 1 = 0 w_1=0 w1=0。因此,从 ∂ L / ∂ λ = 0 \partial L/\partial\lambda=0 ∂L/∂λ=0 我们知道 w 2 = 1 w_2=1 w2=1。并且通过 ∂ L / ∂ w 2 = 0 \partial L/\partial w_2=0 ∂L/∂w2=0,我们找到 λ = 0.2 \lambda=0.2 λ=0.2,从 ∂ L / ∂ w 1 \partial L/\partial w_1 ∂L/∂w1 我们得到 ϕ = 0.1 \phi=0.1 ϕ=0.1。在这种情况下,目标函数的值为 0.1
对于案例 3,通过 ∂ L / ∂ ϕ = 0 \partial L/\partial\phi=0 ∂L/∂ϕ=0 我们得到 w 1 = 1 w_1=1 w1=1。因此,从 ∂ L / ∂ λ = 0 \partial L/\partial\lambda=0 ∂L/∂λ=0 我们知道 w 2 = 0 w_2=0 w2=0。并且通过 ∂ L / ∂ w 2 = 0 \partial L/\partial w_2=0 ∂L/∂w2=0,我们得到 λ = 0.3 \lambda=0.3 λ=0.3,从 ∂ L / ∂ w 1 \partial L/\partial w_1 ∂L/∂w1 我们得到 θ = 0.2 \theta=0.2 θ=0.2。在这种情况下,目标函数的值为 0.25
对于案例 4,通过 ∂ L / ∂ θ = 0 \partial L/\partial\theta=0 ∂L/∂θ=0 我们得到 w 1 = 0 w_1=0 w1=0,但通过 ∂ L / ∂ ϕ = 0 \partial L/\partial\phi=0 ∂L/∂ϕ=0 我们得到 w 1 = 1 w_1=1 w1=1。因此这个案例不可行。
比较案例 2 和案例 3 的目标函数值,我们看到案例 2 的值更低。因此,我们将其作为优化问题的解,最优解为 w 1 = 0 w_1=0 w1=0, w 2 = 1 w_2=1 w2=1。
作为练习,你可以重新尝试上述问题, σ 12 = − 0.15 \sigma_{12}=-0.15 σ12=−0.15。解决方案将是 0.0038,当 w 1 = 5 13 w_1=\frac{5}{13} w1=135,两个不等式约束不激活时。
想开始学习机器学习中的微积分吗?
立即参加我的免费 7 天电子邮件速成课程(附示例代码)。
点击注册并获得课程的免费 PDF 电子书版本。
示例 2:水填充算法
这是一个来自通信工程的例子。如果我们有一个信道(例如,一个无线带宽),其噪声功率为 N N N,信号功率为 S S S,则信道容量(以每秒比特数计)与 log 2 ( 1 + S / N ) \log_2(1+S/N) log2(1+S/N) 成正比。如果我们有 k k k 个类似的信道,每个信道都有其自身的噪声和信号水平,则所有信道的总容量是 ∑ i log 2 ( 1 + S i / N i ) \sum_i \log_2(1+S_i/N_i) ∑ilog2(1+Si/Ni) 的总和。
假设我们使用的电池只能提供 1 瓦特的功率,这个功率必须分配到 k k k 个信道(记作 p 1 , ⋯ , p k p_1,\cdots,p_k p1,⋯,pk)。每个信道可能有不同的衰减,因此最终,信号功率会被每个信道的增益 g i g_i gi 折扣。然后,利用这 k k k 个信道可以达到的最大总容量被表述为一个优化问题
$$
\begin{aligned}
\max && f(p_1,\cdots,p_k) &= \sum_{i=1}^k \log_2\left(1+\frac{g_ip_i}{n_i}\right) \
\textrm{受限于} && \sum_{i=1}^k p_i &= 1 \
&& p_1,\cdots,p_k &\ge 0 \
\end{aligned}
$$
为了方便微分,我们注意到 log 2 x = log x / log 2 \log_2x=\log x/\log 2 log2x=logx/log2 和 log ( 1 + g i p i / n i ) = log ( n i + g i p i ) − log ( n i ) \log(1+g_ip_i/n_i)=\log(n_i+g_ip_i)-\log(n_i) log(1+gipi/ni)=log(ni+gipi)−log(ni),因此目标函数可以替换为
$$
f(p_1,\cdots,p_k) = \sum_{i=1}^k \log(n_i+g_ip_i)
$$
假设我们有 k = 3 k=3 k=3 个信道,每个信道的噪声水平分别为 1.0、0.9、1.0,信道增益为 0.9、0.8、0.7,则优化问题为
$$
\begin{aligned}
\max && f(p_1,p_2,p_k) &= \log(1+0.9p_1) + \log(0.9+0.8p_2) + \log(1+0.7p_3)\
\textrm{受限于} && p_1+p_2+p_3 &= 1 \
&& p_1,p_2,p_3 &\ge 0
\end{aligned}
$$
我们这里有三个不等式约束。拉格朗日函数定义为
$$
\begin{aligned}
& L(p_1,p_2,p_3,\lambda,\theta_1,\theta_2,\theta_3) \
=\ & \log(1+0.9p_1) + \log(0.9+0.8p_2) + \log(1+0.7p_3) \
& – \lambda(p_1+p_2+p_3-1) \
& – \theta_1(p_1-s_1²) – \theta_2(p_2-s_2²) – \theta_3(p_3-s_3²)
\end{aligned}
$$
梯度因此为
$$
\begin{aligned}
\frac{\partial L}{\partial p_1} & = \frac{0.9}{1+0.9p_1}-\lambda-\theta_1 \
\frac{\partial L}{\partial p_2} & = \frac{0.8}{0.9+0.8p_2}-\lambda-\theta_2 \
\frac{\partial L}{\partial p_3} & = \frac{0.7}{1+0.7p_3}-\lambda-\theta_3 \
\frac{\partial L}{\partial\lambda} &= 1-p_1-p_2-p_3 \
\frac{\partial L}{\partial\theta_1} &= s_1²-p_1 \
\frac{\partial L}{\partial\theta_2} &= s_2²-p_2 \
\frac{\partial L}{\partial\theta_3} &= s_3²-p_3 \
\end{aligned}
$$
但现在我们有 3 个松弛变量,需要考虑 8 种情况:
-
θ 1 = θ 2 = θ 3 = 0 \theta_1=\theta_2=\theta_3=0 θ1=θ2=θ3=0,因此 s 1 2 , s 2 2 , s 3 2 s_1²,s_2²,s_3² s12,s22,s32 均非零
-
θ 1 = θ 2 = 0 \theta_1=\theta_2=0 θ1=θ2=0 但 θ 3 ≠ 0 \theta_3\ne 0 θ3=0,因此仅有 s 3 2 = 0 s_3²=0 s32=0
-
θ 1 = θ 3 = 0 \theta_1=\theta_3=0 θ1=θ3=0 但 θ 2 ≠ 0 \theta_2\ne 0 θ2=0,因此仅有 s 2 2 = 0 s_2²=0 s22=0
-
θ 2 = θ 3 = 0 \theta_2=\theta_3=0 θ2=θ3=0 但 θ 1 ≠ 0 \theta_1\ne 0 θ1=0,因此仅有 s 1 2 = 0 s_1²=0 s12=0
-
θ 1 = 0 \theta_1=0 θ1=0 但 θ 2 , θ 3 \theta_2,\theta_3 θ2,θ3 非零,因此仅有 s 2 2 = s 3 2 = 0 s_2²=s_3²=0 s22=s32=0
-
θ 2 = 0 \theta_2=0 θ2=0 但 θ 1 , θ 3 \theta_1,\theta_3 θ1,θ3 非零,因此仅有 s 1 2 = s 3 2 = 0 s_1²=s_3²=0 s12=s32=0
-
θ 3 = 0 \theta_3=0 θ3=0 但 θ 1 , θ 2 \theta_1,\theta_2 θ1,θ2 非零,因此仅有 s 1 2 = s 2 2 = 0 s_1²=s_2²=0 s12=s22=0
-
所有的 θ 1 , θ 2 , θ 3 \theta_1,\theta_2,\theta_3 θ1,θ2,θ3 都非零,因此 s 1 2 = s 2 2 = s 3 2 = 0 s_1²=s_2²=s_3²=0 s12=s22=s32=0
我们可以立即得出案例 8 不可行,因为从 ∂ L / ∂ θ i = 0 \partial L/\partial\theta_i=0 ∂L/∂θi=0 我们可以使 p 1 = p 2 = p 3 = 0 p_1=p_2=p_3=0 p1=p2=p3=0,但无法使 ∂ L / ∂ λ = 0 \partial L/\partial\lambda=0 ∂L/∂λ=0。
对于案例 1,我们有
$$
\frac{0.9}{1+0.9p_1}=\frac{0.8}{0.9+0.8p_2}=\frac{0.7}{1+0.7p_3}=\lambda
$$
从 ∂ L / ∂ p 1 = ∂ L / ∂ p 2 = ∂ L / ∂ p 3 = 0 \partial L/\partial p_1=\partial L/\partial p_2=\partial L/\partial p_3=0 ∂L/∂p1=∂L/∂p2=∂L/∂p3=0。结合 p 3 = 1 − p 1 − p 2 p_3=1-p_1-p_2 p3=1−p1−p2 从 ∂ L / ∂ λ = 0 \partial L/\partial\lambda=0 ∂L/∂λ=0,我们找到解为 p 1 = 0.444 p_1=0.444 p1=0.444, p 2 = 0.430 p_2=0.430 p2=0.430, p 3 = 0.126 p_3=0.126 p3=0.126,目标函数 f ( p 1 , p 2 , p 3 ) = 0.639 f(p_1,p_2,p_3)=0.639 f(p1,p2,p3)=0.639。
对于案例 2,我们有 p 3 = 0 p_3=0 p3=0 从 ∂ L / ∂ θ 3 = 0 \partial L/\partial\theta_3=0 ∂L/∂θ3=0。进一步,使用 p 2 = 1 − p 1 p_2=1-p_1 p2=1−p1 从 ∂ L / ∂ λ = 0 \partial L/\partial\lambda=0 ∂L/∂λ=0,以及
$$
\frac{0.9}{1+0.9p_1}=\frac{0.8}{0.9+0.8p_2}=\lambda
$$
从 ∂ L / ∂ p 1 = ∂ L / ∂ p 2 = 0 \partial L/\partial p_1=\partial L/\partial p_2=0 ∂L/∂p1=∂L/∂p2=0,我们可以解得 p 1 = 0.507 p_1=0.507 p1=0.507 和 p 2 = 0.493 p_2=0.493 p2=0.493。目标函数 f ( p 1 , p 2 , p 3 ) = 0.634 f(p_1,p_2,p_3)=0.634 f(p1,p2,p3)=0.634。
同样在案例 3 中, p 2 = 0 p_2=0 p2=0,我们解得 p 1 = 0.659 p_1=0.659 p1=0.659 和 p 3 = 0.341 p_3=0.341 p3=0.341,目标函数 f ( p 1 , p 2 , p 3 ) = 0.574 f(p_1,p_2,p_3)=0.574 f(p1,p2,p3)=0.574。
在案例 4 中,我们有 p 1 = 0 p_1=0 p1=0, p 2 = 0.652 p_2=0.652 p2=0.652, p 3 = 0.348 p_3=0.348 p3=0.348,目标函数 f ( p 1 , p 2 , p 3 ) = 0.570 f(p_1,p_2,p_3)=0.570 f(p1,p2,p3)=0.570。
案例 5 中我们有 p 2 = p 3 = 0 p_2=p_3=0 p2=p3=0,因此 p 3 = 1 p_3=1 p3=1。因此我们有目标函数 f ( p 1 , p 2 , p 3 ) = 0.0.536 f(p_1,p_2,p_3)=0.0.536 f(p1,p2,p3)=0.0.536。
同样在案例 6 和案例 7 中,我们分别有 p 2 = 1 p_2=1 p2=1 和 p 1 = 1 p_1=1 p1=1。目标函数分别为 0.531 和 0.425。
比较所有这些情况,我们发现目标函数的最大值出现在案例 1。因此,该优化问题的解是
p 1 = 0.444 p_1=0.444 p1=0.444, p 2 = 0.430 p_2=0.430 p2=0.430, p 3 = 0.126 p_3=0.126 p3=0.126,目标函数 f ( p 1 , p 2 , p 3 ) = 0.639 f(p_1,p_2,p_3)=0.639 f(p1,p2,p3)=0.639。
扩展阅读
在上述例子中,我们将松弛变量引入了拉格朗日函数,一些书籍可能更倾向于不添加松弛变量,而是将拉格朗日乘子限制为正值。在这种情况下,你可能会看到拉格朗日函数写作
$$
L(X, \lambda, \theta, \phi) = f(X) – \lambda g(X) – \theta h(X) + \phi k(X)
$$
但需要 θ ≥ 0 ; ϕ ≥ 0 \theta\ge 0;\phi\ge 0 θ≥0;ϕ≥0。
拉格朗日函数在原对偶方法中也很有用,用于找到最大值或最小值。如果目标或约束是非线性的,这特别有帮助,因为解决方案可能不容易找到。
一些涵盖此主题的书籍包括:
总结
在本教程中,你了解了如何将拉格朗日乘子方法应用于不等式约束。具体而言,你学到了:
-
拉格朗日乘子和拉格朗日函数在不等式约束存在时
-
如何利用 KKT 条件解决给定不等式约束的优化问题
拉格朗日乘子法:支持向量机背后的理论(第一部分:可分离情况)
本教程旨在为任何希望深入理解拉格朗日乘子如何在支持向量机(SVM)模型构建中使用的人提供指导。SVM 最初设计用于解决二分类问题,后来扩展并应用于回归和无监督学习。它们在解决许多复杂的机器学习分类问题上取得了成功。
在本教程中,我们将讨论最简单的 SVM,假设正例和负例可以通过线性超平面完全分开。
完成本教程后,你将了解:
-
超平面如何作为决策边界
-
对正例和负例的数学约束
-
什么是边际以及如何最大化边际
-
拉格朗日乘子在最大化边际中的作用
-
如何确定可分离情况下的分离超平面
让我们开始吧。
拉格朗日乘子法:支持向量机背后的理论(第一部分:可分离情况)
照片由 Mehreen Saeed 拍摄,部分权利保留。
本教程分为三个部分,它们是:
-
SVM 的数学模型的公式化
-
通过拉格朗日乘子法寻找最大边际超平面的解
-
解决的示例以演示所有概念
本教程中使用的符号
-
m m m:总训练点数。
-
n n n:所有数据点的特征总数或维度
-
x x x:数据点,是一个 n 维向量。
-
x + x^+ x+:标记为+1 的数据点。
-
x − x^- x−:标记为-1 的数据点。
-
i i i:用于索引训练点的下标。 0 ≤ i < m 0 \leq i < m 0≤i<m
-
j j j:用于索引数据点的单独维度的下标。 1 ≤ j ≤ n 1 \leq j \leq n 1≤j≤n
-
t t t:数据点的标签。
-
T:转置算子。
-
w w w:表示超平面系数的权重向量。它也是一个 n 维向量。
-
α \alpha α:拉格朗日乘子,每个训练点一个。这是一个 m 维向量。
-
d d d:数据点到决策边界的垂直距离。
超平面作为决策边界
支持向量机旨在区分属于两个不同类别的数据点。一组点标记为+1,也称为正类。另一组点标记为-1,也称为负类。现在,我们将做一个简化假设,假设两个类别的点可以通过线性超平面进行区分。
SVM 假设两个类别之间有一个线性的决策边界,目标是找到一个超平面,使两个类别之间的分离最大。因此,有时使用术语最大边界分类器
来指代 SVM。最近的数据点与决策边界之间的垂直距离被称为边界
。由于边界完全分隔了正负示例,并且不容忍任何错误,因此也被称为硬边界
。
超平面的数学表达式如下,其中(w_j)是系数,(w_0)是决定超平面距离原点的任意常数:
$$
w^T x_i + w_0 = 0
$$
对于第 i i i个二维点 ( x i 1 , x i 2 ) (x_{i1}, x_{i2}) (xi1,xi2),上述表达式简化为:
$$
w_1x_{i1} + w_2 x_{i2} + w_0 = 0
$$
对正负数据点的数学约束
由于我们希望最大化正负数据点之间的边界,因此我们希望正数据点满足以下约束:
$$
w^T x_i^+ + w_0 \geq +1
$$
同样,负数据点应满足:
$$
w^T x_i^- + w_0 \leq -1
$$
我们可以通过使用 t i ∈ { − 1 , + 1 } t_i \in \{-1,+1\} ti∈{−1,+1}来表示数据点 x i x_i xi的类别标签,使用一个整齐的技巧来写出两个点集的统一方程:
$$
t_i(w^T x_i + w_0) \geq +1
$$
最大边界超平面
数据点 x i x_i xi到边界的垂直距离 d i d_i di由以下公式给出:
$$
d_i = \frac{|w^T x_i + w_0|}{||w||}
$$
为了最大化这个距离,我们可以最小化分母的平方,从而得到一个二次规划问题:
$$
\min \frac{1}{2}||w||² ;\text{ subject to } t_i(w^Tx_i+w_0) \geq +1, \forall i
$$
通过拉格朗日乘子法的解
为了解决上述带有不等式约束的二次规划问题,我们可以使用拉格朗日乘子法。因此,拉格朗日函数为:
$$
L(w, w_0, \alpha) = \frac{1}{2}||w||² + \sum_i \alpha_i\big(t_i(w^Tx_i+w_0) – 1\big)
$$
为了解决上述问题,我们设置如下:
\begin{equation}
\frac{\partial L}{ \partial w} = 0, \
\frac{\partial L}{ \partial \alpha} = 0, \
\frac{\partial L}{ \partial w_0} = 0 \
\end{equation}
将上述内容代入拉格朗日函数得到如下优化问题,也称为对偶问题:
$$
L_d = -\frac{1}{2} \sum_i \sum_k \alpha_i \alpha_k t_i t_k (x_i)^T (x_k) + \sum_i \alpha_i
$$
我们必须在以下条件下最大化上述目标:
$$
w = \sum_i \alpha_i t_i x_i
$$
和
$$
0=\sum_i \alpha_i t_i
$$
上述方法的好处在于,我们有一个关于 (w) 的表达式,涉及到拉格朗日乘子。目标函数中没有 w w w 项。每个数据点都有一个相关的拉格朗日乘子。 w 0 w_0 w0 的计算也在后面解释。
决定测试点的分类
任何测试点 x x x 的分类可以使用这个表达式来确定:
$$
y(x) = \sum_i \alpha_i t_i x^T x_i + w_0
$$
y ( x ) y(x) y(x) 的正值意味着 x ∈ + 1 x\in+1 x∈+1,负值则意味着 x ∈ − 1 x\in-1 x∈−1
想要开始学习机器学习中的微积分?
立即获取我的免费 7 天邮件速成课程(包含示例代码)。
点击注册并获得课程的免费 PDF 电子书版本。
Karush-Kuhn-Tucker 条件
此外,Karush-Kuhn-Tucker (KKT) 条件满足上述约束优化问题,如下所示:
\begin{eqnarray}
\alpha_i &\geq& 0 \
t_i y(x_i) -1 &\geq& 0 \
\alpha_i(t_i y(x_i) -1) &=& 0
\end{eqnarray}
KKT 条件的解释
KKT 条件规定,对于每个数据点,以下之一是正确的:
- 拉格朗日乘子为零,即 (\alpha_i=0)。因此,这一点在分类中没有作用。
或
- $ t_i y(x_i) = 1$ 和 α i > 0 \alpha_i > 0 αi>0:在这种情况下,数据点在决定 w w w 的值时起作用。这样的点被称为支持向量。
计算 w 0 w_0 w0
对于 w 0 w_0 w0,我们可以选择任何支持向量 x s x_s xs 并求解
$$
t_s y(x_s) = 1
$$
给出:
$$
t_s(\sum_i \alpha_i t_i x_s^T x_i + w_0) = 1
$$
一个已解决的示例
为了帮助你理解上述概念,这里有一个简单的任意求解示例。当然,对于大量点,你会使用优化软件来解决这个问题。此外,这只是满足所有约束条件的一个可能解决方案。目标函数可以进一步最大化,但超平面的斜率对于最优解将保持不变。此外,对于这个例子, w 0 w_0 w0 是通过取所有三个支持向量的 w 0 w_0 w0 的平均值来计算的。
这个示例将向你展示模型并不像它看起来那么复杂。
对于上述点集,我们可以看到 (1,2)、(2,1) 和 (0,0) 是离分隔超平面最近的点,因此,作为支持向量。远离边界的点(例如 (-3,1))在确定点的分类时没有任何作用。
进一步阅读
本节提供更多有关该主题的资源,如果你想深入了解。
书籍
-
模式识别与机器学习 由 Christopher M. Bishop 编著
-
托马斯微积分,第 14 版,2017 年(基于 George B. Thomas 的原著,由 Joel Hass、Christopher Heil 和 Maurice Weir 修订)
文章
-
支持向量机模式识别教程 作者:克里斯托弗·J.C.·伯吉斯
总结
在本教程中,你了解了如何使用拉格朗日乘子法解决通过具有不等式约束的二次规划问题来最大化间隔的问题。
具体来说,你学到了:
-
分离线性超平面的数学表达式
-
最大间隔作为具有不等式约束的二次规划问题的解
-
如何使用拉格朗日乘子法找到正负样本之间的线性超平面
对于这篇文章中讨论的支持向量机,你有任何问题吗?请在下面的评论中提出你的问题,我会尽力回答。
拉格朗日乘数法:支持向量机背后的理论(第三部分:在 Python 中从头开始实现 SVM)
支持向量机(SVM)分类器背后的数学是美丽的。重要的是不仅要学习 SVM 的基本模型,还要知道如何从头开始实现整个模型。这是我们关于 SVM 的系列教程的延续。在本系列的 第一部分 和 第二部分 中,我们讨论了线性 SVM 背后的数学模型。在本教程中,我们将展示如何使用 Python 的 SciPy 库中提供的优化例程构建 SVM 线性分类器。
完成本教程后,您将了解:
-
如何使用 SciPy 的优化例程
-
如何定义目标函数
-
如何定义界限和线性约束
-
如何在 Python 中实现自己的 SVM 分类器
让我们开始吧。
拉格朗日乘数法:支持向量机背后的理论(第三部分:在 Python 中从头开始实现 SVM)
由 Thomas Sayre 创作的雕塑 Gyre,摄影师 Mehreen Saeed,部分权利保留。
教程概述
本教程分为 2 部分;它们是:
-
SVM 的优化问题
-
在 Python 中解决优化问题
-
定义目标函数
-
定义界限和线性约束
-
-
使用不同的 C 值解决问题
先决条件
对于本教程,假设您已经熟悉以下主题。您可以单击各个链接获取更多详细信息。
符号和假设
基本的 SVM 机器假设是一个二分类问题。假设我们有 m m m 个训练点,每个点是一个 n n n 维向量。我们将使用以下符号:
-
m m m: 总训练点数
-
n n n: 每个训练点的维度
-
x x x: 数据点,是一个 n n n 维向量
-
i i i: 用于索引训练点的下标。 0 ≤ i < m 0 \leq i < m 0≤i<m
-
k k k: 用于索引训练点的下标。 0 ≤ k < m 0 \leq k < m 0≤k<m
-
j j j: 用于索引训练点每个维度的下标
-
t t t: 数据点的标签。它是一个 m m m 维向量,其中 t i ∈ { − 1 , + 1 } t_i \in \{-1, +1\} ti∈{−1,+1}
-
T T T: 转置操作符
-
w w w: 权重向量,表示超平面的系数。它也是一个 n n n 维向量
-
α \alpha α: 拉格朗日乘子向量,也是一个 m m m 维向量
-
C C C: 用户定义的惩罚因子/正则化常数
SVM 优化问题
SVM 分类器最大化以下拉格朗日对偶:
$$
L_d = -\frac{1}{2} \sum_i \sum_k \alpha_i \alpha_k t_i t_k (x_i)^T (x_k) + \sum_i \alpha_i
$$
上述函数受以下约束条件的限制:
\begin{eqnarray}
0 \leq \alpha_i \leq C, & \forall i\
\sum_i \alpha_i t_i = 0& \
\end{eqnarray}
我们要做的就是找到与每个训练点相关的拉格朗日乘子 α \alpha α,同时满足上述约束条件。
想开始学习机器学习的微积分?
现在就拿我的免费 7 天电子邮件速成课程(附样例代码)。
点击注册并获得课程的免费 PDF 电子书版本。
SVM 的 Python 实现
我们将使用 SciPy 优化包来找到拉格朗日乘子的最佳值,并计算软间隔和分离超平面。
导入部分和常量
让我们编写优化、绘图和合成数据生成的导入部分。
Python
import numpy as np
# For optimization
from scipy.optimize import Bounds, BFGS
from scipy.optimize import LinearConstraint, minimize
# For plotting
import matplotlib.pyplot as plt
import seaborn as sns
# For generating dataset
import sklearn.datasets as dt
我们还需要以下常量来检测所有数值接近零的 alpha,因此我们需要定义自己的零阈值。
Python
ZERO = 1e-7
定义数据点和标签
让我们定义一个非常简单的数据集、相应的标签和一个简单的绘图例程。可选地,如果给定一串 alpha 给绘图函数,它还将标记所有支持向量及其对应的 alpha 值。仅供回顾,支持向量是那些 α > 0 \alpha>0 α>0 的点。
Python
dat = np.array([[0, 3], [-1, 0], [1, 2], [2, 1], [3,3], [0, 0], [-1, -1], [-3, 1], [3, 1]])
labels = np.array([1, 1, 1, 1, 1, -1, -1, -1, -1])
def plot_x(x, t, alpha=[], C=0):
sns.scatterplot(dat[:,0], dat[:, 1], style=labels,
hue=labels, markers=['s', 'P'],
palette=['magenta', 'green'])
if len(alpha) > 0:
alpha_str = np.char.mod('%.1f', np.round(alpha, 1))
ind_sv = np.where(alpha > ZERO)[0]
for i in ind_sv:
plt.gca().text(dat[i,0], dat[i, 1]-.25, alpha_str[i] )
plot_x(dat, labels)
minimize()
函数
让我们来看看 scipy.optimize
库中的 minimize()
函数。它需要以下参数:
-
需要最小化的目标函数。在我们的情况下是拉格朗日对偶。
-
变量的初始值,关于这些变量进行最小化。在这个问题中,我们需要确定拉格朗日乘子 α \alpha α。我们将随机初始化所有 α \alpha α。
-
用于优化的方法。我们将使用
trust-constr
。 -
对 α \alpha α 的线性约束。
-
α \alpha α 的边界。
定义目标函数
我们的目标函数是上述定义的
L
d
L_d
Ld,需要最大化。由于我们使用 minimize()
函数,所以需要将
L
d
L_d
Ld 乘以 (-1) 来进行最大化。其实现如下。目标函数的第一个参数是优化时的变量。我们还需要训练点和相应的标签作为额外参数。
你可以通过使用矩阵来简化下面的 lagrange_dual()
函数的代码。然而,在本教程中,它保持非常简单,以使一切更加清晰。
Python
# Objective function
def lagrange_dual(alpha, x, t):
result = 0
ind_sv = np.where(alpha > ZERO)[0]
for i in ind_sv:
for k in ind_sv:
result = result + alpha[i]*alpha[k]*t[i]*t[k]*np.dot(x[i, :], x[k, :])
result = 0.5*result - sum(alpha)
return result
定义线性约束
对于每个点的 alpha 的线性约束为:
$$
\sum_i \alpha_i t_i = 0
$$
我们也可以写成:
$$
\alpha_0 t_0 + \alpha_1 t_1 + \ldots \alpha_m t_m = 0
$$
LinearConstraint()
方法要求所有约束以矩阵形式书写,即:
\begin{equation}
0 =
\begin{bmatrix}
t_0 & t_1 & \ldots t_m
\end{bmatrix}
\begin{bmatrix}
\alpha_0\ \alpha_1 \ \vdots \ \alpha_m
\end{bmatrix}
= 0
\end{equation}
第一个矩阵是 LinearConstraint()
方法中的第一个参数。左边界和右边界是第二个和第三个参数。
Python
linear_constraint = LinearConstraint(labels, [0], [0])
print(linear_constraint)
输出
<scipy.optimize._constraints.LinearConstraint object at 0x12c87f5b0>
定义边界
alpha 的边界通过 Bounds()
方法定义。所有 alpha 都被限制在 0 和
C
C
C 之间。以下是
C
=
10
C=10
C=10 的示例。
Python
bounds_alpha = Bounds(np.zeros(dat.shape[0]), np.full(dat.shape[0], 10))
print(bounds_alpha)
输出
Bounds(array([0., 0., 0., 0., 0., 0., 0., 0., 0.]), array([10, 10, 10, 10, 10, 10, 10, 10, 10]))
定义查找 Alphas 的函数
让我们编写一个例程来寻找给定参数 x
、t
和 C
时的最优 alpha
值。目标函数需要额外的参数 x
和 t
,这些参数通过 minimize()
的 args 传递。
Python
def optimize_alpha(x, t, C):
m, n = x.shape
np.random.seed(1)
# Initialize alphas to random values
alpha_0 = np.random.rand(m)*C
# Define the constraint
linear_constraint = LinearConstraint(t, [0], [0])
# Define the bounds
bounds_alpha = Bounds(np.zeros(m), np.full(m, C))
# Find the optimal value of alpha
result = minimize(lagrange_dual, alpha_0, args = (x, t), method='trust-constr',
hess=BFGS(), constraints=[linear_constraint],
bounds=bounds_alpha)
# The optimized value of alpha lies in result.x
alpha = result.x
return alpha
确定超平面
超平面的表达式为:
$$
w^T x + w_0 = 0
$$
对于超平面,我们需要权重向量 w w w 和常数 w 0 w_0 w0。权重向量由以下公式给出:
$$
w = \sum_i \alpha_i t_i x_i
$$
如果训练点过多,最好只使用 α > 0 \alpha>0 α>0 的支持向量来计算权重向量。
对于 w 0 w_0 w0,我们将从每个支持向量 s s s 计算,对于这些支持向量 α s < C \alpha_s < C αs<C,然后取其平均值。对于单个支持向量 x s x_s xs, w 0 w_0 w0 由以下公式给出:
$$
w_0 = t_s – w^T x_s
$$
支持向量的 alpha 不能在数值上完全等于 C。因此,我们可以从 C 中减去一个小常数,以找到所有
α
s
<
C
\alpha_s < C
αs<C 的支持向量。这在 get_w0()
函数中完成。
Python
def get_w(alpha, t, x):
m = len(x)
# Get all support vectors
w = np.zeros(x.shape[1])
for i in range(m):
w = w + alpha[i]*t[i]*x[i, :]
return w
def get_w0(alpha, t, x, w, C):
C_numeric = C-ZERO
# Indices of support vectors with alpha<C
ind_sv = np.where((alpha > ZERO)&(alpha < C_numeric))[0]
w0 = 0.0
for s in ind_sv:
w0 = w0 + t[s] - np.dot(x[s, :], w)
# Take the average
w0 = w0 / len(ind_sv)
return w0
分类测试点
要对测试点 x t e s t x_{test} xtest 进行分类,我们使用 y ( x t e s t ) y(x_{test}) y(xtest) 的符号,如下:
$$
\text{label}{x{test}} = \text{sign}(y(x_{test})) = \text{sign}(w^T x_{test} + w_0)
$$
让我们编写相应的函数,可以将测试点的数组与 w w w 和 w 0 w_0 w0 作为参数传入,并对各种点进行分类。我们还添加了第二个函数来计算错误分类率:
Python
def classify_points(x_test, w, w0):
# get y(x_test)
predicted_labels = np.sum(x_test*w, axis=1) + w0
predicted_labels = np.sign(predicted_labels)
# Assign a label arbitrarily a +1 if it is zero
predicted_labels[predicted_labels==0] = 1
return predicted_labels
def misclassification_rate(labels, predictions):
total = len(labels)
errors = sum(labels != predictions)
return errors/total*100
绘制边界和超平面
我们还将定义绘制超平面和软边界的函数。
Python
def plot_hyperplane(w, w0):
x_coord = np.array(plt.gca().get_xlim())
y_coord = -w0/w[1] - w[0]/w[1] * x_coord
plt.plot(x_coord, y_coord, color='red')
def plot_margin(w, w0):
x_coord = np.array(plt.gca().get_xlim())
ypos_coord = 1/w[1] - w0/w[1] - w[0]/w[1] * x_coord
plt.plot(x_coord, ypos_coord, '--', color='green')
yneg_coord = -1/w[1] - w0/w[1] - w[0]/w[1] * x_coord
plt.plot(x_coord, yneg_coord, '--', color='magenta')
强化 SVM
现在是运行 SVM 的时候了。display_SVM_result()
函数将帮助我们可视化一切。我们将 alpha 初始化为随机值,定义 C,并在此函数中找到最佳的 alpha 值。我们还将绘制超平面、边界和数据点。支持向量也将通过其对应的 alpha 值进行标记。图的标题将是错误的百分比和支持向量的数量。
Python
def display_SVM_result(x, t, C):
# Get the alphas
alpha = optimize_alpha(x, t, C)
# Get the weights
w = get_w(alpha, t, x)
w0 = get_w0(alpha, t, x, w, C)
plot_x(x, t, alpha, C)
xlim = plt.gca().get_xlim()
ylim = plt.gca().get_ylim()
plot_hyperplane(w, w0)
plot_margin(w, w0)
plt.xlim(xlim)
plt.ylim(ylim)
# Get the misclassification error and display it as title
predictions = classify_points(x, w, w0)
err = misclassification_rate(t, predictions)
title = 'C = ' + str(C) + ', Errors: ' + '{:.1f}'.format(err) + '%'
title = title + ', total SV = ' + str(len(alpha[alpha > ZERO]))
plt.title(title)
display_SVM_result(dat, labels, 100)
plt.show()
C
的影响
如果你将 C
的值更改为
∞
\infty
∞,那么软边界将变成硬边界,不容忍错误。在这种情况下,我们定义的问题是不可解的。让我们生成一组人工点并观察 C
对分类的影响。为了理解整个问题,我们将使用一个简单的数据集,其中正例和负例是可分的。
以下是通过 make_blobs()
生成的点:
Python
dat, labels = dt.make_blobs(n_samples=[20,20],
cluster_std=1,
random_state=0)
labels[labels==0] = -1
plot_x(dat, labels)
现在我们定义不同的 C 值并运行代码。
Python
fig = plt.figure(figsize=(8,25))
i=0
C_array = [1e-2, 100, 1e5]
for C in C_array:
fig.add_subplot(311+i)
display_SVM_result(dat, labels, C)
i = i + 1
对结果的评论
上述例子很好地展示了当 C C C 增加时,边界变小。较高的 C C C 值对错误施加了更严格的惩罚。较小的值允许更宽的边界和更多的错误分类。因此, C C C 定义了边界最大化和分类错误之间的权衡。
整合代码
这是整合后的代码,你可以将其粘贴到你的 Python 文件中并在本地运行。你可以尝试不同的
C
C
C 值,并尝试 minimize()
函数中作为参数给出的不同优化方法。
Python
import numpy as np
# For optimization
from scipy.optimize import Bounds, BFGS
from scipy.optimize import LinearConstraint, minimize
# For plotting
import matplotlib.pyplot as plt
import seaborn as sns
# For generating dataset
import sklearn.datasets as dt
ZERO = 1e-7
def plot_x(x, t, alpha=[], C=0):
sns.scatterplot(dat[:,0], dat[:, 1], style=labels,
hue=labels, markers=['s', 'P'],
palette=['magenta', 'green'])
if len(alpha) > 0:
alpha_str = np.char.mod('%.1f', np.round(alpha, 1))
ind_sv = np.where(alpha > ZERO)[0]
for i in ind_sv:
plt.gca().text(dat[i,0], dat[i, 1]-.25, alpha_str[i] )
# Objective function
def lagrange_dual(alpha, x, t):
result = 0
ind_sv = np.where(alpha > ZERO)[0]
for i in ind_sv:
for k in ind_sv:
result = result + alpha[i]*alpha[k]*t[i]*t[k]*np.dot(x[i, :], x[k, :])
result = 0.5*result - sum(alpha)
return result
def optimize_alpha(x, t, C):
m, n = x.shape
np.random.seed(1)
# Initialize alphas to random values
alpha_0 = np.random.rand(m)*C
# Define the constraint
linear_constraint = LinearConstraint(t, [0], [0])
# Define the bounds
bounds_alpha = Bounds(np.zeros(m), np.full(m, C))
# Find the optimal value of alpha
result = minimize(lagrange_dual, alpha_0, args = (x, t), method='trust-constr',
hess=BFGS(), constraints=[linear_constraint],
bounds=bounds_alpha)
# The optimized value of alpha lies in result.x
alpha = result.x
return alpha
def get_w(alpha, t, x):
m = len(x)
# Get all support vectors
w = np.zeros(x.shape[1])
for i in range(m):
w = w + alpha[i]*t[i]*x[i, :]
return w
def get_w0(alpha, t, x, w, C):
C_numeric = C-ZERO
# Indices of support vectors with alpha<C
ind_sv = np.where((alpha > ZERO)&(alpha < C_numeric))[0]
w0 = 0.0
for s in ind_sv:
w0 = w0 + t[s] - np.dot(x[s, :], w)
# Take the average
w0 = w0 / len(ind_sv)
return w0
def classify_points(x_test, w, w0):
# get y(x_test)
predicted_labels = np.sum(x_test*w, axis=1) + w0
predicted_labels = np.sign(predicted_labels)
# Assign a label arbitrarily a +1 if it is zero
predicted_labels[predicted_labels==0] = 1
return predicted_labels
def misclassification_rate(labels, predictions):
total = len(labels)
errors = sum(labels != predictions)
return errors/total*100
def plot_hyperplane(w, w0):
x_coord = np.array(plt.gca().get_xlim())
y_coord = -w0/w[1] - w[0]/w[1] * x_coord
plt.plot(x_coord, y_coord, color='red')
def plot_margin(w, w0):
x_coord = np.array(plt.gca().get_xlim())
ypos_coord = 1/w[1] - w0/w[1] - w[0]/w[1] * x_coord
plt.plot(x_coord, ypos_coord, '--', color='green')
yneg_coord = -1/w[1] - w0/w[1] - w[0]/w[1] * x_coord
plt.plot(x_coord, yneg_coord, '--', color='magenta')
def display_SVM_result(x, t, C):
# Get the alphas
alpha = optimize_alpha(x, t, C)
# Get the weights
w = get_w(alpha, t, x)
w0 = get_w0(alpha, t, x, w, C)
plot_x(x, t, alpha, C)
xlim = plt.gca().get_xlim()
ylim = plt.gca().get_ylim()
plot_hyperplane(w, w0)
plot_margin(w, w0)
plt.xlim(xlim)
plt.ylim(ylim)
# Get the misclassification error and display it as title
predictions = classify_points(x, w, w0)
err = misclassification_rate(t, predictions)
title = 'C = ' + str(C) + ', Errors: ' + '{:.1f}'.format(err) + '%'
title = title + ', total SV = ' + str(len(alpha[alpha > ZERO]))
plt.title(title)
dat = np.array([[0, 3], [-1, 0], [1, 2], [2, 1], [3,3], [0, 0], [-1, -1], [-3, 1], [3, 1]])
labels = np.array([1, 1, 1, 1, 1, -1, -1, -1, -1])
plot_x(dat, labels)
plt.show()
display_SVM_result(dat, labels, 100)
plt.show()
dat, labels = dt.make_blobs(n_samples=[20,20],
cluster_std=1,
random_state=0)
labels[labels==0] = -1
plot_x(dat, labels)
fig = plt.figure(figsize=(8,25))
i=0
C_array = [1e-2, 100, 1e5]
for C in C_array:
fig.add_subplot(311+i)
display_SVM_result(dat, labels, C)
i = i + 1
进一步阅读
本节提供了更多关于该主题的资源,如果你想深入了解,可以参考这些资源。
书籍
- 模式识别与机器学习 由 Christopher M. Bishop 著
文章
-
支持向量机模式识别教程 由 Christopher J.C. Burges 著
API 参考
总结
在本教程中,你学会了如何从头开始实现 SVM 分类器。
具体来说,你学到了:
-
如何为 SVM 优化问题编写目标函数和约束
-
如何编写代码从拉格朗日乘子确定超平面
-
C 对确定边界的影响
你对本文讨论的支持向量机(SVM)有任何问题吗?在下面的评论中提问,我会尽力回答。