UCSD-机器学习基础笔记-全-

UCSD 机器学习基础笔记(全)

001:课程介绍 🎯

在本节课中,我们将要学习《机器学习基础》这门课程的整体介绍。课程将概述学习目标、核心内容、所需技能以及课程结构,帮助你为后续的学习做好准备。

欢迎来到《机器学习基础》课程。在本课程中,你将获得关于从数据构建模型并使用这些模型进行预测的密集训练。

我们将涵盖最广泛使用的机器学习方法,包括逻辑回归、支持向量机、核方法、主成分分析、随机森林、神经网络等。我们将看到这些方法在图像理解、情感分析、语言处理、性格测试等众多领域的应用。最重要的是,我们将深入探讨这些方法的基本原理。

我们不会将它们视为需要盲目遵循的“食谱”,而是将其理解为一旦掌握,就可以进行各种修改和改进的有趣方法。

数学基础 🔢

为了达到这种理解水平,我们将深入机器学习的数学基础。基本上我们需要三种类型的数学:概率论线性代数优化。我们将非常仔细地讲解这三个领域,因为它们对于掌握机器学习至关重要。

你将获得的技能 🛠️

那么,在课程结束时,你将获得哪些技能呢?以下是核心收获:

  • 第一项技能:对最广泛使用的机器学习方法有深入的熟悉度。它们是什么?如何工作?为何有效?它们适用于何种数据?各自的优缺点是什么?其内部机制如何?这将帮助你评估哪些方法最适合解决特定问题,并帮助你理解和解释所获得的结果。
  • 第二项技能:具备改造现有方法以适应特定应用的能力。有时直接使用现成的方法是可以的,但通常这无法达到你期望的性能水平。为了更上一层楼,你需要进行一些定制化工作,要么在现有方法基础上进行修改,要么对数据进行转换。本课程将教你如何进行有效的改造。
  • 第三项技能:本课程将为你打下足够扎实的机器学习基础,帮助你跟上这个飞速发展的领域。

课程实践与项目 💻

对于我们将学习的每一种方法,你都会获得一个或多个Jupyter笔记本。这些笔记本包含代码和可视化内容,展示了该方法在合适数据集上的应用。你可以使用它们并进行调整,以真正感受这些方法的工作原理。

课程还将包含编程项目。这些项目将给你机会跳出固有思维,创造性地在现有方法基础上构建新方案来解决新问题。在课程结束时,这些项目集合将构成一个作品集,即一系列独立的笔记本,你可以向他人展示,例如给你的朋友留下深刻印象。

关于讲师 👨‍🏫

以上是对课程的简要概述,接下来让我简单介绍一下我自己。我是加州大学圣地亚哥分校的教授,在这里工作了大约15年。我主要研究机器学习和算法,这两个是我最关心的领域。这门特定的课程DSE 220X,是紧密模仿我在这里所教的一门课程设计的,我希望将它开放给更广泛的受众。希望你喜欢它。


本节课中,我们一起学习了《机器学习基础》课程的整体框架。我们了解了课程将涵盖的核心机器学习方法、掌握这些方法所需的数学基础(概率论线性代数优化),以及通过课程你将获得的三项关键技能:深入理解主流方法、改造方法的能力和扎实的理论基础。此外,我们也了解了课程将通过Jupyter笔记本和编程项目提供丰富的实践机会。现在,你已经为开启机器学习之旅做好了准备。

002:课程导论 🚀

在本节课中,我们将要学习《机器学习基础》这门课程的整体框架、你将掌握的核心技能,以及课程背后的设计理念。

欢迎来到《机器学习基础》课程。在本课程中,你将深入学习如何从数据中构建模型,并利用这些模型进行预测。

我们将涵盖最广泛使用的机器学习方法,包括逻辑回归、支持向量机、核方法、主成分分析、随机森林、神经网络等。我们会看到这些方法在图像理解、情感分析、语言处理、性格测试等诸多领域的应用。最重要的是,我们将深入探究这些方法的基本原理。

我们不会将它们视为需要盲目遵循的“食谱”,而是将其理解为一旦掌握,就可以进行各种修改和改进的有趣方法。

数学基础 🔢

为了达到这种理解层次,我们将深入机器学习的数学基础。我们主要需要三类数学知识:概率论线性代数优化理论。我们将非常仔细地讲解这三个领域,因为它们对于掌握机器学习至关重要。

你将获得的技能 🛠️

那么,学完这门课程后,你将获得哪些技能呢?以下是核心收获:

首先,你将熟练掌握最常用的机器学习方法。你将了解它们是什么、如何工作、为何有效、适用于何种数据、各自的优缺点以及底层原理。这将帮助你评估哪些方法最适合解决特定问题,并帮助你理解和解释所得到的结果。

其次,你将获得改造现有方法以适应特定应用的能力。有时直接使用现成的方法是可以的,但通常其性能可能达不到你的期望。为了达到更高水平,你需要进行定制化操作,例如在现有方法基础上进行修改,或者对数据进行变换。本课程将教你如何进行有效的改造。

最后,本课程将为你的机器学习基础打下足够扎实的根基,帮助你跟上这个飞速发展的领域。

课程实践与项目 💻

对于我们将学习的每一种方法,你都会获得一个或多个Jupyter笔记本。这些笔记本包含代码和可视化内容,展示了该方法在特定数据集上的应用。你可以使用它们进行实验,真正感受这些方法是如何工作的。

课程还将包含编程项目。这些项目将给你机会跳出固有思维,创造性地在现有方法基础上构建新方案以解决问题。在课程结束时,这些项目集合将构成一个作品集,即一系列独立的笔记本,你可以向他人展示,例如给你的朋友留下深刻印象。

关于讲师 👨‍🏫

以上是对课程的概述,接下来让我简单介绍一下自己。我是加州大学圣地亚哥分校的教授,在这里任教大约15年。我的研究方向是机器学习和算法,这是我最关注的两个领域。这门《机器学习基础》课程,正是基于我在这里所教授的一门课程精心设计的,我希望将它开放给更广泛的受众。希望你喜欢这门课。


本节课中,我们一起学习了《机器学习基础》课程的整体目标、所需的数学基础、你将获得的核心技能,以及课程包含的实践环节。我们明确了本课程旨在帮助你深入理解而非机械套用方法,并为你未来的学习和创新打下坚实基础。

003:最近邻分类

在本节课中,我们将通过了解最古老且最持久的分类方法之一——最近邻分类,来初步感受机器学习。我们将以此方法为切入点,介绍分类问题的概念,并引入一些基本的机器学习术语,如训练集、测试集、训练误差和测试误差。我们将看到数据如何表示为欧几里得空间中的向量,以及如何计算这些向量之间的距离。所有这些都将为我们应用最近邻分类器奠定基础。

概述

我们将要解决的具体问题是:给定一张手写数字的图片或图像,我们需要判断它是哪个数字。例如,下图是一个数字“3”。

而这是一个“0”,那是一个“2”,那是一个“4”,那是一个“7”,等等。

传统方法的局限性

我们如何解决这个问题呢?一个想法是:数字“0”有一个环,“8”有两个环,“1”有一条直线,“4”有三条直线。我们可以编写一个小程序,让它接收一张图像,计算它有多少个环和多少条直线,以及这些环和直线的相对位置。也许我们可以利用这些信息,然后编写一套简单的规则来判断它是哪个数字。

然而,人们很久以前就尝试过这种方法,效果并不理想。第一个问题是手写体噪声非常大,因此识别环和直线的数量并不像看起来那么容易。此外,人们书写“7”、“2”等数字的方式存在巨大差异。因此,需要创建大量的规则来涵盖所有可能的情况。即使付出了所有这些努力,最终的系统效果仍然不佳。

机器学习方法

因此,今天我们来看一种截然不同的方法——机器学习方法。我们不再试图自己找出底层模式,而是让机器为我们找出这些模式。

机器要找出这些模式,需要大量数据。因此,首先我们需要收集一个带有正确标签的手写数字数据集。幸运的是,这样的数据集已经存在,它叫做MNIST数据集。它包含60,000张带标签的手写数字图像,我们可以使用这个训练集来学习一个分类器,即一个接收图像并输出其认为正确数字的函数。

MNIST还包含一个单独的测试集,有额外的10,000张图像。我们可以使用这个测试集来评估分类器的真实性能。

最近邻分类器

今天要讨论的分类方法可能是能想到的最简单的方法,它叫做最近邻分类。我们拥有包含60,000张图像的训练集。为了对一张新图像X进行分类,我们只需遍历这个训练集,找到与X最相似的图像,即X的最近邻,然后输出这个最近邻的标签。就是这样。

这非常简单。但为了实现它,我们确实需要一个距离的概念,即图像之间相似度的概念。事实上,我们首先需要考虑的是,我们如何表示这些图像?

图像表示与向量化

我们将用向量来表示每张图像。MNIST图像是28x28像素,总共有784个像素。每个像素本身是灰度值,其值在0到255之间,0表示纯黑,255表示纯白。

为了将这样的图像转换为向量,我们可以简单地将它拉伸成一个具有784个坐标的向量。具体做法是:首先复制第一行(前28个像素),然后是第二行(接下来的28个像素),依此类推,直到最后一行(第28行)。通过这种方式,每张图像都变成了一个784维的向量。

因此,我们的数据空间(记为X)是784维的欧几里得空间,写作R^784。我们的标签空间Y就是可能的数字集合{0, 1, 2, ..., 9}。

现在,我们有了表示数据的具体方法,可以讨论距离函数了。我们将如何计算两个784维向量之间的距离呢?

欧几里得距离

最常用的距离函数是欧几里得距离。让我们先回顾一下它在二维空间中的定义。下图是二维空间中的两个点X和Z。

它们之间的欧几里得距离就是连接它们的线段的长度。观察这两个点,它们在第一个坐标上相差2,在第二个坐标上相差3。因此,这条线段的长度是√(2² + 3²),即√13。这就是X和Z之间的欧几里得距离。

在高维空间中,公式基本相同。要计算X和Z之间的距离,我们只需看X和Z在每个坐标上的差值,将这些差值平方后求和,然后取总和的平方根。这就是欧几里得距离。我们将用双竖线符号来表示它,这个符号除非特别说明,否则总是指欧几里得距离。

公式distance(x, z) = √( Σ (x_i - z_i)² )

很好。现在我们可以应用最近邻分类了。我们拥有60,000张图像的训练集。为了对一张新图像X进行分类,我们将遍历这60,000张图像,找到在刚刚讨论的784维向量表示下,与X的欧几里得距离最近的那一张。我们找到那个最近邻,并返回它的标签。

分类器性能评估

那么这个分类器有多好,准确度如何?让我们看一些数字。我们有一个包含60,000个点的训练集,在这个训练集上的错误率是多少?对于每个训练点,它的最近邻就是它自己,所以它总能得到正确的标签。因此,训练误差是0。

正如你所看到的,训练误差通常不能很好地指示未来数据上的性能。这就是为什么我们有一个独立的测试集。测试集上的错误率,即测试误差,是衡量分类器质量的更好指标。

在这种情况下,我们可能期望什么样的错误率呢?在我们得到答案之前,先做一个小小的思想实验。一个随机分类器的错误率会是多少?这种分类器甚至不看数据,只是随机猜测一个0到9的数字。这种分类器的错误率会是多少?无论正确标签是什么,它猜中该标签的概率正好是1/10,所以它会有9/10的时间是错的。它的错误率将是90%。

那么最近邻分类器在测试集上的错误率是多少呢?结果是3.09%。这相当不错。总共有10,000个测试点,最近邻分类器弄错了309个。对于一个如此简单的分类器来说,这已经很好了。

现在,让我们看看最近邻分类器犯的一些错误。例如,对于这张图像,它的最近邻是下面这张图,所以它认为原图是“4”。

对于另一张图像,它的最近邻是下面这张图,所以它给出的标签是“8”。这些只是错误案例的随机示例。你可以看到,一旦你理解了分类器在做什么,这些错误其实相当容易理解。

总结

本节课中,我们一起学习了我们的第一个分类器——最近邻分类器。我们了解了如何将图像表示为高维向量,如何使用欧几里得距离来衡量相似度,以及如何利用带标签的训练集对新数据进行分类。我们还区分了训练误差和测试误差,并认识到测试误差是评估模型泛化能力的更可靠指标。虽然最近邻方法简单,但在手写数字识别任务上取得了不错的效果。下次课,我们将探讨如何改进这个分类器。

004:优化最近邻算法

概述

在本节课中,我们将学习如何改进基础的最近邻分类算法。我们将探讨两种主要方法:K最近邻算法和寻找更好的距离函数。同时,我们也会了解如何通过交叉验证选择最佳参数,以及如何处理特征选择和算法效率问题。


回顾基础最近邻分类

上一节我们介绍了最近邻分类的基础知识。我们尝试在MNIST手写数字数据集上应用最近邻算法,并发现它在独立测试集上取得了3.09%的错误率,这是一个相当不错的结果。算法也犯了一些错误。

提升性能的方法

为了进一步提升性能,我们来看两种标准方法。第一种是转向K最近邻算法,第二种是寻找更好的距离函数。


K最近邻分类

K最近邻分类是一个简单的想法。在执行最近邻分类时,我们不再只寻找测试集中最接近的一个点,而是寻找最接近的三个点或五个点。每个点都有一个标签,我们返回这些点中的多数标签或最常见的标签。

以下是K最近邻在MNIST数据集上的表现:

  • K=1 时,这就是我们之前看到的基础最近邻分类器,错误率为3.09%。
  • K=3 时,我们为每个新图像找到训练集中最接近的三个图像,并返回它们的多数标签。错误率略微下降到2.94%。
  • 当我们尝试更大的K值(如5、7、9等)时,错误率又开始上升。

需要重点说明的是,这些错误率是在独立的测试集上测量的。在训练集上测量错误率对于预测未来性能来说是一个非常差的指标。

在这个特定数据集上,调整K值有所帮助,但效果并不显著。在其他情况下,它有时会有很大帮助。


如何选择K值

在这个示例中,我们有一个独立的开发集,但在实际生活中通常没有。我们通常只有训练集。我们已经明确,训练集上的错误率并不能很好地反映实际错误率。

我们如何处理这个问题?这是一个相当棘手的问题,并且这个问题不仅限于最近邻算法。我们在机器学习中会反复遇到这种情况。我们研究的许多方法都有像K这样的参数需要正确设置。如果设置得当,方法就有效;如果设置不当,方法就无效。我们必须仅使用训练集来设置它们。

一个标准的方法是使用交叉验证

让我展示一下如何为K最近邻算法进行交叉验证。假设我们想评估一个特定的K值选择,例如K=3。我们想仅使用训练集来估计3最近邻的错误率。

以下是十倍交叉验证的工作原理:

  1. 我们取训练集(60,000个点),并将其分成10个相等的块,即每块6000个点。我们称这些块为S1, S2, ..., S10。
  2. 对于每个子集Si,我们执行以下操作:
    • 将该子集视为测试集。
    • 将剩余的九个子集视为训练集。
    • 对于Si中的每个点(6000个点),我们使用剩余的54,000个点对其进行分类。
    • 这将为我们得到Si的错误率,我们称之为εi。
  3. 当我们对每个部分都完成此操作后,我们就得到了这10个错误率ε1到ε10。其中每一个单独都是对K最近邻错误率的一个相当不错的估计。
  4. 为了得到更好的估计,我们对这10个错误率取平均值。这个平均值就是我们对于特定K值的K最近邻错误的最终估计。

当然,我们可能想尝试多个K值。我们会尝试K=1, K=3, K=5等等。在每种情况下,对于每个K值,我们都会运行十倍交叉验证,得到一个错误估计,然后选择错误估计最低的K值。这就是我们为K最近邻算法寻找最佳K值的方法。

这里我描述的是十倍交叉验证,因为我们把数据集分成了10等份。但我们也可以做五折交叉验证(分成5份,每份12,000点),或者八折、四折交叉验证等。


寻找更好的距离函数

我们已经看到了一种改进最近邻算法的方法,即通过观察更多邻居(K个邻居)而不仅仅是一个。另一种在许多情况下非常有效的策略是寻找更好的距离函数。

当我们在MNIST上运行最近邻算法时,我们使用了欧几里得距离。但实际上,欧几里得距离对于图像来说通常不是一个好的选择。

例如,看这两张图像。它们实际上是相同的,只是其中一张稍微向右滚动了一点。这对我们来说差别不大,但这意味着它们的向量表示完全不同,因此它们之间的L2距离实际上很大。显然,欧几里得距离对于图像来说不是一个好的选择。

我们想要的是提出一个不同的距离函数,一个不会因为图像轻微平移或旋转而发生巨大变化的距离函数。研究人员已经对此进行了研究,并提出了一种称为切线距离的距离函数。

更好的距离函数应该对更大范围的形变保持不变,不仅仅是小的平移和旋转,可能还包括将一条线稍微弯曲等。这种距离函数的一个例子叫做形状上下文

当你在最近邻算法中使用这些更好的距离函数时,MNIST上的性能会如何?我们可以看到,性能显著提高。例如,使用形状上下文时,错误率远低于1%。

总的来说,利用领域知识选择更好的数据表示、更好的距离函数和相似性函数,对于分类任务可能非常有益。如果你真的想要一个准确的分类器,这可能是非常值得投入精力的。


特征选择

选择距离函数的一个方面首先是选择正确的特征。在MNIST的例子中,我们使用的特征是图像中的784个独立像素,这些特征可以说都与分类相关。

但在许多其他情况下,数据中有很多特征与手头的分类任务完全无关。例如,假设你正在构建一个分类器来处理贷款申请,并试图判断申请人是否有违约风险。在这种情况下,贷款申请数据包含很多有用信息,如年龄、收入等,但也包含很多完全不相关的信息,如社会安全号码。如果你不删除这些特征,它们可能会严重干扰最近邻算法。距离计算可能完全由这些特征主导。

这里有一个图示说明。在左边,我们有一个一维数据集,有两个标签:红色和蓝色。具有较小x值的点是红色,具有较大x值的点是蓝色,它们很好地分开了,最近邻算法在这个一维数据上会表现得非常好。

在右边,我们决定添加一个沿x2轴的额外特征。这个特征完全无关,并且完全破坏了最近邻算法的性能。例如,假设这些点是训练点。这个测试点会如何分类?它的最近邻是这个点,所以它会被分类为红色,但这并不好。这个点会如何分类?它的最近邻是这个点,所以它会被分类为蓝色,同样很糟糕。

因此,在使用最近邻算法之前,特征选择非常重要。


算法效率

到目前为止,我们一直在讨论提高最近邻算法的统计性能,即提高其分类准确率。但另一个非常重要的事情是算法的效率方面。

如果训练集很大,最近邻搜索实际上可能相当慢。例如,当我们在MNIST上做最近邻时,为了分类一个新图像,我们必须查看60,000个训练图像。这并不令人愉快。你能想象如果训练集有100万张或1亿张图像吗?那将使最近邻算法完全不切实际。

更正式地说,如果有一个大小为N的训练集,一个朴素的最近邻搜索需要与N成正比的时间,这非常糟糕。好消息是,这个问题已经被研究了几十年,人们已经提出了各种数据结构来显著加速最近邻搜索。这些数据结构有诸如局部敏感哈希球树k-d树等名称,还有很多其他类型。主要的是要意识到它们的存在。例如,它们是Python标准库的一部分。在某些情况下,它们可以将搜索时间从大约N减少到大约log N,总的来说,它们非常有帮助。


总结

在本节课中,我们一起学习了如何优化最近邻算法。我们介绍了K最近邻算法,它通过考虑多个最近邻的多数投票来提升稳定性和可能的效果。我们学习了使用交叉验证(如十倍交叉验证)来仅基于训练数据选择最佳K值等超参数。我们还探讨了改进距离函数的重要性,例如针对图像任务的切线距离形状上下文,并强调了特征选择对于消除无关或干扰特征的关键作用。最后,我们提到了处理大规模数据时算法效率的问题,以及使用如局部敏感哈希球树等专用数据结构来加速搜索的必要性。

最近邻算法是我们进入机器学习的第一个窗口,我们用它讨论了训练误差与测试误差、特征选择和交叉验证等基本概念。很快我们将遇到各种其他分类方法,但最近邻是其中最古老、最简单且最灵活的方法之一。

005:距离函数 📏

在本节课中,我们将学习机器学习中至关重要的距离函数。我们将介绍两类核心的距离函数:Lp范数度量空间,并通过具体例子理解它们的特点和应用场景。


Lp范数家族 📐

上一节我们讨论了最近邻分类,并强调了选择合适距离函数的重要性。本节中,我们来看看一类在机器学习中反复出现的距离函数——Lp范数。

在M维欧几里得空间中,如何测量两点间的距离?最直观的是L2距离,即我们通常用直尺测量的“直线距离”。然而,L2距离只是Lp距离家族中的一员。

Lp距离的通用公式如下,其中P可以是1到无穷大之间的任意数:

公式: d(x, z) = ( Σ |x_i - z_i|^p )^(1/p)

计算两个向量x和z之间的Lp距离时,需要:

  1. 计算每个坐标上差值的绝对值。
  2. 将每个差值的P次方相加。
  3. 对总和取P次方根。

以下是三个最常用的Lp距离:

  • L1距离 (曼哈顿距离):当P=1时得到。其距离是各坐标差值绝对值的直接求和。形象地说,它像是只能沿水平和垂直方向行走的网格城市中的距离。
    公式: d(x, z) = Σ |x_i - z_i|

  • L2距离 (欧几里得距离):当P=2时得到。这是我们最熟悉的“直线距离”。
    公式: d(x, z) = sqrt( Σ (x_i - z_i)^2 )

  • L∞距离 (切比雪夫距离):当P趋近于无穷大时得到。其距离是各坐标差值中最大的那个。
    公式: d(x, z) = max_i |x_i - z_i|


Lp范数示例 🔍

为了更好地理解这些距离,让我们通过计算向量长度和绘制单位“圆”来看一些具体例子。

示例1:计算向量长度
考虑一个D维向量,其所有分量均为1:x = (1, 1, ..., 1)。其长度定义为该点到原点(零向量)的距离。

以下是该向量在不同范数下的长度:

  • L2范数sqrt(1^2 + 1^2 + ... + 1^2) = sqrt(D)
  • L1范数|1| + |1| + ... + |1| = D
  • L∞范数max(1, 1, ..., 1) = 1

可以看到,不同的范数给出了截然不同的“长度”值。

示例2:二维空间中的单位“圆”
在二维平面(R²)中,所有到原点距离为1的点构成的集合,在不同范数下形状不同:

  • L2单位圆:满足 sqrt(x1² + x2²) = 1 的点集。这是一个标准的圆形。
  • L1单位“圆”:满足 |x1| + |x2| = 1 的点集。其形状是一个菱形(或称旋转45度的正方形)。
  • L∞单位“圆”:满足 max(|x1|, |x2|) = 1 的点集。其形状是一个标准的正方形。

度量空间:更广义的距离 ⚖️

Lp范数虽然常用,但并非适用于所有场景。很多时候我们需要为特定领域(如字符串、图)定制距离函数。这就需要更广义的距离概念——度量

一个在任意数据空间X上定义的函数d(x, y)被称为度量,当且仅当它满足以下四个性质:

  1. 非负性d(x, y) >= 0。距离永远不为负。
  2. 同一性d(x, y) = 0 当且仅当 x = y。只有点到自身的距离为零。
  3. 对称性d(x, y) = d(y, x)。从x到y的距离等于从y到x的距离。
  4. 三角不等式d(x, z) <= d(x, y) + d(y, z)。经过第三点的距离总不小于直接距离。

如果一个距离函数是度量,我们就可以利用许多高效的算法(如某些加速最近邻搜索的数据结构)来处理它。


度量示例 ✅

让我们验证两个常见的距离函数是否为度量。

示例1:L1距离是度量
对于M维空间中的向量,L1距离定义为:d(x, z) = Σ |x_i - z_i|

  • 非负性:绝对值保证结果非负。
  • 同一性:若x=z,每个差值为0,总和为0;若总和为0,则每个差值必为0,故x=z。
  • 对称性:绝对值运算满足对称性。
  • 三角不等式:对每个坐标,|x_i - z_i| <= |x_i - y_i| + |y_i - z_i| 成立,求和后整体不等式依然成立。
    因此,L1距离是一个度量。实际上,所有Lp距离都是度量。

示例2:编辑距离是度量
编辑距离用于衡量两个字符串的相似度,定义为将字符串x转换为字符串y所需的最少插入、删除、替换操作次数。

  • 非负性:操作次数非负。
  • 同一性:相同字符串无需操作,距离为0;距离为0意味着无需操作,字符串相同。
  • 对称性:插入操作的反向是删除,因此从x到y的操作序列反向即是从y到x的操作序列。
  • 三角不等式:将x转为z的操作,可以通过先由x转为y,再由y转为z来实现,因此前者步骤数不会多于后两者步骤数之和。
    因此,编辑距离也是一个度量

非度量距离示例 ❌

度量性质看似基本,但实践中我们有时不得不使用非度量的距离函数。一个典型且极其重要的例子是KL散度,它用于衡量两个概率分布之间的差异。

给定两个定义在相同结果集上的概率向量P和Q(例如,P=(1/2, 1/4, 1/8, 1/8)Q=(1/6, 1/3, 1/3, 1/6)),KL散度定义为:

公式: D_KL(P || Q) = Σ P(i) * log( P(i) / Q(i) )

KL散度不是一个度量,因为它:

  • 不满足对称性D_KL(P || Q) ≠ D_KL(Q || P)
  • 不满足三角不等式
    尽管它不满足度量的条件,但KL散度在机器学习(特别是在信息论和概率模型比较中)被广泛使用。

总结 📝

本节课我们一起学习了机器学习中的核心概念——距离函数。

  1. 我们介绍了Lp范数家族,重点掌握了L1、L2和L∞距离的定义、计算和几何意义。
  2. 我们探讨了更广义的度量空间概念,了解了成为度量必须满足的四个性质,并验证了L1距离和编辑距离都是度量。
  3. 最后,我们认识到并非所有有用的距离都是度量,KL散度作为一个重要的非度量距离函数,在比较概率分布时不可或缺。

理解不同距离函数的特性,对于后续选择模型、设计算法至关重要。与距离函数互补的另一个概念是相似度函数,我们将在后续课程中深入探讨。

006:预测问题概述

在本节课中,我们将学习机器学习中的核心概念——预测问题。我们将从机器学习与算法的区别讲起,然后正式定义预测问题,并按照输出空间的类型对其进行分类。最后,我们将概览本课程后续的学习路线。

机器学习与算法

上一节我们提到了手写数字分类的例子,这是一个预测问题。在深入探讨之前,我们先来看看机器学习与算法的异同。

在当今的计算机世界中,机器学习和算法是两项核心技术。有趣的是,这两个领域有一个共同的核心目标:开发能够实现特定输入输出功能的程序或代码片段。

在算法领域,人们花费数十年时间寻找在图中计算两点间最短路径的好方法。输入是一个图以及图中的两个节点,期望的输出是这两个节点之间的最短路径。算法是一系列从输入导向期望输出的精确步骤。

在机器学习领域,我们也希望找到能从输入映射到期望输出的程序。但我们处理的问题性质不同,通常很难列出一套能直接得到输出的精确步骤。

例如,假设输入是一张动物的图片,期望的输出是动物的名称。很难想象能有哪些精确的步骤来完成这个任务。事实上,这个问题甚至没有精确的定义。因此,我们不是自己设计算法,而是收集大量输入输出对的示例,然后让机器自行找出一个映射关系。

预测问题的形式化定义

上一节我们介绍了机器学习与算法的区别,本节中我们来看看预测问题的正式定义。

这是一个预测问题。存在一个输入空间,我们通常称之为 X,例如所有动物图片的集合。同时存在一个输出空间,例如动物名称的集合。

我们心中有一个从输入到输出的期望映射,但这个映射通常无法被我们精确地描述。因此,我们收集一个由 XY 示例组成的训练集。学习机器接收这个训练集,并利用它来选择一个从 XY 的映射函数。这个函数接收一张动物图片,并返回它认为正确的动物名称。

通常,学习算法的工作方式是寻找一个在训练集上表现良好的函数或映射。

预测问题的分类

我们已经讨论了预测问题的定义,接下来看看如何对它们进行分类。预测问题种类繁多,一种常见的分类方式是依据输出空间的类型。我们通常区分以下三种情况:

  • 当输出空间是离散的。
  • 当输出空间是连续的。
  • 当输出空间由概率值组成。

事实证明,这三种情况需要的方法有所不同。

分类问题:离散输出

以下是当输出为离散值时的情况,我们称之为分类

  • 二分类:最简单的设置是二分类,只有两种可能的输出,例如好/坏、正/负、是/否。在垃圾邮件检测中,输入 X 是电子邮件,期望的输出只是“垃圾邮件”或“非垃圾邮件”。
  • 多分类:在分类问题中,通常存在多于两种可能的输出。例如,输入是一篇新闻文章,期望的输出是文章的主题,如政治、商业、科技、体育、娱乐等。
  • 结构化输出:也存在期望输出是离散的,但具有更复杂组合结构的情况。例如在句法分析中,输入是一个句子(如“John hit the ball”),期望的输出是该句子的句法分析树。输出空间仍然是有限的、离散的,但比简单的类别标签更复杂,具有特定的结构。

我们将投入大量精力研究二分类,因为这是一个研究预测问题的简洁而简单的设置。我们将发现,我们开发的方法可以很容易地推广到其他两种设置,即多分类和结构化输出。

回归问题:连续输出

上一节我们讨论了离散输出的分类问题,本节中我们来看看当输出为连续值时的情况,这被称为回归问题

以下是几个回归问题的例子:

  • 预测污染水平:假设我们想预测明天的污染水平,因为这有助于我们决定是否让孩子明天外出。衡量污染水平的一个常见方法是空气质量指数。这是一个正数,如果小于100意味着空气质量尚可,大于100则不佳,超过200则意味着空气非常危险。输出空间由正数组成,是一个连续空间。即使我们只预测整数值,我们仍然将其视为连续空间,因为预测值100与101或102非常接近,而与200相差甚远。换句话说,这些值位于一个尺度上。
  • 保险公司计算:保险公司在你申请保单时感兴趣的一件事是,他们预计你还能活多久。这决定了他们向你收取的费用。这里,我们想要预测的数字 y 是你的死亡年龄,假设范围在0到120岁之间。同样,我们总是可以将其四舍五入到最接近的整数,但我们仍然将其视为一个连续体,因为这些数字位于一个尺度上。

一个有趣的问题是,对于这类回归问题,什么是合适的预测变量?以预测寿命为例,这是一个被深入研究过的领域。人们使用的信息包括你的年龄、性别(女性往往寿命更长)、是否吸烟、是否有高血压及是否服药、是否有高胆固醇及是否服药等。

概率估计问题

上一节我们介绍了回归问题,本节中我们来看看最后一种输出空间类型:当 Y 代表概率值时的情况。

这里,输出空间就是字面意义上的0到1的范围。这看起来有点像回归,因为它是一个连续范围。但事实证明,这种特殊情况确实需要专门的方法,因此我们倾向于将其单独处理。

以下是概率估计问题的一个例子:

  • 信用卡欺诈检测:输入 X 是信用卡交易的详细信息,例如购买金额、购买物品、商户名称、邮政编码等。我们希望预测的输出 y 是这笔交易是欺诈交易的概率。

一个有趣的问题是:为什么不将其视为二分类问题?为什么我们要预测概率,而不是直接说只有两种可能的标签(欺诈或合法)?这是一个很好的问题。

原因在于,这个预测的结果将被用作更大决策框架的一部分。它只是决策所需信息中的一项。例如,如果一笔交易具有很高的欺诈概率,那么当然应该拒绝该交易。但如果一笔交易具有很低的欺诈概率,是否应该接受?如果它只有很小但显著的欺诈概率,我们是接受还是拒绝?这可能取决于其他因素,比如交易金额。如果是一笔小额交易,也许可以承担风险;如果是一笔大额交易,则可能应该拒绝。为了正确评估风险,拥有一个实际的概率值而不仅仅是二元的预测(欺诈或合法)是非常有用的。

课程路线图

我们已经详细讨论了预测问题,这确实是机器学习的核心内容,我们将在课程中花费大量时间学习它。

除了预测问题,还有其他类型的问题吗?通常,我们收到一个数据集,只是想更好地理解它,不一定有特定的预测任务。我们只想知道数据中是否有有趣的结构,例如是否存在聚类。

属于这一范畴的主题,我们可以称之为表示学习,包括聚类、投影、字典学习等。我们也会花一些时间学习这些内容。

最后,我们将学习深度学习,从某种意义上说,它是结合表示学习和预测问题的一种方式。

总结

本节课中,我们一起学习了机器学习中的预测问题。我们从机器学习与算法的区别入手,形式化地定义了预测问题,并按照输出空间的类型(离散、连续、概率)将其分为分类、回归和概率估计三类。我们还简要了解了表示学习和深度学习。希望这让你对课程内容有了清晰的了解。下次课,我们将开始系统地学习分类问题。

机器学习基础:07:分类的生成式方法 🧠

在本节课中,我们将学习一种构建分类器的简单而强大的方法——生成式方法。该方法基于概率分布,核心思想是为每个类别分别拟合一个概率模型。

概述

生成式方法的主要思想是为每个类别单独拟合一个概率分布。例如,对于一个包含“加号”和“减号”两类标签的训练集,我们会先仅查看“加号”类别的数据点,并为其拟合一个概率分布模型;然后,仅查看“减号”类别的数据点,并为其拟合另一个概率分布模型。

学习过程结束后,当一个新的数据点需要分类时,我们只需判断这个新点更可能来自哪个类别的概率分布,即计算它在哪个分布下的概率更高,从而将其归入该类别。

接下来,我们将通过一个更具体的例子来详细说明这一过程。

具体示例:一维数据与三个类别

假设我们有一个简单的数据集,数据点只有一个特征,因此是一维的,可以绘制在一条直线上。标签空间Y包含三个类别:1、2和3。

以下是构建生成式模型的步骤:

首先,我们分别处理每个类别的数据。

  • 为类别1拟合分布:我们仅查看训练集中标签为1的点,并为其拟合一个概率分布。我们称这个分布为 P₁(x)
  • 为类别2拟合分布:同样,仅查看标签为2的点,并拟合分布 P₂(x)
  • 为类别3拟合分布:最后,查看标签为3的点,拟合分布 P₃(x)

此外,我们还需要每个类别在训练集中的先验概率。例如:

  • 类别1占训练集的10%,因此 π₁ = 0.1
  • 类别2占训练集的50%,因此 π₂ = 0.5
  • 类别3占训练集的40%,因此 π₃ = 0.4

至此,对于每个类别j(j=1,2,3),我们拥有两部分信息:

  1. 该类别的先验概率 πⱼ(一个数值)。
  2. 该类别的数据分布 Pⱼ(x)

联合分布与分类决策

这些信息足以完整地定义特征X和标签Y的联合概率分布。任意数据点x和标签y同时出现的概率可以表示为:

P(x, y) = P(y) × P(x | y) = πᵧ × Pᵧ(x)

现在,当一个新的数据点x到来需要分类时,我们如何为其分配标签y呢?答案是:选择那个能使联合概率 P(x, y) 最大的标签y。

具体到我们的三分类例子,决策过程如下:

对于新点x,我们计算三个值:

  1. π₁ × P₁(x)
  2. π₂ × P₂(x)
  3. π₃ × P₃(x)

然后,我们比较这三个计算结果,并选择数值最大的那个所对应的类别作为预测标签。例如,如果第三个值最大,我们就将x分类为类别3

总结

本节课我们一起学习了分类的生成式方法。其核心流程是:为每个类别独立地估计一个概率分布模型(Pⱼ(x))和先验概率(πⱼ)。在预测时,通过贝叶斯定理计算后验概率,并选择能使联合概率 πᵧ × Pᵧ(x) 最大的类别作为预测结果。

这种方法建立在一套完整的概率论框架之上。为了更深入地理解和实现它,我们将在接下来的课程中回顾相关的概率论概念,并进一步充实这个方法的细节。

008:概率论回顾 I

在本节课中,我们将回顾概率论的基础知识,为后续深入学习用于分类的生成模型做好准备。我们将定义随机实验的概率空间,学习如何描述我们感兴趣的事件,并理解一个事件如何影响另一个事件的概率。所有这些都将最终引向贝叶斯定理,这是机器学习和统计中进行概率推理的核心公式。

概率空间

为了在机器学习中取得进展,你需要熟练掌握三种数学知识:概率论、线性代数和优化。其中,概率论可能是大家最熟悉的部分。为了确保基础扎实,我们将进行一个分为三部分的回顾。

概率空间是对一个随机实验所需全部信息的总结,用于回答关于该实验的问题。

让我们看一个具体例子。假设我们掷两个骰子,我们想知道它们点数之和为10的概率是多少?

这是一个随机实验。该实验的概率空间包含两个组成部分:

  1. 所有可能结果的集合,称为样本空间
  2. 每个结果的概率。

以下是该实验的可能结果:

  • 第一个骰子是4,第二个骰子是2,我们记为 (4, 2)。
  • 第一个骰子是1,第二个骰子是6,记为 (1, 6)。

样本空间是所有可能结果的集合,即所有类似这样的有序对 (Z1, Z2) 的集合。因此,样本空间包含 (1,1), (1,2), ..., (1,6), (2,1), ..., (6,6)。总共有 6 × 6 = 36 种可能结果。

我们可以更简洁地将其写为:

  • 公式样本空间 = {1, 2, 3, 4, 5, 6} × {1, 2, 3, 4, 5, 6} = {1, 2, 3, 4, 5, 6}^2

由于所有结果出现的可能性相同,每个结果的概率都是 1/36。这就是该实验的样本空间。

事件与概率计算

上一节我们定义了概率空间,本节我们来看看如何描述我们关心的事件。

我们关心的事件是“两个骰子点数之和为10”,我们想知道这个事件的概率。让我们称这个事件为 A

一个事件就是可能结果的一个子集。具体来说,事件 A 包含所有满足 Z1 + Z2 = 10 的有序对 (Z1, Z2)。

那么哪些有序对满足条件呢?

  • 如果第一个骰子是4,第二个必须是6:(4, 6)
  • 如果第一个骰子是5,第二个必须是5:(5, 5)
  • 如果第一个骰子是6,第二个必须是4:(6, 4)

因此,事件 A 由36个可能结果中的3个组成。如果我们用文氏图表示,整个样本空间有36个点,事件 A 是其中的3个点。

每个结果的概率是 1/36,所以事件 A 的概率是:

  • 公式P(A) = 3 × (1/36) = 1/12

这就是我们定义事件并计算其概率的方法。

条件概率与贝叶斯定理

在统计学和机器学习中使用概率时,我们通常不只处理一个事件,而是处理多个事件。例如,我们测量病人的体温和血压,并想知道病人是否患有某种疾病。这涉及到三个事件的组合:病人有特定血压的事件、有特定体温的事件以及患有疾病的事件。我们可以观察到其中两个事件(体温和血压),并想知道它们从概率上告诉我们关于第三个未观察到但关心的事件(疾病)的什么信息。

让我们看一个这类问题的具体例子。

假设你面前有10枚硬币,它们看起来一样,但实际不同。其中9枚是正常的公平硬币(正反面概率各半),但第10枚是坏硬币,总是反面朝上。你闭上眼睛随机挑选一枚硬币,然后抛掷它四次,发现每次都是反面。请问你挑到坏硬币的概率是多少?

首先,确定这个随机实验的样本空间。实验过程是:先随机选一枚硬币,然后抛掷四次。我们可以这样描述一个结果:先写我们选了哪枚硬币(编号1到10,假设10是坏硬币),然后写四次抛掷的结果(H 或 T)。因此,所有可能结果的集合是:

  • 公式样本空间 = {1, 2, ..., 10} × {H, T}^4
    总共有 10 × 2^4 = 160 种可能结果。

现在,定义我们关心的事件:

  • 事件 A:我们挑到了坏硬币。形式化地,A 是所有“硬币编号为10”的结果的集合。
  • 事件 B:我们观察到四次抛掷都是反面。形式化地,B 是所有“四次抛掷结果都是 T”的结果的集合。

我们想知道的是:在已知事件 B(四次都是反面)发生的条件下,事件 A(挑到坏硬币)发生的概率,即 P(A|B)

为了计算这个,我们需要用到条件概率的基本公式。对于任意两个事件 A 和 B,条件概率 P(B|A) 表示在已知 A 发生的情况下 B 发生的概率。其基本公式是:

  • 公式P(A ∩ B) = P(A) × P(B|A)
    这个公式表示“A 和 B 同时发生”的概率等于“A 发生”的概率乘以“在 A 发生的条件下 B 发生”的概率。

回到我们的例子,我们可以计算 P(A ∩ B):

  • P(A) = 1/10 (10枚中挑到坏硬币的概率)
  • 如果挑到坏硬币(A发生),那么四次都是反面(B发生)的概率是 1,因为坏硬币总是反面。所以 P(B|A) = 1。
  • 因此,P(A ∩ B) = (1/10) × 1 = 1/10

接下来,我们需要计算 P(B),即“四次都是反面”的总概率。这取决于我们是否挑到了坏硬币,所以我们可以分情况计算:

  • 情况1:挑到坏硬币(A发生)且四次都是反面。概率为 (1/10) × 1 = 1/10
  • 情况2:没挑到坏硬币(A不发生)但四次都是反面。概率为 (9/10) × (1/2)^4 = 9/10 × 1/16 = 9/160
  • 因此,P(B) = 1/10 + 9/160 = 25/160 = 5/32

现在,我们可以计算我们最终想要的概率 P(A|B):

  • 公式P(A|B) = P(A ∩ B) / P(B) = (1/10) / (5/32) = 32/50 = 16/25 = 0.64

所以,在观察到四次都是反面的条件下,我们挑到坏硬币的概率是 64%。这个结果相当显著。

贝叶斯定理

在我们进行上述计算时,我们隐式地使用了贝叶斯定理,这是统计和机器学习中进行概率推理的核心公式。

贝叶斯定理描述的是:当我们观察到某个事件 B 发生后,如何更新我们对另一个事件 A 发生的概率的信念。

其公式如下:

  • 公式P(A|B) = [P(A) × P(B|A)] / P(B)

这个公式可以这样理解:

  • P(A)先验概率,即在没有任何新信息(未观察到 B)时,我们认为 A 发生的概率。
  • P(A|B)后验概率,即在观察到 B 发生后,我们更新得到的 A 发生的概率。
  • 公式中的比值 P(B|A) / P(B) 可以看作一个修正因子,它根据新证据 B 来调整我们先前的信念 P(A)。

贝叶斯定理的推导很简单,就是两次应用条件概率的定义:

  1. P(A|B) = P(A ∩ B) / P(B) (条件概率定义)
  2. P(A ∩ B) = P(A) × P(B|A) (条件概率定义)
  3. 将第2步代入第1步,即得贝叶斯定理。

我们今天所做的各种计算看似简单,但实际上非常强大。贝叶斯定理告诉我们如何在不确定性下进行推理,因此毫不奇怪,它是机器学习中进行推断的基本公式之一。

总结

本节课我们一起回顾了概率论的基础知识。我们首先学习了如何为随机实验定义概率空间,包括样本空间和每个结果的概率。接着,我们探讨了如何描述事件并计算其概率。最后,我们深入研究了条件概率,并通过一个硬币挑选的例子,推导并应用了机器学习和统计中的核心公式——贝叶斯定理。贝叶斯定理为我们提供了在获得新证据后更新概率信念的数学框架,是后续学习生成模型等高级主题的重要基石。

009:一维生成模型 🍷

在本节课中,我们将学习生成式分类方法,并将其应用于一个简单的实际问题:根据葡萄酒的酒精含量来预测其生产酒庄。我们将使用一维高斯分布对每个类别的数据进行建模,并构建一个分类器。


概述

我们之前简要介绍了分类的生成式方法。今天,我们将在一个包含三个类别的简单一维数据集上实际应用这种方法。我们将看到如何通过为每个类别拟合一个高斯分布来对数据进行分类。

问题设定:识别葡萄酒酒庄

我们遇到的问题是:有一瓶葡萄酒,我们很喜欢它,但它的标签丢失了。我们想弄清楚它来自三个酒庄中的哪一个。我们将采用机器学习方法,测量这瓶酒的一些视觉和化学特征,并用这些特征来预测其标签(1、2或3)。

我们有一个训练集来帮助我们。这个训练集来自130瓶酒:43瓶来自酒庄1,51瓶来自酒庄2,其余36瓶来自酒庄3。对于每一瓶酒,我们测量了13个特征(如类黄酮、脯氨酸和镁含量等)。因此,每个数据点本质上是一个13维向量。

我们将使用这些数据构建一个分类器,该分类器接收新酒瓶的特征并预测其标签。此外,我们还有一个包含48个标记点的独立测试集,用于评估分类器的性能。

生成式方法回顾

上一节我们介绍了生成式分类的基本思想。本节中,我们来看看如何具体应用。生成式方法需要为每个酒庄单独拟合一个分布。对于酒庄1,我们拟合分布 P₁(x);对于酒庄2,拟合 P₂(x);对于酒庄3,拟合 P₃(x)。我们还需要知道每个标签的先验概率:酒庄1的葡萄酒所占比例 π₁,酒庄2的比例 π₂,酒庄3的比例 π₃。这些概率之和为1。

当我们得到一瓶新酒,其特征向量为 x 时,我们预测的类别 j 是使 πⱼ * Pⱼ(x) 最大的那个类别。这是因为根据贝叶斯规则,给定特征 x 时,标签为 j 的概率与 πⱼ * Pⱼ(x) 成正比。分母与 j 无关,因此可以忽略。

计算类别先验概率

首先,我们需要计算每个类别的先验概率(权重)。

以下是计算过程:

  • 酒庄1的权重:π₁ = 43 / 130 ≈ 0.33
  • 酒庄2的权重:π₂ = 51 / 130 ≈ 0.39
  • 酒庄3的权重:π₃ = 36 / 130 ≈ 0.28

可以看到,这三个数字相加等于1。拟合类别权重通常非常简单。

为每个类别拟合分布

更困难的部分是为每个类别拟合一个分布。我们的数据有13个特征,是一个13维数据集。为了简化,我们暂时只选取其中一个特征:酒精含量。这样,我们就把数据降到了一维。我们很好奇,仅凭酒精含量能多好地预测酒庄。

现在,我们需要为酒庄1的酒精含量数据拟合一个分布,为酒庄2和酒庄3的酒精含量数据也各拟合一个分布。我们选择哪种一维分布呢?默认的选择是高斯分布(正态分布)。

一维高斯分布

一维高斯分布就是熟悉的钟形曲线。它由两个参数指定:均值 μ 和方差 σ²。标准差 σ 是方差的平方根。我们使用简写 N(μ, σ²) 来表示这个分布。

其概率密度函数由以下公式给出:

P(x) = (1 / √(2πσ²)) * exp(-(x - μ)² / (2σ²))

关于这个分布,我们可以说:

  • 它以均值 μ 为中心。
  • 关于均值对称。
  • 大约三分之二的分布落在均值的一个标准差范围内。
  • 大约95%的分布落在均值的两个标准差范围内。

为酒庄1拟合高斯分布

我们使用一个特征:酒精含量。酒庄1有43瓶酒的数据,即43个酒精含量数值。下图是这些数值的直方图,由于数据点少,直方图显得很锯齿状。

为了拟合高斯分布,我们需要计算出这43个数值的均值和方差。这非常快,只需几行代码。

我们得到的结果是:

  • 均值 μ₁ = 13.72
  • 标准差 σ₁ = 0.44
  • 方差 σ₁² ≈ 0.2

图中红色的平滑曲线就是我们为酒庄1拟合的分布密度函数 P₁(x)

为酒庄2和酒庄3拟合高斯分布

我们对酒庄2和酒庄3进行完全相同的操作。

以下是拟合结果:

  • 酒庄2(51个数据点):均值 μ₂ = 12.3,方差 σ₂² ≈ 0.28
  • 酒庄3(36个数据点):均值 μ₃ = 13.2,方差 σ₃² ≈ 0.27

图中显示了三条曲线:P₁(x)(红)、P₂(x)(黑)、P₃(x)(绿),分别对应三个类别的分布。

使用模型进行分类

现在,我们有了所有信息:先验概率 πⱼ 和每个类别的分布 Pⱼ(x)。我们如何对一瓶新酒进行分类呢?

当我们得到一瓶新酒,测量其酒精含量 x 后,我们选择使 πⱼ * Pⱼ(x) 最大的那个类别 j(1、2或3)。

让我们看几个例子:

  1. 如果新酒的酒精含量是 15,那么酒庄2和酒庄3的分布在该点的密度几乎为零,因此我们会选择酒庄1(红色曲线)。
  2. 如果酒精含量是 11,那么我们会选择酒庄2(黑色曲线)。
  3. 如果酒精含量是 12.5,酒庄1的密度很低,我们会在酒庄2和酒庄3之间选择。由于 π₂ (0.39) > π₃ (0.28),即使两者密度相近,我们最终也会选择酒庄2。

模型性能评估

我们将这个分类器应用于包含48个数据点的测试集。结果它错误分类了14个点。

因此,测试错误率为:

测试错误率 = 14 / 48 ≈ 29%

这个结果并不算很好,但远比随机猜测(约67%错误率)要强。

总结

本节课中,我们一起学习了如何应用生成式方法构建我们的第一个分类器。我们通过一个葡萄酒酒庄识别的例子,演示了如何:

  1. 计算类别的先验概率。
  2. 为每个类别的数据(这里简化为一维酒精含量)拟合高斯分布。
  3. 结合先验概率和似然(分布密度)使用贝叶斯规则对新样本进行分类。

该分类器的性能一般(29%错误率),主要是因为仅使用了单一特征。当我们引入更多特征时,其性能将能得到显著提升。为了理解如何做到这一点,我们将在接下来的课程中进一步深入概率论的知识。

010:概率论复习(二)📊

在本节课中,我们将要学习概率论的核心概念之一:随机变量。我们将了解什么是随机变量,以及如何计算它们的期望值、方差和标准差。

随机变量是什么?

在上一节中,我们介绍了概率空间的概念。现在,我们准备进入下一个主要概念:随机变量。

随机变量究竟是什么?我们如何计算它们的期望值、方差和标准差?

让我们从一个例子开始。假设你掷两个骰子,并且只关心它们的点数之和。我们称这个和为 X

例如,如果第一个骰子是1,第二个也是1,那么 X = 2。如果第一个是1,第二个是2,那么 X = 3,依此类推。

在这种情况下,概率空间有36种不同的结果(第一个骰子有6种可能,第二个也有6种可能)。但我们只关心结果的一个特定方面:两个骰子的点数之和。这个我们称之为 X 的方面,只能取11个可能的值:2, 3, ..., 12。

X 就是一个随机变量。一般来说,当我们有一个概率空间时,随机变量就是结果的任意函数。它捕捉了我们关心的结果的某个方面。

如何确定随机变量的分布?

让我们看看如何根据底层概率空间的信息来确定随机变量的分布。

这里有一个简单的例子:我们掷一个骰子。这次我们不关心骰子具体掷出几点,只关心它是否大于或等于3。

根据我们的兴趣,我们这样定义一个随机变量:我们设 X 只取两个可能的值。如果骰子点数大于或等于3,则 X = 1;否则 X = 0

因此,在这种情况下定义的随机变量取值要么是0,要么是1。我们来计算它的分布。

X = 0 的概率,就是骰子掷出1或2的概率,即 1/3
X = 1 的概率,就是骰子掷出3、4、5或6的概率,即 2/3

通过这种方式,我们可以通过观察结果的底层概率来找出随机变量的分布。

期望值(均值)

一旦我们有了随机变量的分布,接下来的任务通常是计算随机变量的期望值,也称为其均值

随机变量 X 的期望值,就是如果我们重复实验很多很多次,X 的平均值。它是 X 所有可能取值的加权平均,每个值按其发生的概率加权。

公式如下:

E[X] = Σ (x * P(X = x))

让我们看一个简单的例子。我们掷一个骰子,让 X 表示观察到的点数。它的期望值是多少?

在这种情况下,X 可以取值1、2、3、4、5或6。根据公式,X 的期望值是:

E[X] = 1(1/6) + 2(1/6) + 3(1/6) + 4(1/6) + 5(1/6) + 6(1/6) = 21/6 = 3.5

所以 X 的期望值是3.5。

再看另一个例子。假设你有一枚有偏的硬币,它正面朝上的概率是 p(0 ≤ p ≤ 1)。你抛这枚硬币,随机变量 X 定义为:如果硬币正面朝上则 X = 1,反面朝上则 X = 0。那么 X 的期望值是多少?

同样,我们列出公式。X 可以取值0或1。X = 0 的概率是 1-pX = 1 的概率是 p。因此:

E[X] = 0(1-p) + 1p = p

期望值的线性性质

现在我们已经看了一些期望值的例子,让我们看看均值的一个关键性质。

假设你有一组数字,你把所有数字都加倍,平均值会怎样?平均值也会加倍。
如果你不是加倍,而是给每个数字都加1,平均值会怎样?平均值也会增加1。

让我们用更一般的方式来总结。如果你有一个随机变量 X,然后定义一个新的随机变量 Y = aX + b(例如 2X+1 或 4X-3),那么 Y 的期望值是多少?你能从 X 的均值算出来吗?

是的,它简单地等于 a 乘以 X 的均值再加上 b。这是一个线性性质,有助于简化许多计算。

E[aX + b] = aE[X] + b

方差与标准差

通常,一个随机变量 X 可以取很多可能的值。如果我们想用一个数字来概括 X 的分布,我们可能会选择它的均值。让我们用希腊字母 μ 来表示均值。

这是一个很好的概括,简洁有用,但它没有捕捉到 X离散程度

这里有两个不同分布的例子。它们都有完全相同的均值 μ,但左边的分布更紧密地集中在均值周围,而右边的分布则分散得多。它们有相同的均值,但离散程度非常不同。

如果我们被允许用第二个数字来概括分布呢?我们能选一个能捕捉离散程度的数字吗?

一个想法是:为什么不使用与均值的平均距离呢?即 X 与其均值 μ 的绝对差值的期望值。在左边的分布中,X 与均值的平均距离可能很小;在右边的分布中,这个平均距离可能很大。这确实可行,有些人也确实使用它。

但数学上更方便的是看 X 与均值的平均平方距离。这就是我们所说的 X方差

方差是距离均值的平均平方距离。直观上,我们想要的是与均值的典型距离,而不是典型的平方距离。因此,我们最终取方差的平方根,这就是 X标准差。标准差的行为符合我们的期望:例如,在左边的分布中,标准差较小;在右边的分布中,标准差较大。

计算方差与标准差

让我们看一个简单的例子,看看如何计算这些量。

假设我们从数字 {1, 2, 3, 4, 5} 中以相等的概率随机选择一个数作为 XX 的方差是多少?

首先,我们需要计算 X 的期望值(均值)。我们期望它正好是中间的数,即3。让我们验证一下:

E[X] = 1(1/5) + 2(1/5) + 3(1/5) + 4(1/5) + 5*(1/5) = 15/5 = 3

很好,μ = 3

要计算方差,我们需要 X 减去 μ 的平方的期望值。让我们看看 X 的不同取值以及对应的 (X - μ)²

  • 当 X=1 时,(1-3)² = 4
  • 当 X=2 时,(2-3)² = 1
  • 当 X=3 时,(3-3)² = 0
  • 当 X=4 时,(4-3)² = 1
  • 当 X=5 时,(5-3)² = 4

因此,(X - μ)² 可以取三个可能的值:0, 1, 4。

  • 取值为 0 的概率是 1/5(当 X=3)。
  • 取值为 1 的概率是 2/5(当 X=2 或 4)。
  • 取值为 4 的概率是 2/5(当 X=1 或 5)。

所以,X 的方差 Var(X) 为:
Var(X) = E[(X - μ)²] = 0(1/5) + 1(2/5) + 4*(2/5) = 0 + 2/5 + 8/5 = 10/5 = 2

这意味着 X 的标准差 σ 是方差的平方根:
σ = √Var(X) = √2

方差的性质

首先,方差总是一个非负数。为什么?因为它是距离均值的平均平方距离,正数的平均值必须是正的。

让我们做和平均值一样的思维实验。假设你有一组数字,给每个数字加1,方差会怎样?如果你给每个数字加1,所有东西都平移了一点,但离散程度保持不变。所以标准差不变,方差也不变。方差不受平移(加常数)的影响

如果你把每个数字都加倍呢?如果你把数字加倍,离散程度也会加倍。所以标准差加倍,这意味着方差(标准差的平方)乘以4。

让我们用一个通用公式来总结。如果你有一个随机变量 X,然后定义一个新变量 Y = aX + b,那么这个新变量的方差是 乘以 X 的方差。

Var(aX + b) = a² Var(X)

方差的最后一个非常有用的性质是,有另一个公式可以计算它。X 的方差也等于 的期望值减去均值的平方。

Var(X) = E[X²] - (E[X])²

它总是算出相同的数字。让我们验证一下是否适用于之前的例子。

在我们从 {1,2,3,4,5} 均匀选择 X 的例子中,我们已经用原始公式算出方差是2。让我们用新公式再试一次。

首先计算 E[X²]
E[X²] = 1²(1/5) + 2²(1/5) + 3²(1/5) + 4²(1/5) + 5²*(1/5) = (1+4+9+16+25)/5 = 55/5 = 11

均值 μ = E[X] = 3,所以 μ² = 9

根据新公式:
Var(X) = E[X²] - μ² = 11 - 9 = 2

和之前得到的结果完全一样。

总结

本节课中,我们一起学习了随机变量的核心概念。我们了解到随机变量是概率空间结果的函数,用于量化我们关心的特定方面。我们学习了如何计算随机变量的期望值(均值),它代表了长期的平均结果,并具有线性性质。为了描述随机变量取值的离散程度,我们引入了方差(与均值的平均平方距离)和标准差(方差的平方根)。我们还探讨了方差的重要性质,包括其对常数平移的不变性,以及对缩放因子的平方敏感性,并介绍了计算方差的实用公式 Var(X) = E[X²] - (E[X])²

下一节,我们将逐步构建更复杂的情境:处理多个随机变量(如血压、体温、心率、疾病状态),并研究它们之间的相互作用。这正是我们在高维度中构建生成模型所需要的基础。

011:概率论复习_III 📊

在本节课中,我们将要学习随机变量之间的独立性与相关性。我们将从独立性的正式定义开始,然后深入探讨如何量化变量之间的依赖关系,特别是通过协方差和相关系数这两个核心概念。

独立性的定义 📌

上一节我们介绍了随机变量的基本概念,本节中我们来看看两个随机变量何时是独立的。当两个随机变量互不影响时,我们称它们是独立的。

两个随机变量 XY 是独立的,当且仅当它们的联合概率等于各自边缘概率的乘积。用公式表示如下:

P(X = x, Y = y) = P(X = x) * P(Y = y)

这意味着,知道 X 的取值不会改变 Y 取任何值的可能性,反之亦然。

以下是几个判断独立性的例子:

  • 扑克牌示例:从一副标准扑克牌中随机抽一张牌。定义 X 为花色,Y 为点数。它们是独立的,因为得到特定花色和特定点数的概率(如红心6的概率是 1/52)等于得到该花色的概率(1/4)乘以得到该点数的概率(1/13)。
  • 抛硬币示例:抛一枚均匀硬币10次。定义 X 为正面朝上的总次数,Y 为最后一次抛掷的结果。它们不是独立的。例如,P(X=10, Y=反面) 的概率为0,但 P(X=10)P(Y=反面) 各自都不为0,乘积不为0,因此不满足独立性公式。
  • 表格分布示例:给定 XY 的联合概率分布表。通过计算各自的边缘分布并验证表中每一项是否都等于对应边缘概率的乘积,可以判断它们是否独立。

从独立性到相关性 🔗

处理多个独立随机变量是最简单的情况。然而,更常见且更有趣的是变量之间存在依赖关系。我们需要方法来理解和量化这种依赖。

考虑一个思想实验:随机选取一个人,H 代表其身高,W 代表其体重。直观上,身高和体重不是独立的,因为更高的人往往也更重。这种关系被称为正相关

我们可以通过散点图来可视化这种关系:

  • 正相关:数据点呈现出向上的趋势。大值的 X 倾向于与大值的 Y 配对。
  • 负相关:数据点呈现出向下的趋势。大值的 X 倾向于与小值的 Y 配对。
  • 不相关:数据点呈云状分布,没有明显的向上或向下趋势。

量化相关性:协方差与相关系数 📈

为了精确地度量相关性,我们引入两个数学概念。

首先,我们比较 E[XY]E[X]E[Y]。如果 XY 倾向于同时取较大或较小值,那么 E[XY] 通常会大于 E[X]E[Y]。它们的差值定义了一个核心度量:

协方差 (Covariance) 公式为:
Cov(X, Y) = E[XY] - E[X]E[Y]

  • Cov(X, Y) > 0 表示正相关。
  • Cov(X, Y) < 0 表示负相关。
  • Cov(X, Y) = 0 表示不相关。

然而,协方差的值域没有限制,它取决于 XY 自身的波动大小。为了得到一个标准化的、介于 -1 和 1 之间的度量,我们引入:

皮尔逊相关系数 (Pearson Correlation Coefficient) 公式为:
ρ = Corr(X, Y) = Cov(X, Y) / (σ_X * σ_Y)
其中,σ_Xσ_Y 分别是 XY 的标准差。

  • ρ = 1 表示完全正相关。
  • ρ = -1 表示完全负相关。
  • ρ = 0 表示不相关。

关于独立性与不相关性,有一个重要的关系:如果两个变量独立,那么它们一定不相关(协方差和相关系数为0)。但是,不相关并不一定意味着独立。不相关只表示没有线性关系,但变量之间可能存在其他形式的依赖关系。

计算示例 🧮

让我们通过一个具体例子来计算协方差和相关系数。

假设随机变量 XY 有如下联合分布:

  • P(X=-1, Y=-3) = 1/6
  • P(X=-1, Y=3) = 1/3
  • P(X=1, Y=-3) = 1/3
  • P(X=1, Y=3) = 1/6

以下是计算步骤:

  1. 计算 E[X] 和 E[Y]
    • X 以 1/2 的概率取 -1 和 1,所以 E[X] = 0
    • Y 以 1/2 的概率取 -3 和 3,所以 E[Y] = 0
  2. 计算方差和标准差
    • Var(X) = E[X²] - (E[X])² = 1 - 0 = 1,所以 σ_X = 1
    • Var(Y) = E[Y²] - (E[Y])² = 9 - 0 = 9,所以 σ_Y = 3
  3. 计算 E[XY]
    • XY 以 2/3 的概率取 -3,以 1/3 的概率取 3。
    • E[XY] = (-3)(2/3) + (3)(1/3) = -1
  4. 计算协方差
    • Cov(X, Y) = E[XY] - E[X]E[Y] = -1 - 0 = -1
  5. 计算相关系数
    • ρ = Cov(X, Y) / (σ_X * σ_Y) = -1 / (1 * 3) = -1/3

计算结果表明,XY 之间存在微弱的负相关。

总结 📝

本节课中我们一起学习了随机变量间关系的核心概念。

  • 我们首先定义了独立性,即一个变量的取值不影响另一个变量的分布。
  • 接着,我们探讨了更普遍的依赖关系,并学习了如何通过散点图直观判断正相关、负相关和不相关。
  • 为了量化依赖程度,我们引入了协方差 (Covariance)皮尔逊相关系数 (Correlation Coefficient) 这两个重要工具。协方差衡量了变量变化的协同程度,而相关系数将其标准化到 [-1, 1] 区间,便于比较。
  • 我们明确了独立一定导致不相关,但反之不成立。
  • 最后,通过一个数值例子,我们演练了如何从联合分布出发,计算变量的期望、方差、协方差和相关系数。

掌握这些概率论工具,为我们接下来学习生成式模型打下了坚实基础,在这些模型中,我们需要精确地刻画特征之间的依赖关系以实现更准确的分类。

012:二维生成式建模 🧮

在本节课中,我们将学习生成式分类方法在二维空间中的扩展,即二维高斯分布。我们将了解如何利用两个特征之间的相关性来构建更准确的分类器,并以葡萄酒厂预测问题为例进行说明。


上一节我们介绍了一维高斯分布及其在生成式分类中的应用。本节中,我们来看看二维高斯分布。这种分布的一个激动人心之处在于,它允许我们建模特征之间的依赖关系。

例如,如果我们试图根据一个人的胆固醇水平和血压来预测其是否患病,我们无需假设这两个特征是独立的。我们可以实际建模它们之间的依赖关系,以获得更准确的预测。

运行示例:葡萄酒厂预测问题 🍷

回顾一下,在这个问题中,我们有一瓶葡萄酒,从每瓶酒中测量13个视觉和化学特征。我们希望利用这些特征来预测这瓶酒来自哪个酒厂(酒厂1、2或3)。上一节我们只使用了13个特征中的一个,发现仅使用该特征时错误率约为29%。本节我们将使用两个特征,并观察错误率如何显著下降。

该数据集包含一个由130瓶酒组成的训练集(43瓶来自酒厂1,51瓶来自酒厂2,36瓶来自酒厂3),以及一个包含48个标记点的独立测试集。上次我们使用的特征是酒精含量。这次我们将增加第二个特征:类黄酮含量。这是葡萄酒中出现的一类化学化合物。

以下是使用两个特征可能更有帮助的原因。上次我们只有一个特征(酒精含量),并为三个酒厂的数据分别拟合了高斯分布。结果发现这三个分布重叠严重,分离度不高,因此单独使用该特征进行分类的效果不佳。

当我们引入第二个特征时,情况发生了变化。下图是一个散点图,每个点代表130个训练点中的一个(红色来自酒厂1,黑色来自酒厂2,绿色来自酒厂3)。每个点根据其酒精含量和类黄酮含量绘制在二维平面上。可以看到,不同类别的点之间存在相当明显的分离,这让我们有希望利用这两个特征实现更好的分类。

我们将遵循生成式方法,为酒厂1、2和3的数据分别拟合一个分布。这些分布将呈现为类似椭圆的形状。事实证明,这样做可以将错误率从29%大幅降低至8%。

理解二维高斯分布 📊

这些椭圆代表什么?让我们聚焦于其中一个,例如代表酒厂1的红色分布。当我们为那43个训练点拟合一个高斯分布时,得到的就是这个分布。

它是一个定义在二维平面上的分布,为每个可能的酒精含量和类黄酮含量组合分配一个密度值。在三维图中,基底是酒精和类黄酮值构成的二维平面,高度代表该点的密度。这就是二元高斯分布的样子。

为了更容易理解,我们通常用等高线来表示。下图用红色显示了原始的43个二维训练点。我们为这些点拟合了一个高斯分布。该分布有两组参数:一个均值和一个协方差矩阵。

均值是一个二维点,它是分布的中心,也是密度最高的点。随着远离均值,密度会下降,并以椭圆等高线的形式递减。例如,密度为0.4的点可能构成一个椭圆,密度为0.3的点构成另一个更大的同心椭圆,依此类推。

参数详解:均值与协方差矩阵 🔍

均值很容易理解,它就是分布密度的中心点。

协方差矩阵是一个2x2矩阵。左上角的数字是x1方向(酒精含量)的方差。右下角的数字是x2方向(类黄酮含量)的方差。有趣的是非对角线上的数字,即协方差 σ12(或 σ21),它衡量了两个特征之间的依赖关系。

让我们快速回顾一下两个随机变量 X1X2(例如酒精和类黄酮)的协方差是什么。X1 有均值 μ1X2 有均值 μ2。协方差的标准定义是:
Cov(X1, X2) = E[X1 * X2] - E[X1] * E[X2]
当协方差为正时,表示存在正相关;为负时表示负相关;为零时表示两个变量不相关。

二维高斯分布的形式化描述 📝

二维高斯分布是定义在整个二维空间上的分布,为每个点 (x1, x2) 分配一个密度。最高密度的点是均值 μ = (μ1, μ2)。分布的其他参数是方差和协方差参数,它们构成一个2x2的对称矩阵 Σ

  • Σ[1,1]X1 的方差。
  • Σ[2,2]X2 的方差。
  • Σ[1,2] = Σ[2,1]X1X2 的协方差。

分布密度的具体公式如下:
p(x) = (1 / (2π √|Σ|)) * exp( -1/2 * (x - μ)^T * Σ^{-1} * (x - μ) )
其中:

  • |Σ| 表示矩阵 Σ 的行列式。
  • Σ^{-1}Σ 的逆矩阵。
  • (x - μ)^T 是位移向量 (x - μ) 的转置。

公式前面的部分是归一化常数,确保密度总和为1。关键部分在指数项内。密度仅取决于点 x 与均值 μ 的位移 (x - μ)。当 x = μ 时,指数项为0,密度最高。随着 x 远离 μ,该数值增大,密度呈指数下降。

示例解析 🎯

为了加深理解,我们看两个具有相同均值 (1, 1) 但不同协方差矩阵的高斯分布示例。

左侧分布

  • 协方差矩阵为 [[4, 0], [0, 1]]
  • X1 的方差为4,标准差为2。
  • X2 的方差为1,标准差为1。
  • 协方差为0,表示 X1X2 不相关。
  • 从散点图可以看出,数据在 X1 方向上的伸展程度是 X2 方向的两倍,且分布没有倾斜,与坐标轴对齐。

右侧分布

  • 协方差矩阵为 [[4, 1.5], [1.5, 1]]
  • X1X2 的标准差与左侧相同。
  • 但协方差为1.5,表示 X1X2 之间存在正相关。
  • 从散点图可以看出,数据点呈现出向上的倾斜趋势,反映了这种相关性。

应用于葡萄酒厂分类 🏆

现在回到葡萄酒厂的例子。我们为酒厂1(红点)、酒厂2和酒厂3的数据分别拟合了一个高斯分布,并绘制了代表性的等高线。

当一个新的数据点 x 到来时,我们使用贝叶斯规则进行预测。我们有先验类别概率 π1, π2, π3。我们选择使 πj * p_j(x) 最大的类别 j 作为预测结果。

由此产生的决策边界如下图所示。边界内的区域被预测为来自对应的酒厂。这个边界形状有些奇特。它的函数形式是什么?既然使用两个特征已将错误率降至8%,那么使用更多特征能否做得更好?我们如何建模多个变量之间的相关性?

我们将在接下来的课程中看到所有这些问题的答案。


本节课中,我们一起学习了二维高斯分布及其在生成式分类中的应用。我们了解了如何通过均值和协方差矩阵描述分布,如何解释特征间的相关性,并看到了在葡萄酒厂预测问题中,使用两个相关特征能显著提升分类性能。下一节,我们将探讨如何将这些概念扩展到更高维度。

013:线性代数 I 📐

在本节课中,我们将学习线性代数的基础知识,这是机器学习中最核心的数学工具。我们将重点介绍如何使用向量和矩阵表示数据,学习基本的记法,并深入理解点积的概念及其几何意义。


数据表示:向量与矩阵

在之前的课程中,我们越来越多地接触到向量和矩阵。它们逐渐渗透进来,我们无法再回避它们。虽然许多同学可能已经接触过线性代数,但为了确保大家都能掌握,我们将对本课程所需的概念和技能进行一次全面的回顾。

线性代数是机器学习中最基础的数学,因此需要深入理解。

考虑一个包含四个点的数据集。我们可以将每个点表示为一个向量。例如,右下角的点是向量 [5, 2]。左上角的点是 [3, 5]。其附近的点是 [2, 4]。左下角的点是 [1, 1]

我们也可以将整个数据集表示在一个矩阵中。例如,我们可以让每个数据点作为矩阵的一行,形成一个 4 行 2 列的矩阵(4x2 矩阵):

[ [1, 1],
  [2, 4],
  [3, 5],
  [5, 2] ]

或者,我们也可以将数据点作为列,形成一个 2 行 4 列的矩阵(2x4 矩阵):

[ [1, 2, 3, 5],
  [1, 4, 5, 2] ]

在本课程中,我们将主要采用第一种约定,即将数据点作为行。


向量与矩阵的记法

现在,我们来回顾一下索引记法。

一个在 D 维空间中的向量 x ∈ ℝᴰ,我们将其写作列向量,其条目索引为 x₁ 到 x_D。

一个 R x D 的矩阵,意味着它有 R 行和 D 列,总共有 R * D 个条目。位于第 I 行、第 J 列的条目记为 M_IJ。我们称其维度为 R x D。

同样,我们可以将向量描述为 D x 1(D 行,1 列)。


转置操作

对向量或矩阵最简单的操作之一是取转置,即交换行和列。

例如,对于一个列向量 x = [1; 6; 3; 0](4x1),其转置 xᵀ 写作行向量 [1, 6, 3, 0](1x4)。

对于一个矩阵 A = [ [1, 2, 0, 4]; [9, 8, 5, 6]; [3, 3, 3, 3] ](3x4),其转置 Aᵀ 是将第一行变为第一列,第二行变为第二列,以此类推,得到一个 4x3 的矩阵:[ [1, 9, 3]; [2, 8, 3]; [0, 5, 3]; [4, 6, 3] ]

形式上,转置 Aᵀ 由以下公式定义:(Aᵀ)_IJ = A_JI。不难看出,对矩阵进行两次转置,会得到原矩阵:(Aᵀ)ᵀ = A


加法与减法

向量和矩阵的加减法非常简单,只需按元素进行。

例如,向量 [1, 2, 3] 加上 [4, 5, 6] 等于 [5, 7, 9]

对于矩阵 [[2, 1], [0, 2]] 加上 [[1, 2], [3, 4]] 等于 [[3, 3], [3, 6]]

加减法很容易,更有趣的是乘法。


向量点积

本节我们将讨论最基本的一种乘积:两个向量之间的点积。

假设我们有两个 D 维向量 xy。它们的点积记为 x · y

计算点积的方法是:将对应坐标相乘,然后将所有乘积相加。

公式x · y = x₁*y₁ + x₂*y₂ + ... + x_D*y_D

让我们看一个例子。在二维平面中,向量 x = [3, 4],向量 y = [-4, 3]。它们的点积计算如下:
x · y = (3 * -4) + (4 * 3) = -12 + 12 = 0

有趣的是,观察这两个向量,它们看起来彼此垂直(呈90度角)。点积为零与垂直之间是否存在关系?确实存在。


点积与夹角

两个向量之间的点积可以告诉我们它们之间的夹角。

公式:对于任意两个向量 xy,它们之间的夹角为 θ,则有:
cos(θ) = (x · y) / (||x|| * ||y||)
其中,||x|| 表示向量 x 的长度(模)。

例如,如果点积为零(x · y = 0),则 cos(θ) = 0,这意味着 θ = 90 度。我们将彼此垂直的向量称为正交向量,这在本课程中是一个非常重要的概念。现在我们有了一个简单的正交性测试方法:检查点积是否为零。


方向向量与单位向量

向量的另一种用途是指示方向。如果我们只关心方向,那么向量的长度并不重要。因此,常见的做法是将向量归一化为长度为 1,这样的向量称为单位向量

当我们处理单位向量 uv 时,夹角公式变得特别简单,因为分母 ||u|| * ||v|| = 1 * 1 = 1。因此,cos(θ) = u · v


向量与自身的点积

最后,我们来看一个关于点积和夹角的问题:向量与自身的点积是什么?

方法一(直接计算)x · x = x₁² + x₂² + ... + x_D²。这正是向量 x 的欧几里得长度的平方 ||x||²

方法二(利用夹角公式):向量与自身的夹角是 0 度。cos(0) = 1。代入公式:1 = (x · x) / (||x|| * ||x||),可得 x · x = ||x||²。两种方法得到相同的结果。


总结

本节课中,我们一起学习了线性代数的基础知识。我们介绍了如何使用向量和矩阵表示数据,学习了转置操作、基本的加减法,并重点探讨了向量点积的定义、计算方法及其重要的几何意义——点积可以衡量向量之间的夹角和正交性。我们还了解了单位向量的概念。掌握这些基础是理解后续更复杂机器学习算法的关键。

014:线性代数 II 📐

在本节课中,我们将继续回顾线性代数。我们将基于向量的点积,学习向量与矩阵、以及矩阵与矩阵之间的乘积。这些概念对于建模线性函数至关重要,而线性函数是本课程中最常用的函数类型之一。

线性函数与二次函数

上一节我们介绍了向量的点积,本节中我们来看看如何用矩阵和向量来描述更复杂的函数。

在一维空间中,一个变量的线性函数形式如 3x + 2。二次函数则允许包含平方项,例如 4x² - 2x + 6

在更高维度(例如三维空间)中,线性函数是多个项的和。每个项要么是常数(如4),要么是某个变量的倍数。因此,其形式类似于 3x₁ - 2x₂ + x₃ + 4

二次函数同样是项的和。每个项可以是常数、线性项、某个变量的平方(如 x₁² 或 6x₂²),或者是两个变量的成对乘积(如 -2x₁x₃)。

线性决策边界

我们将大量使用线性函数。例如,支持向量机、逻辑回归等许多方法都基于线性决策边界。

假设数据位于二维空间,线性决策边界就是一条直线,如下图所示。决策边界的一侧被分类为“+”,另一侧被分类为“-”。

这条直线的方程是 4x₁ + 3x₂ = 12。我们可以验证点 (3,0) 和 (0,4) 都满足此方程,因此它确实是图中的红线。

在 D 维空间中,线性边界是上述形式的直接推广。当 x 是一个具有 D 个分量的向量 (x₁, ..., x_D) 时,一个线性分隔器的形式为:
w₁x₁ + w₂x₂ + ... + w_D x_D = c

观察等式左边,它很像一个点积。事实上,它可以写成 w · x = c,其中 w 是系数向量 (w₁, ..., w_D)。因此,点积允许我们表达线性边界。

用矩阵表示线性函数

让我们看另一个例子,并进行一些推广。

首先,我们有一个函数,它接收一个四维向量 (x₁, x₂, x₃, x₄),并返回这些特征的线性函数。我们可以将其写为点积:
f(x) = [3, 0, -2, 0] · [x₁, x₂, x₃, x₄]

现在看第二个例子,这是一个推广。它同样接收一个四维向量,但这次输出一个三维向量。输出的每个维度都是 x 的线性函数。

我们可以这样写:

  • 第一个坐标: [4, -1, 0, 0] · x
  • 第二个坐标: [0, 0, 1, 0] · x
  • 第三个坐标: [-1, 0, 0, 6] · x

我们可以使用矩阵更简洁地表达这个函数:

[ 4  -1   0   0 ]   [ x₁ ]
[ 0   0   1   0 ] * [ x₂ ]
[ -1  0   0   6 ]   [ x₃ ]
                    [ x₄ ]

我们将其表示为矩阵乘以向量。

矩阵-向量乘积

现在,让我们更抽象地讨论矩阵-向量乘积。如何将一个矩阵乘以一个向量?

假设我们有一个 R × D 的矩阵 M,意味着它有 R 行和 D 列。我们可以将行表示为 m₁, m₂, ..., m_R,每行是一个 D 维向量。

我们将这个矩阵乘以一个 D × 1 的向量 x。结果是一个 R × 1 的向量,其计算方式如下:
Mx = [ m₁·x, m₂·x, ..., m_R·x ]^T

矩阵-向量乘积就是一系列点积。它捕获了一个线性函数。

最简单的线性函数是将 x 映射到自身的恒等函数。实现此功能的矩阵是单位矩阵 I。如果向量 x 是 D 维的,则单位矩阵 I_D 是一个 D × D 的矩阵,其对角线元素为 1,其他元素为 0。因此,I_D * x = x

矩阵-矩阵乘积

接下来,我们看看如何将一个矩阵乘以另一个矩阵。其规则同样基于点积,非常简单。

假设我们有一个 R × K 的矩阵 A,以及一个 K × P 的矩阵 B。乘积 AB 将是一个 R × P 的矩阵。

乘积矩阵中第 i 行、第 j 列的元素 (AB){ij} 计算如下:
**(AB)
= A的第i行 · B的第j列**

为了计算乘积,我们取 A 的每一行与 B 的每一列进行点积。这意味着,两个矩阵相乘时,内部维度必须一致(即 A 的列数必须等于 B 的行数,均为 K)。乘积矩阵的维度由外部维度给出(即 R × P)。

让我们看一个例子:

A = [1 2 3]   B = [1  0]
    [4 5 6]       [0  2]
                  [-1 1]

A 是 2×3,B 是 3×2,内部维度一致(均为3)。乘积将是 2×2 的矩阵。
计算过程如下:

  • (1,1) 位置: [1,2,3]·[1,0,-1] = 1 - 3 = -2
  • (1,2) 位置: [1,2,3]·[0,2,1] = 0 + 4 + 3 = 7
  • (2,1) 位置: [4,5,6]·[1,0,-1] = 4 - 6 = -2
  • (2,2) 位置: [4,5,6]·[0,2,1] = 0 + 10 + 6 = 16
    因此,AB = [ -2, 7; -2, 16 ]

重要性质

矩阵乘法有一些重要性质:

  1. 乘以单位矩阵:任何矩阵乘以相应维度的单位矩阵,其值不变。A * I = I * A = A
  2. 乘积的转置:乘积的转置等于转置矩阵以相反顺序的乘积。(AB)^T = B^T A^T
  3. 向量点积的矩阵表示:两个向量 u 和 v 的点积可以写成矩阵形式。u · v = u^T v。这是一个非常有用的等式,可以简化许多计算。

让我们看几个基于此的例子:

  • x^T x:这是向量 x 与自身的点积,结果是一个标量,等于向量长度的平方 ||x||²
  • x x^T:这是一个 D × D 的矩阵,其第 (i, j) 个元素是 x_i * x_j,即 x 各特征的所有成对乘积。

这两个表达式看起来相似,但完全不同。一个产生标量,另一个产生矩阵。这引出了一个关键点。

矩阵乘法的不可交换性

在一般情况下,矩阵乘法是不可交换的。AB ≠ BA,除非在特殊情况下。

例如:

A = [1 2]   B = [1 0]
    [0 0]       [0 1]

计算可得:
AB = [1 2; 0 0],而 BA = [1 2; 0 0]?等等,让我们准确计算一下第二个:
BA = [11+00, 12+00; 01+10, 02+10] = [1, 2; 0, 0]。在这个特例中它们相等,但通常不相等。另一个更明显的例子:

A = [1 2]   B = [0 1]
    [3 4]       [1 0]

AB = [2, 1; 4, 3],而 BA = [3, 4; 1, 2],两者完全不同。

因此,不能随意交换矩阵乘法的顺序。

然而,矩阵乘法满足结合律。当连续乘以多个矩阵时,只要保持矩阵的原始顺序,可以任意选择先计算哪一对乘积。例如,计算 A * B * C * D 时,可以先算 (AB),再算 (CD),然后将结果相乘;或者先算 (B*C),再左乘 A,右乘 D。

结合律在简化复杂表达式时非常有用。例如,计算包含多个 x^T x(这是一个标量)的复杂矩阵链式乘法时,可以优先计算这些标量乘积,从而大大简化整个表达式。

总结

本节课中我们一起学习了线性代数的核心运算。我们了解了如何用矩阵和向量表示线性与二次函数,掌握了矩阵-向量以及矩阵-矩阵乘积的计算方法和几何意义。我们特别强调了点积与矩阵乘法的关系(u·v = u^T v),以及矩阵乘法不可交换但满足结合律的重要性质。这些工具和概念是后续构建和理解机器学习模型(如线性分类器)的基础。现在,我们已经具备了建模线性函数所需的所有符号和工具,这在本课程中将有大量应用。

015:线性代数_III 🔢

在本节课中,我们将要学习方阵及其性质。我们将看到,任何方阵不仅可以表示一个线性函数,还可以表示一个二次函数。我们将探讨对称矩阵、对角矩阵、行列式以及矩阵的逆等核心概念。

从特殊到一般:方阵与二次函数

在之前的线性代数入门中,我们了解到任何矩阵都可以被视为表示一个线性函数。今天我们将看到,如果矩阵是方阵,即行数和列数相同,那么它还可以表示一个二次函数。

让我们从一个之前见过的特殊情况开始。我们发现,对于一个向量 xxxx 与自身点积的另一种写法,也就是 x 长度的平方。事实上,你也可以将其视为 xIx,因为单位矩阵 I 乘以 x 就是 x 本身。

现在,单位矩阵只是一个 D×D 的方阵。如果我们把中间的 I 换成其他任意的 D×D 矩阵 M,即计算 xMx,会得到什么呢?

让我们来看一下。我们有 xᵀ(一个 1×D 的行向量),矩阵 M(D×D),以及 x(一个 D×1 的列向量)。当我们相乘时,内部维度匹配,结果将是外部维度,即 1×1。因此,结果是一个单一的数字,正如我们从 xx 的案例中所预期的那样。

实际上,我们可以给出这个数字的公式。将其展开后,结果是:
xMx = Σᵢⱼ Mᵢⱼ xᵢ xⱼ
这是一个关于 x 的二次函数。每一项都包含来自矩阵 M 的某个系数 Mᵢⱼ,而其对 x 的依赖是二次的,包含 xᵢ xⱼ 这样的项,也包括 xᵢ² 这样的项。

具体示例:理解二次函数

让我们看一个具体的例子来加深理解。假设我们有一个 2×2 的矩阵:

M = [1 2]
    [0 3]

它表示什么样的二次函数?由于矩阵是 2×2,向量 x 必须是二维的,即 x = [x₁, x₂]ᵀ。我们计算 xMx

[x₁ x₂] * [1 2] * [x₁] = [x₁ x₂] * [x₁ + 2x₂] = x₁² + 2x₁x₂ + 3x₂²
          [0 3]   [x₂]                 [3x₂]

这确实是一个二次函数,包含了 x₁²、x₁x₂ 和 x₂² 项。

让我们回到之前的求和公式,验证一下是否得到相同的结果。根据公式:
Σᵢⱼ Mᵢⱼ xᵢ xⱼ = M₁₁ x₁x₁ + M₁₂ x₁x₂ + M₂₁ x₂x₁ + M₂₂ x₂x₂
代入矩阵 M 的值:M₁₁=1, M₁₂=2, M₂₁=0, M₂₂=3。
得到:1x₁² + 2x₁x₂ + 0x₂x₁ + 3x₂² = x₁² + 2x₁x₂ + 3x₂²。结果完全一致。

公式总结与反向推导

总结一下公式:对于任何方阵 M,你可以通过映射 x(一个 D 维向量)到数值 xMx 来定义一个二次函数,其结果就是上述求和公式。

这个求和公式让我们可以轻松地读出二次函数。例如,对于这个矩阵:

M = [1 0 0]
    [0 0 0]
    [3 4 5]

它对应的二次函数将三维向量 x = [x₁, x₂, x₃]ᵀ 映射为:
M₁₁x₁² + M₂₂x₂² + M₃₁x₃x₁ + M₃₂x₃x₂ + M₃₃x₃² = 1x₁² + 0x₂² + 3x₃x₁ + 4x₃x₂ + 5x₃²

我们也可以尝试反向推导。假设有一个二次函数:f(x₁, x₂) = x₁² + 2x₁x₂ + 3x₂²。我们如何用矩阵写出这个函数?我们需要一个 2×2 的矩阵 M

从 x₁² 的系数为 1,可知 M₁₁ = 1。
从 x₂² 的系数为 3,可知 M₂₂ = 3。
但 x₁x₂ 的系数为 2,这对应着 M₁₂ + M₂₁ = 2。
因此,存在多种可能的矩阵来实现这个函数,例如:

[1 2]   [1 1]   [1 0]
[0 3],  [1 3],  [2 3]

等等。实际上有无限多种可能性。

对称矩阵与对角矩阵

我们一直在讨论方阵。方阵的一种特殊类型是对称矩阵,即等于其转置的矩阵(M = Mᵀ)。这意味着如果你沿着主对角线反射矩阵,矩阵保持不变。

以下是一个对称矩阵的例子:

[2 5]
[5 3]

反射对角线后,元素位置互换但值相同,因此对称。
而下面这个矩阵则不对称:

[1 2]
[0 3]

(注意 (1,2) 位置的 2 和 (2,1) 位置的 0 不相等)。

对称矩阵的一个特例是对角矩阵。这种矩阵只有主对角线上的元素可能非零,其他位置都是 0。例如:

[4 0 0]
[0 5 0]
[0 0 6]

由于大部分元素是 0,我们有时使用简写 diag(4, 5, 6) 来表示它。

行列式:几何意义

与方阵相关的一个关键量是行列式。对于矩阵 A,其行列式是一个数值,记作 det(A) 或 |A|。

你可能记得,对于 2×2 矩阵 A = [[a, b], [c, d]],其行列式为 ad - bc。
例如,对于矩阵 A = [[3, 1], [1, 2]],行列式为 32 - 11 = 5。

行列式有什么意义吗?答案是肯定的,它有几何解释。我们可以将矩阵的每一行视为一个数据点。对于这个 2×2 矩阵,两个行向量是 [3, 1] 和 [1, 2]。在坐标系中画出这两个点,并以它们为邻边构成一个平行四边形。这个平行四边形的面积恰好等于行列式的绝对值(此处为 5)。

这个概念可以推广到更高维度。对于一个 D×D 方阵,将其每一行视为 D 维空间中的一个点,这些点可以张成一个“平行多面体”。这个平行多面体的(有向)体积就是该矩阵的行列式。

让我们用一个熟悉的例子来验证:考虑一个 3×3 对角矩阵 diag(a, b, c)。它的三个行向量是 [a, 0, 0], [0, b, 0], [0, 0, c]。在三维空间中,它们分别位于三条坐标轴上。它们张成的物体是一个长方体,其体积为 abc。而该对角矩阵的行列式正是其对角线元素的乘积,即 abc。这验证了我们的几何解释。

矩阵的逆

与方阵相关的另一个非常重要的概念是逆矩阵。对于一个 D×D 方阵 A,如果存在另一个 D×D 矩阵 B,使得 AB = BA = I(单位矩阵),则称 BA 的逆矩阵,记作 A⁻¹。

让我们看一个例子。假设矩阵 A 为:

A = [1  2]
    [-2 0]

可以验证,以下矩阵是 A 的逆:

A⁻¹ = [0    -0.5]
      [0.5   0.25]

因为 A * A⁻¹ 的结果是单位矩阵。

关于逆矩阵,有几点需要强调:

  1. 逆矩阵并不总是存在。许多方阵没有逆矩阵,我们称这些矩阵为奇异矩阵或不可逆矩阵。
  2. 判断奇异性有一个简单方法:一个矩阵是奇异的,当且仅当其行列式为 0。换句话说,矩阵可逆的充要条件是其行列式非零。
  3. 对角矩阵的逆:对于一个对角矩阵 diag(a₁, a₂, ..., a_D),其行列式为所有对角线元素的乘积 a₁a₂...a_D。要使它可逆,需要所有 aᵢ ≠ 0。如果可逆,其逆矩阵非常简单,就是每个对角线元素取倒数构成的新对角矩阵:diag(1/a₁, 1/a₂, ..., 1/a_D)。

总结

本节课中我们一起学习了方阵的核心性质及其与二次函数的关联。我们了解到:

  • 任何方阵 M 都可以通过 xMx 定义一个二次函数。
  • 对称矩阵(M = Mᵀ)和对角矩阵是两类重要的特殊方阵。
  • 行列式具有明确的几何意义,表示由矩阵行向量张成的平行多面体的体积。
  • 逆矩阵 A⁻¹ 满足 AA⁻¹ = A⁻¹A = I,但并非所有方阵都可逆(行列式为0时不可逆)。
  • 对角矩阵的行列式和对角线元素乘积,其逆矩阵(如果存在)是对角线元素取倒数。

这些线性代数概念是理解后续机器学习算法(如主成分分析、最小二乘法、多元高斯分布等)的重要基础。建议花时间消化这些内容,我们将在后续课程中继续深入。

016:多元高斯分布 🧮

在本节课中,我们将学习多元高斯分布。我们将从理解其高维密度函数开始,获得一些直观认识,然后探讨一些广泛使用的特殊情形。

从二维到高维的推广

上一节我们回顾了线性代数的基础。现在,我们可以看看任意维度下的高斯分布。

回想我们之前分析葡萄酒数据集时,提取了“酒精含量”和“类黄酮”两个特征,并为其中一个酒庄的数据拟合了一个二维高斯分布。结果如下图所示:

这是一个二维高斯分布,其密度覆盖了整个平面上的每一个可能的点对 (x1, x2)。图中的高度代表了该点的概率密度。

我个人觉得这种三维图有点难以理解。另一种展示方式是绘制等高线图:

图中的红点是实际的数据点。我们通过计算每个特征的均值、方差以及两个特征之间的协方差来拟合高斯分布。

高斯分布的参数有两个:

  1. 均值 μ:一个二维向量,包含两个特征的均值。它是分布的中心点,也是密度最高的点。
  2. 协方差矩阵 Σ:一个 2x2 的矩阵。其对角线元素是两个特征各自的方差,非对角线元素是两个特征之间的协方差。公式表示为:
    Σ = [ Var(x1)    Cov(x1, x2)
          Cov(x2, x1) Var(x2)    ]
    
    图中等高线椭圆向上倾斜,正是因为两个特征之间存在正相关性。

二维高斯分布比较简单,并且可以很直接地推广到 D 维。

D 维高斯分布

现在让我们转向更高维的情况。假设我们处于 D 维空间,有 D 个特征:x1, x2, ..., xD。

  • 均值 μ:是一个 D 维向量,包含每个特征的均值。
    μ = [μ1, μ2, ..., μD]^T
    
  • 协方差矩阵 Σ:是一个 D x D 的矩阵。

这个协方差矩阵包含什么内容呢?

  • 对角线元素:是每个特征自身的方差。共有 D 个这样的数。
    Σ_ii = Var(xi)
    
  • 非对角线元素:是所有可能特征对之间的协方差。例如,第一行包含 Var(x1),然后是 Cov(x1, x2),Cov(x1, x3),依此类推。
    Σ_ij = Cov(xi, xj)  (对于 i ≠ j)
    

因此,高斯分布的密度在均值 μ 处最高。当你远离均值时,密度沿着椭球形的等高线下降。这些椭球的形状完全由协方差矩阵 Σ 决定。

密度函数解析

以下是多元高斯分布密度函数的精确公式:

让我们简要看一下这个公式。

  • 第一部分是一个归一化常数,确保整个密度函数的积分为1。其中包含矩阵 Σ 的行列式 |Σ|。
  • 最重要的部分是指数项内部的内容,因为这是唯一依赖于输入向量 x 的部分。

这个指数项 (x - μ)^T Σ^{-1} (x - μ) 是什么意思?为了简化,我们假设均值 μ = 0(即高斯分布以原点为中心)。那么公式简化为:

x^T Σ^{-1} x

M = Σ^{-1},则上式变为 x^T M x。这看起来很熟悉,它是一个二次型函数。因此,密度函数的值只依赖于 x 的一个二次函数。确实,椭球正是一种二次曲线。

特殊情形一:对角高斯分布

现在,让我们来看一个特别令人感兴趣的特殊情形:假设这 D 个特征是相互独立的。那么高斯分布会是什么样子?

设第 i 个特征 xi 的方差为 σ_i²。让我们推导这种情况下协方差矩阵的形式。

我们知道协方差矩阵 Σ 是一个 D x D 的矩阵:

  • 对角线元素是各个特征的方差。
  • 非对角线元素是特征对之间的协方差。由于特征相互独立,它们不相关,因此协方差为 0。

所以,协方差矩阵是一个对角矩阵

Σ = diag(σ1², σ2², ..., σD²)

其逆矩阵也很容易计算,只需将对角线元素取倒数:

Σ^{-1} = diag(1/σ1², 1/σ2², ..., 1/σD²)

因为协方差矩阵是对角矩阵,我们有时称之为对角高斯分布

在这种情况下,密度函数可以大大简化。实际上,每个特征自身就是一个一维高斯分布:xi ~ N(μi, σi²)。而 D 维点 x 的联合概率密度,恰好是每个特征一维密度的乘积,这正体现了特征的独立性。

此时,分布的等高线是什么样子?由于没有相关性(协方差为0),椭球体不会倾斜。它们是轴对齐的,即椭球的主轴与坐标轴方向平行。椭球沿 xi 方向的伸展程度就是该特征的标准差 σi。

对角高斯分布的一个很大优点是,它可以用很少的参数来指定。以下是所需的参数数量:

  • 均值 μ:D 个参数。
  • 协方差矩阵 Σ:由于是对角矩阵,只需要 D 个方差参数。
  • 总参数数量:2D

这与需要大约 D² 个参数的完整协方差矩阵高斯分布相比,是一个巨大的节省。因此,即使特征并非完全独立,对角高斯分布也经常被使用,因为它更简单、参数更少,不易过拟合。

特殊情形二:球面高斯分布

让我们看一个更特殊的、也非常流行的情形:特征不仅相互独立,而且所有特征都具有相同的方差

此时,协方差矩阵不仅是对角矩阵,而且对角线上的元素都相同。换句话说,协方差矩阵是单位矩阵的倍数:

Σ = σ² I

其中 I 是 D x D 的单位矩阵。

在这种情况下,密度函数可以进一步简化。此时,点 x 处的密度值只取决于 x 到中心 μ 的距离。等密度点位于以 μ 为中心的球面上。因此,密度在 μ 处最高,随着远离 μ,等密度面是一系列同心球面。这被称为球面高斯分布各向同性高斯分布

高斯分布的参数估计(拟合)

现在我们对多元高斯分布有了一些了解,让我们转向一个更具体、更实际的问题:如何根据数据拟合一个高斯分布?

假设我们在 D 维空间中有 M 个数据点:x1, x2, ..., xM。拟合高斯分布的方法非常简单:只需计算这些点的经验均值经验协方差矩阵。它们就是高斯分布的参数 μ 和 Σ。

  • 均值 μ 的估计:计算所有数据点的平均值。
    μ_hat = (1/M) * Σ_{m=1}^{M} x_m
    
  • 协方差矩阵 Σ 的估计:将协方差公式应用于数据集。对于矩阵的 (i, j) 元素:
    Σ_hat[i,j] = (1/M) * Σ_{m=1}^{M} (x_m[i] - μ_hat[i]) * (x_m[j] - μ_hat[j])
    
    这等价于计算数据中特征 i 和特征 j 的乘积的平均值,再减去各自均值的乘积。

总结

本节课中,我们一起学习了多元高斯分布。

  1. 我们首先回顾了二维高斯分布,并将其概念推广到 D 维空间,引入了均值向量 μ协方差矩阵 Σ 作为核心参数。
  2. 我们分析了密度函数的公式,并指出其核心是一个关于 x 的二次型。
  3. 我们探讨了两种重要的特殊情形:
    • 对角高斯分布:当特征独立时,协方差矩阵为对角矩阵,参数数量仅为 2D,计算和存储更高效。
    • 球面高斯分布:当特征独立且同方差时,协方差矩阵是单位矩阵的倍数,等密度面为球面。
  4. 最后,我们介绍了如何从数据中拟合高斯分布,即计算数据的经验均值和经验协方差矩阵。

多元高斯分布是建模高维数据最常用、最重要的分布之一,现在它已成为你知识库中的一部分。

017:高斯生成模型 🧠

在本节课中,我们将学习如何使用多元高斯分布来构建分类器。我们将探讨生成式分类方法,特别是当为每个类别拟合高斯分布时,会形成何种决策边界。我们会从简单的例子开始,逐步深入到更一般的情况,并理解决策边界为何通常是二次的。


上一节我们介绍了多元高斯分布。本节中我们来看看如何利用这些分布来构建分类器。

我们已经回顾了分类的生成式方法,即为每个类别单独拟合一个概率分布。今天我们将重点探讨采用这种方法时所产生的决策边界类型。

从葡萄酒数据开始 🍷

让我们从葡萄酒数据开始回顾。这个数据集包含三个类别(代表三个不同的酒庄)和13个特征。

我们最初只选择了一个特征——酒精含量,并为三个类别分别拟合了一个一维高斯分布。由此得到的分类器在测试集上的错误率为29%,效果并不理想。

随后,我们添加了第二个特征——类黄酮含量。我们为每个类别拟合了一个二元高斯分布,结果如图所示。

由此产生了三个椭圆区域。分类边界,即决策边界,如图所示。

此区域的点被分类为红色类别,此区域的点被分类为绿色类别,而此区域的点被分类为黑色类别。添加第二个特征使测试错误率从29%降至8%。

现在,既然我们已经掌握了多元高斯分布,就可以使用全部13个特征。我们可以为酒庄1的13个特征拟合一个多元高斯分布,再为酒庄2和酒庄3各拟合一个。然后应用贝叶斯规则进行分类。

如果这样做,我们会发现测试错误率实际上降到了0。这是否意味着它是一个完美的分类器?并非如此。一方面,测试集并不大,只有48个点。但这确实意味着,与仅使用一两个特征相比,这是一个好得多的分类器。这也表明,包含多个相关特征可能非常有益。

高斯生成模型的决策边界 📐

现在,让我们看看高斯生成建模通常会产生什么样的决策边界。

多元高斯分布具有我们讨论过的密度函数。正如我们所见,密度函数的第一部分实际上只是一个归一化因子。重要的部分是指数内的内容,它是一个二次函数。

如果想把指数部分“降下来”,可以对密度取对数。让我们看看这样做会发生什么。取 ( P(x) ) 的对数:

第一部分变成某个常数。指数部分则变为 ( -\frac{1}{2} (x - \mu)^T \Sigma^{-1} (x - \mu) )。

因此,( \log P(x) ) 是一个真正的二次函数。这意味着,如果在分类的生成式方法中使用高斯分布,得到的决策边界通常将是二次的。

让我们更仔细地看看为什么是这样。

二元分类情况下的决策规则 ⚖️

为了简化,我们看一个二元分类情况,只有两个类别。在生成式方法中,我们首先估计类别概率 ( \pi_1 ) 和 ( \pi_2 )。然后,为每个类别拟合一个高斯分布 ( P_1 ) 和 ( P_2 ),我们允许它们是任意的多元高斯分布。这些是模型的参数。

当一个新的数据点 ( x ) 到来时,为了对其分类,我们计算 ( \pi_1 \times P_1(x) ) 和 ( \pi_2 \times P_2(x) ),并看哪个值更大。这就是我们的分类规则。

我们可以将高斯密度公式代入 ( P_1 ) 和 ( P_2 ),然后对两边取对数,这将二次函数“降”下来。经过一些代数简化后,我们得到决策规则:

[
x^T M x + 2 w^T x \ge \theta
]

其中:

  • ( M = \frac{1}{2}(\Sigma_2^{-1} - \Sigma_1^{-1}) ) 是一个矩阵,使得 ( x^T M x ) 是一个通用的二次函数。
  • ( w ) 是一个向量,( 2w^T x ) 是一个线性函数。
  • ( \theta ) 是一个阈值常数。

这些都可以从模型参数(均值、协方差矩阵、先验概率)中推导出来。

使用此规则时,一些点被分类为类别1,一些点被分类为类别2。决策边界就是这两个区域之间的分隔区域,它精确地对应于方程 ( x^T M x + 2 w^T x = \theta )。这是一个二次边界。

特殊情况:线性决策边界 📈

有时矩阵 ( M ) 可能为零。从 ( M ) 的方程看,当两个类别的协方差矩阵相同时会发生这种情况。此时,二次项消失,我们得到一个线性决策边界。线性边界是二次边界的一个特例(退化情况)。

让我们从线性情况开始看起。当两个类别具有完全相同的协方差矩阵 ( \Sigma_1 = \Sigma_2 ) 时,会出现线性边界。

示例1:球形高斯,相同协方差与先验
假设每个类别都是一个球形高斯分布,具有相同的协方差矩阵(例如单位矩阵)。同时,假设两个类别的先验概率相同,即 ( \pi_1 = \pi_2 = 0.5 )。在这种情况下,决策边界只是两个类别中心(两个高斯均值 ( \mu_1 ) 和 ( \mu_2 ))之间的垂直平分线。考虑到这种情况的极端对称性,这正是我们所期望的。

示例2:相同协方差,不同先验
如果类别1出现的可能性稍大一些,例如 ( \pi_1 = 0.6, \pi_2 = 0.4 ),会发生什么?决策边界会略微向右移动。因为类别1比类别2更频繁,所以两个中心正中间的点现在会被分类为类别1。决策边界的移动是为了考虑先验类别概率的差异。

示例3:相同但非球形的协方差
如果两个类别具有相同的协方差矩阵,但矩阵不是球形的(即椭圆形状相同),边界仍然是线性的,但它不再是垂直平分线,而是会有所倾斜以适应不同的形状。

在所有这些情况下,分类规则都是 ( w \cdot x \ge \theta ) 形式的简单线性规则。向量 ( w ) 和数值 ( \theta ) 可以从模型参数中得出。在实践中,通常按此方式设置 ( w ),但允许阈值 ( \theta ) 略有变化(例如在训练集或验证集上进行微调以最大化性能),这相当于允许决策边界平行于自身略微左右移动。

一般情况:二次决策边界 🧮

如果协方差矩阵不相等,那么边界就是一个一般的二次曲线。

示例1:球形高斯,不同方差
两个类别都是球形高斯,但协方差矩阵不同。例如,左侧类别的方差较大(协方差矩阵为 ( 4I )),右侧类别的方差较小(协方差矩阵为 ( I ))。在这种情况下,决策边界是一个球体(或圆)。在紫色球体内的点被分类为类别2,球体外的点被分类为类别1。这在一维类比中更清晰:一个大方差高斯和一个小方差高斯,决策边界可能是两个区间,中间区域属于小方差类别,两侧区域属于大方差类别。

示例2:球形 vs 对角高斯
一个类别是球形高斯,另一个是对角高斯(即椭球形状,但主轴与坐标轴平行)。在这种情况下,决策边界是一条抛物线。

决策边界可能呈现许多其他形状,但它们都属于某种二次形式。

扩展到多类别分类 🔢

我们主要讨论了二元情况,因为只有两个标签时,谈论两个区域(类别1和类别2)之间的边界特别简单。但当存在多个标签时,整体情况大致相同。

假设有 ( K ) 个类别。我们为每个类别 ( j ) 拟合一个权重 ( \pi_j )(一个数字)和一个高斯密度 ( P_j )。

分类规则是:当新点 ( x ) 到来时,我们计算 ( \pi_j \times P_j(x) ),并选择使该值最大的类别 ( j )。等价地,我们可以选择使该值对数最大的类别 ( j ),因为高斯密度的对数是一个二次函数。

本质上,( K ) 个类别中的每一个都有其自己的二次函数。当新点到来时,每个类别评估其二次函数,得到一个数值,数值最大的类别胜出,即被预测的类别。

当所有 ( K ) 个类别的协方差矩阵都相同时,边界再次变为线性。


本节课中我们一起学习了高斯生成模型。我们了解到,通过为每个类别拟合高斯分布来构建分类器是一种简单而强大的方法。决策边界的形式取决于类别间协方差矩阵的关系:相同时为线性边界,不同时为二次边界。我们还探讨了从二元到多类别的扩展。高斯分布并非唯一可用的分布,下次我们将看看其他一些选择。

018:生成式建模进阶 🚀

在本节课中,我们将要学习生成式建模的进阶内容。我们将超越高斯分布,探索更多适用于不同数据类型的概率分布,并了解如何将这些分布组合起来处理高维数据。

从高斯分布到更广泛的分布

上一节我们介绍了通过为每个类别拟合高斯分布来构建分类器的方法。本节中,我们来看看当高斯分布不适用时,我们可以选择哪些其他分布。

在生成式分类方法中,核心思想是为每个类别单独拟合一个概率分布。当新数据点出现时,我们使用贝叶斯规则对其进行分类。到目前为止,我们只专注于为每个类别使用高斯分布。这确实是最重要的情况。但是,是否存在高斯分布不合适的情况呢?确实,存在许多这样的情况。

处理不同类型的一维数据

以下是几种常见的数据类型及其对应的合适分布:

情况一:数据为正值实数
假设我们的数据是实数值,因此是数值型的,但它总是正值。在这种情况下,使用高斯分布有时会显得有点奇怪,因为高斯分布的定义域是整个实数轴(包括正数和负数)。是否存在仅定义在正实数轴上的分布呢?一个主要的例子是伽马分布,如上图左上角所示。伽马分布由两个参数指定,就像高斯分布一样。随着参数的变化,你可以得到许多不同的形状,例如这里显示的红色曲线,或者其他形状。

情况二:数据位于特定区间内
如果数据是实数值,但总是位于特定区间内,例如0到1之间。在这种情况下,使用高斯分布会显得奇怪,因为它的定义域是所有实数;使用伽马分布也会显得奇怪,因为它的定义域是所有正实数。是否存在仅定义在一个区间上的分布呢?在这种情况下,一个非常常见的选择是贝塔分布,如上图右上角所示。与高斯分布和伽马分布一样,它由两个参数指定,并且可以呈现多种不同的形状,可以像这样,或者像一个倒置的碗,或者像均匀分布,甚至像这样。

情况三:数据为整数值
假设你拥有实值数据,它是数值型的,但所有数据点都是整数。例如,如果数据由计数组成(例如,夜间去急诊室的人数、加州特定地区发生地震的次数),就会出现这种情况。如果数据是正整数,那么高斯分布、伽马分布、贝塔分布都不完全合适,因为它们是为任意实数定义的分布。在这种情况下,最常见的选择是泊松分布,如上图左下角所示。它由单个参数(分布的均值)指定,并为每个非负整数(0, 1, 2, 3...)分配一个概率。这个分布被证明非常适合各种数据。

情况四:数据为有限类别
如果我们拥有的数据甚至不是数值型的,而是有有限多种可能的结果呢?例如,假设我们想为特定文档语料库中出现的单词拟合一个分布。我们想要每个单词的概率。这里有有限多种可能性(有限多个单词),我们将使用的分布是分类分布。它非常简单,只是为每个特定结果(每个特定单词)分配一个概率。

所有这些分布——伽马分布、贝塔分布、泊松分布、分类分布——在高斯分布不完全适用的情况下都非常有用。这四种分布,连同高斯分布,实际上属于一个更广泛的概率分布类别,称为指数族。伽马分布是指数族的一个特例,贝塔分布是指数族的另一个特例,高斯分布也是指数族的一员。那么,什么是指数族呢?遗憾的是,我们没有时间深入探讨。但简而言之,指数族是具有特定函数形式的分布,这种形式使它们易于处理,例如,非常容易进行参数估计。

处理高维数据

我们已经讨论了一系列适用于一维数据的分布,如伽马分布、贝塔分布等。我们如何处理高维数据呢?有没有办法以某种方式组合这些分布?事实证明,基本上有三种标准选择。

以下是三种处理高维数据的标准方法:

1. 朴素贝叶斯
第一种方法是假设不同的坐标是独立的。这被称为朴素贝叶斯。假设你有D维数据,坐标从x1, x2一直到Xd。如果x1是任意实数值,我们可以为其拟合一个高斯分布。如果x2由整数计数组成,我们可以为其拟合一个泊松分布。如果x3恰好位于一个固定区间内,我们可以为其拟合一个贝塔分布。通过这种方式,我们为每个单独的坐标拟合一个分布。现在,当我们想要整个向量x的概率时,我们只需取x1的一维概率乘以x2的一维概率乘以x3的一维概率,一直乘到最后一个坐标Xd的一维概率。这假设了坐标x1到Xd彼此之间都是独立的,但这很少是真实的。然而,尽管有这个错误的假设,这种特定方法在实践中往往非常有效,这就是朴素贝叶斯。

2. 多元高斯分布
第二种选择是使用我们讨论过很多的多元高斯分布。多元高斯分布不假设坐标是独立的,它允许我们建模坐标之间的两两相关性,正如我们所见,它使用起来确实非常简单。

3. 通用图模型
第三种选择是使用通用的图模型。遗憾的是,这超出了本课程的范围。但简而言之,图模型使用一个图来表示多个坐标上的概率分布。如果有D个坐标,每个坐标都有一个节点(x1一个节点,x2一个节点,一直到Xd一个节点)。如果两个坐标之间存在某种依赖关系,图中这两个节点之间就会有一条边。在完全通用的情况下,图模型允许我们为单个坐标x1, x2等使用任何分布,并且允许我们建模这些坐标之间的任意依赖关系,这是一种非常强大的方法。

总结

本节课中我们一起学习了生成式建模的进阶内容。生成式建模是一种非常流行的分类方法。它简单、高效且非常易于理解。我们首先探讨了高斯分布不适用时,可以选用的其他一维概率分布,如伽马分布(适用于正值实数)、贝塔分布(适用于固定区间)、泊松分布(适用于整数计数)和分类分布(适用于有限类别)。这些分布都属于更广泛的指数族分布。接着,我们了解了处理高维数据的三种主要策略:朴素贝叶斯(假设特征独立)、多元高斯分布(建模特征间的相关性)以及更强大的图模型(建模任意依赖关系)。生成式方法为分类问题提供了一个强大而直观的框架。

019:线性回归导论 📈

在本节课中,我们将学习线性回归的基本概念。我们将从分类问题转向回归问题,重点关注一维情况,即如何用一条直线拟合一组数据点。我们将定义预测变量和响应变量,并将回归问题形式化为一个优化任务,最后使用基础微积分求解。

从分类到回归 🔄

在过去的几周里,我们一直专注于分类问题。今天,我们将转换思路,开始研究回归问题。本节将介绍问题的一维版本,这有助于我们定义一些基本概念,如预测变量和响应变量。我们将看到如何将此问题表述为优化任务,以及如何使用基础微积分求解。

一维回归:拟合一条直线 📊

在一维情况下,回归就是为一系列点拟合一条直线。这是我们以前都见过的场景:我们有一个X轴和一个Y轴,以及一组点。我们想为它们拟合一条直线,但没有一条直线能完全穿过所有点。因此,我们只希望找到一条大致从它们中间穿过的线。我们究竟该如何做到这一点?又为什么要这样做呢?

一个预测示例:GPA与SAT分数 🎓

让我们看一个小例子。某所常春藤盟校收集了其新生班级的数据。在大一学年结束时,他们记录了每个人的GPA。这就是你在这里看到的直方图:GPA(平均绩点)是一个介于0到4之间的数字,显示在水平轴上;垂直轴是频率,即获得该成绩的人数。在这种情况下,最常见的成绩大约在2.25左右,即C+。

假设一个随机学生出现,我们想预测他或她的GPA。我们会预测什么分数?根据这些信息,一个合理的做法是简单地预测这个分布的均值。这很容易计算。如果我们这样做,结果在这种情况下是2.47。

这个预测有多好?评估其质量的一种方法是看它的平均平方误差。一个学生随机出现,这是他们的实际GPA,我们预测了这个特定值2.47。如果我们看这两者之间的差异并求平方,它的期望值是多少?仔细观察,这正是方差的公式,即这个分布的方差。在这种情况下,方差结果是0.55。

引入预测变量:降低误差 📉

现在,这所大学还收集了其他信息。除了每个人的大一GPA,他们还有高中时的SAT分数。这是两者相互对应的散点图:水平轴是SAT分数,垂直轴是大学GPA。你可以看到数据略微向上倾斜,这表明存在正相关关系。

在这种情况下,我们可以看看SAT分数是否有助于我们预测大学GPA。我们继续,拟合一条像这样的直线。现在我们将讨论如何精确地拟合这条线,但暂时,让我们先看看如何使用它。

假设一个随机学生出现,我们想预测他或她的GPA。现在我们找出SAT分数,假设是1200分。SAT分数是1200,我们只需向上找到这条线,然后横移,我们的预测是3,我们预测GPA为3。

当我们使用这个额外的信息进行预测时,结果平均平方误差下降了,降至约0.43。因此,这个额外的信息实际上非常有帮助。

这是一个经典的回归问题。有我们想要预测的东西,称为响应变量,即大学GPA。然后有帮助我们做出这个预测的信息,那些是预测变量。在这种情况下,只有一个预测变量,即SAT分数,所以这是x(帮助我们做出预测的东西)。然后是我们实际想要猜测的值,即Y(大学GPA)。

那么平均平方误差到底是什么?让我们看看这些数据。看这里的这个人。使用我们的线,对该人的预测实际上会在这里。所以存在一定量的误差,我们可以将其平方,看看那个平方误差。再看看这里的这个人。那个人的平方误差是这个距离的平方。再看看这个,那个人的平方误差是这个距离的平方,它小得多。再看看这个人,他们的平方误差实际上相当大。如果我们取所有这些平方误差的平均值,那就是平均平方误差。

参数化直线:斜率和截距 📐

我们如何拟合这种形式的直线?首先是要弄清楚如何参数化一条直线。一种方便的方法是将一条直线写为 y = ax + b,其中 a 是直线的斜率,b 是y轴截距。

例如,假设我们有我们的x轴和y轴。我们有一条像这样的直线,也许这里是2,这里是1。那么y轴截距是直线与y轴相交的地方,即1。在这种情况下,斜率是向下的,所以它将是负数,在这种情况下斜率是负二分之一。因此,这条直线的方程是 y = -0.5x + 1

因此,我们将使用这两个数字A和B来参数化一条直线。

定义优化问题:最小化损失函数 ⚙️

这让我们可以精确地定义问题。我们给定一组数据点,这些是XY对。X和Y都是实数。X是预测变量,在我们的例子中是SAT分数;Y是我们想要猜测的东西,即响应变量,在我们的例子中是GPA。因此,我们有n个这种形式的数据点。

我们想找到一条直线,换句话说,我们想找到定义一条直线的参数A和B。我们想要的是找到导致最小平均平方误差的直线。这就是由这个公式给出的。如果我们看第i个数据点 x_i,那么使用这条直线AB,我们对 x_i 的预测将是这个,这将是我们猜测的值。正确的值是 y_i

因此,在第i个数据点上产生的平方误差是这个项。现在我们取那个并对所有数据点求平均,这就是平均平方误差。这是我们试图最小化的损失函数。

这里发生了一些有趣的事情:我们正在将一个学习任务形式化为一个优化问题,即寻找最小化某种损失函数的参数的问题。这种优化方法在机器学习中被证明是极其富有成果的,我们将会看到更多这样的例子。

求解最优参数:微积分方法 🧮

让我们继续看看如何最小化这个损失函数。我们想要最小化这个具有两个参数A和B的函数L。我们可以直接求导数并设为零。这是通常的微积分方法。

由于有两个参数,我们需要对它们各自求导。为了最小化,我们将简单地将关于A的导数和关于B的导数设为零。

让我们继续计算这些导数。关于B的导数可能稍微简单一些,所以让我们从它开始。L关于B的导数是什么?L是一个大的求和,和的导数是导数的和,所以我们先写下来。现在,我们如何求那个的导数?我们那里有一个平方项。

有一个通用规则:如果我们对某个东西的平方 u^2 求导,结果将是 2u * du,即2u乘以u关于B的导数。对我们来说,u是这个东西。这就是u,我们想求它的导数,所以先写下2u。然后我们取u关于B的导数,实际上就是-1。所以乘以-1。这就是整个导数,我们想将其设为零。

由于我们将其设为零,我们可以直接消去-1和2。让我们看看我们得到了什么。我们得到 Σ y_i = a * Σ x_i + n * b,因为我们对b从i=1求和到n,所以是n乘以b。

让我们继续解出b。这告诉我们 b = (1/n) * Σ y_i - a * (1/n) * Σ x_i。这是b的最优设置。

那么这里的这些项是什么?这个项是什么?嗯,那只是平均y值,即平均响应值。那个东西是什么?那只是平均x值,在我们的例子中就是平均SAT分数。让我们以更紧凑的形式写下来。我们记住这个方程。

我们说的是,让我们看看平均x值,我称之为 。所以我们取所有x的平均值。再看看所有Y的平均值 。结果证明,b的最优设置是平均y值减去a乘以平均x值。这完全说得通:我们希望 y = ax + b。当然我们无法完全得到这个,但b是平均y值减去a乘以平均x值,这完全合理。

我们仍然需要解出a,我们通过将L关于a的导数设为零来做到这一点。然后我们进行计算,这次的代数运算稍微复杂一些。但我可以直接告诉你最终答案是什么。如果你愿意,可以在家尝试这些步骤,只是稍微麻烦一些。

结果证明,a的最优设置很简单,是x和y的协方差除以x的方差。所以它是这种形式:你取所有Y,减去它们的平均y,然后看它们与x的协方差。然后,你除以X减去平均x的平方。这就是a的最优设置。非常简单,一个漂亮的闭式解。

总结 📝

本节课中,我们一起学习了线性回归的基本介绍。今天我们只讨论了单预测变量的一维情况。下次,我们将把这种方法推广到多个预测变量。

020:线性回归 📈

在本节课中,我们将学习线性回归,这是一种用于预测连续数值的统计方法。我们将从一维数据扩展到多维数据,并学习如何通过最小二乘法找到最佳拟合线。

概述

上一节我们初步了解了线性回归在一维数据上的应用。本节中,我们将深入探讨完整的最小二乘回归。这是一种简单而强大的方法,也是统计学的基石之一。

多维数据的回归问题

我们将学习问题表述为一个带有明确损失函数的优化任务。然后我们会发现,这个优化任务实际上很容易解决。

作为示例,我们将使用一项糖尿病研究的数据。该研究的目标是评估哪些特征可能影响疾病的进展速度。例如,在固定时间段内病情恶化的程度。

数据收集自442名糖尿病患者。对于每位患者,测量了10个可能影响疾病进展的特征,包括年龄、身体质量指数(衡量超重程度的指标)、平均血压以及各种血液血清测量值。

这10个特征为每位患者测量后,患者在一年后返回,测量一个表示疾病在一年内进展程度的数值,该数值称为Y。这是一个经典的回归问题,我们有一个响应值Y,并希望根据一系列预测变量来预测这个响应。我们有10个这样的变量X1到X10,可以将它们打包成一个10维向量。

我们希望将Y建模为X的线性函数。让我们看看这意味着什么。

当我们只有一个变量X时,X的线性函数是这样的:Y = wX + b,其中w是斜率,b是截距。当我们有10个变量时,线性函数看起来是这样的:w1x1 + w2x2 + ... + w10x10,最后再加上截距项b。

我们可以更简单地将其写为 w·x + b,其中我们将系数w1到w10打包成一个单独的向量w。这是线性函数的一种简洁形式。

这就是我们将要拟合到数据的模型类型。在任何给定的点x上,我们的预测将是w·x + b,而正确值是y。因此,误差需要以某种方式惩罚。我们将使用平方损失,即我们预测的值与实际值之间的平方差。

这直接引出了最小二乘回归问题。我们有n个数据点,在我们的案例中有442名患者,所以n=442。点x1到xn是我们的D维向量,我们有10个特征,所以d=10。然后我们还有响应值y1到yn。

基于这些数据,我们想要学习一个线性函数,换句话说,我们想要学习参数w和b。我们希望选择能够最小化总平方误差的线性函数,即最小化所有数据点上第i个数据点的平方误差之和。

这是一个非常简单的损失函数。我们希望找到能够最小化这个损失函数的向量w和值b。

结果证明,对于最优的w和b,有一个很好的闭式解,我们很快就会看到。但首先,让我们看看在糖尿病数据上会发生什么。

假设我们根本没有预测变量,我们只需要预测y,我们会预测y的什么值?我们会预测y的平均值,即均值。在这种情况下,均方误差将仅仅是y的方差。

在糖尿病示例中,这个方差结果是5,930。这可能看起来有点大,但实际上这些y值,即疾病的进展程度,是像100、200、300这样的数字,所以当y是200时,y的平方是40,000。相对于这个,大约6,000的方差似乎是合理的。

现在假设我们加入一个预测特征,例如使用身体质量指数。这里显示的是一个散点图,x轴是身体质量指数,y轴是疾病进展的y值。这是442个数据点的散点图。我还显示了通过最小二乘回归得到的线。

使用这条线,均方误差显著下降到3,890。然后我们可以加入第二个预测变量,例如使用其中一个血清测量值,均方误差进一步下降。然后我们可以继续使用所有10个变量,使均方误差最小,为2,860。

在计算上,所有这些不同的计算都非常简单,因为对于w有一个很好的闭式公式。事实上,这是整个课程中少数几个优化测试有如此简单解决方案的情况之一。

优化问题的简化

让我们看看它是如何工作的。我们再次将线性函数拟合到数据,线性函数是这种形式:如果我们有d个特征。

这里的截距项很重要,但它有点突出,有点不方便,因为它看起来与其他所有项都略有不同。在进行优化时,例如,我们必须将其单独处理。

幸运的是,有一种方法可以使其消失,基本上是通过将其吸收到w中。让我们看看如何做到这一点。

这是将b吸收到w向量中的技巧。我们做的第一件事是向数据x添加一个额外的特征,只需在所有数据点前面加一个1。例如,如果我们有一个看起来像这样的数据点,我们写下相同的东西,但在前面加一个1。所以每个点x现在变成了一个新点,我们称之为x波浪,它只是1后面跟着原来的x。这些新点x波浪现在是d+1维。

接下来,我们将b和w放在一起,并称该向量为w波浪。现在让我们看看我们的线性函数会发生什么。我们的线性函数是w·x + b,但这完全等同于w波浪·x波浪,因为w波浪是(b, w),而x波浪是(1, x),所以它正好是b + w·x。

因此,我们成功地将线性函数重写为没有b的形式,通过向数据点和w向量添加一个额外的特征。所以现在我们只需要优化w波浪。这是新的损失函数,我们希望找到w波浪,再次导致数据集上的最小平方误差。

矩阵形式与闭式解

正如我们将看到的,对于w波浪有一个很好的公式。推导公式的第一步实际上是将这个损失函数纯粹重写为矩阵向量乘积。我们为什么要这样做?结果证明,这为w波浪带来了一个简洁的表达式。

让我们看看会发生什么。这是我们的损失函数,我们将用矩阵和向量来重写它。实际上,这通常是非常有用的。部分原因在于,像Python这样的标准平台具有高度优化的矩阵数学例程,用于矩阵和向量乘法。同时,它们在诸如for循环之类的事情上可能非常慢。

因此,如果你能以某种方式将你的for循环重写为矩阵向量乘积或矩阵矩阵乘积,你的代码可能会显著加速。但是,我们如何以这种方式重写呢?让我们看看这个损失函数,我们有一个包含求和的损失函数,通常如果我们有一个求和,那会让我们想到一个for循环。

但我们可以重写它,让我们看看如何。首先,我们创建一个矩阵,每行一个数据点,所以有n行。当然,我们现在已经增强了我们的数据,我们添加了这个额外的特征,我们在每个向量前面加了一个1。所以我们有d+1列。这就是矩阵X。让我们创建一个包含所有响应值的向量,所以y是n×1。

现在让我们看看X乘以w波浪是什么。它是X的第一行与w波浪的点积,X的第二行与w波浪的点积,依此类推,正好是预测值。所以这正好是w波浪·x1,w波浪·x2,一直到w波浪·xn。

同样,如果我们看y - Xw波浪,那是什么?它简单地是误差向量。它是第一个点的误差,y1 - w波浪·x1,一直到最后一个点的误差,yn - w波浪·xn。特别是,这个向量的平方范数,也就是这里的这个量,正好是所有平方误差的总和,正好是损失函数。

因此,我们重写了我们的损失函数,没有任何求和,纯粹用向量和矩阵表示。在这一点上,我们可以求导数并将其设为零,结果证明解如下:我们将w波浪设为 (X^T X)^(-1) X^T y,这是一个(d+1)×(d+1)矩阵乘以X^T y,这是一个(d+1)×1向量。结果是一个(d+1)×1向量。当然,该答案中的第一项是我们之前称为b的截距项。

这是一个非常简单的解决方案。

总结

本节课我们一起学习了最小二乘回归。这是一种非常容易且强大的方法,在广泛的应用中都非常有用。这是统计学中许多内容的基础。

021:正则化线性回归 🧠

在本节课中,我们将学习最小二乘回归的一些流行变体。我们将从泛化问题开始讨论,并引出正则化的强大概念。我们将看到两种正则化的最小二乘回归形式:岭回归和套索回归。


上一节我们介绍了最小二乘回归的基本概念。本节中我们来看看泛化问题。

在训练集上表现良好,是否意味着在未来的测试数据上也必然表现良好?

如果不是,是否存在不专门针对训练集性能的损失函数?这将引出强大的正则化概念。


最小二乘回归涉及寻找一个线性函数,以最小化训练集上的平方损失。这是否意味着在未来的数据上也能获得较低的平方损失和良好性能?不一定。有两种情况需要考虑。

如果训练数据量 n 很大,那么训练集上的良好性能可能合理地预示着未来也会有相当好的性能。但如果 n 很小,那么训练集上的性能很可能严重低估了未来的误差。

让我们通过一个具体例子来看。这是一个数据集,只有一个特征 x 和响应值 y。如果我们用一条线拟合这些数据,它看起来像这样。在这种情况下,这条线只由两个参数决定,这是一个一维设置。我们有两个参数和大约100个数据点,相对于需要拟合的参数数量来说,这是充足的数据。在这种情况下,训练误差很可能对未来数据上的误差率给出合理的估计。

但假设我们没有这么多训练数据。假设我们只有其中一个点,而不是这100个点。我们会用哪条线来拟合这个数据点?有很多可能性,我们可以拟合这条线、那条线或另一条线。它们都有零训练误差。这是否意味着未来测试点上的误差也为零?当然不是。这是一个极端情况。假设我们有两个训练点。在这种情况下,我们拟合的线会是这样的。同样,这是零训练误差。这条线在未来测试点上表现如何?让我们回头看看数据的整体分布。这条线在上面会表现得很差。

所有这些都引发了一些重大问题。

第一个大问题是:如果训练误差不是未来测试误差的良好度量,我们如何获得未来误差的良好估计?

通常的做法,一种简单的方法是使用交叉验证。我们在讨论最近邻时提到过这一点,但让我再快速回顾一下,因为它确实是一项非常重要的技术。

在K折交叉验证中,我们将训练集分成K个大小相等的块。如果我们有 n 个点,我们将它们分成K组,每组 n/K 个点。然后,我们将第一块视为测试集,在剩余的 K-1 块上进行训练。这将产生某个线性函数,然后我们在第一块上评估该函数。这将给出某个误差率。接着,我们将第二块视为测试集,在剩余的 K-1 块上训练,得到某个线性函数并在第二块上评估,依此类推。这样,我们得到K个不同的误差估计 E1EK,我们只需返回它们的平均值,这是对未来误差更合理的估计。

这解决了第一个问题。

第二个问题是:如果训练误差确实不是未来误差的良好度量,那么我们为什么要使用完全基于训练误差的优化准则?我们是否可以优化其他东西?是否有什么东西可能带来更好的未来性能?

确实,存在其他类型的优化准则。


上一节我们提出了关于优化准则的问题。本节中我们来看一个具体的例子:岭回归。

在岭回归中,目标与之前一样,是学习一个由 wb 给出的线性函数,但损失函数略有不同。除了之前的平方损失外,还有一个额外的项,称为正则化项。在这种情况下,它就是 w 的L2范数的平方乘以某个常数 λ

这个正则化项有什么作用?让我们看两个极端情况。

假设我们将 λ 设为零。在这种情况下,第二项消失,无关紧要,我们就得到了常规的最小二乘回归。此时 w 将是最小二乘解。如果我们有很多数据,这是一个合理的解。

现在,假设我们将 λ 设为一个很大的值,甚至让 λ 趋于无穷大。会发生什么?如果 λ 趋于无穷大,唯一重要的是第二项。我们将不惜一切代价使 w 尽可能小,我们会尽力缩小其范数。实际上,我们会直接将 w 设为零。如果我们完全没有数据,这是一个合理的解。

在实践中,我们会选择介于这两个极端之间的某个 λ 值。因此,它的作用是执行类似最小二乘的操作,但将该解向零移动,在某种意义上将其向零收缩。因此,它有时被称为收缩估计量。

实际上,对于岭回归,最优 w 有一个很好的闭式方程。让我展示给你看。

这是 w 的公式。如果我们设 λ 为零。

λ 乘以单位矩阵的项就消失了,我们得到了上次看到的最小二乘解。但随着我们增大 λ,这里的第一项变得更大。因此,它的逆在分母中,意味着分母越来越大,从而我们收缩了得到的 w


了解了岭回归的原理后,让我们看看它在实践中如何运作。

这里,我创建了一个玩具数据集。其中有100个特征 x1x100,每个都服从高斯分布。还有一个响应值 y。有趣的是,响应仅依赖于其中10个特征,即仅依赖于特征 x1x10。其余90个特征是纯噪声。

训练集和测试集各包含100个点。100维空间中的100个训练点,数据量多吗?不,当然不多。实际上,你几乎总是可以拟合100维空间中的100个点,就像解100个线性方程求100个未知数。数据量不大,让我们看看岭回归在这种情况下会怎么做。

λ 是我们需要设定的参数。让我们看看一系列不同的 λ 值。

λ 非常小时,就像这里的这条线所示,我们基本上得到了最小二乘解。

在这种情况下,正则化项无关紧要。所以它是最小二乘解,具有零训练误差,因为如前所述,你几乎总是可以拟合100维空间中的100个点。但测试误差非常高,所以在这种情况下最小二乘表现不佳。

现在看看另一个极端,当 λ 非常大时。

在这种情况下,正如我们所见,我们将得到一个极小的 w,接近于零。有趣的是,当 w 基本为零时,训练误差是12.6。这强调了最小二乘估计量有多差,它的训练误差是585,所以在这种情况下确实表现得非常非常差。

随着我们增大 λ,我们逐渐减少对训练集的重视,逐渐增加对拥有小 w 的重视。由于我们减少了对训练集的重视,训练误差逐渐上升,正如你所见。但测试误差下降了很多。实际上,它在这里触底。在那之后,它又开始上升,因为那时我们基本上没有给予训练集足够的关注。

因此,在这种情况下,λ 的最优值大约在这里。在实践中,我们如何选择最优的 λ?很简单,通过交叉验证。


我们讨论了一种收缩估计量:岭回归,其正则化项是 w 的L2范数的平方。但如果我们使用不同的范数会发生什么?一个非常流行的选择是使用L1范数。在这种情况下,估计量被称为套索回归。

它大致具有与岭回归相同的良好泛化行为,但有一个额外的重要好处:它倾向于产生稀疏解 w。也就是说,它产生的向量 w 往往有很多零,只有少数非零项。

例如,如果你回到我们的小玩具数据集,并在其上运行套索回归,它找到的 w 将只有少数非零特征,它会识别出10个相关特征。

实际上还会多找出几个。这令人印象深刻。

一般来说,为什么我们需要稀疏解?为什么拥有稀疏的 w 有吸引力?当然有一些计算上的好处。如果我们只使用几个特征,那就意味着我们需要存储的数据少得多,计算也更快。但最重要的是,拥有稀疏 w 的好处在于,得到的线性模型更容易理解和解释。人类更可能欣赏和使用他们真正理解的模型。


本节课中我们一起学习了正则化线性回归。我们探讨了训练误差与泛化误差的区别,并介绍了交叉验证作为评估未来性能的方法。我们深入研究了两种正则化方法:岭回归(使用L2正则化)和套索回归(使用L1正则化)。岭回归通过收缩系数向零来控制模型复杂度,而套索回归除了收缩外,还能产生稀疏模型,有助于特征选择。

我们尚未讨论的是超越线性回归,例如使用多项式函数的回归。但在课程稍后部分,我们将开发一些方法来展示如何轻松地处理这个问题。下次见。

022:条件概率估计的线性模型 📈

在本节课中,我们将学习一种新的预测问题类型:条件概率估计。我们将从探讨预测问题中的不确定性来源开始,然后了解如何用线性函数来捕捉这种不确定性,最终引出逻辑回归的公式。

预测中的不确定性来源

上一节我们介绍了分类和回归问题,本节中我们来看看为什么完美的分类器通常无法实现。主要有两个原因。

第一个原因是,我们拥有的特征 X 可能本身就不包含足够的信息来完美预测标签 y。例如,即使拥有患者完整的医疗记录,也无法完全确定地预测某人未来是否会患病,因为其中存在大量偶然因素。在这种情况下,我们不仅希望做出预测,还希望能对预测的不确定性进行量化,例如说“此人有80%的概率会患病”。

第二个原因是,我们使用的分类器类型可能无法完美捕捉真实的决策边界。例如,如果我们使用线性分类器,而真实边界是非线性的,那么最好的线性分类器也无法做到完美分类。此时,我们同样希望能输出一个概率,例如“该样本标签为绿色的概率是70%”。

从线性边界到概率

我们主要讨论二分类问题,标签为 +1-1。我们的目标是,对于给定的数据点 x,预测 y = +1 的概率 P(y=+1 | x)。当然,P(y=-1 | x) = 1 - P(y=+1 | x)

假设我们使用一个线性决策边界。在边界上,y = +1 的概率是50%。在边界的一侧,概率会高于50%,并随着距离边界越远而越高;在另一侧,概率则低于50%,并随着距离边界越远而越低。因此,概率的大小取决于数据点到决策边界的距离。

让我们通过一个二维例子来具体说明。

一个二维示例

假设我们有一个二维空间,决策边界是直线 x1 + x2 - 2 = 0。这条线就是 P(y=+1 | x) = 0.5 的等概率线。

以下是不同概率对应的等值线:

  • 在直线 x1 + x2 - 2 = 1 上,P(y=+1 | x) = 0.6
  • 在直线 x1 + x2 - 2 = -1 上,P(y=+1 | x) = 0.4

可以看到,我们只需计算线性函数 f(x) = x1 + x2 - 2 的值。这个值 f(x) 决定了概率:

  • f(x) = 0,概率为 0.5。
  • f(x) > 0,概率大于 0.5,且值越大,概率越高。
  • f(x) < 0,概率小于 0.5,且值越小,概率越低。

推广到一般情况

现在我们将这个概念推广到 D 维数据。对于一个数据点 x ∈ R^D,我们计算一个通用的线性函数:

f(x) = w · x + b

其中 w 是权重向量,b 是偏置项。这个函数 f(x) 的值域是 (-∞, +∞)

为了将 f(x) 映射到 [0, 1] 的概率区间,我们需要一个“压缩函数”。这里我们使用 Sigmoid 函数(或称逻辑函数):

σ(z) = 1 / (1 + e^{-z})

这个函数的特性是:

  • z = 0 时,σ(z) = 0.5
  • z → +∞ 时,σ(z) → 1
  • z → -∞ 时,σ(z) → 0

逻辑回归模型

结合线性函数和Sigmoid函数,我们得到逻辑回归模型。对于点 xy = +1 的概率为:

P(y = +1 | x) = σ(w · x + b) = 1 / (1 + e^{-(w·x + b)})

相应地,y = -1 的概率为:

P(y = -1 | x) = 1 - P(y = +1 | x) = e^{-(w·x + b)} / (1 + e^{-(w·x + b)})

我们可以将这两个公式统一为一个简洁的表达式。对于任意标签 y ∈ {+1, -1},其条件概率为:

P(y | x) = 1 / (1 + e^{-y (w·x + b)})

验证

  • y = +1 时,公式变为 1 / (1 + e^{-(w·x + b)}),即 P(y=+1 | x)
  • y = -1 时,公式变为 1 / (1 + e^{+(w·x + b)}),经过简单代数变换(分子分母同乘 e^{-(w·x + b)})即可得到上面的 P(y=-1 | x) 公式。

总结

本节课中我们一起学习了条件概率估计的线性模型——逻辑回归。我们首先探讨了预测中不确定性的两个主要来源:特征信息不足和模型表达能力有限。接着,我们看到了如何利用线性函数结合Sigmoid压缩函数,将任意实数值转化为 [0, 1] 区间内的概率,从而构建出逻辑回归模型。该模型的核心公式是:

P(y | x) = 1 / (1 + e^{-y (w·x + b)})

这个模型基于参数 wb。在下节课中,我们将学习如何从数据中学习(训练)出这些参数。

023:逻辑回归模型学习 🧠

在本节课中,我们将学习如何从数据中学习一个逻辑回归模型。我们将从回顾模型的基本形式开始,然后将其学习问题表述为一个优化任务,目标是最小化一个合适的损失函数。这个损失函数具有良好的性质,特别是它是凸函数。最后,我们将看到如何使用梯度下降来最小化这个函数。


模型回顾

上一节我们介绍了逻辑回归模型。它适用于二元标签分类问题,其中标签 y 只能取两个值:-1+1。数据点 x 位于 D 维空间中。对于任意给定的点 x,标签 y 的概率由以下公式给出:

\[P(y|x) = \frac{1}{1 + e^{-y(w \cdot x + b)}} \]

我们首先计算 x 的线性函数 w \cdot x + b,然后将其代入逻辑函数。这个模型有两个需要设定的参数:权重向量 w 和偏置 b

从几何上看,决策边界是使得概率恰好为 0.5 的点集,即满足 w \cdot x + b = 0 的点。在二维空间中,这是一条直线;在三维空间中,是一个平面;更高维度中,则是一个超平面。当我们沿着垂直于边界的方向移动时,y=+1 的概率会相应增加或减少。


学习问题:最大似然估计

本节中,我们来看看如何从数据中学习这个线性函数。我们有一个包含 n 个数据点的数据集:(x1, y1), (x2, y2), ..., (xn, yn)

我们将采用最大似然估计原则,即选择能使数据概率最大化的参数 wb。具体来说,我们希望最大化以下联合概率:

\[\prod_{i=1}^{n} P(y_i | x_i) \]

为了计算方便,我们通常取对数,将乘积转化为求和。同时,为了将其转化为最小化问题,我们在前面加上负号。这样,我们就得到了最终的损失函数:

\[L(w, b) = -\sum_{i=1}^{n} \log P(y_i | x_i) \]

我们的目标是找到最小化该损失函数的 wb


简化与优化

为了简化问题,我们可以像在线性回归中那样,通过添加一个恒为 1 的特征将偏置 b 吸收到权重向量 w 中。这样,我们只需优化一个参数 w

关于最优解 w,有一个坏消息和一个好消息。

  • 坏消息是,与最小二乘回归不同,逻辑回归没有闭式解(即一个简单的公式可以直接计算出 w)。
  • 好消息是,这个损失函数是凸函数。这意味着它的形状像一个碗,只有一个全局最小值,没有令人困扰的局部最小值。这使得优化过程更加可靠。

梯度下降法

既然没有直接公式,我们如何找到这个最小值点呢?我们将使用局部搜索的方法,也就是梯度下降法

其核心思想是:从一个初始猜测(例如 w 为零向量)开始,然后反复朝着能降低损失函数值的方向微调 w,直到收敛。

具体如何决定调整方向呢?答案是使用梯度(即函数在某点的斜率)。在最小化问题中,我们应朝着负梯度方向移动。梯度下降的更新规则如下:

\[w_{t+1} = w_t - \eta \sum_{i=1}^{n} \left[ \frac{y_i x_i}{1 + e^{y_i (w_t \cdot x_i)}} \right] \]

以下是该更新规则中关键部分的解释:

  • w_t:第 t 次迭代时的权重向量。
  • \eta学习率(步长),控制每次更新的幅度。初期可以设为一个小常数(如 0.1),后续可以逐渐减小。
  • 求和项:计算的是一个加权平均的数据点方向。每个数据点 x_i 的权重取决于当前模型对其分类的好坏。如果模型对某个点 (x_i, y_i) 的分类概率很低(即分类错误),那么这个点在更新中会获得更高的权重,促使模型更多地关注它。

示例演示

让我们在一个简单的二维示例上看一下效果。假设我们有两类数据点,分别标记为 -1(紫色)和 +1(绿色)。

我们采样一些数据点,并应用上述梯度下降算法来寻找最优的线性函数。

最终,算法找到了三条重要的线:

  1. 中间的实线:决策边界(P(y=+1) = 0.5)。
  2. 上方的虚线:对应 P(y=+1) = 0.75 的等高线。
  3. 下方的虚线:对应 P(y=+1) = 0.25(即 P(y=-1) = 0.75)的等高线。

这意味着,位于上方虚线处的点,模型认为其属于绿色类别的概率是 75%;位于下方虚线处的点,模型认为其属于紫色类别的概率是 75%。这为我们提供了分类的置信度信息,尽管在实际解读这些概率时需要谨慎。


总结

本节课中,我们一起学习了如何从数据中学习逻辑回归模型。我们首先将学习问题形式化为最大似然估计,并推导出凸的损失函数。由于没有闭式解,我们介绍了使用梯度下降法进行优化的过程,并解释了其更新公式的直观含义。最后,我们通过一个简单示例观察了模型学习到的决策边界和概率等高线。

下次课,我们将把逻辑回归应用到一个更实际的学习问题——文本分类任务上。

024:逻辑回归的应用 🧠

在本节课中,我们将通过一个具体的案例研究,学习逻辑回归如何应用于实际问题。我们将探讨如何将文本数据转换为机器学习模型可以处理的格式,并解读模型训练的结果与意义。


文本分类问题

我们想要解决的问题是文本分类。具体来说,我们获得一段关于产品、电影或餐厅的评论,需要判断它是正面评价还是负面评价。我们使用的数据收集自亚马逊和Yelp等网站,每条数据是从评论中提取的一个句子,并已被标记为正面(+)或负面(-)。

以下是几个例子:

  • 负面:“needless to say I wasted my money”。关键词是“wasted”。
  • 正面:“he was very impressed when going from the original battery to the extended battery”。关键词是“impressed”。
  • 负面:“I have to jiggle the plug in order to get it to line up right to get decent volume”。这个句子没有明显的负面词汇,判断起来有些难度。
  • 正面:“We‘ll order from them again”。这个句子也没有明显的正面词汇,同样具有挑战性。

这个任务并非轻而易举。逻辑回归的优势在于,它不仅能输出预测结果(正面或负面),还能给出相应的概率,从而帮助我们量化预测的不确定性。

我们拥有约2500个训练句子和500个测试句子。这个数据量并不算大。


文本向量化:词袋模型

为了运行逻辑回归,我们需要将句子转换为固定长度的向量。将文档转换为向量有一种非常标准的方法,称为词袋表示法

以下是具体步骤:

  1. 首先,确定一个词汇表。例如,我们可以选择数据集中最常见的5000个词。
  2. 然后,每个文档(句子)将被表示为一个5000维的向量。向量的每个维度对应词汇表中的一个词。
  3. 该维度的值,就是这个词在文档中出现的次数。

例如,假设词汇表的第一个词是“despair”。我们遍历文档,统计“despair”出现的次数(比如1次),那么向量第一个位置的值就是1。接着看第二个词“evil”,出现2次,则对应值为2。第三个词“happiness”未出现,值为0,以此类推。

需要指出的是,这种表示法生成的向量通常非常稀疏。对于一个只有10个词的句子,在5000维的向量中,最多只有10个非零值。


应用逻辑回归

现在我们已经准备好应用逻辑回归。我们将正面类别编码为+1,负面类别编码为-1。我们有2500个数据点,每个点都是一个5000维的向量。我们的目标是找到由权重向量 W 和偏置项 b 定义的线性函数,以最小化逻辑回归的损失函数。

正如上一节所介绍的,这是一个凸损失函数,可以使用局部搜索方法轻松优化,例如梯度下降、随机梯度下降或牛顿法等。它们都能找到正确的解。

本节课我们将使用随机梯度下降方法。这是一种非常重要的优化方法,我们将在下周详细讨论。目前,你可以将其理解为一个局部搜索方法:它从一个初始的 Wb 猜测开始,然后不断进行微调,最终收敛到正确的答案。

对于这个特定数据集,大约需要300次迭代才能使线性函数 Wb 收敛。每次迭代都会遍历整个数据集。随着迭代的进行,训练集上的损失函数持续下降。在前50次迭代左右,损失函数急剧下降,之后逐渐趋于平缓,最终停止变化。

训练结束后,我们得到了最终的分类器 Wb。它在测试集上的错误率是21%。考虑到这些句子的模糊性和难度,这个结果不算出色,但也不差。


分析错误案例

让我们看看模型犯的一些错误:

以下是模型预测错误的部分句子:

  • “not much dialogue, not much music, the whole film was shot as elaborately anestheically like a sculpture.”(实际:正面)——这个句子开头听起来有点负面,且没有明显的正面词汇。
  • “The last 15 minutes of movie are also not bad as well.”(实际:正面)——包含了双重否定“not bad”,容易造成混淆,模型预测为负面。
  • “if you look for authentic Thai food, go elsewhere.”(实际:负面)——“authentic Thai food”听起来不错,但“go elsewhere”却是负面,判断起来有难度。
  • “waste your money on this game.”(实际:负面)——这是一个非常棘手的句子。

理解模型的“置信度”

逻辑回归不仅输出分类,还输出一个介于0和1之间的概率值,我们可以将其视为一种置信度水平

对于任意句子 x,我们得到一个概率值 P(y=+1 | x)。如果概率大于0.5,我们预测为正面;小于0.5则预测为负面。当概率接近0.5时,意味着模型非常不确定。置信度更高的预测,其概率值更接近0或1。

我们可以定义“边界”来衡量置信度:

  • 边界(Margin) 的公式为:|P(y=+1 | x) - 0.5|
  • 例如,概率高于0.8或低于0.2,可以认为是80%置信度(边界 ≥ 0.3)。
  • 概率高于0.9或低于0.1,则是90%置信度(边界 ≥ 0.4)。

分析测试集数据发现:

  • 大约75%的测试点具有90%或更高的置信度(边界 ≥ 0.4)。
  • 大约55%的测试点具有99%或更高的置信度。

这表明逻辑回归模型即使在训练数据不多的情况下,也做出了许多非常自信的预测。这本身有点令人怀疑,因此值得探究这种置信度是否合理。

我们知道整体错误率是21%。但如果我们只看模型置信度高的那些点呢?

  • 在模型90%置信度(边界≥0.4)的点上,错误率约为13%,远低于21%。
  • 在模型99%置信度(边界≥0.49)的点上,错误率仅略高于10%。

这说明了两个问题:

  1. 这些置信度水平需要谨慎看待。模型99%的置信度并不意味着它99%的情况下都是正确的。
  2. 但这些置信度值确实提供了信息。通过关注高置信度的预测,我们可以有效降低错误率。

解读模型:重要的词汇

我们还可以探究模型做出预测的依据,即哪些词汇对决策的影响最大。这可以通过分析学习到的权重向量 W 来实现。W 是一个5000维的向量,每个维度对应一个词。

对预测影响最大的词汇,就是那些具有最大系数(权重)的词,无论是最大的正系数还是最大的负系数。

以下是具有最大正系数(倾向于预测为正面)和最大负系数(倾向于预测为负面)的部分词汇:

正面词汇beautiful, fantastic, excellent, wonderful, nice, awesome, perfect 等。😊

负面词汇disappointing, stupid, lazy, dirty, bad, fails, unfortunately 等。

这些词汇看起来是判断评论正面或负面的合理指标,结果非常符合直觉。


总结与预告

本节课中,我们一起学习了逻辑回归在一个文本情感分类案例中的完整应用流程。我们从定义问题开始,学习了如何使用词袋模型将文本数据转换为特征向量。接着,我们应用逻辑回归进行训练,并分析了模型的测试错误率、错误案例以及模型输出的概率置信度所蕴含的信息。最后,我们通过解读权重向量,发现了模型认为最重要的正面和负面词汇。

我们暂时搁置了一个重要讨论:如何实际优化这些损失函数。像凸性随机梯度下降这样的概念和技术,是现代机器学习的核心。接下来,我们将花些时间,仔细深入地研究这些内容。

下次课见!

025:无约束最优化 I

在本节课中,我们将要学习机器学习中的一个核心概念:优化。我们将了解如何通过最小化损失函数来学习模型参数,并重点介绍一种名为梯度下降的通用优化算法。掌握这个方法将使你能够为特定问题定制损失函数,而不必依赖现成的解决方案。

局部搜索与局部最优问题

在过去的几节课中,我们一直在使用优化方法来解决预测问题。基本做法是定义一个合适的损失函数,然后通过最小化该函数来学习参数。我们在最小二乘回归和逻辑回归中就是这样做的。在接下来的几周里,我们还会做更多类似的工作。事实上,优化是现代机器学习的核心。

有时,你需要解决的问题恰好属于某个预定义的类别,那么你很幸运,可以直接使用逻辑回归、Lasso或支持向量机等现有软件。但有时,为了获得真正好的解决方案,你必须提出一个定制的、真正为特定领域量身打造的损失函数。在这些情况下,你不能再依赖现有的代码。幸运的是,对于几乎任何损失函数,都有一些相对直接的方法来设计最小化算法。今天,我们将介绍其中一种方法,称为梯度下降。

熟悉梯度下降是一种强大的能力,因为它使你摆脱了对现成解决方案的依赖。

现在,我们开始讨论如何使用局部搜索来解决优化问题,以及多局部最优值的问题。

梯度下降算法

我们将要介绍的算法是梯度下降。使用它只需要能够计算损失函数的导数,我们稍后会讨论这意味着什么。

对于大多数机器学习任务,我们通过定义合适的损失函数并最小化它来学习。例如,这些是最小二乘回归和逻辑回归的损失函数。

我们如何最小化这样的损失函数?如何找到最小化参数 W?在大多数情况下,我们通过局部搜索来实现。我们从对 W 的某个猜测开始,然后稍微调整它以使其更好(减少损失),然后再调整一些,如此反复,直到整个过程收敛。

从图像上看,它是这样的:横轴代表参数 W,纵轴代表损失函数 L(W)。我们要找的是这个损失函数的最小值点,我们称之为 W*。

局部搜索从任意一个初始解开始,比如这里。然后它稍微调整一下,使其变得更好,可能跳到那个点。然后它再调整一些,如此继续,直到到达一个地方,在那里任何微小的调整都无法再提供帮助,然后停止。在这种情况下,它最终找到了正确答案。

然而,结果很大程度上取决于你的起点。例如,如果你的参数初始猜测在这里,那么局部搜索可能只会让你停留在这里。这是一个局部最优解,但不是正确的解,它可能比 W* 差得多。

问题在于,这个特定的损失函数有很多局部最优值。有很多不同的地方,局部搜索算法可能会被困住。不幸的是,这种损失函数在机器学习中经常出现。总的来说,我们对此无能为力,但我们非常喜欢损失函数行为更好的情况,并且我们积极寻找它们。

那么,我们想要什么样的损失函数呢?我们想要像这样的损失函数:凸函数。很快我们会准确定义这意味着什么,但目前你可以把它想象成损失函数看起来像一个碗,我们只想到达碗的底部。这样只有一个局部最优值,它同时也是全局最优值。因此,像这样的函数相对容易最小化。

如何决定移动方向?📈

那么,我们具体如何做到这一点呢?假设我们处于某个特定的 w 值,我们如何知道该向哪个方向移动?例如,这张图中的 W 是一维的,我们如何知道是向左还是向右移动?

一个简单的方法是查看函数的斜率或导数。让我们看看这具体意味着什么。例如,假设我当前对 W 的猜测在那里。让我们看看那里的斜率。

这是斜率,它是正的。这意味着如果你增加 W,函数值会上升;如果你减少 W,函数值会下降。我们想做什么?我们想最小化函数,所以我们希望它下降,这意味着我们必须向左移动。

因此,斜率告诉我们必须向左移动。斜率为正,所以我们想朝相反的方向(向左)移动。

现在假设我们的参数估计在某个地方,那里的斜率看起来像这样。在这种情况下,斜率为负。所以,如果我们想减少函数值,我们必须向右移动。同样,斜率为负,所以我们增加 W,我们朝着与斜率相反的方向移动。

这是一个可以普遍使用的规则。调整当前参数 W 的方法是简单地沿着梯度的相反方向移动。

这就引出了梯度下降算法。假设我们想最小化函数 L(w)w 可能由 D 个参数组成,所以 w 可能是一个 D 维向量。

我们首先初始化 w 为任意值,例如,初始设置可能只是 0。然后我们不断调整 w。在时间 T,我们对 w 的当前设置(当前猜测)是 w_T。然后我们稍微调整它,得到 w_{T+1}

这个调整具体是什么?我们计算损失函数在 w_T 处的导数,然后我们想朝相反方向移动,所以我们取它的负值。这告诉了我们想要移动的方向,但我们也必须决定在这个方向上走多远。这就是步长 η_T(那个看起来像 n 的符号实际上是希腊字母 eta)。你可以把它看作一个小常数,我们稍后会详细讨论。它告诉我们在那个方向上走多远。

所以我们有一个当前的估计 w_T,我们稍微调整它得到 w_{T+1},我们以这种方式继续,直到最终收敛,那就是答案。

这是一个极其简单的算法,只有四行代码。它可以用来解决各种各样不同的问题。

为了使用这个算法,我们真正需要做的一件事就是计算这个导数,即损失函数的导数。让我们看看这具体需要什么。

计算导数:从单变量到多变量 🧮

我想我们都非常熟悉求单变量函数的导数。例如,如果 y = 3x²,那么 dy/dx 是什么?就是 6x。我们知道怎么做。

但是当你有一个多变量函数时会发生什么?例如,这里有一个三个变量的函数:W1W2W3。在这种情况下求导数意味着什么?现在你可以对三个不同的东西分别求导数。

以下是计算多变量函数导数的步骤:

首先,分别计算对每个变量的偏导数。对于函数 f(W1, W2, W3) = 3W1W2 + W3

  • W1 求导时,将 W2W3 视为常数,结果是 3W2
  • W2 求导时,将 W1W3 视为常数,结果是 3W1
  • W3 求导时,只有最后一项涉及 W3,结果是 1

然后,将这些单独的偏导数堆叠在一起,形成一个向量,这就是函数 f 的梯度(导数)。对于这个例子,梯度是向量 [3W2, 3W1, 1]。它是一个三维向量。

让我们看另一个例子。这次我们有一个 D 个变量的函数:f(w) = w · x = w1x1 + w2x2 + ... + wDxD

以下是计算其导数的步骤:

  • 对每个 w_j 求导:在求和中,只有一项 w_j x_j 涉及 w_j,所以导数是 x_j
  • 将这些导数堆叠成向量:梯度是 [x1, x2, ..., xD],也就是向量 x

再来看一个例子:函数 f(w) = ||w||² = w1² + w2² + ... + wD²

以下是计算其导数的步骤:

  • 对每个 w_j 求导:只有 w_j² 一项涉及 w_j,所以导数是 2w_j
  • 将这些导数堆叠成向量:梯度是 [2w1, 2w2, ..., 2wD],也就是 2w

一般来说,如果你有一个 D 个变量的函数,那么它的导数(梯度)就是一个 D 维向量。

回到梯度下降

现在让我们回到梯度下降算法。假设我们要最小化的函数是 D 个变量的函数。让我们看看这个更新规则:w_{t+1} = w_t - η_t * ∇L(w_t)

现在这个导数是什么?我们已经看到,那个导数是一个 D 维向量。所以这个更新规则是有意义的:wD 维的,我们减去一个 D 维向量,至少在维度对齐上是合理的。

为什么这个规则有效?为什么朝这个方向移动会减少损失?这是我们下次课要探讨的内容。

总结

本节课中,我们一起学习了机器学习中优化问题的基本思想。我们了解到,通过最小化损失函数可以学习模型参数,并重点介绍了梯度下降这一强大的通用优化算法。我们讨论了局部搜索可能遇到的局部最优问题,以及凸函数作为理想优化目标的特性。我们学习了如何计算单变量和多变量函数的导数(梯度),这是实现梯度下降的关键步骤。最后,我们给出了梯度下降算法的基本框架:w_{t+1} = w_t - η_t * ∇L(w_t)。下次课,我们将更详细地探讨这个算法的工作原理和细节。

026:无约束优化方法II 🧠

在本节课中,我们将继续探讨梯度下降法。我们将首先解释梯度下降法为何有效,并讨论如何设置学习率这一关键问题。接着,我们将以逻辑回归为例,具体演示如何推导出一个梯度下降算法。


上一节我们介绍了梯度下降法,它是一种用于最小化损失函数的通用算法。

本节中,我们来看看梯度下降法的工作原理。

梯度下降法回顾 🔄

梯度下降算法的目标是找到最小化某个损失函数 L 的参数向量 w。其基本流程是:从初始向量 w⁽⁰⁾ 开始,进入一个循环,不断调整 w 直到其收敛。

以下是其更新规则的核心公式:

w⁽ᵗ⁺¹⁾ = w⁽ᵗ⁾ - ηₜ ∇L(w⁽ᵗ⁾)

其中:

  • w⁽ᵗ⁾ 是第 t 次迭代的参数向量。
  • ∇L(w⁽ᵗ⁾) 是损失函数在 w⁽ᵗ⁾ 处的梯度(导数)。
  • ηₜ 是第 t 次迭代的学习率(步长)。

这个更新非常简单:计算当前点的梯度,然后沿着梯度的反方向移动一小步。

梯度下降为何有效? 🤔

梯度下降利用了损失函数的导数。如果导数存在,意味着损失函数在局部是近似线性的。

具体来说,如果我们观察损失函数 L 在点 w 附近一个极小的邻域(即点 w + u,其中 u 是一个微小的位移),那么函数可以近似为线性:

L(w + u) ≈ L(w) + u · ∇L(w)

这是函数在 w 点的线性近似,由梯度给出。

现在,考虑梯度下降的更新方向 u = -η ∇L(w)。将其代入上述线性近似:

L(w + u) ≈ L(w) + (-η ∇L(w)) · ∇L(w) = L(w) - η ||∇L(w)||²

由于 η 为正数,且梯度模长的平方 ||∇L(w)||² 总是非负的,因此 L(w + u) 近似小于 L(w)。这保证了沿着梯度反方向移动能够降低损失函数的值,这就是梯度下降法有效的原因。

如何设置学习率? ⚖️

学习率 η 的设置是一个关键问题。根据上面的数学原理,线性近似只在极小的邻域内成立,这似乎意味着应该将 η 设得非常小。然而,过小的 η 会导致每次迭代参数更新幅度微小,收敛速度极慢。

反之,如果 η 设置得过大,则可能“步子迈得太大”,越过最低点,甚至导致损失值上升,算法无法收敛。

以下是为学习率设置提供的两种常见策略:

  • 固定调度:将学习率设置为一个随时间递减的固定序列,例如 ηₜ = 1 / t。许多梯度下降的数学分析都基于此类假设。
  • 线搜索:这是一种更复杂的方法。在确定了梯度方向后,沿着该方向进行一维搜索(例如通过采样或二分查找),找到能使损失函数下降最多的最优步长 η

实例:推导逻辑回归的梯度下降 📝

现在,让我们将理论具体化,以逻辑回归为例,实际推导其梯度下降算法。

假设我们有一个数据集 {(x₁, y₁), ..., (xₙ, yₙ)}。逻辑回归的目标是找到一个由参数向量 w 定义的线性函数,以最小化以下损失函数(此处已通过添加常数特征将偏置项 b 并入 w):

L(w) = Σᵢ log(1 + exp(-yᵢ (w · xᵢ)))

为了使用梯度下降,我们需要计算损失函数 L 关于参数 w 的梯度。w 是一个 D 维向量,因此梯度也是一个 D 维向量。我们计算其对第 j 个分量 wⱼ 的偏导数。

经过求导和化简(过程详见课程推导),我们得到:

∂L(w) / ∂wⱼ = - Σᵢ [ 1 / (1 + exp(yᵢ (w · xᵢ))) ] * yᵢ * xᵢⱼ

观察方括号内的项 1 / (1 + exp(yᵢ (w · xᵢ))),它恰好等于在当前参数 w 下,给定 xᵢ 时预测标签为 -yᵢ(即错误标签)的概率,记作 P_w(-yᵢ | xᵢ)

因此,偏导数可以简洁地写为:

∂L(w) / ∂wⱼ = - Σᵢ [ P_w(-yᵢ | xᵢ) * yᵢ * xᵢⱼ ]

将所有这些偏导数组合起来,就得到了完整的梯度向量:

∇L(w) = - Σᵢ [ P_w(-yᵢ | xᵢ) * yᵢ * xᵢ ]

逻辑回归的梯度下降算法 🚀

基于计算出的梯度,我们可以写出逻辑回归的梯度下降算法:

  1. 初始化:将参数向量 w 初始化为零向量。
  2. 迭代更新:对于第 t 轮迭代,当前参数为 w⁽ᵗ⁾,按以下规则更新:
    w⁽ᵗ⁺¹⁾ = w⁽ᵗ⁾ + ηₜ Σᵢ [ P_{w⁽ᵗ⁾}(-yᵢ | xᵢ) * yᵢ * xᵢ ]

注意,这里更新是“加”而不是“减”,因为我们的梯度公式前面有一个负号。

这个更新公式具有清晰的直观解释:我们计算所有数据点的加权和,然后加到当前参数上。权重 P_{w⁽ᵗ⁾}(-yᵢ | xᵢ) 是模型在当前参数下对第 i 个样本预测出错误标签的概率。这意味着,算法会对当前预测错误率高的样本赋予更高的权重,从而在更新时更侧重于纠正这些错误。


本节课中我们一起学习了梯度下降法的原理、学习率设置的考量,并通过逻辑回归的例子完整地推导了一个具体的梯度下降算法。现在,梯度下降法已成为你工具箱中的一项重要工具。通过一些练习,你应该能够为你希望最小化的任何损失函数推导出相应的梯度下降算法。

027:无约束优化_III - 随机梯度下降法 🎯

在本节课中,我们将要学习梯度下降法的一个变体——随机梯度下降法。这种方法特别适用于处理大规模数据集,是机器学习工具箱中一个至关重要的组成部分。

上一节我们介绍了梯度下降法。本节中我们来看看一种更适用于大数据场景的优化算法。

梯度下降法的回顾

首先,我们来回顾一下逻辑回归的梯度下降算法。我们的目标是找到能最小化逻辑回归损失函数的参数向量 W

算法步骤如下:

  1. W 初始化为 0
  2. 进入循环,不断更新 W 直到收敛。
  3. 每次更新时,计算所有数据点的加权和,权重取决于当前模型在该数据点上的表现(预测概率越高,权重越大)。
  4. 将这个加权和乘以一个步长 η_t,然后加到当前的 W 上。

公式表示为:
W_{t+1} = W_t + η_t * Σ_{i=1}^n [y_i * x_i / (1 + exp(y_i * W_t^T x_i))]

这个算法的一个缺点是,每次更新都需要遍历整个数据集。如果数据点数量 n 很大(例如一百万),每次更新的计算开销会非常大,而更新量可能却很小,效率不高。

随机梯度下降法介绍

因此,在处理大量数据时,一个流行的替代算法是随机梯度下降法。

以下是随机梯度下降法的步骤:

  1. 同样,将 W 初始化为 0
  2. 进行更新,但每次更新只基于一个数据点,而非整个数据集。
  3. 算法从第一个数据点开始更新 W,然后是第二个、第三个,依次遍历所有数据点。
  4. 当遍历完整个数据集后,再从头开始循环。

其更新公式与梯度下降法类似,但移除了求和符号,仅针对单个数据点 (x_i, y_i)
W_{t+1} = W_t + η_t * [y_i * x_i / (1 + exp(y_i * W_t^T x_i))]

这种方法更新速度快,简单且实用。虽然这是针对逻辑回归的,但类似的思路可以推广到其他损失函数。

损失函数的通用形式

让我们更仔细地分析其工作原理。逻辑回归的损失函数可以表示为在整个训练集上的总和。

事实上,机器学习中遇到的大多数损失函数都具有以下通用形式:
给定训练集 {(x_1, y_1), ..., (x_n, y_n)},模型参数 W 的总体损失 L(W) 可以表示为每个数据点损失 l(W, x_i, y_i) 的和。

公式为:
L(W) = Σ_{i=1}^n l(W, x_i, y_i)

对于逻辑回归,点损失函数 l 是:
l(W, x, y) = ln(1 + exp(-y * W^T x))

最小二乘回归、岭回归、Lasso回归等也符合这种形式。我们的目标就是找到最小化总损失 L(W) 的参数 W

梯度下降与随机梯度下降的对比

如果使用梯度下降法,我们需要计算损失函数 L 的梯度。由于 L 是求和形式,其梯度也是每个点损失梯度的和。

因此,梯度下降的每次更新都需要对全部 n 个数据点进行求和计算,这在数据集很大时计算量可观。

随机梯度下降法则做了类似但更简单的事情:每次更新只基于一个数据点。它同样从 W=0 开始,然后遍历数据点。当处理到数据点 (x, y) 时,更新仅涉及该点的损失梯度 ∇ l(W, x, y)

这使得每次更新更简单、更快速,对于非常大的数据集来说也更为实用。

小批量随机梯度下降法

需要指出的是,梯度下降和随机梯度下降是光谱的两个极端。梯度下降每次更新使用全部数据;随机梯度下降每次更新只用一个数据点,因此更新方向可能噪声较大。

一个很好的折中方案是让每次更新依赖于一个合理大小的数据子集(例如100或1000个数据点),这被称为小批量随机梯度下降法

其操作流程如下:

  1. W_0 开始。
  2. 第一次更新基于第一批(如前1000个)数据点,执行基于这批数据的梯度下降更新。
  3. 然后移动到下一批1000个数据点进行更新,依此类推。
  4. 当处理完所有批次后,再从头开始循环。

这是一种非常合理且有效的折中方法。

总结

本节课中我们一起学习了两种极其强大且通用的优化技术:梯度下降法和随机梯度下降法。梯度下降法通过计算整个数据集的梯度来稳定更新参数,而随机梯度下降法则通过每次仅使用一个样本来实现高效的大规模数据训练。作为折中,小批量随机梯度下降结合了二者的优点,在实践中被广泛采用。这些算法堪称是有史以来最具影响力的算法之一。

028:凸性_I

在本节课中,我们将要学习一个在机器学习优化问题中至关重要的概念:凸性。我们将了解凸函数的定义,并学习如何通过计算二阶导数来检验一个函数是否为凸函数。

概述:为什么凸性很重要?

正如我们所见,机器学习问题常常归结为优化问题。我们定义一个合适的损失函数,然后通过最小化该函数来学习参数。然而,有些损失函数比其他函数表现更好,允许使用多种不同的求解方法。因此,能够识别这些特殊情况非常重要。在所有表现良好的函数中,凸函数是最优的一类。这个概念我们已经接触了一段时间,今天我们将正式聚焦于它。

凸函数的定义

上一节我们提到了凸函数的重要性,本节中我们来看看它的正式定义。凸性是一种几何性质,它使得函数更容易被优化。

以下是凸函数的定义:取函数图像上的任意两点A和B,连接这两点得到一条线段。如果函数在这两点之间的图像完全位于这条线段的下方,那么这个函数就是凸的。

更形式化地说,对于定义域内的任意两点 ab,以及任意参数 θ(满足 0 ≤ θ ≤ 1),如果以下不等式恒成立,则函数 f 是凸的:
f(θa + (1-θ)b) ≤ θf(a) + (1-θ)f(b)

这个定义确保了函数图像是“碗状”的,没有局部极小值陷阱,只有一个全局最小值。

凸函数的检验:单变量情况

理解了凸函数的定义后,我们来看看如何检验一个给定的函数是否为凸函数。对于只有一个变量的函数,检验方法非常简单。

以下是检验单变量函数凸性的方法:计算函数的二阶导数。如果二阶导数在定义域内始终大于或等于零,则该函数是凸的。

让我们看一个例子:函数 f(z) = z²

  • 一阶导数:df/dz = 2z
  • 二阶导数:d²f/dz² = 2

由于二阶导数恒等于2,大于0,因此函数 f(z) = z² 是凸的。

从单变量到多变量:海森矩阵

上一节我们介绍了单变量函数的凸性检验,本节中我们来看看如何处理更常见的多变量函数。机器学习中的损失函数通常是多个参数的函数。

当函数有多个变量时,情况会变得复杂一些。对于一个有 d 个变量的函数:

  • 函数值本身是一个标量(一个数字)。
  • 一阶导数(梯度)是一个 d向量
  • 二阶导数则是一个 d × d矩阵,称为海森矩阵

海森矩阵的 (j, k) 元素是函数对第 j 个变量和第 k 个变量的二阶偏导数:
H[j, k] = ∂²f / (∂z_j ∂z_k)

让我们通过一个具体例子来计算海森矩阵。考虑函数 f(z) = z₁² + z₂² + ... + z_d²,即向量 z 长度的平方。

以下是计算其海森矩阵的步骤:

  1. 首先计算一阶偏导数:对任意 z_j,有 ∂f/∂z_j = 2z_j
  2. 然后计算二阶偏导数:
    • 如果 j = k,则 ∂²f / (∂z_j ∂z_k) = 2
    • 如果 j ≠ k,则 ∂²f / (∂z_j ∂z_k) = 0

因此,这个函数的海森矩阵是一个对角矩阵,对角线元素全为2,非对角线元素全为0。我们可以将其简洁地写为 2I,其中 I 是单位矩阵。

多变量函数的凸性检验

现在我们已经知道了海森矩阵是什么,可以回到核心问题:如何判断一个多变量函数是否为凸函数?

检验多变量函数凸性的关键,在于其海森矩阵。一个函数是凸的,当且仅当它的海森矩阵在定义域内的每一点都是半正定的。

“半正定矩阵”听起来可能有些神秘,但它是机器学习和线性代数中一个极其重要的概念。由于我们已经学习了足够多的新知识,现在让我们稍作休息。在下一次课程中,我们将深入探讨半正定矩阵的含义及其重要性。

总结

本节课中我们一起学习了凸性的基础知识。我们首先了解了凸函数在机器学习优化中的重要性,因为它能保证损失函数具有良好的形状,易于找到全局最优解。然后,我们学习了凸函数的正式几何定义。接着,我们探讨了如何通过计算二阶导数来检验单变量函数的凸性。最后,我们将概念扩展到多变量函数,引入了海森矩阵的概念,并指出多变量函数凸性的最终检验标准是其海森矩阵是否为半正定矩阵。这是我们下一节课的重点。

029:半正定矩阵 📈

在本节课中,我们将要学习半正定矩阵。这是一种在机器学习中频繁出现的特殊方阵。我们将了解半正定矩阵的定义、核心性质,并学习如何判断一个矩阵是否属于这种类型。


从凸性到矩阵的“正性”

上一节我们介绍了凸函数的概念。对于一个单变量函数,如果其二阶导数始终为正,则该函数是凸的。

然而,对于一个具有 D 个变量的函数,其二阶导数是一个 D × D 的矩阵。那么,一个 D × D 的方阵是“正”的,这又意味着什么呢?


定义半正定矩阵

一个直观的想法是,如果矩阵中的所有元素都是正数,那么这个矩阵就是“正”的。但这是一种表面的定义,实际帮助不大。

一个更深刻、更有洞察力的定义是:如果一个方阵 M 所定义的二次型函数始终非负,那么这个矩阵就是半正定的。

让我们看看这意味着什么。对于一个矩阵 M,它定义的二次型函数是将一个向量 x 映射到 xᵀMx

例如,对于一个 2×2 矩阵 M = [[1, 1], [1, 1]],其二次型函数为:
f(x) = xᵀMx = x₁² + 2x₁x₂ + x₂² = (x₁ + x₂)²

由于这是一个平方项,无论 x 取何值,函数值 f(x) 总是大于或等于 0。因此,我们称矩阵 M半正定的。


正式定义与性质

更一般地,对于一个 D × D 的对称方阵 M,如果对于所有 D 维向量 x,都有:
xᵀMx ≥ 0
那么矩阵 M 就是半正定的。

以下是半正定矩阵的一些重要性质:

  • 对角矩阵:一个对角矩阵是半正定的,当且仅当其所有对角线元素都大于或等于 0。
  • 数乘:如果矩阵 M 是半正定的,且常数 c ≥ 0,那么矩阵 cM 也是半正定的。
  • 加法封闭性:如果矩阵 MN 都是半正定的,那么它们的和 M + N 也是半正定的。


如何判断一个矩阵是否半正定?

根据定义,我们需要检查 xᵀMx ≥ 0 是否对所有 x 都成立,这涉及无限种可能,难以操作。

幸运的是,有一个非常实用的判断准则:如果一个矩阵可以写成 M = UUᵀ 的形式(其中 U 是任意矩阵),那么 M 一定是半正定的。

让我们简要验证一下:

  1. M 是方阵:若 Ur × d 矩阵,则 M = UUᵀr × r 方阵。
  2. M 是对称的:Mᵀ = (UUᵀ)ᵀ = UUᵀ = M
  3. 对于任意向量 x,有 xᵀMx = xᵀ(UUᵀ)x = (Uᵀx)ᵀ(Uᵀx) = ||Uᵀx||² ≥ 0

这个准则非常强大。基于类似的推导,我们可以得出另一个重要结论:任何协方差矩阵都保证是半正定的。


总结与展望

本节课中,我们一起学习了半正定矩阵

  • 我们首先从凸函数二阶导数的概念引出问题:矩阵的“正性”应如何定义。
  • 我们学习了半正定矩阵的核心定义:一个对称矩阵 M 是半正定的,当且仅当由其定义的二次型 xᵀMx 对所有 x 都非负。
  • 我们探讨了半正定矩阵的几个基本性质,包括对角矩阵、数乘和加法的封闭性。
  • 最后,我们掌握了一个非常实用的判断方法:任何能写成 UUᵀ 形式的矩阵都是半正定的,这也保证了协方差矩阵的半正定性。

半正定矩阵在机器学习中无处不在。我们已经看到了它在判断函数凸性上的一个应用,在后续课程中,我们将会看到更多依赖半正定矩阵的重要场景。

030:凸性_II 🔍

在本节课中,我们将学习如何判断一个函数是否为凸函数。凸性在机器学习中至关重要,因为许多算法都涉及最小化损失函数,而函数的凸性决定了我们如何有效地进行优化。我们将回顾凸性的二阶导数检验方法,并通过一系列例子来加深理解。

概述 📋

我们已经了解了凸函数的定义。对于一个具有D个变量的函数,如果其在整个定义域上的二阶导数矩阵(即Hessian矩阵)是半正定的,那么该函数就是凸的。本节课,我们将具体学习如何应用这个检验方法。

二阶导数检验法回顾 📐

对于一个D维变量的函数,其凸性可以通过其Hessian矩阵来判断。Hessian矩阵是一个D×D的矩阵。如果该矩阵在所有点都是半正定的,则函数是凸的。

那么,什么是半正定矩阵呢?一个矩阵H是半正定的,如果对于任意向量x,其定义的二次型总是非负的,即满足:
xᵀHx ≥ 0

此外,还有一个更实用的等价定义:一个矩阵是半正定的,当且仅当它可以写成U Uᵀ的形式,其中U是任意实矩阵。在后续的示例中,我们将同时运用这两种定义。

示例分析 📝

以下是几个具体的函数凸性判断示例。

示例一:平方范数函数

首先,我们来看一个简单的例子:函数 f(x) = ||x||²。这个函数是凸的吗?

第一步是计算其Hessian矩阵。我们上次已经计算过,其Hessian矩阵是2I,即两倍的单位矩阵。

现在判断这个矩阵是否半正定。对于任意向量z,计算二次型:
zᵀ (2I) z = 2 zᵀ z = 2 ||z||² ≥ 0
由于结果总是非负的,因此矩阵2I是半正定的。另一种看法是,2I是一个对角元素全为正数的对角矩阵,这直接表明它是半正定的。

因此,函数 f(x) = ||x||² 是凸函数。它实际上是经典凸函数 y = x² 在多维空间中的推广。

示例二:点积平方函数

接下来,我们看一个稍复杂的例子。设u是D维空间中的一个固定向量,定义函数 f(z) = (u · z)²,其中z是变量。这个函数是凸的吗?

我们首先计算其一阶导数。对zⱼ求导:
∂f/∂zⱼ = 2 (u · z) uⱼ

接着计算二阶导数,对zₖ求导:
∂²f/∂zₖ∂zⱼ = 2 uⱼ uₖ

因此,Hessian矩阵是一个D×D矩阵,其(j, k)元素为 2 uⱼ uₖ。这可以简洁地写成:
Hessian = 2 u uᵀ

根据我们之前的等价定义,矩阵 u uᵀ 本身就具有 U Uᵀ 的形式,因此是半正定的。乘以常数2后,它仍然是半正定的。

所以,函数 f(z) = (u · z)² 也是凸函数。

示例三:最小二乘损失函数

现在,我们来分析一个在机器学习中至关重要的函数:最小二乘回归的损失函数。假设我们有n个数据点 (xᵢ, yᵢ),其中xᵢ是D维向量,yᵢ是实数标量。我们希望找到一个权重向量w,使得线性预测 w · xᵢ 与真实值yᵢ的误差平方和最小。损失函数定义为:
L(w) = Σᵢ (yᵢ - w · xᵢ)²

我们需要判断L(w)是否为凸函数。首先计算其一阶导数。对wⱼ求导:
∂L/∂wⱼ = Σᵢ [ -2 (yᵢ - w · xᵢ) xᵢⱼ ]

然后计算二阶导数,对wₖ求导:
∂²L/∂wₖ∂wⱼ = Σᵢ [ 2 xᵢⱼ xᵢₖ ]

因此,整个Hessian矩阵可以表示为:
Hessian = 2 Σᵢ [ xᵢ xᵢᵀ ]

这里,每个 xᵢ xᵢᵀ 都是一个D×D的矩阵,并且具有 U Uᵀ 的形式,所以每个都是半正定的。半正定矩阵的和仍然是半正定的,乘以正常数2也保持半正定性。

因此,最小二乘损失函数 L(w) 是一个凸函数。这也是我们如此青睐最小二乘法的重要原因之一——其凸性保证了优化过程能找到全局最优解。

总结 🎯

本节课我们一起学习了如何利用二阶导数检验函数的凸性。我们回顾了半正定矩阵的定义和性质,并通过三个由浅入深的例子进行了实践:

  1. 平方范数函数 f(x) = ||x||²
  2. 点积平方函数 f(z) = (u · z)²
  3. 最小二乘回归的损失函数 L(w) = Σ (yᵢ - w·xᵢ)²

我们验证了这些函数都是凸的。掌握凸性的判断方法,为我们接下来学习高效的优化算法和更复杂的分类模型奠定了坚实的基础。

031:一个简单的线性分类器 🧠

在本节课中,我们将学习线性分类器的基本概念,并推导出一种名为感知机(Perceptron)的经典算法。我们将从回归和概率估计转向分类问题,并采用以优化为核心的视角来构建解决方案。


线性决策边界 📏

上一节我们讨论了回归和条件概率估计。本节中,我们来看看如何将学习任务构建为一个优化问题,并应用于分类。

一个线性分类器通过一个线性边界(决策边界)来分隔数据。在二维空间中,这个边界是一条直线。其方程可以表示为:

公式: w · x + b = 0

其中:

  • w 是权重向量。
  • x 是特征向量。
  • b 是偏置项。

对于一个新数据点 x,我们通过计算 w · x + b 的值并取其符号(正或负)来进行预测。

预测规则:

if w · x + b > 0:
    prediction = +1
else:
    prediction = -1

分类的正确性条件 ✅

对于一个带有真实标签 y(取值为 +1 或 -1)的数据点 (x, y),我们的分类器何时是正确的?

以下是判断条件:

  • y = +1w · x + b > 0 时,分类正确。
  • y = -1w · x + b < 0 时,分类正确。

我们可以将这两个条件合并为一个简洁的表达式:

公式: y * (w · x + b) > 0

如果该乘积大于 0,说明预测标签与真实标签符号相同,分类正确。


定义分类的损失函数 📉

为了训练分类器,我们需要定义一个损失函数来衡量预测的错误程度。对于分类问题,有多种损失函数可供选择。

我们这里采用一种直观的损失函数:

  • 如果分类正确(即 y * (w · x + b) > 0),则损失为 0。
  • 如果分类错误(即 y * (w · x + b) < 0),则损失为 -y * (w · x + b)。这个值越大,说明我们错得越离谱。

这个损失函数是凸函数,这有利于我们使用梯度下降等优化方法找到最小值。


随机梯度下降与感知机算法 ⚙️

现在,我们希望通过最小化上述损失函数来找到最优的 wb。为了使过程简单,我们使用随机梯度下降(SGD)方法。

以下是更新规则:

  1. 初始化 w = 0, b = 0
  2. 遍历数据点 (x, y)
  3. 如果 y * (w · x + b) > 0(分类正确),则参数不变。
  4. 如果 y * (w · x + b) <= 0(分类错误),则按以下规则更新参数:
    • w = w + y * x
    • b = b + y

这个极其简单的更新规则,就是著名的感知机算法


感知机算法的特性与保证 🛡️

感知机算法虽然简单,但有一个重要的理论保证:如果训练数据是线性可分的(即存在一个超平面能完美分开两类数据),那么感知机算法保证能在有限步内收敛,并找到一个完美的分类器。

在实际运行中,算法对数据点的遍历顺序可能敏感,但最终总能找到一个解。每次参数更新(即发生分类错误时)都会使分类器向正确方向调整一步。


总结 🎯

本节课中我们一起学习了:

  1. 线性分类器的基本形式:w · x + b = 0
  2. 分类正确的条件:y * (w · x + b) > 0
  3. 为分类问题设计了一个简单的凸损失函数
  4. 通过对该损失函数应用随机梯度下降,推导出了简洁优雅的感知机算法
  5. 了解了感知机算法的核心特性:对于线性可分数据,它能保证找到完美解。

感知机算法是机器学习中的一颗明珠,它用寥寥数行代码就实现了一个强大的学习原理。下一节,我们将探讨如何在线性可分的数据中找到那个“最理想”或“最安全”的决策边界。

032:支持向量机 I 🧠

在本节课中,我们将学习一种性能卓越的线性分类器——支持向量机。我们将从线性分类器的“间隔”概念开始,然后探讨如何找到具有最大可能间隔的线性分类器。这最终会引出一个凸优化问题,其解具有一个独特的性质:它仅依赖于少数几个被称为“支持向量”的训练点。

线性分类器的间隔

上一节我们介绍了感知机算法及其收敛定理。该定理指出,如果数据集是线性可分的,感知机算法保证能找到一个完美分隔训练集的线性分类器。然而,它可能返回众多可行解中的任意一个。

那么,如果我们想要那个最“居中”、周围“缓冲”区域最大的分类器呢?例如下图中的这条线。我们该如何形式化地定义和寻找它?

问题形式化

我们的设定如下:我们有训练数据,包含 N 个点 x1xN(特征向量),以及对应的二元标签 y(取值为 +1 或 -1)。我们希望找到一个线性分类器,即参数 wb,使其能完美分类数据。

完美分类的条件可以简洁地写为:对于所有训练点 i,满足:
y_i * (w·x_i + b) > 0

为了讨论间隔,我们将这个条件改写为一个更强的形式:
y_i * (w·x_i + b) >= 1

为什么可以这样做?如果存在 wb 使得原条件成立(所有值 > 0),那么通过按比例放大 wb,总能使所有值 >= 1。因此,这个新条件与原问题的可行性是等价的。

间隔的几何意义

改写后的条件带来了清晰的几何解释。决策边界是 w·x + b = 0。而 w·x + b = 1w·x + b = -1 则是两条平行的超平面。

我们的条件要求:所有正类点(y=+1)必须位于右侧超平面(w·x + b = 1)的右侧;所有负类点(y=-1)必须位于左侧超平面(w·x + b = -1)的左侧。这样,两类点之间就形成了一个“缓冲区”,没有任何点落在这个区域内。

这个缓冲区的宽度就是“间隔”(margin),记作 γ。间隔有一个简单的计算公式:
γ = 1 / ||w||

因此,为了最大化间隔,我们需要最小化权重向量 w 的范数。

优化问题

综合以上,支持向量机的核心优化问题可以表述为:

最小化(1/2) * ||w||^2
约束条件:对于所有 i = 1, ..., Ny_i * (w·x_i + b) >= 1

这是一个凸优化问题,因为目标函数(w 的范数平方)是凸函数,而所有约束条件都是关于 wb 的线性不等式。凸优化问题通常可以高效求解。

支持向量与对偶解

凸优化理论中的对偶性告诉我们,最优解 w* 具有一种特殊形式:
w* = Σ_{i=1}^{N} α_i * y_i * x_i

其中,α_i 是大于等于零的系数。一个关键的性质是:大多数 α_i 的值会是零。只有那些恰好位于间隔边界(即满足 y_i*(w·x_i+b)=1)的训练点,其对应的 α_i 才大于零。这些点被称为支持向量

因此,最终的分类器仅由这些支持向量决定。即使数据集有上百万个点,如果只有几百个支持向量,那么模型也只需要依赖这几百个点。

示例:鸢尾花数据集

让我们看一个支持向量机在实际数据集上工作的例子。我们使用著名的鸢尾花数据集,它包含三种鸢尾花的测量数据。为了进行二元分类可视化,我们只取其中两类(Setosa 和 Versicolor),并只使用两个特征(花瓣宽度和萼片宽度)。

数据集明显是线性可分的。感知机算法能找到某个分隔超平面,但支持向量机会寻找具有最大间隔的那个。

上图展示了支持向量机找到的解。它返回了一个非常“居中”的线性分类器。这个分类器仅依赖于三个训练点——即图中的三个支持向量。间隔 γ 是图中所示的距离,这是在该数据上可能达到的最大间隔。

总结

本节课中,我们一起学习了支持向量机的基本原理。我们专注于数据线性可分的情况,通过最大化分类间隔来定义优化问题,并了解到其解可以表示为支持向量的线性组合,这使得模型具有稀疏性和鲁棒性。

然而在实践中,数据往往不是线性可分的。下一节课,我们将探讨如何将支持向量机的方法扩展到更一般的、任意数据的情况。

033:支持向量机 II 🧠

在本节课中,我们将要学习支持向量机(SVM)的一个重要扩展——软间隔支持向量机。上一节我们介绍了硬间隔SVM,它要求数据必须是线性可分的。本节中我们来看看当数据无法被完美线性分割时,如何通过引入松弛变量来构建一个更强大、更实用的分类器。

回顾:硬间隔支持向量机

上一节我们介绍了支持向量机。给定一个训练集,它通过求解一个凸优化程序来寻找具有最宽间隔的线性分类器。

它效果很好,但仅适用于线性可分的数据,即确实存在一个线性分类器能完美地将正类(+1)和负类(-1)分开的数据。

在实践中,情况往往并非如此,因此我们今天要做的是研究支持向量机的另一个版本,称为软间隔支持向量机。它可以处理任何类型的数据。

我们将看到,通过向凸优化程序中引入新的松弛变量,可以轻松处理不可分数据的情况。然后,我们将看看它在实践中如何工作,以及会出现的一些问题。

软间隔SVM的数学形式

以下是上一节的情况。我们有一个数据集,一个由点 x₁ 到 x_N 组成的训练数据集,每个点都有一个标签 y₁ 到 y_N,这些标签是 +1 或 -1。这是一个二元分类任务。

支持向量机通过求解一个凸优化程序来寻找线性分类器,即下面这个程序。它寻找一个由向量 w 和偏移量 b 给出的线性分类器。

这个凸优化程序包含 n 个线性约束,即这里的这些约束,每个数据点一个。约束的含义是该数据点必须被正确分类。

在满足这些约束的前提下,程序还希望找到具有最宽间隔的分类器。正如我们所见,这等同于最小化 w 的长度,或者等价地最小化 w 的平方长度。

这是一个凸优化程序,意味着它可以被高效求解,并且有现成的软件包可以为我们完成,我们无需担心其背后的算法。此外,最终得到的解 w 具有非常优美的形式:它是数据点 x 的线性组合。更重要的是,这个线性组合只使用了部分数据点——那些恰好位于间隔边界上的点。这些点就是支持向量。

这是一个非常优美的图景。这一切都很好,但这仅适用于数据线性可分的情况。问题是,在不可分的情况下会发生什么?例如,假设这里有一个蓝点。

如果我们有这样一个点,那么就不存在能够完美分类训练数据的线性分类器,因此我们将无法满足所有这些约束。我们必须放弃其中一些约束。我们该怎么做呢?

事实证明,一个非常简单的方法是引入新的松弛变量。让我解释一下这意味着什么。

以前,对于每个数据点 i,我们坚持要求 y_i * (w·x_i + b) ≥ 1。这是一个硬约束。

现在,我们通常无法满足所有这些约束。所以我们要做的是,允许违反其中一些约束,并引入一个新的松弛变量 ξ_i(希腊字母 xi)。我们为每个数据点引入一个这样的变量,它们记录了违反约束的程度。

对于数据点 i,我们理想情况下希望 y_i * (w·x_i + b) ≥ 1。但我们将允许它被违反,ξ_i 的大小告诉我们该特定点的违反程度。

现在,我们希望最小化的目标与之前相同,即 ||w||²,因为我们希望间隔宽。但同时,我们要确保没有太多约束被违反,因此我们还要加上所有 ξ_i 的总和,即约束被违反的总体程度。

为了更深入地理解这些松弛变量,让我们看看这张图。这里我们有一个决策边界 w·x + b = 0。这一侧的间隔边界是 w·x + b = 1,另一侧的平行超平面是 w·x + b = -1。在这种情况下,间隔就是这个距离。正如我们之前推导的,这个距离就是 1 / ||w||。这些都与上一节相同。

但现在不同的是,点并不都完全在我们希望它们所在的位置。例如,看这个点。它在边界的正确一侧(红色一侧),但我们希望它在间隔边界的右侧。它没有,它差了一点。对于那个特定的点,我们理想情况下希望 y_i * (w·x_i + b) ≥ 1。但它没有,实际上等于像 0.25 这样的值。因此,我们用松弛变量来弥补这个差值。该特定点的松弛变量因此是 0.75,即 y * (w·x + b) 的实际值与我们希望它达到的值之间的差值。

现在看这个点。这个点实际上在边界的错误一侧(红色一侧)。它离我们希望的位置很远。我们希望它完全在那边。那么它的松弛变量是多少?为了到达边界,需要 1 的松弛,再加上大约 0.5 的额外松弛,所以该点的松弛变量大约是 1.5。

在这张图中,只有这两个数据点使用了任何松弛,其他点都很好,它们就在我们希望的位置。因此,我们使用的松弛总量,即从 i=1 到 n 的 ξ_i 之和,在这张图中就是 0.75 + 1.5 = 2.25。

软间隔SVM的优化目标

因此,软间隔支持向量机的完整凸优化问题如下:

最小化: (1/2) ||w||² + C * Σ_{i=1}^{n} ξ_i

约束条件:

  1. y_i (w·x_i + b) ≥ 1 - ξ_i, 对于所有 i = 1, ..., n
  2. ξ_i ≥ 0, 对于所有 i = 1, ..., n

这里,C 是一个大于 0 的正则化参数,它控制着我们对最大化间隔(最小化 ||w||²)和最小化分类错误(最小化 Σ ξ_i)这两个目标的重视程度之间的权衡。

参数 C 的作用

为了理解参数 C 的影响,让我们看看两个极端情况:当 C 尽可能小(趋近于 0)时,以及当 C 非常大(趋近于无穷大)时,看看每种情况下会发生什么。

  • 当 C = 0 时:公式中的第二项基本上消失了。这意味着松弛是免费的,我们可以使用任意多的松弛,无需付出代价。我们可以随意违反任意多的约束,可以随意增大 ξ_i。我们唯一想做的就是最小化 w 的长度,所以我们会将 w 设为零。
  • 当 C → ∞ 时:这意味着松弛是无限昂贵的。如果我们使用哪怕一点点松弛,其代价都是无穷大。因此我们将不使用任何松弛,这就回到了之前的硬间隔 SVM。我们必须完美分类每一个点,不允许任何松弛。

当然,在实践中我们会选择介于这两个极端之间的某个数值。让我们通过一个小例子看看这是如何运作的。

实践中的效果与参数选择

以下是使用软间隔SVM处理一个线性可分数据集(鸢尾花数据集的一部分)时,不同 C 值的效果:

  • C 很大(如 1000):松弛非常昂贵,本质上等同于硬间隔SVM。所有约束都被完美满足,只有少数几个点成为支持向量(位于间隔边界上的点)。间隔相对较窄。
  • 逐渐减小 C(如 3):松弛变得便宜一些。算法开始允许违反少数几个点的约束(使用松弛),以换取获得更宽的间隔。支持向量的数量会增加,包括那些被违反约束的点。
  • C 很小(如 0.01):松弛非常便宜。算法倾向于使用大量松弛来违反许多约束,从而获得一个非常宽的间隔。许多点都成为支持向量。

这个例子说明,即使数据是线性可分的,允许少量违反约束(使用软间隔)也可能通过获得更宽的间隔来提升模型的泛化能力。

在情感分析数据集上的应用

现在让我们回顾情感分析数据集。这个数据集包含从产品、电影或餐厅评论中提取的句子,每个句子被标记为正面或负面。我们可以使用词袋表示法将每个句子转换为向量。

为了在这样的数据上使用软间隔支持向量机,我们必须决定如何设置参数 C。让我们看看不同 C 设置的效果。

随着 C 增大(松弛更贵):

  • 训练误差下降(因为违反的约束更少)。
  • 支持向量的数量减少(因为违反约束的点更少)。
  • 测试误差先下降后上升,存在一个“最佳点”。

我们如何选择 C 的值?我们不能偷看测试集。标准的做法是使用交叉验证。例如,我们可以尝试一系列不同的 C 值(如在对数尺度上),对每个值进行 k 折交叉验证(例如 5 折),计算平均验证误差,然后选择验证误差最小的那个 C 值。这样选出的 C 通常能在未知数据上取得良好的性能。

总结

本节课中我们一起学习了软间隔支持向量机,这是实践中通常使用的 SVM 形式。它是一个极其强大的线性分类器。

其核心思想是通过引入松弛变量 ξ_i 来允许某些训练样本被误分类或落入间隔之内,从而将原始的硬间隔优化问题转化为一个更灵活的软间隔优化问题。关键的正则化参数 C 控制着最大化间隔和最小化分类错误之间的权衡。

软间隔SVM的美妙之处在于,你实际上可以进一步使用它来获得二次、多项式或更复杂的决策边界。在接下来的课程中,我们将看到如何通过“核技巧”来实现这一点。

034:对偶性

概述

在本节课中,我们将学习线性分类算法中的“对偶性”概念。我们将看到感知器算法和支持向量机(SVM)都可以用一种新的、被称为“对偶形式”的方式来表达。这种视角不仅提供了对算法的新理解,也是我们后续将线性方法扩展到非线性边界(如二次或多项式边界)的关键第一步。


感知器算法的两种视角

上一节我们回顾了感知器和SVM等强大的线性分类方法。本节中,我们来看看如何从“对偶”的角度重新审视这些算法。

感知器算法的原始形式非常直观。其设置如下:我们有训练点 (X_i, Y_i),其中 Xd 维空间中的向量,Y 是标签 +1-1。我们学习一个由 WB 给出的线性分类器。

以下是算法的原始(原始形式)步骤:

  1. 初始化 W = 0B = 0
  2. 循环遍历数据集。
  3. 每当遇到一个被当前 (W, B) 错误分类的点 (X, Y) 时,执行更新:
    • W = W + Y * X
    • B = B + Y

这意味着最终得到的 W 具有一个简单的形式。最终答案 W 可以表示为:

公式: W = Σ_i (α_i * Y_i * X_i)

其中,α_i 是我们在第 i 个数据点上执行更新的次数。这是一个非负整数。如果我们从未在该点更新,则 α_i = 0;更新一次则为 1,以此类推。

因此,我们有两种表示答案的方式:

  • 原始形式:向量 W(维度为 d)。
  • 对偶形式:计数向量 α(维度为 n,即数据点数量)。

我们可以进一步重写整个算法,使其完全用 α 来表示。

以下是感知器算法的对偶形式步骤:

  1. 初始化 α = 0(一个 n 维向量),B = 0
  2. 循环遍历数据点。
  3. 每当遇到一个被错误分类的点 (X_i, Y_i) 时,执行更新:
    • α_i = α_i + 1 (增加该点的计数)
    • B = B + Y_i

在任何时刻,对应的 W 都可以通过公式 W = Σ_i (α_i * Y_i * X_i) 计算得到。这个对偶形式的算法在每一步只增加一个计数,在某些方面比原始形式更简单。这两种形式描述的是完全相同的算法和解决方案。


支持向量机(SVM)的对偶性

现在让我们将对偶性的概念应用到支持向量机上。我们有两种SVM:硬间隔SVM(要求数据严格线性可分)和更常用的软间隔SVM。

硬间隔SVM

对于硬间隔SVM,我们求解一个由 WB 定义的线性分类器,这是一个凸优化问题(原始问题)。其目标是最大化间隔,等价于最小化 W 的范数,并满足每个数据点都被正确分类的约束。

每个优化问题都有一个对应的对偶优化问题。原始问题是最小化问题,其对偶问题是最大化问题,并且它们具有相同的最优值。

硬间隔SVM的对偶问题如下:它不再求解 WB,而是求解变量 α_1α_n(与感知器中的 α 类似)。求解出 α 后,我们想要的解 W 同样具有与感知器相同的形式:W = Σ_i (α_i * Y_i * X_i)

原始问题和对偶问题都是可以高效求解的“好问题”。对偶性理论(特别是互补松弛性)揭示了原始解和对偶解之间的关系。它告诉我们:只有那些恰好位于间隔边界上的点,其对应的 α_i 才非零。这正是“支持向量”概念的来源。对偶性告诉我们,解 W 仅依赖于这些支持向量。

软间隔SVM

软间隔SVM的原始问题类似于硬间隔问题,但引入了松弛变量 ξ_i,允许某些约束被违反,以处理非线性可分数据。

同样,我们可以写出它的对偶问题。这个对偶问题看起来与硬间隔SVM的对偶问题非常相似。解同样给出系数 α,而 W 由这些 α 与数据点的线性组合给出。

应用互补松弛性分析,我们会发现在软间隔SVM中,实际上有两种支持向量:

  1. 恰好位于间隔边界上的点。
  2. 使用了松弛变量的点(即被错误分类或落在间隔内的点)。

这再次体现了对偶性这一优美理论所带来的深刻见解。


总结

本节课我们一起学习了机器学习中的“对偶性”概念。我们看到了感知器算法、硬间隔SVM和软间隔SVM都可以用原始形式和对偶形式两种方式来表达。对偶形式将解表示为数据点的线性组合,其系数 α 揭示了算法内部的工作原理,并清晰地定义了“支持向量”。对偶性是优化理论的核心,在机器学习中会反复出现。对我们而言,理解对偶性为我们下一步将感知器和SVM从线性边界扩展到多项式乃至更一般的非线性边界奠定了必要的基础。

035:多分类线性预测 📈

在本节课中,我们将要学习如何将线性分类方法从二分类问题扩展到多分类问题。我们将看到,通过一个简单而统一的框架,可以轻松地扩展逻辑回归、感知机算法和支持向量机,使其能够处理多个类别。


从二分类到多分类

上一节我们介绍了多种线性分类方法,但它们都只适用于标签为+1或-1的二分类情况。本节中我们来看看,当存在更多类别时,我们该如何处理。

一些方法天生就支持多分类,例如最近邻算法和生成式模型。最近邻算法能自动适应任意数量的类别。生成式模型则为每个类别单独拟合一个高斯分布或其他分布。

然而,线性分类器似乎有些棘手,因为一条直线只有两侧。为了理解核心思想,让我们回顾高斯生成模型。在那里,我们为每个类别拟合一个高斯分布,每个类别都有自己的二次函数。当新数据点到来时,每个类别评估其二次函数,得分最高的类别获胜。

我们可以将类似的思想应用于线性分类:让每个类别拥有自己的线性函数。


多分类线性模型框架

假设我们的数据点 x 位于 D 维空间,即 x ∈ ℝᴰ。标签有 K 个可能的值,例如 1, 2, ..., K。

我们将为每个类别分配一个线性函数:

  • 类别 1:w₁·x + b₁
  • 类别 2:w₂·x + b₂
  • ...
  • 类别 K:wᴋ·x + bᴋ

其中,每个 wⱼ 是一个 D 维向量,每个 bⱼ 是一个偏移量(标量)。

预测规则:当新数据点 x 到来时,每个类别计算其线性函数的值。我们预测具有最大值的那个类别作为标签。

公式表示为:
预测标签 = argmaxⱼ ( wⱼ·x + bⱼ )


多分类逻辑回归

对于二分类逻辑回归,我们只有一个线性函数 w·x + b,并通过 sigmoid 函数计算概率。

现在扩展到 K 个类别。我们为每个标签 j 设置线性函数 wⱼ·x + bⱼ。给定点 x,其标签为 j 的概率与 exp(wⱼ·x + bⱼ) 成正比。

为了使所有类别的概率之和为 1,我们需要进行归一化。因此,多分类逻辑回归(也称为 Softmax 回归)的概率公式为:

P(y = j | x) = exp(wⱼ·x + bⱼ) / Σₖ₌₁ᴷ [ exp(wₖ·x + bₖ) ]

学习过程:给定训练集 { (xᵢ, yᵢ) },我们通过最大化训练数据的似然(或等价地,最小化负对数似然)来学习所有参数 {wⱼ, bⱼ}。这是一个凸优化问题,可以使用标准软件包求解。


多分类感知机算法

感知机算法代码简洁。我们可以将其修改以处理多分类,修改后的算法同样简短。

以下是算法步骤:

  1. 初始化:将所有 K 个线性函数的参数 wⱼ 和 bⱼ 设置为 0。
  2. 迭代:遍历训练数据。
  3. 预测:对于每个数据点 (x, y),根据当前参数计算预测标签 ŷ = argmaxⱼ ( wⱼ·x + bⱼ )。
  4. 更新:如果预测错误(ŷ ≠ y),则更新两个线性函数的参数:
    • 对于正确标签 yw_yw_y + x, b_y ← b_y + 1
    • 对于预测标签 ŷw_ŷw_ŷ - x, b_ŷ ← b_ŷ - 1
  5. 重复直到所有数据点被正确分类或达到迭代次数上限。

该算法找到的是一个能完美分类训练数据的线性分界,但这个边界由多个线性片段组成,且不一定是最优的(例如,没有最大化间隔)。


多分类支持向量机

我们也可以将支持向量机扩展到多分类。目标是找到一个能正确分类所有数据点的线性函数集,同时最大化“间隔”并允许一些误差(软间隔)。

以下是多分类软间隔SVM的凸优化问题

最小化: (1/2) Σⱼ₌₁ᴷ ||wⱼ||² + C Σᵢ₌₁ᴺ ξᵢ

约束条件:对于每一个训练样本 (xᵢ, yᵢ) 和每一个错误标签 r (r ≠ yᵢ):
w_{yᵢ}·xᵢ + b_{yᵢ} ≥ w_r·xᵢ + b_r + 1 - ξᵢ
且 ξᵢ ≥ 0

变量说明

  • wⱼ, bⱼ: 每个类别的线性函数参数。
  • ξᵢ: 松弛变量,允许第 i 个样本违反间隔约束。
  • C: 正则化参数,控制对误分类的惩罚力度。

规模分析

  • 变量总数: K×D (所有 w) + K (所有 b) + N (所有 ξ) = KD + K + N
  • 约束总数: 每个样本有 (K-1) 个约束(正确类别需击败所有其他类别),总共 N × (K-1) 个约束。

这个优化问题可以通过现成的凸优化求解器来解决。


总结

本节课中我们一起学习了如何将线性分类方法扩展到多分类场景。核心思想是为每个类别分配一个独立的线性函数,并通过比较这些函数的值来进行预测。

我们具体探讨了三种方法的扩展:

  1. 多分类逻辑回归:使用 Softmax 函数将线性输出转化为概率分布。
  2. 多分类感知机:通过简单的加/减更新规则,在误分类时调整正确和错误类别的权重。
  3. 多分类支持向量机:构建一个凸优化问题,在最大化间隔的同时,要求正确类别的分数高于其他类别一个单位(减去松弛变量)。

这个统一的框架强大而简洁,使我们能轻松应对现实世界中常见的多类别分类问题。

036:基扩展 🔄

在本节课中,我们将开始学习核方法。这些方法能实现一个非常神奇的功能:它们允许我们使用线性分类器(如感知机或支持向量机)来生成二次、多项式甚至更复杂的决策边界。实现这一目标涉及几个核心概念,我们将逐一详细讲解。今天,我们将首先了解基扩展的工作原理。

线性可分性的局限

在之前对分类问题的研究中,我们已经了解到,如果数据是线性可分的,那么问题就很简单。例如,我们可以使用感知机算法来学习分类器。

然而,线性可分性常常不成立,主要有两种情况:

  1. 数据近似线性可分,但存在少数位于错误一侧的点。
  2. 数据完全不是线性可分的,决策边界可能是抛物线等二次函数。

对于第一种情况,我们可以使用软间隔支持向量机等方法轻松处理。本节课,我们将重点探讨如何处理第二种情况,即学习二次决策边界。

基扩展的核心思想

假设我们有一个二维数据集,特征为 x1x2。决策边界是一个抛物线,其方程可能类似于:

x1 = x2^2 + 5

这是一个关于 x1x2 的二次边界。

基扩展的核心思想是扩展输入的表示。具体做法如下:
原始数据是二维的,包含特征 x1x2。我们将使用一个映射函数 φ(x) 来扩展表示,使其包含五个特征:

φ(x) = [x1, x2, x1^2, x2^2, x1*x2]

这样,原始位于 R^2 空间的数据点,就被映射到了 R^5 的高维空间。

关键在于,原本在二维空间中的二次决策边界 x1 - x2^2 - 5 = 0,在高维空间 φ(x) 中变成了一个线性边界。我们可以将其表示为:

w · φ(x) + b = 0

其中,权重向量 w = [1, 0, 0, -1, 0],偏置 b = -5

公式解释:通过基扩展,我们将非线性问题(二次边界)转换为了高维空间中的线性问题。

扩展到更高维度

如果原始数据是 d 维的,为了学习一个二次决策边界,我们需要创建一个扩展表示 φ(x),它包含:

  • 所有原始特征:x1, x2, ..., xd
  • 所有特征的平方项:x1^2, x2^2, ..., xd^2
  • 所有特征的两两组合项(交叉项):x1*x2, x1*x3, ..., x_{d-1}*xd

这个扩展表示的维度是:

维度 = d + d + C(d, 2) = 2d + d(d-1)/2

这大致是 O(d^2) 的复杂度。在这个高维空间中,任何关于原始特征的二次边界,都变成了关于 φ(x) 的线性边界。

实现:感知机算法的基扩展

要让感知机算法学习一个二次边界,方法非常简单:我们只需将原始感知机算法中所有出现输入向量 x 的地方,替换为扩展后的向量 φ(x) 即可。

代码描述

# 原始感知机更新规则
w = w + y_i * x_i

# 基扩展后的感知机更新规则
w = w + y_i * φ(x_i)

其中,φ(x_i) 是如上定义的扩展特征向量。

基扩展感知机示例

让我们通过两个例子来看基扩展感知机的效果:

  1. 非线性可分数据集:下图展示了一个包含两类(黑色三角形和红色圆形)的数据集,它显然不是线性可分的。

    运行基扩展感知机算法后,它学习到了一个完美的二次决策边界(看起来像一段抛物线)。虽然在二维空间中这个边界是弯曲的,但在对应的五维嵌入空间中,它实际上是一个线性的超平面。

  2. 另一个复杂数据集:另一个明显非线性可分的数据集。

    算法学习到了一个椭圆形的决策边界。同样,这个椭圆在二维空间是二次曲线,但在高维特征空间 φ(x) 中,它对应的是一个将两类数据完美分开的线性超平面。

总结与展望

本节课中,我们一起学习了核方法的第一个关键概念——基扩展。我们了解到,通过将原始特征映射到更高维的空间(例如,添加平方项和交叉项),可以将原始空间中的非线性分类问题(如二次决策边界)转化为高维空间中的线性分类问题。这使得像感知机这样的线性模型能够学习复杂的非线性模式。

我们实现这一点的方法非常简单:只需在标准感知机算法中用扩展后的特征向量 φ(x) 替换原始特征 x 即可。

基扩展展示了核方法的初步威力,但这仅仅是开始。它存在一个明显的挑战:当原始维度 d 很大时,扩展后的维度 O(d^2) 会急剧增长,导致计算和存储成本变得非常高。在接下来的课程中,我们将探讨核技巧,这是一种无需显式计算高维向量 φ(x) 就能在高维空间中进行运算的巧妙方法,从而高效地解决这个问题。敬请期待下一讲!

037:核方法技巧 🧠

在本节课中,我们将学习如何利用“核技巧”来高效地学习二次决策边界,而无需处理高维特征向量带来的计算负担。我们将从回顾感知机算法的基础扩展开始,逐步推导出核感知机算法。

回顾:基础扩展与感知机

上一节我们介绍了感知机算法如何通过基础扩展来学习二次决策边界。其核心思想是:通过将原始特征 x 映射到一个更高维的特征空间 φ(x),使得在原始空间中非线性的二次边界,在新空间中变为线性的。

具体来说,对于原始特征 x,我们构造一个扩展特征向量 φ(x),它包含原始特征、特征的平方项以及特征间的成对乘积项。这样,任何关于 x 的二次函数,都可以表示为关于 φ(x) 的线性函数。

感知机算法的基础扩展形式如下:

# 伪代码:基础扩展感知机
初始化 w = 0, b = 0
循环直到所有数据点被正确分类:
    对于每个数据点 (x_i, y_i):
        计算预测值 sign(w · φ(x_i) + b)
        如果 y_i * (w · φ(x_i) + b) <= 0:
            w = w + y_i * φ(x_i)
            b = b + y_i

然而,这种方法存在一个显著问题:φ(x) 的维度可能非常高,导致计算和存储成本巨大。例如,对于 MNIST 数据集(784维),二次扩展后的维度约为 ,即约 308,504 维,这在实际应用中通常是不可行的。

核技巧的核心思想

为了解决高维问题,我们引入核技巧。其核心洞察是:我们可以在不显式写出高维向量 φ(x) 的情况下,完成所有必要的计算。

第一步:对偶形式与权重向量 w

首先,我们注意到在感知机算法中,最终的权重向量 w 可以表示为训练样本的线性组合:

w = Σ_{j=1}^{n} α_j y_j φ(x_j)

其中,α_j 记录了算法在第 j 个数据点上犯错的次数(即更新次数)。因此,我们可以不直接存储高维向量 w,而是存储一个对偶系数向量 α = (α_1, ..., α_n)

第二步:避免计算高维点积

接下来,在分类一个新点 x 时,我们需要计算 w · φ(x)。利用对偶形式,我们可以将其重写为:

w · φ(x) = Σ_{j=1}^{n} α_j y_j [φ(x_j) · φ(x)]

现在,问题的关键变成了如何高效计算两个高维向量 φ(x_j)φ(x) 的点积,而无需显式构造它们。

第三步:核函数

对于二次扩展,存在一个巧妙的数学关系。假设我们采用一个特定的扩展形式(包含常数项和缩放因子),那么两个扩展向量的点积可以简化为:

K(x, z) = φ(x) · φ(z) = (1 + x · z)²

这个函数 K(x, z) 被称为核函数。它允许我们直接在原始的低维空间中,通过计算简单的点积 (x · z),来得到高维空间中的点积结果。

这意味着,对于 MNIST 数据,要计算两个 308,504 维向量的点积,我们只需计算原始 784 维向量的点积,然后加 1 并平方即可。这极大地提升了计算效率。

核感知机算法

基于以上推导,我们得到核感知机算法的对偶形式。

以下是算法的步骤:

  1. 初始化:设置对偶系数向量 α = 0,偏置 b = 0
  2. 训练循环:遍历训练数据集 (x_i, y_i)
  3. 计算预测:对于每个点,计算预测值 sign( Σ_{j=1}^{n} α_j y_j K(x_j, x_i) + b )
  4. 更新规则:如果点 (x_i, y_i) 被误分类(即 y_i * (预测值) <= 0),则更新:
    • α_i = α_i + 1
    • b = b + y_i
  5. 分类新样本:对于一个新测试点 x,其预测标签为 sign( Σ_{j=1}^{n} α_j y_j K(x_j, x) + b )

该算法的优势在于,我们只需要存储对偶系数 α 和偏置 b,并在计算中通过核函数 K 隐式地利用高维特征空间的信息,完全避免了处理超高维向量 φ(x)

算法效果与总结

通过核技巧,感知机算法能够高效地学习复杂的非线性决策边界(如二次边界)。在低维数据(如2维)上,基础扩展和核方法可能效率相当;但在高维数据(如图像)上,核技巧是使算法变得可行的关键。

本节课我们一起学习了:

  1. 基础扩展感知机在处理非线性边界时面临的高维计算挑战。
  2. 核技巧的核心思想:通过对偶形式和核函数,避免显式计算高维特征向量。
  3. 针对二次边界的特定核函数:K(x, z) = (1 + x · z)²
  4. 核感知机算法的完整对偶形式及其高效的更新规则。

核技巧是机器学习中一个强大而优美的思想,它不仅应用于感知机,也是支持向量机等许多高级模型的基础。下次课我们将探索如何利用核方法处理更复杂的多项式决策边界。

038:核支持向量机 🧠

在本节课中,我们将学习如何将核技巧应用于支持向量机,从而高效地学习复杂的非线性决策边界,特别是多项式边界。

上一节我们完整地介绍了核技巧。它为我们提供了感知机算法的高效版本,能够学习任意的二次决策边界。本节中,我们将看到可以对支持向量机做同样的事情,并且更进一步,超越二次边界,学习任意阶的多项式边界。

我们的首要任务是将支持向量机“核化”。然后,我们将探讨如何获得多项式决策边界。

快速回顾

在过去的几节课中,我们一直在研究如何使用线性分类的简单方法来学习二次决策边界。到目前为止,我们使用了两个技巧。

第一个技巧是基扩展。其核心思想是用扩展后的向量 φ(x) 替换原始数据向量 x。如果原始数据向量具有特征 x₁, x₂ 等,那么扩展向量 φ(x) 将包含原始特征、这些特征的平方以及它们的成对乘积(如 x₁x₂)。

这样做的原因是,如果一个函数在 x 上是二次的,那么它在 φ(x) 上就是线性的。因此,我们可以在原始空间 x 中学习一个二次边界,方法是在更高维的空间 φ(x) 中简单地学习一个线性边界。

这为我们带来了带基扩展的感知机算法,它只是普通的感知机算法,只不过我们将 x 替换为 φ(x)

然而,这个算法有一个显著的缺点:这些扩展向量 φ(x) 和权重向量 w 的维度可能极高。例如,在MNIST手写数字数据集中,原始数据向量的维度是784,但扩展向量 φ(x) 的维度超过了30万。这使得它们处理起来非常不便。

因此,我们提出的解决方案是核技巧。其关键思想是不直接处理 w,而是处理其对偶表示。从感知机算法的形式可以看出,在任何时刻,w 向量都具有以下形式:w = Σ αⱼ yⱼ φ(xⱼ)。这是因为我们从 w=0 开始,唯一对 w 的操作就是加上 yᵢ φ(xᵢ)。系数 αⱼ 正是我们在第 j 个数据点上更新的次数。

因此,我们不使用 w,而是使用由这些系数 α₁, …, αₙ 组成的对偶形式。以下是感知机算法的对偶形式,可以看到所有关于 w 的提及都消失了。我们完全使用 α 工作:将它们初始化为1,遍历数据,如果在某个点(比如第 i 个点)上犯错,我们只需增加对应的系数 αᵢ,并相应地调整偏置 b

为了分类一个新点 x,我们使用公式:sign( Σ αⱼ yⱼ φ(xⱼ)·φ(x) + b )。这等同于 sign( w·φ(x) + b ),只是我们用系数 α 的表达式替换了 w

所有这些操作都非常简单,除了一件事:看起来我们必须计算这些扩展数据向量之间的点积。然而,我们上次看到,对于二次嵌入,我们可以非常容易地计算这些点积。具体来说,φ(x)·φ(z) = (x·z + 1)²。因此,整个算法变得极其高效。

核化支持向量机

既然核技巧在感知机上效果如此之好,一个自然的问题是:我们能否对支持向量机做类似的事情?

对于支持向量机,我们通过求解一个优化问题来进行学习。我们见过这个问题的两种形式:原始形式和对偶形式。在原始形式中,我们直接求解 wb。在对偶形式中,我们求解系数 α,其解释与感知机中的相同,即 w = Σ αᵢ yᵢ φ(xᵢ)

我们应该使用哪种形式?看起来对偶形式已经让我们朝着目标迈进了一半,因为我们无论如何都希望使用这些系数 α。因此,让我们使用对偶形式。

以下是核支持向量机的步骤。我们有一个特定的嵌入(例如,用于二次决策边界的嵌入),现在我们求解对偶优化问题。我们的数据点是 (xᵢ, yᵢ)。对于对偶问题,我们需要计算所有 φ(xᵢ)φ(xⱼ) 之间的点积。这没问题,我们已经知道这些点积可以高效计算。我们计算这些点积,同时还有标签 yᵢyⱼ(只是+1或-1),然后将所有这些交给优化包,它会返回 α

为了进行分类,我们再次使用规则 sign( w·φ(x) + b ),或者我们可以代入 w 的对偶形式,得到分类规则:sign( Σ αⱼ yⱼ φ(xⱼ)·φ(x) + b )。这一切都非常直接,使用的正是我们在核感知机中发展出来的相同思想。

实际效果

让我们看看它在实际中的效果。

这里有一个我们之前见过的数据集。这是感知机算法得出的边界,它是一个二次边界(椭圆),效果不错。但看看核支持向量机得出的边界,它更加美观,位置居中。图中加粗显示的点是支持向量,只有8个。因此,最终的 α 向量大部分为零,只有8个坐标非零。相比之下,感知机算法最终使用了几乎所有的数据点。所以,支持向量机产生了一个稀疏得多的 α 解。

再看另一个例子,这是一个非线性可分的数据集。感知机算法得出某个二次边界,而这是支持向量机得出的边界。

这条线是决策边界,其公式为 w·φ(x) + b = 0。假设绿色点是-1类,紫色点是+1类。那么这边的边界是 w·φ(x) + b = -1,对应的另一边边界是 w·φ(x) + b = 1

这些边界在二维空间中看起来是二次的,但在更高维的嵌入空间(那个五维空间)中,它们只是线性的超平面。在五维空间中,黑色三角形在一侧,红色圆圈在另一侧,中间有一个具有最大间隔的漂亮线性边界。

扩展到更高阶多项式

我们已经取得了很大进展。我们找到了一种方法,可以使用感知机或软间隔支持向量机来获得二次决策边界。可以说,我们已经解决了学习二次决策边界的问题。

现在让我们更进一步,看看是否能获得更复杂的决策边界,比如更高阶的多项式边界(不仅仅是二次,可能是三次或四次多项式)。例如,下图是一个多项式决策边界。

这个多项式的阶数是多少?它看起来转折了三次,所以阶数至少是四。我们能学习这样的决策边界吗?事实证明,我们可以使用几乎相同的技巧轻松做到这一点。

那么,在这种情况下,我们的嵌入 φ(x) 是什么?和往常一样,我们取原始特征 x₁x_d。但现在,我们还加入所有阶数最高为 p 的项,其中 p 是我们想要的多项式的阶数。例如,假设我们想要一个四次多项式的边界,那么 p=4

我们的扩展向量 φ(x) 将包含所有原始特征,以及所有阶数不超过4的项,例如 x₁⁴x₂² x₇²x₁ x₂ x₃ x₄x₁³ x₈ 等。所有指数之和为4或更小的项都包含在内。

这样的项非常多。实际上,这类项的数量大约是 d^p,其中 d 是原始向量的维度,p 是多项式的阶数。但如果我们这样做,我们仍然可以继续使用我们的线性分类器技术,因为任何在 x 上是 p 次多项式的函数,在这个表示 φ(x) 中都是线性的。

为了使这可行,这些表示现在确实非常庞大,我们甚至无法写出一个这样的数据点。那么,有我们可以使用的核技巧吗?有没有一种方法可以高效地计算这些点积?

事实证明,确实有。φ(x)φ(z) 的点积再次变得非常简单:(x·z + 1)^p。事情的发展简单得超乎想象。

总结

本节课中,我们一起学习了以下内容:

  • 我们为感知机和支持向量机都创建了核化版本。
  • 我们看到了如何轻松高效地使用它们来学习任何类型的多项式决策边界。
  • 核技巧的惊人之处在于,我们还能用它做更多的事情。

核技巧的潜力巨大,让我们拭目以待,下次课再见。

039:核函数 🧠

在本节课中,我们将学习核方法的核心概念。我们将看到,核感知机和核支持向量机的核心是一个称为核函数的对象。这将为我们打开通往各种复杂决策边界的大门。

回顾:多项式决策边界

上一节我们介绍了如何通过基展开获得多项式决策边界。本节中,我们来看看如何利用线性分类技术实现这一点。

关键在于使用基展开。我们不是使用原始数据向量 x,而是创建其扩展表示 φ(x)φ(x) 包含 x 中的所有原始特征,以及这些原始特征中所有阶数最高为 p 的项。

例如,假设原始数据点是二维的,即 x 有两个特征 x₁x₂。我们想要一个阶数为3的多项式边界(即 p=3)。那么,我们创建的扩展表示 φ(x) 将包含:

  • 原始特征 x₁x₂
  • 所有2阶项:x₁²x₂²x₁x₂
  • 所有3阶项:x₁³x₂³x₁²x₂x₁x₂²

如果 x 原本是 D 维的,并且我们想要所有 P 阶的项,那么 φ(x) 的大小可能达到 Dᴾ,这可能会非常大。

这之所以有帮助,是因为任何关于 xP 阶多项式函数,实际上在 φ(x) 空间中是线性的。如果我们想在原始空间中学习一个 P 阶多项式决策边界,等价于在 φ(x) 的高维特征空间中学习一个线性决策边界。

为了学习这个线性分类器,我们可以使用感知机或支持向量机等标准方法。唯一的缺点是这些扩展表示向量 φ(x) 可能非常庞大。但幸运的是,我们不需要显式地写出它们。

对于感知机和SVM,我们只需要能够计算点积。事实证明,我们可以高效地计算这些点积。两个高维向量 φ(x)φ(z) 的点积就是 (1 + x·z)ᴾ

核支持向量机算法

基于此,我们得到了核支持向量机算法。

以下是核SVM的步骤:

  1. 选择基展开:在我们的例子中,需要选择多项式的阶数 p
  2. 学习分类器:通过求解对偶SVM优化问题来学习分类器。更准确地说,我们不需要自己求解,而是将其交给标准的SVM软件包。
  3. 提供信息:我们需要向优化包提供训练集 {(x₁, y₁), ..., (xɴ, yɴ)}、标签 yᵢ,以及所有扩展特征向量之间的点积(即每对数据点在扩展特征空间中的点积)。我们可以高效地计算这些点积。
  4. 获取参数:优化包返回一个向量 α 和一个偏移量 bαN 个坐标,每个数据点一个。
  5. 预测新点:要对一个新点 x 进行预测,我们计算加权和:∑ᵢ (αᵢ * yᵢ * (φ(xᵢ)·φ(x))) + b。如果结果为正,则预测+1;如果为负,则预测-1。

核函数:核心概念

虽然我们明确指定了扩展表示 φ(x),但在算法中,我们从未在任何时候构造 φ(x)。我们只使用了这些点积。事实上,这是我们访问数据的唯一方式。

因此,我们给这个点积一个特殊的名称:核函数。对于原始特征空间中的任意两点 xz,核函数 K(x, z) 定义为:
K(x, z) = φ(x)·φ(z)

我们可以用核函数完全重写我们的算法。对于核SVM,步骤如下:

  1. 选择核函数:例如,如果我们想要一个 P 阶多项式,核函数就是 K(x, z) = (1 + x·z)ᴾ
  2. 学习:计算所有数据点对之间的核函数值,并将此信息提供给优化包,得到 αb
  3. 预测:对新点 x 分类时,计算 ∑ᵢ (αᵢ * yᵢ * K(xᵢ, x)) + b 并返回其符号。

核函数可以看作数据点之间相似性的度量。两个数据点越接近,它们的向量对齐越紧密,点积(即核函数值)就越高。

核感知机算法

那么感知机算法用这种方式重写后是什么样子呢?它非常简单。

以下是核感知机的步骤:

  1. 初始化:将参数 αb 初始化为0。
  2. 循环训练:循环遍历数据,直到所有点都被正确分类。如果在某个时刻错误分类了第 i 个数据点,我们只需更新:αᵢ = αᵢ + 1b = b + yᵢ
  3. 预测:要分类一个新点 x,计算 ∑ᵢ (αᵢ * yᵢ * K(xᵢ, x)) + b 并返回其符号。

让我们仔细看看这个用于分类的加权和。它实际上是一种基于相似性的加权投票。为了分类一个点 x,我们计算它与每个训练数据点的相似度,然后根据这些相似度值,对这些点的标签进行加权投票。

选择任意相似性度量

这引出了一个有趣的问题:我们能否选择任何我们想要的相似性度量?例如,如果我们正在对文档进行分类,能否定义一个合理的相似性度量(比如文档之间共同单词的比例),然后将其用于感知机算法?

答案是:几乎可以,但不完全是。我们需要这个相似性度量对应于某个高维扩展特征空间中的点积。只要这样的扩展表示 φ 存在,具体是什么并不重要。

如何检查我们设计的相似性度量是否合法(即是否存在对应的 φ)?这可以通过Mercer条件来检查。

概念上很简单:取任意有限的数据点集 {x₁, ..., xₘ},计算所有点对之间的相似度,并将其写入一个 m×m 的矩阵 K,其中 Kᵢⱼ = K(xᵢ, xⱼ)。我们需要这个方阵是半正定的。如果满足,那么这个相似性函数就是一个有效的核函数。

高斯核(RBF核)

这为我们打开了使用各种核函数的大门。一个非常流行的核函数是高斯核径向基函数核

高斯核定义两点 xz 之间的相似度为:
K(x, z) = exp(-||x - z||² / s²)

其中 s 是一个缩放参数。

  • x = z 时,距离为0,指数为0,相似度为1。
  • x 远离 z 时,距离增大,指数减小,相似度从1向0下降。
  • 因此,K(x, z) 总是在0到1之间,并在 x = z 时达到最大,这是一个相当合理的相似性概念。

高斯核是一个有效的核函数,它对应的扩展特征向量 φ(x) 是无限维的,但我们永远不需要构造它,只需要计算点积,而点积的计算非常简单。

高斯核的效果非常强大。即使在原始空间数据不是线性可分的,使用RBF核的SVM也能产生复杂而漂亮的决策边界。

高斯核的参数 s

高斯核有一个尺度参数 s。改变这个参数有什么影响呢?预测函数 f(x) 是一个基于相似性的加权投票。让我们看看两个极端情况:

  • 当 s → ∞:除以无穷大意味着指数项趋近于0,所有相似度都变得相同(等于1)。因此,对于任何点 x,预测结果总是相同的。这类似于我们几乎没有数据时的情况。
  • 当 s → 0:除以一个极小的数意味着距离被极大地放大。任何距离上的微小差异都会被急剧放大。对于一个新点 x,与其最接近的那个训练数据点的相似度将占绝对主导,预测的标签将基本上就是那个最近邻的标签。这类似于最近邻分类器的行为。

随着我们获得更多数据,我们显然希望从左侧(s 很大)向右侧(s 较小)移动,以捕捉数据中更细致的结构。

总结

本节课中,我们一起学习了核方法的核心。我们首先回顾了通过基展开获得非线性决策边界的方法,并指出了其计算瓶颈。接着,我们引入了核函数的概念,它高效地计算了高维空间中的点积。我们看到,无论是支持向量机还是感知机算法,都可以完全用核函数来表述,从而避免显式处理高维特征。我们还探讨了如何判断一个自定义的相似性度量是否构成有效的核函数(Mercer条件)。最后,我们介绍了一个强大且常用的核函数——高斯核(RBF核),并分析了其尺度参数 s 对模型行为的影响,从过于平滑(大 s)到过于局部(小 s)。核方法为我们提供了构建复杂、非线性模型的强大工具,而计算成本依然可控。

040:组合简单分类器 🧩

在本节课中,我们将转变思路,从一个全新的视角来审视学习过程。这将引导我们了解一些最成功的现成分类系统。

我们之前已经讨论过许多不同类型的分类器,例如最近邻分类器、基于不同分布的生成模型、逻辑回归或支持向量机等线性预测器,以及使用核方法的非线性决策边界。很快,我们还将接触到神经网络。

但有一个问题我们尚未考虑:我们能否将一堆不同的分类器组合起来,得到一个比其中任何一个单独模型都更优的结果? 答案是肯定的。事实证明,这是一条非常富有成果的研究路线。


组合分类器的基本问题 🤔

上一节我们介绍了组合分类器的核心思想。本节中,我们来看看在开始研究组合分类器这一整体业务时,会浮现出哪些基本问题。

以下是组合分类器时需要考虑的几个关键问题:

  1. 模型的简单性:我们将组合多个模型,因此其中任何一个模型都不是最终产品。这意味着单个模型无需完美。或许我们可以让它们保持简单。事实上,我们可以让它们非常简单,例如,仅依赖于一个特征的分类器。
  2. 模型的训练方式:我们需要一个模型集合,并以某种方式组合它们。但这些模型该如何训练?我们是在同一个训练集上分别、独立地训练它们,还是可以采取更巧妙的方法?例如,我们能否一次训练一个模型,每次都专注于当前表现不佳的训练集区域?
  3. 泛化问题:我们将组合大量模型。最终模型可能非常庞大,参数数量巨大。这是否意味着我们也需要海量数据来学习所有这些参数?

这些就是我们在开始研究组合分类器时,将潜伏在背景中的一些基本问题的例子。


总结与预告 📚

本节课中,我们一起学习了组合简单分类器的基本概念和潜在优势。我们探讨了这种方法的可行性,并提出了在实施过程中需要解决的几个关键问题,包括模型的简单性、训练策略以及泛化能力。

这只是一个非常简短的介绍,为我们开启了一条全新且富有成果的研究路线。下次课,我们将正式开始学习决策树。

041:决策树 🌳

在本节课中,我们将要学习决策树。决策树是一种灵活且易于理解和使用的分类器。我们将从了解决策树的形式开始,然后探讨如何学习这些模型。一个主要问题是过拟合,我们将花时间讨论这个问题以及如何缓解它。

决策树的形式与示例

上一节我们介绍了课程概述,本节中我们来看看决策树的具体形式。决策树是一种灵活的、易于理解和使用的分类器。

在20世纪70年代末,加州大学圣地亚哥分校医学中心的研究人员希望解决一个特定的预测问题。他们想知道哪些心脏病发作的患者可以安全出院。具体来说,他们想了解最近心脏病发作的患者在未来30天内是否有死亡风险,即是否为高风险患者。

为了更好理解,他们收集了215名患者的数据,记录了每位患者住院期间的19个相关特征。在这些患者中,约20%(37人)在随后一个月内死亡。这是一个经典的二分类问题。研究人员可以使用许多标准方法,如最近邻、生成模型、线性分类器等。

但他们最想要的是一个易于解释和理解的模型,因此决定使用决策树。以下是他们找到的决策树。

这个决策树模型将患者分类为高风险或非高风险,最多只需问三个问题。

第一个问题是:查看患者过去24小时内的最低收缩压,是否超过91?如果没有,这是一个不好的迹象,血压低,患者为高风险。如果血压正常,则下一个问题是关于患者的年龄:是否超过62.5岁?如果没有,则将患者分类为非高风险。最后一个问题适用于血压正常且年长的患者:患者是否有异常心率?如果有,则分类为高风险;如果没有,则为非高风险。

这个模型非常易于理解,基于明确相关的特征。然而,即使是专家,也很难手动构建这样的模型。应该使用哪些特征?问题应该按什么顺序提出?具体的阈值(如62.5和91)是多少?这是机器学习的一个绝佳应用。

决策树的学习过程

上一节我们看了一个决策树的应用实例,本节中我们来看看决策树是如何被学习构建的。

这是一个二维数据集的玩具示例,有两个特征x1和x2,以及两个类别:红色圆圈和蓝色星星。决策树以自上而下的方式构建。最初,我们只有一个包含所有数据点的节点,其中有13个红点和15个蓝点。如果必须进行预测,我们会预测蓝色,但误差会很高,存在很大的不确定性。因此,我们希望分割这个节点。

以下是构建决策树的基本步骤:

  1. 尝试所有可能的分割:我们可以沿着x1或x2进行分割。沿着x1,我们可以在这里、这里或这里分割;沿着x2,我们可以在这里、这里或这里分割。我们尝试所有这些分割,看看哪一个能最大程度地减少不确定性或误差。
  2. 选择最佳分割:有多种量化不确定性的方法,我们通常让软件包来处理。高层次的观点是,算法尝试所有可能的分割,并贪婪地选择最佳的一个。在这个例子中,它选择在x1上分割,问题是:x1是否小于0.5?
  3. 递归分割:在左侧,我们得到8个全是红色的点,完美。在右侧,我们得到5个红点和15个蓝点。为了进一步减少误差,我们继续分割这个叶节点。我们再次尝试所有可能的分割,最佳分割出现在x2等于0.5处。
  4. 继续生长或停止:我们可以继续分割,直到每个叶节点都是纯的(即只包含一个类别的点),或者根据某些标准停止。

在这个例子中,我们继续分割,直到每个叶节点都完全纯净,得到了最终的决策树及其诱导的数据空间划分。

总结来说,我们通过一种贪婪的自上而下算法构建决策树。我们从所有数据点在一个节点开始,然后开始生长树。在任何给定点,我们已经生长了一些树,并有一堆叶节点。我们可以分割其中任何一个叶节点。我们将尝试所有可能的叶节点和所有可能的分割,并选择能最大程度减少误差或不确定性的那个。有多种量化方法,如基尼指数、熵等。

一个重要的问题是:我们何时停止生长树?我们什么时候完成?

以下是几种可能的停止标准:

  • 继续直到每个叶节点都是纯的(就像我们在例子中所做的那样)。
  • 继续直到树变得太大(例如,达到一定深度或节点数)。
  • 继续直到每个叶节点相对纯净(例如,95%纯净)。

这些实际上都是合理的停止标准。我们在例子中使用的是第一种,即继续直到每个叶节点都是纯的。但这样做存在严重的过拟合风险。

过拟合问题与缓解策略

上一节我们介绍了决策树的生长过程,本节中我们来看看一个关键问题:过拟合。

在我们的例子中,这是我们最终得到的树,其中每个单元都是纯的。而这是我们在此过程中遇到的中间树之一。哪一个更好?右边的最终树训练误差为零,在这方面很好。左边的树有一点训练误差,但非常少,而且更简单。在许多方面,它更好。在右边的树上,我们只是为了正确分类那一个额外的红点而付出了很大努力。这值得吗?可能不值得。那个点可能只是一个异常值。因此,右边的树很可能过拟合了数据。

让我们具体谈谈这在决策树上下文中的含义。

当你生长决策树时,如果需要,你可以将训练误差降至0,你可以让每个点都在自己的叶节点(自己的单元)中。在下图中,X轴显示了树的生长过程,树中的节点数变得越来越大。随着树的生长,训练误差下降(Y轴显示误差)。但我们最终感兴趣的并不是训练误差,而是未来的性能,即未来数据上的误差(测试误差)。测试误差通常看起来像这样。

当我们最初生长树时,训练误差和测试误差都在下降,一切顺利。但随后到达一个点,训练误差继续下降,而测试误差开始上升。这就是我们开始过拟合数据的点。我们正在拟合数据中那些实际上只是抽样误差、只是噪声的方面,这些方面对未来预测没有帮助。

因此,我们理想的做法是在这里的某个地方停止树的生长过程。

让我们从稍微不同的角度看待过拟合。假设底层真实的决策边界是这样的。

基于有限的数据点,我们无法得到这个真实的决策边界。如果我们用决策树完美地拟合这些数据点,我们最终可能会得到一个锯齿状的阶梯,像这样。它在精神上是正确的,具有与真实决策边界大致相同的形状,但这里的许多细节,这些小阶梯,实际上只是在拟合噪声,拟合数据中的偶然结构。它们真的只是抽样误差的反映,过多关注这种细节就是过拟合。

决策树的特性与总结

上一节我们讨论了过拟合,本节我们来总结一下决策树的特性。

决策树是非常灵活和富有表现力的分类器。它们可以容纳任何类型的数据。在我们的例子中,我们有数值数据,但它们也可以处理分类数据,例如,一个人的眼睛颜色是蓝色、黑色还是棕色。在决策树中,我们可以有诸如“他们的眼睛是棕色的吗?”这样的问题。决策树对此没有困难。

它们可以容纳任意数量的类别,本质上是多类的,你不需要做任何特殊处理。通过将树生长得足够大,它们可以拟合任何数据集,你可以将训练误差降至0。最重要的是,它们非常易于解释。所以它们是非常好的模型。

最大的缺点是它们容易过拟合。那么有哪些应对策略呢?

以下是处理过拟合的一些策略:

  1. 提前停止生长:例如,当叶节点达到所需的纯度水平时,或者当树达到某个最大大小时。
  2. 后剪枝:如果我们愿意,我们可以一直生长树直到所有叶节点都完全纯净,得到一个巨大的树,然后使用验证集对其进行剪枝。这意味着我们尝试所有可能的剪枝方式(虽然数量是指数级的),但我们可以使用动态规划算法在多项式时间内找到最佳的一个。这也是拟合决策树的一种完全合理的方法。

本节课我们一起学习了决策树,这是一种极其简单且最重要的是易于解释的分类器。在许多应用中,可解释性确实至关重要。

042:提升法 🚀

在本节课中,我们将要学习一种巧妙组合简单分类器的方法,它被称为“提升法”。我们将从介绍“弱学习器”的概念开始,然后探讨如何通过提升法,特别是可爱的AdaBoost算法,来克服这类学习器的不足。


弱学习器与提升法的基本思想

上一节我们介绍了提升法的目标。本节中我们来看看其核心思想。

在机器学习中,一个常见的情况是,在数据上获得60%、70%或80%的准确率通常比较容易,但后续的提升则需要付出巨大努力。

让我们更抽象地思考这个问题。一个弱分类器是指其性能优于随机猜测的分类器,即其错误率低于50%,但可能好得不多,例如错误率为45%或49%。一个弱学习器则是一种能够反复生成此类弱分类器的学习算法。

那么,我们能否提升弱学习器的性能?能否利用弱学习器来生成质量高得多的分类器?这就是提升法所做的事情。

以下是提升法的基本思路:

假设我们有一个数据集 (x1, y1) ... (xn, yn),并且我们拥有一个弱学习器。我们不知道它的具体工作原理,它是一个黑盒分类算法:我们输入数据,它返回一个弱分类器,唯一保证的是这个分类器优于随机猜测。

这听起来并不那么令人放心。我们如何利用它来获得高质量的分类器呢?

首先,我们假设这个弱学习器允许我们为数据点附加权重。这意味着我们可以指定每个数据点的重要性,例如,某个点的权重为2,相当于该点在数据集中出现了两次。大多数学习算法都能在不显式复制数据点的情况下处理权重。


AdaBoost算法详解

上一节我们介绍了提升法的基本思想。本节中我们来看看其具体实现——AdaBoost算法。

AdaBoost算法的整个过程可以概括如下。我们有一个数据集,其标签为 -1+1。在任何时刻,我们都有一个对数据点的加权分布,在时间 t 的权重分布称为 D_t

初始权重是赋予所有点相同的权重,例如 1 或归一化的 1/m

然后我们开始多轮提升。在每一轮中:

  1. 我们将加权数据集输入弱学习器,它返回一个弱分类器 h_t
  2. 我们评估这个弱分类器的好坏,为其计算一个分数 r_t
  3. 我们根据 h_t 的表现更新数据点的权重:对于分类正确的点,降低其权重;对于分类错误的点,提高其权重,以便后续学习器更关注这些困难点。
  4. 我们为这个弱分类器 h_t 计算一个权重 α_t,用于最终的投票组合。

经过 T 轮后,我们得到一系列弱分类器 h1, h2, ..., hT 及其对应权重 α1, α2, ..., αT

最终的分类器是所有这些弱分类器的加权多数投票。对于一个新点 x,我们计算加权和 Σ α_t * h_t(x)。如果结果为正,则预测 +1;如果为负,则预测 -1

以下是算法中的核心公式:

  • 弱分类器分数r_t = Σ_i D_t(i) * y_i * h_t(x_i)
    • 这个分数在 -1+1 之间。+1 表示完全正确,-1 表示完全错误,0 类似于随机猜测。
  • 弱分类器权重α_t = 0.5 * ln((1 + r_t) / (1 - r_t))
    • 表现越好的分类器,其权重 α_t 越高。
  • 数据点权重更新D_{t+1}(i) = (D_t(i) * exp(-α_t * y_i * h_t(x_i))) / Z_t
    • 其中 Z_t 是归一化因子,确保 D_{t+1} 是一个概率分布。分类错误的点权重会增加。

AdaBoost工作示例

上一节我们介绍了AdaBoost的算法步骤。本节中我们通过一个具体例子来看看它是如何工作的。

这是一个由AdaBoost的创建者Yoav Freund和Robert Schapire设计的简单示例。

我们有一个二维训练集,包含10个点(5个正类,5个负类)。我们将使用提升法构建分类器。此例中,弱学习器生成的弱分类器是简单的水平或垂直分割线(也称为“决策树桩”),例如“如果x1 > 某个阈值,则预测+1,否则预测-1”。

以下是AdaBoost的运行过程:

  1. 第一轮:所有点初始权重相同。弱学习器可能生成第一条分割线(例如一条垂直线)。这条线分错了3个点(错误率30%)。我们计算其分数 r1 和权重 α1。然后,我们增加那3个被分错点的权重,减少分对点的权重。
  2. 第二轮:将更新权重后的数据集输入弱学习器。由于第一轮分错的点现在权重很高,弱学习器必须生成一个不同的分类器来更好地处理它们,例如另一条垂直线。这条新线又会分错另一组点(比如另外3个)。我们再次更新权重,增加这新一轮分错点的权重。
  3. 第三轮:重复此过程,弱学习器可能生成一条水平线。假设此时我们停止。

现在我们有了三个决策树桩 h1, h2, h3 及其权重 α1, α2, α3。最终的分类是它们的加权投票。

即使每个基分类器(弱分类器)都非常简单(仅基于单个特征的阈值),但通过加权组合,最终得到的决策边界是非线性的,并且在这个例子中完美分类了所有训练数据。


AdaBoost的理论保证与扩展

上一节我们看到了AdaBoost在实践中如何组合简单模型。本节中我们来看看其强大的理论性质以及一些扩展应用。

AdaBoost有一个非常惊人的数学性质:只要弱学习器每一轮产生的弱分类器错误率都低于 1/2(即优于随机猜测,设错误率为 1/2 - γγ > 0),那么经过 T 轮提升后,最终分类器的训练误差会以指数速度下降至零。这是一个非常强大的保证,意味着我们可以将仅比随机猜测好一点点的弱分类器,组合成一个任意高精度的强分类器。

在实际应用中,常用的弱分类器选择包括:

  • 决策树桩:如示例所示,这是最简单的决策树(只有一个分裂点)。提升的决策树桩集合通常与决策树进行比较,因为决策树也是由树桩(分裂节点)组成的,只是以分层方式组织。
  • 决策树:也可以将整个决策树作为弱分类器进行提升。这样会生成一系列树,有时被称为“森林”。这引出了我们下次课将深入探讨的“随机森林”概念。


总结

本节课中我们一起学习了提升法,特别是AdaBoost算法。

我们从弱学习器的概念出发,理解了如何通过迭代地调整数据权重、组合多个弱分类器,来构建一个强大的最终模型。AdaBoost算法通过为每个弱分类器分配权重,并对分类错误的数据点给予更多关注,有效地将一系列“略好于随机”的规则整合起来。

我们看到了AdaBoost在简单示例中的工作过程,并了解了其指数级降低训练误差的理论保证。最后,我们提到了提升法可以与不同的基学习器(如决策树桩或完整决策树)结合使用,形成高效且性能优异的集成分类系统。

提升法是一个简单、高效且性能强大的现成分类工具,其思想在机器学习领域影响深远。

043:随机森林 🌲

在本节课中,我们将要学习一种被称为“随机森林”的集成学习方法。我们将从理解什么是分类器集成开始,然后详细探讨随机森林的构建过程,最后通过一个实验来对比决策树、提升方法和随机森林的性能。

集成方法与随机森林概述

提升方法通常被称为一种集成方法,因为它会生成一个分类器的集合或集成。

本节我们将探讨另一种极其流行的集成方法,它因其极端的简单性和在实际中的优异性能而广受欢迎,这种方法被称为随机森林。

我们将从观察树分类器的集成(有时也称为森林)开始。然后,我们将了解随机森林是如何构建的。最后,我们将进行一个实验,将我们对决策树、提升方法和随机森林的讨论整合在一起。

决策树的局限性与改进思路

我们已经讨论了很多关于决策树的内容。这些是非常有吸引力的分类器。它们会问一些问题(在图中由圆形节点表示),然后将我们引向一个叶子节点,在那里做出预测。

理论上,决策树可以拟合任何数据集。但在现实中,它们存在一个问题:一旦树开始变得太大,它就会开始对数据过拟合。随着树变得过大,训练误差会持续下降,但我们真正关心的测试误差却开始上升。因此,最佳性能通常由一棵中等大小的树实现。

那么,如何改进这一点呢?一种方法是使用提升方法来创建一整批树。我们不是继续生长单棵树(这会使情况更糟),而是重新开始一棵树,专注于第一棵树犯的错误。完成第二棵树后,我们再开始第三棵决策树,专注于前两棵树的错误,依此类推。

随着我们不断添加越来越多的树,训练误差会下降,而且测试误差也经常会下降。这是一个非常有吸引力的方案。然而,一个不便之处是,这个过程必须顺序进行。我们必须等待第一棵决策树完成,才能开始第二棵树,因为这告诉我们如何重新加权数据点。同样,我们必须等待第二棵树完成,才能开始第三棵树。所有这些有时可能相当慢。

如果能并行构建所有这些树,那该多好。要做到这一点需要什么呢?如果我们想同时构建一整批树,我们首先必须确保这些树最终彼此之间有很大不同。拥有多个相同树的副本是没有意义的。

那么,如何确保你并行构建的这些树都彼此不同呢?一个很好的方法就是在树构建过程中简单地引入随机性,而这正是随机森林所做的。

随机森林的构建过程

让我们看看随机森林是如何构建的。假设我们有一个包含 N 个数据点的数据集,比如在 D 维空间中,我们称这个数据集为 S。假设我们想要构建一个包含 T 棵树的集合。如果我们愿意,我们可以并行完成。

我们将构建 T 棵决策树。在构建每棵树时,我们将使用两种随机化方法。

以下是构建随机森林的两个关键随机化步骤:

  1. 数据重采样:我们不会使用原始数据集 S,而是对数据进行重采样。具体做法是,我们从 S 中有放回地随机抽取 N' 个点,作为我们的数据点集。通常,N' 被设定为 N。
  2. 特征随机选择:在树构建过程中,当我们在一个节点需要进行分割时,我们不会考虑所有 D 个特征。相反,我们会随机选择 K 个特征,并且强制只能从这 K 个特征中选择一个进行分割。通常,K 被设定为类似 sqrt(D) 的值,或者一个固定的比例,如 D/2

这样做可以在树之间创造多样性,从而创造一种鲁棒性。这些树必须以多种不同的方式得出正确的答案(正确的标签)。这是一种非常有趣的随机性。事实上,当我们研究神经网络时,我们会看到类似的做法,通常被称为“丢弃法”。

使用这两种随机性,我们得到了一组 T 棵树,它们彼此之间都相当不同。

现在,当需要预测一个新点 x 的标签时,我们只需让 x 通过所有树,获得每棵树的“投票”(即每棵树的预测标签),然后采取多数投票

实验:森林类型预测

让我们看一个简单的例子,它将所有这些内容整合在一起。既然我们一直在讨论树,我认为看一个关于森林类型的生态学例子是合适的。这就是“覆盖类型”数据集。

它包含了从美国国家森林各个地点收集的数据。每个数据点都是从一小块土地(30米 x 30米)收集的。从这块土地上测量了 54 个特征。这些特征包括海拔、坡度、阴影量、到道路的距离、土壤类型等。基于这些特征,目标是预测这块土地的森林类型。

总共有七种森林类型,但在这个特定的数据集中,有两种类型完全主导了其他类型,它们是云杉和黑松。为了简化,我们实际上剔除了其他数据点,所以本质上我们有一个二元分类问题。数据量非常大,我们将其分为约 50,000 个点的训练集和约 450,000 个点的测试集。

单棵决策树的性能

第一步是将一棵决策树拟合到数据上。我们像往常一样生长这棵树,在某个时刻它开始过拟合。在这个案例中,我们选择在深度为 20 时停止生长树。当我们这样做时,我们发现训练误差为 1%,测试误差约为 12.6%。这已经很难再大幅改进了。

提升方法的性能

我们如何通过使用提升方法来创建一整批决策树来改进这一点呢?我们固定决策树深度为 20,并创建了总共 40 棵树的集合。图表显示了随着我们添加越来越多的树,测试误差是如何下降的。

当我们只有一棵树时,测试误差是 12.6%。随着我们添加更多的树,测试误差持续下降,最初急剧下降,然后逐渐趋于平稳,达到略低于 8% 的错误率。这效果很好。为了与随机森林进行比较,我们选择了一个固定数量的树,比如 10 棵树。

随机森林的性能

现在让我们看看在这个数据上构建随机森林会发生什么。我们决定使用 10 棵树。在构建随机森林时,在每次分割节点时,不允许使用所有可能的特征。我们随机选择其中一部分特征,然后将注意力限制在仅这些特征上。

在我们的案例中,我们将这个比例设定为 50%。因此,当我们在分割一个节点时,我们从 54 个特征中随机选择 50%。然后,我们要求分割必须涉及这些选定的特征之一。为了补偿这一点,我们允许树变得更大,将深度从 20 增加到 40。

我们以这种方式构建了 10 棵树。结果发现,如果你查看随机森林中生成的任何一棵单独的树,其测试误差在 15% 到 17% 之间。这比单棵决策树的误差要差得多,这是因为树构建过程中的所有约束和随机性。

然而,这 10 棵树彼此之间足够不同,以至于对它们进行多数投票,产生了一个好得多的分类器,其测试误差仅为 8.8%。这比单棵决策树好得多,并且与由 10 棵决策树组成的提升森林相当。

总结

本节课中我们一起学习了随机森林。我们看到的最后一种方法——随机森林,它实际上是两样东西的巧妙结合:决策树的表达能力,以及随机化算法的思想。最终,它是一种简单、易用且高性能的分类方法。

044:表征学习 🧠

在本节课中,我们将要学习表征学习。我们之前花费了大量时间讨论如何构建数据的预测模型,例如分类器、回归器和概率估计器。一直以来,我们都假设数据的表示——即特征、距离函数、相似度函数——是直接给定的且固定不变的。然而,实际情况通常并非如此。事实上,所有这些预测方法的有效性,都关键取决于是否拥有一个良好的数据表示。简而言之,良好的表征使学习变得更容易


为何需要良好表征?✨

上一节我们介绍了表征学习的重要性,本节中我们来看看良好表征之所以重要的具体原因。

良好表征能以多种方式、因多种原因提升学习效果。以下是其主要作用:

  • 揭示数据的真实自由度:它能够捕捉数据中固有的、本质的变化因素。
  • 捕捉多尺度结构:它能够识别数据在不同层次上的模式。
  • 筛选噪声并弱化无关特征:它有助于过滤干扰信息,并降低不相关特征的影响。

所有这些听起来都很棒,但它们具体意味着什么呢?例如,当我们谈论数据的“自由度”时,究竟指什么?让我们通过一个例子来更清晰地理解。


一个例子:语音信号 🎤

为了理解“揭示真实自由度”的含义,我们来看一个语音信号的例子。

这是一个一维时间序列的语音信号。当我说话时,会扰动嘴前的空气分子,从而传播声波。当这个声波到达你的耳朵时,耳内一个非常薄的鼓膜会响应这种扰动而振动。这里的信号,即这个一维信号,本质上就是该鼓膜的位移,也就是它振动的方式。

这是一个连续的一维时间序列。如果我们想在计算机上处理它(例如进行语音识别),就必须以某种方式将其数字化和离散化。这通常是如何做的呢?

以下是一种常见方法:

  1. 首先,将语音信号分割成一系列重叠的窗口,例如每个窗口25毫秒。
  2. 然后,对每个窗口应用一系列滤波器。每个滤波器会产生一个数值。
  3. 最后,将这些数值堆叠在一起,形成一个向量。

通过这种方式,一段连续的语音窗口就被转换成了某个高维欧几里得空间中的一个点。我们使用的滤波器越多,维度就越高,因此我们实际上可以得到一个超高维的表示。

然而,这其中存在一些迷惑性。毕竟,语音是由我的声道这个物理装置产生的,而这是一个只有少数几个自由度的物理系统。因此,存在一种方法,可以从这个由所有滤波器值拼接而成的高维表示中,恢复出潜在的自由度。也就是说,存在一种方式,可以从那个高维向量出发,对其进行简化或压缩,从而真正揭示出数据的底层结构。

能否做到这一点,关键取决于这些底层自由度与高维向量表示之间的关系:是线性关系、非线性函数,还是其他类型的编码?我们将在后续课程中探讨这些不同的可能性。


多尺度结构的重要性 🏗️

另一个表征学习的重要方面是,我们需要发现的结构通常存在于多个不同的尺度上。

例如,想象一下理解一张图像需要什么。其中存在一些非常低层次的结构,例如单个的边缘。然后,存在稍高层次的结构,例如一组边缘组合起来形成了一个熟悉的物体,如一扇窗户。这种将简单部分组合成稍复杂对象的“组合”过程,可以反复应用,从而产生越来越复杂的事物,如房屋、汽车、马匹等等。

因此,我们感兴趣的是具有这种多尺度特性的表征。


表征学习的目标与核心方法 🎯

在表征学习中,目标简而言之就是揭示数据中的结构。我们将重点关注某些关键类型的结构,特别是聚类结构线性投影

稍后,我们会将许多这类方法统一在自编码器的概念之下。自编码器的核心思想是学习一个能有效压缩并重建数据的表示,其基本结构可以表示为:
输入 -> 编码器 -> 潜在表示(编码) -> 解码器 -> 重建输出
学习的目标是最小化输入与重建输出之间的差异。


良好表征的用途 🔧

一旦学习到一个良好的表征,它就可以用于后续的预测建模,如分类、回归等。有时,我们心中可能没有特定的预测任务,而仅仅是希望更好地理解数据本身。

在课程的最后,我们将探讨如何将表征学习与分类器学习结合起来。而这,正是深度学习所致力实现的目标。


总结 📚

本节课中我们一起学习了表征学习的基础概念。我们了解到,数据的表示方式对机器学习模型的性能至关重要。良好的表征能够揭示数据的真实自由度、捕捉多尺度结构并过滤噪声。我们通过语音信号处理的例子具体理解了这些概念,并简要介绍了表征学习的目标、核心方法(如聚类、线性投影和自编码器)及其在预测任务和深度学习中的重要作用。接下来,我们将从第一种表征学习方法——聚类开始深入探讨。

045:使用K均值进行聚类 📊

在本节课中,我们将要学习表示学习中的第一个重要主题:聚类。我们将定义什么是聚类,并探讨其两种主要应用场景。随后,我们将介绍极其流行的K均值算法的成本函数及其对应的算法流程。

什么是聚类?🤔

在聚类任务中,我们被给定一组数据点,例如位于 R^D 空间中的点集。我们的任务是将它们进行聚类或分组。

例如,在这个数据集中,可能存在一个聚类在这里,另一个在那里。或者,在右侧可能实际上存在两个聚类:一个在这里,另一个在那里。这两种可能性看起来都完全合理。

聚类的两种主要用途 🎯

聚类主要有两种截然不同的应用方式。

第一种可以称为向量量化。在这种场景下,存在一个非常大(可能是无限或连续)的空间,数据是从这个空间中采样得到的。目标是找到该空间的少数几个代表点。

例如,这个空间可以是所有20毫秒语音录音的集合,这是一个连续且非常庞大的空间。我们想要的是这些声音片段的一个代表性子集。每当一个新的声音片段到来时,我们只需用其最接近的代表点来替换它。这是一种紧凑的编码声音片段的方式,是音频压缩的一种形式。

如果这是我们使用聚类的方式,那么衡量聚类质量的好方法是什么呢?很自然地,我们会通过用最接近的代表点替换原始点时所引入的失真量来衡量。

第二种主要用途是在数据中寻找有意义的组,即在数据集中发现自然的聚类。这通常出现在探索性数据分析中。

例如,假设一家超市正在收集其顾客的购买数据。是否存在一种对顾客进行聚类的方法,能够根据他们的购买模式创建出自然的人群分组?这可能非常有用。例如,如果超市要举行促销活动,它可以确保提供的折扣对每个足够大的聚类都具有吸引力。

这两种不同的聚类用途,在我们评估不同聚类算法时,需要牢记在心。

流行的聚类算法 🌟

聚类是一个重要问题,人们已经提出了大量不同的聚类算法。然而,事实证明,只有少数算法非常流行并被广泛使用。其中最重要的就是K均值算法,这也是我们今天要讨论的内容。后续我们还会学习其他一些流行算法,如EM算法(高斯混合模型)以及一些凝聚层次聚类算法。

K均值算法介绍 🧮

还记得我们讨论过聚类的两种用途吗?其中一种是向量量化。K均值算法似乎正是为这个目标量身定制的。

在这个优化问题的表述中,给定的是D维空间中的一组点(即待聚类的点)和一个整数K(即期望的聚类数量)。输出是一组代表点(聚类中心)μ_1μ_K,也就是D维空间中的K个点。

我们的目标本质上是考虑用每个点的最接近的代表点来替换它,从而最小化由此产生的失真。

更精确地形式化这个目标:我们希望找到一组中心点,使得每个点到其最近中心的平均距离最小。

让我们来看成本函数。与一组特定中心点 μ_1, ..., μ_K 相关的成本是:对所有数据点 x_i 求和。对于每个点 x_i,我们找到K个中心点中最近的那个(取最小值 min_j),成本就是到那个中心点的距离的平方。

公式:
Cost(μ_1, ..., μ_K) = Σ_i min_j ||x_i - μ_j||^2

因此,点 x_i 的“代价”是到最近中心点距离的平方。我们希望最小化这种代价的平均值或总和。这是一个非常针对向量量化的表述。

这是一个包含10个点的示例数据集,假设我们想要两个聚类。聚类中心可能放在哪里呢?这里有一个可能的放置位置。如果我们把中心放在那里,本质上就是说平面上的每个点都将被分配到其最近的中心。这将把平面划分成不同的区域。在这种情况下,K均值成本就是这10个点到各自中心距离的平方和。

更一般地,在 R^D 空间中,有K个中心。我们将每个点分配给其最近的中心,这最终将D维空间划分为K个区域。事实证明,每个这样的区域都将是一个凸区域,通常被称为Voronoi单元。这就是K均值优化问题。

寻找解决方案:Lloyd算法(K均值算法) 🔄

坏消息是,这个优化问题是NP难的。这意味着没有高效的算法能保证总是找到最优解。因此,我们必须寻找启发式方法。

最流行的启发式方法,也是有史以来最流行的聚类算法,就是Lloyd算法,通常直接被称为K均值算法。这是一个非常简单的算法,本质上是一个局部搜索或爬山算法。

算法的目标是找到K个中心点。它首先以某种方式初始化K个中心点(通常是从数据点中随机选取K个)。然后,它通过不断微调这些中心点来降低成本,直到收敛。

具体步骤如下:

  1. 初始化:以某种方式初始化K个中心点(例如,随机选择K个数据点)。
  2. 主循环(迭代改进)
    • 分配步骤:将每个数据点分配给距离它最近的中心点。
    • 更新步骤:将每个中心点移动到所有分配给它的点的均值位置。

让我们看一个运行示例。我们有一个包含10个点的数据集。假设我们随机选取了三个点作为初始中心。然后开始主循环:

  • 第一次迭代:将每个点分配给最近的中心,空间被划分。然后,将每个中心移动到分配给它的所有点的均值位置。这通常会改善中心点的位置。
  • 第二次迭代:再次根据新的中心点进行分配,然后更新中心点位置。
  • 持续迭代,直到中心点位置不再改变(或变化极小),算法收敛。

这是一个非常简单的算法。关于它,我们能说些什么呢?它总能找到K均值成本函数的最优解吗?不,不能。考虑到这是一个NP难问题,我们不会期望它做到。但我们可以肯定的是,在每一次连续的迭代中,成本都保证会下降。最终,算法会停止在某个局部最优解上(通常不是全局最优解)。

初始化的重要性 🎲

我们已经完整地描述了算法,但有一件事尚未明确指定:初始化方法。事实证明,正确初始化非常重要。

让我们看一个小例子。这里有一个大约16个点的数据集,我们尝试两种不同的初始化方式,并观察最终的K均值聚类结果。

  • 初始化一:随机选取三个点作为初始中心。运行K均值后,得到一种聚类结果。
  • 初始化二:随机选取另外三个点作为初始中心。运行K均值后,得到另一种截然不同的聚类结果。

哪种答案更好呢?无论如何,这清楚地表明,良好地初始化算法非常重要。

常见的初始化方法 📝

以下是几种常见的初始化方法:

  1. 随机选择:迄今为止最常见的做法是简单地从数据点中随机选取K个点作为初始中心。
  2. 过采样后剪枝:如果你想要10个聚类,可以从20个中心开始(过采样)。运行几轮K均值后,剔除掉10个中心(例如,剔除那些只有很少点分配给它,或者离其他中心非常近的中心),然后继续运行K均值直到收敛。
  3. K-means++ 算法:这是一种非常好的初始化方法。其核心思想是逐个选取初始中心点,并倾向于选择距离已选中心点较远的点。
    • 首先,随机选择一个数据点作为第一个中心 μ_1
    • 然后选择第二个中心 μ_2:从数据集中随机选取,但选取点 x 的概率与其到 μ_1 的距离平方成正比(距离越远,被选中的概率越高)。
    • 选择第三个中心 μ_3:同样随机选取,但此时倾向于选择距离 μ_1μ_2 都较远的点。
    • 以此类推,直到选出所有K个中心。

代码描述(K-means++ 核心思想):

# 伪代码描述 K-means++ 初始化
centers = []
# 1. 随机选择第一个中心
centers.append(random.choice(data_points))

for i in range(1, K):
    # 计算每个点到已选中心的最短距离平方
    distances = [min([distance(x, c)**2 for c in centers]) for x in data_points]
    # 根据距离平方作为权重,随机选择下一个中心
    probabilities = distances / sum(distances)
    next_center = random.choices(data_points, weights=probabilities)[0]
    centers.append(next_center)

K-means++ 初始化方法在实践中被证明非常有效。

总结 📚

本节课中,我们一起学习了聚类的基本概念及其两种主要应用:向量量化和发现数据中的自然分组。我们重点介绍了最流行的K均值算法,包括其针对向量量化设计的成本函数 Σ_i min_j ||x_i - μ_j||^2,以及Lloyd算法的具体步骤(分配和更新)。我们还探讨了初始化对K均值结果的重要影响,并介绍了几种初始化方法,特别是效果良好的K-means++算法。

下一节课,我们将更深入地探讨K均值,看几个实际应用案例,并了解一些针对海量数据集的K均值变体。

046:基于K均值的聚类 📊

在本节课中,我们将继续学习K均值聚类算法。我们将探讨该算法的两种截然不同的应用场景,了解一种适用于海量数据集的算法变体,并总结K均值算法的优缺点。


上一节我们介绍了K均值算法的基本流程,本节中我们来看看它的具体应用。

K均值算法(Lloyd‘s K-means algorithm)是一种局部搜索过程。它首先以某种方式初始化K个中心点,然后进入一个循环,迭代地改进这些中心点直至收敛。

以下是K均值聚类的两种主要用途:

  1. 向量量化:目标是在一个大的、连续的、甚至是无限的空间中,找到一小部分代表点,以最小化这种离散化带来的失真。
  2. 发现自然分组:目标是在数据中发现有意义的组或“自然”的簇。

应用一:图像表示与向量量化 🖼️

首先,我们来看K均值在向量量化中的应用,具体以图像表示为例。

一个核心问题是:如何将尺寸各异的图像表示为固定长度的向量?计算机视觉领域提出了多种解决方案,其中许多方案思路相似。这里介绍一种基于K均值聚类的方法。

方法步骤如下:

  1. 从每张图片中提取大量固定尺寸的小图像块(例如10x10像素)。
  2. 将所有图片的所有图像块汇集起来,形成一个庞大的图像块集合。
  3. 对这个集合应用K均值聚类。例如,设定K=1000,算法会从数百万个图像块中找出1000个最具代表性的图像块。
  4. 对于一张新图片中的每一个图像块,找到这1000个代表中与之最接近的一个,并用该代表的编号来代表这个图像块。
  5. 统计整张图片中,每个代表图像块出现的频率(即图片中有多少比例的图像块被分配给了某个代表)。
  6. 最终,整张图片被表示为一个1000维的向量,每个维度代表一个特定图像块出现的概率,所有维度的值之和为1。

这种表示方法在许多视觉应用中都被证明非常有效。


应用二:发现数据中的自然分组 🐾

接下来,我们看看K均值在发现数据自然分组中的应用。这里使用一个名为“Animals with attributes”的数据集,它包含50种动物(如羚羊、灰熊、斑点狗等),每种动物用85个特征描述(如栖息地、食性、外貌等)。因此,数据集是85维空间中的50个点。

我们对这个数据集运行K均值聚类,设定K=10以寻找10个簇。由于K均值对初始化敏感,每次运行可能得到不同结果。以下是两次独立运行的结果示例:

第一次运行结果:

  • 簇2:蜘蛛猴、大猩猩、黑猩猩(合理,灵长类动物)。
  • 簇5:虎鲸、蓝鲸、座头鲸(合理,水生动物)。
  • 簇3:老虎、豹、狼、山猫、狮子(合理,大型猫科/捕食者)。
  • 簇10:灰熊、北极熊、暹罗猫、波斯猫(部分合理,但混入了猫,显得不协调)。

第二次运行结果:

  • 许多簇与第一次相同(如簇2、簇5)。
  • 簇10:灰熊、北极熊(更合理)。
  • 暹罗猫和波斯猫这次与大熊猫分到了一组。

由此可见,K均值得到的结果是混合的:一些簇能很好地反映数据中有意义的自然分组,而另一些则可能不尽如人意。这在聚类分析中是非常常见的情况。


处理海量数据:在线/流式K均值 ⚡

在实际应用中,我们经常需要处理极其庞大的数据集(例如之前图像例子中数亿个图像块)。当数据量大到无法全部装入内存时,该怎么办?

计算领域发展出了适用于此类场景的模型,例如流式计算模型在线计算模型

  • 流式计算:数据量巨大,存储在磁盘上。算法只能对数据进行少量几轮扫描,且只能存储其中一小部分。
  • 在线计算:数据持续不断产生,每个数据点只出现一次,看过即消失,算法只能用有限的内存进行更新。

那么,能否在这些模型下进行K均值聚类呢?答案是肯定的。序列化K均值(Sequential K-means)就是一种适用于此类模型的变体。

算法步骤如下:

  1. 初始化:将前K个到达的数据点直接作为初始的K个中心点 μ1, μ2, ..., μK,并将每个中心点对应的计数 n1, n2, ..., nK 设为1。
  2. 迭代更新:对于之后到达的每一个新数据点 x
    • 找到与 x 最近的中心点 μj
    • 更新该中心点的计数:nj = nj + 1
    • 更新该中心点的位置,将其向 x 方向略微移动(即用 x 来平均更新 μj)。更新公式可以表示为:
      μj(new) = μj(old) + (1/nj) * (x - μj(old))
      这等价于用所有已分配给该中心点的数据点重新计算均值,但无需存储所有历史数据。

这是一种非常轻量级的K均值变体,能够轻松应对海量数据流。


K均值算法的优缺点总结 ⚖️

我们花了大量时间讨论K均值,因为它是一个非常重要且流行的算法。现在我们来总结一下它的优缺点。

优点:

  • 算法简单,运行速度快
  • 对于向量量化这类应用,其成本函数(最小化点到其最近中心点的平方距离和)非常合理且直接。

缺点:

  • 当目标是发现数据中的自然簇时,K均值倾向于寻找特定类型的簇:球形尺寸大致相同的簇。对于其他形状(如带状、嵌套状)或尺寸差异大的簇,其效果可能不理想。

因此,我们希望能找到其他同样简单但能识别更通用簇类型的算法,这将是我们后续课程的内容。


本节课中,我们一起深入探讨了K均值聚类算法。我们学习了它的两种主要应用场景(向量量化和发现分组),了解了如何通过序列化变体应对海量数据,并分析了该算法的优势与局限。接下来,我们将继续学习其他关键的聚类方案。

047:基于高斯混合模型的聚类 📊

在本节课中,我们将学习一种不同于K均值聚类的算法——期望最大化(EM)算法。该算法基于高斯分布,能够处理更一般形状和大小的数据簇。我们将从介绍高斯混合模型开始,形式化聚类问题的优化目标,并学习通过EM算法这一简单的局部搜索方法来解决它。最后,我们将通过实例来观察其效果。

从K均值到高斯混合模型

上一节我们介绍了K均值聚类算法。它虽然简单有效,但在处理大小不一或非球形簇时存在局限。本节中,我们来看看另一种同样流行但能适应更广泛簇形状的算法——EM算法。

EM算法基于高斯分布。因此,我们首先需要引入高斯混合模型。这是一种为包含簇的数据生成模型。

高斯混合模型:形式化定义

高斯混合模型的核心思想是:我们有一组数据点,希望将其聚类。在聚类后,我们为每个簇拟合一个高斯分布。

最终,我们将得到K个簇。每个簇由一个高斯分布 ( P_j ) 描述,其中 ( j = 1, 2, ..., K )。在D维空间中,第j个簇的高斯分布由其均值向量 ( \mu_j )(一个D维向量)和其协方差矩阵 ( \Sigma_j )(一个D×D矩阵)指定。这些参数描述了该簇的数据分布密度。

此外,我们还会为每个簇记录一个混合权重 ( \pi_j ),它表示数据中来自该簇的比例。例如,如果所有簇大小相近,那么 ( \pi_1, \pi_2, \pi_3, \pi_4 ) 都大约为0.25。

通过组合这些簇的密度,我们得到一个覆盖整个数据空间的高斯混合分布。该分布对任意点 ( \mathbf{x} ) 赋予的密度为:
[
P(\mathbf{x}) = \sum_{j=1}^{K} \pi_j \cdot P_j(\mathbf{x})
]
这个公式的含义是:点 ( \mathbf{x} ) 的概率取决于它来自哪个簇。我们对所有可能的簇求和,其中“来自簇j的概率”是 ( \pi_j ),而“在簇j中观察到点 ( \mathbf{x} ) 的概率”是 ( P_j(\mathbf{x}) )。

最大似然估计与优化问题

我们的目标是用高斯混合模型拟合数据。假设我们有N个D维数据点 ( \mathbf{x}_1, ..., \mathbf{x}_N )。拟合过程结束后,我们将得到一组参数:混合权重 ( \pi_1, ..., \pi_K ),以及K个高斯分布的均值 ( \mu_j ) 和协方差矩阵 ( \Sigma_j )。

我们希望找到能使观测数据似然性最大的参数。数据在混合模型下的概率(似然)是每个数据点概率的乘积:
[
\mathcal{L} = \prod_{i=1}^{N} P(\mathbf{x}i) = \prod^{N} \left( \sum_{j=1}^{K} \pi_j \cdot \mathcal{N}(\mathbf{x}_i | \mu_j, \Sigma_j) \right)
]
其中 ( \mathcal{N} ) 表示高斯密度函数。

最大化该似然等价于最大化其对数,也等价于最小化其负对数似然(我们的损失函数):
[
\mathcal{L}{\text{loss}} = -\sum^{N} \log \left( \sum_{j=1}^{K} \pi_j \cdot \mathcal{N}(\mathbf{x}_i | \mu_j, \Sigma_j) \right)
]
我们的优化目标是找到参数 ( {\pi_j, \mu_j, \Sigma_j} ) 来最小化这个损失函数。

然而,这个损失函数不是凸函数,其表面存在许多局部最优解,找到全局最优解是NP难问题。因此,我们采用局部搜索策略。

EM算法:期望最大化

EM算法就是一种局部搜索过程。它从一个初始的参数猜测开始,然后通过迭代逐步改进。

以下是EM算法的步骤概述:

  1. 初始化参数:随机选择K个数据点作为初始均值 ( \mu_j ),将混合权重 ( \pi_j ) 初始化为 ( 1/K ),并将所有协方差矩阵 ( \Sigma_j ) 初始化为整个数据集的协方差矩阵。
  2. 迭代改进(主循环)
    • E步(期望步):基于当前的高斯分布参数,计算每个数据点 ( \mathbf{x}i ) 属于每个簇j的“责任”或权重 ( w )。
      [
      w_{ij} = \frac{\pi_j \cdot \mathcal{N}(\mathbf{x}i | \mu_j, \Sigma_j)}{\sum^{K} \pi_l \cdot \mathcal{N}(\mathbf{x}_i | \mu_l, \Sigma_l)}
      ]
      这相当于一个“软分配”,数据点以一定的概率权重属于所有簇,而不是硬性分配到单一簇。
    • M步(最大化步):基于E步计算出的权重 ( w_{ij} ),更新所有参数,以最大化数据的期望似然。
      • 更新混合权重:新的 ( \pi_j ) 是数据点属于簇j的平均权重。
        [
        \pi_j^{\text{new}} = \frac{1}{N} \sum_{i=1}^{N} w_{ij}
        ]
      • 更新均值:新的 ( \mu_j ) 是所有数据点的加权平均,权重为 ( w_{ij} )。
        [
        \mu_j^{\text{new}} = \frac{\sum_{i=1}^{N} w_{ij} \mathbf{x}i}{\sum^{N} w_{ij}}
        ]
      • 更新协方差矩阵:新的 ( \Sigma_j ) 是基于加权数据的协方差估计。
        [
        \Sigma_j^{\text{new}} = \frac{\sum_{i=1}^{N} w_{ij} (\mathbf{x}i - \mu_j^{\text{new}})(\mathbf{x}i - \mu_j{\text{new}})T}{\sum^{N} w{ij}}
        ]
  3. 重复E步和M步,直到参数收敛(变化很小)。

算法对比与示例

为了理解EM算法的优势,我们来看一个包含三个不同形状和大小簇的二维玩具数据集示例。

以下是使用不同方法的结果:

  • K均值聚类:由于K均值假设球形簇且对初始化敏感,多次运行可能得到不同且不理想的聚类结果(例如,错误地将不同大小的簇切分或合并)。
  • EM算法(高斯混合模型):EM算法能够一致地找到我们预期的三个簇。这是因为它通过高斯分布显式地建模了每个簇的形状(协方差矩阵)和大小(混合权重),从而能够适应椭圆形和大小不一的簇。

总结

本节课中,我们一起学习了基于高斯混合模型(GMM)的聚类方法。我们首先形式化了将数据建模为多个高斯分布混合的优化问题,即最大化数据的似然。由于该问题非凸且复杂,我们引入了期望最大化(EM)算法作为一种有效的局部搜索解决方案。EM算法通过交替执行E步(软分配数据点)和M步(更新模型参数)来迭代优化模型。与K均值相比,GMM通过协方差矩阵能够捕捉簇的椭圆形状,通过混合权重适应不同簇的大小,因而在处理更复杂结构的数据时更具灵活性。下一节,我们将转向另一种完全不同的聚类方法,旨在发现数据中的层次结构。

048:层次聚类 🌳

在本节课中,我们将要学习层次聚类。这是一种能够同时捕捉数据中多个尺度结构的聚类方法。

概述

之前我们主要讨论了K均值和EM这两种聚类算法。它们都属于“扁平聚类”,即它们发现的簇都处于单一尺度。然而,当我们介绍表示学习时,我们强调了所寻找的结构通常存在于多个不同的尺度中。层次聚类正是聚类的多尺度版本,这就是我们今天要探讨的内容。

我们将首先介绍层次聚类的概念,然后继续了解几种寻找此类聚类的流行算法。

什么是层次聚类?

让我们回顾一下这个数据集。这里有多少个簇?左边显然有一个簇。右边是一个簇,还是两个簇?这很难判断。事实上,并没有唯一正确的答案,两种选择都完全合理。真实数据通常以这种方式呈现,经常在多个不同层次上存在簇结构,而层次聚类让我们能够同时捕捉所有这些不同的层次。

层次聚类通常被描绘成一棵树。在顶部,有一个单一的节点,这是一个包含所有数据点的簇。在本例中,它会分裂成两个簇:左边的簇和右边的簇。右边的簇会再次分裂成两个。现在,左边的簇可能包含八个数据点,右边的两个簇各包含大约六个点。这棵树中叶子的总数正好等于数据点的数量,即20个。因此,这棵树捕捉了数据中完整的簇结构层次。

层次聚类的例子

动物属性数据集

还记得“动物属性”数据集吗?这个数据集包含50种不同动物的信息,每种动物有85个特征,因此一个动物由一个85维向量表示。这里有50个数据点。

我使用了一种称为“平均链接”的标准算法对这些数据点进行了层次聚类。结果返回了一棵有50片叶子的树。让我们看看其中的一些簇。

例如,这里有一个红色的簇,包含海豚、海豹、虎鲸、海象、座头鲸、蓝鲸、水獭和海狸。这看起来相当合理,都是生活在海里、河里或靠近河流的动物。该簇的第一次分裂产生了两个子簇:一个是水獭和海狸的小簇,另一个是包含所有鲸鱼和海豚的较大簇,这也是非常合理的划分方式。

再看一个大的绿色簇,其中包含一个由黑猩猩、蜘蛛猴和大猩猩组成的子簇,都是灵长类动物,非常合理。另一个分支包含斑点狗、德国牧羊犬、柯利牧羊犬、吉娃娃、波斯猫和暹罗猫,基本上是家养宠物,也很合理。还有一个簇包含狮子、老虎、山猫和豹子等猫科动物。

整个结果看起来相当合理,并且我们只是通过对动物数据运行层次聚类算法就自动找到了它。

基因表达分析

层次聚类在基因表达分析领域也相当流行。在这个例子中,纵轴代表不同的基因,横轴代表不同的样本(例如来自不同的病人)。每个像素的颜色表示该基因在特定病人样本中的表达强度。

当涉及数千个基因时,数据会变得非常高维。理解和简化数据的一个好方法是应用层次聚类。图中纵轴显示的是基因的层次聚类结果,其获取方式是将每一行(代表一个基因)视为一个数据点,然后对它们应用层次聚类算法(如平均链接),得到这棵树。

例如,观察顶部的一个簇,它可能由五六个基因组成。这些基因倾向于协同作用,要么都低表达,要么都高表达,它们似乎作为一个单元在运作。这是理解数据的一种非常好的方式:从数量庞大的基因开始,层次聚类为你找到这些基因簇,即那些真正作为一个单元协同作用的基因组,这减少了你需要思考的不同事物的数量。

通常也会对病人进行聚类。做法是取相同的数据矩阵,将每一列视为一个数据点,然后对这些点应用层次聚类。这样做的原因在于,结果往往很有趣。例如,有时你认为所有病人都患有同一种疾病,但当你对这些列进行层次聚类时,你可能会发现实际上存在两个截然不同的群体。这可能表明这种疾病实际上存在两种亚型,也许这两组病人需要不同的治疗方法。

如何进行层次聚类?

单链接算法

让我们从单链接算法开始,它可能是层次聚类方法中最简单的一种。虽然它不是最好的算法(我们很快就会看到更好的替代方案),但因为它描述起来相当简单,所以很有用。

它是如何工作的?假设我们有10个数据点。单链接以自底向上的方式工作。我们首先将这10个点视为独立的簇,即树底部的叶子。然后我们合并最接近的两个点,接着合并下一对最接近的点,依此类推,以自底向上的方式构建树。

具体步骤如下:

  1. 从10个簇开始。
  2. 合并最接近的两个点(例如点4和点5),现在剩下9个簇。
  3. 合并下一对最接近的点(例如点6和点7),剩下8个簇。
  4. 继续此过程,每次合并当前阶段距离最近的两个簇,直到所有点合并为一个簇。

从合并历史中可以轻松恢复出树状结构。第一次合并的是点4和5,然后是点6和7,接着是点2和3,之后将点1加入由点2和3组成的簇,再合并点8和9,最后将点10加入。这样就形成了最终的层次聚类树。

不同的链接方法

存在多种链接方法用于层次聚类,它们的基本流程大致相同。它们都以自底向上的方式工作:从每个点作为自己的簇开始,然后合并最接近的两个簇,接着合并下一对最接近的簇,依此类推。在任何给定阶段,你都有一些簇,你需要连接距离最近的两个簇。

如何衡量两个簇之间的距离?这是唯一剩下的自由度,而这个特定的选择造成了所有差异。不同的链接方法正是通过定义两个簇之间距离的方式而有所不同。在每一阶段,我们计算这些距离,然后合并距离最小(即最接近)的那对簇。

以下是几种主要的链接方法:

  • 单链接:定义两个簇 CC‘ 之间的距离为两个簇中最近点对之间的距离。公式上,可以表示为:
    distance(C, C') = min_{x in C, y in C'} ||x - y||
    这本质上是两个簇之间可能的最小距离概念。

  • 完全链接:这是另一个极端。它定义两个簇之间的距离为两个簇中最远点对之间的距离。公式上,可以表示为:
    distance(C, C') = max_{x in C, y in C'} ||x - y||
    可以想象,完全链接倾向于产生相当紧密、相当紧凑的簇。

  • 平均链接:这是最流行的链接方法之一,它采取了一种中间立场。它不只看最近对或最远对,而是看两个簇之间的平均距离。具体定义平均距离的方式有多种,都很合理,这导致了不同的平均链接算法。

以下是三种常见的定义方式:

  1. 所有点对平均:查看两个簇中所有点对(一个来自左簇,一个来自右簇)的距离,然后取这些距离的平均值。如果左簇有 m 个点,右簇有 n 个点,则查看 m * n 对,并取平均距离。
    distance(C, C') = (1/(|C|*|C'|)) * sum_{x in C} sum_{y in C'} ||x - y||

  2. 质心距离:只查看两个簇的质心(均值),然后测量质心之间的距离。公式为:
    distance(C, C') = ||mean(C) - mean(C')||

  3. Ward方法:这种方法也属于一种平均概念,但它关注的是合并两个簇所带来的K均值成本的增加。具体来说,计算合并前两个簇各自的K均值成本(点到其簇质心的平方距离和)与合并后新簇的K均值成本之间的差值,将这个差值作为距离。公式简化为类似质心距离的形式,但前面有一个与簇大小(包含的点数)相关的因子,这意味着它更倾向于合并点数较少的簇。
    distance(C, C') = sqrt( (2*|C|*|C'|) / (|C|+|C'|) ) * ||mean(C) - mean(C')||

总结

本节课中,我们一起学习了层次聚类。我们了解到层次聚类是一种能够揭示数据中多尺度结构的强大工具,它通过树状图来展示簇的嵌套关系。我们探讨了层次聚类的应用实例,如动物分类和基因表达分析。最后,我们详细介绍了实现层次聚类的几种链接算法,包括单链接、完全链接以及不同形式的平均链接(特别是Ward方法),理解了它们通过不同方式定义簇间距离来影响最终的聚类结果。

下次课,我们将探讨一种完全不同的表示学习形式:投影。

049:线性投影 📐

在本节课中,我们将要学习一种非常有效的表示学习方法——线性投影。我们将从讨论降维开始,然后探讨两种不同的降维思路:选择信息丰富的坐标与选择信息丰富的方向。

降维的必要性

当我们面对一个非常高维的数据集时,一个很自然的问题是:维度真的需要这么高吗?是否存在某种方法,可以在保留数据中全部或绝大部分信息的同时,降低其维度?

如果能实现这种降维,将带来诸多好处:

  • 计算与存储效率:更低的维度意味着更快的计算速度,更重要的是,更小的内存需求。
  • 减少冗余:高维数据通常包含大量冗余。例如,在基因表达分析中,经常有成组的基因作为一个单元共同作用。我们真的需要为它们每一个都设置单独的特征吗?还是可以将它们组合成一个单一的组特征?
  • 剔除噪声:降维是剔除无关或噪声特征的绝佳机会。例如,在查看某人的医疗记录以评估其患病风险时,其中的社会安全号码等信息就是纯粹的噪声,应该被丢弃。

降维方法一:选择信息丰富的坐标

那么,我们如何进行降维呢?让我们从一个简单的例子开始。

这是一张来自MNIST数据集的数字图片。这些图像都是28x28像素,因此可以表示为一个784维的向量(将第一行像素、第二行像素等依次排列而成)。

这个维度必须是784吗?我们能否以某种方式降低它?我们当然可以丢弃一些像素。例如,四个角落的像素几乎总是关闭的,不包含信息。这样,我们就将维度从784降到了780。虽然降幅不大,但这是一个开始。

在我们过于兴奋之前,应该退一步思考一下我们刚才做了什么。为什么我们可以丢弃这些像素?因为它们总是具有相同的值,这意味着它们的方差为零。这给了我们一个启示:如果我们想丢弃更多坐标(像素),为什么不选择方差最低、信息量最少的那些呢?

下图展示了当你这样做时会发生什么。让我们来解释一下。

如果我们查看所有784个坐标(即完整表示),其总方差就是每个像素方差的总和。公式表示为:

总方差 = Σ (像素 i 的方差),其中 i 对所有坐标求和。

这张图显示的是,当你丢弃一些方差最低的坐标时,会损失多少总方差。例如,假设我们丢弃方差最低的600个坐标,我们会损失大约40%的总方差。

有趣的是,我们可以丢弃300到400个像素,而在此过程中几乎不损失任何方差。这很棒,我们可以轻松地将维度从约800降到约400。然而,事实证明我们可以做得比这好得多,实际上可以将维度降到更接近50甚至更少的水平。但要做到这一点,我们需要一种更通用的投影概念。

降维方法二:选择信息丰富的方向

为了解释这一点,让我们看看这个二维数据集。它有两个特征,x1 和 x2,沿着这两个方向都有相当大的方差,因此我们自然不会倾向于丢弃其中任何一个。

但如果你观察这些数据,会发现两个特征之间存在很强的相关性。问题是,有没有办法利用这种相关性,将它们简化为一个数字而不是两个?答案是肯定的,方法就是投影到图中所示的红色方向上。

这种投影意味着什么?以这个点为例,我们将它投影到红线上,得到这个值。我们用这个距离(一个数字)替换了原来的二维点。同样地,对于这个点,我们将其投影到线上(即找到线上最近的点,这意味着必须以直角与线相交),并用这个长度替换它。

通过这种方式,数据集被压缩到了一维。由于这些点大体上都靠近这条线,因此在这个过程中没有损失太多信息。那么,这条红线到底是什么方向?事实证明,这是方差最大的方向。这是什么意思呢?

理解投影与方差

一旦我们不再局限于坐标轴,就有无限多个方向可以投影。我们可以投影到这个方向,也可以投影到那个方向,等等。

假设我们投影到x1轴方向。那么,一个点 (x1, x2) 就被映射到它的第一个坐标 x1。投影数据的方差就是 x1 的方差。

假设我们投影到x2轴方向。那么,点 (x1, x2) 就被映射到 x2。投影数据的方差就是 x2 的方差。

但我们没有理由将自己限制在坐标轴投影上。我们也可以投影到另一个方向,比如这样。如果我们投影到任意一个这样的方向,那么点 (x1, x2) 将被映射为 x1 和 x2 的某个线性组合,即映射为 ax1 + bx2 这种形式的单个数字,其中 a 和 b 是常数。

同样,我们得到一个一维值,并且可以讨论这些数字的方差。我们想要找到的是,沿着哪个方向,这些投影数据能获得可能的最大方差。这可以很容易地求解,但在深入之前,我们需要从数学上形式化投影的确切含义。

投影的数学定义

我们想要投影到某个方向,比如这个方向。这个特定向量的长度并不重要,因此投影到这个方向与投影到那个方向是相同的。为了方便起见,我们通常将其归一化为单位长度。因此,当我们投影到某个方向时,我们用一个单位向量(长度为1的向量)来表示该方向。

例如,假设我们想投影到方向 (3, 4)。这是一个单位向量吗?它的长度是 sqrt(3² + 4²) = 5,不是单位向量。为了使其成为单位向量,我们只需除以长度,使用 (3/5, 4/5)。这就是我们要投影到的方向。

那么,如何进行投影呢?现在我们有一个要投影到的方向 u。一个点 x 在该方向上的投影是什么?它简单地就是 xu 的点积。公式为:

投影值 = x · u = u · x = uᵀx = xᵀu

这个长度就是 x · u。为什么?解释起来其实很简单。让我们看看这个角度,称之为 θ。根据三角学,投影长度是 x 的长度乘以该角度的余弦值。当我们第一次讨论点积时,我们了解到点积实际上给出了两个向量之间的角度。公式为:

cos(θ) = (x · u) / (||x|| * ||u||)

由于 u 是单位向量,其长度为1,因此公式简化为 投影值 = ||x|| * cos(θ) = x · u。所以,投影就是点积。

让我们看几个例子。这里有一个向量 x = (2, 3),我们想把它投影到两个不同的方向上。

  1. 投影到 x1 轴方向,即方向 (1, 0)。投影值就是点积 (2,3)·(1,0) = 2。正如我们所料。
  2. 投影到方向 (1, -1)。首先需要确保它是单位向量。其长度为 sqrt(1² + (-1)²) = √2。为了使其成为单位向量,我们除以它的长度,得到 u = (1/√2, -1/√2)。现在计算点积:(2,3)·(1/√2, -1/√2) = (2-3)/√2 = -1/√2。答案就是 -1/√2。

总结

本节课中,我们一起学习了线性投影的基础知识。我们首先探讨了降维的必要性和好处,然后介绍了两种降维思路:通过丢弃低方差坐标来降维,以及通过将数据投影到特定方向(如方差最大的方向)来更有效地降维。我们正式引入了投影的数学概念,并发现它本质上就是向量的点积运算。

下一节课,我们将在此基础上,学习如何找到数据方差最大的方向。

050:主成分分析 I - 寻找最大方差方向 🔍

在本节课中,我们将要学习主成分分析(PCA)的核心思想:如何为数据找到一个最佳的投影方向,使得投影后的数据方差最大。方差越大,意味着数据在该方向上包含的信息量越多。

上一节我们介绍了投影的基本概念,本节中我们来看看如何找到这个“最佳”方向。

投影的方差公式 📐

假设我们有一个D维数据集,我们希望将其映射(投影)到一维空间。我们需要找到一个单位向量 u,数据点 x 在该方向上的投影值就是点积 u · x。我们的目标是找到那个能让投影数据方差最大的方向 u

那么,如何计算在任意方向 u 上的投影方差呢?有一个非常简洁的公式。

核心公式:如果数据 x 的协方差矩阵是 Σ,那么在方向 u 上的投影方差为:
方差 = u^T Σ u

这个公式虽然抽象,但非常强大。接下来,我们通过一个具体例子来理解它。

一个二维示例 📈

考虑一个熟悉的二维数据集,其协方差矩阵 Σ 是一个2x2的对称矩阵:

Σ = [ 1.0,  0.85
      0.85, 1.0 ]

矩阵对角线上的元素(1.0)分别是特征x1和x2各自的方差。非对角线元素(0.85)是x1和x2的协方差,表示这两个特征之间存在正相关关系。

现在,让我们使用公式计算在不同投影方向上的方差。

以下是几个投影方向的尝试:

  • 投影到x1轴:方向向量 u = [1, 0]。计算方差:[1, 0] Σ [1, 0]^T = 1.0。这正是x1本身的方差。
  • 投影到x2轴:方向向量 u = [0, 1]。计算方差同样为 1.0
  • 投影到对角线方向:方向向量 u = [1/√2, 1/√2](这是一个单位向量)。计算方差:[1/√2, 1/√2] Σ [1/√2, 1/√2]^T = 1.85

可以看到,投影到对角线方向([1, 1]方向)时,数据的方差(1.85)远大于投影到坐标轴方向(1.0)。这确实是一个更优的投影方向。

如何找到最大方差方向? 🎯

现在回到一般情况。我们的目标是最大化投影方差 u^T Σ u。如何找到这个使方差最大化的方向 u 呢?

答案非常简单:这个最优方向就是协方差矩阵 Σ 的第一个(或称为“主”)特征向量

那么,什么是特征向量?这是一个在机器学习中极其重要的概念。简单来说,对于一个像协方差矩阵这样性质良好(对称、半正定)的方阵,存在一组特殊的向量(特征向量)和对应的值(特征值)。特征向量指示了矩阵作用的“特殊方向”,而特征值则描述了矩阵在该方向上的“拉伸”程度。

目前,你只需要记住两点:

  1. 最大方差方向就是 Σ 的最大特征值所对应的特征向量。
  2. 在实际操作中,我们可以轻松地通过计算工具(如Python的NumPy库)来获得协方差矩阵的特征向量和特征值。

回到我们的二维例子,图中红色的箭头方向正是协方差矩阵 Σ 的第一个特征向量方向,也就是数据方差最大的方向。将数据投影到这个方向上,就得到了数据的第一主成分。这就是主成分分析(PCA)最基础的形式。

总结与预告 📚

本节课中我们一起学习了主成分分析的第一步:如何为数据寻找一个最佳的投影方向以最大化方差。我们掌握了计算任意方向投影方差的公式 u^T Σ u,并了解到最大方差方向就是数据协方差矩阵的主特征向量。

今天我们看到的是投影到单个方向(一维)的情况。下一次,我们将把这个概念推广开来,探讨如果我们想将数据投影到K个方向上(降维到K维),应该如何设置这些方向。

051:主成分分析 II

在本节课中,我们将学习如何将高维数据投影到多个方向上,以进行有效的降维。我们将介绍多方向投影的定义、最优解(即主成分分析),以及如何从降维后的数据重建原始数据。

上一节我们讨论了将数据集投影到单一最佳方向上的方法。本节中,我们来看看如何投影到多个方向上。

多方向投影的定义

首先,我们需要定义将数据投影到多个方向上的含义。

假设我们选择了K个不同的方向,记作 U1UK。投影的含义在这些方向满足特定属性时最容易理解,特别是当它们是标准正交的时候。这意味着两点:首先,所有方向向量的长度均为1;其次,它们彼此正交,即点积为零。

如果满足这些条件,投影就非常简单。一个点 x 在这K个方向上的投影就是K个数字:第一个数字是 xU1 方向上的投影(即 x · U1),第二个数字是 x · U2,依此类推,直到最后一个数字 x · UK

我们也可以用矩阵形式表示。将这K个方向向量作为列向量组合成一个矩阵 U。那么,x 的投影就是 U^T x(即 U 的转置乘以 x)。这样,一个原本在D维空间中的向量就被投影到了K维空间。

最优投影:主成分分析

接下来,我们探讨如何找到最优的投影方向。

与寻找单一最佳方向类似,最优的多方向投影也由数据的协方差矩阵的特征向量给出。我们有一个D维数据集,其协方差矩阵是一个 D × D 的矩阵。这个矩阵有一组对应的特征向量,这些是与之相关的特殊方向。

最优解非常简单:我们只需投影到前K个特征向量上。这个过程被称为主成分分析

具体步骤如下:

  1. 计算数据集的协方差矩阵。
  2. 使用工具(如Python)计算该协方差矩阵的所有特征向量。
  3. 选取特征值最大的前K个特征向量,记作 U1UK
  4. 数据的投影即为与这些向量的点积:U^T x

为了直观理解其效果,让我们看一个MNIST手写数字数据集的例子。该数据集是784维的(即28x28像素的图像)。下图展示了使用不同方法将数据降到不同维度时,所保留的数据方差比例。

  • 蓝线:通过简单地选择方差最大的K个像素(即坐标轴投影)进行降维。
  • 红线:使用主成分分析进行降维。

结果显示,要达到相同的方差保留率,主成分分析所需的维度远低于简单的像素选择法。例如,要保留80%的方差,PCA只需不到50维,而像素选择法则需要约250维。

以下是使用PCA将单个数字图像投影到不同维度(K=200, 150, 100, 50)后再重建回原始空间的视觉效果。可以看到,即使降到50维,重建的图像依然清晰可辨。

从投影重建原始数据

现在,我们解决另一个关键问题:当你只拥有数据的低维投影时,如何重建出原始高维空间中的近似表示?

让我们从一个简单的例子开始:将二维数据投影到一维。假设我们选择了一个方向 U 进行投影。投影后,每个点 x 变成了一个标量值 U^T x。为了重建,我们只需将这个标量值乘以方向向量 U,即 重建点 = (U^T x) * U。这样,我们就把一维线上的点映射回了二维空间(尽管它们都落在通过原点的直线 U 上)。

将这个逻辑推广到多方向投影。假设我们将D维数据投影到了K个标准正交方向 U1, ..., UK 上,得到了投影向量 z = U^T x(其中 z 是一个K维向量,z_i = x · Ui)。

重建过程同样直接:
重建点 = z1 * U1 + z2 * U2 + ... + zK * UK

用矩阵形式表示则更为简洁。我们的投影是 z = U^T x。那么,重建就是 U z。因为 U 的列是 U1UK,所以 U z 正好就是上面那个求和公式。

回到之前MNIST的例子,那些重建图像正是通过这个过程得到的:将50维的投影向量 z 乘以由前50个特征向量组成的矩阵 U,从而得到了一个784维的向量,并将其重新排列成28x28的图像。

总结

本节课中我们一起学习了主成分分析的核心内容。我们首先定义了将数据投影到多个标准正交方向上的方法。接着,我们了解到最优的投影方向是数据协方差矩阵的前K个特征向量,这一过程即为主成分分析。最后,我们探讨了如何从低维投影重建出原始高维数据的近似表示,其核心操作是 重建点 = U * (U^T x)

主成分分析是统计学和机器学习中最重要的基础工具之一。它通过捕捉数据中方差最大的方向,为我们提供了一种强大而高效的降维和数据压缩手段。

机器学习基础:10-04-02:案例研究-人格评估

在本节课中,我们将学习主成分分析的一个具体应用案例:如何量化人格特质。我们将看到,通过收集和分析数据,并结合PCA技术,研究者们能够将复杂的人格特征简化为几个核心维度。

主成分分析是一项已有至少一个世纪历史的基础工具,广泛应用于所有使用统计学的领域。今天,我们将通过一个具体案例,研究PCA在量化人格方面的应用。

我们每个人都有不同的人格,这些人格似乎是多维的。任何两个人在某些方面不同,在其他方面又相似。那么,有没有办法量化这一切呢?例如,我们能否将每个人的人格表示为某个低维空间中的一个点?这类问题一直困扰着人们。一些最杰出的思想家,如卡尔·荣格,曾提出过部分答案,但通常是各种定性的标准。如今,我们生活在一个数据收集的时代,似乎有可能将这个问题定量化。今天要讨论的,就是在这个方向上取得的一些进展。

起点通常被称为“词汇假说”。这是一个简单的想法:任何哪怕只有一丝一毫重要性的人格特质,都必然有一个对应的英文单词,例如“勇敢”、“敏感”或“恶意”。基于此,两位研究者在1930年代,奥波特和奥德伯特,坐下来仔细翻阅英语词典,寻找所有可以用来区分人的词汇。他们找到了18000个这样的词。然而,并非所有这些词都指代人格特质,有些词指的是“高”和“矮”这类特征。因此,他们进行了第二轮筛选,从这18000个词中进一步提炼出描述人格特质的词汇,最终得到了4500个词。这个列表仍然很大。但后来发现,其中很多词是同义词,例如“快乐的”、“愉快的”、“开心的”。于是,另一组研究者在1960年代手动将这些词聚类成同义词组,从而将列表缩减到大约500个不同的人格词汇。

此时,是时候进行数据收集了。数据收集的方式非常有趣。研究人员请来参与者,向每个人展示这500个词,并询问:“哪些词描述了您?”实际上,这个过程采用了更精细的方式。每个人会逐一看到这500个词,例如其中一个词是“害羞”,并被询问:“‘害羞’这个词是否描述了您?请用1到5分表示,1代表强烈不同意,5代表强烈同意,或者选择2、3、4。”通过这种方式,收集到了一个完整的数据矩阵。矩阵有500列(对应500个词),每一行是某个特定参与者的所有回答。

那么,给定这类数据,我们如何获得人格的低维表示呢?实际上有很多方法可以处理。一种思路是将列视为数据点并进行聚类。这将给我们带来相似人格词汇的簇。例如,如果结果发现害羞的人也倾向于宽容,那么这两个词就会归入同一个簇。或者,我们可以将行视为数据点,即每个人是一个数据点,然后对数据应用主成分分析、因子分析或其他形式的表示学习。研究者们基本上尝试了所有这些方法。结果在某种程度上相当一致。因此,今天我将描述PCA方法。

让我们从一些直观理解开始。假设有两个特质,比如“慷慨”和“信任”,它们恰好高度相关。这只是假设的例子,我不知道慷慨和信任是否真的如此。但如果它们完全相关,那么每个人对“慷慨”的回答将与对“信任”的回答完全相同。因此,所有答案都会落在y=x这条线上。如果我们要求主成分分析找出数据中的重要方向,它会找到这个方向。从这一个PCA方向,从这一个数字,我们将能够完美地重建“慷慨”值和“信任”值。这就是我们试图理解的直观概念。

现在,让我们看看实践中会发生什么。我们有一个数据矩阵。我们将每一行视为一个数据点,因此我们有500个词,即数据点位于500维空间中。现在应用主成分分析,我们得到主成分,假设它们是U1、U2、U3等。这些是500维空间中的方向。

选取第一个方向U1,即第一主成分。我们可以将第一个人的数据投影到这个成分上:只需取该人的行向量与U1进行点积。这给出一个数字,比如2.3。然后看第二个人在U1上的投影:取第二个人的行向量与U1点积,得到另一个数字,比如-0.1。接着处理第三个人,依此类推。通过这种方式,我们得到一整列数字。这本质上是一个新合成的“人格特质”,我们称之为特质T1。

然后,我们可以对第二主成分做同样的事情。取每个人的数据与方向U2的点积,得到另一组数字,称之为T2。接着可以计算T3、T4、T5等。如果我们计算到T5,那么对于每个人,我们就得到了五个新数字。本质上,这是将每个人嵌入到一个五维空间中,是对其人格的一种量化。

那么,这些特质具体指代什么?我们如何理解它们的含义?例如,特质T1是从数据中自动提取的合成特质,它捕捉了人格的哪个方面?为了弄清楚这一点,我们可以查看该特定列(即T1),然后遍历对应500个英文单词的原始列。我们看看其中哪些列与T1最接近,即哪些列与T1的夹角最小或点积最大。通过观察这些词是什么,我们就能了解T1捕捉了人格的哪个方面。然后对T2、T3、T4和T5重复此过程。

当我们这样做时,就得到了通常所说的“大五人格”分类法。

以下是具体结果:

  • 第一主成分 T1:与“健谈的”、“自信的”、“活跃的”、“精力充沛的”等词具有很高的正点积;与“安静的”、“矜持的”、“害羞的”、“沉默的”等词具有很高的负点积。研究者们决定将这一合成特质命名为外向性
  • 第二主成分 T2:与“有同情心的”、“友善的”、“感激的”高度相关;与“挑剔的”、“冷漠的”、“好争吵的”负相关。这被称为宜人性
  • 第三主成分 T3:与“有条理的”、“彻底的”、“高效的”、“负责任的”高度相关;与“轻浮的”、“粗心的”等负相关。这被称为尽责性
  • 第四主成分 T4:与“紧张的”、“焦虑的”、“神经质的”、“情绪化的”有较大的点积。这被称为神经质
  • 第五主成分 T5:与“富有想象力的”、“聪明的”、“有独创性的”有较大的点积(可能不如前几个那么大);与“狭隘的”、“肤浅的”负相关。这被称为开放性

这些特质看起来都相当合理。有人可能会问,为什么不继续下去?为什么停在5个?为什么不提取第六、第七、第八主成分?事实证明,从那时起,结果开始变得不那么有说服力了。前五个特质(至少前四个)的一个优点是,当使用其他数据分析方法(如聚类或因子分析)时,也得到了类似的结果。然而,这种一致性在大约第五个特质之后就不复存在了,因此这确实是人们能够达成共识的子集。这种量化方法现在被用于许多场景,例如计算机化的婚恋匹配。

本节课中,我们一起学习了主成分分析的一个实际应用案例。我们看到了数据和PCA如何被用来回答关于人类的一些非常根本的问题。

053:特征值与特征向量 📊

在本节课中,我们将要学习特征值与特征向量的概念。我们将从一个数据集的“自然”坐标系出发,逐步理解线性代数中这一核心思想,并了解它如何简化数据分析。

从数据到自然坐标系

当我们思考数据时,通常习惯于从我们选择的特征角度来考虑,即数据向量的各个坐标。然而,数据分析往往在转换到一个替代的坐标系后会变得简单得多,而这最终引出了特征向量的概念。

在上图中,我们有一个简单的二维数据集,两个特征呈正相关。如果我们为这些数据拟合一个高斯分布,它看起来会像这样。

接下来,我将展示这个数据的一个替代坐标系。我们不再使用常规的坐标轴 E1 和 E2,而是使用这些倾斜的轴 U1 和 U2。我们可以很容易地在这两个系统之间转换,这只是一个简单的旋转。在许多方面,这些红色的坐标 U1 和 U2 对于这些数据来说更为自然。它们的好处在于,如果你稍微倾斜一下头,你会发现在这个新的基底下,两个坐标实际上是不相关的。例如,我们可以为它们拟合一个对角高斯分布。在这个替代坐标系中,事情变得更简单了。

线性变换与对角矩阵

现在,让我们尝试将其中一些概念形式化,为此我们需要线性代数。设 M 为任意 D×D 矩阵,即任意方阵。正如我们所知,这样的矩阵定义了一个线性函数,它将一个向量 x 映射到另一个 D 维向量 Mx。这是一个线性函数,我们见过它的例子,但这个函数到底在做什么?很难想象或可视化这个从 D 维向量到另一个 D 维向量的变换。但有一种特殊情况,这些变换实际上非常容易理解,那就是当矩阵是对角矩阵时。

这里我们有一个对角矩阵的例子,一个 3×3 矩阵。它定义了一个从三维向量到三维向量的线性变换。因为这个矩阵是对角的,所以很容易说出这个变换是什么:它取一个向量 (x1, x2, x3),然后简单地将 x1 加倍,将 x2 乘以 -1,将 x3 乘以 10。

对角矩阵易于理解,因为它只是分别缩放每个坐标,坐标之间完全不会混淆。

对称矩阵与特征向量

那么,对于一个更一般的对称矩阵呢?在这种情况下,有许多非对角线条目,它们混合了不同的坐标,这可能令人困惑。但事实证明,如果我们简单地改变坐标系,从我们自己的坐标系(x1, x2, x3 轴)移动到一个不同的、对矩阵来说更自然的坐标系,那么在这个替代基底下,矩阵再次变得非常简单,它变成了一个对角矩阵。因此,任何对称矩阵,如果移动到它自己的坐标系中,实际上又是一个简单的对角矩阵。

那么,这些自然坐标可能是什么?我们如何找到它们?让我们看看上面这个对角矩阵的例子。我们所说的是,对于一个对角矩阵,它的自然坐标就是常规坐标。例如,X1 坐标,我们可以这样写。那么,当我们将 M 应用于 E1 时会发生什么?我们只是将第一个坐标加倍,所以我们得到 2 倍的 E1。换句话说,M 将 E1 发送到完全相同的方向上的另一个向量,它不会与其他方向混合,这就是为什么事情如此简单。

这给了我们一个如何定义“自然方向”概念的思路。设 M 为任意 D×D 矩阵。如果 M 将向量 u 发送到同一方向上的另一个向量,我们就称 u 是 M 的一个特征向量。在某种意义上,这意味着 u 是 M 的一个自然方向。M 将 u 保持在完全相同的方向上,M 乘以 u 只是一个常数(一个缩放常数)乘以 u。这个缩放常数被称为与该特定特征向量 u 相关的特征值。因此,特征值和特征向量是成对出现的。

回到对角矩阵的例子

让我们回到刚才看到的对角矩阵的例子。它的特征向量和特征值是什么?我们已经提出,这个矩阵的自然方向就是坐标方向。让我们试试这些坐标方向:E1 = (1,0,0),E2 = (0,1,0),E3 = (0,0,1)。M 对这些方向做了什么?M 乘以 E1 就是 2 倍的 E1。它将 E1 发送到同一方向,所以 E1 确实是这个矩阵的一个特征向量。因此,E1 是一个特征向量,对应的特征值就是缩放因子 2。M 将 E2 发送到 -1 倍的 E2,所以 E2 也是一个特征向量,这种情况下的特征值是缩放因子 -1。M 将 E3 发送到 10 倍的 E3,所以 E3 是一个特征向量,对应的特征值是 10。

因此,E1、E2 和 E3 是这个对角矩阵的自然方向或特征向量。还有其他特征向量吗?实际上还有很多其他特征向量,因为如果 E2 是一个特征向量,那么根据定义,E2 的任何倍数也自动是一个特征向量。例如,如果我们取它的某个倍数,比如 (0, 8, 0),那也是一个特征向量,因为 M 乘以它等于 -1 乘以它。所以 E2 的任何倍数也是具有相同特征值 -1 的特征向量。因此,我们通常的做法是将特征向量归一化为单位长度,就像 E1、E2、E3 那样。

那么,让我们重新表述这个问题:这个矩阵还有其他单位长度的特征向量吗?没有。我们有一个 3×3 矩阵,恰好有三个单位长度的特征向量。情况总是这样吗?不同单位长度特征向量的数量是否总是等于矩阵的维数?对于我们的目的,答案是肯定的。另外要注意的是,这些特征向量彼此都是正交的,任何一对特征向量的点积都是 0。情况也总是这样吗?不同的特征向量总是彼此正交吗?答案再次是肯定的。这意味着特征向量构成了一个基。

对称矩阵的特征分解

让我们继续看看这是如何实现的。取任意对称方阵。如果它是一个 D×D 矩阵,那么它有 D 个特征向量 u1 到 uD,并且这些特征向量是标准正交的。换句话说,它们都具有单位长度,并且任何一对特征向量彼此正交。对于任何 i ≠ j,有 u_i · u_j = 0。这意味着这 D 个特征向量构成了一个基。我们可以将它们视为该矩阵的自然坐标系的轴。事实证明,将数据转换到这个坐标系可以简化许多不同的操作。

在我们深入探讨之前,让我们看另一个简单的例子,其中一个例子的特征向量不是坐标方向。这里有一个 2×2 矩阵。我给出了矩阵的特征向量 u1 和 u2。我们想要做的是计算对应的特征值。首先检查它们是否真的构成了一个标准正交基。我们有两个,这对于一个 2×2 矩阵来说是合理的。它们是单位长度吗?是的,它们的长度是 1。它们彼此成直角吗?u1 点乘 u2 是多少?点积在这种情况下是 0。因此,这两个特征向量确实是标准正交的。

它们的特征值是什么?让我们计算 M 乘以 u1。我们可以把 √2 提到前面。所以是 (1/√2) * [[1, -2], [-2, 1]] * [1, 1]。计算结果为 (1/√2) * [-1, -1] = -1 * [1/√2, 1/√2] = -1 * u1。所以它将向量 u1 发送到 -1 倍的同一向量。因此,对应的特征值是 -1。现在看另一个向量 M 乘以 u2,同样,我们把 √2 提到前面。所以是 (1/√2) * [[1, -2], [-2, 1]] * [-1, 1]。计算结果为 (1/√2) * [3, 3] = 3 * [-1/√2, 1/√2] = 3 * u2。所以第二个特征值是 3。

总结

本节课中我们一起学习了特征值与特征向量的核心概念。我们从寻找数据集的自然坐标系出发,引出了特征向量的定义:对于一个矩阵 M,如果存在非零向量 u 和标量 λ,使得 M u = λ u 成立,则 u 是 M 的特征向量,λ 是对应的特征值。对于对称矩阵,其特征向量构成一组标准正交基,这为数据提供了自然的坐标轴,可以极大地简化后续分析。下次课程我们将看到任何矩阵(特别是数据矩阵)如何用特征向量和特征值重写,这将成为数据分析中一个非常强大的工具,称为谱分解。

054:谱分解

在本节课中,我们将学习谱分解定理。这是一个强大的数据分析工具,它告诉我们如何仅使用矩阵的特征向量和特征值来重新表示矩阵。我们将看到这个定理如何为理解矩阵提供一种简单直观的方式,并最终引出主成分分析(PCA)的核心思想。

回顾:特征向量与特征值

上一节我们介绍了特征向量和特征值。本节中,我们将看看如何利用它们来直观地理解矩阵。

特征向量和特征值可以帮助我们找到数据的“自然”坐标系。考虑一个简单的二维数据集,其两个特征之间存在相关性。如果我们切换到一组新的坐标轴,数据可能会变得更简单——相关性可能会消失。这些新的坐标轴方向,就是数据的“自然”坐标。

特征向量与特征值定义

对于任意一个 D×D 的矩阵 M,一个特征向量 u 是一个满足以下条件的向量:当 M 作用于 u 时,结果向量与 u 方向相同,仅被缩放。这个缩放因子 λ 被称为与 u 对应的特征值。

公式表示为:
M u = λ u

对于一个对称矩阵 M,它存在 D 个相互正交且长度为 1(即标准正交)的特征向量 u₁, u₂, ..., u_D。这些特征向量构成了一个新的坐标系的基础。

谱分解定理

谱分解定理是本节课的核心结果。它指出,任何对称矩阵 M 都可以用其特征向量和特征值重新表示。

具体来说,我们构造三个矩阵:

  1. U:一个 D×D 矩阵,其每一列是一个特征向量。
  2. Λ:一个对角矩阵,对角线上的元素是相应的特征值 λ₁, λ₂, ..., λ_D。
  3. Uᵀ:矩阵 U 的转置。

谱分解定理表明:
M = U Λ Uᵀ

这个分解非常强大。它意味着矩阵 M 的全部信息都包含在其特征向量和特征值中。更重要的是,它将 M 的复杂操作分解为三个简单易懂的步骤。

理解矩阵操作的三步分解

现在,我们来看看矩阵 M 对任意向量 x 的操作如何被分解为三个直观的步骤。

M x = (U Λ Uᵀ) x

以下是每一步的解释:

  1. Uᵀ x:这是一个基变换。它将向量 x 从原始坐标系转换到由特征向量构成的新坐标系中。结果向量 x' 的每个坐标是 x 在各个特征向量方向上的投影。
  2. Λ (Uᵀ x):这是一个缩放操作。在新的特征向量坐标系下,矩阵 Λ 只是简单地对每个坐标(即每个特征向量方向上的分量)进行独立的缩放,缩放因子就是对应的特征值。
  3. U (Λ Uᵀ x):这是逆基变换。它将缩放后的结果从特征向量坐标系转换回我们熟悉的原始坐标系。

通过这种方式,任何对称矩阵的线性变换都可以被理解为“换到自然坐标系 -> 在各个方向上独立缩放 -> 换回原坐标系”的过程。

实例演算

让我们通过一个具体的 2×2 矩阵例子来应用谱分解定理。

假设矩阵 M 为:

M = [[2, -4],
     [-4, 2]]

(注:视频中使用的具体数值在转录中不完整,此处为说明性示例,原理相同)

其计算出的特征向量和特征值为:

  • 特征向量 u₁ = [1/√2, -1/√2]ᵀ, 特征值 λ₁ = -2
  • 特征向量 u₂ = [1/√2, 1/√2]ᵀ, 特征值 λ₂ = 6

根据定理构造矩阵:

  • U = [[1/√2, 1/√2], [-1/√2, 1/√2]]
  • Λ = [[-2, 0], [0, 6]]
  • Uᵀ = [[1/√2, -1/√2], [1/√2, 1/√2]]

可以验证 M = U Λ Uᵀ 成立。现在,如果我们用 M 乘以向量 x = [1, 2]ᵀ:

  1. Uᵀ x = [ -1/√2, 3/√2 ]ᵀ。这表示 x 在新坐标系下的坐标。
  2. Λ (Uᵀ x) = [ (-2)(-1/√2), 6(3/√2) ]ᵀ = [ 2/√2, 18/√2 ]ᵀ。这是在自然坐标系下的缩放。
  3. U (Λ Uᵀ x) = [ (2/√2 + 18/√2)/√2, (-2/√2 + 18/√2)/√2 ]ᵀ = [10, 8]ᵀ。这是最终在原始坐标系下的结果。

与主成分分析(PCA)的联系

谱分解定理是主成分分析(PCA)的数学基础。以下是PCA的步骤,它们直接建立在谱分解之上:

我们从一组 D 维数据向量 X 开始。

  1. 计算协方差矩阵:首先计算数据的 D×D 协方差矩阵。这个对称矩阵捕获了所有特征之间的相关性。
  2. 特征分解:计算协方差矩阵的特征向量和特征值。这通常由标准软件包完成。
    • 特征向量 u₁, u₂, ..., u_D 定义了数据的“自然”坐标系(主成分方向)。在这个坐标系下,数据的各个坐标是不相关的。
    • 特征值 λ₁, λ₂, ..., λ_D 具有明确的统计意义:在方向 u_i 上的方差恰好等于 λ_i
  3. 选择与投影:为了降维,我们将特征值按从大到小排序(λ₁ ≥ λ₂ ≥ ... ≥ λ_D)。保留前 K 个最大特征值对应的特征向量 u₁, ..., u_K
  4. 数据转换:将原始 D 维数据向量 x 投影到这 K 个主成分方向上,得到 K 维的新表示:[ x·u₁, x·u₂, ..., x·u_K ]

投影后数据的协方差矩阵是一个 K×K 的对角矩阵:

[[λ₁, 0, ..., 0],
 [0, λ₂, ..., 0],
 ...,
 [0, 0, ..., λ_K]]

对角线上的方差被最大程度地保留,而非对角线上的协方差为零,意味着降维后的特征是不相关的。

总结

本节课中我们一起学习了谱分解定理。我们了解到,任何对称矩阵都可以分解为 M = U Λ Uᵀ 的形式,这相当于将矩阵的操作解释为“变换到特征向量基 -> 独立缩放 -> 变换回原基”三个步骤。这个定理不仅是理解线性变换的有力工具,更是主成分分析(PCA)等众多数据降维与特征提取技术的核心数学基础。通过切换到数据的“自然”坐标系(主成分),我们可以简化数据结构,消除特征间的相关性,并专注于保留最重要的方差信息。

055:自编码器 🧠

在本节课中,我们将学习深度学习的一个重要概念——自编码器。自编码器是一种能够揭示数据潜在自由度的模型,它能产生一种新的数据表示形式。我们将探讨自编码器的基本框架,并了解聚类和主成分分析等经典方法如何自然地融入这个框架。此外,我们还将简要介绍流形学习和独立成分分析,并探讨如何通过堆叠自编码器来构建数据的多尺度层次化表示。

自编码器概述

自编码器的核心思想是学习数据的“编码”和“解码”过程,以揭示其内在结构。

在左侧,我们有一个D维的数据点,包含特征x1到xD。在右侧,是自编码器产生的表示,包含M个数值h1到hM。这些数值包含了数据中有用的信号或某些方面。

这种表示是需要被发现的,因此常被称为潜在表示隐藏表示。我们将右侧的向量称为由M个隐藏单元组成的潜在或隐藏向量。

从原始数据点到这个潜在表示的映射可以看作是一个编码过程,由某个函数E给出。相反,从潜在空间回到原始空间的映射可以看作是一个解码过程,由某个函数D给出。

理想情况下,这个自编码过程不会丢失太多数据信息。也就是说,如果我们取一个数据点X,编码得到其隐藏表示,再解码它,我们希望能得到接近原始X的结果。这将是讨论自编码器时反复出现的最优性准则。

作为自编码器的聚类与投影

上一节我们介绍了自编码器的抽象概念,本节中我们来看看一些具体的聚类和投影问题如何用这个框架来表达。

K均值聚类

K均值聚类问题中,我们有N个数据点,希望将它们分成K个簇,并为每个簇找到一个代表或中心。

在这个例子中,有10个数据点,我们希望将它们分成三个簇,并找到每个簇的中心。中心μ1、μ2和μ3如图所示。

我们可以用其最近的中心来近似每个数据点。这样产生的近似误差,例如对于这个点,就是这段距离。通常,使用平方距离会更方便。因此,对于第i个数据点,近似误差就是到其最近中心的平方距离。K均值聚类的目标是找到能产生最小可能近似误差的K个簇和K个中心。

这如何成为一个自编码器?在这种情况下,左侧是原始的D维数据点。此时的潜在表示就是簇标签。我们将每个点发送到1到K这些簇中的一个。

一种做法是让右侧的单元h1到hK代表各个簇。例如,如果x属于簇J,则hJ(x)被激活为1,否则为0。这样,隐藏表示就是一个二进制向量,一个由0和1组成的向量。实际上,除了标识x所属簇的那个位置是1外,其余都是0。

如果我们想用向量形式表示,可以说向量h是一个二进制向量。它是x的编码。如果x在簇J中,那么h就是第J位为1的0/1向量eJ。这就是编码函数。

那么解码呢?我们只知道簇标签,如何解码回原始空间?我们只需发送回该簇的均值μJ。因此,对特定向量eJ的解码就是μJ。

这个自编码器引起的误差是什么?如果我们取一个向量x,观察先编码再解码引起的误差,即这个平方距离,它正好是x到其最近中心μJ的平方距离。因此,我们看到K均值解实际上是这种特定类型的最优自编码器。

主成分分析

在PCA中,我们有一堆数据点。我们想要做的是找到一个从原始数据空间(如RD)到某个低维空间(如RK)的投影,并且我们希望找到一个能最大化投影数据方差的投影。我们已经知道这可以很容易地完成。

首先需要计算数据的协方差矩阵,一个D×D的矩阵。然后找到这个矩阵的前K个特征向量,这些就是我们要投影的方向。

如果我们想用矩阵形式表达,可以定义一个矩阵U,其列就是这些前K个特征向量u1到uK。这是一个D×K的矩阵。投影将原始空间中的向量x发送到U^T x。如果我们有一个投影空间中的向量,想将其映射回原始空间,这也很容易,重建是通过将RK中的向量z发送到Uz来实现的,Uz位于RD中。

这是一种什么样的自编码器?在自编码器的左侧,和往常一样,是原始数据表示,即D维向量x。在右侧,有K个隐藏单元。在这种情况下,这些单元就是x在不同方向上的投影。hJ(x)就是x在第J个特征向量上的投影,即x点乘uJ。

如果我们想用向量形式表示,那么x的嵌入h就是U^T x。如果我们有这个潜在空间中的一个K维向量,想将其发送回原始空间,解码操作将h发送到矩阵U乘以h。这显然是一个自编码器。

这种编码和解码过程引起的误差是什么?我们取一个点x,我们通过先编码再解码的结果来有效地近似它。这就是x减去U U^T x的平方距离。事实证明,PCA所做的就是找到最小化这种重建误差的投影。因此,PCA也是这种特定形式的最优自编码器。

其他类型的自编码器

我们已经看到K均值聚类和PCA很容易融入自编码器框架。事实上,还有许多其他类型的无监督学习可以很容易地用这种方式表达。以下是几个例子。

流形学习

流形学习的理念是,通常你拥有的数据是高维的,有很多特征(D个),但数据点位于或接近一个维度低得多的曲面(流形)上,其维度是某个远小于D的数K。

语音信号就是一个例子。当你有语音信号并想在计算机上表示它时,你可以通过使用大量不同的滤波器使其表示维度尽可能高。但归根结底,语音是由人的声道产生的,这是一个只有少数自由度的物理系统。因此,这是高维数据集接近低维流形的典型案例。

这是一个玩具示例。这里的数据是三维的,或者可能更高,但所有数据都位于这个二维曲面,这个瑞士卷形状的物体上。问题是,如果我们得到这种类型的数据,能否自动确定这个曲面?能否将高维表示映射到由网格线所示的二维坐标?我们能否在某种意义上“展开”这个曲面?有几种算法试图做到这一点。

这如何融入自编码器框架?左侧是原始的D维数据。这些数据被发送到右侧的K个数值,这些数值就是流形上的坐标。因此,编码过程将原始空间中的数据发送到其流形坐标,而解码过程则从流形上的坐标系返回到流形所在的原始空间。所以,这显然又是一个自编码器。

独立成分分析

独立成分分析是一种在信号处理和神经科学中非常流行的无监督学习形式。它是解决鸡尾酒会问题等方法之一。

当我们在一个派对上,有很多人在交谈和走动时,在任何给定时间,我们的耳朵会接收到许多不同对话的混合。我们如何能够将这些分开,并专注于某一个对话?我们如何分离所有这些对话?

如果我们试图让计算机做到这一点,我们可能会在房间的不同位置设置麦克风。每个麦克风接收到的声音信号是多个不同对话的混合。这就是左侧所示的情况,我们有D个输入单元,每个麦克风一个。每个单元都接收不同对话的混合,这是一个语音数据的时间序列。

假设实际上只有K个不同的对话在进行,我们想做的是获取这D个混合的声音信号,并恢复出K个纯净的对话,每个源一个。这就是自编码器的右侧。这个过程被称为独立成分分析,或者在这种情况下,有时被称为盲源分离。显然,这是自编码器的另一种形式。

堆叠自编码器与层次化表示

当前深度学习的革命,在某种意义上,是由研究人员找到堆叠自编码器的方法、以某种方式分层使用多个自编码器以获得多尺度表示所推动的。

其思想是,在底层是原始数据,即输入层。然后对其应用一个自编码器,以发现数据中的某些结构,提取数据中有趣的结构。接着,再对其应用一个自编码器,以在结构中发现结构,换句话说,是一种更高层次的结构,然后是更高层次的结构,依此类推。这样,你就得到了一个特征层次结构,这些特征具有越来越高的泛化水平。

例如,假设输入层是一幅图像。那么这里的第一个隐藏层可能包含一些非常低层次的结构,比如微小的边缘片段或小斑点。下一层可能包含稍高层次的结构,例如真正的边缘。然后随着你沿着链条向上,你会得到像小盒子或其他标准形状的东西,更复杂的物体就是由这些构成的。事实上,人类视觉皮层就有这种层次化处理方式,这为设计此类模型提供了灵感。

我们如何训练这样的模型?如何自动学习这种堆叠自编码器?一种非常自然的方法是自底向上逐层进行。

我们从输入层开始。然后学习一个能给我们第一个隐藏层的自编码器。接着,我们将该隐藏层中的值视为新的输入,并拟合另一个能给我们第二个隐藏层的自编码器,依此类推得到第三隐藏层。通过这种方式,我们得到了整个层次结构。此时,我们可以将输入到最终层的映射也视为一个自编码器,然后进行微调。

我们一直在讨论以纯粹无监督的方式进行。但事实证明,鉴于当前的技术水平,如果我们实际上使用大量标签数据以有监督的方式进行,效果会更好。这将是我们本周晚些时候讨论前馈神经网络时要谈到的内容。

总结

本节课中我们一起学习了自编码器。我们看到自编码是一个非常通用的框架,它让我们能够统一多种类型的无监督学习,例如聚类和投影。首先,这是一个非常有用的框架,它让我们能够识别这些不同类型表示学习之间的相似性和差异性。其次,它也提出了模块化组合不同类型表示学习的方法,正如我们在堆叠自编码器中看到的那样。

056:分布式表征 🧠

在本节课中,我们将要学习分布式表征的核心概念。我们将从对比独热编码和分布式编码开始,然后具体探讨如何为单词构建分布式编码,并了解其实际应用。

从独热编码到分布式编码

上一节我们介绍了自编码器框架下的K均值聚类和主成分分析。有趣的是,这两种不同的无监督学习形式能以这种方式统一起来。然而,它们产生的编码方式实际上相当不同。

以下是它们的具体区别:

  • K均值编码:对于一个数据点x,如果它属于第J个簇,其潜在表示是一个二进制向量。该向量除了在第J个位置为1,其余位置均为0。例如,点x属于第2个簇,其编码为 [0, 1, 0, 0, ...]。这是一种独热编码
  • PCA编码:相比之下,PCA产生的是密集编码。它将点x映射到K个不同方向上的投影,从而产生K个数字。这些数字是密集的,例如 [-0.3, 2.6, 1.1, ...]。这是一种分布式编码,x的信息被分散或分布在这些K个数字中。

因此,独热编码和分布式编码的主要区别在于信息是集中在一个激活单元上,还是分布在多个单元上。

单词的分布式表征:词嵌入

现在,我们来看看这种区别在单词表示中的应用。我们之前讨论过文档的词袋表示法。

以下是词袋表示法的构建步骤:

  1. 首先固定一个词汇表(例如,最常见的10000个词)。
  2. 然后,用一个10000维的向量表示一个文档,每个位置对应一个选定的词,该位置的值是该词在文档中出现的次数。

在这种方案下,单个单词如何表示呢?它会被表示为一个10000维的向量,该向量除了在对应特定单词的坐标处为1,其余位置均为0。换句话说,就是独热编码

然而,这种编码有一些缺点。例如,考虑“thrilled”(激动)、“delighted”(高兴)和“miserable”(痛苦)这三个词。前两个词在含义上非常相似,几乎是同义词,而第三个词几乎是反义词。但这种语义关系在独热编码中完全没有体现。编码似乎对单词的语义不敏感,这显然不是一个好的特性。

那么,是否存在一种不同的编码方式,能够为每个单词分配一个向量,使得含义相似的单词其向量也彼此接近呢?例如,“thrilled”的向量可能像这样,我们希望“delighted”的向量与之接近,而“miserable”的向量则远离前两者。

事实证明,有几种不同的方法可以构建这种词嵌入,其中一些相当复杂。今天,我们将看一种非常简单的构建此类词嵌入的方法。

一个简单的词嵌入构建方法

词嵌入的一般思想可以用英国语言学家J. R. Firth的一句名言来概括:“观其伴,知其义”。这意味着,一个单词的含义在很大程度上可以通过与它共同出现的单词(即其上下文中的其他单词)来捕捉。

以下是构建词嵌入的一个具体步骤:

  1. 固定词汇表和语料库:首先,确定一个词汇表V(例如10000个词)和一个大型文本语料库(如维基百科语料库)。
  2. 收集上下文信息:对于词汇表中的每个单词W,遍历语料库,找到W的所有出现位置。对于每一次出现,观察其周围的上下文(例如,前后各三个词)。通过统计这些上下文单词,我们可以得到给定W时,附近出现单词C的概率分布 P(C|W)。这个V维的概率向量形式化地表示了单词W的“同伴”。
  3. 计算点互信息:我们可以直接使用这个V维向量作为W的嵌入。但通常,我们会进行两步改进。首先,计算点互信息,即观察单词C在W的上下文中出现的频率相对于C本身基线频率的比值,并对其取对数。这有助于归一化并拉开数值范围。公式大致为:PMI(W, C) = log( P(W, C) / (P(W)*P(C)) )
  4. 降维:经过上述步骤,我们为每个单词W得到了一个V维的向量(例如10000维)。这种高维表示可能过于庞大。此时,我们可以使用主成分分析等技术进行降维。实践证明,仅100、200或300维的嵌入就能非常有效地捕捉单词的大量语义信息。

这是一种你可以在家尝试的特定词嵌入方案。当然,也有像 Word2VecGloVe 这样的标准预训练词向量集可供直接下载使用。

词嵌入的应用示例

最后,我们通过几个例子来说明这些词向量所捕获的信息类型。

1. 最近邻搜索
假设我们构建了一个词嵌入,现在查看单词“Africa”(非洲)的向量(比如一个200维的向量)。它的最近邻是什么?即哪个单词的向量与“Africa”的向量最接近?我们可以通过对词向量列表进行最近邻搜索来找出答案。结果取决于你使用的具体嵌入模型。在我使用的模型中,结果是“Asia”(亚洲)。这非常合理,因为“Africa”和“Asia”在上下文单词上有很高的重叠度。你可以用其他词如“communism”(共产主义)、“war”(战争)、“hysteria”(歇斯底里)等进行尝试,结果通常都相当合理且易于理解。这证明了词嵌入的一个可靠特性:最近邻往往是语义上非常相关的词。

2. 解决类比问题
词嵌入的一个巧妙应用是解决类比问题。例如:国王(king)对应女王(queen),如同男人(man)对应什么?答案显然是女人(woman)。

我们如何使用词嵌入在计算机上解决这个问题呢?方法是将类比关系写成一个线性代数方程。我们寻找一个未知词 ?,使得:
vector(king) - vector(queen) = vector(man) - vector(?)
我们可以重新排列这个方程,得到未知词向量的表达式:
vector(?) = vector(man) - vector(king) + vector(queen)
现在我们有了右侧的表达式,可以计算出一个目标向量。很可能没有哪个单词的向量恰好等于这个结果向量,但我们可以寻找词向量列表中与这个结果向量最接近的邻居。当你这样做时,结果正是“woman”。

总结

本节课中,我们一起学习了分布式表征。我们具体探讨了词嵌入的案例,并了解了如何构建既能捕捉单词语义,又能保持较低维度的词向量。词嵌入通过将单词映射到连续的向量空间,使语义相似的单词在空间中也彼此接近,从而为自然语言处理任务提供了强大的基础。

057:前馈神经网络 🧠

在本节课中,我们将要学习前馈神经网络。我们将了解这种网络的结构、参数化方式,以及它们能够表达哪些类型的函数。

网络结构与灵感

前馈神经网络的灵感大致来源于大脑的神经回路。从整体上看,它通常是一个大型的图结构。

图中的每个节点通常被称为一个“单元”。这些单元被组织成不同的层。

最底层是输入层。如果我们处理的数据是D维的,那么输入层就包含D个单元,每个单元对应输入X的一个特征。因此,有一个单元对应x1,一个对应x2,一个对应x3,一直到xD。

输入数据从底部呈现。然后,各种计算在自底向上的传递过程中完成,最终输出结果出现在最顶层。

隐藏层与计算过程

那么中间层是什么呢?那些既不是输入也不是输出的节点被称为“隐藏单元”,它们也被组织成层。

例如,有第一隐藏层、第二隐藏层,在这个示意图中,一直到第L隐藏层。

给定输入后,我们首先要计算第一隐藏层中单元的值。

然后,我们利用这些值来计算第二隐藏层的值,以此类推,直到到达最顶层。

单元值的计算方法

这些值是如何计算的呢?让我们来看一下图中的任何一个内部节点,例如这个节点。

它连接到前一层中的多个节点,在这个例子中是三个。我们称这些节点为它的“父节点”。该节点的值是其父节点值的函数。

一旦我们知道了输入层,我们就可以简单地应用这个函数来计算第一隐藏层的值。

那么这些函数具体是什么呢?让我们选取一个特定的节点,称之为H。

给定其父节点(这里为三个)的值,我们如何得到H的值呢?

让我们来看一个隐藏单元,假设它有m个父节点。给定这些父节点的值,我们得到H的方法非常简单。在大多数情况下,它只是一个线性函数。

我们首先计算Z1到Zm的线性函数,形式为:W1*Z1 + W2*Z2 + ... + Wm*Zm + 偏移量B

我们计算这个线性函数,得到一个实数。最后,我们对结果应用一个非线性激活函数,这里用Sigma表示。

激活函数

这个激活函数Sigma是什么呢?例如,它可以是逻辑回归中的压缩函数。但在神经网络的背景下,最常用的激活函数是所谓的“修正线性单元”函数。

它遵循一个简单的规则:它接收一个实数,如果该数为正,则保留该数;如果该数为负,则返回0。

如果我们绘制这个函数的图像,它会像这样:

我们有一个数U,我们想计算ReLU(U)。如果U为负,我们返回零。

如果U为正,我们直接返回U。

参数化总结

从父节点Z1到Zm得到H的函数,由参数W1到Wm以及偏移量B参数化。实际上,我们可以将W1到Wm想象为这些边上的权重。

我们计算z1*w1 + z2*w2 + ... + zm*wm,加上B,这全是线性部分。然后我们看结果,它是一个实数:如果为正,则保留;如果为负,则返回零。这就是H。

非线性激活的重要性

现在,为什么需要非线性激活函数呢?为什么不全程使用线性函数?假设我们只有线性函数,那么整个H1层就只是X的线性函数,H2层就只是H1的线性函数,H3层就只是H2的线性函数。

线性函数的线性函数仍然是线性函数。在这种情况下,H2将是X的线性函数。实际上,图中任何节点都只是由X的线性函数给出。

整个网络的计算可以总结为一个线性函数,那么根本就不需要任何隐藏单元了。因此,为了利用这种具有多个隐藏单元的层次结构,在其中加入某种形式的非线性是至关重要的。

输出层

我们已经看到了如何获得所有隐藏层的值。但输出层会发生什么呢?输出层的值是如何获得的?

为了具体说明,假设我们试图解决的是一个有K个可能标签的分类问题。在这种情况下,我们很可能在输出层有K个单元,Y1到YK,每个单元对应一个可能的标签。

我们想要的是每个标签的概率。给定一个输入X,我们想知道给定X时标签1的概率、标签2的概率,一直到标签K的概率。

我们如何做到这一点呢?首先,我们让每个y是其父节点值的线性函数。

我们最终得到K个实数,y1到yk。但这些可能是像-2.3或6.7这样的数字。我们如何将它们转换为概率呢?我们采用与多类逻辑回归完全相同的方法:使用softmax函数。

在我们计算了这些值y1到YK之后,为了得到概率,我们说特定标签(如标签J)的概率与e^(Yj)成正比。因此,最可能的标签是相应y值最大的标签。具体的概率就是e^(Yj)的归一化版本,即e^(Yj) / (e^(Y1) + ... + e^(YK))

从某种意义上说,网络的最后一层只是在实现多类逻辑回归。

网络参数量

现在,让我们思考一下在这样的神经网络中总共有多少参数。

我们看到,每个节点都是其父节点的线性函数加上一个非线性激活。如果一个节点有三个父节点,那么它有自己的线性函数,包含四个参数(每个父节点一个,加上一个偏移项)。

因此,即使忽略偏移项,图中每条边也至少有一个参数。所以,神经网络中的参数数量至少是边的数量。

那么有多少条边呢?让我们具体一点。假设输入是中等大小的,比如1000维。

隐藏层可以是任意大小,比如大小为20或10,000。为了具体起见,假设我们有两个层,大小都是1000,即一个有1000个节点的层和另一个有1000个节点的层,并且假设它们是全连接的。

它们之间有多少条边呢?如果每层都有1000个节点,那么边的数量就是1000乘以1000,也就是一百万。

而这仅仅是网络的一层。

由此可见,像这样的网络中的参数数量很容易变得非常庞大。

深度与表达能力

这立即意味着两件事:首先,这些网络表达能力极强,可以表达各种不同的函数。其次,显然我们需要大量数据来学习所有这些参数。

现在,让我们谈谈网络的深度。深度如何影响网络的表达能力,即它能计算的功能范围?

有一个非常著名的结果指出,仅有一个隐藏层的神经网络可以计算任何函数,并且可以达到任意精度。也就是说,它可以任意好地逼近任何函数。

这听起来非常强大。这也引出了一个问题:如果我们只用一层就能得到任何函数,为什么我们还需要使用多于一个隐藏层呢?为什么我们还需要更多层?

这是一个非常好的问题,目前并没有完全确定的答案。但我们可以指出一点:人们已经发现,存在某些函数,你可以用一层网络(一个隐藏层的网络)来逼近它们,但如果这样做,隐藏层必须非常庞大,其中的隐藏节点数量可能是指数级的,例如相对于输入维度等问题的参数是指数级的。

但是,如果你使用更深的网络,那么每个单独的层实际上都可以是中等大小的。这是深度非常有帮助的一种方式。

总结

本节课中我们一起学习了前馈神经网络。我们了解了它的结构,包括输入层、隐藏层和输出层。我们学习了每个隐藏单元如何通过线性组合父节点的值并应用非线性激活函数(如ReLU)来计算其值。我们还探讨了输出层如何使用softmax函数将线性输出转换为概率分布。我们认识到,由于网络参数量巨大,它表达能力很强,但也需要大量数据进行训练。最后,我们讨论了网络深度的重要性,虽然单层网络理论上可以逼近任何函数,但深层网络可以用更紧凑的结构高效地表示复杂函数。

下次课,我们将讨论如何学习这种网络的参数。

058:神经网络训练 🧠

在本节课中,我们将学习如何训练前馈神经网络。我们将从定义合适的损失函数开始,然后探讨如何使用一种称为反向传播的巧妙方案,通过随机梯度下降算法来最小化这个损失函数。最后,我们还会介绍一些有助于模型良好泛化的实用技巧。

前馈神经网络架构回顾

上一节我们介绍了前馈神经网络,这是一个表达能力极强的函数类别。本节中,我们来看看如何学习这些模型。

上图展示了一个前馈网络的结构。它包含大量按层组织的单元。最底层是输入层,用于呈现输入向量 x。计算从底部开始,一直向上进行,最终到达输出层 y。每个节点都是其父节点的简单函数。

具体来说,每个节点的计算是其父节点的线性函数,然后经过一个非线性激活函数(通常是修正线性单元)。通过这种方式,计算向上传播并得到输出。正如我们上次所见,这样的网络可以轻松拥有大量参数。

定义损失函数

面对如此多的参数,我们如何使用训练集来学习它们呢?与往常一样,方法是将学习表述为一个优化问题,目标是找到能最小化合适损失函数的参数。

为了具体说明,假设我们使用神经网络解决一个分类问题,其中有 k 个标签。在这种情况下,最终的输出层将包含 K 个单元,每个标签一个。我们上次看到,可以通过在最后一层使用类似多类逻辑回归的方法(即使用 softmax 函数)来生成每个标签的概率。

我们想要学习的参数是整个网络的所有参数,即指定每个不同节点线性函数的参数。一旦我们固定了这些参数,我们就有了一个完全指定的网络。对于任何输入 x,它都能给出各种可能标签的概率。这很像逻辑回归。

实际上,我们可以遵循一些相同的方法论。对于每个数据点 x,我们得到 K 个可能标签的概率。因此,我们可以寻找能最大化训练集概率的参数 W(即这大量的参数)。也就是说,最大化每个数据点标签概率的乘积。

与往常一样,我们可以取其对数值使其变为求和,并在前面加上负号,得到一个需要最小化的目标。这样我们就得到了最终的损失函数。

给定一个包含 n 个训练点的数据集,我们希望找到一组参数 W(整个网络的参数),以最小化这个损失函数。请注意,这正是我们在逻辑回归中使用的损失函数,有时被称为交叉熵

在逻辑回归的情况下,这是一个凸优化问题。但在处理神经网络时,情况还是这样吗?遗憾的是,并非如此。事实上,它离凸优化问题非常遥远。

损失函数的性质

在讨论损失函数时,我们总是区分两种情况。

左边这种情况,损失函数表现不佳。它有许多局部最优解,我们可能会陷入其中,而且这些局部最优解的质量差异很大。如果我们最终陷入一个错误的局部最优解,那可能是一个相当糟糕的解。

我们喜欢的损失函数是右边这种,凸损失函数。事实上,到目前为止我们在课程中研究的几乎所有问题(如最小二乘法、LASSO、支持向量机等)都具有凸损失函数。唯一具有这种非凸成本函数的问题是 K-Means 聚类。我们曾指出,K-Means 是一个 NP 难优化问题,我们无法指望高效地找到最优的 K-Means 解。然而,有些算法能保证高效地找到接近最优的 K-Means 解。

不幸的是,神经网络优化完全是另一回事。它是高度非凸的,甚至没有太多希望找到必然接近最优的解。尽管如此,或许由于这些模型极强的表达能力,我们最终仍然经常能得到性能非常好的网络。

优化方法:梯度下降

那么,我们将如何进行这种最小化呢?与往常一样,我们将使用某种形式的梯度下降。我们已经研究过三种梯度下降的变体:普通梯度下降随机梯度下降小批量随机梯度下降

这三种方法都从以某种方式初始化参数 W 开始,然后进行一系列更新,不断调整 W,并希望损失函数 L(W) 在整个过程中稳步下降。

所有三种变体都基于使用损失函数对 W 的导数。在普通梯度下降中,每次更新都涉及使用整个数据集。如果数据集非常庞大(这在神经网络中很常见),这可能不切实际。另一个极端是随机梯度下降,每次更新只涉及一个数据点,这样好得多,但更新可能相当嘈杂。

一个很好的折衷方案是小批量随机梯度下降,更新既不涉及完整数据集,也不涉及单个点,而是涉及适度数量的数据点(例如每次 10 个数据点)。最常见的选择是某种形式的小批量随机梯度下降。

对于任何一种方法,我们需要计算的是损失函数相对于网络中每个参数的导数。我们知道,参数数量非常多。

计算导数:反向传播

这是我们的网络。我们在底部输入 x,在顶部得到 y。一旦得到 y,我们就可以评估损失(正确标签的概率)。因此,我们需要损失函数相对于网络中每个参数的导数。请记住,这里的每条边都有一个关联的参数 W。我们需要损失函数相对于每个这样的参数 W 的导数。

我们之所以需要这些导数,是因为更新 W 的方式就是使用该导数——我们将沿着该导数的相反方向移动 W

那么,我们如何计算所有这些导数呢?最容易计算的是最后一层中的参数,即沿着这些边的 W。正如我们所见,最后一层实际上只是多类逻辑回归,我们已经知道如何计算这些导数。

但是网络中更下方的参数呢?比如像这样的 W?我们如何计算损失函数相对于那个 W 的导数呢?事实证明,为了做到这一点,我们严重依赖于微积分中的链式法则

链式法则

这是用完整数学符号写出的微积分链式法则。实际上,这是我们一直用来计算导数的规则。例如,假设要求计算 (2x + 3)^10 的导数。你会这样做:嗯,让我们把这个表达式 2x + 3 称为 u。那么我们在计算 u^10 的导数,那是 10 * u^9 * du。现在,du 是什么?u2x + 3,所以 du2。因此导数是 10 * (2x + 3)^9 * 2

更一般地说,假设有一个函数 h,它是两个函数的复合:h(x) = g(f(x))。那么 h(x) 的导数就是 gf(x) 处的导数乘以 fx 处的导数。这正是我们在上面用到的规则。

让我们看看链式法则的另一种写法。假设有三个变量 xyz,其中 yx 的函数,zy 的函数。那么 zx 的导数就是 zy 的导数乘以 yx 的导数。可以看到这与第一种表述是等价的。

应用于神经网络

我们如何将其应用于神经网络呢?为了简单起见,这些网络可能非常庞大。为了防止事情变得混乱,让我们只看一个每层只包含一个节点的网络。

因此,输入层 x 只是一个数字 x。第 1 层只包含一个节点 h1,第 2 层只包含一个节点 h2,第 3 层包含一个节点 h3。最后,我们有最后一层 hL。所以现在神经网络看起来就像一条单链。事实上,为了使符号完全一致,我们就把输入称为 h0

当我们得到一个输入 x(或等价的 h0)时,我们通过一次前向传播计算 h1h2h3 直到 hL

每个值,比如 h3,都是前一个节点的线性函数。线性函数的公式如下:h_i = σ(W_i * h_{i-1} + b_i),其中 σ 是非线性激活函数(例如修正线性激活函数)。所以我们从 x 开始,计算 h1h2h3 等等。

一旦我们到达末尾,得到 hL,我们就可以从中得到概率 P(y|x),并评估该点的损失。我们需要的是损失函数相对于每个参数的导数,特别是相对于每个 W_i 的导数。

我们如何获得这个导数呢?这有两个步骤。

首先要注意,损失函数是这里一大堆东西(Wbh)的函数。为了计算损失 LW_i 的导数,事实证明,只需要知道损失函数相对于每个隐藏单元 h_i 的导数就足够了。这是因为链式法则。

我们想计算损失函数相对于 W_i 的导数,因为这能告诉我们如何调整 W_i。为此,让我们看看这个方程并应用链式法则。损失函数相对于 W_i 的导数,等于损失函数相对于 h_i 的导数,乘以 h_i 相对于 W_i 的导数。而计算 h_i 相对于 W_i 的导数相当简单,它就是 σ 在特定点 (W_i * h_{i-1} + b_i) 的导数,乘以这个内部表达式相对于 W_i 的导数(即 h_{i-1})。

好的,我们已经在前向传播过程中计算了所有这些 h 值,所以我们知道右边所有这些项。我们唯一需要的就是损失函数相对于 h_i 的导数。如果我们有这个,那么我们就可以计算相对于 W_i 的导数。因此,第一个高层次的信息是:我们只需要损失函数相对于每个隐藏节点 h1h2 等的导数。

那么,我们如何获得它们呢?事实证明,我们可以通过一次反向传播轻松获得它们。

反向传播算法

让我们看看这是如何发生的。这就是反向传播的思想。要得到损失函数在最后一个单元处的导数很容易,因为损失是该单元的直接函数。

但是,假设我们已经向下进行了一定程度,现在我们想要损失函数相对于下一个隐藏单元 h_i 的导数。

假设我们已经有了损失函数相对于单元 h_{i+1} 的导数。现在我们想要损失函数相对于单元 h_i 的导数。我们该怎么做呢?

我们写下 h_{i+1} 的公式,它是 h_i 的线性函数。然后我们应用链式法则。相对于 h_i 的导数,等于相对于 h_{i+1} 的导数,乘以 h_{i+1} 相对于 h_i 的导数。第二项我们可以直接从方程计算:它是 σ 在特定点 (W_{i+1} * h_i + b_{i+1}) 的导数,乘以这个内部表达式相对于 h_i 的导数(即 W_{i+1})。

同样,右边所有这些项都是我们已经有的。我们真正需要计算的只是 h 值,而我们在前向传播过程中已经获得了它们。

因此,给定相对于 h_{i+1} 的导数,我们可以轻松得到相对于 h_i 的导数。正如我们所见,这为我们提供了模型所有参数的导数。这被称为反向传播,它是动态规划的一种非常巧妙的运用,用于高效计算我们需要的所有导数。

扩展到更宽的网络

现在,等等,如果这只是针对看起来像一条链的神经网络(即每层只有一个隐藏节点的网络)呢?

事实证明,这种情况包含了完整情况的所有复杂性。在扩展到更宽的隐藏层时,唯一真正改变的是事情变得更混乱,但基本思想完全保持不变。

提高泛化能力的技巧

我们正在处理具有大量参数的模型,并且我们优化的损失函数是高度非凸的。鉴于这些情况,为了获得一个泛化能力良好的模型,我们必须稍微小心一些。

我们在讨论决策树和随机森林时,曾在程度轻得多的情况下见过这种情况。事实上,这些设置中的一些想法也已被引入神经网络。现在我们将讨论两个特定的想法,用于获得泛化能力更好的模型。

技巧一:早停

第一个技巧称为早停。我们的训练过程是:我们有一个训练数据集,并运行小批量随机梯度下降的迭代。

在运行这些迭代时,我们可以降低训练误差。由于参数非常多,这是我们完全可以预期能做到的事情。然而,这并不意味着我们真正关心的真实误差或测试误差也会随之下降。

事实上,测试误差可能以某种奇怪的方式表现:它可能在某个点开始上升,然后又下降,谁知道呢。为了更好地跟踪它,拥有一个单独的验证集会很有帮助。

我们可以这样做:运行训练迭代,每经过大约 100 次迭代,我们就切换到验证集,看看当前模型的表现如何。我们得到验证误差,这是实际误差的一个良好代理。然后我们看看,与 100 次迭代前相比,我们是否有所改进?如果我们改进了,很好;如果没有,我们可以简单地恢复到之前的模型(即 100 次迭代前的模型),并从该点重新开始优化。这是一个非常方便的技巧。

技巧二:Dropout

另一个被证明非常有用的技巧叫做 Dropout,这有点让人联想到随机森林。

我们在这里做的是:在训练期间,在呈现输入 x 之后,我们随机“杀死”一半的隐藏单元。更准确地说,对于每个隐藏单元,我们以某个固定概率(如 0.5)独立地删除它。因此,我们最终会删除一大堆隐藏单元,有效地将它们从图中移除。现在我们仍然运行前向传播计算,并为 x 获得一个标签,我们希望这个标签是正确的。

通过这种方式,我们迫使网络通过多种不同的路径来为 x 获得正确的标签。这引入了一种鲁棒性。

总结与工具

我们已经讨论了很多关于前馈神经网络的内容:它们是什么以及如何训练它们。其中很多内容都相当直接:损失函数的使用非常直观,随机梯度下降的想法非常自然。当涉及到细节时,比如使用反向传播计算所有导数,以及进行早停和 Dropout 等操作,这些在原则上似乎可行,但在实践中可能变得相当混乱和棘手。

幸运的是,你可能不需要自己实现所有这些。现在有一些像 TensorFlow 这样的软件包,它们处理了许多混乱的细节。你只需要指定网络架构以及每个单独节点的函数形式。一旦你做到了这一点,软件包就会处理剩下的事情:它计算出所有导数,负责训练,从而使神经网络更容易上手。

事实上,如果你想进一步学习神经网络,我认为目前最好的方法就是开始使用其中一个软件包来玩转数据。你已经具备了所需的基础知识,现在是时候出去开始实验了。

本节课中,我们一起学习了如何训练前馈神经网络。我们从定义交叉熵损失函数开始,认识到神经网络的优化是非凸的。接着,我们探讨了使用小批量随机梯度下降进行优化,并深入了解了利用链式法则高效计算所有梯度的核心算法——反向传播。最后,我们介绍了早停和 Dropout 这两个提高模型泛化能力的重要技巧。掌握这些基础后,你就可以借助现代深度学习框架开始实践了。

059:我们所略过的内容 📚

在本节课中,我们将回顾课程中因时间限制而未能深入探讨的几个重要机器学习领域。我们将简要介绍概率方法、强化学习以及机器学习中的人本考量,为你的进一步学习提供方向。

概述

课程即将结束。我们涵盖了大量内容,包括多种预测和表征学习方法,以及许多数学基础。然而,由于时间有限,我们略过了许多其他重要领域。今天,我们将简要提及这些被我们忽略的领域。

概率机器学习方法

上一节我们介绍了分类的生成方法。本节中,我们来看看更广泛的概率机器学习框架。

我们曾在讨论分类的生成方法时,接触过一点概率方法。我们看到,通过为每个类别拟合一个高斯分布,可以轻松构建分类器。高斯分布的优势在于能够捕捉特征之间的相关性,并且这些模型通常相当有效。

然而,这只是冰山一角。归根结底,高斯分布是一种相当受限的概率分布形式;例如,它们都具有椭球形状。图模型框架允许我们捕捉任何维度数据上的任何概率分布。

图模型由一个图来定义,其中每个特征对应一个节点(例如,x1, x2, x3,一直到 XD)。如果希望捕捉两个特征之间的依赖关系,我们就在对应的两个节点之间添加一条边。

模型的大小,即我们所需的参数数量,取决于我们选择的边的数量。边越多,参数越多。如果我们完全不添加边,那么最终得到的分布中,不同特征彼此独立,这只需要很少的参数。如果我们添加所有可能的边,得到一个完全图,那么我们需要大量参数,但能够建模或捕捉任何分布。通过这种方式,我们可以在模型准确性和所需参数数量之间进行权衡。

这是一个优美的框架,充满了精妙的算法、巧妙的方案和丰富的理论基础。这些模型帮助我们捕捉各种我们尚未有机会讨论的数据类型。

以下是图模型能处理的数据类型示例:

  • 序列数据:例如 DNA 序列、句子、语音。
  • 空间数据:例如某个区域内污染水平的分布。

概率方法的另一个方面是,它们可以作为理解因果关系的起点。因果关系在我们构建世界和解释事物时非常重要,我们的推理都关乎原因和结果。那么,因果结构能否从数据中自动推断?如果可以,我们需要何种数据?这些都是引人入胜的问题,如果我们希望机器能够对世界进行推理,这些问题就非常重要。

概率建模的第三条途径是贝叶斯方法。这是一个丰富的领域,本身就是一个完整的统计学分支。在本课程中,我们主要关注一类学习算法,它接收一个数据集并返回一个单一的模型(例如,一个线性回归函数)。由于我们只有有限的数据,这个函数不会完美。因此,我们处于一个有点奇怪的情况:我们有一个不完全正确的模型,却不太清楚模型的哪些部分非常可靠,哪些部分更不确定。

在贝叶斯方法中,学习算法不仅返回一个单一模型,而是返回所有可能模型上的一个概率分布。例如,它可能表示这个线性回归器的概率是0.2,那个是0.1,另一个是多少等等,我们得到整个分布。我们可以从这个分布中挑选出最可能的单个模型并使用它。但此外,这还能让我们识别该模型的哪些部分比其他部分更确定,并量化我们做出预测时的不确定性。因此,这是一种非常强大的方法。

强化学习

在讨论了基于静态数据预测的概率方法后,本节我们转向一个动态交互的学习范式:强化学习。

在本课程中,我们主要专注于训练机器反复回答一种非常具体的问题(例如,“这张图片中的动物叫什么名字?”)。但想象一下,当我们转向一个更广泛的场景时会发生什么,例如训练机器人完成像拿起一杯咖啡这样的任务。

在任何给定时刻,机器人处于特定的配置状态,这就是世界或环境的状态。它选择一个适合该环境的动作(例如,稍微移动一下)。这个动作改变了世界的状态,它随后选择的动作必须适应这个变化了的环境。因此,我们处于这样一种情况:机器在移动,它选择适合当前环境的动作,但同时,这些动作也在改变环境。

一个用于对此类情况进行建模的优美框架称为强化学习,其灵感来源于行为主义心理学的直觉。

在强化学习中,你可以将所有可能的状态(所有可能的环境)想象成一个巨大的图。每个节点代表一个可能的世界状态,它们通过边连接。在任何给定时间,我们处于其中一个状态(当前状态)。然后我们选择一个动作,该动作的效果是将我们移动到相邻状态之一(例如,这个状态或那个状态)。通过这种方式,我们在图中移动。

我们获得的唯一反馈是,偶尔会有奖励散布在图中,其中一些状态关联着少量奖励。因此,学习机器的目标是以最大化长期总体奖励的方式行事。

这是一个优美的框架,能够捕捉许多不同的情境。

机器学习中的人本考量

在探讨了机器如何从数据和交互中学习之后,最后我们来看看机器学习系统与人和社会的关系。

机器学习在我们的生活中扮演着越来越重要的角色。例如,机器学习系统通过我们的电子邮件、社交媒体和购买行为不断监控我们。我们也依赖这些系统做出大量日常决策。

一个机器学习系统需要什么才能赢得我们的信任?我们认为什么样的系统是值得信赖的?仅仅具有高预测准确性就足够了吗?还是它们也需要具备其他重要特征,例如说“我不知道”的能力?

其中一些系统被用于做出真正重要的决策,例如哪些贷款申请被接受或拒绝。对于这类系统,机器学习系统的推理过程透明至关重要,它需要能够以对所有相关方都有意义的方式解释决策,并且可能需要在法庭上经受住审查。

我们研究过的一些方法相当透明,例如决策树,它们很容易理解。但其他一些方法,如神经网络,则相当难以理解。要使这些方法更透明需要什么?是存在一些小的修复方法可以使用,还是我们必须从头开始,从根本上重新设计我们的模型和方法?这些都是非常有趣的问题。

总结

本节课中我们一起学习了本课程未深入探讨的三个关键领域:概率机器学习方法(包括图模型和贝叶斯推理)、用于序列决策的强化学习,以及关乎信任、透明度和责任的机器学习人本与社会层面。机器学习是一个丰富的领域,拥有强大的技术和优美的底层数学,同时也充满了未来的开放性问题与挑战。希望本课程激发了你的兴趣,促使你进一步探索这个迷人的领域。

posted @ 2026-03-26 12:19  布客飞龙III  阅读(1)  评论(0)    收藏  举报