EPFL-机器学习笔记-全-

EPFL 机器学习笔记(全)

1:课程介绍与回归基础 📚

概述

在本节课中,我们将学习EPFL机器学习课程的基本框架、课程结构,并深入探讨机器学习的核心概念——回归分析。我们将从课程介绍开始,逐步理解机器学习的基本原理、应用场景以及线性回归的数学基础。


课程介绍与结构 🏫

大家好,欢迎来到今年的EPFL机器学习课程。我是Martin,将与Nikicola Flamon一起带领大家完成本学年的课程讲座。

今年的课程形式有所不同,但我们尽力确保所有材料对大家开放。我们预计有大约500名学生,与去年类似。机器学习应用广泛,许多同学来自校园的不同院系。为了满足更专业的需求,校园内还开设了其他与机器学习相关的课程,相关信息可在课程网页上找到。

所有课程幻灯片都将在Github和课程页面上提供。此外,我们提到的两个研讨会也对硕士生开放。

课程评分与形式

课程评分至关重要,如果你想获得学分,评分构成如下:

  • 项目:占总分的40%,包含两个项目。
  • 期末考试:占总分的60%,为纸质考试。网页上提供了往年的考试样例。

课程形式今年略有调整:

  • 讲座视频:每周发布两个视频,上传至YouTube。
  • 问答环节:每周二下午5点进行。
  • 练习课:非常重要,我们稍后会详细解释。

课程网页上已经列出了每周的教学计划。我将主要负责前三周左右的课程,之后由Nikola Flamon接手,最后我将负责无监督学习的部分内容。

讲座将被录制,我们尽力营造课堂氛围。注释版本也将提供。视频通常在每个周二发布。

练习课与助教团队

练习课非常重要,尤其是在疫情期间,长时间在家观看视频容易感到枯燥。定期参加现场互动有助于打破这种单调。

我们将遵循EPFL的常规时间表。如果你的课程安排允许,非常欢迎你每三周来校园参加一次线下练习课。我们出色的助教团队中,大约三分之一会在线下,其余三分之二将通过Zoom提供支持。练习课在每周四进行,请务必在日历上标记,这对于提问和与同学讨论至关重要。

实验课主要使用Python,你将学习如何运行机器学习示例,亲身体验课堂上学到的理论概念。请务必为这些实验课投入时间。

我们的助教团队也可以通过电子邮件联系。我们非常期待本周四的第一次课程。

论坛与项目

对于任何问题,请始终使用Moodle论坛。这是最便捷的方式,因为你的问题可能也是其他同学的疑问,公开讨论能让所有人受益。论坛设有子主题,请充分利用它来讨论各种问题。

我还提到了每周二下午5点关于讲座的问答环节。

接下来是项目介绍,这是本课程的一个特色。

  • 第一个项目:是一个热身项目,帮助你开始处理数据并在一个真实数据集(实际上来自CERN的粒子物理学)上进行机器学习。
  • 第二个项目:在课程后半段进行,更加令人兴奋。你可以自由选择主题,但需要以三人小组的形式完成(两个项目都如此)。在第二个项目中,我们鼓励你进行任何你感兴趣的真实世界项目。你可以联系EPFL校园内任何实验室或其他学术机构,与他们合作,利用真实数据识别机器学习的新应用,进行激动人心的跨学科项目。这被称为“机器学习用于科学”选项,通常约有一半的学生选择。我们稍后会详细讨论。

此外,你还可以选择我们提供的三个预定义挑战之一,这类似于Kaggle竞赛,团队在同一数据集上竞争,看谁的机器学习系统能获得最佳准确率。或者,如果你对机器学习本身的研究方面更感兴趣,可以选择“机器学习可重复性挑战”,这是一个全球范围内的重要项目,旨在复现*期论文中的科学结果,验证其实验是否合理且可重复。

关于第二个项目的这三个选项,请保持关注,并务必阅读项目描述和课程信息表(PDF格式,可在我们的Github和网页上找到)。请仔细阅读相关细则。

课程目标与定位

本课程旨在为你提供对机器学习的基本理解,并教授其基础知识。我们不仅希望你知道如何在商业软件中按几个按钮,更希望你真正理解机器学习的原理、可能出错的情况以及何时能成功。我们会介绍一些数学基础,虽然不会像学习理论课程那样深入,但会确保涵盖核心内容。

另一方面,我们也希望确保课程与现实世界保持联系,让你在实际数据集和应用中体验各种方法的优缺点。我们将在课程中多次看到这一点。希望我们能在教授实践经验和理论基础知识之间取得*衡。

当然,你无法仅从这门课程中获得一切。如果你需要更专业的知识,可以参考其他相关课程。这只是打下一个基础。课程中也会涉及许多实用的技巧。希望学完本课程后,你至少能更好地理解当前的发展趋势,并能够快速跟进最新的进展,以便在某个领域进行更深入的专业学习。

学生背景与学习工具

我们讨论了教师团队,那么你们是谁呢?这是去年课程的情况,我展示这张图是因为我非常喜欢这门课程的多样性——它汇集了来自校园各个院系的众多学生,不仅在数量上,更在背景上。这真的很棒。

你们来自生物、数学、物理、生命科学、数学工程、金融数学等各个专业,还有许多博士生。这使得课程具有高度的跨学科性,这实际上也是一项关键优势。在项目团队合作中,我们强烈建议组建跨学科团队,不要总是和背景相同的熟人组队,尝试与不同背景的同学合作,这样项目会更成功。

例如,如果你能将擅长编程、擅长数学和擅长特定领域应用(如生物学)的人组合在一起,就能形成更强大的团队。我们认为,应用机器学习本身就是一个跨学科的主题,因此这是一个很好的项目合作机会。在Moodle论坛上很容易找到队友,即使在疫情期间,远程协作也更加方便。所以,这是一个很好的机会。欢迎所有人。

去年来自不同院系的所有学生表现都非常出色,这通常超出了人们对这个主题的初步预期。这不一定是一门纯粹的计算机科学课程,每个人都非常受欢迎,并且取得了成功。

我们还有一个额外的学习工具,这不是练习和讲座材料的替代品,而是一个补充。这是一个不错的手机应用,也可以在浏览器中使用,它会提醒你课程中涉及的关键词和维基百科概念。这实际上是一个很好的学习应用,它甚至包含一个小小的机器学习组件,能够根据你的遗忘和学习速度,适时地提醒你复习那些容易出错的概念。这很有趣,体现了人类学习和机器学习之间的联系。如果你想尝试这个游戏化的学习应用,欢迎使用。


什么是机器学习?🤖

对我来说,机器学习基本上可以描述为从数据中定义和学习的算法

与在代码中逐行硬编码算法不同,机器学习算法的参数由某个数据集决定。这意味着算法被一些数值参数化。你可以将这些参数想象成系统上的旋钮或权重。这些旋钮是可调的,意味着它们被优化以最好地拟合数据集。

这些旋钮具体是什么,取决于我们使用的机器学习模型类型。例如,在线性回归模型或神经网络中,核心思想是相同的:算法根据数据进行调整,然后可以作为一个算法来使用。

一个具体例子:图像分类

图像分类是过去十年中广泛使用的经典机器学习应用。我想给你展示一个能够完成此任务的数学算法。

以下是其工作原理的图示。你需要将数据点(位于底部)表示为特征空间中的点。这是你的训练数据,这里有六张图像。以其中一个训练数据点为例,你需要将该图像表示为一个点,这样我们才能使用机器学习模型来分离这些点,例如将狗的图像与猫的图像分开。

“分离”是什么意思?例如,这里我们采用一个简单模型,即使用一个*面(在二维中是直线)。在二维*面上,每个点都是*面上的一个点,你会寻找最佳直线来分隔这两组点。如果你能像图中那样分隔它们,那么你就找到了一个好的分类器。

一旦找到了这个分类器(即那条直线),你就可以处理新图像。例如,对于这张标签未知的新图像,我可以使用我的机器学习系统来回答这个问题。系统会判断该点落在直线的哪一侧。实际上,它落在了蓝色一侧,因此系统的答案将是:这是一张狗的图像。

这就是分类器的工作原理。那么,图像是如何变成二维点的呢?实际上并非如此。机器学习中的数据点通常不止二维,它们具有许多特征。这里的特征不止两个,例如可能有数百个特征,即每个像素的值。你可以将所有像素值写成一个很长的向量。如果像素是黑色,你写0;如果是白色,你写1(或者反过来)。所以,这张图像可能由100或1000个像素组成。这意味着代表照片的点是一个1000维的数据点,由0和1组成(或者对于灰度图,每个值在0到1之间,可以是任何数字或百分比)。

这只是将原始数据(这里是数字图像)转换为数值格式的一种简单方法,或者更专业的术语是:为原始数据项定义特征。一旦将其转换为特征,即我们找到了D个数值特征来表示我们的点,我们就可以进行机器学习了。

学习过程:感知器算法

那么学习是如何完成的呢?你如何找到分隔这些点的*面?我提到过,这不是一条直线,而是一个*面,也就是所谓的超*面。你试图找到它,使得红点在一侧,蓝点在另一侧。

如何做到这一点?训练是如何工作的?这里有一个非常优雅的算法,至今仍然非常基础,甚至现在仍用于训练神经网络。基本上,还没有出现比这更好的新算法。这只是一个非常简单的算法示例,但该算法实际上早在1957年就已应用于线性和更强大的非线性分类器。

它是如何工作的?我们的模型是这里的黑色超*面。我们如何描述*面?例如,我们用一个法向量来描述它。假设我们考虑所有通过原点的*面。这是一个不好的*面,它由法向量 w 描述。w 是一个D维向量。

这是一个不好的*面。我如何找到一个更好的?我找到一个被错误分类的点,即位于错误一侧的点,比如这个红点。这意味着它是一张猫的图像。但问题在于它位于*面的下方,即蓝色一侧,这是不应该的。我们希望所有红点都位于上方。

我们怎么做呢?有趣的是,在极高维空间中,你能做的事情并不多。记住,点 x 是一个超高维向量,例如1000维,因为它来自照片。w 也是如此,有1000个分量。我不想讨论在这种空间中的复杂操作。但我肯定能做的最简单的事情,就是将这两个向量相加一点点。

所谓“一点点”,我是指取被错误分类的数据点向量,乘以一个小标量(比如0.1),然后将其加到我的 w 向量上。这样我就得到了这个新向量,作为我的新法向量 w,也就是我将要使用的新*面。

这里并没有发生什么神奇的事情,只是我们通过添加一点点错误分类的数据点向量,修改了旧的*面。现在,我们有了一个新*面。这是该算法的一次迭代。你可以看到*面已经变得更好了。现在,我们几乎分隔了所有两类点。虽然还有两个点分类错误,但所有红点都已经正确分类了。

这就是你执行该算法一次迭代的方式。这个算法现在实际上被称为随机梯度下降。这只是针对一个特定模型和损失函数的一个非常简单的例子,我们稍后会解释这具体意味着什么。但这里我们所做的就是这个算法,它现在也被称为支持向量机。我们将在课程中期更多地讨论这类方法。

这个算法的优点在于它超级快。执行一次迭代当然很快,虽然最终需要多次迭代,但每次迭代只需要将两个向量相加,成本极低。只需要大约1000次浮点运算来相加这两个向量,也许再乘以一个标量。

这就是我们在进行机器学习时应考虑的操作类型。我们进行了内积运算来判断点位于哪一侧,然后进行了两个向量的加法。我们使用标量0.1作为步长,稍后会解释其含义。

这是机器学习算法中非常典型的迭代或操作示例。这个算法基本上是世界上唯一的机器学习算法,只不过我们会稍后解释得更详细、更通用,并看看它如何用于许多监督学习和无监督学习的用例。

我展示这张幻灯片是为了说明,如果一个机器学习系统在硬件上训练,你可以想象CPU或显卡正在执行的就是这类操作。它们必须计算内积(这实际上会导致梯度,我们稍后会讲到),然后必须在非常大、非常大的向量上进行更新。机器学习模型的参数不仅限于10维,实际上可以达到数百万、数十亿甚至更多,通常比数据点数量还要多得多,这也是我们稍后会讨论的一点。

监督学习的一般流程

这是一个具体的例子,希望能激发你的一些兴趣。为了更概括地理解,这里发生了什么?我们拥有训练数据,即猫和狗的图片。它们已经带有标签,标签指明它属于哪个类别:是猫还是狗。你有很多你想要完成的任务(区分猫狗)的示例,并且这些数据已经有人工标注。

这是标准监督学习中的假设。这并不总是容易的。实际上,主要问题往往不在于写一行Python代码来在数据上训练神经网络,而在于如何识别、找到这些数据,或者说服许多人进行手动标注工作,为机器学习算法生成训练数据。

我们之前看到的算法,例如支持向量机,可以通过梯度下降进行训练(稍后我们会更精确地定义)。当然,还有其他机器学习方法。无论如何,它们会输出一个训练好的模型,通常称为 w。在我们的例子中,这是描述*面的向量。这个*面就是整个模型,即分类器。一旦你有了它,就可以交付给客户,他们将使用这个超*面来做“是”或“否”的决策,或者决定自动驾驶汽车是停止还是加速(这也是一个分类问题)。

当你有了模型,就可以输入测试数据。这就是我之前描述的绿点。关键是你不知道它的标签,但你可以将其输入模型,然后询问它位于超*面的哪一侧,你会得到一个答案:要么是狗,要么是猫。

你还需要进行非常可靠的评估,这是一个重要主题。如果未经彻底评估,我们不会放心部署这样的机器学习系统。这也是我们将要讨论的内容。如果有人给你一个训练好的模型,你如何判断这是一个训练良好的模型?你如何确定它足够准确?这就是监督学习的流程。

在课程后期,我们还将讨论更多关于无监督学习的内容,这是一个不同的、甚至可以说更有趣的用例,即尝试在没有手动标注训练数据的情况下进行学习。有时你也可以使用一些辅助任务或让模型自我训练,从而了解数据的一些信息。


机器学习与智能、其他领域的关系及现状 🔍

让我们退一步思考。这一切与智能有什么关系?到目前为止,这看起来并不智能。我们只是拟合了一个线性*面,确实如此。实际上,你可以说机器学习只是一种回归,这是一个相当准确的描述。然而,与传统模型相比,这仍然是一大进步。传统模型只有硬编码的规则,例如由人类编程的硬编码聊天机器人(如果用户说这个,聊天机器人就回答那个)。这与机器学习模型所能达到的准确性和质量相去甚远。当然,这些模型还不是智能,但它们正试图朝着更好地泛化和真正理解任务某些方面的方向迈进一步。但核心上,这些模型确实只是我们描述的回归模型。

与神经科学的比较

另一种观点是与神经科学比较。神经科学试图理解生物神经网络的工作原理以及生物大脑为何工作。这本身就是一个超级有趣的领域,并且基本上独立于机器学习。另一方面,机器学习也独立于此。它更像是一种工程方法:我们能否建造一台会飞的机器?它不需要像鸟,我们只想建造某种机器。在我展示的例子中,我们建造了一个“*面”(线性超*面),它与任何聪明的大脑之类的东西无关,但如果针对某些应用在足够的数据上训练,它就能工作。这就是另一种方法。机器学习不关心提出的模型是否与生物大脑有任何相似之处,只关心在分类任务上获得良好的测试准确率,以便你的自动驾驶汽车能安全行驶。

到目前为止,它们似乎是完全分离的。但有趣的是,我们在机器学习中获得的许多表现最好的模型(例如与人工神经网络相关的模型),仅仅因为从工程角度看它们效果最好而出现,结果发现它们也与生物网络有相似之处。这是一个引人入胜的*行现象。当然,仍然存在巨大差异。例如,在机器学习中,我们使用的每个人工神经元都通过反向传播进行训练(稍后会解释),这在生物大脑中并不真正存在:信号顺序地从输入到输出向前传播,然后又顺序地从输出到输入向后传播以调整权重。你不会认为生物大脑中有如此协调有序的序列化过程来进行调整。所以问题是,是否存在类似的算法?这是一个巨大的开放性问题。我们不会接*回答这个问题,但如果你对这两个领域之间的类比或有趣关系感兴趣,神经科学系也有一些其他有趣的课程。

与其他领域的交叉

另一张简短的幻灯片。你可能已经见过这个,我不会花太多时间。这只是关于机器学习如何与其他领域结合。众所周知,统计学已有数百年历史,计算机科学的历史稍短一些。那么,我们如何定位机器学习?我们认为,机器学习实际上始终处于这三个领域的交叉点:

  • 计算机科学:提供工程方面,使其真正工作,能够在大数据集上实现。
  • 应用领域:明确的任务,例如我们想根据基因组等对疾病进行分类。数据来源以及答案和训练数据的来源。
  • 建模决策:例如,我们可以使用线性模型(*面),然后使用计算机科学的训练算法来高效地找到最佳*面。

如果你能将这些结合起来,你就处于这三个领域的交叉点,也就是机器学习领域。在就业市场上也是如此,这类技能需求日益增长,也更加普遍。许多行业应用现在也试图从数据中受益,机器学习通常是一个重要工具。你可以看到,这与数据科学专家紧密合作。

现状与挑战

机器学习领域确实经历了一些热潮,当然,人们的兴趣也增加了。我想展示的是,过去五年发生了很大变化。你可以看到兴趣有显著增长(这是谷歌趋势数据)。虽然最*趋于*稳,但人们对机器学习的兴趣仍然很高。例如,如果你比较传统领域如线性代数,我放这两个有点奇怪,但有趣的是,这两种技术在使用方式上有点相似,因为线性代数也广泛应用于任何应用领域,可能是生物学、心理学、地理学等许多科学和工业应用都需要这类数据技术,它们已经存在很长时间了。在某种程度上,机器学习也与线性代数类似,它只是许多已有术语的重新包装。但一个很大的区别是,现在我们实际上能够更广泛地应用它,我们发现了更多的应用,有更多机会使用这些数据驱动的技术,而且技术本身也在一定程度上得到了改进。

热潮有利有弊。你可能看到,也许两年前,机器学习确实处于炒作曲线的顶端。现在它正朝着更合理的领域发展。从长远来看,事物应该趋于合理水*,这就是我们现在看到的整合。它不再是最酷、最时髦的东西了,但人们也开始更实质、更扎实地对待它。仅仅抛出机器学习这个流行语已经不够了。它正成为一种许多人了解的标准工具,因此更深入地了解细节也变得更重要:具体在什么意义上、为了什么、以及如何精确地使用机器学习。你可以看到许多专业应用,如设备端AI、可解释AI、自然语言处理、自动化机器学习等,涉及方方面面。我们课程会涉及其中一些,但不会全部。深度学习、图分析等也有很多方面。很高兴看到人们更认真地对待它,而不仅仅是把它当作一个流行语。

为什么使用机器学习?

我希望我已经稍微激发了你对机器学习的兴趣。但我会快速浏览这些幻灯片,我只想指出一点:这不仅关乎通常的数字公司或互联网数据。在传统上非数字化的领域,机器学习也带来了大量机会。

例如,在瑞士西部地区,你可以看到许多初创公司也在使用机器学习。例如,在农业领域制造智能机器人,或利用卫星数据进行预测,以实现更好的农业管理。或者非政府组织,例如共享单车(虽然现在可能不是最好的例子,但它们可以使用机器学习)。我只是

10:泛化与验证 🧠

在本节课中,我们将要学习机器学习中的核心概念:泛化验证。我们将探讨如何评估一个预测函数的好坏,以及如何从多个候选模型中选择最佳模型。理解这些概念对于构建可靠且有效的机器学习系统至关重要。


1. 引言与动机

上一节我们介绍了机器学习的基本框架。本节中,我们来看看两个核心问题:泛化验证

想象一下,你的朋友Mike告诉你他有一个预测函数F,并且声称这个函数效果非常好。你自然会问:如何信任他?如何验证这个函数确实能做出好的预测? 这引出了泛化和验证的问题。

在机器学习中,我们不仅关心模型在已有数据上的表现,更关心它在新数据上的表现,即泛化能力

第二个问题是模型选择。例如,在岭回归中,我们有一个超参数λ来控制模型的复杂度。λ=0意味着没有正则化,而λ很大则会严重约束模型。问题在于:我们应该选择哪个λ值? 这不仅是岭回归的问题,在多项式特征扩展、神经网络架构选择、优化算法选择等场景中都会遇到。

以下是本节课将涵盖的核心内容:

  • 泛化误差的定义与挑战。
  • 如何使用数据来估计和验证模型性能。
  • 模型选择的标准流程与理论保证。
  • 交叉验证等更高效的数据利用方法。

2. 概率框架与数据模型

为了回答上述问题,我们需要建立一个概率框架。在实践中所拥有的是观测数据,我们会基于这些数据做出假设,并在这些假设下推导结论。但必须注意,这些假设在实践中可能并不完全成立。

我们考虑一个简单的模型:

  • 存在一个未知的分布 D,它定义了数据(特征X和标签Y)的生成机制。
  • 我们观测到一个数据集 S = {(X₁, Y₁), ..., (Xₙ, Yₙ)},其中的样本是独立同分布地从D中采样得到的。

这个假设非常强。在实践中,数据可能不独立(例如时间序列数据),分布也可能随时间变化(分布漂移)。我们必须意识到这些局限性。

此外,我们假设可以访问一个学习算法 A。它接收一个数据集S作为输入,并输出一个预测函数 f = A(S)。当算法依赖于超参数λ时,我们记作 f = A_λ(S)


3. 泛化误差、经验误差与训练误差

上一节我们建立了数据模型。本节中我们来看看如何量化一个预测函数的好坏。

3.1 泛化误差(真实风险)

我们真正关心的是模型在未知数据上的表现,这由泛化误差(或称真实风险)来衡量。

定义:给定一个损失函数 L(y, y‘)(例如均方误差 L(y, y‘) = (y - y‘)²)和一个预测函数 f,其泛化误差 R(f) 是损失在数据分布D上的期望值:
R(f) = 𝔼_{(X,Y)∼D} [ L(Y, f(X)) ]

这是一个数值,衡量了f的*均预测损失。我们的目标是找到最小化R(f)的函数。

核心问题:我们无法直接计算R(f),因为分布D是未知的。

3.2 经验误差

既然无法计算期望,一个自然的想法是用观测数据的*均损失来*似它,这称为经验误差

定义:在数据集 S 上,f的经验误差 R_S(f) 定义为:
R_S(f) = (1/n) Σ_{i=1}^{n} L(Y_i, f(X_i))

经验误差是泛化误差的一个无偏估计量,即 𝔼_S [R_S(f)] = R(f)。根据大数定律,当样本量n趋于无穷时,经验误差会收敛到泛化误差。

3.3 训练误差及其问题

然而,在机器学习流程中,我们通常用数据集S来训练(即选择)预测函数f。此时,如果我们用同一个数据集S来计算f的经验误差,就得到了训练误差

关键区别:当f依赖于S时(即 f = A(S)),训练误差 R_S(A(S)) 不再是泛化误差 R(A(S)) 的无偏估计。过度优化训练误差可能导致过拟合,即模型在训练集上表现很好,但在新数据上泛化能力很差。

因此,训练误差和泛化误差是两个不同的概念,训练误差不能代表模型在新数据上的表现。


4. 验证:训练集/测试集划分

上一节我们指出了使用相同数据训练和评估的问题。本节中我们来看看如何通过数据划分来解决它。

为了可靠地评估模型性能,我们需要一个与训练过程独立的数据集。标准做法是将原始数据集 S 随机划分为两部分:

  • 训练集 S_train:用于训练模型,得到预测函数 f = A(S_train)
  • 测试集 S_test:用于评估模型,计算测试误差 R_{S_test}(f)

由于 S_test 独立于 S_train,因此函数f也独立于 S_test。这样,测试误差 R_{S_test}(f) 就是泛化误差 R(f) 的一个无偏估计,我们可以用它来*似真实性能。

权衡:划分比例(如70%/30%, 80%/20%)是一个需要权衡的问题。更多的训练数据通常能得到更好的模型,而更多的测试数据则能让性能评估更可靠、方差更小。


5. 泛化误差的理论控制

我们不仅希望用测试误差来估计泛化误差,更希望从理论上知道这种估计的可靠程度。

5.1 霍夫丁不等式

我们的目标是控制泛化误差 R(f) 与经验误差 R_S(f) 之间的差距(即泛化差距)。这依赖于一个重要的概率工具——霍夫丁不等式

定理(霍夫丁不等式):设 Z₁, ..., Zₙ 是n个独立同分布的随机变量,且满足 a ≤ Z_i ≤ b。令其均值为 μ = 𝔼[Z_i],则对于任意 ε > 0,有:
P( |(1/n)Σ Z_i - μ| ≥ ε ) ≤ 2 exp( -2nε²/(b-a)² )

这个不等式表明,样本均值会以很高的概率集中在真实均值附*,偏离超过ε的概率随着样本量n增加而指数级下降。

5.2 应用于泛化误差控制

将霍夫丁不等式应用于我们的问题:令 Z_i = L(Y_i, f(X_i)),并假设损失函数有界,即 a ≤ L(·, ·) ≤ b。那么,对于任意给定的失败概率 δ > 0,我们可以推导出,以至少 1-δ 的概率,泛化差距满足:
|R(f) - R_S(f)| ≤ (b-a) √( log(2/δ) / (2n) )

结论解读

  1. 样本量n:所需样本量与 1/√n 成正比。样本越多,估计越准。
  2. 置信度δ:对数值 log(1/δ) 出现在公式中,这意味着即使要求极高的置信度(δ非常小),所需代价也很小。
  3. 损失范围(b-a):损失函数的范围直接影响界限。范围越大,估计越不确定。

这个结果为模型性能提供了概率性证书:我们可以说,有95%的把握,模型的真实误差不超过测试误差加上某个计算出的偏差值。


6. 模型选择的理论保证

上一节我们解决了单个模型评估的问题。本节中我们来看看如何为从多个模型中选出的最佳模型提供保证。

6.1 模型选择流程

假设我们有K个不同的超参数设置 {λ₁, ..., λ_K},对应K个模型。模型选择的标准流程如下:

  1. 将数据S划分为训练集 S_train 和测试集 S_test
  2. S_train 上分别用每个λ训练模型,得到K个预测函数 f₁, ..., f_K
  3. S_test 上计算每个函数的测试误差 R_{S_test}(f_k)
  4. 选择测试误差最小的模型,即 k* = argmin_k R_{S_test}(f_k)

6.2 理论分析:控制最大偏差

我们想知道,选出来的模型 f_{k*} 的泛化误差 R(f_{k*}),与理论上所有模型中最好的泛化误差 min_k R(f_k) 相比,到底差多少。

我们需要同时控制所有K个模型的泛化差距。利用联合界,我们可以得到:
以至少 1-δ 的概率,对于所有k=1,...,K,同时有:
|R(f_k) - R_{S_test}(f_k)| ≤ (b-a) √( log(2K/δ) / (2n_{test}) )

与单个模型的界限相比,这里多了一个 log(K) 项。这意味着即使尝试大量(K很大)不同的模型,我们付出的代价也只是对数级的,这是可以接受的。

6.3 最终性能保证

基于上述一致收敛界限,我们可以证明以下关键结果:
以高概率,我们选出的模型 f_{k*} 的泛化误差满足:
R(f_{k*}) ≤ min_{k} R(f_k) + 2 (b-a) √( log(2K/δ) / (2n_{test}) )

结论:通过测试集选择出的模型,其性能与候选模型中理论上的最佳性能之间的差距,被一个与 log(K)/√n 成正比的量所控制。这为模型选择流程的有效性提供了理论依据。

重要提醒:一旦我们使用测试集做出了选择决策,这个测试集就被“污染”了,不能再用于提供最终模型的公正评估。因此,在严谨的流程中,需要进一步将数据划分为训练集验证集(用于模型选择)和测试集(用于最终评估)。


7. 交叉验证

简单的训练集/测试集划分会浪费部分数据。为了提高数据利用效率,实践中广泛使用交叉验证方法。

7.1 K折交叉验证流程

以下是K折交叉验证的步骤:

  1. 将数据集S随机划分为K个大小*似相等的子集(折)S₁, S₂, ..., S_K
  2. 对于每一折 i = 1 to K
    • S_i 作为验证集
    • 将其他K-1折的数据合并,作为训练集
    • 在训练集上训练模型,并在验证集 S_i 上计算误差 E_i
  3. 最终的交叉验证误差估计是K次验证误差的*均值:CV_error = (1/K) Σ_{i=1}^{K} E_i

7.2 优势与注意事项

  • 优势:每个数据点都既被用于训练,也被用于验证一次,数据利用率高,评估结果通常更稳定。
  • 复杂度:需要训练模型K次,计算成本是单一训练的K倍。
  • 模型选择:我们可以对每个候选超参数λ计算其CV_error,然后选择*均验证误差最小的λ。
  • 最终模型:在选出最佳λ后,通常会使用全部数据重新训练一个最终模型。

8. 总结

本节课中我们一起学习了机器学习中关于评估与选择模型的核心知识。

我们首先定义了泛化误差作为衡量模型性能的根本指标,并指出了其不可直接计算的困难。为此,我们引入了经验误差作为估计,并强调了训练误差因其与模型的依赖性而不能用于可靠评估。

为了解决评估问题,我们介绍了训练集/测试集划分的方法,并利用霍夫丁不等式从理论上给出了泛化误差的概率性上界,为模型性能提供了可量化的保证。

接着,我们将理论扩展到模型选择场景,证明了通过最小化测试误差来选择超参数是有效的,选出的模型性能与理论最优的差距是可控的。

最后,我们简要介绍了更高效的K折交叉验证方法,它通过多次训练-验证循环来更充分地利用数据,以获得更稳健的模型性能估计。

理解泛化、验证和模型选择是构建实用、可靠机器学习系统的基石。这些概念将贯穿于后续所有更复杂的模型(如分类器、神经网络)的学习与使用过程中。

11:偏差-方差分解 📊

在本节课中,我们将学习一个机器学习中的核心概念:偏差-方差分解。我们将探讨模型复杂度如何影响预测性能,并理解为什么有时简单的模型表现不佳,而过于复杂的模型也可能存在问题。我们将通过一个具体的回归例子,并推导出总风险的数学分解,从而清晰地看到偏差、方差和噪声这三个组成部分。

上一节我们讨论了如何通过训练集和测试集来评估模型性能。本节中,我们将深入分析模型复杂度对泛化误差的影响。

引言:模型复杂度的挑战

我们面临一个核心问题:如何为我们的问题选择合适复杂度的模型?例如,在多项式回归中,我们应该使用一次多项式(线性模型)还是九次多项式?模型的最大阶数 D 决定了模型类的复杂度。D 值小,模型简单;D 值大,模型复杂。

以下是两种极端情况:

  • 模型过于简单(如 D=1:模型无法捕捉数据中的潜在模式(例如非线性关系),导致对数据的拟合不佳。
  • 模型过于复杂(如 D=9:模型可以完美拟合训练数据(训练损失接*零),但其预测函数对训练数据中的随机噪声过于敏感,导致在新数据上表现不稳定。

为了理解这种现象,我们需要考虑数据本身的随机性。我们观察到的数据 y 是真实函数值 f(x) 加上随机噪声 ε 的结果:y = f(x) + ε。即使真实函数 f 是固定的,不同的训练集(由于噪声不同)也会产生不同的预测函数。

偏差-方差分解的推导

我们的目标是分析期望风险如何随训练集 S 和模型复杂度变化。我们固定一个测试点 x₀,并考察预测函数 f_S 在该点的期望*方误差。

我们假设以下数据生成模型:

  • x 服从某个固定但未知的分布。
  • y = f(x) + ε,其中 f 是未知的真实函数。
  • 噪声 ε 均值为零(E[ε] = 0),方差为 Var(ε),且与 x 独立。

学习算法 A 根据训练集 S 给出预测函数 f_S。在点 x₀ 的期望损失(风险)为:
L(f_S) = E_ε[(y - f_S(x₀))²],其中 y = f(x₀) + ε

我们关心的是这个风险在不同训练集上的*均表现,即 E_S[L(f_S)]。通过数学推导,我们可以将此期望风险分解为三个非负项之和:

期望风险 = 噪声方差 + (偏差)² + 方差

具体公式如下:
E_S[L(f_S)] = Var(ε) + (f(x₀) - E_S[f_S(x₀)])² + E_S[(f_S(x₀) - E_S[f_S(x₀)])²]

接下来,我们详细解释每一项的含义。

分解项的解读

1. 噪声方差 (Irreducible Error)

Var(ε) 项代表了数据中无法消除的随机噪声。即使我们知道了真实函数 f,预测误差的期望也不会低于这个值。它给出了模型性能的理论下限。

2. 偏差² (Bias)

(f(x₀) - E_S[f_S(x₀)])² 项衡量了*均预测真实值之间的差距。它反映了模型由于本身过于简单而无法捕捉真实关系所导致的系统性误差。

  • 高偏差:模型“欠拟合”,*均预测偏离真实值较远。通常发生在模型复杂度较低时。
  • 低偏差:模型足够灵活,*均预测接*真实值。通常需要较高的模型复杂度。

3. 方差 (Variance)

E_S[(f_S(x₀) - E_S[f_S(x₀)])²] 项衡量了单个预测函数相对于*均预测函数的波动程度。它反映了模型对训练集中特定随机性的敏感度。

  • 高方差:模型“过拟合”,训练数据的微小变化会导致预测函数的巨大改变。通常发生在模型复杂度过高时。
  • 低方差:模型预测稳定,不同训练集得到的预测函数彼此接*。通常发生在模型复杂度较低时。

偏差-方差权衡

总风险是偏差、方差和噪声之和。噪声是固定不可控的,因此我们的目标是最小化偏差和方差之和。然而,偏差和方差通常随模型复杂度变化趋势相反,形成权衡关系。

以下是模型复杂度对各项的影响:

  • 低复杂度模型:高偏差,低方差。
  • 高复杂度模型:低偏差,高方差。
  • 最优复杂度:存在于中间某点,此时偏差和方差之和最小,总风险最低。

这种关系通常导致总风险曲线呈U形。选择模型的任务就是在偏差和方差之间找到最佳*衡点,使总期望风险最小化。

现代机器学习中的新现象

需要指出,上述经典的偏差-方差权衡描述主要适用于参数数量适中或少于样本数的“欠参数化”模型。在现代深度学习领域,我们经常使用“过参数化”模型(参数远多于样本)。

有趣的是,在这些极其复杂的模型中,有时会出现“双重下降”现象:随着模型复杂度增加到远超插值点(训练误差为零),测试风险会再次下降,甚至低于经典权衡理论预测的最优风险。这被称为“良性过拟合”,是当前研究的热点。它表明,对于特定的模型族(如深度神经网络)和优化算法(如随机梯度下降),偏差-方差关系可能比经典理论描述更为复杂。

总结

本节课我们一起学习了偏差-方差分解。我们了解到,模型的泛化误差可以分解为不可约的噪声、偏差和方差三部分。偏差衡量了模型的系统性误差,方差衡量了模型对数据扰动的敏感性。在模型选择中,我们面临着偏差与方差的权衡,目标是通过选择合适的模型复杂度来最小化总误差。最后,我们也了解到在深度学习等现代范式中,这种经典关系可能会有新的表现形式。理解这一概念对于诊断模型问题和指导模型设计至关重要。

12:练习4 - 入门指南 📚

在本节课中,我们将学习如何执行交叉验证,并利用它来选择最佳模型。我们还将探究一个称为偏差-方差分解的现象。

概述 📋

本次练习将引导你完成交叉验证的实现过程。你需要使用之前在练习2和练习3中编写的代码,并将其应用到新的函数中,以评估不同模型参数下的性能。

准备工作 🛠️

在开始之前,你需要复制之前练习中的代码。

以下是需要复制的函数:

  • 从练习2复制的最小二乘法函数
  • 从练习3复制的岭回归函数
  • 用于分割数据的函数。

请将这些函数复制到本次练习指定的文件中。

实现交叉验证函数 🔧

上一节我们介绍了准备工作,本节中我们来看看如何实现核心的交叉验证函数。

你需要填写 cross_validation 函数中的代码。此函数旨在计算对应于一个子组的训练误差和测试误差。

该函数接收以下输入:

  • y 值和 x 值(整个训练数据)。
  • 一组索引 k_indices,代表第 k 个子组。
  • 回归参数 lambda
  • 用于多项式回归的阶数 degree

k_indices 对应的子组应作为测试数据集。所有其他不在 k_indices 中的索引应作为训练数据集

使用这个测试和训练数据集,你应该运行一个指定 degreelambda 参数的多项式岭回归

然后,计算训练损失和测试损失,并将其作为输出返回。

核心计算步骤可以用伪代码描述如下:

# 1. 根据 k_indices 分割数据
x_train, y_train = x[~k_indices], y[~k_indices]
x_test, y_test = x[k_indices], y[k_indices]

# 2. 构建多项式特征(假设有 expand_features 函数)
phi_train = expand_features(x_train, degree)
phi_test = expand_features(x_test, degree)

# 3. 使用岭回归求解权重 w
w = ridge_regression(phi_train, y_train, lambda_)

# 4. 计算均方误差 (MSE)
train_loss = mean_squared_error(y_train, phi_train @ w)
test_loss = mean_squared_error(y_test, phi_test @ w)

评估正则化参数 λ 的影响 📊

接下来,我们将使用上面实现的函数来评估不同正则化参数 lambda 的影响。

我们将运行一个 7阶 的多项式岭回归,并让正则化参数 lambda10^{-4}1 的范围内变化。

对于每个 lambda 值,我们将执行 4折交叉验证。这意味着将数据集分成4部分,并调用 cross_validation 函数4次,每次使用不同的部分作为测试集。

以下是执行流程:

  1. 将数据随机分成4个折叠。
  2. 对于每个 lambda 值,进行4折交叉验证。
  3. 存储每次折叠得到的训练和测试误差。

正确实现代码后,你应该能看到一个类似的图表。请注意,由于交叉验证的数据分割是随机的,你的图表可能不会与示例完全一致。

评估多项式阶数的影响 🔬

在第二部分,我们将改变多项式回归的阶数,观察其影响,而不是改变正则化参数 lambda

代码结构与之前非常相似。我们将反复调用 cross_validation 函数,计算训练和测试误差的均值。

我们将使用 100 次不同的数据分割 来运行交叉验证,并绘制随着多项式阶数增加,训练误差和测试误差的变化情况。

你应该能得到一个类似的图表。图中:

  • 粗线 代表这100次重复交叉验证的均值
  • 细线 代表每次单独的运行结果。

每种颜色的细线分布范围代表了方差,而粗线代表了均值。请注意方差如何随着阶数的增加而变化。

扩展任务 💡

本次练习还包含一些扩展问题,要求你不仅计算交叉验证的*均误差,还要计算这些误差的方差。这有助于更深入地理解模型的稳定性。

总结 🎯

本节课中我们一起学习了:

  1. 交叉验证 的基本原理和实现方法,包括如何分割数据、训练模型并计算误差。
  2. 如何利用交叉验证来评估不同模型参数(如正则化强度 lambda 和多项式阶数 degree)对模型性能的影响。
  3. 通过可视化结果,观察了模型复杂度变化时,训练误差与测试误差的关系以及误差方差的变化,这直接关联到偏差-方差分解的概念。

希望这些练习能帮助你巩固对模型选择和评估的理解。我们周四见!

13:分类问题入门 🎯

在本节课中,我们将要学习机器学习中的核心任务之一:分类。我们将从定义分类问题开始,探讨其与回归问题的区别,并介绍几种基础的分类方法。

概述 📋

分类是监督机器学习中继回归之后最基础的任务之一。与回归不同,分类的输出变量是离散的、类别型的。本节课我们将介绍分类问题的基本框架、核心挑战以及几种初步的解决方法。

什么是分类? 🤔

在监督机器学习中,我们观察一个数据集 S,它包含输入 X_i 和输出 Y_i。分类问题的主要区别在于,输出 Y 属于一个离散的集合 Y

目标:给定一个新的输入 X,预测其对应的标签 Y

这与回归的框架完全相同,核心区别在于输出变量是类别型的,只能取离散值。

二元分类与多元分类

  • 二元分类:输出 Y 只能取两个值,例如两个类别 C1C2。我们通常用 01-11 来命名这些类别。重要的是,这些数字仅仅是标签,没有顺序关系(例如,0 并不比 1 “小”)。
  • 多元分类:输出 Y 可以取 K 个不同的值,对应 K 个类别,例如 0K-1

分类问题示例 📧🐱🐶

以下是几个分类问题的典型例子:

  • 垃圾邮件检测:输入是一封邮件,输出是“正常邮件”(类别1)或“垃圾邮件”(类别0)。标签 01 可以互换,不影响问题本质。
  • 图像分类:输入是一张图片,输出是图片内容的标签,例如“猫”或“狗”。
  • 信用卡违约预测:输入是客户的收入、信用余额等特征,输出是客户“会违约”(类别1)或“不会违约”(类别0)。通过历史数据,我们可以学习一个模型来预测新客户的违约风险。

分类器与决策边界 📐

分类器是一个函数,它将输入空间 X 映射到输出集合 Y。它的作用是将输入空间划分为属于不同类别的区域。

  • 决策边界:这些区域之间的分界线。当输入跨越决策边界时,预测的类别就会改变。
  • 线性分类器:决策边界是线性的(在二维空间中是直线,高维空间中是超*面)。
  • 非线性分类器:决策边界是非线性的。值得注意的是,通过特征变换(例如多项式扩展),一个在扩展特征空间中的线性分类器,在原始特征空间中可能表现为非线性分类器。

上一节我们介绍了分类问题的基本定义和示例,本节中我们来看看能否用回归的方法来解决分类问题。

将分类视为回归:可行吗? ⚠️

由于分类可以看作是输出受限的回归问题,一个自然的想法是:能否直接使用回归技术(如最小二乘法)来解决分类问题?

思路

  1. 将类别标签数值化(例如,类别0设为 0,类别1设为 1)。
  2. 使用最小二乘法拟合数据,得到一个线性模型 f(x) = w^T x
  3. 对于新样本 x,计算 f(x),并通过一个阈值(如 0.5)将其转换为类别预测:若 f(x) > 0.5 则预测为类别1,否则预测为类别0。

存在的问题

尽管直观,但这种方法存在几个严重问题:

  1. 概率解释不合理:最小二乘法的预测值 f(x) 可能不在 [0, 1] 区间内,难以解释为概率。
  2. 对类别不*衡敏感:当两类样本数量差异巨大时,最小二乘拟合的直线会严重偏向多数类,导致决策边界不合理,对少数类的预测效果很差。
  3. 对“简单”样本敏感:在分类中,那些特征值极端且标签明确的样本(如债务极高且违约的客户)是“简单”样本,应能轻松预测正确。但在最小二乘中,这些点会像回归中的“离群值”一样,显著地拉动拟合直线,扭曲决策边界。
  4. 损失函数不匹配:分类的核心目标是最小化错误分类的数量。而最小二乘的*方损失函数惩罚的是预测值与标签 0/1 之间的数值差距,这与我们关心的“对/错”度量并不一致。一个预测函数可能有较大的均方误差,但仍然是一个好的分类器。

因此,我们需要为分类问题设计专门的方法。

分类方法初探 🗺️

解决分类问题的核心是为输入空间找到决策边界,将其划分为不同的决策区域。本节课我们将简要介绍几种基础方法,后续课程会深入分析。

1. 最*邻法 👑

最*邻法基于一个核心假设:在特征空间中相*的样本,其类别标签也 likely 相同。

算法:对于一个新样本点 x,在训练集中找到与它距离最*的样本,然后将该最*邻的标签赋予 x

以下是最*邻法的优缺点:

  • 优点
    • 无需训练/优化过程。
    • 易于理解和实现。
    • 在低维空间中,能拟合非常复杂的决策边界。
  • 缺点
    • 预测时速度慢:每次预测都需要计算与所有训练样本的距离,复杂度为 O(N),其中 N 是训练集大小。
    • 高维灾难:在高维空间中,数据点之间*均距离很大,很难找到真正“邻*”的样本,导致预测不准。
    • 距离度量选择关键:使用不同的距离度量(如欧氏距离、曼哈顿距离)会得到不同的结果。

K*邻法

一个自然的扩展是考虑 K 个最*邻,而不仅仅是一个。

算法:对新样本 x,找出训练集中距离最*的 K 个点,然后通过投票决定 x 的类别(即这 K 个点中占多数的类别)。

  • *滑核方法:可以进一步为不同距离的邻居赋予不同的权重,距离越*权重越高。

K*邻法引入了超参数 K,其选择涉及到偏差-方差权衡,我们将在后续课程中讨论。

2. 线性分类器与最大间隔超*面 📏

另一种思路是假设决策边界是线性的(一个超*面)。对于样本 x,预测规则为:
预测类别 = sign( w^T x )
其中 sign 是符号函数。若结果为正,预测为一类;为负,则预测为另一类。(注:通常会增加偏置项 w0,或通过添加常数特征 1 来实现)。

线性可分与最大间隔

当存在一个超*面能完美分开所有训练样本时,我们称数据是线性可分的。此时,这样的超*面通常有很多个。

问题:应该选择哪一个?

答案:选择最大间隔超*面。间隔定义为超*面到所有训练样本的最小距离。最大化这个间隔的超*面被认为是最鲁棒的,因为它对数据中的小扰动和噪声最不敏感,泛化能力通常更好。

支持向量机(SVM)就是寻找(或*似寻找)最大间隔超*面的经典算法,我们将在后续课程中详细讲解。逻辑回归在某种意义上也与最大间隔的思想相关。

3. 引入非线性:特征变换 🌀

对于非线性可分的数据,线性分类器表现会很差。与回归类似,我们可以通过特征变换引入非线性。

方法:将原始特征 x 映射到更高维的特征空间 φ(x)(例如,添加多项式特征 x^2, x^3, x1*x2 等)。然后在这个新的高维空间中学习一个线性分类器。当把这个线性决策边界映射回原始特征空间时,它就变成了非线性的。

挑战:直接进行特征变换可能会显著增加计算复杂度(维度灾难)。

解决方案(后续课程):核方法。它允许我们在极高维(甚至无限维)的特征空间中隐式地工作,而无需显式计算这些特征,从而避免了计算成本激增的问题。

分类的理论基础:贝叶斯最优分类器 🧠

最后,我们从理论角度探讨分类问题的极限性能。我们假设数据 (X, Y) 服从某个未知的联合分布 D

分类损失与风险

对于分类问题,最自然的损失函数是 0-1 损失
L(y, y') = 1 如果 y ≠ y',否则为 0
其中 y 是真实标签,y' 是预测标签。

分类器 g真实风险(泛化误差)是该损失的期望:
R(g) = E[ L(Y, g(X)) ] = P( Y ≠ g(X) )
这正好就是分类器出错的概率。

贝叶斯最优分类器

在所有可能的分类器中,那个能最小化真实风险 R(g) 的分类器,称为贝叶斯最优分类器 g*。即使拥有无限数据且知道真实分布,我们也不能做得比它更好。

g* 有一个简洁的形式:对于给定的输入 x,它输出后验概率最大的那个类别。
g*(x) = argmax_y P( Y = y | X = x )
直观理解:对于每个 x,选择最可能出现的那个类别,这样*均错误率最低。

(注:课程幻灯片中提供了该结论的简要证明。)

一个重要的理论联系

一个有趣的理论结果是:如果一个回归函数 f(x) 能够很好地*似条件期望 E[Y|X=x](即均方误差很小),那么由它通过阈值法导出的分类器,其分类错误率也会被限定在一个较小的范围内。但这不意味着所有回归方法都适合做分类,它只说明均方误差很小是分类效果好的一个充分条件,而非必要条件。

总结 🎓

本节课中我们一起学习了:

  1. 分类问题的定义:输出为离散类别的监督学习任务。
  2. 直接使用回归方法的缺陷:包括概率解释不清、对不*衡数据敏感、损失函数不匹配等。
  3. 几种基础分类方法
    • 最*邻法:基于局部相似性,简单但预测慢,高维效果差。
    • 线性分类器与最大间隔:寻找一个分离超*面,最大间隔原则提供了鲁棒性。
    • 特征变换:通过将数据映射到高维空间来实现非线性分类。
  4. 分类的理论基础:0-1损失函数、真实风险(错误率)以及理论上限——贝叶斯最优分类器。

这只是分类学习的入门。在接下来的课程中,我们将深入探讨逻辑回归、支持向量机、决策树等具体算法,并分析它们的理论性质与实践应用。

14:逻辑回归 🧠

概述

在本节课中,我们将要学习逻辑回归。这是一种用于二元分类的基础且经典的方法。我们将了解其动机、核心概念、模型定义、训练方法以及优化算法。


1. 二元分类问题回顾 📊

上一节我们介绍了分类问题的基本设定。本节中,我们来看看逻辑回归要解决的具体问题。

在监督学习中,我们有一个数据集 S,包含 n 个观测值 (xᵢ, yᵢ),其中 i 从 1 到 n。输入 x 属于某个集合 X,输出 y 属于标签集。对于今天的二元分类,我们设定标签集为 {0, 1}

我们的目标是:给定一个新的观测值 x,预测其对应的标签 y,即判断它属于哪个类别。我们使用训练数据 (xᵢ, yᵢ) 和某种学习算法来训练一个分类器,并用它进行预测。

符号说明

  • 小写 xᵢ, yᵢ 通常表示固定的观测值(向量)。
  • 大写 X, Y 通常表示随机变量。
  • 粗体 X 表示包含所有特征 x₁xₙ 的设计矩阵。

2. 逻辑回归的动机 🤔

上一节我们提到,分类问题可以不直接预测输出 0 或 1,而是去建模概率。例如,我们预测客户违约的概率,而不是直接预测“违约”或“不违约”。如果属于类别 1 的概率大于 0.5,我们就预测类别 1,否则预测类别 0。

那么,如何学习这个概率呢?我们曾尝试用线性回归来解决分类问题,即假设概率是 x 的线性函数:P(y=1|x) = wᵀx。但这带来了两个问题:

  1. 预测值不在 [0, 1] 区间内:线性函数的输出可以是任意实数,包括负数或大于 1 的数,这无法解释为概率。
  2. 对极端值敏感:对于预测值非常大(或非常小)的点,即使模型已经非常确信其类别,*方损失函数仍然会施加很大的惩罚。实际上,对于这些容易预测的点,我们希望模型能以很高的置信度给出接* 1(或 0)的概率,而不是承受巨大的损失。

因此,我们希望找到一个方法,能将线性模型的输出(范围是 (-∞, +∞)映射到概率区间 [0, 1]。这样,当线性预测值非常大时,概率就接* 1;当线性预测值非常负时,概率就接* 0。

逻辑回归使用一个特定的函数来完成这个映射,即逻辑函数(Logistic Function),也称为 Sigmoid 函数。


3. 逻辑函数(Sigmoid)📈

逻辑函数是一个历史悠久的函数,其定义如下:

对于一个实数 η,逻辑函数 σ(η) 定义为:
σ(η) = e^η / (1 + e^η)

这个函数具有典型的 S 形曲线。它具有以下关键性质:

  • η = 0 时,σ(η) = 0.5
  • η → +∞ 时,σ(η) → 1
  • η → -∞ 时,σ(η) → 0
  • 函数值始终在 (0, 1) 区间内。

因此,它完美地将整个实数轴映射到了 (0, 1) 区间,满足了我们将线性输出转化为概率的需求。

逻辑函数还有一些有用的数学性质,我们将在推导中用到:

  1. 1 - σ(η) = 1 / (1 + e^η)
  2. 导数σ‘(η) = σ(η) * (1 - σ(η))。由于 σ(η)(1 - σ(η)) 都大于 0,所以导数恒为正,说明逻辑函数是单调递增的。


4. 逻辑回归模型定义 🧩

现在,我们使用逻辑函数来建模概率。这就是逻辑回归名称中“逻辑”的由来。

逻辑回归模型定义观测值 x 属于类别 1 的概率为:
P(y=1|x) = σ(wᵀx + w₀)

其中,wᵀx + w₀ 是我们的线性预测部分。相应地,属于类别 0 的概率为:
P(y=0|x) = 1 - P(y=1|x) = 1 - σ(wᵀx + w₀)

这里,两个类别是对称的,我们可以互换类别 0 和 1 的定义。

为什么叫“回归”?
因为我们的第一步是“回归”出一个概率值(一个连续值),第二步才是根据这个概率值进行“分类”决策。具体决策规则是:

  • 如果 P(y=1|x) > 0.5,则预测 ŷ = 1
  • 如果 P(y=1|x) < 0.5,则预测 ŷ = 0

由于 σ(η) > 0.5 等价于 η > 0,所以决策规则可以简化为:

  • 如果 wᵀx + w₀ > 0,则预测 ŷ = 1
  • 如果 wᵀx + w₀ < 0,则预测 ŷ = 0

关于偏移项 w₀ 的说明
在实践中,w₀(常被称为偏置项)非常重要,因为它允许决策边界不强制通过原点。为了简化记号,我们通常会在特征向量 x 前面添加一个恒为 1 的维度,这样 w₀ 就可以合并到权重向量 w 中,模型简化为 P(y=1|x) = σ(wᵀx),其中 xw 的维度都增加了 1。在应用时,切记要在特征中添加常数项 1


5. 模型参数的影响 🎛️

理解权重向量 w 和偏移 w₀ 如何影响模型预测至关重要。

  • w 的方向:决定了决策边界(即概率为 0.5 的等高线)的方向。决策边界是一个超*面,其法向量就是 w。改变 w 的方向,就旋转了这个决策*面。
  • w 的模长(尺度):决定了从概率 0 到概率 1 的过渡速度
    • 如果 ||w|| 很小,过渡非常*缓,模型很少会给出非常接* 0 或 1 的概率(即预测置信度低)。
    • 如果 ||w|| 很大,过渡非常陡峭,逻辑函数接*阶跃函数,模型通常会给出非常接* 0 或 1 的概率(即预测置信度高)。
    • 对于单纯的分类决策(0或1),尺度影响不大。但对于需要评估预测置信度或不确定性的场景,尺度非常重要。
  • w₀:决定了决策边界沿法向量 w 方向的位移。改变 w₀,决策边界会*行移动。


6. 训练逻辑回归模型:最大似然估计 🏋️

前面我们知道了如何用给定的参数 w 做预测。现在,我们学习如何从数据中学习出参数 w。我们将采用最大似然估计(MLE) 方法。

MLE 是一种参数估计方法。其核心思想是:寻找一组模型参数,使得在这组参数下,观测到当前数据的可能性(似然)最大

6.1 似然函数

首先,我们假设观测数据 (xᵢ, yᵢ) 是独立同分布的。我们需要计算在参数 w 下,观察到整个数据集 {X, y} 的似然 P(y, X | w)

利用概率链式法则和 X 独立于 w 的假设(这是一个常见的建模假设),我们可以将似然写为:
P(y, X | w) = P(X | w) * P(y | X, w) ∝ P(y | X, w)
其中 表示“正比于”。因为 P(X | w) 不依赖于 w,在最大化似然时可以被忽略。

由于数据点独立,P(y | X, w) 可以写成每个数据点概率的乘积:
P(y | X, w) = ∏ᵢ P(yᵢ | xᵢ, w)

对于每个数据点,其概率根据我们的模型是:

  • yᵢ = 1P(yᵢ=1 | xᵢ, w) = σ(wᵀxᵢ)
  • yᵢ = 0P(yᵢ=0 | xᵢ, w) = 1 - σ(wᵀxᵢ)

我们可以将这两种情况统一写成一个紧凑的形式:
P(yᵢ | xᵢ, w) = [σ(wᵀxᵢ)]^{yᵢ} * [1 - σ(wᵀxᵢ)]^{1 - yᵢ}
可以验证,当 yᵢ = 1yᵢ = 0 时,上式分别退化为前两种情况。

因此,整个数据集的似然函数为:
L(w) = ∏ᵢ [σ(wᵀxᵢ)]^{yᵢ} * [1 - σ(wᵀxᵢ)]^{1 - yᵢ}

6.2 负对数似然损失函数

乘积形式不易处理,我们通常取其对数将乘积变为求和。同时,为了将其转化为一个最小化问题(与优化惯例一致),我们取负对数似然作为我们的损失函数 J(w)

J(w) = -log L(w) = -∑ᵢ [ yᵢ log(σ(wᵀxᵢ)) + (1 - yᵢ) log(1 - σ(wᵀxᵢ)) ]

利用逻辑函数的性质 1 - σ(η) = 1/(1+e^η)σ(η) = e^η/(1+e^η),我们可以进一步简化上述表达式(推导过程略),得到一个更简洁的形式:

J(w) = ∑ᵢ [ log(1 + exp(wᵀxᵢ)) - yᵢ (wᵀxᵢ) ]

J(w) 就是逻辑回归的损失函数(也称为交叉熵损失)。我们的目标就是找到 w* 来最小化这个损失函数:w* = argmin_w J(w)

注意:如果我们将标签定义为 {-1, +1} 而不是 {0, 1},会得到一个形式上略有不同的损失函数。在实际使用不同库的实现时需要注意这一点。


7. 优化损失函数 ⚙️

我们已经得到了凸的损失函数 J(w)。现在需要找到最小化它的方法。

7.1 梯度

首先计算损失函数 J(w) 关于 w 的梯度。经过计算(推导过程略),梯度为:

∇J(w) = ∑ᵢ [ (σ(wᵀxᵢ) - yᵢ) xᵢ ] = Xᵀ (σ(Xw) - y)

其中 X 是设计矩阵,y 是标签向量,σ 被逐元素地应用于向量 Xw

这个梯度形式与线性回归的梯度 Xᵀ(Xw - y) 非常相似,只是多了一个逻辑函数 σ。正是这个 σ 使得方程 ∇J(w) = 0 没有闭式解,我们必须使用迭代优化算法。

7.2 优化算法

以下是几种常用的优化算法:

  1. 梯度下降(GD)

    • 更新公式w_{t+1} = w_t - α ∇J(w_t)
    • 特点:每步需要计算整个数据集的梯度(O(n) 复杂度)。当数据集很大(n 很大)时,每一步的计算成本很高。
  2. 随机梯度下降(SGD)

    • 更新公式w_{t+1} = w_t - α ∇J_i(w_t),其中 i 是在每一步随机从 {1,...,n} 中选取的索引,∇J_i(w) = (σ(wᵀxᵢ) - yᵢ) xᵢ 是单个样本的梯度。
    • 特点:每一步只用一个样本估计梯度,计算成本为 O(1),非常适合大数据集。虽然每一步的方向噪声较大,但*均来看方向是正确的。通常,在考虑总计算成本时,SGD 比 GD 更快收敛到解附*。

  1. 牛顿法
    • 思想:不仅使用一阶梯度信息,还使用二阶海森矩阵信息来考虑损失函数的曲率。
    • 更新公式w_{t+1} = w_t - α [H(w_t)]⁻¹ ∇J(w_t),其中 H(w_t)J(w)w_t 点的海森矩阵。
    • 特点:收敛速度非常快(二次收敛)。但每一步需要计算并求逆海森矩阵(或等价地求解一个线性系统),计算复杂度高达 O(d³)d 为特征维度),对于高维问题不实用。其变种(如拟牛顿法)试图在速度和成本间取得*衡。


8. 线性可分与正则化 ⚖️

当一个数据集是线性可分的,即存在一个超*面能完美分开两类数据时,逻辑回归的优化会遇到一个理论问题:损失函数 J(w)下确界是 0,但这个最小值无法在有限的 w 处取得。为了达到任意小的损失,权重向量 w 的模长需要趋向于无穷大。

从优化角度看,算法可能不会收敛,权重会不断增长。从统计角度看,这可能导致过拟合,模型泛化能力差。

解决方案是引入正则化,最常见的是 L2 正则化(也称为岭回归)。我们在损失函数中加入权重的*方和作为惩罚项:

J_reg(w) = J(w) + (λ/2) ||w||²

其中 λ > 0 是正则化强度超参数。这个附加项惩罚过大的权重,确保最优解在有限处取得,并且通常能提升模型的泛化性能。

一个有趣的现象是:即使在不加正则化的情况下,对线性可分数据使用 SGD 优化,权重模长会发散至无穷,但其方向会收敛到某个特定的方向,这个方向对应着最大间隔分类器(我们将在后续关于支持向量机的课程中讨论)。


总结

本节课中我们一起学习了逻辑回归。我们从二元分类问题出发,探讨了直接使用线性回归的不足,从而引出了使用逻辑函数将线性输出映射为概率的动机。我们详细定义了逻辑回归模型,并分析了模型参数对决策边界的影响。接着,我们通过最大似然估计推导出了逻辑回归的损失函数(负对数似然/交叉熵损失),并证明了该函数是凸函数。最后,我们介绍了用于优化此损失函数的几种算法:梯度下降、随机梯度下降和牛顿法,并讨论了在线性可分数据上可能遇到的问题及其解决方案——正则化。逻辑回归是理解更复杂分类模型(如神经网络)的重要基础。

15:逻辑回归与分类 🧠

在本节课中,我们将学习如何使用逻辑回归进行二元分类。我们将从使用线性回归进行简单分类开始,逐步过渡到更严谨的逻辑回归方法,并最终探讨正则化技术。本教程将引导你完成习题集中的核心任务。


练习一:使用线性回归进行分类 📈

上一节我们回顾了线性回归的基础。本节中,我们来看看如何将其应用于分类问题。虽然线性回归通常不适用于分类,但在处理简单数据时,它可以作为一个直观的起点。

我们将使用第一课中的身高体重数据,这次的目标是预测一个二元变量:性别。为了更好的可视化,代码会从数据中随机抽取200个点。

以下是需要你完成的核心步骤:

  1. 你需要将之前练习中的最小二乘法函数复制到当前文件中。
  2. 该函数将接收二元标签和已添加截距项的特征数据。
  3. 运行代码后,你将通过最小二乘法获得权重参数。

完成计算后,使用提供的可视化函数绘制数据点和决策边界。运行结果应类似于下图,其中蓝色和绿色区域分别代表模型预测的男性和女性类别。


练习二:实现逻辑回归 🔄

线性回归为分类提供了直观认识。本节中,我们将学习处理二元分类更根本的方法:逻辑回归。我们将分步实现它。

首先,我们需要实现 Sigmoid 函数。该函数将实数映射到 (0, 1) 区间,其公式如下:

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

在代码中,你可以这样实现:

def sigmoid(z):
    return 1.0 / (1.0 + np.exp(-z))

接下来,我们需要计算损失函数和梯度。以下是需要填写的两个函数:

  • 计算损失 (calculate_loss): 返回给定模型参数 w、特征数据 x 和标签 y 下的负对数似然。
  • 计算梯度 (calculate_gradient): 返回损失函数关于参数 w 的梯度。

这两个函数的公式可以在课程讲义中找到,你也可以自行推导。

有了损失和梯度计算函数后,我们就可以进行学习了。学习过程涉及对参数 w 执行一步梯度下降。

你需要实现函数 learning_by_gradient_descent,它计算当前损失和梯度,然后更新权重并返回。这样设计的原因是,在接下来的Jupyter Notebook单元格中,我们将使用学习率进行多次迭代训练。

完成训练后,可视化预测结果。你应该得到一个与之前类似的决策边界图,但这次是使用Sigmoid函数和逻辑回归的更严谨方法。


练习三:实现牛顿法 ⚡

我们已实现了梯度下降法。本节中,我们来看看一种更快的二阶优化方法:牛顿法。牛顿法需要使用海森矩阵 (Hessian)。

首先,实现 计算海森矩阵 (calculate_hessian) 函数。它接收标准参数,并返回损失函数关于参数 w 的海森矩阵。

然后,完成 逻辑回归 (logistic_regression) 函数。该函数应利用我们之前构建的所有功能,并返回损失、梯度和海森矩阵。注意,此函数不应更新参数 w,因为更新将在下一步进行。

最后,实现 牛顿法学习 (learning_by_newton_method) 函数,它执行一步牛顿法更新并返回损失及更新后的参数 w

完成上述步骤后,进行迭代学习。如果实现正确,你会发现牛顿法所需的迭代次数远少于梯度下降法。思考一下为什么会这样是很有益的。


练习四:添加正则化 🛡️

我们已经实现了基础逻辑回归及其优化。本节中,我们将在损失函数中加入正则化项以防止过拟合。

你需要实现 带惩罚项的逻辑回归 (penalized_logistic_regression) 函数。它返回正则化后的损失、梯度以及海森矩阵。

作为一个完整性检查,你可以将正则化系数 lambda_ 设为一个非常小的值。此时,正则化损失应*似等于未正则化的损失。

接着,实现 带惩罚项的学习步骤 (learning_by_penalized_gradient) 函数,它更新参数并返回损失。

最后,运行学习过程并再次可视化结果。这应该会生成一个与之前相似的决策边界图。


总结

本节课中,我们一起学习了分类问题的多种方法。我们从使用线性回归进行简单分类入手,然后深入实现了标准的逻辑回归模型,包括其损失函数、梯度以及使用梯度下降进行优化。接着,我们探索了更高效的牛顿法。最后,我们通过添加正则化项来增强模型的泛化能力。通过这些练习,你应该对二元分类的基本原理和实现有了扎实的理解。

16:指数族与广义线性模型 🧮

在本节课中,我们将要学习两个核心概念:指数族广义线性模型。我们将从回顾线性回归和逻辑回归的动机开始,理解如何将概率模型推广到更广泛的分布类别,并学习如何利用这些模型进行统一的机器学习建模。


动机:从线性回归到更广泛的模型 🔄

上一节我们介绍了线性回归和逻辑回归。本节中我们来看看如何将它们统一到一个更广泛的框架中。

在线性回归中,我们有两种方式得到最小二乘估计器:

  1. 几何方法:最小化残差*方和。
  2. 概率方法:假设数据来自一个带有高斯噪声的线性模型 y = x^T w + ε,然后通过最大似然估计来恢复参数 w

然而,线性模型对于许多复杂数据来说过于简单。我们通过特征增强(例如添加 x^2, x^3 等)来引入非线性。

另一种思路是考虑不同的概率模型。在线性回归中,线性预测 x^T w 直接预测了输出 y条件均值。在逻辑回归中,线性预测 x^T w 并不直接预测均值,而是预测了一个通过链接函数(sigmoid)与均值相关联的量。

这引出了一个问题:我们能否将这种思路推广到高斯分布和伯努利分布之外?答案是肯定的,这就是指数族广义线性模型


指数族分布 📊

指数族是一类非常重要的概率分布族,在统计学和信息论中广泛应用。它为许多常见的分布(如高斯、伯努利、泊松)提供了一个统一的表达形式。

一个分布属于指数族,如果其概率密度函数或质量函数可以写成以下形式:

p(y | η) = h(y) * exp( η^T φ(y) - A(η) )

以下是公式中各项的含义:

  • η自然参数典范参数
  • φ(y)充分统计量。它包含了从数据中估计参数 η 所需的全部信息。
  • h(y):一个只与 y 有关的非负函数。
  • A(η)对数配分函数累积量函数。它的作用是确保概率分布的归一化(积分为1)。其表达式为:
    A(η) = log( ∫ h(y) exp(η^T φ(y)) dy )
    

指数族的自由度由 h(y), φ(y)η 决定。我们只考虑使积分有限的 η 的集合,称为自然参数空间


实例:常见分布属于指数族 ✅

让我们验证几个常见分布确实是指数族成员。

1. 伯努利分布 (Bernoulli)

伯努利分布描述二值随机变量(如抛硬币)。其概率为:

P(y | μ) = μ^y * (1-μ)^(1-y), 其中 y ∈ {0, 1}

我们可以将其重写为指数族形式:

P(y | η) = exp( η y - log(1 + exp(η)) )

其中:

  • 自然参数η = log( μ / (1-μ) )
  • 充分统计量φ(y) = y
  • 对数配分函数A(η) = log(1 + exp(η))
  • 基函数h(y) = 1

这里的链接函数 glogit 函数η = g(μ) = log(μ/(1-μ))。其反函数,即均值函数,正是 sigmoid 函数μ = σ(η) = exp(η)/(1+exp(η))

2. 高斯分布 (Gaussian)

单变量高斯分布 N(μ, σ^2) 的概率密度函数为:

p(y | μ, σ^2) = 1/√(2πσ^2) * exp( -(y-μ)^2/(2σ^2) )

经过代数变换,可以写成:

p(y | η) = exp( η_1 y + η_2 y^2 - A(η) )

其中:

  • 自然参数η = [η_1, η_2]^T = [μ/σ^2, -1/(2σ^2)]^T
  • 充分统计量φ(y) = [y, y^2]^T
  • 对数配分函数A(η) = -η_1^2/(4η_2) - 1/2 log(-2η_2)
  • 基函数h(y) = 1/√(2π)

3. 泊松分布 (Poisson)

泊松分布常用于计数数据。其概率质量函数为:

P(y | μ) = (μ^y * e^{-μ}) / y!

可以重写为:

P(y | η) = (1/y!) * exp( η y - exp(η) )

其中:

  • 自然参数η = log(μ)
  • 充分统计量φ(y) = y
  • 对数配分函数A(η) = exp(η)
  • 基函数h(y) = 1/y!

链接函数是对数函数η = log(μ)


对数配分函数 A(η) 的性质 🔬

上一节我们看到了指数族的形式。本节中我们来看看其核心组件 A(η) 的两个关键性质,这些性质在推导广义线性模型时至关重要。

A(η) 具有以下优美性质:

  1. 凸性A(η) 是关于 η 的凸函数。
  2. 导数与矩
    • 一阶导数给出充分统计量的期望:∇A(η) = E[φ(y)]
    • 二阶导数(Hessian矩阵)给出充分统计量的协方差:∇^2 A(η) = Cov(φ(y))

性质1证明思路:利用 exp(A(η)) 的定义和 Hölder 不等式,可以直接验证凸函数的定义不等式成立。

性质2证明:通过对 A(η) = log( ∫ h(y) exp(η^T φ(y)) dy ) 直接求梯度,并交换梯度与积分次序,可得:

∇A(η) = ∫ φ(y) * h(y) exp(η^T φ(y) - A(η)) dy = ∫ φ(y) p(y|η) dy = E[φ(y)]

求二阶导即可得到协方差。

这些性质意味着,通过对 A(η) 求导,我们可以轻松得到分布的所有矩信息。


广义线性模型 🚀

前面我们为独立同分布数据介绍了指数族。现在,我们将其与机器学习中的预测问题结合,就得到了广义线性模型

在广义线性模型中,我们对于每一个输入 x,假设输出 y 的条件分布是指数族的一员,并且其自然参数 η 是输入 x 的线性函数

GLM 做出以下三个核心假设:

  1. 条件分布:给定 xy 的条件分布属于指数族:p(y | x; w) = h(y) exp( η φ(y) - A(η) )
  2. 线性预测器:自然参数 η 通过线性组合与输入相关联:η = x^T w
  3. 链接函数:系统的均值响应 μ = E[φ(y) | x] 通过一个可逆的链接函数 g 与线性预测器关联:μ = g^{-1}(η) = g^{-1}(x^T w)

重要说明:当链接函数 g 使得 η = g(μ) 恰好等于分布的自然参数时(如伯努利中的 logit,泊松中的 log),该链接函数称为典范链接函数。使用典范链接可以简化计算。


GLM 的参数估计与学习 📈

给定数据集 {(x_i, y_i)},假设数据由某个 GLM 生成,我们的目标是找到最优参数 w。我们使用最大似然估计

负对数似然函数为:

L(w) = -∑ [ log h(y_i) + η_i φ(y_i) - A(η_i) ],其中 η_i = x_i^T w

由于 -log h(y_i) 项与 w 无关,η_i φ(y_i)w 的线性项,而 -A(η_i) 是凸函数 A 与线性函数 η_i(w) 的复合,因此 L(w) 是关于 w凸函数。这意味着我们可以使用梯度下降等优化方法找到全局最优解。

计算梯度并令其为零,我们可以得到似然方程。利用 ∇A(η) = E[φ(y)] = μ 和链接函数 μ = g^{-1}(η),方程可以写为:

∑ [ (y_i - μ_i) * (∂μ_i/∂η_i) * x_i ] = 0

其中 μ_i = g^{-1}(x_i^T w)。这个方程正是我们在线性回归(g 为恒等函数)和逻辑回归(g^{-1} 为 sigmoid)中看到的正规方程的推广形式。


总结 🎯

本节课中我们一起学习了:

  1. 指数族:一个统一表达多种概率分布(高斯、伯努利、泊松等)的框架,其形式为 p(y|η) = h(y) exp(η^T φ(y) - A(η))
  2. 指数族的性质:对数配分函数 A(η) 是凸函数,其导数给出了充分统计量的期望和方差。
  3. 广义线性模型:将指数族用于预测建模。其核心是假设响应变量 y 的条件分布属于指数族,且其自然参数 η 是输入特征 x 的线性组合(η = x^T w),并通过一个链接函数与均值关联。
  4. GLM 的学习:通过最大似然估计来拟合 GLM,其负对数似然损失是凸函数,保证了优化过程的可靠性。

GLM 的强大之处在于,它为我们提供了一套系统的方法,将线性模型的思想扩展到各种类型的响应数据(连续值、二分类、计数等),而无需为每种情况单独推导学习算法。

17:最*邻分类器与维度诅咒 📚

在本节课中,我们将学习最*邻分类器,并探讨所谓的“维度诅咒”。我们将看到,最*邻方法既可用于分类,也可用于回归。今天我们将主要讨论分类场景,但请记住,它同样适用于回归。

我们将首先正确定义最*邻方法,然后查看其不同版本,并尝试分析它在何时有效、何时无效。在本节课的最后,我们将对 k=1 的情况进行正式分析。

本节课的核心要点是:在低维输入空间中,如果你有足够的数据,最*邻方法会表现得非常好,能够建模非常复杂的决策边界。然而,随着输入空间维度的增加,该方法将不再有效。因此,它本质上是一种在低维空间中表现优异的方法。


监督学习场景回顾 📖

首先,我们快速回顾一下监督学习的设置。我们有一个训练集 S_train,目标是利用这个训练集,当给定一个新的输入 x 时,预测其输出 y。通常,我们会使用训练集学习一个算法 A,然后用这个算法进行预测。今天我们要讨论的算法就是最*邻算法


最*邻函数的定义 🎯

为了定义最*邻,我们首先需要一个函数,称为 最*邻函数

定义
我们有一个输入空间 X,一个训练集 S_train,以及一个参数 k(即我们要寻找的邻居数量)。函数 N(S_train, k, x) 的输出是训练集中与输入点 x 最接*的 k 个元素。

这个定义很明确:给定训练集和 k,你寻找训练集中与点 x 距离最小的 k 个点。

什么是“最接*”?
它意味着最小的距离。这里我们假设已经定义了一个距离度量,例如欧几里得距离。

示例
假设我们有一个测试点 x,我们寻找它的3个最*邻点。我们会在训练集中找到距离 x 最*的三个点。

注意
有时,可能存在多个点与 x 的距离完全相同。在这种情况下,最*邻的集合可能不是唯一定义的,具体取决于你的实现方式(例如,可能选择索引最小的前两个点)。在实践中,这种情况不常发生,但了解这一点很重要。


关于最*邻函数的说明 💡

关于这个函数,有几点需要注意:

  1. 隐含的距离度量:你隐式地假设了一个距离(如欧几里得距离)。如果改变距离度量(例如使用其他 Lp 距离或任何自定义度量),函数的行为也会改变。
  2. 计算复杂度:查询最*邻的复杂度通常是 O(N),其中 N 是训练集的大小。因为为了找到最*的点,你可能需要检查所有点。有时,通过特定的数据结构(如 k-d 树)可以实现亚线性的*似算法,但今天我们假设计算是“免费”的。

这个函数定义简单明确,现在我们将用它来定义用于回归和分类的最*邻规则。


最*邻回归 📈

对于回归任务,做法很简单:

  1. 找到点 xk 个最*邻。
  2. 计算这些邻居的输出值 y_i 的*均值。
  3. 将这个*均值作为你的预测值。

公式
预测值 = (1/k) * Σ( y_i ),其中求和针对 k 个最*邻的标签。

示例
对于一个点 x,其三个最*邻的输出值分别为 y1, y2, y3,则预测值为 (y1 + y2 + y3) / 3


最*邻分类 🏷️

对于分类任务,做法类似,但使用多数投票

  1. 找到点 xk 个最*邻。
  2. 统计这些邻居中每个类别出现的次数。
  3. 预测出现次数最多的类别(即进行多数投票)。

示例
对于一个点 x,其三个最*邻的标签分别是 [0, 1, 0]。通过多数投票,类别 0 出现两次,类别 1 出现一次,因此预测类别为 0

*局问题
如果 k 是偶数,可能会出现两个类别票数相同的情况(例如,两个邻居是类别0,两个是类别1)。为了避免这种不确定性,一个常见的技巧是选择奇数的 k 值,这样总能产生一个明确的获胜类别。

扩展
k 很大时,你可能不希望所有邻居的权重相同,而希望给更*的点更高的权重。这引出了核*滑方法,但今天我们只讨论简单的多数投票。在理论分析中,我们甚至会专注于最简单的情况:k=1。此时,你只需找到最*的一个点,并输出与其相同的标签。


最*邻方法何时有意义? 🤔

最*邻方法只有在数据点之间存在空间相关性时才有意义。也就是说,你需要相信“相*的点很可能具有相同的标签”。如果这个假设成立,那么使用最*邻分类就是合理的。

反之,如果输出 y 与输入 x 完全独立(例如随机抛硬币),那么使用邻*点的信息进行预测就没有任何意义。

最*邻方法在低维空间中且数据点足够多时非常有效。它可以学习非常复杂的决策边界,这是其优点。例如,对于某些复杂的数据集,线性模型(如逻辑回归)可能无法很好地区分类别,但最*邻方法可以。


参数 k 与偏差-方差权衡 ⚖️

参数 k 控制着模型的复杂度,并与我们之前讨论的偏差-方差权衡密切相关。

  • k 很小(例如 k=1)

    • 低偏差:模型非常灵活,能够拟合复杂的决策边界。
    • 高方差:预测结果对训练数据非常敏感。换一个训练集,最*邻点可能完全不同,导致预测结果变化很大。这本质上是过拟合
  • k 很大(例如 k = N,即训练集大小)

    • 高偏差:模型变得非常简单。对于分类,预测结果将是整个训练集中最多的类别(一个常数预测),无法捕捉数据中的复杂模式。
    • 低方差:预测结果非常稳定,几乎不随训练集的变化而改变。这本质上是欠拟合

因此,我们需要选择一个合适的 k 值,在偏差和方差之间取得*衡,从而获得良好的测试性能。实验表明,测试误差随 k 的变化通常呈 U 形曲线。选择合适的 k(例如下图中 k=11),可以使最*邻方法的性能优于简单的线性分类器。


维度诅咒 😱

到目前为止,我们看到在低维且数据充足时,最*邻方法效果很好。现在我们要探讨为什么在高维空间中,这个方法会失效。这就是所谓的“维度诅咒”。

核心思想是:在低维空间中,“邻居”的概念很直观。但在高维空间中,数据点会变得非常稀疏,所有点之间的距离都差不多,因此“最*邻”的概念就失去了意义。

第一个论断:固定训练集大小,增加维度

假设我们的输入空间是 D 维超立方体 [0, 1]^D,数据点均匀分布在其中。考虑中心点 x0 和一个边长为 r 的小超立方体(以 x0 为中心)。

问题:随机采样一个新点 x,它落在这个小超立方体中的概率是多少?
答案:概率是 r^D(小立方体体积)除以 1^D(大立方体体积),即 r^D

分析

  • 设我们想让这个概率为 α(例如 10% 或 1%),则需要 r = α^(1/D)
  • 当维度 D 增大时,为了保持一个固定的概率 α,所需的边长 r 会急剧增大。
  • 例如,D=10α=1% 时,r ≈ 0.63α=10% 时,r ≈ 0.8

这意味着,在高维空间中,为了捕捉哪怕一小部分(如10%)的数据点来进行局部*均,你实际上需要考察几乎整个空间的大部分区域。因此,“局部性”不复存在。

第二个论断:高维空间中点与点之间的距离

同样考虑 D 维超立方体 [0, 1]^D,其中有 n 个均匀分布的训练点。再次考虑中心点 x0

问题:为了以大于 1/2 的概率,使得至少有一个训练点落在以 x0 为中心、边长为 r 的小超立方体内,r 需要多大?
推导

  1. 一个随机点落在小立方体内的概率是 r^D
  2. n 个点全部不落在小立方体内的概率是 (1 - r^D)^n
  3. 至少有一个点落在内的概率是 1 - (1 - r^D)^n
  4. 令此概率 > 1/2,可解得 r > (1 - (0.5)^(1/n))^(1/D)

分析

  • 固定 n=500D=10,计算可得 r > 0.52
  • 这意味着,即使有500个点,在10维空间中,为了有超过一半的机会找到一个“邻居”,你需要考察一个边长超过0.52的超立方体(占据了超过一半的坐标范围)。

结论:在高维空间中,所有点都显得非常遥远,最*邻的概念变得模糊且不可靠。数据点更多地分布在空间的边界附*,而不是内部。


最*邻分类器的理论分析(k=1)🔬

现在,我们尝试从理论上分析1-最*邻分类器的泛化性能,并将其与最优分类器(贝叶斯分类器)进行比较。这将进一步印证我们对维度诅咒的直觉。

问题设置

  • 数据 (X, Y) 服从分布 D,定义在 X × Y 上,其中 X = [0, 1]^DY = {0, 1}
  • 分类错误率(风险)定义为:R(g) = P_{(X,Y)~D}[ g(X) ≠ Y ],其中 g 是我们的分类器。

贝叶斯分类器:最优基准

  • 定义条件概率 η(x) = P(Y=1 | X=x)
  • 如果我们知道真实分布 D(即知道 η(x)),那么最优分类器(贝叶斯分类器) g* 的预测规则为:
    g*(x) = 1 如果 η(x) > 1/2,否则为 0
  • 贝叶斯分类器的风险(最小可能错误率)为:
    R* = E_X [ min( η(X), 1 - η(X) ) ]

最*邻分类器的误差上界

我们分析1-最*邻分类器 g_nn期望风险(对训练集取*均)。

核心假设(空间相关性)
我们假设条件概率函数 η(x)L-利普希茨连续的。即存在常数 C,使得对于任意 x, x’,有:
|η(x) - η(x’)| ≤ C * ||x - x’||
这个假设意味着:如果两个点距离很*,那么它们属于同一类别的概率也很接*。

定理
在以上假设下,1-最*邻分类器的期望风险满足以下上界:
E_{S_train}[ R(g_nn) ] ≤ 2 * R* + C * E_{X, S_train}[ ||X - X_{(1)}|| ]

其中:

  • R* 是贝叶斯风险(最优风险)。
  • 第二项 E[ ||X - X_{(1)}|| ] 是一个几何项,表示一个随机点 X 到其训练集中最*邻点 X_{(1)} 的*均距离。

解读

  1. 最*邻分类器的误差最多是最优分类器的两倍,再加上一个附加项。
  2. 附加项依赖于:
    • C:空间相关性的强度。C 越小,相关性越强,该项越小。
    • *均最*邻距离:如果数据密集,最*邻很*,该项就小。

几何项与维度的关系

可以证明,在 D 维超立方体 [0, 1]^D 中,若数据均匀分布,则有:
E[ ||X - X_{(1)}|| ] = O( sqrt(D) * n^{-1/(D+1)} )

分析

  • 固定维度 D,增加样本数 n:该项以 ~ n^{-1/(D+1)} 的速率趋于 0。因此,当数据很多时,1-最*邻分类器的风险接* 2R*,表现不错。
  • 固定样本数 n,增加维度 D:由于指数项 -1/(D+1) 的绝对值随着 D 增大而减小,n^{-1/(D+1)} 会趋*于 1。再乘以 sqrt(D),该项会变得非常大。这意味着,如果维度很高而数据量不足,误差上界会变得很松,性能可能急剧下降。

这从理论上解释了维度诅咒:为了在高维空间中获得好的性能,所需的数据量 n 需要随维度 D 指数级增长,这通常是不现实的。


总结 📝

本节课我们一起学习了最*邻分类器。

  1. 定义与使用:我们定义了最*邻函数,并说明了如何将其用于回归(取*均)和分类(多数投票)。选择奇数的 k 值可以避免*局。
  2. 偏差-方差权衡:参数 k 控制模型复杂度。k 小则偏差低、方差高(过拟合);k 大则偏差高、方差低(欠拟合)。需要选择合适的 k 以*衡两者。
  3. 维度诅咒:在高维空间中,数据变得极其稀疏,点与点之间的距离趋于相似,“最*邻”的概念失效。为了进行有意义的局部估计,所需的数据量随维度指数增长,这在实际中往往无法满足。
  4. 理论分析:在空间相关性(利普希茨条件)的假设下,我们分析了1-最*邻分类器的泛化误差上界。其上界包含最优误差的2倍和一个与*均最*邻距离成正比的项。该几何项的行为揭示了维度诅咒的根源:在固定数据量下,高维空间中的*均最*邻距离很大,导致性能下降。

最*邻方法是一种简单直观的非参数方法,在低维小规模问题中非常有效。但在处理高维数据时,必须警惕维度诅咒带来的挑战。

18:习题6入门指南 📚

在本节课中,我们将学习习题6的主要内容。本次习题包含三个核心问题,旨在帮助大家巩固凸函数性质、多类别分类以及混合线性回归模型的知识。由于下周有项目截止日期,本次习题仅包含三个问题,以便大家有更多时间在习题课上讨论项目相关问题。


凸函数与严格凸函数的性质 🔍

上一节我们介绍了习题的整体结构,本节中我们来看看第一个问题:凸函数与严格凸函数的性质证明。这些性质在机器学习中非常有用,例如,损失函数通常表现为多个独立损失项的和,了解其凸性有助于证明优化算法的收敛性。

以下是需要证明的几个关键性质:

  • 凸函数与凸函数的和仍然是凸函数。
  • 凸函数与一个单调递增函数的复合仍然是凸函数。
  • 严格凸函数具有唯一的极小值点。

这些性质对于理解线性回归、逻辑回归等模型的损失函数形式至关重要。


多类别分类与Softmax函数 🎯

在之前的课程中,我们学习了二分类问题。本节我们将问题扩展到多类别分类。在多分类中,样本标签可以是K个类别中的任何一个。

与二分类仅有一组参数 w 不同,多分类为每个类别k都配备了一组参数 w_k。对于每个数据点 x_n,我们计算其与所有 w_k 的点积。然而,直接取最大值作为类别分配的函数并不可微,且不能给出类别的概率分布。

因此,我们引入 Softmax 函数。对于一个固定的数据点 x_n,它属于类别k的概率由以下公式给出:

公式: P(y = k | x_n) = exp(w_k^T x_n) / (∑_j exp(w_j^T x_n))

该函数确保了所有类别的概率之和为1,并且点积值较大的类别将获得较高的概率。与逻辑回归类似,我们假设样本独立同分布,可以写出联合概率分布。在本问题中,你需要推导对数似然函数、关于 w_k 的梯度,并证明该对数似然函数是凸函数。


混合线性回归模型 🧩

最后一个问题涉及混合线性回归模型。在标准线性回归中,我们使用一个线性模型拟合数据。但在某些情况下,数据可能来自多个不同的线性关系。

混合线性回归模型假设有K个混合成分,每个成分都有自己的参数 w_k 和权重 π_k。数据点围绕这些不同的“线”生成,如下图所示。如果只用一个线性模型拟合,效果会很差。

在本问题中,你需要:

  • 推导该模型的最大似然估计量,以找到参数 Wπ
  • 分析该似然函数的性质(例如,是否是联合凸的)。
  • 讨论该模型是否是可识别的,即当数据量趋于无穷时,是否能唯一确定参数。

总结与建议 📝

本节课中,我们一起学习了习题6的三个核心部分:凸函数的性质证明、多类别分类的Softmax模型以及混合线性回归。这些内容涵盖了机器学习中的重要概念和模型。

请务必参加习题课,助教们将非常乐意解答大家关于习题和项目的任何疑问。

19:支持向量机 (SVM) 🎯

在本节课中,我们将学习支持向量机 (SVM),这是一种非常重要且强大的线性分类器。我们将从最大间隔的概念出发,探讨如何找到最优的分类超*面,并学习如何处理线性不可分的数据。我们还将介绍凸优化的基本概念,并了解如何通过其对偶形式更高效地求解SVM问题。


1. 线性分类器回顾 📐

上一节我们介绍了分类的基本概念,本节中我们来看看线性分类器的具体框架。

我们定义一个超*面。给定一个向量 w(假设其范数为1,即 ||w|| = 1),由 w 定义的法*面 H 是所有满足 x^T w = 0 的点 x 的集合。这就是我们的超*面。

我们可以使用这个超*面进行分类。对于一个新数据点 x,我们预测其标签为 sign(x^T w)。例如,对于一个点 x1,如果内积 x1^T w 为正,则将其分类为+1;对于点 x2,如果内积 x2^T w 为负,则将其分类为-1。

一个非常重要的性质是,一个点 x0 到超*面的距离等于 |x0^T w| 的绝对值。这是因为我们假设了 ||w|| = 1

距离公式证明
x0 到超*面 H 的距离定义为到 H 上任意点 u 的最小距离,即 min_{u in H} ||x0 - u||。可以证明,这个最小值在 u 等于 x0w 方向上的投影时取得,该距离恰好等于 |x0^T w|


2. 硬间隔支持向量机 (Hard-Margin SVM) 🛡️

上一节我们回顾了线性分类器,本节中我们来看看如何定义最大间隔超*面。

首先,我们假设数据集是线性可分的。这意味着存在一个超*面,能够将所有正类样本(红色点)和负类样本(蓝色点)完全分开。然而,这样的超*面通常有很多个。问题是:我们应该选择哪一个?

一个合理的想法是选择间隔最大的那个超*面,即离所有训练样本点都最远的那个。这样,即使数据有轻微扰动,这个超*面仍然很可能保持良好的泛化性能。

如何定义最大间隔?
一个超*面的间隔是其到所有训练样本点距离中的最小值。对于样本点 (x_i, y_i),其到超*面 w 的距离是 |x_i^T w|。因此,超*面 w 的间隔 M(w) 为:
M(w) = min_i |x_i^T w|

最大间隔超*面的数学定义
我们寻找一个方向 w (||w||=1),在满足所有样本都被正确分类(即 y_i (x_i^T w) > 0)的条件下,最大化其间隔 M(w)。这等价于以下优化问题:
max_{w: ||w||=1} min_i y_i (x_i^T w)

可以证明,最大间隔超*面位于两个类别最*点的“正中间”。

等价形式
上述问题可以重新表述为以下更易处理的形式:
min_w ||w||^2
约束条件为:y_i (x_i^T w) >= 1,对于所有 i=1,...,n

在这个形式中,我们不再约束 ||w||=1,而是最小化 ||w||^2,同时要求所有样本点距离超*面的函数间隔至少为1。间隔的实际宽度为 2 / ||w||,因此最小化 ||w|| 等价于最大化间隔。


3. 软间隔支持向量机 (Soft-Margin SVM) 🧸

上一节我们讨论了线性可分的情况,但在现实中,数据往往是线性不可分的。本节中我们来看看如何处理这种情况。

我们不再要求所有数据点都必须被正确分类,而是允许一些点违反间隔约束。为此,我们引入松弛变量 ξ_i >= 0

我们将原来的约束 y_i (x_i^T w) >= 1 放松为:
y_i (x_i^T w) >= 1 - ξ_i

ξ_i 衡量了第 i 个样本违反约束的程度。如果 ξ_i = 0,则该点被正确分类且在间隔之外;如果 ξ_i > 0,则该点可能位于间隔内或被错误分类。

软间隔SVM的优化问题
我们联合最小化两项:一项是最大化间隔(即最小化 ||w||^2),另一项是惩罚约束违反(即最小化所有 ξ_i 之和)。这通过一个参数 λ 来权衡:
min_{w, ξ} λ ||w||^2 + Σ_i ξ_i
约束条件为:y_i (x_i^T w) >= 1 - ξ_iξ_i >= 0

  • λ 很大时,我们非常看重大间隔,对分类错误容忍度低(趋向于硬间隔)。
  • λ 很小时,我们更看重正确分类,允许间隔变小。

合页损失 (Hinge Loss) 形式
上述优化问题可以等价地写成一个无约束的正则化经验风险最小化问题:
min_w λ ||w||^2 + Σ_i max(0, 1 - y_i (x_i^T w))

其中,max(0, 1 - z) 被称为合页损失 (Hinge Loss)。这个形式清晰地表明,SVM是在最小化合页损失加上L2正则项。


4. 从经验风险到凸替代损失 📉

上一节我们引入了合页损失,本节中我们来看看它如何从更一般的分类框架中产生。

在二分类问题中(标签 y ∈ {-1, +1}),我们真正想最小化的是0-1损失对应的风险(即错误率):
R(g) = P(g(x) ≠ y)
由于真实分布未知,我们使用经验风险 R_n(g) = (1/n) Σ_i I{g(x_i) ≠ y_i} 来*似。

然而,直接最小化0-1经验风险有两个问题:

  1. 分类器集合 g 不连续,不是凸集。
  2. 指示函数 I{·} 不连续且非凸,导致优化极其困难。

解决方案:使用凸替代损失
我们进行两步放松:

  1. 限制分类器形式:只考虑线性分类器,即 g(x) = sign(x^T w)
  2. 替代损失函数:用凸函数 φ(z) 替代非凸的0-1损失 I{z <= 0},其中 z = -y (x^T w)。我们最小化φ-风险(1/n) Σ_i φ(-y_i (x_i^T w))

理论证明,在合适的条件下,最小化凸替代损失得到的解,在0-1损失下也有好的性能。

以下是几种常见的凸替代损失函数(针对 y ∈ {-1,+1} 格式调整后):

  • *方损失 (Square Loss): φ(z) = (1 - z)^2
  • 逻辑损失 (Logistic Loss): φ(z) = log(1 + exp(-z))
  • 合页损失 (Hinge Loss): φ(z) = max(0, 1 - z)

损失函数对比

  • *方损失:对称惩罚,即使分类正确,如果置信度不高(|z| 不大)也会受到惩罚,这不理想。
  • 逻辑损失:非对称,分类错误时惩罚更大,但即使分类完全正确,损失也不会降到零。
  • 合页损失:是SVM使用的损失。其特点是:当分类足够正确(z >= 1)时,损失为0;只有当 z < 1 时,才会产生线性增长的惩罚。这直接鼓励模型产生一个“间隔”,并追求分类的置信度。

因此,SVM算法等价于:min_w λ||w||^2 + Σ_i HingeLoss(y_i x_i^T w)


5. 对偶问题与支持向量 🤝

上一节我们得到了SVM的优化问题,但直接优化(例如使用次梯度法)可能较慢。本节中我们来看看如何通过凸对偶得到另一个等价的、有时更易求解的问题。

对偶思想
对于一个函数 L(w),如果我们能将其表示为 L(w) = max_{α∈A} G(w, α),那么原问题 min_w L(w) 就变成了 min_w max_{α} G(w, α)。我们称其为原问题
我们可以考虑交换极小和极大的顺序,得到对偶问题max_{α} min_w G(w, α)
在满足一定条件(如 G 关于 w 凸、关于 α 凹,且定义域凸紧)时,强对偶成立,原问题和对偶问题的最优值相等。

SVM的对偶形式
关键的一步是注意到合页损失可以写成一个极大化形式:
max(0, 1 - y_i x_i^T w) = max_{α_i ∈ [0,1]} α_i (1 - y_i x_i^T w)

将其代入SVM目标函数,并经过一系列推导(包括求内层 min_w 的闭式解),我们可以得到SVM的对偶问题
max_{α ∈ [0,1]^n} 1^T α - (1/(2λ)) α^T Y X X^T Y α
其中 Y 是以 y_i 为对角元素的对角矩阵。

对偶问题的优势

  1. 更易求解:目标函数是光滑的二次函数,约束是简单的框约束,可以使用高效的二次规划或坐标上升法求解。
  2. 核技巧基础:数据仅以内积形式 X X^T(即Gram矩阵)出现,这为使用核函数处理非线性问题奠定了基础。
  3. 解的稀疏性与可解释性:对偶变量 α 具有稀疏性。

支持向量的解释
最优解 α* 中的非零分量对应的训练样本称为支持向量。根据KKT条件,它们可以分为三类:

  1. α_i = 0:对应那些被正确分类且位于间隔之外的样本。这些点对最终的超*面没有贡献。
  2. 0 < α_i < 1:对应那些恰好位于间隔边界上的样本。
  3. α_i = 1:对应那些位于间隔之内或被错误分类的样本。

最终的超*面 w* 可以表示为支持向量的线性组合:w* = (1/λ) Σ_i α_i y_i x_i。这意味着决策边界仅由支持向量决定,其他样本点可以被移除而不影响模型。这提供了很好的可解释性,并解释了“支持向量机”名称的由来。


总结 📚

本节课中我们一起学习了支持向量机 (SVM) 的核心思想。

  1. 出发点:在众多能分开数据的超*面中,选择间隔最大的那一个,以获得更好的泛化能力。
  2. 硬间隔SVM:针对线性可分数据,通过最小化 ||w||^2 来最大化间隔。
  3. 软间隔SVM:针对线性不可分数据,引入松弛变量,在最大化间隔和减少分类错误之间进行权衡,其目标函数可表示为合页损失加L2正则化。
  4. 损失函数视角:SVM是使用合页损失这一凸替代损失进行经验风险最小化的一个例子,合页损失鼓励产生分类间隔。
  5. 对偶问题:通过凸对偶理论,可以将SVM的原问题转化为一个关于拉格朗日乘子 α 的二次规划问题。这个形式更易求解,并揭示了解的稀疏性。
  6. 支持向量:最终模型仅由一部分训练样本——支持向量决定,这赋予了模型良好的可解释性。

下一节课,我们将探讨核技巧,它将允许SVM在更高维的特征空间中寻找线性分界,从而处理非线性分类问题。

20:核岭回归与核技巧 🔥

在本节课中,我们将学习核岭回归和核技巧。我们将看到,许多机器学习问题都可以通过核矩阵来重新表述,从而允许我们在高维特征空间中高效地进行计算,而无需实际计算高维映射。


上一节我们介绍了支持向量机及其对偶形式。本节中,我们来看看核岭回归。

核岭回归与对偶形式

在介绍SVM的对偶形式时,我们看到数据以一种非常特殊的形式进入模型:它只依赖于核矩阵 K,即 K = X X^T。为了运行SVM软件,我们只需要知道这个核矩阵。

事实上,这种特性并非SVM独有。许多其他问题也可以被重新表述,以具有相同的特征,岭回归问题(最小二乘法)也是如此。我们将引入所谓的核岭回归

在核岭回归的基础上,我们将能够定义所谓的核技巧。核技巧本质上是一种为模型添加大量额外维度(特征)而无需支付相应计算成本的方法。

之前,当我们添加额外特征时,问题会处于更高的维度,求解的复杂度也会增加。而通过核技巧,我们可以将数据映射到一个非常高维的空间,但仍然在低维空间中进行所有计算。这样,我们就能享受高维特征带来的好处,同时保持良好的样本复杂度和计算复杂度。

让我们从岭回归问题开始。岭回归试图最小化残差的*方范数,并对参数 w 施加正则化,防止其范数过大。

我们知道这个问题有闭式解:
w = (X^T X + λ I)^{-1} X^T y*

其中,矩阵 X^T X + λ I 属于 R^{d×d} 空间。计算这个 w* 的复杂度大约是 O(d^3),因为我们需要计算一个 d×d 矩阵的逆,此外计算 X^T X 还需要 O(n d^2) 的复杂度。

然而,我们也可以用另一种等价形式写出 w
w = X^T (X X^T + λ I)^{-1} y

注意,这里的矩阵 X X^T + λ In×n 维的。这两种形式是等价的。我们可以通过一个通用的矩阵恒等式来证明:对于矩阵 P (m×n)Q (n×n),有 P (Q P + I)^{-1} = (P Q + I)^{-1} P。令 P = X^TQ = (1/λ) X,即可得到上述等价关系。

两种形式的效用

这两种等价形式各有其效用,主要体现在计算复杂度上。

以下是两种方法的计算复杂度对比:

  • 原始形式:复杂度为 O(d^3 + n d^2)。当 d 不大但 n 很大时,这个代价是线性的,可以接受。
  • 对偶形式:复杂度为 O(n^3 + d n^2)。当 d 远大于 n 时,使用这种形式计算复杂度更低。

因此,根据输入维度 d 和样本数量 n 的相对大小,我们可以选择更高效的计算形式。

第二个重要的结构差异是,在对偶形式中,解 w* 具有特殊结构:w* = X^T α。这意味着 w 是观测值 x_i 的线性组合,即 w* 属于观测值 x_1, ..., x_n 张成的空间。

这个性质不仅限于最小二乘问题,它可以推广到许多其他问题,这就是所谓的表示定理

表示定理

表示定理是核方法文献中最著名的定理之一。它告诉我们,解属于观测值张成的空间这一性质,可以推广到*方损失之外的其他问题。

定理指出,考虑任何损失函数 L,并试图最小化经验风险(即损失之和)加上 L2 正则化项(λ ||w||^2)。这是一个非常通用的监督学习形式。

那么,总存在一个向量 α ∈ R^n,使得该优化问题的解 w 恰好等于 X^T α。这意味着,w** 总是位于观测值的张成空间中。

直观上,如果维度 d 非常大(远大于 n),那么观测值张成的空间维度最多为 n。这个定理告诉我们,如果维度太大,我们实际上并不关心观测值生成空间之外发生了什么,那个子空间才是对问题重要的。

证明思路很简单:假设 w* 是解,我们总可以将其分解为 w* = w + u,其中 w 在观测值张成的空间中,而 u 与该空间正交。可以证明,对于相同的预测值,w 的正则化项更小,因此如果 u 不为零,w 就是一个目标函数值更小的点,这与 w* 是最小值矛盾。因此 u 必须为零,即 w* 在观测值的张成空间中。

这个定理是使用核技巧的基础,它允许我们将许多机器学习问题(如核SVM、核岭回归、核PCA等)的求解转化为在系数 α 空间中进行。

应用于岭回归

根据表示定理,对于岭回归问题,我们可以不直接求解 w,而是求解 α

原始的岭回归问题是:
min_w ||y - X w||^2 + λ ||w||^2

其对偶形式是:
min_α α^T (X X^T + λ I) α - 2 α^T y

这是一个关于 α 的二次函数。令其梯度为零,我们得到:
α = (X X^T + λ I)^{-1} y*

然后,我们可以通过 w = X^T α** 恢复原始解。这两种形式完全等价。

这里的关键点是,为了计算 α,数据仅通过核矩阵 K = X X^T 进入模型。如果我们已知这个核矩阵,我们就可以直接计算 α,而无需进入 d 维空间。

特征映射与核技巧

在实际问题中,线性分类或回归的能力有限。我们通常希望将原始观测 x 映射到一个更高维的空间 Φ(x),以便在这个新空间中数据可能是线性可分的。

例如,一个一维的“XOR”类型数据在原始空间不是线性可分的,但如果我们通过特征映射 Φ(x) = (x, x^2) 将其映射到二维空间,数据就变得线性可分了。在扩展空间中使用线性方法,当投影回原始空间时,我们就得到了一个非线性的分类器。

这种方法的问题是,如果特征空间维度 D 非常高,计算成本会很大。核技巧解决了这个问题。

核技巧的核心思想是:我们不需要显式计算高维映射 Φ(x) 以及在高维空间中的内积 Φ(x)^T Φ(x‘)。相反,我们寻找一个核函数 κ(x, x‘),它直接在原始低维空间中计算,但其结果等于在高维空间中的内积,即 κ(x, x‘) = Φ(x)^T Φ(x‘)

这个核函数只有在它的计算复杂度与特征空间的维度 D 无关,而只与输入空间维度 d 相关时,才是有趣的。

通过核技巧,我们可以:

  1. 在低维空间中计算核函数 κ(x_i, x_j),得到核矩阵 K
  2. 使用这个核矩阵 K 来学习模型(如求解 α*)。
  3. 进行预测时,也只需要计算新点与训练点之间的核函数值,而无需计算高维的 Φ(x)

这样,我们就能在高维特征空间中享受线性分类器的优势,而所有计算都在低维输入空间中进行。

核函数示例

以下是一些常见的核函数示例:

  • 线性核κ(x, x‘) = x^T x‘。对应的特征映射就是恒等映射 Φ(x) = x
  • 多项式核:例如 κ(x, x‘) = (x^T x‘)^2。对于三维输入,它可以对应到一个六维的特征映射,包含了所有单项式和交叉项。
  • 高斯核(RBF核)κ(x, x‘) = exp(-γ ||x - x‘||^2)。这个核对应的特征空间是无限维的。它使我们能够在无限维空间中进行线性分类,而计算成本仅取决于原始维度。

构建新核

我们可以从已有的核函数构建新的核函数:

  • 正线性组合:如果 κ1κ2 是核函数,α, β ≥ 0,那么 α κ1 + β κ2 也是核函数。
  • 乘积:如果 κ1κ2 是核函数,那么 κ1 · κ2 也是核函数。

梅塞尔定理

一个自然的问题是:如何判断一个函数 κ(x, x‘) 是否是一个有效的核函数(即是否存在某个特征映射 Φ 使得内积等式成立)?

梅塞尔定理给出了充要条件:

  1. 对称性κ(x, x‘) = κ(x‘, x)
  2. 正定性:对于任何有限的点集 {x_1, ..., x_n},对应的核矩阵 K(其中 K_{ij} = κ(x_i, x_j))是半正定的。

如果一个函数满足这两个条件,那么它就存在一个对应的特征映射 Φ,是一个有效的核函数。

使用核函数进行预测

最后,我们如何利用核函数对新样本 x 进行预测?预测值通常是 f(x) = w^T Φ(x)

根据表示定理,w = Σ_{i=1}^n α_i Φ(x_i)。因此:
f(x) = Σ_{i=1}^n α_i Φ(x_i)^T Φ(x) = Σ_{i=1}^n α_i κ(x_i, x)

可以看到,进行预测也只需要计算新点 x 与所有训练点 x_i 之间的核函数值,完全不需要计算高维的 Φ(x)Φ(x_i)

虽然在高维特征空间中我们使用的是线性分类器(一个超*面),但当我们将这个线性函数通过核函数表示并投影回原始输入空间时,它对应的是一个非线性的决策函数。这正是核方法强大之处。


本节课中我们一起学习了核岭回归与核技巧。我们了解到,通过将数据映射到高维空间可以增强模型的表达能力,但直接计算高维映射成本高昂。核技巧允许我们通过核函数隐式地在高维空间中进行运算,而所有计算都在原始低维空间中进行,从而高效地实现了这一目标。核方法是机器学习中连接线性模型与非线性能力的重要桥梁。

21:习题7入门指南 🚀

在本节课中,我们将聚焦于第七次习题集,主题是支持向量机。我们将从回顾SVM的基本优化问题开始,然后探讨两种优化方法:随机梯度下降和对偶问题的坐标上升法。最后,我们会学习一些关于核函数有效性的理论性质。


概述 📋

本周我们将专注于第七次习题集,处理支持向量机。在分类问题中,我们已经学习了线性回归和逻辑回归。现在,我们将关注一种新方法——支持向量机。

在课堂上,我们已经了解到,我们希望最小化的问题由公式(1)给出。可以注意到,除了我们考虑的损失函数是合页损失而非逻辑损失外,其形式与逻辑回归类似。

那么,优化这个问题的最佳方式是什么?在实验中,我们可以访问包含特征X和标签Y的训练集与测试集。需要注意的是,使用这种公式和合页损失时,标签Y必须是+1或-1,而不是0或1。


第一部分:原始问题与随机梯度下降

解决公式(1)所示原始问题的自然方法是使用随机梯度下降。当数据量N很大时,SGD通常比普通梯度下降更高效。

以下是需要实现的几个函数:

  • calculate_accuracy:对于给定参数W,计算在训练集和测试集上的准确率。
  • calculate_primal_objective:计算考虑正则化参数λ的原始目标函数值(即损失)。

需要指出的是,准确率计算函数不涉及参数λ。

对于问题2,需要实现两个SGD函数:

  • 一个函数针对给定的单个数据点(小n)返回随机梯度。
  • 另一个函数 sgd_for_svm_demo 执行完整的SGD过程并计算目标函数值。

第二部分:对偶问题与坐标上升法

然而,在原始问题上直接进行SGD并不总是最佳方法。我们还可以考虑对偶问题,如公式(2)所示。这是一个关于α的最大化问题,它是一个二次函数,并且是凹函数,因此易于最大化。该问题受约束,因为α的每个坐标必须在区间[0, 1]内。

解决此问题的一种方法是使用坐标上升法。第一个问题是理论性的:需要证明当只关注一个坐标时,存在闭式解。这意味着,如果我们随机选择一个坐标n,并希望找到函数F(α)在该方向上的最大值(一个带约束的一维优化问题),我们可以推导出该问题的解。然后,我们可以用这个解来更新α。

一旦回答了这个理论问题,实现就变得直接了。你需要:

  • 计算坐标更新(即实现上述更新规则)。
  • 计算对偶目标函数值(即实现公式2)。
  • 展示坐标上升法的性能,并使用函数 sgd_for_svm_demo 进行比较。问题在于比较SGD和坐标上升法哪个更快,并比较两种情况下目标函数值的变化。

第三部分:核函数的理论性质

在课堂上,我们已经看到有些核函数可以表示为良好的内积形式。在实践中,对于一个给定的核函数K(x, x'),通常很难将其表示为某个特征映射φ的内积。实际上,特征映射可能是无限维的。

然而,在接下来的两个问题中,我们将展示一些能保持核函数有效性的操作。在课堂上,我们已经学过两个有效核函数的和仍然是有效核函数,一个有效核函数乘以一个正常数也仍然是有效核函数。

这里,我们将证明:

  1. 如果K1是一个有效核函数,而F是一个具有正系数的多项式,那么复合函数F(K1)仍然是一个有效核函数。这很有用,因为如果我们知道K1有效,那么即使不计算相关的特征映射φ,我们也知道K1²是有效的。
  2. 证明一个核函数的指数函数仍然是一个有效核函数。提示是允许取极限。这意味着,如果存在一个有效核函数的序列,并且该序列逐点收敛于某个极限核函数K,那么根据给定的定理,这个极限核函数K也是有效的。你可以使用这个定理来证明第二个问题。

总结 ✨

本节课我们一起学习了支持向量机习题集的核心内容。我们回顾了SVM的原始优化问题及其对偶形式,并实践了使用随机梯度下降和坐标上升法进行优化。最后,我们探讨了核函数有效性的重要理论性质,特别是通过多项式和指数运算构造新核函数的方法。希望这些知识能帮助你顺利完成习题。

22:神经网络基础与表达能力 🧠

在本节课中,我们将要学习神经网络的基本结构,并探讨其强大的表达能力。我们将从动机出发,理解为什么神经网络能够自动学习数据特征,然后深入其数学定义和核心工作原理。


动机:从特征工程到自动学习

在之前的课程中,我们主要讨论了线性预测方法。线性预测(例如 y = w^T x)只有在数据具有良好的特征表示时才能表现良好。过去,这通常需要领域专家为每个特定应用(如计算机视觉)手动设计特征,然后将这些特征输入给线性模型。

这种方法存在明显问题:它非常耗时,且高度依赖于具体领域。我们更希望的是,机器学习模型能够自动从数据中学习到好的特征表示

这正是神经网络的核心思想。神经网络将特征学习的过程整合到了学习问题本身中。它的第一部分(隐藏层)负责自动学习数据的良好特征表示,而第二部分(输出层)则在这些学习到的特征之上进行线性分类或回归


神经网络的基本结构 🏗️

上一节我们介绍了神经网络的动机,本节中我们来看看它的具体结构。

一个基本的前馈神经网络包含以下部分:

  • 输入层:维度为 D,对应输入数据的特征数。
  • L 个隐藏层:每个隐藏层有 K 个节点(神经元)。为简化讨论,我们假设所有隐藏层大小相同。
  • 输出层:在本课中,我们考虑输出层大小为 1(例如,用于回归或二分类)。

信息从输入层开始,单向地流经各个隐藏层,最终到达输出层,没有反馈回路,因此称为“前馈”网络。

网络的参数包括:

  • 隐藏层的数量 L 和每层的大小 K
  • 连接各层节点之间的权重 W_{ij}^{(l)}
  • 每个节点上的偏置 b_i^{(l)}

前向传播:值是如何计算的? ➡️

了解了结构后,我们需要知道每个节点的值是如何计算的。这个过程称为前向传播。

在一个全连接网络中,每一层的每个节点都连接到前一层的所有节点。第 l 层中第 j 个节点的值 x_j^{(l)} 递归地定义如下:

公式:
x_j^{(l)} = φ( Σ_i ( W_{ij}^{(l)} * x_i^{(l-1)} ) + b_j^{(l)} )

以下是计算过程的分解:

  1. 线性组合:将前一层所有节点的值 x_i^{(l-1)} 与对应的权重 W_{ij}^{(l)} 相乘并求和,然后加上本节点的偏置 b_j^{(l)}
  2. 激活函数:将上述线性组合的结果输入一个非线性函数 φ,得到该节点的最终输出值。

为什么 φ 必须是非线性的?
如果 φ 是线性函数,那么整个网络就只是一系列线性变换的叠加,最终输出仍然是输入的一个线性函数。这样,网络的表达能力就退化成了简单的线性模型。引入非线性激活函数是神经网络能够学习复杂模式的关键。

常见的激活函数包括:

  • Sigmoidφ(x) = 1 / (1 + exp(-x)),将输入压缩到 (0, 1) 区间。
  • ReLUφ(x) = max(0, x),目前最流行的激活函数之一。

神经网络的两种视角 👓

现在,我们可以从两个角度来理解神经网络的功能。

视角一:自动特征学习器
神经网络的前 L 层(输入层和隐藏层)共同作用,将原始输入 x ∈ R^D 映射到一个新的特征空间 R^K。这个映射函数 f 由网络的权重、偏置和激活函数共同定义。网络正在自动学习对当前任务有用的特征

视角二:特征之上的线性预测器
学习到特征表示 f(x) 之后,输出层仅仅是在这些特征上执行一个线性操作(例如 w^T f(x) + b)。对于回归任务,直接输出该值;对于分类任务,则可能再通过一个符号函数或 softmax 函数。

因此,神经网络的参数量级约为 O(K^2 * L)。现代深度学习模型通常使用非常深(L 很大)和/或非常宽(K 很大)的网络,即过参数化模型。


深度学习的三大谜题 ❓

神经网络在实践中取得了巨大成功,但其背后仍有许多未解之谜,主要可归纳为三点:

  1. 表达能力之谜(Approximation):给定一个复杂函数,是否存在一个神经网络能够以足够高的精度逼*它?这就是*似理论关心的问题。我们将在本节课重点讨论。
  2. 优化之谜(Optimization):神经网络的损失函数是关于参数的高度非凸函数,参数空间巨大。然而,使用梯度下降法等简单优化算法,我们通常能(看似神奇地)找到使训练误差很低的解。我们将在下节课探讨。
  3. 泛化之谜(Generalization):过参数化的神经网络可以完美拟合训练数据(训练误差为0),但为什么它同时能在未曾见过的测试数据上表现良好(泛化能力强)?这与传统统计学习理论相悖,是当前研究的热点。


神经网络的表达能力:*似理论 📈

本节我们将聚焦于第一个谜题:神经网络的表达能力。核心问题是,神经网络能否*似任意复杂的函数?

Barron 定理(1993)提供了一个答案:
考虑一个定义在 R^D 上的函数 f,其傅里叶变换满足一定的*滑性条件(即函数足够光滑)。那么,对于任意整数 n存在一个仅含单隐藏层(使用类似 Sigmoid 的激活函数)的神经网络 f_n,使得在半径为 R 的球内,其 L^2 *似误差满足:

公式:
∫_{||x||≤R} |f(x) - f_n(x)|^2 dx ≤ (2C * R^2) / n

对这个结果的解读:

  • 误差上界:*似误差以 O(1/n) 的速率下降,其中 n 是隐藏层神经元的数量。神经元越多,*似越精确。
  • *滑性:常数 C 度量了函数的*滑程度。函数越*滑(C 越小),越容易*似。
  • 定义域:*似保证只在有界区域(半径 R 内)成立。区域越大,要达到相同精度所需的神经元可能越多。
  • 普遍性:该定理表明,单隐藏层神经网络在理论上就是以*似一大类光滑函数。

这个定理是存在性定理,它告诉我们这样的网络参数是存在的,但并未说明如何通过训练找到它们。


直观理解:用神经网络“画”出函数 🎨

为了更直观地理解神经网络的表达能力,我们可以通过一个非严格的“图示化”证明来感受一下。

目标:证明使用 Sigmoid 激活函数、最多两个隐藏层的神经网络,可以在 L^1 范数下很好地*似一个光滑的一维函数。

证明思路(三步走):

  1. 用矩形逼*函数:任何在有限区间上黎曼可积的光滑函数,都可以用一系列矩形函数的和来任意精度地逼*(这本质上是黎曼积分的定义)。
  2. 用神经网络逼*矩形:一个矩形函数可以看作两个阶跃函数之差。而一个阶跃函数可以通过一个权重很大的 Sigmoid 函数来*似(调整偏置决定阶跃位置,调整权重决定阶跃陡峭度)。因此,一个矩形函数可以用两个 Sigmoid 函数的线性组合来*似。
    • 对应神经网络:一个具有两个隐藏神经元(使用 Sigmoid)和线性输出层的网络可以实现这个*似。
  3. 组合起来:既然原函数*似于许多矩形之和,而每个矩形又*似于一个小神经网络,那么所有这些小神经网络的叠加(即一个更大的神经网络)就可以*似原函数。由于需要对 Sigmoid 的输出进行求和,最终形成的网络会是一个两隐藏层的网络。

扩展到高维:对于二维或更高维的函数,思路类似。我们可以用高维的“矩形柱”来逼*函数,而每个“矩形柱”可以通过组合多个 Sigmoid 函数(并在最后添加一个阈值激活函数来裁剪不需要的部分)来*似。这同样可以通过具有两个隐藏层的网络实现。


点态*似与 ReLU 网络 ✨

Barron 定理给出了*均意义下的*似保证。我们能否得到更强的、对每个输入点都成立的点态*似保证呢?

对于定义在紧集上的连续函数,著名的Stone-Weierstrass 定理指出,可以用多项式函数以任意精度一致逼*。但多项式本身不易由神经网络直接实现。

一个更相关的结果是Cybenko(1989)等人的通用*似定理,它指出,使用 Sigmoid 等激活函数的单隐藏层神经网络,可以在紧集上一致逼*任意连续函数。

此外,对于使用 ReLU 激活函数的网络,我们有一个非常直观的理解:

任何连续的分段线性函数都可以表示为一组 ReLU 函数的线性组合:
f(x) = β + α*x + Σ_i a_i * ReLU(x - b_i)

为什么?

  • 每个 ReLU(x - b_i)x = b_i 处产生一个“拐点”。
  • 系数 a_i 决定了在拐点处斜率的变化量。
  • 通过选择和组合多个这样的 ReLU 函数,我们可以构造出具有任意多个拐点和斜率的复杂分段线性函数。

由于连续函数可以用分段线性函数很好地*似,而分段线性函数又可以用 ReLU 网络精确表示,这就在直觉上说明了 ReLU 网络同样具有强大的*似能力。一个单隐藏层的 ReLU 网络就可以实现上述表示。


总结 🎯

本节课中我们一起学习了:

  1. 神经网络的动机:其核心优势在于能够自动学习数据特征,省去了繁琐的手动特征工程。
  2. 基本结构:包括输入层、隐藏层和输出层,通过权重、偏置和非线性激活函数进行前向传播计算。
  3. 两种视角:神经网络既是自动特征学习器,也是特征之上的线性预测器
  4. 三大谜题:我们概述了围绕深度学习的表达能力、优化和泛化三大未解之谜。
  5. 表达能力:我们重点探讨了神经网络的*似能力。通过 Barron 定理 和直观的图示证明,我们了解到即使是很浅的网络(如单隐藏层),只要足够宽,就足以在理论上*似一大类函数。我们也简要提到了 ReLU 网络如何通过组合来实现分段线性*似。

理解神经网络的表达能力是理解其为何成功的第一步。在下节课中,我们将面对第二个谜题:如何通过优化算法(如梯度下降)来训练这个拥有海量参数的复杂非凸模型。

23:神经网络训练与反向传播算法 🧠

概述

在本节课中,我们将学习如何训练神经网络。我们将重点介绍反向传播算法,这是一种高效计算神经网络中所有参数梯度的核心方法。我们将从回顾神经网络的基本结构开始,然后深入探讨训练过程、损失函数以及如何通过链式法则计算梯度。


神经网络回顾

上一节我们介绍了神经网络的基本结构。本节中,我们来看看神经网络的本质及其在监督学习中的作用。

神经网络的本质

神经网络本质上是一个函数。在监督学习中,我们使用它来进行预测。给定一个输入观测值 x,神经网络实现一个函数 F,并利用该函数进行预测。

核心公式:
预测值 = F(x)

在课程中,我们主要将神经网络用于监督学习。我们观察训练数据,包括输入 x 和输出 y,目标是学习 xy 之间的关系,以便对新输入 x 预测其对应的标签 y

线性预测与特征学习

我们之前看到,线性预测的形式是 φ(x)^T w,其中 φ 是特征映射。线性预测的效果取决于特征 φ 的好坏,而这些特征通常由领域专家手动设计。

当使用神经网络进行预测时,预测值就是 F(x),其中 F 是由神经网络实现的函数。神经网络的参数是所有权重 W 和偏置 b。因此,神经网络的目标是学习一个最佳函数,以找到 xy 之间的最佳关系。

神经网络实际上是一种学习高维函数的方式。最终,它只是一个函数。

网络结构:表示学习与线性预测

神经网络可以大致分为两部分:

  1. 第一部分(输入层和所有隐藏层):将输入 x 转换为一种良好的表示或特征。这部分自动为数据学习好的特征。
  2. 第二部分(最后一层,输出层):在这个学习到的良好表示之上,进行线性预测(例如线性回归或逻辑回归)。

因此,神经网络的核心是自动为数据学习一个好的表示(特征),而之前这需要手动完成。


神经网络结构详解

让我们再次回顾一下神经网络的基本结构。

网络层与节点

  • 输入层:有 D 个节点,每个节点对应输入 x 的一个分量。
  • 隐藏层:有 L 层,每层有 K 个节点(为简化,假设每层节点数相同)。
  • 输出层:有 1 个节点(以回归为例)。

信号在网络中沿着节点传播。我们用 x_i^l 表示第 l 层第 i 个节点的值。

全连接与参数

我们考虑的是全连接神经网络。这意味着每一层的每个节点都与前一层的所有节点相连。

网络的参数包括:

  • 权重:每条连接边(例如,连接第 l-1 层节点 i 和第 l 层节点 j)都有一个权重 w_{ij}^l
  • 偏置:每个节点都有一个偏置 b_j^l

这些权重和偏置就是我们需要学习的参数,类似于线性回归中的 w

前向传播与激活函数

节点值的更新是递归定义的。第 l 层第 j 个节点的值 x_j^l 计算如下:

核心公式:
z_j^l = Σ_i (w_{ij}^l * x_i^{l-1}) + b_j^l
x_j^l = φ(z_j^l)

其中:

  • z_j^l 是应用激活函数前的值。
  • φ非线性激活函数

激活函数的非线性至关重要。如果激活函数是线性的,那么整个神经网络实现的函数也将是线性的,多层结构就失去了意义。非线性激活函数使得神经网络能够表达非常丰富复杂的函数。


神经网络的函数逼*能力

上一节我们探讨了神经网络可以逼*何种函数。本节中,我们简要回顾相关结论。

我们研究了神经网络(特别是具有 sigmoid 或 ReLU 激活函数的网络)对*滑函数的逼*能力。主要结论有两类:

  1. L2 距离(*均意义):神经网络实现的函数与目标函数 f 之间的 L2 距离可以很小。
  2. L∞ 距离(逐点意义):对于 ReLU 激活函数,我们还可以得到逐点逼*的结果。

这些理论结果保证了足够大的神经网络能够*似广泛的函数,这是其强大表达能力的基础。


训练神经网络:问题定义

现在,我们转向本节课的核心问题:如何训练一个神经网络?

目标:最小化损失函数

假设我们处理一个回归问题,训练集为 { (x_n, y_n) },共有 N 个样本。我们使用均方误差作为损失函数:

核心公式:
L(W, b) = (1/N) * Σ_n (y_n - F(x_n))^2

其中 F(x_n) 是由权重 W 和偏置 b 定义的神经网络函数。

我们的目标是找到一组参数 (W, b),使得损失函数 L 最小化。在实践中,我们可能还会添加正则化项(如权重衰减)来防止过拟合,但这不会改变训练算法的本质。

训练面临的挑战

与线性回归、逻辑回归等模型不同,训练神经网络面临两个主要挑战:

  1. 非凸优化问题:损失函数 L 关于参数 (W, b)非凸的。这意味着优化算法不能保证收敛到全局最小值,而可能陷入局部极小值或鞍点。
  2. 参数量巨大:神经网络通常有大量参数(例如 ~K^2 * L)。这意味着存在许多能完美拟合训练数据的函数,其中一些会泛化得很好,而另一些则会过拟合。仅仅最小化训练损失并不能保证获得泛化能力强的模型。

优化算法:随机梯度下降

我们如何最小化这个非凸的损失函数呢?

我们将使用随机梯度下降 算法。因为在实际中,训练集规模 N 通常很大,计算完整损失函数的梯度(批量梯度下降)成本太高。

在 SGD 的每一步,我们均匀地采样一个样本 n(或一个小批量 mini-batch),然后计算该样本的个体损失函数的梯度:

个体损失: l_n = (y_n - F(x_n))^2

然后,我们沿着该梯度负方向更新所有参数:

参数更新(对于权重 w_{ij}^l): w_{ij}^l := w_{ij}^l - η * (∂l_n / ∂w_{ij}^l)
(偏置 b 的更新类似)

其中 η 是学习率。

因此,实现 SGD 算法的关键在于:如何高效地计算损失函数关于每个参数的梯度 (∂l_n / ∂w_{ij}^l) 和 (∂l_n / ∂b_j^l)。这正是本节课要解决的核心问题。

SGD 的优势:尽管问题是非凸的,但 SGD 在实践中表现非常好,通常能找到训练损失较小的解,并且这些解往往具有良好的泛化能力。


反向传播算法:高效计算梯度

神经网络函数是许多层的复合函数。计算梯度需要应用链式法则。直接计算所有参数的梯度看似计算量巨大(可能有 O(K^2 * L) 个参数,每个梯度计算又涉及多层链式求导)。

然而,反向传播算法 提供了一种非常高效的方法,能够以大约 O(K^2 * L) 的复杂度(即与参数量同阶)计算出所有梯度。

第一步:前向传播

在计算梯度之前,我们需要先进行一次前向传播来计算网络中所有节点的值。

算法过程:

  1. 从输入 x^0 = x 开始。
  2. 对于每一层 l = 1 to L+1
    • 计算 z^l = W^l * x^{l-1} + b^l (应用权重和偏置)
    • 计算 x^l = φ(z^l) (应用激活函数)

前向传播结束后,我们得到了所有层的 z^lx^l。这个过程的复杂度是 O(K^2 * L),与网络参数数量成正比。

第二步:反向传播与梯度计算

现在,我们需要计算损失函数关于每个 z_j^l 的梯度,我们将其记为 δ_j^l

定义: δ_j^l = ∂l_n / ∂z_j^l

关键思想:我们可以从输出层开始,反向逐层计算这些 δ

  1. 初始化输出层梯度 (δ^{L+1})
    对于回归问题(均方误差损失,输出层激活函数为恒等函数):
    δ^{L+1} = ∂l_n / ∂z^{L+1} = 2 * (F(x_n) - y_n) * φ̃'(z^{L+1})
    由于 φ̃ 是恒等函数,其导数为1,所以简化为:
    δ^{L+1} = 2 * (F(x_n) - y_n)
    (如果使用其他损失函数或输出激活函数,此处公式会变化,但算法框架不变。)

  2. 反向递归计算 (δ^l)
    利用链式法则,可以推导出相邻层梯度之间的关系:
    δ^l = ( (W{l+1})T * δ^{l+1} ) ⊙ φ'(z^l)
    其中:

    • 表示逐元素相乘(Hadamard积)。
    • φ'(z^l) 是激活函数在 z^l 处的导数向量。
      这个公式告诉我们,第 l 层的梯度可以通过第 l+1 层的梯度和第 l 层的权重矩阵转置相乘,再与第 l 层激活函数的导数逐元素相乘得到。

    我们从 δ^{L+1} 开始,利用上述公式反向计算 δ^L, δ^{L-1}, ..., δ^1。这个反向过程的复杂度也是 O(K^2 * L)

  3. 计算参数梯度
    一旦我们有了所有的 δ^l 和前向传播中存储的 x^{l-1},计算权重和偏置的梯度就非常简单了:

    • 权重梯度: ∂l_n / ∂w_{ij}^l = δ_j^l * x_i^{l-1}
    • 偏置梯度: ∂l_n / ∂b_j^l = δ_j^l

    直观理解:权重的梯度等于“该连接下游节点的误差信号 δ_j^l”乘以“该连接上游节点的激活值 x_i^{l-1}”。偏置的梯度直接等于其所在节点的误差信号。

算法总结

以下是反向传播算法的完整步骤:

  1. 前向传播:输入 x,计算并存储每一层的 z^lx^l
  2. 计算输出误差:根据损失函数计算 δ^{L+1}
  3. 反向传播:利用公式 δ^l = ( (W{l+1})T * δ^{l+1} ) ⊙ φ'(z^l) 从后向前计算所有 δ^l
  4. 计算参数梯度:利用公式 ∂l_n / ∂w_{ij}^l = δ_j^l * x_i^{l-1}∂l_n / ∂b_j^l = δ_j^l 计算所有权重和偏置的梯度。

通过一次前向传播和一次反向传播,我们就能高效地得到损失函数关于所有参数的梯度,然后就可以用 SGD 更新参数了。


常用激活函数

在结束前,我们简要回顾几种常用的激活函数及其特点:

  1. Sigmoidσ(x) = 1 / (1 + e^{-x})
    • 优点:*滑,易于求导。
    • 缺点:当输入绝对值很大时,梯度会趋*于0(梯度消失问题),这使得训练深层网络非常困难。

  1. Tanhtanh(x)
    • 优点:输出以0为中心,收敛可能比Sigmoid快。
    • 缺点:同样存在梯度消失问题。

  1. ReLU (整流线性单元)ReLU(x) = max(0, x)

    • 优点:对于正输入,梯度恒为1,有效缓解了梯度消失问题,使得训练深层网络成为可能。计算简单高效。
    • 缺点:在 x=0 处不可导(实践中通常指定一个导数)。对于负输入,梯度为0,可能导致某些神经元“死亡”(不再被激活)。
  2. Leaky ReLULeakyReLU(x) = max(αx, x),其中 α 是一个小的正数(如0.01)。

    • 优点:解决了 ReLU 在负区间梯度为0的问题,可能缓解“神经元死亡”问题。

  1. Maxoutmax(w_1^T x + b_1, w_2^T x + b_2, ...)
    • 优点:是 ReLU 和 Leaky ReLU 的泛化,可以学习更复杂的激活函数。
    • 缺点:参数数量增加。

在实践中,ReLU 及其变体(如 Leaky ReLU)是最常用的隐藏层激活函数。


总结

本节课中我们一起学习了:

  1. 神经网络的训练目标:最小化损失函数(如均方误差),这是一个非凸优化问题。
  2. 核心优化算法:使用随机梯度下降 来更新网络参数。
  3. 反向传播算法:这是训练神经网络的核心。它通过一次前向传播计算网络中间值,再通过一次反向传播高效地计算损失函数关于所有参数的梯度。其关键在于利用链式法则和递归关系从输出层向输入层传播误差信号。
  4. 激活函数的选择:我们比较了几种常见激活函数(Sigmoid, Tanh, ReLU, Leaky ReLU),并指出 ReLU 族函数因其能有效缓解梯度消失问题而成为训练深层网络的主流选择。

通过结合 SGD 和反向传播,我们能够有效地训练复杂的神经网络,使其在众多任务上取得卓越的性能。

24:第8次练习入门教程 🚀

在本教程中,我们将介绍 EPFL 机器学习课程第8次练习的入门内容。我们将学习如何使用 PyTorch *台开始深度学习项目,并简要讨论神经网络中的梯度消失问题。本教程旨在帮助初学者理解核心概念并上手实践。


1. 熟悉 PyTorch 📚

上一节我们概述了本次练习的目标,本节中我们来看看如何开始使用 PyTorch。首先,请熟悉 PyTorch 官方教程。以下是两个推荐的官方教程链接:

  • 第一个教程是一个16分钟的快速回顾,帮助你更好地理解 PyTorch 库及其高级 API。
  • 第二个教程通过自包含的示例介绍了 PyTorch 的基本概念。它从你可能在之前项目和练习中见过、用过的模块开始。

在之前的实验中,你需要手动实现反向传播部分来更新模型。但对于更大、更复杂的网络,这种方法不可行。这就是为什么我们需要使用 PyTorch 作为开发大型模型的标准工具之一。

该教程介绍了 PyTorch 最基本的概念——张量。张量可以跟踪计算图和梯度,并为自动微分提供支持。教程还包含了对自动微分的介绍,它使我们能够自动化大型计算图中反向传播的计算。此外,教程描述了 nn.Module API,它功能强大,可以帮助我们定义复杂的算子,并自动计算不同序列上的导数。

如果你不熟悉 PyTorch,强烈建议在开始练习前先查看这些教程。


2. 问题一:实现基础模型 🔧

现在让我们回到练习本身。对于问题一,我们首先要求你实现基础线性回归。这里,我们尝试构建一个自包含的 PyTorch 流程。请注意不要使用 torch.nn 中的现成模型。

你需要修改以下三个函数:

  • 模型初始化函数
  • 前向传播函数
  • 损失函数

最终,你将得到一个可微分的模型,它可以基于随机输入进行预测。你还需要实现一个评估函数,以便用于后续的测试。

一旦我们有了模型和损失函数,就需要在 PyTorch 中定义训练流程。你需要修改以下三个步骤:

  1. 前向传播计算预测值
  2. 计算损失
  3. 反向传播并更新参数

期望的输出结果类似于一个能够拟合数据的线性模型。


3. 问题一:深入理解算子与模块 🧠

上一节我们完成了基础线性回归的实现,本节中我们来看看更高级的用法。对于练习2,我们设置了一个非常简单的例子,帮助你更好地理解 PyTorch 中最基本的算子类型。

对于练习3,我们将介绍 PyTorch 中的 nn 包。你将需要使用这个标准模块来重构之前的线性回归类。当你面对大型神经网络时,你会理解它为何如此有帮助。

最后,你将需要实现一个更复杂的神经网络——一个两层的多层感知机。它将输出一个非线性特征映射,正如在练习1B中那样。

到目前为止,我们简要介绍了实践问题一的内容。希望你能够通过它入门 PyTorch,这将对你的项目有所帮助。


4. 问题二:梯度消失问题 📉

对于问题二,这是一个理论性问题。你需要对 Sigmoid 函数进行简单的求导,并考虑网络层数的影响。

利用以下两个提示,你应该可以得出最终结论:

  • 提示一:推导 Sigmoid 函数导数的表达式。
  • 提示二:分析当该导数在多层网络中连乘时会发生什么。

通过这个练习,你将理解为什么更深的网络会存在梯度消失问题。


总结 ✨

在本节课中,我们一起学习了如何开始使用 PyTorch 进行深度学习练习。我们从熟悉 PyTorch 官方教程开始,然后动手实现了基础的线性回归模型,并理解了 PyTorch 中算子和模块的使用。最后,我们从理论层面探讨了神经网络中著名的梯度消失问题及其成因。希望本教程能为你后续的机器学习项目打下坚实的基础。

25:卷积神经网络与深度学习技巧 🧠

在本节课中,我们将学习深度学习中的多个核心主题,包括卷积神经网络、正则化、数据增强、Dropout和批归一化。这些技术是现代深度学习,特别是计算机视觉领域取得成功的关键。


从全连接网络到卷积网络 🔄

上一节我们介绍了全连接神经网络。在全连接网络中,每一层的每个神经元都与前一层的所有神经元相连。对于一个有L层、每层K个神经元的网络,其参数量级为 O(K²L)。参数量巨大,导致训练非常复杂,并且需要海量数据。

此外,当处理计算机视觉任务(如图像识别)时,输入维度极高(例如,256x256x3 ≈ 20万维)。全连接网络会将图像展*为向量,从而完全丢失了像素间的空间依赖关系(例如,相邻像素在展*后可能相距甚远)。这意味着我们失去了图像中至关重要的局部结构信息。

因此,我们需要一种既能处理高维数据,又能保留空间结构的网络架构。卷积神经网络应运而生。


卷积层:定义与核心思想 🧩

卷积层的核心思想是进行局部加权*均。它模仿了信号处理中的卷积操作,仅对输入数据的局部区域进行处理,从而提取特征。

卷积运算公式

给定一个输入矩阵 X⁰ 和一个滤波器(或卷积核)F,输出矩阵 中的每个元素计算如下:

X¹[n, m] = Σ_k Σ_l F[k, l] * X⁰[n + k, m + l]

其中,滤波器 F局部的,即当 k 和 l 较大时,F[k, l] = 0。这意味着输出 X¹[n, m] 的值仅依赖于输入 X⁰ 在位置 (n, m) 附*的一小片区域。

卷积的关键特性

  1. 稀疏连接:输出层的每个神经元只与输入层的一小部分神经元相连,这使得权重矩阵非常稀疏。
  2. 参数共享:同一个滤波器 F 会滑动遍历整个输入图像。这意味着网络中许多不同的连接共享相同的权重值。

这两种特性极大地减少了模型的参数量,使其更易于训练,并能更好地捕捉图像的局部特征。


边界处理与填充策略 🛡️

在卷积过程中,滤波器移动到图像边界时,部分区域会超出图像范围。我们有两种主要的处理策略:

以下是两种主要的填充方式:

  • 零填充:在输入图像的边界外围填充零值,使得卷积操作可以对原始图像的每一个位置进行计算。输出特征图尺寸与输入相同。
  • 有效填充:只对输入图像中能够完整应用滤波器的位置进行计算。输出特征图尺寸会小于输入图像。

在实际构建网络时,可以根据架构设计选择使用零填充或有效填充。


多通道卷积与池化层 📊

多通道卷积

在实践中,我们通常会对输入应用多个不同的滤波器。每个滤波器会产生一个独立的输出矩阵,这些矩阵被称为“通道”。因此,卷积层的输出是一个三维张量(高度 x 宽度 x 通道数)。

当输入本身具有多个通道(例如RGB图像的3个通道)时,卷积核的深度必须与输入通道数相同。计算时,对每个输入通道应用对应的滤波器,然后将所有通道的结果求和,并加上偏置项,得到单个输出值。

池化层

池化层通常接在卷积层之后,用于降低特征图的空间尺寸,从而减少计算量并提取更鲁棒的特征。池化操作是逐通道独立进行的。

以下是两种常见的池化方式:

  • 最大池化:取滤波器覆盖区域内的最大值。输出 = max(区域值)
  • *均池化:取滤波器覆盖区域内的*均值。输出 = mean(区域值)

池化操作通常以非重叠的方式滑动窗口。在实践中,最大池化因其更好的性能而更常被使用。


卷积神经网络的整体架构 🏗️

一个典型的卷积神经网络由卷积层和池化层交替堆叠而成。

初始的卷积层倾向于提取低级特征(如边缘、颜色),随着网络加深,后续层能够提取更高级的特征(如物体部件)。

在通过一系列卷积和池化层提取特征后,我们会将最终的三维特征图展*成一个一维向量。然后,在这个向量后面连接一个或多个全连接层,用于完成最终的分类或回归任务。

整个网络的参数(权重和偏置)通过反向传播算法进行学习。


卷积网络的反向传播 ⚙️

卷积神经网络的反向传播需要考虑其两个特殊结构:

  1. 稀疏权重矩阵:由于连接稀疏,许多权重恒为0,在反向传播中无需更新,这不会带来问题。
  2. 权重共享:多个连接共享同一权重。处理方法是:
    • 首先,忽略权重共享,进行标准的反向传播,计算每个连接的梯度。
    • 然后,将所有共享同一权重的连接的梯度求和
    • 最后,用这个求和后的梯度来更新那个共享的权重。

这本质上是链式法则在约束优化中的应用。


神经网络的泛化:正则化与数据增强 🛡️

权重衰减

与线性模型类似,对神经网络进行正则化有助于防止过拟合。通常我们只对权重进行L2正则化,而不对偏置项进行正则化。

L2正则化的目标函数为:损失函数 + λ * Σ ||W||²
这等价于在随机梯度下降更新时,加入权重衰减项:W := (1 - γλ)W - γ * 梯度

偏置项控制着激活函数的阈值,我们通常希望它能自由调整以适应数据,因此不加以正则化。

数据增强

数据增强是一种通过人工扩展训练集来提升模型泛化能力和鲁棒性的强大技术。其核心思想是应用一系列保持标签不变的变换 τ 到原始数据上。

例如,对于图像分类任务,有效的增强包括:

  • *移、旋转、缩放
  • 水*翻转
  • 裁剪、颜色抖动
  • 添加噪声、模拟天气效果(雨、雪、雾)

通过数据增强,我们不仅获得了更多训练样本,还隐式地教会了模型对这些变换具有不变性,从而显著提升模型在真实复杂场景下的性能。


Dropout:随机失活 🎲

Dropout是一种在训练阶段随机“关闭”网络中一部分神经元的技术,它有两种重要作用:防止过拟合和实现模型集成。

训练阶段

对于网络中的每个神经元,以概率 p(保留概率)将其激活,以概率 1-p 将其输出置零(即“丢弃”)。每次前向传播时,都随机生成一个不同的“子网络”进行训练。

测试阶段

使用完整的网络进行预测。为了补偿训练时因丢弃神经元而导致的期望输出变化,需要对权重进行缩放:

  • 推理时缩放:将训练好的所有权重乘以保留概率 p
  • 训练时缩放(更常用):在训练时,对每个被保留的神经元的激活值除以 p

Dropout的作用

  1. 减少协同适应:防止神经元过度依赖其他特定的神经元,迫使每个神经元都能独立地提供有用的特征。
  2. *似模型集成:训练过程相当于同时训练了大量不同的子网络。测试时对这些子网络的预测进行了*均,这类似于集成学习,但计算效率高得多。

批归一化:稳定训练加速收敛 ⚡

批归一化是一种通过标准化每一层输入来稳定和加速深度网络训练的技术。

操作步骤

对于一个小批量数据中的某一层激活:

  1. 计算该批数据的均值和方差:
    μ = mean(批量数据), σ² = variance(批量数据)
  2. 对数据进行归一化:
    X_hat = (X - μ) / sqrt(σ² + ε) (ε 是为数值稳定性添加的小常数)
  3. 引入可学习的缩放和*移参数:
    Y = γ * X_hat + β
    参数 γβ 通过网络学习得到,它们使网络可以恢复原始的表示能力。

主要优点

  • 允许使用更大的学习率:减轻了内部协变量偏移问题,使优化地形更*滑。
  • 对初始化不那么敏感
  • 有一定的正则化效果:因为每个样本的激活都受到批次内其他样本的影响。

在测试时,使用训练阶段计算得到的移动*均均值和方差进行归一化。


总结 📝

本节课我们一起学习了深度学习中几项至关重要的技术:

  • 卷积神经网络:通过局部连接和权重共享,高效处理图像等网格化数据,保留空间信息。
  • 正则化:通过权重衰减约束模型复杂度,防止过拟合。
  • 数据增强:人工扩展数据集,提升模型泛化能力和对不变性变换的鲁棒性。
  • Dropout:在训练中随机丢弃神经元,防止过拟合并实现高效的模型集成。
  • 批归一化:标准化层输入,稳定训练过程,允许使用更大的学习率,加速收敛。

这些技术共同构成了现代深度学习,特别是计算机视觉领域取得突破性进展的基石。理解并合理运用它们,是构建高效、鲁棒神经网络模型的关键。

26:对抗性机器学习 🛡️

在本节课中,我们将学习一个机器学习领域的新兴且令人兴奋的主题——对抗性机器学习。这是一个在过去几年非常活跃的研究领域,但仍有许多工作要做,并且具有非常重要的实际应用价值。

什么是对抗性机器学习?🤔

当我们谈论对抗性机器学习时,我们具体在讨论什么?观察人类视觉,你会发现一些对人类来说困难的任务。例如,区分一张图片是狗还是拖把,对人类来说并不总是容易的。你可能会认为,神经网络在处理这类任务时也会遇到同样的问题。

然而,事实并非如此。对于神经网络来说,这类任务实际上非常容易。在许多模式识别、语音处理等任务中,今天的神经网络甚至能取得比人类更好的性能。但事实上,神经网络在做出预测和决策的方式上存在许多问题,它们并不具备鲁棒性。当我们希望使用神经网络来理解世界并做出决策时,这一点变得尤为重要。你真正需要的是一个可以信赖的、鲁棒的检测器。

今天我们将看到,神经网络很容易被欺骗,这是一个主要问题。

对抗样本 🎯

那么,我们所说的“被欺骗”是什么意思呢?这就是所谓的对抗样本。对抗样本是指你可以添加到图片中的一些微小扰动,这些扰动会使你的神经网络完全迷失方向。

例如,有一张猪的图片,所有人都能认出这是一头猪。但我们可以手动添加一些微小的噪声(注意,这种扰动是精心设计的,并且非常小)。当我们观察结果图片(即原始猪的图片加上这个小扰动)时,教室里的所有人仍然会看到一头猪,并且非常确信这是一头猪。

然而,如果你要求你的神经网络对这张图片进行分类,它会告诉你这是一架飞机。但如果你要求神经网络对原始图片进行分类,它会告诉你这是一头猪。对人类来说,这完全是同一张图片,但对神经网络来说,一张是猪,另一张是飞机。

这种现象并非这张图片所特有。我们今天将看到,对于任何图片,都有可能找到这样的扰动,从而使你的神经网络被欺骗。这就是所谓的对抗样本。

你可以看到,你的神经网络在处理这类样本时确实存在困难。不难想象,这在安全方面将是一个巨大的问题。因为如果欺骗你的网络如此容易,你如何能依赖你的数据来做出真正重要的决策?这不仅仅是针对自动驾驶摄像头,你可以想象在许多应用中,如果决策如此不可靠,你还能依赖它们吗?

这是第一个问题。第二个问题是,即使不考虑安全问题,我们也发现我们根本不理解这些架构是如何泛化的。或者,是否可能当我仅轻微改变输入图片时,它的预测就发生了改变?这就是我们今天要讨论的问题。

形式化定义 📐

让我们尝试更形式化地定义这个问题。我们将考虑一个分类问题,具体来说是一个二分类问题。和往常一样,(X, Y) 遵循某个未知的分布 DY 属于两个类别:-11

今天我们将主要讨论神经网络,因此我的函数 F 将是通过神经网络学习到的预测分类器。但鲁棒性问题实际上超越了神经网络,如果你考虑线性分类器,也会遇到同样的问题。这是一个非常普遍的问题。

我们有一些来自 D 的样本,并学习了一个分类器 F。在课程的第一部分,我们了解到,为了判断你的分类器是否是一个好的分类器,你希望分类器具有较小的风险。我们关注的是分类损失,即 F(x) ≠ y 的指示函数。如果你分类正确,则没有损失;如果分类错误,则付出代价 1。我们对所有可能的 (x, y) 分布取损失的期望值。

这个期望值恰好等于犯错的概率。因此,在经典的监督学习中,我们希望最小化犯错的概率。但这是*均意义上的风险。

那么,如果你希望做出鲁棒的预测,这个风险定义的问题是什么?问题在于它是一个期望值,是*均意义上的风险。你希望*均意义上表现不太差,但它没有考虑到最坏情况。

因此,我们今天将引入所谓的对抗风险。对抗风险 R_epsilon(f) 在级别 epsilon 上仍然是期望值,但不再是对数据 XF(x) ≠ y 指示函数的期望,而是对最坏情况指示函数取期望。我们取所有在 X 的球 B_epsilon(x) 内的 x' 中,指示函数的最大值。

我们在这里做的是:假设我们有一个对手,他被允许轻微地操纵你的输入。对手不会让你在 x 上评估,而是让你在 x' 上评估,但你仍然希望表现良好。因此,你不仅希望在 x 上表现良好,还希望在 x 周围的所有球内都表现良好。

当然,你必须施加一些约束,因为如果没有任何约束,对手非常强大,可以将 x' 设置得离 x 非常远,那么问题将变得非常困难。这就是为什么我们要施加约束,要求 x' 不能离 x 太远。

我们需要定义这个距离是什么,以及 epsilon 是什么。本质上,对于每个 x,都有一个对手可以找到最坏的扰动,而你不希望被欺骗。

我们可以通过图片来理解这一点。经典风险是:我们有一些点,例如 -1+1,我们希望找到一个分类器能很好地对我们的数据进行分类。我们只是希望所有绿点在一侧,所有蓝点在另一侧,这是标准的经典风险。

当我们考虑对抗风险时,我们观察每个点 x 周围的某个球,并希望你在该球内预测相同的标签。现在,如果我观察这个之前获得很小标准风险的线性预测器,你会发现这个预测器的对抗风险会变差,因为例如对于那个在标准风险下分类正确的点,我现在可以找到一个最坏情况的实例,而它没有被正确分类。

因此,你不仅希望风险对所有输入 X 都很小,还希望显然能在 X 周围的所有球内进行正确预测。这就是对抗风险的定义。

需要牢记的重要一点是,对于某些预测器,有可能具有非常低的标准风险,但却具有很大的对抗风险。仅仅因为你强制要求在这个定义下表现良好,并不意味着它就是鲁棒的。

这就是为什么当我们考虑鲁棒性时,你不仅希望*均意义上表现良好,还希望在最坏情况下表现良好。你真正希望的是不存在能欺骗你的对抗样本。因此,如果你能最小化这个对抗风险,那么你将得到一个鲁棒的分类器。

对抗风险引发的问题 ❓

对抗性漏洞引发了许多不同的问题。

  1. 如何定义威胁模型? 如何定义对手的游戏规则?你需要考虑使用哪种范数:L∞ 范数、L2 范数、L1 范数,还是 L0 范数(这不是一个真正的范数)?你如何描述你的几何形状?或者你想定义一组扰动?这里我们只考虑一些球,但它可以是任何你可以描述的集合。这就像是第一个问题:我应如何定义我的威胁模型?这个威胁模型定义了对抗性程序。

  2. 标准风险小的预测器,其对抗风险能有多差? 如果你有一个标准风险很小的神经网络 F,当你观察对抗风险时,情况能有多糟糕?对抗风险能有多大?这是我们将尝试解决的第二个问题。

  3. 如何计算对抗样本? 我们是否有算法,对于每个输入图片,都能给出一个对抗样本?对于这样的算法,它需要何种程度的神经网络访问权限?这也是我们今天要讨论的。

  1. 是否可能设计一个鲁棒的分类器? 是否可能解决这个问题?是否可能使用神经网络设计一个鲁棒的分类器?我们该如何做?

  2. 是否可能将一个非鲁棒的分类器转化为鲁棒的? 如果我们给你一个不鲁棒的分类器 F,是否可能通过某种理论变换将其转化为鲁棒的分类器?这也是可能的,你可以在课程资料中查看。

  1. 为什么神经网络如此不鲁棒? 如果时间允许,我们将尝试稍微探讨一下。

你可以看到,所有这些对抗性机器学习问题都非常重要,我们将尝试回答其中的一些问题。

生成对抗样本 ⚔️

首先,让我们看看如何生成对抗样本。我们如何获得能欺骗神经网络的、对猪图片的扰动?

我们想要做什么?我给你一个输入 (x, y),即一张图片和一个标签(例如一张猪的图片,我告诉你这是一头猪)。我还给你一个神经网络 F。你的神经网络实际上是一个从图片空间到 {-1, 1} 的函数(在之前的例子中是多分类问题,有猪、飞机等不同类别;这里我们只考虑二分类 -11,但问题是完全相同的)。

我给你一个输入,我给你一个模型。你的任务是什么?你想找到一个输入 x',使得:

  1. x' 接* x。你希望你的对抗样本不要离初始图片太远,有一个指定的距离,你希望这个距离小于 epsilon
  2. 你的模型 Fx' 上犯错误。你希望找到一张接*猪的图片,但当你问神经网络这是否是一头猪时,神经网络说不是。

施加这个约束非常重要,否则会非常容易:如果给出另一张图片,它当然不是猪。所以,你想找到接* xx',使得神经网络在这个 x' 上犯错误。

有两种可能的情况:

  • 简单情况x 已经被网络错误分类。那么你什么都不用做,因为你已经找到了一个非常接* x 的点(就是 x 本身),并且你的神经网络在预测这张图片时犯了错误。
  • 我们假设的情况x 被你的神经网络正确分类。我们假设 F(x) = y 是正确的标签。我们想找到一个点 x',使得 F(x') ≠ y,并且 ||x' - x|| ≤ epsilon

观察图片,我们想要什么?我们想找到一个点 x',它在以 x 为中心、半径为 epsilon 的球内,并且在你决策边界的另一侧。这里 x+1 的一侧,所以你希望找到一个点,使得 F(x') = -1

因此,问题完全等同于在这个集合中找到一个点:你的球与神经网络预测标签为 -y 的所有点的交集。

为了找到这样的 x',你能做什么?想象我给你无限的计算能力,你可以直接在这个集合中搜索并尝试找到一个点。但这在计算上不可行。我们还能尝试做什么?我们可以尝试限制搜索空间,这是一个选择。但我们还能做更简单的事吗?每当我们想做某事时,我们通常会做什么?我们会尝试找到一个优化目标,这样如果你解决了这个目标,你就会找到一个对抗样本。这个目标将不是凸的,但我们已经不害怕非凸性了。

转化为优化问题 🔄

实际上,尝试找到一个对抗样本完全等价于最大化以下函数:
max_{x' : ||x' - x|| ≤ epsilon} 1_{F(x') ≠ y}

为什么等价?根据定义,一个对抗样本是一个满足约束的点 x',使得 F(x') ≠ y。所以,如果你有一个对抗样本,这个值将等于 1。由于这个函数只取 01,最大化它就相当于找到一个 x' 使这个函数等于 1,也就相当于找到一个对抗样本。

所以,如果你能解决这个最大化问题,你就完成了,找到了你的 x'

这个问题与之前课程中看到的问题的主要区别是什么?

  1. 之前,当我们考虑分类损失时,我们想对函数 F 进行优化,想找到一个实现低分类损失的预测器。现在,我的优化问题不再针对函数 F,而是针对我的输入 x'。我在寻找一个输入 x',使分类损失很大。
  2. 第二个区别是,我们现在是在做最大化,而不是最小化。

另外,如果你还记得,当我们讨论支持向量机时,我们遇到了完全相同的问题:为什么这个优化问题很困难?除了非凸/非凹之外,首先是因为指示函数是一个非连续函数。它从 1 跳到 0 的方式是不连续的。所以这个函数不可微,难以最小化或最大化。非连续优化比连续优化更困难。

第二个问题是,我们考虑的是神经网络。我们考虑神经网络直接输出类别。所以神经网络是一个分类器,其输出值在 {-1, 1} 之间。所以它是一个从 x{-1, 1} 的函数,输出空间是离散的,因此也很难微分。

我们已经在考虑分类损失时遇到过这两个问题。你还记得我们如何解决这两个问题吗?

对于第一个问题(非连续性),我们可以通过另一个*滑函数来松弛这种不连续性。对于第二个问题(神经网络输出离散值),我们可以考虑神经网络在量化之前的输出。我们假设神经网络在做出决策之前输出一个连续值 G(x),它可以被解释为估计 y=1 给定 x 的概率。然后,神经网络根据这个概率进行预测:如果 G(x) > 0.5,则预测标签为 1,否则为 0(或者用符号函数:如果 G(x) 为正,则预测 +1;为负则预测 -1,这完全一样)。

因此,为了解决第二个问题,我们考虑神经网络在量化之前的输出,即一个连续值。

主要思想是,我们将这个困难的问题(最大化一个不连续函数)替换为这个更简单的问题:最大化一个*滑函数。现在我想在一个约束集上最大化一个*滑函数。

但你仍然可以看到,这仍然不容易,因为你的神经网络 G 是一个非凸函数。所以你仍然有一个非凸问题:在一个集合上最大化这个非凸函数,这仍然是一个难以保证收敛的问题。但在实践中,它通常工作得非常好。

另一个主要问题是我们将如何解决这个*滑且有约束的问题?正如你所说,我们将尝试使用基于梯度的优化。但与之前的主要区别是什么?

  1. 我不再是对网络的权重参数进行优化,而是在对输入进行最大化。
  2. 我是在最大化函数,而不是最小化。
  3. 我的集合上有约束。

白盒攻击:已知模型 🕵️

首先,让我们看看如何在所谓的白盒情况下最大化这个问题。白盒情况是指你完全了解你的模型 G(x)。你可以访问 G(x),可以微分 G(x),你知道一切。

如果你知道一切,并且你想最大化这个函数,首先假设我们忘记约束,我们应该做什么?我们已经将不可微的程序松弛为一个可微的程序,所以我们想计算这个函数关于输入的梯度。这并不难,损失函数关于输入的梯度恰好等于:损失函数的导数在 (y, G(x)) 处的值,乘以 y,再乘以神经网络关于 x 的梯度。

现在我们将使用分类损失是递减的这一事实,即 l' 是负的。所以,如果我想沿着最大化这个函数的方向前进,我应该遵循正梯度方向。我不再是做最小化,所以我不遵循负梯度方向,而是遵循正梯度方向。因此,我想沿着 -y * ∇_x G 的方向前进。

这里的解释是:如果我告诉你 G(x)y=1 的概率,那么如果 y=1,你想降低这个概率,因为你想要犯错误。所以你想沿着负梯度方向走。如果 y=-1,那么为了犯错误,你想增加 y=1 的概率,所以你想沿着 G(x) 的梯度方向走。所以在两种情况下,你都想沿着 -y * ∇G(x) 的方向前进。

这样就结束了吗?我们只需要做梯度上升,乘以某个步长,也许做多步?它会给出解吗?问题是什么?首先,即使在这之前,我们必须考虑约束。如果我只是遵循正梯度步长,我可能会发散到无穷大。所以我们必须考虑我希望 x' 接* x 这一事实。

处理约束:投影梯度上升 📏

由于 epsilon 被认为很小,我们想要带有小噪声的对抗样本,否则就不那么有趣了。我可以做的是,仍然考虑我函数的一阶*似(线性化)。用 L_tilde(x) 表示我的函数 L(y, G(x)),以简化符号。

我想要的正是最大化 L_tilde,对于接* xx',满足 ||x' - x|| ≤ epsilon。由于 epsilon 很小,我说这个函数的最大化非常接*其线性*似的最大化。线性*似恰好等于 L_tilde(x) + ∇L_tilde(x)^T (x' - x)

我想在 x' 上取这个的最大值。第一项完全独立于 x',所以我可以取内部的最大值,得到 L_tilde(x) 加上后面项的最大值。然后我可以做变量替换 x' - x = δ。所以我想做的是:最大化我的梯度和 δ 的标量积,其中 δ 的范数不大于 epsilon

这就是我们试图寻找的:最优局部更新。在局部,如果你接* x 并且想最大化损失函数,它将由这个问题的解给出。好处是,对于许多范数,有可能得到闭式解。

你想取能使你的内积尽可能大的 δ,从而使你的损失函数尽可能大。这就是所谓的最速上升,你想找到能最快增加函数值的方向。

具体攻击方法:FGSM 和 PGD 🎯

我们将看到,对于许多范数,可以以闭式解决它。这就是所谓的单步攻击,我们只做一步梯度上升。我们想最大化这个线性函数,它是有约束的。

考虑 L2 范数的情况。我的球由这个圆(球)给出。我有我的梯度向量,我想找到在我的球面上的向量 δ,使得它与我的梯度向量的标量积最大。很自然地,取 δ 恰好沿着梯度方向,并按比例缩放,使得 δ 的范数等于 epsilon。所以 δ 恰好等于 epsilon 乘以你的梯度 ∇L_tilde 的归一化向量。

因此,最大化这个内积的 δ 恰好是与你的梯度对齐的向量,然后你固定 δ 的尺度为 epsilon。所以这个向量与我的梯度对齐,其尺度为 epsilon:我先归一化我的梯度,然后乘以 epsilon,这样 δ 的范数恰好是 epsilon

然后为了计算 x',你只需更新你的起点 x,并加上你的 δ。所以这是我们的算法:你有一个点 x,然后你给这个点 x 加上这个梯度。你可以看到,你的 x' 恰好在你集合的边界上。如果你看约束,它恰好满足:||x' - x|| 恰好等于 epsilon

现在你计算出了 x',你想用它做什么?这是你的目标:你想找到一个 x' 使你的模型出错。你已经计算出了 x',它在局部最大化了你的损失。现在你想检查这是否是一个对抗样本,所以你想计算 `

27:练习9 - 入门视频 🧠

在本节课中,我们将学习更多关于神经网络的知识。我们将深入探讨反向传播的工作原理,并分析神经网络权重空间的一些内部机制。

在此之前,我们曾学习如何使用 PyTorch 实现具有多层、复杂损失函数和不同激活函数的神经网络。PyTorch 是一个对研究者和工程师都非常有用的工具,它抽象了计算神经网络梯度所需的大部分复杂工作。

然而,在今天的练习中,我们将尝试完成这些复杂工作。这很重要,因为如果我们能在实践中至少实现一次反向传播,将有助于我们更好地理解神经网络的工作原理。

本周的练习包含两个部分。第一部分更偏实践,我们将计算并实现一个简单的单隐藏层神经网络的前向传播和反向传播。第二部分,我们将对这个网络进行一些分析。

第一部分:实现前向与反向传播 🔄

上一节我们介绍了本次练习的目标,本节中我们来看看具体的实践部分。

我们将使用一个非常简单的模型。该模型是一个简单的神经网络,包含一个具有5个神经元的隐藏层,以及一个4维的输入层。这个神经网络将实现一个前向传播,输出一个标量 y_hat

练习1:实现前向传播

在第一个练习中,要求你根据网络结构进行计算以得到 y_hat。这个练习需要使用 NumPy(而非 PyTorch)来实现这个神经网络的前向传播路径,本质上就是将这些方程用 NumPy 重写一遍。

以下是具体步骤:

  • 首先,你需要从逻辑回归课程的代码中复制 sigmoid 函数及其梯度的代码。
  • 然后,实现一个前向传播函数。
  • 我们提供了一些简单的测试,用于验证你的实现是否正确。我们会给出一些示例权重值和输入向量。如果你的函数实现正确,对于这个特定的权重和输入,你得到的标量输出值应该接*预期的结果。

练习2:实现反向传播

在练习的第二部分,我们将计算网络权重相对于损失的梯度,这是训练神经网络所必需的。具体来说,我们将针对特定的损失函数进行计算。

这个练习要求你重现课程中计算反向传播的步骤,本质上就是在网络权重上应用链式法则计算损失函数的梯度。

以下是计算梯度的步骤:

  • 首先,你需要推导出隐藏层权重的梯度表达式,然后是输入层到隐藏层权重的梯度表达式。
  • 为此,你只需要应用链式法则。首先计算损失函数对 y_hat 的偏导数,然后计算 y_hat 对权重的偏导数,依此类推。
  • 正如课堂上所讲,简化计算的一个好方法是引入中间变量 Z1。请仔细进行这些计算。

一旦推导出这些表达式,你需要再次使用 NumPy 编写这些表达式,并计算网络的反向传播。和之前一样,我们会提供一些示例权重值。

如果你的函数实现正确,梯度计算测试将会通过,这表明你的实现是正确的。

第二部分:权重空间的理论分析 📊

上一节我们完成了神经网络前向和反向传播的实践,本节中我们将转向更理论化的分析。

尽管神经网络非常难以分析,但有时我们可以利用课程中学到的一些工具来获得一些直观理解。在这个练习中,我们将讨论一个抽象的神经网络,我们甚至不知道其具体架构,但至少知道我们可以将其所有权重写成一个向量 W

我们将研究神经网络在权重空间(即所有权重可能取值的空间)中的一些性质。为此,我们将对损失函数的结构做一些假设。

众所周知,神经网络的损失函数曲面或优化过程非常复杂,难以分析。但研究者有时为了理解其工作原理,会假设在某个特定点附*,损失函数是凸的。具体来说,我们将假设损失函数在最优权重点 W* 附*可以*似为一个二次函数。

这实际上就是在最优权重集附*对损失函数进行二阶泰勒展开。在这个展开式中,没有梯度项,因为我们在最优点附*,而最优点的梯度为零。因此,这个泰勒展开只包含一个由海森矩阵(Hessian)决定的二次项。海森矩阵是损失函数对权重的二阶导数矩阵。

练习要求你思考:如果现在我们给这个损失函数加上一个类似于岭回归的正则化项,会发生什么?问题在于,添加这个正则化项后,最优解 W* 将如何变化?

这个假设的好处在于,它将所有非凸性抽象掉了,至少在 W* 附*,我们得到了一个凸损失函数。这样,我们就可以使用已学过的凸优化工具,推导出这个二次函数的精确最小值。

你会发现,通过令梯度为零来推导这个最小值,正则化问题的解将具有以下形式:

W_reg = (H + μI)^(-1) H W*

其中,H 是海森矩阵,μ 是正则化系数,I 是单位矩阵。

这个解可以理解为:没有正则化时的最优解 W*,乘以一个依赖于 μ 和海森矩阵特征分解的矩阵。

深入理解正则化效应

推导出这个表达式后,练习的下一部分旨在理解这个项背后的直观含义。

首先,我们需要分析矩阵 (H + μI)^(-1) H 的特征值。你会发现,这实际上是一个对角矩阵,其特征值由因子 μ 重新缩放。

具体来说,对于海森矩阵 H 的每个特征值 λ_i,新矩阵对应的特征值为 λ_i / (λ_i + μ)。

最后的练习试图理解这在实际情况中意味着什么。我们假设海森矩阵有不同的特征值。问题是,根据特征值的大小,正则化项的效果会有什么不同?

我们要求你证明:对于较大的特征值,正则化的影响微乎其微,在该特征向量方向上的分量基本保持不变;而正则化效果主要作用于那些特征值非常小的方向。

这个练习旨在让你更正式地展示这一点,并围绕这个概念建立直观理解。

总结 📝

本节课中我们一起学习了神经网络的核心机制。我们首先动手实现了一个简单神经网络的前向传播和反向传播,以深入理解梯度计算过程。接着,我们通过理论分析,探讨了在最优解附*用二次函数*似损失函数时,权重正则化如何影响最终解,并理解了其效果在不同特征值方向上的差异性。

如果你有任何问题,欢迎在聊天区提出。非常感谢。

28:机器学习中的伦理与公* 👨‍⚖️

在本节课中,我们将要学习机器学习中的伦理与公*问题。我们将探讨算法决策中可能存在的歧视,理解公*性为何不是机器学习模型的默认属性,并介绍几种衡量公*性的统计学标准。


概述:算法决策的现实影响 🤖

如今,机器学习被广泛应用于教育、就业、医疗等多个领域,用于做出关于人类的决策。理解这一点至关重要:机器学习并非天生公*。仅仅因为决策由算法或计算机做出,没有人为干预,并不意味着最终的应用或算法决策就是公*的。

我们生活在一个机器学习模型越来越强大、越来越容易实现的世界。作为未来的软件工程师或数据科学家,我们必须谨慎思考模型在现实生活中的影响。机器学习与人工智能赋予了我们巨大的力量,同时也伴随着重大的责任。


案例研究:揭示问题 📊

为了奠定讨论的基础,我们首先来看两个简单的例子。

案例一:约会应用中的推荐算法 💑

假设你想构建一个类似Tinder的约会应用,目标是向用户推荐个人资料。这是一个典型的机器学习问题,类似于Netflix的电影推荐,被称为协同过滤。

公司有明确的目标:提高匹配率和用户参与度。我们拥有大量历史约会数据和用户资料,从机器学习角度看,这似乎是一个定义明确、数据丰富的简单问题。

然而,这类涉及人的机器学习应用会引发深刻的伦理问题。例如,如果仅为了提高匹配率,算法可能会考虑将肤色作为特征,因为向用户展示相同肤色的人可能更容易获得“喜欢”。但作为一个社会,我们认为这不是一个好主意,因为考虑此类特征会损害少数群体的利益,并可能助长歧视。

你可能会认为这个问题很简单:只需不使用这些特征,不提取肤色信息,算法就会公*。但现实情况要复杂得多。

案例二:“公*无意识”的失败 🚚

第二个例子来自2016年彭博社关于亚马逊的一篇文章。亚马逊使用数据驱动技术来决定在美国哪些城市社区提供免费次日送达服务。

结果发现,在波士顿,唯一未被该服务覆盖的社区是罗克斯伯里,这是一个以非裔美国人为主的社区。最终,该市白人居民获得此项服务的可能性是黑人居民的两倍以上。

亚马逊很可能并未将客户种族作为特征。他们只是试图预测各社区的购买数量。购买数量与财富高度相关,而在美国,财富又与种族高度相关。因此,即使最初没有考虑敏感属性,最终模型的结果仍然歧视了某些群体。

这展示了所谓的“公*无意识”的失败:仅仅移除或不包含敏感属性,并希望借此消除歧视问题,是行不通的。如果只是移除所有看似敏感的属性,然后让算法自由运行,仍可能导致糟糕的结果。


什么是歧视?⚖️

在分类课程中,我们学习的是寻找决策边界,将数据点分为正类和负类。这本身就是一种“区分”。

我们今天讨论的歧视,特指不公正的区分依据。这种不公正可能体现在两个方面:

  1. 实际无关性:例如,性取向不应影响雇佣决策。
  2. 道德相关性:例如,尽管雇佣残障人士可能为公司带来额外成本,但社会普遍认为承担此成本具有道德意义。

因此,我们关注的是基于种族、性别、残障状况、性取向等社会类别的、在过去曾遭受不公正系统性不利待遇的区分。这些区分会影响人们生活中重要的机会,如雇佣、大学录取、贷款、司法和医疗等领域。


机器学习流程中的偏见传播 🔄

为了理解人口统计差异如何通过机器学习流程传播,我们考虑一个典型的机器学习系统阶段:个体、世界状态、数据和模型之间的交互。

  1. 测量阶段:将世界状态转化为数据集中的数字。这个过程远非客观科学,涉及大量人为决策,可能引入测量偏差。
  2. 学习阶段:将数据转化为模型。这是我们课程迄今的重点,希望模型能学习数据模式并泛化到新观测。
  3. 行动阶段:使用模型进行预测并采取行动。行动的意义各不相同,但最终都会影响世界状态,有时模型还会从个体获得反馈。

接下来,我们看看人口统计差异如何在这个流程中传播。


数据与社会偏见 📉

首先,许多机器学习应用最终都是关于人的决策。其次,用于训练模型的数据通常已经包含了现存的人口统计差异。

人类社会充满了人口统计差异,训练数据很可能反映这些差异。如果盲目地将算法应用于这些数据,就会固化这些刻板印象。例如,一个自动给论文评分的算法,其训练数据来自人类评分,可能反映了评分者的刻板印象,导致算法也延续这些偏见。

即使是不直接关于人的应用,最终也可能影响人的生活。例如,波士顿的“Street Bump”应用,通过智能手机数据自动检测坑洼。结果发现,投诉多来自富裕社区,导致有限的市政资源被导向富裕社区,影响了不同社区人们的生活质量。


测量阶段的挑战 🎯

测量阶段涉及定义感兴趣的变量、与世界互动并将观察转化为数据。即使定义变量本身也具有挑战性,并且会存在测量偏差。

例如,数码相机的设计涉及许多参数选择。历史上,测试这些参数的人多为浅肤色人群,导致相机的默认设置(如色彩*衡)为浅肤色优化,难以在同一张照片中同时捕捉亮部和暗部细节。这表明,即使是看似客观的测量,也涉及可能引入偏见的人为选择。

定义目标变量同样困难。例如,在雇佣决策中,如何定义“好员工”?使用年度评审作为数据可能会延续评审者的偏见。在司法决策中,预测“谁将犯罪”时,使用逮捕数据作为代理变量也存在严重偏差,因为许多犯罪并未导致逮捕。

因此,从业者必须努力理解数据的来源,以试图解决这些偏差。


从数据到模型:固化与放大 🔍

我们拥有数据集并训练模型。问题是:模型是会反映、放大还是减少训练数据中存在的社会差异?

训练数据中包含两种模式:

  • 知识:我们想要学习的模式(如吸烟与癌症相关)。
  • 刻板印象:我们不想学习的模式(如女孩喜欢粉色,男孩喜欢蓝色)。

机器学习算法无法区分这两者。如果不进行特定干预,算法会同时提取知识和刻板印象。

一个典型的例子是机器翻译中的性别偏见。几年前,将“She is a doctor and he is a nurse”翻译成土耳其语(一种无性别代词的语言)再译回英语,结果变成了“He is a doctor and she is a nurse”。这是因为训练数据中医生更可能是男性,护士更可能是女性,算法在回译时选择了最匹配训练数据统计规律的句子。

你可能会想:为什么不直接移除性别等敏感属性?首先,性别信息可能编码在其他特征中(如“开始编程的年龄”可能与性别相关)。其次,这些特征可能对预测有帮助(如“开始编程的年龄”对评估软件工程师很重要),不能随意移除。

因此,从数据到模型,差异可能被固化。即使训练数据本身没有问题,学习阶段也可能引入人口统计差异。


学习阶段引入的差异 📊

即使你精心收集了考虑公*性的训练数据,在学习阶段如果不加干预,仍可能引入差异。这主要是由于样本量差异

通过任何形式的抽样,少数群体数据通常更少。如果少数群体在总体中本就代表性不足(如科技行业的某些群体),训练数据中他们的代表性会更差。

机器学习在数据量大时效果最好。因此,模型对多数群体的决策可能更好,而对少数群体的效果可能较差。在开发应用时,我们通常使用在整个群体上的*均错误率作为评估标准。一个低的总体错误率(如5%)可能掩盖了在少数群体上很高的错误率。

这种情况在异常检测中可能更严重。例如,谷歌和Facebook曾尝试屏蔽使用不常见姓名的用户,认为这可能是假名。但在某些文化中,名字本就多样。结果导致许多来自少数文化背景的用户被错误屏蔽。这表明,机器学习算法会基于主流文化进行泛化,可能导致对少数群体的高错误率。

大多数机器学习目标函数会创建对多数群体准确的模型,但可能以牺牲受保护群体为代价。即使训练数据良好,如果不加干预,也会如此。


一个雇佣决策的例子 👔

假设我们是一个招聘委员会,基于两个特征决定是否雇佣申请人:大学GPA和面试分数。我们拥有过去申请人的数据,希望预测其未来工作表现(质量)。

训练数据中有两个群体:A组(方形)和B组(三角形)。我们训练一个不考虑群体归属的模型(如线性回归预测*均工作表现),然后根据想雇佣的人数设定一个阈值,选择分数最高的候选人。

观察发现,三角形候选人比方形候选人更可能被选中。这是因为在训练数据中,B组(方形)预测的真实工作表现系统性地低于A组(三角形)。原因可能是公司内部存在偏见,或者B组在教育机会等方面处于劣势。

这导致了雇佣概率的群体差异。如何减少这种差异?有几种非正式方法:

  1. 省略相关特征:例如,省略与人口属性相关的GPA,仅使用面试分数。但这会降低模型准确性。
  2. 使用不同阈值:对不同群体使用不同的录取分数线,以实现相同的成功率。但这可能导致具有相同特征的候选人因群体不同而得到不同决策。
  3. 鼓励多样性:修改模型,降低GPA特征的权重,或增加多样性正则化,以增加入选候选人的多样性。

形式化公*性标准 📐

在课程的最后部分,我们将讨论统计学家和机器学习研究者如何尝试解决这些公*性问题,即如何衡量机器学习应用中的歧视。我们将专注于分类问题。

形式化设置

在分类中,数据由协变量 X 描述,结果变量(标签)Y 取值为0或1。目标是给定新的 X,预测其标签 Y

我们将使用一种特定的公式:首先学习一个评分函数 R(x)(一个实数,例如在0和1之间),然后根据阈值 t 做出二元决策:如果 R > t,则预测为1;否则预测为0。

我们假设已经获得了一个评分 R,并关注如何使用这个评分进行预测和决策。此外,我们在总体层面讨论问题,不涉及泛化。

分类标准回顾

在课程中,我们主要关注分类错误率(误判概率)。但这可能遗漏许多重要方面。其他形式分类标准可以突出分类器的不同方面。

考虑混淆矩阵:

  • 真阴性 (TN):Y=0,预测为0。
  • 假阳性 (FP):Y=0,预测为1。
  • 假阴性 (FN):Y=1,预测为0。
  • 真阳性 (TP):Y=1,预测为1。

由此可以定义:

  • 真阳性率 (TPR):P(D=1 | Y=1)
  • 假阳性率 (FPR):P(D=1 | Y=0)
  • 真阴性率 (TNR):P(D=0 | Y=0)
  • 假阴性率 (FNR):P(D=0 | Y=1)

在机器学习中,我们通常只考虑两种错误的成本,但并未区分假阳性和假阴性。阈值 t 的选择深刻影响这些分类标准。例如,如果假阳性的成本很高,则应选择较高的阈值;如果假阴性的成本很高,则应选择较低的阈值。

纳入敏感属性

在许多任务中,特征 X 可能编码了个体的敏感属性(如性别、种族、残障状况)。我们假设有一个额外的变量 A 来编码受保护群体的成员身份。

重申:仅仅从 X 中移除敏感属性并不能解决问题,因为许多特征与敏感属性相关,可用于恢复该属性。例如,在美国,访问Pinterest网站的可能性与性别相关。因此,仅靠“无意识”无法实现公*。


三大公*性标准 ⚖️

我们将定义三个基本的公*性标准,它们都基于均衡涉及群体成员身份的统计量的思想。

1. 独立性 (Independence)

定义:要求敏感属性 A 与评分 R 独立,即 A ⟂ R

含义:这意味着所有群体具有相同的“接受率”。例如,如果一个群体有80%的接受机会,其他群体也应有相同的接受率。

局限性:满足独立性标准仍可能包含不公*的做法。例如,公司可以在A群体中精心招聘,在B群体中随机招聘,同时满足相同的总体接受率。这将导致B群体中不合格的申请人更可能被选中,长期来看会加剧不*等。独立性未能区分假阳性和真阳性。

实现独立性的方法包括预处理(调整分类器使其与 A 不相关)、处理中(在优化中添加约束)和后处理(调整特征使其与 A 不相关)。

2. 分离性 (Separation)

定义:要求敏感属性 A 与评分 R 在给定真实标签 Y 的条件下独立,即 A ⟂ R | Y

含义:这意味着所有群体具有相同的假阳性率和假阴性率。它均衡了错误率,使得无法用假阳性交换真阳性,看起来更公*。

挑战:在决策时,我们并不知道真实标签 Y(例如,未被雇佣者的表现)。这是一个事后标准,但可以在拥有结果数据后进行评估。也可以通过后处理将现有评分转换为满足分离性的评分。

3. 充分性 (Sufficiency)

定义:要求敏感属性 A 与真实标签 Y 在给定评分 R 的条件下独立,即 A ⟂ Y | R

含义:这意味着在已知评分 R 的情况下,不需要知道敏感属性 A 来预测 Y。对于任何群体,给定评分 R 后,正结果的概率相同。

与校准的关系:充分性与“按组校准”密切相关。校准意味着 P(Y=1 | R=r) = r。按组校准要求每个群体内部都满足校准,这直接意味着充分性。校准提供了概率解释的保证(但这是群体层面的*均保证,而非个体层面)。

重要发现:群体校准(充分性)通常是机器学习默认满足的性质。研究表明,机器学习做得越好(越接*贝叶斯最优分类器),就越满足群体校准。这意味着,标准的机器学习无需特别干预就能达到充分性。

局限性:即使满足充分性,决策在道德上仍可能有问题。例如,预测员工未来工作年限的最优模型,可能会给可能怀孕或有残障的人较低的分数,尽管这在道德上值得商榷。


标准间的互斥性与结论 🤔

我们介绍了三种公*性标准:独立性(均衡接受率)、分离性(均衡错误率)和充分性(群体校准)。它们各有局限性。

一个关键问题是:能否同时满足这些标准?除了某些退化情况,这些标准在一般情况下是互斥的。例如,不可能同时满足独立性和分离性,也不可能同时满足充分性和独立性。

因此,公*性标准本身存在根本性限制。它们不能排除所有不公*的做法,满足某个标准并不意味着操作就是公*的。要真正实现公*,可能需要超越 X, Y, R, A 的联合分布信息,进行因果推理。


总结与核心要点 🎯

本节课我们一起学习了机器学习中的伦理与公*。核心要点如下:

  1. 机器学习非天生公*:算法决策可能延续或放大社会中的现有偏见与不公。
  2. 偏见贯穿全流程:从数据测量、模型学习到决策行动,每个环节都可能引入或传播人口统计差异。
  3. “公*无意识”无效:简单地移除敏感属性无法保证公*,因为偏见可能编码在其他特征中。
  4. 形式化公*标准:我们学习了独立性、分离性和充分性三大标准,它们分别对应不同的统计均衡目标,但各有局限且通常互斥。
  5. 没有银弹:不存在一个普适、完美的数学标准能定义和保证所有场景下的公*。公*性是领域特定、情境依赖的。
  6. 责任在于实践者:作为机器学习从业者,我们必须意识到黑箱模型没有与社会价值观保持一致的保证。在设计和使用模型时,必须积极思考其伦理影响,努力将人类价值融入技术实践。

机器学习赋予我们强大的工具,但用之有道,方能为社会创造真正的价值。

29:无监督学习与聚类 🧠

概述

在本节课中,我们将要学习无监督学习的基本概念、主要方法及其应用。与之前学习的监督学习不同,无监督学习不依赖于人工标注的标签,而是直接从数据本身的结构中学习。我们将重点探讨表示学习和生成模型,并详细介绍一个经典的无监督学习算法——K均值聚类。


无监督学习简介

上一节我们介绍了监督学习,其核心是系统在每次预测后都能获得一个真实的答案(标签)。然而,这并非人类学习的主要方式。人类的大部分学习是通过观察世界,而非总是被告知正确答案。例如,观看视频时,没有人会为每一帧标注“这是鸟”或“这是桌子”,我们必须自己理解内容。

那么,机器学习是否也能在没有标签的情况下进行学习呢?这就是无监督学习。它通常更为困难,方法也多种多样,但其潜力巨大,因为它允许我们利用比人工标注多得多的数据。

核心定义:在无监督学习中,我们只有观测数据 X,而没有对应的输出标签 y

无监督学习主要有两个重要目标:

  1. 学习表示:学习数据中有意义的特征。这些特征可能比原始数据(如图像的原始像素)更能捕捉数据的本质和逻辑,对未来可能进行的监督学习或其他任务更有用。
  2. 生成数据:训练一个系统,使其能够从一些随机噪声中生成看起来像真实数据的新数据点。这被称为生成模型。一个相关的任务是密度估计,即理解真实数据在概率空间中的分布形态。

表示学习示例

以下是几种表示学习的应用场景:

推荐系统与词向量

推荐系统的目标是在用户和物品(如电影)之间建立联系。我们可以学习一个用户矩阵和一个物品矩阵,使得用户特征向量与物品特征向量的内积能够预测用户对该物品的评分(如星级)。

数学形式预测评分 ≈ 用户特征向量 · 物品特征向量

有趣的是,完全相同的数学模型可以用于学习文本中单词的表示(即词向量,如Word2Vec)。我们学习每个单词的特征向量,使得两个单词向量的内积能够解释它们在文本中共同出现的频率。这个过程完全是无监督的,因为我们只是利用了文本中自然存在的共现信息,无需任何人工标注。

主成分分析

主成分分析是一种降维技术,用于将高维数据投影到低维空间,同时保留数据中最重要的变化方向。

应用示例

  • 瑞士投票模式:将每个城镇的数百次投票结果(一个高维向量)通过PCA降维到两个主要特征,可以在无需理解每次投票内容的情况下,清晰地观察到德语区、法语区和意大利语区之间的系统性差异。
  • 基因组数据:对大量个体的基因组序列进行PCA分析,可以在不使用任何地理信息的情况下,发现数据中与地理起源相关的模式。

这些例子表明,PCA能够帮助我们在没有标签的情况下,从高维数据中发现并可视化其内在结构。


深度表示学习技术

随着深度学习的发展,出现了一些更强大的无监督表示学习方法。

自编码器

自编码器的目标是学习数据的压缩表示(编码),并能从该表示中重建原始数据(解码)。

网络结构

输入图像 -> [编码器网络] -> 低维特征向量 -> [解码器网络] -> 重建图像

训练信号(损失函数):最小化原始输入图像与重建图像之间的差异(如均方误差)。虽然看似只是在学习重建数据,但关键在于中间的“瓶颈”层迫使网络学习数据中最关键的特征,因为这些特征是重建所必需的。

对比学习

对比学习只使用编码器网络来学习特征表示,而不进行数据重建。

核心思想:在特征空间中,让相似的样本彼此靠*,不相似的样本彼此远离。

如何定义“相似”

  • 正样本:通过已知的数据变换(如对图像进行裁剪、旋转)生成,这些变换后的图像应与原图语义相似。
  • 负样本:随机选择的其他数据点,它们几乎肯定与原图语义不同。

训练目标:最小化正样本对在特征空间中的距离,同时最大化负样本对的距离。

这种方法的好处在于,一旦通过无监督方式学习到好的特征,我们只需要很少的标注数据,在这些特征之上训练一个简单的分类器(如线性分类器),就能达到接*最先进的性能。


生成模型

生成模型的目标是学习生成与真实数据相似的新数据。

生成对抗网络

GAN是一个巧妙的想法,它通过两个神经网络相互博弈的方式进行训练:

  1. 生成器:接收随机噪声,尝试生成逼真的假数据。
  2. 判别器:接收真实数据和生成器产生的假数据,尝试区分它们是真还是假。

训练过程:这是一个对抗游戏。生成器努力生成以假乱真的数据来“欺骗”判别器;判别器则努力提高其鉴别能力。两者通过梯度下降同时进行优化。最终,生成器能够生成非常逼真的图像、文本等。


K均值聚类算法 🎯

现在,让我们转向一个更具体、更具数学性的无监督学习任务——聚类。聚类旨在将数据点分组,使得同一组内的点彼此相似,不同组间的点彼此不同。我们将重点介绍最常用的聚类算法之一:K均值聚类。

问题定义

假设我们有 N 个数据点,希望将它们分成 K 个组。K均值聚类的目标是:

  • 为每个簇 k 找到一个代表点,称为质心 μ_k
  • 为每个数据点 n 分配一个簇标签 z_n

我们使用独热编码来表示分配:z_n 是一个 K 维向量,在其所属簇的位置上为1,其余为0。

目标函数

K均值通过优化以下目标函数来寻找好的聚类:

最小化L(μ, Z) = Σ_n Σ_k z_nk * ||x_n - μ_k||²

约束条件:对于每个数据点 nΣ_k z_nk = 1z_nk ∈ {0, 1}

这个目标函数的直观解释是:最小化每个数据点到其所属簇质心的距离*方和。

K均值算法

虽然上述优化问题是NP难的,但我们可以使用一个简单而有效的迭代算法来找到不错的解:

  1. 初始化:随机选择 K 个点作为初始质心 μ_k
  2. 迭代直至收敛
    • 分配步骤:将每个数据点 x_n 分配给距离它最*的质心所属的簇。
      • z_nk = 1 如果 k = argmin_j ||x_n - μ_j||²,否则为0。
    • 更新步骤:重新计算每个簇的质心,将其更新为该簇所有数据点的*均值。
      • μ_k = (Σ_n z_nk * x_n) / (Σ_n z_nk)

算法特性

  • 每次迭代都会降低目标函数 L 的值。
  • 当分配不再发生变化时,算法收敛。
  • 该算法可以看作是在变量 Z(离散)和 μ(连续)上的坐标下降法。

如何选择K值?

选择簇的数量 K 是一个挑战。目标函数值 L 随着 K 增大而单调递减(当 K = N 时,L 可降至0),但这并不意味着更大的 K 更好(每个点自成一类没有意义)。

一种常用的启发式方法是寻找“拐点”:绘制 LK 变化的曲线,选择曲线斜率发生显著变化(变*缓)的点作为 K。最终,K 的选择通常需要结合具体应用场景。

应用示例:图像压缩(颜色量化)

K均值可以用于图像压缩。我们将图像中的每个像素视为一个三维数据点(RGB值)。对这些像素点进行K均值聚类,用 K 个颜色(簇质心)来代表整张图像的所有像素。每个像素只需存储其所属簇的索引,而不是完整的RGB值,从而实现了压缩。


K均值的概率解释

为什么使用距离*方和作为目标函数?这可以从概率角度得到解释。

假设数据由以下生成过程产生:

  1. 每个簇 k 对应一个球形高斯分布,其均值为 μ_k,方差固定。
  2. 每个数据点 x_n 根据其分配 z_n,从对应的高斯分布中采样。

那么,给定参数 μZ,观察到整个数据集的似然函数为各数据点概率的乘积。对该似然函数取负对数,并忽略常数项后,得到的目标函数恰好就是K均值的目标函数。

因此,最大化数据似然等价于最小化K均值目标函数。这为K均值算法提供了一个坚实的概率论基础。


总结

本节课中我们一起学习了无监督学习的核心思想与方法。我们了解到,无监督学习不依赖标签,旨在从数据本身发现结构,主要分为表示学习和生成模型两大类。我们探讨了PCA、自编码器、对比学习等表示学习技术,以及GAN等生成模型。最后,我们深入研究了K均值聚类算法,包括其目标函数、迭代优化过程、应用场景以及背后的概率解释。无监督学习使我们能够利用海量未标注数据,是机器学习领域一个非常重要且活跃的方向。

30:对抗性训练入门教程 🛡️

在本节课中,我们将学习对抗性训练的基本概念,并完成两个实践任务:在MNIST数据集上实现对抗性训练,以及探讨线性模型的对抗性训练理论。

概述

本周的练习主要围绕对抗性训练及其鲁棒性展开。练习分为两个部分:第一部分是实践任务,需要在MNIST数据集上实现逻辑回归和卷积神经网络的对抗性训练;第二部分是理论任务,探讨线性模型的对抗性训练闭式解。

练习材料可在课程代码库中找到。对于实践部分,由于MNIST数据集相对较大,建议使用Google Colab的免费GPU服务。

实践部分:MNIST对抗性训练

上一节我们介绍了课程的整体安排,本节中我们来看看实践部分的具体内容。

任务一:实现逻辑回归模型

首先,你需要实现一个简单的逻辑回归模型。大部分代码已经提供,你只需在指定位置填写几行代码。由于我们完全依赖PyTorch,无需手动实现反向传播或梯度计算,可以利用其自动求导功能。

以下是训练脚本中需要填写的关键部分:

# 定义逻辑回归模型
class LogisticRegression(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(input_dim, output_dim)

    def forward(self, x):
        return self.linear(x)

任务二:实现卷积神经网络

接下来,你需要实现一个简单的卷积神经网络。同样,大部分代码已经提供,你只需定义网络架构。

以下是卷积神经网络架构的定义示例:

# 定义卷积神经网络
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
        self.fc1 = nn.Linear(64 * 7 * 7, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2)
        x = x.view(x.size(0), -1)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

任务三:实现快速梯度符号攻击

在实现模型后,我们将学习如何生成对抗样本。这里使用快速梯度符号攻击方法,其核心公式如下:

公式
x_adv = x + ε * sign(∇_x L(θ, x, y))

其中,x是原始输入,ε是扰动预算,L是损失函数,∇_x表示对输入的梯度。

以下是FGSM攻击的实现步骤:

  1. 计算输入x的梯度。
  2. 根据梯度符号生成扰动。
  3. 将扰动添加到原始输入中,生成对抗样本。

任务四:可视化对抗样本

生成对抗样本后,你需要可视化这些样本,并观察扰动是否对人类视觉产生影响。同时,绘制模型在不同扰动预算下的鲁棒性曲线。

以下是需要完成的可视化任务:

  • 绘制逻辑回归和卷积神经网络在不同扰动预算下的鲁棒性曲线。
  • 展示生成的对抗样本,并分析其视觉变化。

任务五:对抗性训练

最后,我们将实现对抗性训练,使模型对FGSM攻击具有鲁棒性。对抗性训练的核心思想是在训练过程中生成对抗样本,并将其加入训练集。

以下是对抗性训练的关键步骤:

  1. 在每次训练迭代中,使用FGSM生成对抗样本。
  2. 将对抗样本和原始样本一起用于模型训练。
  3. 重复上述过程,直到模型收敛。

理论部分:线性模型的对抗性训练

上一节我们完成了实践任务,本节中我们来看看理论部分的内容。

任务一:闭式解推导

对于线性模型,我们需要推导对抗性训练中内部最大化问题的闭式解。假设损失函数L是基于间隔的单调递减函数,例如逻辑损失或合页损失。

以下是闭式解的推导步骤:

  1. 定义线性模型的损失函数。
  2. 求解内部最大化问题,得到对抗样本的闭式表达式。
  3. 分析解的形式及其与模型参数的关系。

任务二:与软间隔SVM的比较

接下来,我们将探讨对抗性训练与软间隔SVM之间的异同。以下是需要分析的关键点:

  • 目标函数的差异。
  • 对异常值的处理方式。
  • 鲁棒性与泛化能力的权衡。

任务三:L2与L∞对抗性训练的关系

最后,我们将分析L2和L∞对抗性训练之间的关系。特别是,L∞对抗性训练的内部优化问题如何与快速梯度符号方法相似。

以下是需要讨论的内容:

  • L∞对抗性训练的内部优化问题形式。
  • 与FGSM方法的相似之处。
  • 两种方法在实践中的应用场景。

总结

在本节课中,我们一起学习了对抗性训练的基本概念和实践方法。通过实现逻辑回归和卷积神经网络的对抗性训练,我们深入理解了FGSM攻击的原理及其防御方法。在理论部分,我们探讨了线性模型对抗性训练的闭式解,并比较了其与软间隔SVM的异同。

希望这些内容能帮助你更好地理解对抗性训练及其在机器学习中的应用。如果有任何问题,欢迎在课程论坛或Discord上提问。

31:高斯混合模型 (GMM) 与期望最大化 (EM) 算法概述 🧮

在本节课中,我们将学习高斯混合模型。这是一种更通用的聚类方法,允许簇的形状是椭圆或其他形态,而不仅仅是球形。我们将从概率模型的角度理解它,并学习如何通过期望最大化算法来估计其参数。

从 K-Means 到高斯混合模型

上一节我们介绍了 K-Means 聚类,它假设每个簇是球形的。本节中,我们将看看如何推广这个模型。

在 K-Means 中,每个簇的分布是一个协方差矩阵为单位矩阵 I 的正态分布,即球形高斯分布。现在,我们将其推广为具有更通用协方差矩阵 Σ 的正态分布,从而允许簇呈现椭圆形。

数学上,这意味着数据点 x 的生成过程变为一个混合了 K 个高斯分布的模型,每个分布有其自己的均值 μ_k 和协方差 Σ_k

概率模型与隐变量

与 K-Means 的“硬分配”(每个点确定性地属于一个簇)不同,高斯混合模型引入了“软分配”。每个数据点 x_n 都有一个对应的隐变量 z_n,它是一个随机变量,表示该点属于各个簇的概率。

以下是该模型的核心组成部分:

  • 混合权重 π_k:表示一个数据点先验地属于第 k 个簇的概率,满足 ∑_{k=1}^K π_k = 1
  • 簇参数:每个簇 k 有其均值 μ_k 和协方差 Σ_k
  • 数据生成过程
    1. 首先,根据混合权重 π 随机选择簇标签 z_n
    2. 然后,根据所选簇的高斯分布生成数据点 x_nx_n | z_n=k ~ N(μ_k, Σ_k)

因此,模型的参数总共有三类:μ (K×D个), Σ (K×D²个), 和 π (K个)。这些参数的数量不依赖于数据点数量 N,这使得模型更易于处理。

边际似然函数

我们的目标是找到能最好解释观测数据 X 的参数 θ = {π, μ, Σ}。然而,隐变量 z 是未被观测到的。为了处理这个问题,我们通过对 z 的所有可能取值求和(即“边际化”)来消除它,从而得到仅关于观测数据 X边际似然函数

对于单个数据点 x_n,其概率是各高斯成分的加权和:
p(x_n | θ) = ∑_{k=1}^K π_k * N(x_n | μ_k, Σ_k)

对于整个数据集 X(假设数据点独立同分布),其对数边际似然函数为:
L(θ) = log p(X | θ) = ∑_{n=1}^N log [ ∑_{k=1}^K π_k * N(x_n | μ_k, Σ_k) ]

我们的优化目标是最大化这个对数边际似然函数 L(θ)

优化面临的挑战

直接最大化 L(θ) 非常困难,主要原因有三点:

  1. 非凸问题:目标函数 L(θ) 是非凸的,存在许多局部最优解。
  2. 不可识别性:如果交换两个簇的标签(即同时交换 π_k, μ_k, Σ_k),似然函数值不变。因此存在至少 K! 个等价的全局最优解。
  3. 无界性:理论上,似然值可以趋于无穷大。当一个簇的协方差矩阵 Σ_k 收缩到只包含一个数据点时,该点对应的概率密度会变得极高,导致对数似然值爆炸。这在实际中意味着需要正则化或小心初始化。

期望最大化 (EM) 算法框架

为了解决这个复杂的优化问题,我们引入期望最大化算法。其核心思想是迭代地构建并优化一个目标函数的替代函数(下界)

具体步骤如下:

  1. 初始化:从参数的一个初始猜测 θ^{0} 开始。
  2. 迭代直至收敛
    • E步 (期望步):在给定当前参数 θ^{t} 和观测数据 X 的条件下,计算隐变量 z 的后验分布 p(z | X, θ^{t})。这相当于为每个数据点计算它属于各个簇的“责任”(一个概率值)。
    • M步 (最大化步):将 E 步计算出的“责任”视为固定权重,最大化一个完整的对数似然函数(此时隐变量已知),从而更新参数得到 θ^{t+1}。这个完整的对数似然函数就是原边际似然的一个替代下界。

从几何角度看,在每次迭代的当前点 θ^{t},我们构造一个替代函数 Q(θ | θ^{t}),它满足两个条件:

  • 它是原目标函数 L(θ) 的一个下界:L(θ) ≥ Q(θ | θ^{t})
  • 它们在当前点相等:L(θ^{t}) = Q(θ^{t} | θ^{t})

然后,我们通过最大化这个更简单的替代函数 Q(θ | θ^{t}) 来得到下一个参数估计 θ^{t+1}。由于下界性质,这保证了原目标函数 L(θ) 不会下降(通常会上升)。

总结

本节课中,我们一起学习了高斯混合模型的基本原理。我们从 K-Means 出发,引入了更灵活的簇形状和软分配概念,建立了完整的概率生成模型。我们认识到直接优化其边际似然函数非常困难,并因此引入了期望最大化算法的基本框架。EM 算法通过交替执行 E 步和 M 步,迭代地优化一个替代下界,为我们提供了一种强大的工具来拟合高斯混合模型等含有隐变量的复杂概率模型。在接下来的课程中,我们将深入 EM 算法的具体推导和细节。

32:期望最大化算法详解 🧠

在本节课中,我们将深入学习期望最大化算法。上周我们讨论了高斯混合模型,在此之前还介绍了K均值聚类,它是高斯混合模型的一个简化版本。我们引入高斯混合模型是为了建立一个更强大的概率模型,它能提供软分配,并且能匹配更复杂的数据形状。这些都是重要的无监督学习方法。本节课,我们将深入探讨用于解决这类模型拟合问题的核心算法——期望最大化算法。

概述 📋

期望最大化算法是一种迭代优化算法,用于在概率模型含有无法观测的隐变量时,寻找模型参数的最大似然估计。我们将从构建一个易于优化的替代函数开始,然后逐步最大化它,从而逼*最优解。

构建替代函数(E步)

上一节我们介绍了高斯混合模型的参数优化问题,本节中我们来看看如何构建一个易于处理的替代函数。

我们的目标是最大化数据的对数似然函数 ( L(\theta) ),但由于模型复杂,直接优化很困难。因此,我们采用迭代方法,从一个初始参数 (\theta^{(t)}) 开始,构建一个在该点处与原函数相等且始终是原函数下界的替代函数 ( \bar{L}(\theta; \theta^{(t)}) )。

利用凸性构建下界

核心技巧是利用对数函数的凹性(或负对数函数的凸性)。对于任意凸函数 (f) 和一组权重 (q_k)(满足 (\sum_k q_k = 1)),詹森不等式成立:
[
f\left( \sum_k q_k r_k \right) \le \sum_k q_k f(r_k)
]
对于凹函数(如对数函数),不等式方向相反。我们利用这个性质来构造下界。

具体到我们的模型,对于单个数据点 (x_n),其对数似然为:
[
L_n(\theta) = \log \left( \sum_{k=1}^{K} \pi_k \mathcal{N}(x_n | \mu_k, \Sigma_k) \right)
]
我们引入辅助变量 (q_{kn}),并构造替代函数:
[
\bar{L}n(\theta; \theta^{(t)}) = \sum^{K} q_{kn}^{(t)} \log \left( \frac{\pi_k \mathcal{N}(x_n | \mu_k, \Sigma_k)}{q_{kn}^{(t)}} \right)
]
其中,权重 (q_{kn}^{(t)}) 定义为在当前参数 (\theta^{(t)}) 下,数据点 (n) 属于聚类 (k) 的后验概率:
[
q_{kn}^{(t)} = p(z_n = k | x_n, \theta^{(t)}) = \frac{\pi_k^{(t)} \mathcal{N}(x_n | \mu_k^{(t)}, \Sigma_k{(t)})}{\sum_{j=1} \pi_j^{(t)} \mathcal{N}(x_n | \mu_j^{(t)}, \Sigma_j^{(t)})}
]

这个选择保证了两个关键性质:

  1. 下界性质:对于所有 (\theta),有 (\bar{L}_n(\theta; \theta^{(t)}) \le L_n(\theta))。
  2. 相等性质:在当前点 (\theta = \theta^{(t)}) 处,有 (\bar{L}_n(\theta^{(t)}; \theta^{(t)}) = L_n(\theta^{(t)}))。

因此,(\bar{L}_n) 是一个在 (\theta^{(t)}) 处与原函数相切的下界,是理想的替代函数。

最大化替代函数(M步)

构建好替代函数后,下一步就是最大化它以得到新的参数估计 (\theta^{(t+1)})。我们需要优化所有参数:混合权重 (\pi_k)、均值 (\mu_k) 和协方差矩阵 (\Sigma_k)。

总体的替代函数是所有数据点替代函数的和:
[
\bar{L}(\theta; \theta^{(t)}) = \sum_{n=1}^{N} \bar{L}_n(\theta; \theta^{(t)})
]
最大化这个函数比直接最大化原始似然函数要简单得多,因为对数内部的求和被“线性化”了。

以下是最大化步骤:

1. 更新均值 (\mu_k)

对 (\bar{L}) 关于 (\mu_k) 求导并令其为零,得到更新公式:
[
\mu_k^{(t+1)} = \frac{\sum_{n=1}^{N} q_{kn}^{(t)} x_n}{\sum_{n=1}^{N} q_{kn}^{(t)}}
]
新的均值是数据点的加权*均,权重正是E步计算出的后验概率 (q_{kn}^{(t)})。

2. 更新协方差 (\Sigma_k)

对 (\bar{L}) 关于 (\Sigma_k^{-1}) 求导并令其为零,得到更新公式:
[
\Sigma_k^{(t+1)} = \frac{\sum_{n=1}^{N} q_{kn}^{(t)} (x_n - \mu_k^{(t+1)})(x_n - \mu_k{(t+1)})T}{\sum_{n=1}^{N} q_{kn}^{(t)}}
]
新的协方差矩阵是加权的外积矩阵,权重同样是 (q_{kn}^{(t)})。

3. 更新混合权重 (\pi_k)

在约束条件 (\sum_{k=1}^K \pi_k = 1) 下最大化 (\bar{L})。使用拉格朗日乘子法,得到更新公式:
[
\pi_k^{(t+1)} = \frac{1}{N} \sum_{n=1}^{N} q_{kn}^{(t)}
]
新的混合权重是数据点属于聚类 (k) 的*均后验概率。

EM算法与K均值的关系 🔗

现在我们已经理解了EM算法的两个步骤,让我们看看它如何与之前学过的K均值算法联系起来。

当高斯混合模型满足以下两个条件时,EM算法退化为K均值算法:

  1. 所有聚类的协方差矩阵都是球形的,即 (\Sigma_k = \sigma^2 I),其中 (\sigma^2) 是一个标量。
  2. 方差 (\sigma^2) 趋*于零 ((\sigma^2 \to 0))。

在这种情况下:

  • E步:后验概率 (q_{kn}) 会变得非常“硬”。对于每个数据点 (x_n),只有距离最*的聚类中心 (k) 对应的 (q_{kn}) 趋*于1,其余趋*于0。这等价于K均值中的硬分配 (z_{kn})。
  • M步:均值 (\mu_k) 的更新公式变为仅对分配给该聚类的点求*均,这正是K均值的中心更新步骤。混合权重 (\pi_k) 则变为分配给各聚类的数据点比例。

因此,K均值可以看作是EM算法在高斯混合模型方差无限小且各向同性这一特例下的极限形式。

EM算法的直观演示与泛化 🎯

算法演示

EM算法的迭代过程可以直观展示:

  1. E步(期望步):基于当前参数计算每个数据点属于各个聚类的“软”概率 (q_{kn})。在图中,这表现为数据点的颜色是聚类颜色的混合(例如,紫色点表示对两个聚类的归属概率相*)。
  2. M步(最大化步):根据计算出的 (q_{kn}) 更新模型参数(均值、协方差、权重)。在图中,这表现为聚类椭圆(形状由协方差决定)的位置和形状发生改变。
  3. 重复上述步骤直至收敛。最终,算法能够找到拟合数据形状的椭圆聚类。

算法的泛化观点

EM算法不仅适用于高斯混合模型,它是一个处理含有隐变量 (z) 的概率模型的通用框架。
给定观测数据 (x) 和模型参数 (\theta),我们希望最大化边际似然 (p(x | \theta)),但其中涉及对隐变量 (z) 的求和或积分,导致计算困难。

EM算法的通用形式如下:

  • E步:计算在给定当前参数 (\theta^{(t)}) 和观测数据 (x) 下,隐变量 (z) 的后验分布 (p(z | x, \theta^{(t)}))。然后,构建替代函数(Q函数):
    [
    Q(\theta; \theta^{(t)}) = \mathbb{E}_{z \sim p(z | x, \theta^{(t)})} \left[ \log p(x, z | \theta) \right]
    ]
    这可以理解为:由于我们不知道确切的 (z),就用它的后验期望来代替。
  • M步:最大化这个Q函数,得到新的参数估计:
    [
    \theta^{(t+1)} = \arg\max_{\theta} Q(\theta; \theta^{(t)})
    ]

在高斯混合模型中,隐变量 (z) 就是数据点的聚类标签,E步计算的后验概率 (q_{kn}) 正是 (p(z_n=k | x_n, \theta^{(t)}))。因此,我们之前推导的具体步骤是这一通用框架的一个完美实例。

总结 📝

本节课中我们一起学习了期望最大化算法的核心思想与具体步骤。

  • 动机:为了解决含有隐变量的复杂概率模型(如高斯混合模型)的参数估计问题。
  • 核心思想:通过迭代构建并最大化一个替代函数(下界)来逼*原目标函数的最优解。
  • 两个步骤
    1. E步(期望步):基于当前参数,计算隐变量的后验分布(对于GMM,是计算软分配概率 (q_{kn})),并构建替代函数 (Q)。
    2. M步(最大化步):最大化 (Q) 函数,更新模型参数(对于GMM,更新 (\mu_k, \Sigma_k, \pi_k))。
  • 与K均值的关系:K均值是EM算法应用于球形协方差且方差趋于零的高斯混合模型时的特例,此时软分配退化为硬分配。
  • 泛化性:EM算法是一个强大的通用框架,适用于任何具有隐变量和可分解联合分布的概率模型。

通过EM算法,我们能够以概率化的方式对数据进行软聚类,并捕捉更复杂的数据结构(如椭圆形状的聚类),这比K均值等硬聚类方法更为灵活和强大。

33:习题集11入门指南 🚀

在本教程中,我们将学习如何完成 EPFL 机器学习课程(CS-433)的习题集11。我们将涵盖梯度与海森矩阵的计算、概率模型的参数估计,以及 K-Means 算法的实现与应用。


1. 计算梯度与海森矩阵 📈

在第一个问题中,你需要确定函数 F 关于变量 X 的梯度和海森矩阵。

建议将 F 写成 X 中每个元素的函数,并以此方式推导出答案。


2. 概率模型与参数估计 🔍

上一节我们介绍了函数梯度的计算,本节中我们来看看如何对数据建立概率模型并估计其参数。

2.1 联合概率分布

在第二题的第一部分,你需要写出数据的联合概率分布。

由于数据是独立同分布的,你可以将联合分布写成每个概率分布的乘积,从而得到一个更简洁的答案形式。

公式
P(X₁, X₂, ..., Xₙ) = ∏ P(Xᵢ)

2.2 最大似然估计

在第二部分,你需要找出使数据似然度最大化的超参数 μσ

由于对数函数是单调递增的,你也可以最大化数据的对数似然度。

2.3 估计量评估

在第三和第四部分,你需要将经验估计值与真实参数值进行比较,以判断你的估计量是否有偏。

请记住,你的经验估计依赖于所有随机变量。


3. K-Means 算法实现 💻

在习题的实现部分,你首先需要实现 K-Means 算法,然后将其应用于二维相位数据和三维图像的 RGB 值。

以下是实现 K-Means 算法的核心步骤:

代码

# 伪代码示例
1. 初始化聚类中心(可从数据中采样或随机生成)。
2. 将每个数据点分配到最*的聚类中心。
3. 重新计算每个聚类的中心点。
4. 重复步骤2和3,直到收敛。

首先,通过从数据中采样一些点或根据数据范围生成随机点来初始化你的聚类中心。

然后,尝试不同的 k 值,看看哪个能给出更好的成本函数值。

但请记住,k 值最大并不代表对数据的拟合最好。你可以查阅贝叶斯信息准则来了解更多关于为数据选择模型复杂度的信息。


4. 图像压缩应用 🖼️

在习题的最后一部分,你需要使用刚刚开发的 K-Means 算法来压缩图像。

首先,将你的图像转换为三维 RGB 值的向量,然后应用 K-Means 算法。

请记住,如果你的成本函数不再改善,可以提前终止算法。


总结 📝

本节课中我们一起学习了:

  1. 如何计算函数的梯度与海森矩阵。
  2. 如何为独立同分布数据建立联合概率模型,并使用最大似然法估计其参数。
  3. 如何实现 K-Means 聚类算法,并将其应用于二维数据和三维图像 RGB 值。
  4. 如何利用 K-Means 算法进行图像压缩,并理解提前终止的条件。

希望你能享受这次习题练习。

34:生成对抗网络 (GANs) 入门 🎭

在本节课中,我们将要学习生成对抗网络。这是一种通过让两个神经网络相互对抗来学习生成数据的方法。


概述

上一节我们介绍了期望最大化算法。本节中,我们来看看生成对抗网络。这是一种学习生成模型或生成数据的方法。

生成模型与我们熟悉的标准监督模型有很大不同。在监督学习中,我们有带标签的数据来解决分类问题。但生成模型不同,我们没有标签,只有一堆给定的数据点 X。我们的目标是学习一个“黑盒”,它能生成与这些真实数据点相似的数据。换句话说,我们想学习一个模型,它能生成尽可能多的、看起来像真实数据的“假”数据。

我们之前在讨论高斯混合模型时已经接触过生成模型的思想。今天,我们将更进一步。这里的核心思想是,它不仅仅学习一个模型,而是同时学习两个模型。这两个模型相互作用,目标相互竞争,就像一场游戏。


生成对抗网络 (GANs) 的设定

我们将这种学习形式化为一个双人游戏。游戏的两位参与者是:

  • 生成器:一个具有参数 θ 的神经网络。它的任务是生成假数据(例如图像,但可以是任何数据模态)。
  • 判别器:一个具有参数 φ 的神经网络。它以图像作为输入,输出一个决策(是/否),判断输入是真实图像还是生成器生成的假图像。

接下来,我们需要定义如何学习这些参数,即优化问题是什么。


优化问题:极小极大博弈

对于判别器,我们最小化判别器损失函数 L。关键在于,这个损失函数依赖于双方。它取决于生成器参数 θ 和判别器参数 φ。这个损失值就像游戏中的收益:如果为负,对一方有利;如果为正,对另一方有利。

判别器作为最小化玩家,希望最小化 L。生成器可能有不同的目标,例如最大化 L。在最简单的设定中,一个玩家的损失函数是另一个玩家损失函数的负值,这被称为零和博弈:一方的收益是另一方的损失。

因此,如果损失函数对双方相同(或符号相反),我们就有一个零和博弈。那么,生成器(黄色玩家)希望最小化 L,而判别器(红色玩家)希望最大化 L(即最小化 -L)。这就形成了一个极小极大问题

其数学形式为:

min_θ max_φ L(θ, φ)

其中,θ 是生成器参数(最小化玩家),φ 是判别器参数(最大化玩家)。

这种零和博弈的公式化是处理游戏的一种通用方式。使用神经网络的好处在于它们是可微分的。如果生成器和判别器都是神经网络,并且损失函数定义在它们之上,那么这个损失函数很可能也是可微的。我们称之为可微分博弈。这使得我们更有可能优化这类游戏,即找到让双方都满意的解(一种均衡状态)。


生成模型与极大似然估计

生成模型的目标是生成数据点,使得人工数据的分布与真实数据的分布相似。我们用 P_data(x) 表示真实数据的分布(我们不知道它),用 P_model(x; θ) 表示模型生成的分布。我们希望找到一个参数 θ*,使得 P_model 尽可能接* P_data

通常,我们通过极大似然估计来训练生成模型。即,最大化给定模型参数下数据的似然:

θ* = argmax_θ P_model(X; θ)

其中 X 是整个数据集。这是学习此类密度的一个通用原则。

生成模型的一个关键区别在于,有些模型假设我们知道真实的密度函数形式(显式密度模型),而有些则不需要(隐式密度模型)。GANs 属于后者,它只需要能够从模型和真实数据中采样数据点即可进行训练。


可微分博弈与纳什均衡

到目前为止,我们学习的都是单玩家优化问题,即最小化一个关于单一参数 θ 的损失函数。其优化“地形”可能是一个复杂的曲面,我们寻找最小值点。

在双玩家博弈中,情况有所不同。现在有两个具有对立目标的玩家。判别器(红色坐标)试图最大化损失值,生成器(绿色坐标)试图最小化损失值。优化地形可能看起来像一个鞍点:一个玩家想尽可能走高,另一个想尽可能走低。我们希望找到一个点,双方都无法再改进,这被称为纳什均衡

对于可微分博弈,我们可以给出一个更便利的最优条件。如果满足以下条件,则点 (θ*, φ*) 是一个微分纳什均衡

  1. 梯度为零∇_θ L(θ*, φ*) = 0∇_φ L(θ*, φ*) = 0。这是一个驻点。
  2. 局部最优性:对于最小化玩家(生成器),关于 θ 的 Hessian 矩阵是正定的(曲面向上弯曲)。对于最大化玩家(判别器),关于 φ 的 Hessian 矩阵是负定的(曲面向下弯曲)。

这意味着在该点附*,任何微小的偏离都会使各自的损失变差。虽然对于大型神经网络计算 Hessian 矩阵不现实,但这个条件在数学上清晰地定义了均衡点。

为了优化此类博弈,我们将使用标准算法——梯度下降。生成器将对 θ 执行梯度步以最小化损失,判别器将对 φ 执行梯度步以最大化损失。两者交替进行。


GANs 的目标函数

现在,我们为生成数据的具体任务定义损失函数。以下是基本设定:

  • 生成器 G:接收一个随机噪声向量 z(例如,从均匀分布或高斯分布 P_z(z) 中采样),并输出一个数据点 G(z)(例如一张图像)。其目标是生成看起来真实的数据。
  • 判别器 D:接收一个数据点 x(可以是真实的 x ~ P_data(x),也可以是生成的 G(z)),并输出一个标量 D(x),表示 x 是真实数据的概率(理想情况下,真实数据输出 1,生成数据输出 0)。

判别器的任务类似于一个标准的二分类器(监督学习)。生成器的任务是“欺骗”判别器。

目标函数公式

一个经典且简单的 GAN 目标函数如下,它类似于逻辑回归的损失:

对于判别器 D,它试图最大化:

max_φ [ E_(x~P_data) [log D(x)] + E_(z~P_z) [log(1 - D(G(z)))] ]
  • 第一项鼓励判别器对真实数据 x 给出高概率(接* 1)。
  • 第二项鼓励判别器对生成数据 G(z) 给出低概率(接* 0)。

对于生成器 G,它试图最小化判别器将其数据识别为假的能力,即最小化 log(1 - D(G(z)))。一个常用的*似是转而最大化 log(D(G(z))),这能提供更强的早期梯度。因此,生成器的目标可写为:

min_θ [ E_(z~P_z) [log(1 - D(G(z)))] ]  或*似为   max_θ [ E_(z~P_z) [log(D(G(z)))] ]

综合起来,GAN 的优化问题是一个极小极大博弈:

min_θ max_φ V(D, G) = E_(x~P_data) [log D(x)] + E_(z~P_z) [log(1 - D(G(z)))]

其中,D 的参数是 φG 的参数是 θ


理论分析:最优解与分布匹配

为什么选择这个特定的损失函数?原因在于,在这个极小极大博弈的均衡点,有一个非常好的性质:生成器学到的分布 P_G 将等于真实数据分布 P_data

为了分析这一点,我们需要一个衡量两个概率分布相似度的工具。

  • KL 散度:衡量一个分布 P 相对于参考分布 Q 的差异,不对称。
    KL(P || Q) = ∫ P(x) log(P(x) / Q(x)) dx = E_(x~P) [log(P(x) / Q(x))]
    
  • JS 散度:基于 KL 散度的对称版本。
    JS(P || Q) = (1/2) KL(P || M) + (1/2) KL(Q || M),其中 M = (P+Q)/2
    

证明概要

  1. 给定生成器 G,最优判别器 D*:
    对于固定的生成器 G(即固定的分布 P_G),我们可以推导出最优判别器 D* 为:

    D*(x) = P_data(x) / [P_data(x) + P_G(x)]
    

    直观上,判别器对样本 x 给出的最优概率,是 x 来自真实分布的概率与来自总分布(真实+生成)的概率之比。

  2. 将 D 代入目标函数*:
    将最优判别器 D* 代回极小极大目标函数 V(D, G) 中,经过推导,生成器的优化问题转化为:

    min_θ [ 2 * JS(P_data || P_G) - log(4) ]
    

    由于 log(4) 是常数,这等价于最小化 P_dataP_G 之间的 JS 散度。

  1. 均衡状态
    P_G = P_data 时,JS 散度达到最小值 0,此时 D*(x) = 1/2(判别器完全无法区分)。这正是我们期望的均衡状态:生成器完美复制了真实数据分布,判别器则只能随机猜测。

这个理论结果表明,在这个特定博弈的均衡点,生成器确实学会了匹配真实数据分布。


GANs 的挑战与改进

虽然经典 GAN 在理论上有很好的性质,但其使用的 JS 散度在实践中存在一个问题:当两个分布没有重叠或支撑集不相交时,JS 散度是常数(log2),导致梯度消失。例如,如果真实数据和生成数据是离散的且没有重叠,JS 散度无法提供有意义的梯度来指导生成器改进。

因此,研究人员提出了使用其他分布距离的 GAN 变体。

  • Wasserstein 距离(推土机距离):直观上,它衡量将一个分布 P 的“土堆”搬动成另一个分布 Q 的“土堆”所需的最小“工作量”。即使两个分布没有重叠,该距离也是定义良好且可微的(在适当条件下)。
  • Wasserstein GAN:使用 Wasserstein 距离作为损失函数的 GAN 变体,通常能提供更稳定的训练和更有意义的梯度信号。

训练算法与实践

训练 GAN 的算法非常直观,就是交替进行梯度下降:

以下是训练步骤:

  1. 从真实数据分布 P_data 中采样一个小批量真实数据 {x}
  2. 从先验噪声分布 P_z(如高斯分布)中采样一个小批量噪声 {z}
  3. 使用噪声 {z} 通过当前生成器 G 生成假数据 {G(z)}
  4. 更新判别器 D:计算判别器损失关于其参数 φ 的梯度,并执行一步梯度上升(因为判别器要最大化目标)。
    φ <- φ + η * ∇_φ [ (1/m) Σ log D(x) + (1/m) Σ log(1 - D(G(z))) ]
    
  5. 更新生成器 G:计算生成器损失(如 -log(D(G(z))))关于其参数 θ 的梯度,并执行一步梯度下降(因为生成器要最小化目标)。
    θ <- θ - η * ∇_θ [ (1/m) Σ log(D(G(z))) ]
    
  6. 重复步骤 1-5。

在实践中,通常使用卷积神经网络作为生成器和判别器的架构。生成器将低维噪声 z 上采样为完整图像,判别器将图像下采样为一个标量概率值。

此外,还有条件 GAN,它可以生成符合特定条件(如类别标签、文本描述)的数据,方法是将条件信息同时输入给生成器和判别器。


总结

本节课中,我们一起学习了生成对抗网络的核心思想。我们了解到:

  1. GAN 通过一个生成器和一个判别器之间的极小极大博弈来学习数据分布。
  2. 其优化目标可以形式化为 min_θ max_φ V(D, G)
  3. 在理论均衡点,生成器学到的分布能完美匹配真实数据分布,这通过最小化 JS 散度等分布距离来实现。
  4. 经典 GAN 可能面临梯度消失问题,而改进版本如 Wasserstein GAN 能提供更稳定的训练。
  5. 训练过程是交替梯度下降,交替更新判别器和生成器的参数。
  6. GAN 是一种强大的生成模型,可用于图像、音频等多种数据的生成和增强。

通过将博弈论思想与神经网络的可微分优化相结合,GANs 为生成式人工智能开辟了一条独特的道路。

35:主成分分析(PCA)基础与应用 🧠

在本节课中,我们将要学习主成分分析(PCA)的基本原理及其在无监督学习中的应用。我们将从线性代数的角度理解PCA,并探讨它如何用于数据降维、特征提取以及数据可视化。


概述:为什么需要PCA?

PCA是无监督学习章节的一部分。它的价值不仅在于其线性代数的技术层面,更在于它提供了一种无监督的方式来总结数据或将数据投影到更易于管理的空间中。这对于处理大型数据集和进行探索性数据分析非常有帮助,这也是PCA至今仍被广泛使用的原因。


动机:降维与信息保留

一方面,PCA的动机是用于降维。当我们拥有大量特征时,原始特征空间可能维度非常高。每个数据点有D个特征,我们希望将这些点映射到一个维度更小的空间(K维),并且希望K通常远小于原始维度D。

当然,你可以随意进行降维。但关键在于,能否以一种有意义的方式进行?能否在降维的同时保留原始特征中的大部分信息?这就是问题的核心。否则,你可以简单地将所有点映射到同一个点上,但这并不是降维的目的。我们的目标是,在保留每个数据点大部分信息的同时进行降维。我们将在后续更精确地定义“大部分信息”的含义。


数据矩阵与低秩*似

我们通常将数据组织成矩阵形式。数据矩阵通常是D行N列,其中每一列代表一个数据点 ( x_i )。

我们的目标是*似这个矩阵。更具体地说,我们希望将其分解为一个低秩矩阵。你可以将其视为一种矩阵分解,将原始矩阵分解为两个维度更小的矩阵的乘积。

直观上,我们希望将原始数据矩阵 ( X )(D x N)变换为 ( \hat{X} )(D x N),其中 ( \hat{X} ) 的秩为K(K远小于D和N)。这可以通过因子分解 ( X \approx RC ) 来实现,其中 ( R ) 是D x K矩阵,( C ) 是K x N矩阵。这样,每个原始数据点(D维)现在只用K个特征来表示。


奇异值分解(SVD)回顾

我们通过奇异值分解(SVD)来实现上述目标。任何矩形矩阵 ( X )(D x N)都可以精确地分解为以下形式:
[
X = U S V^T
]
其中:

  • ( U ) 是D x D的正交矩阵(左奇异向量)。
  • ( S ) 是D x N的矩阵,只有主对角线上的元素(奇异值)非零,且通常按从大到小排序:( s_1 \ge s_2 \ge ... \ge s_{\min(D,N)} \ge 0 )。
  • ( V^T ) 是N x N的正交矩阵(右奇异向量的转置)。

正交矩阵意味着其列向量是单位正交的(内积为0或1)。对于实数矩阵,正交性等同于 ( U^T U = I ) 和 ( V^T V = I )。正交变换(如旋转)的一个重要性质是它保持向量的长度(范数)不变。


从SVD到最佳低秩*似

现在,我们来看看SVD如何与降维联系起来。我们的目标是找到一个线性映射(压缩矩阵 ( C ))将数据 ( X ) 投影到低维空间,以及一个重建矩阵 ( R ) 将其映射回来,使得重建误差最小。

具体来说,我们希望找到矩阵 ( C )(K x D)和 ( R )(D x K),使得在只保留K个中间特征的情况下,重建后的矩阵 ( R(CX) ) 尽可能接*原始矩阵 ( X )。我们使用Frobenius范数(矩阵所有元素*方和的*方根)来衡量误差:
[
| X - R(CX) |_F^2
]

关键结论(Eckart-Young定理)指出:对于给定的秩K,通过截断SVD得到的最佳K秩*似矩阵 ( \hat{X}_K ) 是所有秩为K的矩阵中,对 ( X ) *似误差最小的

这个最佳*似可以通过以下方式获得:

  1. 取SVD分解 ( X = U S V^T )。
  2. 只保留前K个最大的奇异值,将其他奇异值置零,得到矩阵 ( S_K )。
  3. 最佳K秩*似为:( \hat{X}_K = U_K S_K V_K^T ),其中 ( U_K ) 是 ( U ) 的前K列,( V_K^T ) 是 ( V^T ) 的前K行。

在这种情况下,压缩矩阵 ( C ) 就是 ( U_K^T ),重建矩阵 ( R ) 就是 ( U_K )。压缩后的数据点为 ( z = U_K^T x )(K维),重建后的数据点为 ( \hat{x} = U_K z )(D维)。

重建误差恰好等于被丢弃的奇异值的*方和:
[
| X - \hat{X}_K |F^2 = \sum^{\min(D,N)} s_i^2
]
由于奇异值按降序排列,这意味着我们保留了数据中“能量”或“信息”最大的部分。K越大,重建误差越小;当K等于矩阵的秩时,重建是完美的。


PCA在真实数据上的应用:人脸图像示例

为了理解PCA的实际效果,我们来看一个人脸图像数据集。每张图像是50x50像素,因此原始特征维度D=2500。这是一个很高的维度。

我们应用PCA,选择K=10进行降维。这意味着:

  • 压缩:每张原始图像(2500维向量)被投影到由前10个主成分(( U_K ) 的列)张成的空间,得到一个仅包含10个特征的压缩向量 ( z )。
  • 重建:通过 ( \hat{x} = U_K z ),我们可以将压缩后的10维向量重建回2500维的图像空间。

结果显示,重建后的图像虽然不完美,但人物的基本轮廓和特征仍然可辨。这非常令人惊讶,因为我们仅用10个数字就捕捉到了一张复杂图像的大部分关键信息。这10个方向(主成分)是通过分析整个数据集找到的“最佳”线性投影方向,能够最大程度地保留数据中的信息。

这些主成分方向(( U_K ) 的列)本身也是2500维的向量,可以可视化为图像,被称为“特征脸”。它们代表了数据集中变化最大的方向。


PCA用于数据探索与可视化

PCA不仅可用于压缩单个数据点,更强大的功能在于探索整个数据集的结构。我们可以将所有数据点投影到前两个主成分上(即K=2),从而在二维*面上可视化高维数据。

在这个二维散点图中,每个点代表一个原始图像。我们可能会观察到数据点形成了一些簇。例如,在特定的人脸数据集中,属于同一个人的不同照片(不同角度或光照)在PCA投影后倾向于聚集在一起。尽管PCA本身并不知道这些标签(无监督),但它揭示了数据中内在的聚类结构。

这有助于我们:

  • 发现模式:识别相似的数据组。
  • 检测异常值:寻找远离群体的点。
  • 理解数据分布:获得对高维数据集的直观认识。

选择K=2或3是为了可视化和解释的便利。对于不同的目标(如压缩),可以选择不同的K。


矩阵分解视角与去相关

从矩阵分解的角度看,PCA的截断SVD ( \hat{X}_K = U_K S_K V_K^T ) 可以重写为两个矩阵的乘积:( \hat{X}_K = W Z ),其中 ( W = U_K )(D x K),( Z = S_K V_K^T )(K x N)。这是一种高效的、参数化的数据表示方式,因为只需要存储K(D+N)个参数,而不是原始的DN个参数。这类似于神经网络中的瓶颈层。

PCA还有一个重要的统计解释:它能够对特征进行去相关

首先,计算数据矩阵 ( X )(假设每个特征已中心化,即均值为0)的协方差矩阵:
[
\Sigma_X = \frac{1}{N} X X^T
]
将 ( X = U S V^T ) 代入,利用 ( U ) 的正交性,可得:
[
\Sigma_X = \frac{1}{N} U S^2 U^T
]
这表明原始特征的协方差矩阵通常不是对角的,意味着特征之间存在相关性。

现在,考虑压缩后的数据 ( Z = U_K^T X )(K x N)。其协方差矩阵为:
[
\Sigma_Z = \frac{1}{N} Z Z^T = \frac{1}{N} (U_K^T X)(X^T U_K) = U_K^T \Sigma_X U_K = \frac{1}{N} S_K^2
]
这是一个对角矩阵!这意味着,经过PCA变换后得到的新特征(主成分)彼此之间是不相关的

此外,对角线上的元素就是前K个奇异值的*方(除以N),并且是降序排列。这意味着:

  • 第一主成分具有最大的方差,解释了数据中最大比例的变化。
  • 后续主成分的方差依次递减。
  • 拥有不相关的特征对于许多机器学习模型是有利的,可以避免多重共线性等问题,并提高模型的可解释性。

计算技巧

在实际计算PCA/SVD时,有一个高效的技巧。我们需要计算的是数据矩阵 ( X )(D x N)的奇异向量 ( U )。直接对 ( X ) 进行SVD可能计算量较大。

注意到协方差矩阵 ( \Sigma_X = \frac{1}{N} X X^T ) 的特征值分解与 ( X ) 的SVD有直接关系:( \Sigma_X ) 的特征向量就是 ( X ) 的左奇异向量 ( U ),而 ( \Sigma_X ) 的特征值是 ( X ) 的奇异值的*方除以N。

因此,我们可以:

  1. 计算较小的那个方阵:如果 D < N,计算 D x D 的矩阵 ( X X^T ) 的特征值和特征向量。如果 N < D,则计算 N x N 的矩阵 ( X^T X ) 的特征值和特征向量(其特征向量是 ( V ))。
  2. 通过特征值分解得到奇异向量和奇异值。

这通常比直接计算大型矩形矩阵的完整SVD更高效。


总结

本节课中我们一起学习了主成分分析(PCA)的核心内容:

  1. 动机与目标:PCA是一种无监督的降维技术,旨在将高维数据投影到低维空间,同时尽可能保留原始数据的信息(方差)。
  2. 数学基础:通过奇异值分解(SVD)实现。数据矩阵 ( X ) 被分解为 ( U S V^T )。
  3. 最佳*似:截断SVD(保留前K个最大的奇异值及对应的奇异向量)提供了原始矩阵在秩K约束下的最佳*似。重建误差等于被丢弃的奇异值的*方和。
  4. 操作步骤:压缩通过 ( z = U_K^T x ) 实现,重建通过 ( \hat{x} = U_K z ) 实现。
  5. 实际应用:PCA能有效压缩数据(如人脸图像),并可通过将数据投影到前两个主成分上进行可视化,帮助发现数据中的聚类结构和模式。
  6. 统计特性:PCA变换后的新特征(主成分)是彼此不相关的,且第一个主成分具有最大的方差。
  7. 计算:可通过计算协方差矩阵 ( X X^T ) 或 ( X^T X ) 的特征值分解来高效求解PCA。

PCA因其概念清晰、实现简单且效果显著,仍然是探索性数据分析和预处理中不可或缺的工具。

36:奇异值分解入门 🚀

在本节课中,我们将学习如何高效计算奇异值分解,并探讨对称矩阵情况下的特殊性质。课程包含两个理论练习,内容较为轻松,旨在为项目工作留出时间。

概述 📋

本周我们有两个理论练习。第一个练习讨论如何高效计算奇异值分解,特别是当特征维度远大于数据点数量时。第二个练习探讨对称矩阵的奇异值分解特性。

练习一:高效计算奇异值分解 ⚙️

上一节我们介绍了课程安排,本节中我们来看看第一个练习的具体内容。

当数据矩阵 X 的维度为 D × ND 为特征维度,N 为数据点数量),且 D 远小于 N 时,我们可以通过计算 X Xᵀ 的特征值分解来高效获得奇异值分解,因为 X Xᵀ 的维度仅为 D × D

然而,在某些情况下,特征数量可能远多于数据点数量(即 D 远大于 N)。第一个练习要求你找到一种解决方案,使得计算奇异值分解时不需要处理 D × D 的大矩阵,而是使用一个更小的矩阵。

以下是解决思路的关键点:

  • 核心在于利用矩阵 Xᵀ X,其维度为 N × N
  • N 远小于 D 时,计算 Xᵀ X 的特征值分解比直接计算 X Xᵀ 更高效。
  • 通过 Xᵀ X 的特征向量可以构造出原始奇异值分解中的右奇异矩阵 V,并间接得到左奇异矩阵 U

练习二:对称矩阵的奇异值分解 🔄

在了解了高效计算的一般方法后,本节我们来看看一种特殊矩阵——对称矩阵的奇异值分解有何独特之处。

任何矩阵 X 都有奇异值分解 X = U S Vᵀ,其中 UV 通常是不同的矩阵。本练习要求证明:如果矩阵 X 是对称矩阵(因此也是方阵),那么 UV 是相同的。

此外,练习的第二部分要求证明:如果 X 同时也是半正定矩阵,那么奇异值矩阵 S 对角线上的所有元素都是正数。

以下是一个解题提示:

  • 可以从对称矩阵的性质入手,即满足 X = Xᵀ
  • 将这一性质代入奇异值分解的标准形式 X = U S Vᵀ 中,并与 Xᵀ = V S Uᵀ 进行比较。
  • 结合正交矩阵的性质进行分析。

总结 🎯

本节课中我们一起学习了奇异值分解的两个重要理论练习。我们探讨了在特征维度与样本数量关系不同时,如何选择高效的计算路径。我们也分析了对称矩阵在奇异值分解中表现出的特殊性质,即其左右奇异矩阵相同。理解这些概念有助于在实际应用中更灵活、更高效地使用奇异值分解这一强大工具。

祝你好运,我们将在下周讨论练习的解答。

37:矩阵分解与推荐系统 🎬

在本节课中,我们将要学习矩阵分解(Matrix Factorization)这一核心概念,并探讨其在推荐系统(Recommender Systems)中的具体应用。我们将从矩阵分解的一般形式出发,理解其如何将复杂问题转化为寻找两个较小矩阵的优化问题,并学习如何通过梯度下降等方法高效地求解。


矩阵分解概述

在之前的课程中,我们已经见过几个矩阵分解的例子。

例如,K-Means 聚类算法可以看作是矩阵分解的一个特例。我们曾看到,K-Means 的目标可以被表述为寻找两个矩阵,使得它们最小化某个函数。这是一个典型的优化问题,属于矩阵分解的范畴。

同样,主成分分析(PCA)也是矩阵分解的另一个例子。在上周课程的最后,我们了解到 PCA 也可以被视作一种矩阵分解。

今天,我们希望从更一般的视角来看待矩阵分解,并讨论其在推荐系统中的应用,这可能是矩阵分解最著名的案例。本周四的课程将讨论文本表示学习,即如何为文本学习嵌入向量。


推荐系统动机 🎯

今天的动机来自于推荐系统。你可能已经听说过它,这是一个非常自然的场景。

例如,假设我们有 D 部电影和 N 个用户。我们希望研究用户的偏好,了解他们是否喜欢某些电影(也可以是商品或其他物品)。我们试图利用的数据是用户已经给出的一些偏好数据。

矩阵中的一个条目 X_dn 表示第 n 个用户给第 d 部电影打了 4 星。例如,在位置 (2, 3) 的评分是 4。这构成了一个用户-电影-评分的三元组。

有趣的是,大部分数据实际上是缺失的(未观测到的)。图中所有灰色区域都是未知的。在我们的问题中,有大量的未知数据。任务正是预测这些未知数据。这就是我们今天要做的事情。

我们将看到,最自然的方法之一就是通过矩阵分解来实现。

希望这个设定是清晰的。再次强调,大部分灰色条目是真正未知的,我们想要预测它们。也许 99% 以上的条目都是未观测到的。我们的目标是训练一个模型来填补这些缺失值,进行预测。

有很多方法可以做到这一点。例如,最简单的基线方法是取用户对该电影的*均评分,然后填充那些条目。当然,还有许多其他基线方法。

需要明确的是,这些缺失值不是零,而是我们对其值一无所知。

实际上,有一些不错的数据集,例如项目二中使用的数据集,它与 Netflix Prize 数据集相关。大约十年前,这是一个非常流行的竞赛,数千名参与者尝试了各种技巧来尽可能准确地填充这些数据,并尝试了所有可能的工程方法。这是第一个著名的数据科学竞赛。

在那个案例中,大约有 20,000 部电影和 50 万用户。这个矩阵的绝大部分是未观测到的。此外,这个矩阵作为稠密矩阵存储会非常大,因此我们希望将其作为稀疏矩阵存储,只存储已知的条目,而对未知条目不做任何处理。


模型与损失函数

我们已经解释了所拥有的数据。条目 X_dn 表示用户 n 对电影 d 的评分,可能是 1 到 5 星。

我们能对此做什么呢?让我们尝试构建一个损失函数,以便训练一个模型,同时也构建模型本身。

我们将尝试使用两个小矩阵,并利用它们的乘积作为我们的模型。即尝试找到矩阵 WZ,它们比较“小”(指列数较少)。例如,可能只有 k 列(一个很小的数字,比如 20 或 30)。这里 W 的维度是 D x kZ 的维度是 N x kN 是 50 万,D 是 2 万,都是非常大的维度,但内部维度 k 非常小)。

当我们相乘两个矩阵时,为了得到条目 X_dn 的*似值,我们取 W 的第 d 行与 Z^T 的第 n 列(即 Z 的第 n 行)的内积。我们希望这个内积能大致*似用户的评分。

因此,我们的模型是:预测值 = W 的第 d 行 与 Z 的第 n 行 的内积。这很容易评估,因为它们只是 k 维向量,非常小,做预测非常高效。

如果我们有一个未知的电影-用户对(即我们从未见过这两个组合在一起),这就是我们进行预测的方式:只需将这两个向量的对应行相乘。

我们有了模型,接下来还需要一个损失函数。这由你选择。我们将为整个矩阵的每个条目定义一个损失,然后对所有条目求和。但训练损失只针对观测到的条目。

损失函数将我们的模型预测值与真实值(标签或 1 到 5 星的评分)进行比较。最简单的做法是使用*方损失,但你也可以使用绝对损失等。最*的一些工作尝试使用绝对损失,因为它更鲁棒。

这里要记住的一般原则是:当我们说矩阵分解时,正如我们所说,指的是我们最小化某个函数。损失函数依赖于两个矩阵,但这里的性质是,我们的损失函数实际上只依赖于这两个矩阵的乘积 W Z^T

任何形式为 F(W Z^T) 的函数,当我们通过最小化 WZ 来训练时,我们称之为矩阵分解。在这里,F 的作用是:它接受这些预测条目,并将它们与真实评分进行比较,并且只对观测到的 (n, d) 对求和。

现在我们有了损失函数和模型。接下来只需运行梯度下降,这基本上就是全部内容。我们将更详细地讨论如何高效地实现。

请确保你理解了模型和损失函数的结构:

  • 模型就是 W Z^T
  • Ω 是观测到的条目集合。

损失函数看起来相当简单,只是*方损失,乘积也很简单。看起来不错。

现在,你可能会问,这是一个容易解决的问题吗?它复杂吗?也许你们中有些人已经有预感了。


模型特性与挑战

问题一:非凸性

第一个问题是,这个优化问题不是凸的。我们已经多次见过类似的非凸函数。

一个简单的例子是,如果矩阵小到只是一个数字(1x1 矩阵),那么函数 F(W, Z) = W * Z(我们损失函数的简化版)的图像是怎样的?函数 W * Z 的图像是一个鞍形曲面,这证明它是一个非凸函数。

当然,我们实际的损失函数是 (真实评分 - W*Z)^2。即使加上*方,它仍然是非凸的。例如,函数 (3 - x*y)^2 的图像虽然看起来顶部弯曲,似乎有点像凸函数,但如果你取两个点并画一条线,会发现函数值在线段中间可能高于端点,这违反了凸函数的定义。

因此,这仍然是一个非凸函数。但它是一个不错的函数,类似于凸函数。最*的一些研究甚至表明,像这样的矩阵分解问题没有严格的局部最小值。例如,这个函数是星形凸的,意味着从最优点到任何其他点的连线上,函数表现良好。

从任何局部最小值都可以连接到全局最小值(可能有很多全局最小值,但它们都是连通的)。如果你找到了其中一个,那就没问题了。

这是一个非常有趣的问题类别。对于如此简单的函数,它具有相当丰富的结构,目前仍然是开放的研究课题。

不过,非凸性并不会太吓到我们,因为我们无论如何都会应用基于梯度的方法来交替优化 WZ

问题二:可识别性

第二个方面是可识别性。解不是唯一的,意味着存在多个最优解。

为什么?如果我给你一个最优解 WZ,你能给出另一个不同的矩阵对仍然是最优的吗?当然可以。例如,你可以将 W 乘以一个标量 β,同时将 Z 乘以 1/β,乘积不变,所以这也是最优解。或者,如果维度相同,可以交换它们的位置。甚至同时改变两者的符号。

因此,存在许多最优解。这很有趣,但不一定是个大问题,但意识到这一点是好的。


矩阵分解的一般概念

我们在这里所做的相当重要,因为它不仅适用于推荐系统,而且更通用。我们将其应用于任何形式为 F(W Z^T) 的结构。任何关于矩阵乘积的函数都可以。

因此,我们在这里讨论的内容也可以用于 K-Means、PCA 或周四将要学习的词嵌入等应用。有很多应用场景。

但对于推荐系统,问题又来了:如何选择 k?同样,不幸的是,我没有完美的答案。这很棘手,取决于具体情况。

这又是一个权衡。如果你将 k 设置得非常大,那么很容易过拟合。如果 k 大于 ND,那么你可以简单地将 W 设为单位矩阵,将 Z 设为 X,这样乘积完全等于 X,训练误差为零。但这可能没有意义,因为你很容易得到零训练误差,意味着对所有观测条目都有完美预测,但这并不总是有用的。

关键不仅在于拟合观测到的条目,还在于拥有一个能够预测未知条目的模型。为此,你可能需要一个单独的测试集来检查泛化能力。

因此,我们通常面临这种权衡:训练误差和泛化能力。我们是否在测试集上表现良好?我们是否在训练集上过拟合?

如果 k 太大,我们会过拟合。如果 k 太小,我们会欠拟合。

这里有一个 k=2 的例子。这展示了电影矩阵 W。每一行是一个电影向量(因为 k=2,所以是二维的)。图中显示了这些电影向量的位置。在训练之后,你可以看到所有电影的位置。这会是一个有趣的电影嵌入吗?

实际上,它效果很好。相似的电影被分组在一起。它们具有相似的特征。同样,这些特征不是手工制作的,而是学习得到的特征。这很好。

右边的图显示了稍微不同的分解(可能使用了 PCA)。他们学习了具有*方损失的分解,然后获得了这些电影的嵌入。你可以看到,许多有点相似的电影确实被分组在一起。

有趣的是,这个方法对电影一无所知。它只知道你给了多少颗星。这里没有使用任何附加信息。没有关于用户的附加信息,也没有关于电影的附加信息。系统仅直接从给出的星级中学习。

那么,如何选择 k?有点像在 K-Means 中。我们需要做出折衷。实际上,这里更简单:我们可以说最好的 k 是能给你最佳测试误差的那个。如果你有一个单独的测试集,那么你可以用它来选择 k,或者甚至用一个单独的验证集来寻找 k。一旦你获得了最佳的预测质量,就使用那个 k


正则化与优化

我们讨论了一点欠拟合和过拟合。小的 k 会导致欠拟合。另一个情况很清楚,如果过拟合,你可以减小 k。或者,如果你不想减小 k,那么你可以做另一件事:使用正则化。

如果我们再次看这个损失函数,我们添加了正则化项。通常是 Frobenius 范数(即各元素*方和)。我们希望这些矩阵的范数不要太大。然后,我们还需要讨论这个权衡参数,需要选择它对我们有多重要。如果你正则化,这是另一个限制模型复杂度、防止过拟合的机会。

你只需将损失函数修改为原始损失加上正则化项的和。


优化方法:随机梯度下降

接下来我们应该讨论一下如何优化它。像往常一样,将是随机梯度下降。这很标准,没什么大惊喜。但也许很有趣的是它的计算成本,因为这些矩阵非常巨大(可能是百万乘以百万)。因此,算法的每一步最好比处理整个矩阵更便宜。这是我们希望实现的目标。

让我们看看在使用 SGD 时是否如此。为了运行 SGD,我们总是需要某种结构化的目标函数。是的,我们有。

你甚至可以除以观测条目数来归一化,以表明你的目标函数是*均值,但这只是形式上的。在训练中,你可以选择是否归一化,因为解是相同的。

为了运行随机梯度下降,我们均匀地采样一个观测到的条目(随机采样)。然后我们有一个用户 n 和电影 d。现在我们需要计算那个小部分的梯度。我们需要计算关于整个参数 WZ 的梯度。

W 的梯度是一个大小为 D x k 的矩阵,Z 的梯度是 N x k。让我们看看是否能计算它们。这并不难,你需要使用链式法则等。我们将计算这个内积的梯度。

这听起来有点吓人,因为我们说过希望有非常廉价、不依赖于整个矩阵的操作。休息之后,我们将看到计算这一个条目的梯度需要什么信息,计算复杂度如何。我们会看到情况并不坏,然后我将展示公式。


梯度计算详解

回到我们学习这两个矩阵的方法。我们将其表述为一个优化问题:我们想最小化某个损失,找到最好的电影矩阵 W 和用户矩阵 Z。我们想找到最好的特征,并完全从头开始学习它们,不使用任何附加信息。这是优化方法。

但还有另一种方法:在左图中,这些特征是硬编码的。例如,如果主角是男性或女性,你就放入 1 或 -1。这是一种你也可以使用的方法,利用关于用户或电影的专家信息。但真正酷的是学习它们,这就是我们在这里所做的。我们还看到,学习方法具有更好的泛化能力,因为如果你只是手工制作一些东西,你总会忘记一些不直接、不完全明显的维度或方面。

因此,左边的方法不是机器学习,右边的方法是机器学习方法。当我们将其定义为优化问题并使用基于梯度的工具求解时,这就是我们的下一个任务:讨论有哪些算法可用来找到最好的 WZ

这相当直接。唯一不*凡的事情是实际计算这个梯度,计算和函数中某一部分关于用户矩阵或电影矩阵的梯度。

首先,我想计算关于电影矩阵 W 的梯度,然后再展示关于用户矩阵 Z 的梯度。

对于 W,我们只有一个函数(我们观测到了一个评分)。对于这个函数,我们想计算 F_dn 的梯度。现在 dn 是固定的(一个特定的用户-电影对)。但你要问的是整个 W 的梯度。即使 F_dn 只是一个条目,关于 W 的整个梯度仍然是一个矩阵。

所以我们需要询问 W 的所有条目。我需要给它们起一些名字。W 是一个 D x k 矩阵。我可以询问第 d' 行第 k 列的条目(d 已经被使用了,所以我引入 d' 来命名 W 的条目)。

对于一个参数 W_{d'k},我的损失函数在这个参数上变化有多快?这就是我们要计算的。

损失函数是一个数字。梯度是关于 d'k 的。对于这一个样本观测的绿色损失函数。

需要小心:绿色的 d 是固定的,黄色的 d' 是变量,我们询问所有可能的值。

结果已经在这里了。现在我们需要看看。我们询问 W 的第 d' 行第 k 列的条目,你可以想象它在矩阵中的某个位置。行是 d'。我们问,这一行如何影响这个损失?答案是,它根本不影响,除非你碰巧问到的行正是我们选择的 d

任何其他 W 的行对 (d, n) 的预测都没有影响。只有电影 d 的那一行有影响。如果 d' 等于 d,那么就有梯度。然后很容易看出梯度是什么:这一行与 Z 的某一行相乘,然后取*方。计算它的梯度并不难。

对于我们的目的,Z 是固定的。发生的情况只是 W 的这一行与 Z 的那一行相乘。这个的梯度实际上是 Z 的第 n 行第 k 列的条目(Z_{nk})。然后,因为外面有*方,*方的导数会消去 1/2,剩下预测误差(真实值减去预测值)。所以梯度是 (真实值 - 预测值) * Z_{nk}

这计算起来非常廉价。例如,X 是星数(离散值 1, 2, 3, 4, 5)。模型预测是电影行与用户行的内积,这计算成本很低,因为只涉及特定的 dn。我只需取用户行乘以电影行,这花费 k 次操作。然后我乘以这个数字。这看起来是一个非常廉价的操作。

这只是矩阵的一个条目。其他所有条目都是零(如果你问的是错误的行)。如果我们对所有条目都这样做,我们基本上就完成了计算。这个梯度实际上只有一行是非零的(第 d 行)。这个梯度矩阵非常稀疏,我们甚至不需要存储整个东西,只需要存储那一行。

计算它的成本是:我需要计算预测,这需要 k 次操作(两个 k 维向量的内积)。然后对于每个 k,用户向量有一个不同的条目,需要与 (真实值 - 预测值) 相乘。所以成本大约是 k 次乘法和 k 次加法,非常廉价,是 O(k) 的复杂度。

DN 可能非常巨大(百万级),但 k 很小(在 Netflix Prize 中,最佳结果大约是 k=30)。与 50 万用户相比,这是一个非常小的数字。因此,你可以以非常低的成本计算一个随机梯度。有了梯度,我们就可以执行一步更新。

对于用户矩阵 Z 的梯度,故事完全相同。同样,它只对应用户 n 的那一行是非零的。其他所有用户对 n 的预测没有贡献,因此它们不会出现在梯度中,我们也不需要存储。

用户矩阵 W 是电影矩阵或项目矩阵。当然,这不仅限于电影。推荐系统可用于任何应用,例如广告投放。你也可以使用这种方法为每个用户学习一个特征向量,为每个广告学习一个特征向量。有时也会与附加信息结合,但这里没有使用关于用户或电影的信息,只是学习了分解。

如果你想使用附加信息,那也很有趣。你可以将已有的关于用户的硬编码信息连接起来。然后,你可以学习与这些硬编码信息一起工作的附加部分。同样,你也可以添加关于电影的硬编码信息。这是一种结合现有关于用户或电影的附加信息与学习特征的好方法。

我们很高兴可以使用随机梯度下降,每一步的成本非常低。我们必须运行很多步。你只需遍历你的数据集。在实践中,人们通常取整个观测训练集的一个随机排列,然后遍历它,就像在分类器或回归中使用 SGD 一样。遍历所有训练样本一次称为一个周期。然后你可以继续,直到你对测试准确率满意为止。

关于这个算法的妙处在于它如此廉价,而且我们执行的每一步都比任何矩阵操作便宜得多,因为这是一个矩阵问题,但执行一步我们只需要向量操作,极其廉价。

这在其他方法中并不常见。即使在 K-Means 中,一次迭代也需要处理所有数据。但在这里,我们执行

38:文本表示学习与词向量 🧠

在本节课中,我们将要学习如何将文本数据(特别是单词)转换为数值特征,以便机器学习模型能够处理。我们将从最简单的方法开始,逐步深入到更先进、更智能的表示学习方法,例如矩阵分解和对比学习。


从单词到特征:目标与挑战

我们的目标是将单词转换为数值特征。例如,英语中可能有数百万个单词,但常用的可能只有一两万个。我们希望为每个单词找到一个实数表示,通常包含 K 个特征。

以下是实现此目标的几种方法。

独热编码与词袋模型

最简单的方法是使用独热编码。这意味着将第 i 个单词 w_i 映射为一个向量,该向量仅在单词出现的位置为 1,其他位置为 0。

公式
w_i = [0, ..., 1, ..., 0],其中 1 位于第 i 位。

如果词汇表大小为 V,那么这个向量就是 V 维的。这种方法也被称为词袋模型表示。当处理包含多个单词的句子时,只需将所有出现单词对应的位置设为 1,忽略单词的顺序。

然而,这种方法有明显的缺点:

  1. 特征维度极高:如果词汇表很大,向量维度会非常高,导致计算和存储成本巨大。
  2. 缺乏语义信息:每个单词的向量都是完全独立的。例如,一个单词的单数和复数形式会被视为两个完全不同的向量,模型无法捕捉它们之间的任何关联。

因此,我们期望找到更好的特征表示,使得语义相似的单词具有相似的特征向量。这就是表示学习的目标。


更好的特征:矩阵分解方法

上一节我们介绍了基础的词袋模型,本节中我们来看看如何通过矩阵分解来学习更优的词向量。

我们可以利用一个非常简单的无监督数据源:共现矩阵。这个矩阵 X 的每个元素 X_ij 记录了单词 i 和单词 j 在文本中(例如,在一个固定大小的窗口内)一起出现的次数。

核心思想:这个共现矩阵的结构,与我们之前在推荐系统中遇到的用户-物品评分矩阵非常相似。

因此,我们可以采用类似的矩阵分解方法。我们将庞大的共现矩阵 X(大小为 V x V)分解为两个小得多的矩阵的乘积:

公式
X ≈ W * Z^T

其中:

  • WV x K 的矩阵,它的每一行就是对应单词的 K 维词向量
  • ZV x K 的矩阵,可以理解为“上下文词”的向量表示。
  • K 是我们选择的特征数量(例如 50 或 100),远小于词汇表大小 V

我们的优化目标是让 W 的第 i 行和 Z 的第 j 行的内积,尽可能接*共现矩阵中的值 X_ij。通过优化这个目标(例如使用*方损失函数),我们就能学习到有意义的词向量 W

这种方法就是 GloVe 模型的核心。与推荐系统一样,我们可以使用随机梯度下降来高效地训练这个模型。

GloVe 的细节调整

  • 输入数据:通常使用共现次数的对数 log(X_ij + 1),而不是原始计数,以*滑极端值的影响。
  • 加权函数:损失函数中引入了一个加权项 f(X_ij),用于*衡常见共现和罕见共现的重要性,避免模型被高频词对主导。

通过这种方式学习到的词向量,能够将语义信息编码到低维空间中。


词向量的神奇之处:语义与类比

学习到的词向量有什么用?为什么它们比词袋模型更好?

词向量在低维空间中编码了丰富的语义关系:

  1. 相似性:语义相*的单词(如“猫”和“狗”)在向量空间中位置接*。
  2. 类比关系:词向量空间中的方向可以对应某种语义关系。经典的例子是:
    公式vec(“king”) - vec(“man”) + vec(“woman”) ≈ vec(“queen”)
    这意味着“国王”与“男人”的向量差(可能代表“王室”属性),加上“女人”的向量,结果会非常接*“女王”的向量。类似地,vec(“Paris”) - vec(“France”) + vec(“Germany”) ≈ vec(“Berlin”)

这些特性使得词向量可以用于信息检索(寻找相似词)或作为更复杂自然语言处理任务的优质特征输入。


更高效的算法:Word2Vec 与对比学习

虽然 GloVe 很有效,但它需要预先计算并存储庞大的共现矩阵。本节中我们来看看 Word2Vec 模型,它通过流式处理文本避免了这个问题。

Word2Vec 的核心思想是对比学习。它不再预测共现次数,而是训练一个二分类器来区分“真实”的单词对和“虚假”的单词对。

  • 正样本:从真实文本中连续出现的单词对(如“人工智能”)。
  • 负样本:将一个正样本中的上下文词替换为随机选择的单词(如“人工智能”和“香蕉”),构成虚假的单词对。

模型为每个单词学习两个向量:一个作为中心词向量,一个作为上下文词向量。训练目标是让正样本的内积得分高,负样本的内积得分低(例如使用逻辑损失函数)。

关键优势:Word2Vec 可以流式训练。它不需要预先计算任何矩阵,只需顺序读取文本,为每个出现的单词对及其随机负样本执行一次 SGD 更新,极其高效。

这种“利用共同出现作为学习信号”的思想非常强大,可以推广到其他领域,如图像或推荐系统,形成了对比学习范式。


超越单词:句子与文档表示

到目前为止,我们主要关注单词的表示。但在实际应用中,我们常常需要处理整个句子或段落。本节中我们来看看如何获得更长文本的表示。

简单方法:*均词向量。将一个句子中所有单词的向量取*均,作为句子的表示。这种方法简单有效,但信息有损失。

语言模型方法:训练一个模型来预测文本序列中的下一个词(或遮盖的词)。这类模型(如 GPT、BERT)在大量文本上训练后,其内部激活(尤其是最后几层的输出)可以作为整个输入序列的高质量上下文感知特征。同时,这些模型也具备了强大的文本生成能力。

卷积神经网络方法:对于句子分类等任务,可以将句子中每个单词的词向量拼接成一个矩阵,然后使用一维卷积核在“词维度”上进行滑动,提取局部特征,再通过池化层得到固定长度的句子表示。

FastText 方法:这是一个简单高效的句子分类模型。它将句子表示为词袋模型,然后学习一个词嵌入矩阵和一个线性分类器

  1. 句子通过词袋向量表示。
  2. 词袋向量与词嵌入矩阵相乘,得到句子中所有单词向量的*均(即句子向量)。
  3. 句子向量再通过线性分类器得到预测结果。

公式y_pred = W * (1/N * ∑ Z_i),其中 Z_i 是句子中第 i 个单词的嵌入向量。

其巧妙之处在于,词嵌入矩阵 Z 和分类器 W联合学习的。这使得词向量被训练成“适合相加”的形式,从而得到的句子表示比简单地*均预训练词向量更优。训练同样可以通过 SGD 高效完成。


总结与回顾

本节课中我们一起学习了文本表示学习的核心思想与方法:

  1. 起点是简单的独热编码词袋模型,它们维度高且缺乏语义。
  2. GloVe 模型通过矩阵分解共现矩阵,无监督地学习到低维、富含语义的词向量
  3. Word2Vec 采用对比学习框架,通过区分真实/虚假词对来学习词向量,支持流式训练,更加高效。
  4. 学习到的词向量空间展现了有趣的语义相似性类比关系
  5. 为了处理句子和文档,我们可以使用*均词向量、基于语言模型的深度特征、CNNFastText 等方法来获得固定长度的文本表示。

这些技术是将文本数据引入机器学习模型的基础,也是现代自然语言处理取得突破的关键。

39:基于矩阵分解的推荐系统入门教程 🎬🤖

在本节课中,我们将学习如何实现一个基于矩阵分解的推荐系统。推荐系统是一种模型,其输入是用户和电影,输出是该用户对该电影的预测评分。我们将从加载和处理数据开始,逐步实现几个基线模型,最终构建并优化一个矩阵分解模型。


数据集加载与探索 📊

我们首先加载 MovieLens 数据集,其中包含 100,000 条电影评分数据。每条数据由三个相同长度的数组组成:电影ID、用户ID和用户给出的评分。

# 示例:加载数据
# 数据格式:movie_ids, user_ids, ratings

加载数据后,我们需要查看每个用户给出的评分数量以及每部电影获得的评分数量的分布情况。这将帮助我们了解数据的稀疏性。


数据预处理:移除稀疏条目 ✂️

在数据集中,有些电影或用户出现的频率极低。例如,如果一部电影只有一个评分,基于此进行预测是不可靠的。因此,我们需要移除那些评分数量过少的条目。

以下是处理步骤:

  1. 计算每部电影和每个用户的评分数量。
  2. 设定一个最小阈值(例如,至少5个评分)。
  3. 移除评分数量低于该阈值的电影和用户对应的所有条目。

完成此步骤后,数据集将变得更加稠密和可靠。


划分训练集与测试集 🧱

为了评估模型性能,我们需要将数据集划分为训练集和测试集。在本教程中,我们将使用90%的数据进行训练,10%的数据进行测试。

这意味着我们将保留一部分用户-电影评分对,不用于模型优化,仅用于最终的性能评估。


理解评分矩阵 📈

到目前为止,我们将数据集视为三个列表。另一种更常见的理解方式是将其视为一个矩阵。

  • 矩阵的行 代表用户。
  • 矩阵的列 代表电影。
  • 矩阵中的值 代表用户对电影的评分。

基于训练集构建的这个矩阵将包含大量未知单元格(因为我们没有所有评分)。推荐系统的核心挑战可以看作是填充这个矩阵。如果我们能填满它,我们就知道了所有用户对所有电影的潜在评分。


实现基线预测模型 🎯

在构建复杂模型之前,我们先实现几个简单的基线模型进行比较。所有模型都将实现为一个预测器类,该类在初始化时接收训练数据,并包含一个 __call__ 方法用于对新数据进行预测。

全局*均预测器

第一个基线模型是全局*均预测器。它忽略用户和电影的个体差异,对所有用户-电影对都预测数据集中所有评分的全局*均值。

公式
预测评分 = 所有评分的*均值

这是一个非常简单的基线,但为我们提供了一个比较的基准。如果后续更复杂的模型表现比它还差,那就说明模型有问题。

用户*均预测器

接下来,我们实现用户*均预测器。对于任何用户-电影对,它预测该用户对所有已评分电影的*均分。

公式
预测评分(user_j, movie_i) = 用户j的所有评分*均值

请思考:这个模型在实践中为什么可能用处有限?(提示:它无法区分用户对不同电影的偏好差异)。

电影*均预测器

类似地,我们实现电影*均预测器。对于任何用户-电影对,它预测所有用户对该部电影评分的*均值。

公式
预测评分(user_j, movie_i) = 电影i的所有评分*均值

请思考:在什么假设下,这个模型会是一个好模型?(提示:假设电影本身的质量是评分的主要决定因素)。


模型评估:均方误差 📉

我们使用均方误差(MSE)来比较不同模型的性能。MSE计算预测评分与真实评分之间差异的*方的*均值。

公式
MSE = (1/N) * Σ(预测评分 - 真实评分)^2

你需要实现这个评估函数,并在测试集上计算每个基线模型的MSE。


核心模型:矩阵分解 🧠

现在,我们进入本练习的核心部分:实现矩阵分解模型。

模型原理

矩阵分解的核心思想是为每个用户和每部电影学习一个低维度的向量表示(也称为嵌入)。

  • 为每部电影 i 分配一个 D 维可训练向量 M_i
  • 为每个用户 j 分配一个 D 维可训练向量 U_j
  • 直观上,如果两部电影被相似的用户喜欢,它们的向量 M 应该相似。同样,如果两个用户口味相似,他们的向量 U 也应该相似。

我们可以将所有电影向量堆叠成矩阵 M(形状:电影数量 × D),将所有用户向量堆叠成矩阵 U(形状:用户数量 × D)。

预测与矩阵形式

模型预测用户 j 对电影 i 的评分,是通过计算用户向量和电影向量的点积(内积)来实现的。

公式
预测评分(user_j, movie_i) = U_j · M_i^T

如果我们同时考虑所有用户和所有电影,整个预测评分矩阵可以表示为两个矩阵的乘积。

公式
预测评分矩阵 = M * U^T

这正是“矩阵分解”名称的由来——我们将大的评分矩阵*似分解为两个小矩阵的乘积。

模型优化:随机梯度下降

我们需要优化电影和用户的表示向量。这通过最小化训练集上的预测误差来实现。我们使用随机梯度下降(SGD)进行优化。

损失函数(含L2正则化/权重衰减)
L = (1/|训练集|) * Σ( (U_j · M_i^T - 真实评分)^2 ) + λ * (||M||^2 + ||U||^2)

其中,λ 是正则化系数,用于控制向量的大小,防止过拟合。

在SGD中,我们随机采样一个训练样本(用户-电影-评分三元组),计算损失相对于该样本对应的 U_jM_i 的梯度,然后沿梯度反方向更新这两个向量。

你需要实现这个训练过程,并观察测试误差是否能够下降到1.0以下,这应该比之前的基线模型表现更好。

模型优化:交替最小二乘法

另一种优化方法是交替最小二乘法(ALS)。其思想是:

  1. 固定用户向量 U,此时优化电影向量 M 是一个可以直接求解的二次优化问题。
  2. 固定电影向量 M,此时优化用户向量 U 同样是一个可以直接求解的二次优化问题。

我们交替执行步骤1和步骤2。这种方法通常更稳定,并且能够获得更好的结果。你需要实现ALS算法,并比较其与SGD的性能。


总结 📝

本节课中,我们一起学习了推荐系统的基本概念和实现方法。

  1. 我们从数据预处理开始,学习了如何处理稀疏的评分数据。
  2. 接着,我们实现了多个基线模型,包括全局*均、用户*均和电影*均预测器,并使用均方误差对它们进行了评估。
  3. 然后,我们深入探讨了矩阵分解模型,理解了其通过用户和电影的低维向量表示进行预测的原理。
  4. 最后,我们实现了两种优化算法:随机梯度下降和交替最小二乘法,来训练矩阵分解模型。

通过本教程,你应该掌握了构建一个简单但有效的推荐系统的基本流程,并理解了矩阵分解这一核心技术的运作方式。请尝试调整模型参数(如向量维度D、学习率、正则化系数λ),观察它们对模型性能的影响。

posted @ 2026-03-26 08:20  布客飞龙II  阅读(0)  评论(0)    收藏  举报