华盛顿大学机器学习笔记-全-
华盛顿大学机器学习笔记(全)
第一部分 1:概述 👋

课程概述
在本节课中,我们将要学习机器学习专项课程的第一门课,即机器学习的基础知识。我们将一起探索机器学习的应用、如何构建机器学习系统,以及其背后的算法原理与实现方法。
欢迎与介绍
欢迎来到机器学习专项课程,以及这门关于机器学习基础的第一门课。
我们非常高兴能与您一同踏上这段学习旅程。
我是卡洛斯,我是艾米丽。
我们将共同学习机器学习的应用、如何构建机器学习系统、其背后的算法如何工作,以及如何构建这些算法。
我们对这门课程和整个专项课程充满热情,现在让我们正式开始学习。
总结

本节课中,我们一起学习了机器学习专项课程的入门介绍,明确了本课程的目标是理解机器学习的基础知识、应用与算法构建。在接下来的课程中,我们将逐步深入这些核心主题。
第一部分 2:讲师介绍与课程愿景 👨🏫

在本节课中,我们将认识本系列课程的主讲教师,了解他们的专业背景,并理解他们设计这门在线课程的初衷与愿景。
讲师介绍
大家好,我是卡洛斯·加斯顿,我是亚马逊机器学习教授。等等,我是亚马逊机器学习教授。你是谁?
我是艾米丽·福克斯。我是计算机科学领域的亚马逊机器学习教授,同时也是统计学领域的亚马逊机器学习教授。我们都在美国西雅图的华盛顿大学任教。
为了澄清,这里指的是美利坚合众国。
那么,艾米丽,你今天在这里的资格是什么?我需要读我的简历吗?不,好吧,只读开头部分。我的资格是什么?
好的,我在麻省理工学院待了太久,九年。虽然那九年并非只为了一个学位,我在此期间获得了几个学位。我在那里攻读电气工程和计算机科学的博士学位。需要列出更多资格吗?我认为……
这已经很好了,她非常有资格。让我补充一下。
我的本科毕业于巴西圣保罗大学,博士学位来自斯坦福大学的计算机科学专业。我从事机器学习工作已经很长时间了,就像有人喜欢说的,非常长的时间。我想也许我应该描述一下我转向统计学的经历。在获得电气工程和计算机科学博士学位后,我在杜克大学做了统计学博士后。实际上,坦率地说,我的博士研究很大程度上就是一个统计学博士项目,但在录制本课程时,麻省理工学院没有统计学系,我学习的时候也没有。所以,是的,我是一名自学成才的统计学家。
我们都可以自学。这就是这门慕课的意义所在。嘿,我们一起学习。
我从事机器学习工作有一段时间了,我对来自广泛领域的机器学习方法感到非常兴奋。我曾研究过用于“不确定性下的规划”的理论算法,即使用机器学习进行决策。我曾研究过传感器数据、分布式传感器(当时称为传感器网络,今天称为物联网,但这要追溯到很久以前),然后我将重点放在了大规模机器学习上,即如何将机器学习方法扩展到海量数据。
我们也会在本专项课程中使用其中一些想法。
你呢?我没有卡洛斯那么长的历史,但我真正喜欢研究的是时间序列应用,即随时间推移产生的数据,我们想从中发现一些潜在的结构或模式。我研究的很多重点是如何扩展到非常高维或大规模的时间序列集合,特别是当它们具有非常复杂的动态时。我的另一个主要兴趣是如何在数据流式输入时进行在线推断。
我研究过各种不同的应用领域,其中一些我非常有热情,目前特别关注的是神经科学。但我也研究过语音数据、动作捕捉应用(分析人体运动)、金融数据等等。许多数据都具有非常重要的时间结构,这确实是我的热情所在。
我教授机器学习已经很长时间了,主要是在大学环境中,有些课程比其他课程更受欢迎。这个笑话永远不会结束。所以,我们在这里,对我们来说,教授这门在线课程是一次激动人心的经历。
课程愿景与设计理念
那么,你们是如何决定开设这门在线课程的?我是如何决定的?这是个很好的问题。
有很多原因促使我想开设这门在线课程,但最根本的原因是思考如何向非常广泛的受众传播机器学习知识。因为就我个人而言,我来自一个非常不同的背景和培训经历,卡洛斯也是。
我自己也经历过尝试学习机器学习、学习统计学的过程。我认为有一种非常好的方式,可以在非常基础的层面上向非常广泛的受众教授这些知识,这是我的热情之一。另一个原因是,我想为未来的其他目标考虑如何将这些知识传授给我在华盛顿大学作为教授所接触的其他校园群体。
我对机器学习的教学方式感到非常兴奋,我们一直在深入思考如何以一种新的方式来处理机器学习这个非常广泛的概念。在这个专项课程中,正如我们将在本模块中进一步讨论的,你将以一种完全不同的方式体验机器学习,一种在其他地方的新体验。我们将真正专注于应用优先,理解机器学习如何运作,然后深入理解这些方法是如何构建的以及它们如何发挥作用。所以,对我们来说,这段旅程的一部分是构建一种教授机器学习的新方式,这很酷。
这确实很酷。所以非常令人兴奋,是的。
我们很兴奋。
总结


本节课中,我们一起认识了本课程的两位主讲教师卡洛斯和艾米丽,了解了他们多元化的学术背景和在机器学习、统计学、时间序列分析等领域的丰富研究经验。更重要的是,我们理解了本课程的核心理念:以应用为先导,面向广泛受众,旨在构建一种全新的、易于理解的机器学习教学方式。在接下来的课程中,我们将跟随他们的引导,开始这段激动人心的学习之旅。
第一部分 3:机器学习如何改变世界 🌍

在本节课中,我们将探讨机器学习如何从学术研究演变为驱动现代智能应用的核心技术,并理解其在不同行业中的实际影响。
我从事机器学习已有很长时间。当前是从事机器学习非常令人兴奋的时期,因为你正亲眼目睹它带来的巨大影响。

但这并非我最初接触机器学习的方式。如果几年前你与我交谈,我对机器学习的看法截然不同。那时,你从一些数据开始,将这些数据输入某个神奇的机器学习算法,然后展示我的曲线比你的曲线更好,最后向机器学习会议提交一篇论文。
😊
这就是我一直以来对机器学习的看法。
然而,这并非我最初进入这个领域的原因。我为何投身于机器学习?
当我还是个孩子时,我阅读了许多书籍,尤其是科幻小说。我非常想建造真正智能的机器人,它们能思考世界、推理事物,也就是我今天所说的智能应用。真正酷且令人兴奋的是,如今我们看到许多使用机器学习的智能应用产生了巨大影响。
😊
事实上,如果你观察一个又一个行业,当今成功的公司——那些被称为颠覆者的公司——它们进入一个市场并彻底改变它。它们的差异化优势通常来自于以机器学习为核心的智能应用或智能。
例如,早期,亚马逊通过在其网站引入产品推荐系统,真正颠覆了零售市场。我们看到谷歌通过利用机器学习精准投放广告,预测用户点击行为,从而颠覆了广告市场。你看到Netflix这家电影发行公司彻底改变了电影的观看方式。我们不再去商店租借电影,而是上网流媒体观看。Netflix的核心改变在于其推荐系统,它帮助我从其提供的成千上万部电影中,找到我喜欢、适合我的电影。
😊
你还会看到像Pandora这样的公司,它们提供音乐系统和音乐推荐系统,让我找到喜欢的音乐,并为我推荐适合清晨困倦时或夜晚准备入睡时聆听的音乐流,为我找到真正的好音乐。
😊
这种现象出现在许多地方、许多行业。你看到Facebook将我与我可能想结交的人联系起来。你甚至看到像Uber这样的公司,通过实时优化如何连接司机与乘客,颠覆了出租车行业。
因此,在所有这些领域,机器学习都是核心技术之一,是使这些公司产品真正与众不同的技术。所以,在这个专项课程中,我们将真正讨论机器学习的各个方面,让你准备好构建类似的智能应用。
我们将反复看到一个流程:从数据开始,引入机器学习方法,对数据进行新型分析,而这种分析将赋予你智能——例如,我现在可能购买什么产品。通过理解这个流程,并在各种场景、各种应用、使用多种算法中实践,真正理解如何将它们连接起来。
😊
你将能够真正构建属于自己的智能应用。

本节课总结

本节课中,我们一起学习了机器学习角色的演变:它从一个侧重于算法性能和学术论文的领域,发展成为驱动现代智能应用和颠覆性商业产品的核心技术。我们看到了机器学习在亚马逊、谷歌、Netflix、Pandora、Facebook和Uber等公司中的实际应用,并介绍了构建智能应用的核心流程:数据 -> 机器学习分析 -> 智能。这为我们后续深入学习机器学习的各个方面奠定了基础。
第一部分 4:案例研究方法导论 📚

在本节课中,我们将学习如何通过一系列具体的案例研究,来理解从数据到智能的完整流程。这些案例将把抽象的机器学习方法,建立在真实世界的应用场景之上,这也是本课程的一大特色。

为什么采用案例研究方法?🤔
上一节我们提到了课程的整体目标,本节中我们来看看实现这一目标的具体方法。
我们将通过研究一系列案例来学习从数据到智能的流程。这些案例将把我们要介绍的方法,建立在真实世界的应用基础之上。这是本课程一个非常独特的特点。
案例研究概览 📋
以下是本课程将探讨的五个核心案例,每个案例都对应一种关键的机器学习方法。
案例一:房价预测
我们将首先研究预测房价的案例。我们要获取的智能,是与某个未上市房屋相关联的价值。我们不知道它的价值,希望从数据中学习得到。
我们的数据是其他房屋的信息。我们将查看其他房屋的销售价格,以此来推断我们感兴趣的房屋的价值。除了销售价格,我们还会查看房屋的其他特征,例如卧室数量、浴室数量、平方英尺数等。
我们将使用的机器学习方法,是建立房屋属性与销售价格之间的关系模型。如果我们能从房屋层面的特征与观察到的销售价格之间学习到这个模型(这种关系),那么我们就可以用它来预测新房屋。我们获取新房屋的属性,并预测其销售价格。这种方法被称为回归。
案例二:情感分析
在第二个案例中,我们将探索一个情感分析任务。我们有一些餐厅的评论。
例如,有一条评论说:“寿司很棒,食物很棒,但服务很糟糕。”我们希望处理这条评论,并能够将其分类为具有积极情感(好评,竖起大拇指)还是消极情感(差评,竖起大拇指)。
我们将通过查看大量其他评论来实现这一点。我们将查看评论的文本和评分,以理解文本与情感分类之间的关系。
例如,在这个案例中,我们可能会分析这条评论的文本,统计它使用了多少次“awesome”这个词,以及使用了多少次“awful”这个词。根据我们已有的其他评论,我们将学习一个基于这些词语使用频率的决策边界,来判断评论是正面还是负面。我们从这些其他评论中学习的方法,是基于与文本相关联的评分。这种方法被称为分类方法。
案例三:文档检索
在第三个案例中,我们将进行一个文档检索任务。这里,我们要获取的智能是一篇读者可能感兴趣的文章或书籍。
我们拥有的数据是一个庞大的可能推荐文章的集合。
在这种情况下,我们将尝试基于相关文章组在数据中寻找结构。例如,可能有一组关于体育、世界新闻、娱乐和科学的文章。如果我们找到了这种结构,并用这些类型的标签来标注我们的语料库(文档集合)——这些标签我们事先并没有,而是试图从数据中推断出来——那么我们就可以用它来进行非常快速的文档检索。
因为如果我正在阅读一篇关于世界新闻的文章,那么当我想检索另一篇文章时,我已经知道应该搜索哪些文章了。这种类型的方法被称为聚类。
案例四:协同过滤
在第四个案例中,我们将做一个非常有趣的事情,叫做协同过滤,在过去十年中对许多领域产生了巨大影响。
具体来说,我们将研究产品推荐。你根据过去的购买记录,尝试使用这些记录来推荐一组你可能感兴趣购买的其他产品。
在这种情况下,我们将用于获取产品推荐智能的数据是:我们希望理解你过去的购买记录与你未来可能购买的产品之间的关系。为此,我们将使用其他用户的购买历史记录,以及可能包含的这些用户的特征。
但这里的关键思想是,我们将获取这些数据,并将其排列成一个“顾客 × 产品”矩阵。这里的方格表示顾客实际购买的产品,即该顾客喜欢的产品。
从这个矩阵中,我们将学习关于用户的特征和关于产品的特征。一旦我们从所描述的数据中学习了这些关于用户和产品的特征,我们就可以考虑使用这些特征来查看用户的喜好(用户喜欢的各种属性)与产品是否真正具备这些属性之间的一致性程度。
在我展示的这个例子中,也许一个作为母亲的用户具有某些特征,这些特征与其他也是母亲的用户相似。由此,我们可以推断出关于产品的信息,例如,哪些婴儿产品的属性是母亲们感兴趣的。我们利用这些信息来形成我们的推荐。这种从“顾客 × 产品”矩阵到学习用户和产品特征的方法,被称为矩阵分解。

案例五:视觉产品推荐
在我们的最后一个案例研究中,我们将研究一个视觉产品推荐器。
这里,我们的数据是:某人将访问网页,他们输入的不是文本,而是一张图片。他们会输入一张图片,比如一双黑色鞋子、黑色靴子、高跟鞋、某种船鞋或跑鞋的图片。他们想要的是一组可能也感兴趣的结果,即与他们拥有的图片在视觉上相似的鞋子。他们希望能够搜索这些结果来购买商品。
为了实现从一张图片到一组相关图片的转换,我们需要拥有关于该图片的非常好的特征,以找到其他相似的图片。我们将获取这些非常详细特征的方法,叫做深度学习。
具体来说,我们将研究这些神经网络,其中神经网络的每一层都提供越来越具描述性的特征。在我们展示的小例子中,第一层可能只检测图像中的不同边缘,而当我们到达第二层时,我们开始检测角落和更复杂的特征。随着在这些层中越走越深,你会得到更精细的特征出现。
总结 📝
本节课中,我们一起学习了本课程的核心教学方法。
正如你所看到的,我们将通过一系列真实世界的案例研究(真实世界的问题和真实世界的解决方案)来学习机器学习。通过这种方式,我们将探索一系列功能强大的方法,这些方法将使你能够在新的问题上(即使不是我们使用的确切案例)开发和部署新的机器学习技术。这些案例研究将使我们能够将所描述的方法建立在非常易于理解的事物之上。
第一部分 5:从案例出发 🚀


在本节课中,我们将一起了解华盛顿大学《机器学习(基础篇)》专项课程的整体结构与核心理念。本课程将通过一系列实际案例来讲解机器学习,帮助初学者理解概念,并最终构建智能应用。
正如Emily所讨论的,我们将通过不同领域的广泛案例研究来学习机器学习。这种方法能真正夯实概念背后的基础。
其他机器学习课程可能更像一份算法和方法的清单。例如支持向量机、核方法、逻辑回归、神经网络等。它们只是方法的罗列。这种方法的弊端在于,从算法开始学习,最终接触到的用例或应用往往过于简化,与现实脱节。
因此,在这个专项课程中,我们采取了截然不同的方法。Emily和我在华盛顿大学创建了一门关于大规模数据机器学习的课程,并率先采用了这种案例教学法。在那门课程中,我们收到了大量积极的反馈,学员们真正理解了这些概念。
所以,在第一门课程中,我们将从实际用例开始。通过从用例出发,你将能够真正掌握关键概念和技术,从而构建、衡量质量并判断你的智能应用是否运行良好。最终,你将构建一系列这样的智能应用。
要构建此类智能应用,通常需要考虑几个问题:我要解决什么任务(例如情感分析问题)?我将使用什么机器学习模型(例如支持向量机或逻辑回归)?我将使用什么方法来优化该模型的参数?然后我会问:这真的能提供我所期望的智能吗?我们如何衡量该系统的质量?
在这个专项课程中,我们将把如何描述模型和优化模型的核心部分放到后续课程中。第一门课程将专注于帮助我们弄清楚要解决什么任务、哪些机器学习方法合适以及如何衡量它们。通过将算法视为“黑箱”,我们将能够共同构建一系列真正智能、酷炫的应用。我们实际上会编写代码、构建它们,并以多种方式演示。
整个专项课程包含四门核心课程和一个顶点项目,它们将在不同领域深入探讨。
以下是我们在整个专项课程中将深入学习的几个快速示例。
回归分析 📈
上一节我们介绍了课程的整体思路,本节中我们来看看第一门核心课程:回归分析。
回归课程将讨论预测实数值的各种模型。例如,根据房屋特征预测房价。我们将讨论线性回归技术,以及像岭回归(Ridge Regression)和套索回归(Lasso)这样的高级技术,它们能帮助你选择最适合问题的特征。我们将讨论优化技术,如梯度下降(Gradient Descent)和坐标下降(Coordinate Descent),以优化这些模型的参数。同时,还会涉及一些关键的机器学习概念,如损失函数、偏差-方差权衡、交叉验证等。你需要了解这些概念才能真正运用这些方法、改进它们并用它们构建应用。
分类技术 🗂️
在了解了如何预测连续值后,我们进入下一个核心领域:分类。
第二门关于分类的课程,我们将构建Emily提到的情感分析用例。以下是本课程将涵盖的主要内容:
- 模型:从线性分类器到更高级的方法,如逻辑回归、支持向量机,并加入核方法和决策树来处理非线性复杂特征。
- 优化方法:讨论大规模处理这些技术和构建集成模型(如提升法Boosting)的优化方法。
- 核心概念:帮助你掌握分类器、扩展并将其应用于不同方法的底层机器学习概念。
聚类与检索 🔍
掌握了预测和分类后,我们来看看如何发现数据中的内在结构,特别是在文档背景下。
第三门课程将专注于聚类和检索。以下是本课程的核心内容:
- 基础与高级技术:讨论最近邻等基础技术,以及混合高斯模型、潜在狄利克雷分配等高级文本分析聚类技术。
- 算法与扩展:探讨支撑这些技术的算法,以及如何使用KD树、采样和期望最大化等技术来扩展它们。
- 分布式计算:核心概念围绕如何扩展这些方法、如何衡量质量,以及如何利用MapReduce等技术将其编写为分布式算法(在Hadoop等系统中实现)。在第四门课程中,你将实际编写一些用于分布式机器学习的MapReduce代码。
矩阵分解与降维 🧩
在学习了处理文档数据的方法后,我们转向一种广泛适用的技术,尤其用于推荐系统。
第四门技术课程将专注于矩阵分解和降维技术。以下是本课程的重点:
- 应用与技术:这些技术应用广泛,尤其适用于推荐产品的推荐系统,例如协同过滤、矩阵分解、主成分分析。
- 优化方法:优化这些技术的底层方法,如交替最小二乘法、奇异值分解。
- 核心概念:一系列非常有用的核心机器学习概念,特别是在推荐领域,例如如何选择多样化的推荐集,以及如何将其扩展到大型问题。
顶点项目 🏆

最后,在掌握了各核心模块后,我们将通过一个综合性的顶点项目来整合所学。
顶点项目将非常令人兴奋。在本模块结束时,我会回过头来更详细地介绍这个顶点项目。先给你一点提示:你将构建一个极其酷炫的项目,可以向所有朋友和潜在雇主展示。你会发现,你可以围绕推荐系统,结合文本数据、图像数据、情感分析和深度学习,构建一个真正智能的应用程序。这将非常酷。
本节课中我们一起学习了华盛顿大学机器学习专项课程的整体框架。我们从实际用例出发,概述了四门核心课程(回归、分类、聚类与检索、矩阵分解)分别关注的重点,以及一个综合性的顶点项目。这种学习方法旨在帮助你理解核心概念、掌握实用技术,并最终能够构建和评估自己的智能应用。
第一部分 6:如何进入机器学习领域 🚀

在本节课中,我们将探讨两位专家如何进入机器学习领域,并了解这一领域如何吸引来自不同背景的人们。通过他们的个人经历,我们可以看到机器学习的广泛应用和跨学科特性。
从机器人到数据科学:Emily的旅程 🤖
上一节我们介绍了课程背景,本节中我们来看看Emily是如何进入机器学习领域的。
Emily最初对机器人充满热情,并认为机械工程是构建机器人的途径。因此,她开始了机械工程的学习。然而,她很快意识到构建机器人的真正挑战在于“机器人大脑”,这促使她转向计算机科学。进一步探索人工智能后,她发现理解数据是AI中的难点,这最终将她引向了机器学习。于是,她攻读了机器学习博士学位,完成了从关注机器人到热衷于数据和机器学习的转变。
以下是Emily旅程的关键步骤:
- 始于对机器人的热情,学习机械工程。
- 认识到机器人的核心挑战在于智能控制,转向计算机科学。
- 发现人工智能的关键在于处理和理解数据,从而进入机器学习领域。
从目标追踪到模型学习:Alex的旅程 ✈️
了解了Emily的路径后,我们再来看看Alex进入机器学习领域的不同经历。
Alex的经历相似但不同。他并非从小立志建造机器人,但后来确实从事过与机器人相关的工作。真正让他进入机器学习领域的,是一个目标追踪应用程序项目。该项目旨在追踪高机动性目标(如飞机),这些目标会做出规避动作以避免被追踪。
当时系统基于对飞机物理运动的已知假设(如左转、右转、直线飞行)进行高度工程化建模。但当飞机做出未曾预料的行为时,系统会通过快速切换预设模式(如“左转-右转-左转”)来尝试适应,但这并不能准确描述实际情况。
Alex因此认为,必须找到更好的方法来学习所部署模型的参数,并量化对指定模型的确信程度,从而使系统对此类情况更具鲁棒性。这个需求将他带入了机器学习和统计学领域。
机器学习:一个汇聚多元背景的领域 🌈
从上述两个故事可以看出,Emily从机械工程经由数据科学进入机器学习,而Alex则从电气工程和飞机追踪领域进入机器学习。如今,令人兴奋的是,我们看到来自各个领域的人们都在进入机器学习领域。
以下是投身机器学习领域的一些典型背景:

- 物理学:研究者对数据科学充满热情。
- 生物学与社会科学:利用机器学习分析复杂系统。
- 哲学、数学与统计学:从基础理论角度贡献智慧。
- 计算机科学与工程:提供算法与实现基础。
- 艺术:甚至艺术专业的学生也运用机器学习创作酷炫的装置艺术。
例如,在卡内基梅隆大学授课时,曾有艺术专业学生选修机器学习课程,并构建了内含机器学习技术的艺术装置,这非常令人惊叹。我们甚至与朋友Oman K合作开设过关于构建运用机器学习的艺术装置的课程。
我们看到,拥有不同背景的人们正在改变他们的职业轨迹,思考数据科学和机器学习,并构建智能应用。他们都对数据抱有极大的热情。
总结与展望 📚

本节课中,我们一起学习了两位专家进入机器学习领域的个人旅程。他们的故事表明,对现实问题的求解热情和跨学科思维是进入这一领域的重要动力。机器学习作为一个高度融合的领域,正吸引着来自工程、科学、艺术等不同背景的人才,共同利用数据构建智能解决方案。


正如他们所说:“这很酷。” 我们下次课再见。
第一部分 7:课程适合人群与预备知识 📚


在本节课中,我们将了解这门机器学习专项课程的定位、目标人群以及学习所需的预备知识。我们将明确课程的设计理念,并详细说明学习前需要具备的数学和编程基础,以及必要的计算环境。
课程定位与目标 🎯
首先需要强调的是本专项课程的难度级别和教学内容。我们将教授非常重要的机器学习方法,并将这些方法建立在真实世界的应用案例之上,正如我们在案例研究中看到的那样。我们的座右铭是:将艰深的概念变得直观且可应用。
因此,这门课程不会专注于定理证明,而是致力于在非常直观和实用的层面上,理解一些非常重要的机器学习算法,并思考如何将它们部署到新的问题中。
为了实现这个目标,我们的宗旨是:在最小化理解课程内容所需先修知识的同时,最大化您在实际感兴趣的新问题上开发和部署这些方法的能力。在呈现概念时,我们将以这些案例研究为基础,采用非常直观、易懂的方式。
目标受众 👥
以下是本课程主要面向的人群:
- 软件工程师:对机器学习感兴趣的软件工程师。
- 科研人员:希望转型为数据科学家的科研人员。
- 数据爱好者:拥有一定数学和编程经验,希望分析数据并从中获得乐趣的广大人群。他们渴望了解更多关于机器学习的知识,以及如何从数据中获取智能。
预备知识详解 🔧
之前提到,我们假设您具备一定的数学和编程背景。现在让我们更详细地讨论这一点。
数学背景要求
在数学背景方面,我们假设您具备以下基础知识:
- 基础微积分知识:理解导数的概念及其计算方法。
- 基础线性代数知识:您需要知道什么是向量、什么是矩阵以及如何进行矩阵乘法。
我们将尽可能以最直观的层面呈现内容。即使我们可以用矩阵和矩阵乘法的形式写出方程,我们也会尝试提供尽可能多的视觉辅助工具来帮助您建立直觉。因此,如果您对这些概念只是略有了解,我们建议您复习一下。但请放心,我们会努力提供符合我们座右铭的直观解释。
编程背景要求
在编程经验方面,本专项课程将使用基础的Python进行编程。

如果您不熟悉Python,具备基础的Python知识当然会很有帮助。但我们认为,如果您具备其他编程语言的知识,也可以掌握本课程所需的重要工具。
计算环境需求 💻

最后,本课程对您的计算环境有何要求?
我们假设您拥有一台可以访问互联网的基础台式机、笔记本电脑或能够使用这样的设备。这当然很重要,因为您需要观看这些精彩的视频。
除此之外,为了完成作业,您需要能够安装和运行Python。此外,您还需要能够存储几GB的数据。
总结 📝

本节课中,我们一起学习了华盛顿大学机器学习基础专项课程的定位。我们明确了课程旨在将复杂的机器学习概念变得直观且实用,适合具备基础数学和编程背景的软件工程师、科研人员和数据爱好者学习。课程要求学习者了解基础的微积分和线性代数,并能使用Python进行编程,同时需要准备好能够运行Python和存储数据的计算环境。希望您符合这些条件,并准备好开始这段学习旅程。
第一部分 8:你将能够做什么 🚀
在本节课中,我们将了解完成这门课程及整个专项课程后,你将能够运用机器学习实现哪些令人惊叹的应用。课程不仅关注最终成果,更强调在整个学习过程中逐步构建智能应用。

现在你已经了解了这门课程以及整个专项课程的内容概览。
你会发现,通过机器学习,你将能够实现令人惊叹的应用。
在整个学习过程中,你将构建真正智能的应用,而不仅仅是在课程结束时。
在整个专项课程中,你将构建非常酷的项目,并学习广泛的概念和算法。
第一门课程的核心是使用预先构建的机器学习算法来开发一系列智能应用。
后续的第二到第五门课程则深入探讨不同领域,详细讲解其背后的算法、方法和核心技术。
现在,让我们回到顶点项目的讨论。
顶点项目将非常令人兴奋,你将构建一个运用机器学习的、非常酷且令人印象深刻的应用。
课程内容与结构 📚
上一节我们概述了课程目标,本节我们来详细看看课程的具体安排和你能获得的技能。
以下是课程的核心组成部分:
- 第一门课程(基础篇):重点在于应用。你将学习如何使用现有的、强大的机器学习工具和库(例如
scikit-learn或TensorFlow中的高级API)来快速解决实际问题。 - 后续深入课程(第2-5门):这些课程将分模块深入机器学习的不同核心领域,如监督学习、无监督学习、深度学习等。你将不再只是调用API,而是深入理解算法背后的数学原理(例如梯度下降公式:
θ = θ - α · ∇J(θ))和实现细节。 - 顶点项目:这是整个专项课程的实践高潮。你需要综合运用所学知识,独立或协作完成一个完整的、有挑战性的机器学习项目,从而巩固你的技能并丰富你的作品集。
学习路径与收获 🎯
了解了课程结构后,我们来看看你的学习路径和最终能获得的成果。
以下是你将经历的学习旅程:
- 从应用到原理:你将从实际应用入手,快速获得成就感,再逐步深入到支撑这些应用的理论基础。
- 构建项目组合:在整个学习过程中,你会持续动手实践,积累一系列可以展示的项目。
- 掌握核心能力:最终,你将不仅知道如何使用机器学习算法,更能理解它们为何有效,以及如何根据问题选择和调整合适的算法。
总结

本节课中,我们一起学习了华盛顿大学机器学习专项课程(基础篇)的目标与结构。

我们明确了第一门课侧重于使用预建算法进行应用开发,后续课程将深入算法原理,而整个专项课程将以一个综合性的顶点项目作为终点。
通过这条学习路径,你将逐步获得构建智能机器学习应用所需的理论知识和实践技能。
第一部分 9:顶点项目与智能应用示例 🎯

在本节课中,我们将深入探讨一个顶点项目。我们将一起构建一个智能的产品推荐系统,该系统将结合文本、图像、情感分析和深度学习技术。
在详细介绍这个令人兴奋的顶点项目之前,我们先通过一个快速演示,来了解一个结合了文本与图像数据、并以深度学习为核心的推荐系统可以如何工作。
一个智能推荐应用的故事 📖
让我从一个故事开始。我的姐姐是一位时装设计师,她的生日即将到来,我想送她一条裙子作为礼物。但对我来说,选择一条她喜欢的裙子非常困难。
如果我使用标准的关键词搜索,比如搜索“裙子”,结果会像下图右侧所示,出现各式各样的裙子。我很难用语言描述我姐姐喜欢的裙子风格。






例如,我知道她穿过一些碎花裙。我可以组合关键词“裙子”和“碎花”进行搜索,系统会浏览裙子的描述来寻找碎花裙。但即使都是碎花裙,它们的风格也千差万别。
那么,问题来了:我该如何描述哪种风格适合我姐姐呢?
以这条裙子为例,它有着温暖的日落色调,看起来不错。我们可以通过文本分析来了解它的描述,但更重要的是它的视觉观感。问题是:我们能否利用视觉线索来找到其他看起来类似的裙子?
在你的顶点项目中,你将实现类似的功能。当我点击这条裙子时,系统将使用一种名为深度学习的技术来寻找视觉上相似的裙子。你将在本课程中学到这项技术,并在实践中应用它。

当我点击这条裙子后,右侧会显示一系列在视觉上与它相似的裙子。

你可以看到,这些裙子大多是碎花风格,色调和颜色也相似。即便如此,描述我姐姐的喜好仍然困难。但我可以看着中间这条裙子,觉得它的图案有趣、颜色多样,也许这正是我姐姐喜欢的。

如果我点击它,系统会继续寻找与这条裙子视觉相似的款式,这些裙子通常拥有更有趣的图案和多种颜色。当我滚动浏览时,可能会被某一条吸引,觉得它很适合我姐姐。




我可能会想:“我为你找到了一条很棒的裙子,就是这条。”
需求的变化与探索 🔄
假设我打电话给姐姐,她看起来有点像这位模特。她看了之后说:“这条看起来还行,但我要去参加一个鸡尾酒会,你不如帮我找一条鸡尾酒裙吧?”
于是我需要重新开始,为她寻找一条鸡尾酒裙。




鸡尾酒裙是参加正式派对时穿的,看起来像这样,有各种颜色。也许她对黑色的鸡尾酒裙感兴趣。
如果仅基于“黑色鸡尾酒裙”这样的关键词搜索,会得到类似的结果,但仍然难以描述她的具体喜好。我可能会问她,她说:“我想要一条有趣、带一点颜色的鸡尾酒裙。”

作为一名时装设计师,她会如何描述呢?我浏览结果,发现左边第一条裙子有点意思。查看它的关联关键词,我看到了“爵士风”这个词。也许她对爵士风格的裙子感兴趣。
那么爵士风的裙子是什么样的呢?当我点击这个从文本中发现的“爵士风”关键词时,会看到其他爵士风裙子,它们很有趣,但又不完全是鸡尾酒裙的风格。
让我点击其中一条,然后寻找视觉上相似的鸡尾酒裙。

现在你看到的是一系列鸡尾酒裙,它们往往带有更有趣的图案。这些裙子更特别,更符合她的描述。
如果我滚动浏览:


我觉得这条蓝色的,中间带些颜色的,可能就是她想要的。我点击它,但发现它对于鸡尾酒会来说不够正式。不过,当我向下滚动时:


我可以找到像这样一条裙子:它足够正式,符合鸡尾酒裙的要求,带有一点颜色,设计有趣,很可能正是她会喜欢穿的那种。


至此,我们看到了一个智能应用的示例,它分析文本数据、图像数据,运用深度学习,完成了一些非常酷且有趣的事情。
你的顶点项目:构建更强大的系统 🚀

我们刚刚看到了一个用于视觉产品推荐的深度学习演示。但在你的顶点项目中,你将完成更酷、更有趣的任务。
你将综合运用在本课程中学到的多种技术来构建推荐系统:
以下是你在项目中将要完成的核心任务列表:
- 构建推荐系统:搭建一个完整的推荐系统框架。
- 进行文本分析:处理和分析产品相关的文本信息。
- 实施情感分析:提取并分析用户对产品的评论,理解其中的情感倾向。
- 运用计算机视觉:从视觉上理解产品图像。
- 应用深度学习:利用深度学习技术,大幅提升计算机视觉任务的准确性。
- 部署为Web服务:将你的系统部署成一个类似我刚才演示的网页那样的Web服务。
最终,你将拥有属于自己的智能产品推荐Web服务。你可以与之交互,完成有趣的推荐任务,并向众人展示你是如何为这项服务创造智能的。

总结 📝

本节课中,我们一起探讨了顶点项目的构想。我们通过一个为姐姐挑选裙子的故事,演示了一个结合文本、图像和深度学习的智能推荐应用是如何工作的。我们了解到,仅靠关键词搜索的局限性,以及利用视觉相似性和深度学习进行探索的强大之处。最后,我们概述了你在顶点项目中将要完成的任务:构建一个集推荐系统、文本分析、情感分析、计算机视觉和深度学习于一体的完整智能Web服务。这将是展示你机器学习技能的综合实践。
第一部分 10:智能应用的未来 🚀

在本节课中,我们将要学习机器学习在当今世界中的广泛应用,并了解掌握其基础知识如何让你为未来的技术发展做好准备。

如今是学习机器学习专业知识的绝佳时机,因为机器学习已遍布我们日常生活的各个角落。
例如,我的手机里装满了各种智能应用,这些应用会根据我作为用户的习惯进行个性化推荐。

这些应用的核心都在使用机器学习技术。如今,几乎每次你访问一个网站,背后都可能有一个机器学习算法在运行,分析数据,分析用户交互,并真正利用机器学习改变用户体验。
我们看到机器学习正被应用于极其广泛的场景中。它不仅存在于我的手机上,还存在于像可穿戴设备这样的硬件中。这类设备可以追踪我的活动、分析我的睡眠和锻炼习惯,收集我的行为数据,理解这些数据,并帮助我观察自己的健康状况如何随时间演变。

因此,思考机器学习的现状是令人兴奋的。当然,机器学习在我们的生活中还有更多可能性。
你可以看到世界正在因机器学习而改变:自动驾驶汽车、个性化医疗、物联网(我们在各处嵌入传感器)、无处不在的智能系统。
在本系列课程中,你将学习实现所有这些应用的基础知识。事实上,完成本系列课程后,你将能够面向未来,为未来做好准备,你将“未来化”,你将成为机器学习的未来。
这很酷。事实上,你确实是未来,因为我们是在过去录制的这段内容,所以这实际上是真的,这也很酷。
显然,有人还在观看和阅读,主要是看了太多科幻片。你看过未来的剧集吗?你看过《神秘博士》的最新一季吗?很酷。
无论如何,基于以上所述,这很酷,这将是一个非常酷的系列课程。让我们开始吧。




本节课中,我们一起学习了机器学习在当今智能应用中的核心作用及其塑造未来的巨大潜力。从手机个性化推荐到健康追踪设备,再到自动驾驶和物联网,机器学习技术正驱动着各行各业的变革。掌握机器学习的基础知识,是理解和参与构建这个智能未来的关键第一步。
第一部分 100:深度学习的挑战 🧠


在本节课中,我们将探讨深度学习,特别是神经网络,在带来革命性成果的同时所面临的主要挑战。我们将了解其工作流程、优势以及实际应用中需要克服的困难。
神经网络确实能提供令人兴奋的成果,但它们也伴随着一些挑战。
在优势方面,神经网络使你能够表示这些非线性的复杂特征,并取得令人印象深刻的结果。这不仅体现在计算机视觉领域,还体现在其他一些领域,如语音识别。例如,手机上的Siri等系统在幕后也使用深度神经网络,以及一些文本分析任务。它在更广泛的领域具有产生更大影响的潜力。
现在,它们确实带来了一些挑战。为了理解这些挑战,我们需要讨论训练神经网络的工作流程。
你需要从海量的数据开始,并且这些数据必须被标注。每张图像都必须知道其中是什么狗:是拉布拉多犬、贵宾犬、金毛寻回犬,还是吉娃娃等等。这需要大量的人工标注,可能很困难。我们从大量图像开始,将其分割成我们讨论过的训练集和测试集(或验证集)。然后我们学习一个深度神经网络,这可能要花费相当长的时间。一旦我们进行验证,可能会意识到那个拥有6000万个参数的复杂八层结构并不完全是我们所需要的。我们需要修改它,或者需要调整参数,改变学习方式,并且必须一次又一次地迭代。
事实上,为了获得那个获胜的神经网络(即AlexNet),他们确实需要连接具有不同表示形式的各层,并在学习算法中加入大量复杂性,所以这很困难。

因此,尽管神经网络(深度神经网络)有一些巨大的优点,但它们也伴随着一些缺点。它们需要大量数据才能获得出色的性能。即使在有GPU的情况下,它们的计算成本也很高,并且极难调优。你在使用什么层、使用多少层或参数方面有很多选择,这可能相当困难。
所以,如果你将计算选择和成本与如此多需要调优的因素结合起来,最终会得到一个极其困难的过程,用于确定该使用什么样的神经网络。
本节课总结
本节课中,我们一起学习了深度学习的双面性。我们了解到,神经网络虽然能建模复杂特征并在多个领域取得突破,但其成功依赖于海量的标注数据、高昂的计算成本以及极其复杂的模型调优过程。这些挑战使得设计和训练一个有效的深度神经网络成为一个需要反复迭代和大量资源的艰巨任务。
第一部分 101:深度特征 🧠

在本节课中,我们将要学习深度特征的概念。这是一种强大的技术,它允许我们在数据量有限的情况下,依然能够构建高性能的神经网络模型。


我们已经了解到,深度神经网络非常强大,并且能达到很高的准确度。但是,构建和训练它们通常非常困难,并且需要海量的数据。
接下来,我们将探讨一个令人兴奋的概念——深度特征。它让你即使在数据不多的情况下,也能构建有效的神经网络。

从传统流程到新思路 🔄
回顾我们标准的图像分类流程:从一张图片开始,我们检测并提取一些特征,然后将这些特征输入到一个简单的分类器(如线性分类器)中。
这里的问题是:我们能否利用神经网络学习到的那些特征——那些能够识别角、边甚至人脸的强大特征——来“喂养”这个简单的分类器呢?
我们可以尝试一种不同的方法。这个想法,即深度特征的核心,被称为迁移学习。
理解迁移学习 🧳

迁移学习是一个存在已久的概念,但近年来在深度神经网络领域产生了巨大影响。
其核心思想是:我先在一个拥有大量数据的任务上训练一个神经网络。例如,在一个区分猫和狗的任务中,我训练了一个有8层、6000万个参数的复杂神经网络,并在此任务上获得了极高的准确度。
现在,有趣的部分来了:如果我有一个新任务(例如,检测椅子、大象、汽车、相机等上百个类别),但只有少量数据,我该怎么办?
我们能否利用从“猫狗分类”任务中学到的特征,结合一个简单的分类器,来在这个新的101个类别的任务上获得高准确度呢?这就是迁移学习的理念:从一个任务(猫狗分类)中学到的特征,被迁移到新任务(检测大象、相机等)中,以提升其性能。
深度网络学什么?🔍
为了理解迁移学习在深度神经网络中如何工作,我们先回顾一下深度网络可能学习到的内容。
假设我们有一个用于猫狗分类的深度神经网络。如果我们观察网络的最后几层,它们会高度专注于“猫 vs 狗”这个具体任务,就像之前例子中最后一层专门检测“珊瑚”一样。
然而,网络中间层的特征则更为通用。它们可以表示角、边、圆形、曲线等模式。这些通用特征能够从“猫狗分类”任务,很好地泛化到更通用的“101个类别”任务中。
如何应用迁移学习?⚙️
那么,我们如何将已训练好的猫狗分类网络,应用到第二个“101个类别”的任务上呢?
考虑到网络的末端部分(最后几层)非常特定于“猫狗”任务,对检测“椅子”可能没什么用。因此,我们可以这样做:“砍掉” 网络的最后几层(比如最后一层),并固定前面几层的权重,因为这些层已经学会了很好的通用特征。

然后,我们将这些固定层输出的特征(即深度特征),输入到一个新的、简单的线性分类器中。这个新分类器很简单,因此我们只需要用新任务(椅子、汽车、大象等)的少量数据来训练它即可。
用公式表示,新模型的预测过程为:
预测结果 = 新分类器( 固定深度网络的前N层(输入图像) )
构建基于深度特征的流程 📊
现在我们已经理解了迁移学习的概念,让我们回顾一下深度学习流程,但这次使用深度特征。
以下是构建流程的步骤:

- 准备少量标注数据:为新任务收集一些标注数据,不需要海量,少量即可。
- 提取深度特征:使用预训练好的深度神经网络(如砍掉最后几层的网络)来处理你的数据,提取出深度特征。
- 划分数据集:将带有深度特征的数据集划分为训练集和验证集(或测试集)。
- 训练简单分类器:在训练集上学习一个简单的分类器,例如线性分类器、支持向量机或线性回归。
- 验证与评估:在验证集上评估这个简单分类器的性能。
由于这是一个参数很少的简单分类器,用少量数据就能训练得很好,并且很容易调优。事实上,这种思想在许多应用中效果极佳。在本模块开头的演示中,那个帮你选购新裙子的应用,正是运用了这个理念。我们没有大量关于裙子视觉描述的数据,但我们使用了在ImageNet上训练好的模型提供的特征,来为你提供良好的购物体验。
深度特征有多通用?🌍

我们可能会问:这些深度特征到底有多通用?它们真的能用于各种有趣甚至非常规的任务吗?答案是肯定的,结果可能会让你惊讶。
让我们来谈谈垃圾。有一家叫Compology的公司,他们正在尝试革新垃圾收集的方式。传统上,垃圾车每天或每周定期挨家挨户、逐个商铺地收集垃圾。他们希望通过优化垃圾车的路径和收集方式来减少时间消耗。

他们的做法是在垃圾桶上安装摄像头,以判断里面有什么以及有多满。然而,他们并没有大量关于“满垃圾桶”是什么样子的标注数据。于是,他们使用了深度特征,并结合少量由人工标记的垃圾桶满溢程度数据,训练出了一个垃圾检测器。这使他们能够优化垃圾车的路径,从而更高效地服务,减少收集垃圾所需的时间。
由此可见,深度特征的应用非常广泛,甚至对处理垃圾也有用。
总结 📝
本节课中,我们一起学习了深度特征与迁移学习。
- 我们了解到,深度神经网络的前几层学习到的是通用特征(如边、角),这些特征可以迁移到其他视觉任务中。
- 通过“砍掉”预训练网络的最后几层(任务特定层),并固定前面层的权重,我们可以提取出强大的深度特征。
- 将这些深度特征输入到一个新的、简单的分类器中,即使用于新任务的数据量很少,我们也能构建出高性能的模型。
- 深度特征的通用性极强,能够应用于从图像分类到工业优化等各种不同的领域。
掌握深度特征,是让你在有限数据条件下也能利用深度学习强大能力的关键一步。
第一部分 102:深度学习模块图解析 🧠

在本节课中,我们将学习深度学习在计算机视觉任务中的应用,特别是如何利用深度特征进行图像分类。我们将回顾一个总结回归、分类及其他机器学习任务的模块图,并探讨其在深度学习和计算机视觉中的具体应用。

深度特征与图像分类 🖼️
上一节我们介绍了深度学习在图像分析中的广泛应用及其高精度表现。本节中,我们来看看如何利用深度特征进行图像分类。
输入数据是图像及其标签的配对。标签表示图像中的对象类别,例如猫、狗、房屋或其他物体。
以下是处理流程:
- 特征提取:使用深度学习模型作为特征提取器,处理输入图像。
- 特征输出:为每张图像生成一组“深度特征”。
- 分类模型:将深度特征输入一个机器学习模型,例如逻辑回归分类器。
- 预测输出:模型输出预测的标签。
- 质量评估:将预测标签
Y_hat与真实标签Y进行比较,使用分类准确率等指标评估模型质量。 - 参数优化:模型参数
W_hat(即逻辑回归的权重)通过机器学习算法进行调整,目标是提高分类准确率。
核心公式与代码描述:
- 逻辑回归示例:
Y_hat = sigmoid(W_hat * X + b),其中X代表深度特征。 - 质量评估(分类准确率):
accuracy = (number of correct predictions) / (total number of predictions)
总结与展望 🚀

本节课中,我们一起学习了深度学习在计算机视觉任务中的强大能力。我们看到了如何将深度神经网络和深度特征应用于图像分类与检索,并通过实践了解到构建此类模型并应用于实际任务(例如寻找特定款式的鞋子)是相对直接的。
掌握这些知识后,你将能够构建令人兴奋的智能应用程序,运用当今机器学习领域最受追捧的技术之一——深度学习。
第一部分 103:使用深度特征进行图像分类 🖼️

在本节课中,我们将学习如何利用深度特征进行图像分类。我们将加载一个图像数据集,探索其内容,并了解如何为后续的分类任务准备数据。

加载图像数据

上一节我们介绍了深度学习的两个应用:图像分类和图像检索。本节中,我们来看看如何为图像分类任务加载和准备数据。
首先,我们需要导入必要的库并加载数据集。
import graphlab
以下是加载数据集的步骤:
- 我们将使用一个名为CIFAR-10的基准数据集。
- 我们从中选择一个子集,只包含四个类别的物体。
- 该数据集已预先分为训练集和测试集,这是计算机视觉领域的常见做法,以确保研究结果的可比性。
# 加载训练数据
image_train = graphlab.SFrame(‘train_data’)
# 加载测试数据
image_test = graphlab.SFrame(‘test_data’)
探索数据集
数据加载完成后,我们需要对其内容有一个初步的了解。我们将配置可视化工具,以便在笔记本中直接查看图像。
# 设置画布目标为当前笔记本
graphlab.canvas.set_target(‘ipynb’)
现在,让我们查看训练数据。我们主要关注的是包含图像数据的列。
# 显示训练数据中的图像列
image_train[‘image’].show()
为了更清晰地查看图像,我们可以临时调整显示设置。观察图像,我们可以看到数据集中包含鸟、猫、狗和汽车这四类物体。
总结


本节课中我们一起学习了图像分类任务的第一步:加载和探索图像数据集。我们导入了GraphLab Create库,加载了CIFAR-10数据集的子集,并初步查看了其中的图像内容。这些数据将作为我们后续构建图像分类模型的基础。
第一部分 104:使用原始图像像素训练并评估分类器 🖼️🔍

在本节课中,我们将学习如何使用图像的原始像素值作为特征,来训练一个基础的分类器,并评估其性能。我们将使用逻辑回归模型,并在CIFAR-10数据集的一个子集上进行实践。
训练基于原始像素的分类器
上一节我们介绍了数据集。本节中,我们来看看如何使用最基础的图像信息——原始像素——来构建一个分类模型。
我们首先不使用任何复杂的特征提取方法,而是直接将图像的像素值作为特征输入分类器。我们将训练一个逻辑回归分类器。
以下是训练分类器的步骤:
- 准备数据:使用训练数据集
image_train。 - 指定目标:目标变量是数据集中的
label列,它包含了每张图像的标签。 - 指定特征:特征数据是
image_array列,它存储了图像的原始像素数组。 - 创建模型:使用
graphlab.logistic_classifier.create()函数来创建逻辑回归分类器。
对应的核心代码如下:
raw_pixel_model = graphlab.logistic_classifier.create(
dataset=image_train,
target='label',
features=['image_array']
)
我们称这个模型为原始像素模型。执行这段代码后,模型就训练完成了。但需要提醒的是,我们预期仅使用原始像素的分类性能不会很高。
对模型进行预测
模型训练完成后,我们可以用它来进行预测。让我们看看它在测试集的前几张图片上表现如何。
我们从测试集 image_test 中选取前三张图像进行可视化,并查看它们的真实标签。
以下是操作步骤:
- 选取测试集的前三张图像:
image_test[0:3]['image']。 - 调用
.show()方法显示这些图像。可以看到,它们分别是一只猫、一辆汽车和另一只猫。 - 查看这些图像对应的真实标签:
image_test[0:3]['label']。确认标签是“猫”、“汽车”、“猫”。
现在,让我们使用训练好的原始像素模型对这三张图像进行预测:
raw_pixel_model.predict(image_test[0:3])
预测结果是“鸟”、“猫”、“鸟”。与真实标签(猫、汽车、猫)对比,模型将两只猫都预测成了鸟,将汽车预测成了猫,三张图片全部预测错误。
当然,这只是对少数样本的定性观察,可能存在偶然性。为了全面评估模型性能,我们需要进行定量分析。
在测试集上评估模型
为了获得模型性能的客观度量,我们需要在整个测试集上对其进行评估。
我们使用模型的 .evaluate() 方法,传入测试数据集 image_test。这个方法会计算包括准确率在内的多种评估指标。
核心评估代码如下:
raw_pixel_model.evaluate(image_test)
评估结果显示,模型的分类准确率仅为 46.8%。考虑到我们处理的是4分类问题(数据子集),随机猜测的准确率是25%。虽然模型表现优于随机猜测,但46.8%的准确率仍然非常不理想。
评估输出中还包含了混淆矩阵等更详细的信息,可供进一步分析。但核心结论是明确的:仅使用原始像素特征,分类器的性能有限。

课程总结

本节课中我们一起学习了如何使用图像的原始像素值作为特征来训练一个逻辑回归分类器。我们完成了从模型训练、样本预测到整体评估的完整流程。

实践表明,在这个图像分类任务上,原始像素模型仅取得了46.8%的测试准确率。这说明了对于像图像这样的复杂数据,直接使用原始像素作为特征信息可能不够有效,为后续课程中引入更高级的特征提取方法(如深度学习特征)做好了铺垫。
第一部分 105:使用深度特征训练并评估分类器 🧠

在本节课中,我们将学习如何利用深度特征来改进图像分类模型。我们将使用一个在大型数据集上预训练好的深度学习模型,将其应用到我们的小型数据集上,并训练一个分类器来评估性能的提升。
概述
上一节我们介绍了使用原始像素特征训练分类器的方法,但其准确率有限。本节中,我们来看看如何利用迁移学习的思想,使用一个在大规模数据集(如ImageNet)上预训练好的深度神经网络来提取深度特征,并用这些特征在我们的小型数据集上训练一个更强大的分类器。
加载预训练模型
首先,我们需要加载一个预训练的深度学习模型。这里我们使用一个在ImageNet数据集上训练好的模型,该数据集包含150万张图像和1000个类别。
# 加载预训练模型
pretrained_model = graphlab.load_model('Imagenet_model')
这个模型(例如著名的AlexNet)在2012年的ImageNet竞赛中取得了突破性成果。我们将其作为特征提取器使用。
为数据提取深度特征
接下来,我们将使用这个预训练模型为我们的训练数据集提取深度特征。我们的训练集image_train只有2000张图像,数据量较小。
以下是提取深度特征的两个核心步骤:
# 为训练图像提取深度特征
image_train['deep_features'] = pretrained_model.extract_features(image_train)
这段代码将预训练模型应用到我们的CFR-10数据集上,并在image_train数据框中创建一个名为deep_features的新列。该列包含了每张图像的高层抽象特征。这个过程可能需要几分钟的计算时间。为了节省时间,本教程中我们使用预先计算并保存好的特征数据。
现在,如果我们查看image_train数据框的前几行,会看到除了image_id、image、label和原始的image_array(像素值)外,还多了一个deep_features列。
使用深度特征训练分类器
现在我们已经有了深度特征,可以开始训练一个新的分类器了。我们将使用逻辑回归模型,但这次的特征输入是深度特征,而不是原始像素。
# 使用深度特征训练逻辑回归分类器
deep_features_model = graphlab.logistic_classifier.create(
image_train,
features=['deep_features'],
target='label'
)
这段代码创建了一个新的分类器deep_features_model。它接收image_train数据,使用deep_features列作为特征,并预测label列作为目标。
评估深度特征模型
为了评估新模型的性能,我们首先在测试集的前几个样本上做一个快速测试。
# 获取测试集前三张图像
sample_test_images = image_test[0:3]
# 使用深度特征模型进行预测
predictions = deep_features_model.predict(sample_test_images)
之前使用原始像素模型时,这三张图像(猫、汽车、猫)的分类效果可能不理想。现在,使用深度特征模型,预测结果很可能是完全正确的(猫、汽车、猫)。
然而,我们需要更正式地评估模型在整个测试集上的性能。
# 在完整测试集上评估模型
deep_features_accuracy = deep_features_model.evaluate(image_test)
之前使用原始像素特征的逻辑回归模型准确率约为46%。使用深度特征后,我们的新模型准确率提升到了78%。这个结果非常出色,已经接近当前最优水平,并且相比46%的基线有了巨大提升。
总结
本节课中,我们一起学习了如何利用迁移学习和深度特征来显著提升图像分类器的性能。关键步骤包括:
- 加载预训练模型:使用在大规模数据集上训练好的深度神经网络。
- 提取深度特征:将预训练模型作为特征提取器,应用于我们的小型数据集。
- 训练新分类器:使用提取出的深度特征,而非原始像素,来训练一个简单的分类器(如逻辑回归)。
- 评估性能:新模型在测试集上取得了远高于原始像素模型的准确率。

这种方法的核心优势在于,即使我们只有少量标注数据(如2000张图像),也能通过利用在大数据上学到的通用视觉特征,构建出强大的分类模型。深度特征为图像分类任务提供了一个极其有效的工具。
第一部分 106:图像检索:使用深度特征 🔍

在本节课中,我们将学习如何利用深度特征进行图像检索,而不仅仅是图像分类。我们将使用一个预先计算好深度特征的数据集,来寻找与给定图像相似的其他图像。
从分类到检索:深度特征的新应用
上一节我们介绍了深度特征在图像分类任务中的强大表现。它允许我们在特定分类任务上,即使只有少量训练数据,也能获得相当高的准确率。这些特征源自赢得了2012年ImageNet竞赛的深度学习模型。
但如果你还记得本模块开始时提到的动机和示例用例,我们的目标是寻找我喜欢的图像或产品。例如,我喜欢鞋子,我想找到与我的鞋子相似的鞋子,或者找到与我关心的产品相似的图像。

因此,我们现在不再进行图像分类任务,而是要利用这些深度特征来完成图像检索任务。接下来,让我们开始实践。

准备环境与数据
我们将命名我们的笔记本,主题是“深度特征用于图像检索”。为了获得更多空间,我们将隐藏页眉和工具栏。然后,启动GraphLab Create并加载数据集。
以下是加载数据的步骤:
- 加载我们之前讨论深度特征分类时使用的相同数据集。
- 在本例中,我们只加载训练集,因为我们将专注于检索任务。
- 我们将这个SFrame命名为
image_train。
import graphlab
image_train = graphlab.SFrame('image_train_data')
作为一个小提示,如果我们查看这个 image_train 数据集的前几行,会发现它包含以下列:
image: 实际图像。label: 图像的标签。在检索任务中,我们完全不会使用这个标签。image_array: 图像的像素数组。同样,我们也不会直接使用它。deep_features: 预先计算好的深度特征。在关于深度特征分类的笔记本中,我们看过计算这个特征列所需的代码行。这里,我们将直接使用这些现成的深度特征。
总结


本节课中,我们一起学习了如何将深度特征的应用从图像分类扩展到图像检索。我们准备了实验环境,加载了包含预计算深度特征的数据集,并明确了在检索任务中我们将使用哪些数据列。接下来,我们就可以利用这些深度特征来寻找相似的图像了。
第一部分 107:创建用于图像检索的最近邻模型 📚
在本节课中,我们将学习如何构建一个用于图像检索的最近邻模型。我们将使用深度特征来代表图像,并通过计算特征之间的相似度,快速找到与给定查询图像最相似的图像。

概述与目标 🎯
上一节我们介绍了文档检索的基本概念。本节中,我们来看看如何将类似的方法应用于图像数据。
我们的目标是训练一个最近邻模型,用于基于深度特征检索相似的图像。这个过程与我们之前为巴拉克·奥巴马、克林顿、贝克汉姆等人查找相似文档的笔记本非常相似。
核心步骤与方法 ⚙️
我们将使用一个名为 K最近邻(K-NN)模型 的方法,就像在文档检索中所做的那样。以下是实现此模型的核心步骤:
- 准备数据:我们将使用训练数据,其中每张图像都已提取了深度特征。
- 构建模型:利用
GraphLab Create库中的最近邻工具来创建模型。 - 配置模型:指定使用哪些特征(这里就是深度特征)以及一个标签ID,以便我们能回溯找到对应的原始图像。
以下是创建模型的核心代码描述:
# 伪代码示例:创建最近邻模型
model = graphlab.nearest_neighbors.create(training_data,
features=['deep_feature'],
label='image_id')
在这段代码中:
training_data是包含图像深度特征的数据集。features=[‘deep_feature’]指定模型使用名为“deep_feature”的列作为比较依据。label=‘image_id’指定图像的唯一标识符,用于后续检索对应图像。
实现细节 📝
现在,让我们详细拆解每个部分。
首先,我们需要训练数据。这些数据中的每张图像都已经通过一个深度神经网络转换为一组数值向量,即“深度特征”。这些特征能有效捕捉图像的高级语义内容。
接下来,我们调用创建函数来实际构建这个最近邻模型。与文档检索模型类似,我们需要向它提供数据。在本例中,就是我们的训练数据。我们还需要告诉它使用哪些特征,这里我们将明确使用那些深度特征。
最后,作为一个重要提醒,你可以为模型指定一个标签ID。这里的标签,我们将使用图像ID。这样,当我们找到最近的邻居(即最相似的图像)时,就能通过这个ID回溯并找到对应的原始图像文件。
总结与回顾 📖
本节课中,我们一起学习了如何为图像检索创建一个最近邻模型。
我们回顾了该方法与文档检索的相似性,明确了使用深度特征作为图像表示的核心思想,并了解了构建K-NN模型的关键步骤:准备带特征的数据、利用库函数创建模型、并通过设置label参数来确保结果的可追溯性。

通过这个模型,我们能够高效地根据图像内容进行相似性搜索,这是许多图像应用(如以图搜图、产品推荐)的基础。
第一部分 108:使用最近邻模型检索相似图像 🖼️🔍

在本节课中,我们将学习如何利用已训练的最近邻模型,根据深度特征来检索与给定查询图像相似的图像。我们将通过一个具体的例子——查找与一张猫图片相似的图像——来演示整个过程。
模型应用概述
上一节我们介绍了如何构建和训练最近邻模型。本节中,我们来看看如何实际使用这个模型进行图像检索。
现在我们可以使用这个基于深度特征的图像检索模型来寻找相似的图像。
步骤一:选择查询图像
首先,我们需要从训练数据集中选择一张特定的图像作为查询起点。以下是具体操作:
- 我们从图像训练数据中选取第18张图像。
- 为了明确其内容,我们使用
cat_image.show()来显示这张图像。 - 我们将画布目标设置为在笔记本中显示。
执行上述操作后,我们得到了一张猫的图片。对于熟悉猫品种的人来说,这是一只虎斑猫。图片尺寸虽小,但足以识别。
步骤二:查询最近邻
现在,我们可以为这张猫图片寻找最近的邻居(即最相似的图像)。
我们使用训练好的K最近邻模型,并以猫图片作为输入进行查询。查询完成后,模型会返回一系列图像的索引编号,例如384、690、60、910等。
然而,仅凭这些数字索引很难直观地看到对应的图像。因此,我们需要一个辅助函数来将这些索引转换为实际的图像进行展示。
步骤三:创建图像检索辅助函数
为了便于查看结果,我们将共同创建一个新的Python函数。这个函数的作用是根据查询返回的索引ID列表,从数据表中获取对应的图像数据。
我们将这个函数命名为 get_images_from_ids。它的工作原理如下:
- 输入参数是查询结果(即索引ID列表)。
- 函数内部对训练数据表进行操作,使用
filter_by方法筛选出那些行ID与查询结果中reference_label列相匹配的数据行。 - 最终,函数返回所有匹配ID的图像数据。
定义这个函数后,我们就不必每次都手动执行这些步骤了。
步骤四:显示相似图像结果
让我们使用这个新函数来获取并显示猫的相似图像。
我们调用 get_images_from_ids 函数,并将KNN模型对猫图片的查询结果作为输入。我们将返回的结果存储在变量 cat_neighbors 中。
最后,我们通过 cat_neighbors[‘image’].show() 来展示这些相似的图像。结果显示,与输入猫图片最接近的图像都是猫,并且很多都是类似的虎斑猫。
课程总结

本节课中,我们一起学习了如何应用最近邻模型进行图像检索。我们完成了从选择查询图像、执行模型查询,到创建辅助函数并可视化相似结果的全过程。通过这个实践,你掌握了利用预训练模型根据内容寻找相似图像的基本方法。
109:查询与汽车图像最相似的图像 🚗

在本节课中,我们将学习如何利用已构建的辅助函数,为一张新的汽车图像查找其最相似的图像(即“最近邻”图像)。我们将通过一个具体示例,演示从查询图像到获取相似图像的完整流程。
上一节我们介绍了辅助函数的创建,本节中我们来看看如何将这些函数应用于另一张图像。
这里我使用了一张汽车图像进行演示。该图像来自训练集,是其中的第八张图像。为了明确查询对象,我们首先查看这张汽车图像。
以下是加载并显示该汽车图像的代码:
car_image = image_train[8]
car_image.show()
如图所示,这是一辆红色汽车。
接下来的问题是:这辆红色汽车的最近邻图像有哪些?我们可以使用之前定义的 get_images_from_ids 函数进行查询。但为了更直接地演示,这里采用一个简化的方法。
以下是查询最近邻图像的代码:
nearest_neighbors = model.query(car_image)
similar_images = nearest_neighbors['image']
similar_images.show()
执行上述代码后,我们可以看到输入图像(红色汽车)及其最近邻图像。结果显示,系统成功找到了一系列红色汽车作为最相似的图像。
通过短短几行代码,我们便完成了针对汽车和猫咪图像的最近邻搜索示例,这展示了该方法的简洁与高效。

本节课中我们一起学习了如何查询指定图像的最近邻图像。我们加载了一张汽车图像,利用模型进行查询,并成功获取并展示了一系列相似的红色汽车图像。这个过程展示了最近邻算法在图像检索中的直观应用。
第一部分 11:启动与使用Jupyter Notebook 🚀

在本节课中,我们将学习两种用于编程机器学习算法和数据科学的强大工具:Python编程语言和Jupyter Notebook。我们将从启动Jupyter Notebook开始,逐步了解其界面和基本功能,并编写第一个Python程序。
启动Jupyter Notebook
上一节我们介绍了本课程将使用的核心工具。本节中,我们来看看如何启动Jupyter Notebook。
假设你已经在系统中安装了Python。启动Jupyter Notebook后,你会看到一个类似文件浏览器的界面,其中列出了当前目录下的所有文件,包括数据文件和已有的笔记本文件。

要创建一个全新的笔记本,请选择“New” -> “Python 2”(或其他Python版本)。这个工具结合了Python脚本语言和Wiki页面的优点,使得编写算法和与他人交流变得非常方便。




认识Jupyter Notebook界面
现在我们已经创建了一个新笔记本,本节我们来熟悉其用户界面。
界面顶部是笔记本的标题,你可以点击它进行修改。例如,我们可以将其改为“Getting started with Python Notebook”。


这个笔记本就像一个Python控制台,但它允许你保存生成的页面,并在其中包含文本和图像。顶部菜单栏提供了保存、加载、编辑、复制和添加新单元格等功能。

编写第一个Python程序
了解了界面后,我们现在可以开始编写代码了。以下是创建和运行第一个Python程序的步骤。
首先,点击一个单元格(这类似于控制台中的一个输入行)。然后,输入你的第一个Python函数。我们将使用print函数来打印一个字符串。
print('Hello World')
要执行这个单元格,请按 Shift + Enter。执行后,单元格下方会显示输出结果:“Hello World”。
在笔记本中使用文本和Markdown
Jupyter Notebook的强大之处在于它能混合代码和格式丰富的文本。本节我们学习如何添加和格式化文本。
有两种方式可以创建文本单元格。第一种是点击菜单栏中的“Cell” -> “Cell Type” -> “Markdown”。然后,你可以在单元格中使用Markdown语法编写文本。
例如,输入以下内容可以创建标题和列表:
# Getting Started with Python
## What We Have Done So Far
我们已完成以下步骤:
* 安装了Python编程语言
* 启动了Jupyter Notebook
按 Enter 可以换行。要渲染Markdown文本,请按 Shift + Enter。之后,你将看到格式清晰的标题和项目符号列表。


总结


本节课中,我们一起学习了Jupyter Notebook的基本使用方法。我们启动了Jupyter Notebook,熟悉了其界面,编写并执行了第一个Python程序,还学会了如何使用Markdown单元格来添加格式化的文本说明。这些是使用Jupyter Notebook进行机器学习和数据科学项目的基础。
第一部分 119:使用Python Lambda函数进行图像检索示例 🖼️🔍

在本节课中,我们将学习如何利用Python的lambda函数和预训练的深度学习模型,构建一个简单的图像检索系统。我们将通过一个具体的例子,展示如何查询一张图片,并找到数据集中与它最相似的其他图片。
上一节我们介绍了如何使用深度学习特征进行基本的图像检索。本节中,我们将通过编写一个简洁的lambda函数,将这个流程封装起来,以便更灵活、便捷地对任意图片进行相似性查询。
以下是创建这个图像检索lambda函数的步骤:
- 定义函数:我们将创建一个名为
show_neighbors的lambda函数。 - 指定输入:该函数接受一个参数
i,代表数据集中某张图片的索引。 - 执行查询:在函数内部,它将执行我们之前见过的检索流程:获取查询图片的特征,并在特征空间中寻找其最近邻。
- 展示结果:最后,函数会调用一个展示函数,将查询图片及其最相似的邻居图片一并显示出来。
这个lambda函数的代码如下:
show_neighbors = lambda i: do_show_neighbors(get_images_from_ids(query=image_train[i:i+1]))
创建了这个函数后,我们可以用它进行一些有趣的尝试。现在,只需调用 show_neighbors 并传入图片索引,就能立即看到检索结果。
让我们用几个例子来测试这个函数。
首先,查询索引为8的图片(一辆红色汽车):
show_neighbors(8)
执行后,系统会返回并显示与这辆红色汽车最相似的其他图片。
接着,尝试查询索引为26的图片(一辆蓝色汽车):
show_neighbors(26)
结果会显示这辆蓝色汽车及其相似车辆。
然后,查询索引为1222的图片:
show_neighbors(1222)
这次查询的是一只鸟,系统成功地找到了其他姿态相似的鸟类图片。
最后,尝试查询索引为2000的图片:
show_neighbors(2000)
在这次查询中,系统出现了一次误判(将一只鸵鸟识别为汽车),但其余返回的图片都是正确的汽车类别。

本节课中我们一起学习了如何利用Python的lambda函数快速构建一个图像检索工具。通过封装检索流程,我们能够便捷地探索数据集中图片的相似性关系。尽管在少数例子中出现了误判,但基于深度特征的方法在未经目标数据集专门训练的情况下,依然展现出了令人印象深刻的检索性能。这项技术简单而强大,可以广泛应用于各种需要图像匹配和检索的场景。
第一部分 111:回顾与总结 🎯
在本节课中,我们将回顾并总结机器学习基础课程的核心内容,探讨如何将所学概念部署到实际生产系统中,并展望后续课程与机器学习领域的整体发展方向。

课程回顾与总结 📚
上一节我们介绍了课程的整体框架,本节中我们来看看本课程所涵盖的核心内容。
Emily和我衷心希望您到目前为止已经享受了这门课程。我们广泛探索了机器学习的基础知识,涉及多个领域和不同的应用场景。课程深入探讨了部署和构建机器学习系统时遇到的许多实际问题。
以下是本课程涵盖的主要领域:
- 监督学习与非监督学习的基本概念
- 特征工程与数据预处理
- 模型训练、评估与选择
- 过拟合与正则化等实际问题
部署机器学习系统 🚀
在掌握了基础概念后,下一步是了解如何将这些想法应用到实际的生产环境中。
在本课程的最后模块,我们将总结所学的一些核心概念,讨论如何将这些理念部署为生产环境中的机器学习系统。
部署过程通常涉及以下关键步骤:
- 模型固化:将训练好的模型保存为可复用的格式,例如使用
pickle或joblib库。import joblib joblib.dump(trained_model, 'model.pkl') - 构建预测服务:创建API或服务来接收新数据并返回模型预测结果。
- 监控与维护:持续监控模型在生产环境中的性能,并定期进行更新或重新训练。
展望未来 🔮
了解当前基础后,让我们看看机器学习领域的后续发展方向。
接下来,我们将探讨专项课程以及机器学习整体的未来前景。在结束这第一门课程时,有一些非常令人兴奋的内容。
机器学习领域正在快速发展,未来的重点可能包括:
- 自动化机器学习(AutoML):旨在自动化模型选择、超参数调优等过程。
- 可解释AI(XAI):提高复杂模型(如深度学习)的透明度和可理解性。
- 持续学习与在线学习:使模型能够适应不断变化的数据流。


总结 ✨
本节课中我们一起学习了机器学习基础课程的核心要点。我们回顾了从基础概念到实际应用的全过程,探讨了将模型部署到生产系统的关键步骤,并展望了机器学习领域充满潜力的未来发展方向。希望这些知识能为您后续的学习和实践打下坚实的基础。
第一部分 112:部署机器学习服务 🚀

在本节课中,我们将要学习如何将训练好的机器学习模型部署到实际应用中,使其能够实时地为用户提供预测服务。我们还将探讨如何评估模型在长期使用中的表现,以及如何管理和更新模型,确保其持续有效。
模型部署概述
到目前为止,我们主要讨论了如何使用数据构建机器学习模型、如何评估模型质量以及如何判断模型是否有效。然而,要构建一个智能应用,仅做到这些是不够的。当你构建智能应用时,你需要将训练好的模型真正地部署到生产环境中,例如,让公司网站的客户能够使用它来购买产品。那么,这个过程具体是怎样的呢?
模型部署涉及多个方面,我们称之为模型部署,即让模型能够实时提供预测。我们将详细讨论这一点。此外,我们还需要探讨如何评估模型,确保我们在离线训练阶段所做的工作在长期使用中仍然有效。

部署流程详解
上一节我们介绍了模型部署的基本概念,本节中我们来看看一个完整的部署系统是如何工作的。
考虑以下场景:你正在构建一个全新的产品推荐系统,使用了数百万条产品评论和用户数据。你希望在笔记本电脑、台式机或大型集群上训练好模型后,将其部署到与用户实时交互的网站上。这具体是怎样的过程呢?

整个系统始于一些历史数据,即你收集的关于系统用户的数据,包括他们写的评论、偏好等。我们利用这些数据训练模型,正如Emily在推荐系统模块中介绍的那样。
这个过程通常是在批量离线设置中完成的。你在本地机器或集群上训练模型,然后将其部署到云端,以便进行预测服务。这是系统的在线实时部分。
例如,如果你有一个网站,系统会实时获取用户当前的行为信息,例如他们正在浏览的页面、考虑购买的产品等。基于这些信息,系统会实时提供预测,比如“看看这个长颈鹿玩具,你可能现在就想购买”。用户看到这个推荐后,可能会购买,也可能不会。这种反馈(用户是否购买)将影响实时决策,并最终被收集为历史数据,用于长期改进模型。
随着我们从现实世界中收集越来越多的数据,模型也会不断优化。
这就是一个完整的机器学习部署系统可能的样子。
模型管理与持续改进
在部署模型后,我们还需要考虑所有的管理环节。以下是几个关键方面:
- 确保模型持续有效:我们需要监控模型的表现,确保其预测质量不会随时间下降。
- 模型更新与替换:当有更好的模型出现时,我们需要知道如何安全地替换旧模型。
- 监控与响应:我们需要定义并监控一系列指标,以判断模型是否仍然有效,或者是否需要重新从数据中学习。
所有这些环节并非孤立存在,而是相互关联、相互影响的。我们需要深入理解这些环节,并创建一个模型持续改进的循环。
总结

本节课中我们一起学习了机器学习模型部署的全过程。我们从构建和评估模型的基础出发,探讨了如何将模型部署到生产环境中进行实时预测服务。我们了解了部署系统的关键组成部分,包括离线训练、在线服务以及用户反馈的收集。最后,我们强调了模型持续管理和改进的重要性,确保模型能够长期有效地服务于应用。
通过本课的学习,你应该对如何将机器学习模型从开发环境推向实际应用有了更清晰的认识。记住,构建一个成功的智能应用不仅仅是训练一个准确的模型,更在于如何可靠、高效地部署和管理它。
第一部分 113:模型部署后会发生什么?🚀

在本节课中,我们将要学习机器学习模型部署到生产环境后,如何进行有效的管理、评估与监控。我们将探讨如何利用用户反馈更新模型,如何通过在线指标评估模型性能,以及如何在实际应用中做出模型更新的决策。

模型部署后的关键环节 🔄
上一节我们介绍了模型的初始部署过程。本节中我们来看看部署后需要关注的三个核心环节:模型管理、评估与监控。这些环节旨在确保我们训练的模型不仅能在离线测试中表现良好,还能在实际用户交互中持续提供价值。
模型部署并非终点,而是一个持续迭代过程的开始。我们需要收集用户反馈,利用这些信息训练新模型,并不断更新现有模型。
反馈循环与模型更新 🔁
回顾我们的机器学习流水线,它包含批处理与实时处理两个部分。用户反馈(例如是否购买了推荐的商品)会同时流入实时数据和历史数据中。
我们将利用这些反馈来学习新的模型。例如,在积累了更多历史数据后,我们可能会训练出第二个推荐模型(称为 Model 2)。此时,我们需要判断这个新模型是否优于原有的 Model 1,并决定是否将其投入生产环境。
以下是围绕生产环境模型管理的几个关键问题:
- 何时更新到 Model 2?
- 如何判断更新是否值得?
- 如何在多个模型间进行选择?
解决这些问题的核心在于监控生产环境中模型在真实用户中的表现,并理解用户的使用模式。
生产环境中的模型评估 📊
监控模型的关键在于生产环境中的模型评估。这需要将模型的预测结果与实时用户行为产生的指标相结合。
部署模型时,你需要明确以下问题:
- 你从用户那里收集哪些数据?(不仅是历史数据,还包括实时交互数据)
- 你将使用哪些指标来衡量交互效果?(例如,用户是否购买了商品,模型是否提升了用户参与度)
- 机器学习模型是否在你构建的系统中发挥了预期作用?
离线指标与在线指标 ⚖️
回顾推荐系统的例子,我们曾使用最小化均方误差作为离线训练模型的优化指标。
公式: MSE = (1/n) * Σ(实际值 - 预测值)²
然而,生产环境中我们真正关心的是在线指标,例如:
- 用户购买率
- 点击率
- 用户参与度
- 对业务核心指标的影响
离线指标用于优化和评估模型本身,而在线指标则用于判断新模型是否真的比旧模型更好,从而指导模型更新决策。
模型更新决策流程 🤔
核心问题是:我是否应该用基于新数据学习到的新模型来更新旧模型?
模型更新的原因可能包括:世界趋势变化、新产品出现、用户偏好改变(例如之前提到的“耐嚼长颈鹿”玩具不再流行)。
更新决策不应基于直觉,而应基于对现实世界统计数据的追踪。我们需要通过量化的数据来明确判断“情况已经改变,是时候更新模型了”。这个过程结合了用于训练模型的离线指标,但更依赖于我们捕获的在线指标。
使用在线指标选择模型:A/B 测试示例 🧪
一种利用在线指标在模型间做出选择的方法是 A/B 测试。
假设我们有两个模型:Model 1 和 Model 2。为了找出哪个更好,我们可以将部分用户(例如A组,如美国用户)分配给 Model 1,将另一部分用户(例如B组,如加拿大用户)分配给 Model 2。
然后,我们观察两组用户的行为并捕获指标(如点击率 CTR)。例如,Model 1 的点击率是 10%,而 Model 2 的点击率是 30%。在收集了足够的测试样本后,我们就可以决定在生产环境中全面启用表现更优的 Model 2。
模型管理的复杂性与重要性 ⚠️
我们目前讨论的A/B测试、模型切换时机、数据收集量等问题都包含许多其他注意事项和复杂性,需要深入思考。
此外,在实际场景中,通常会有多位数据科学家基于各自的想法训练多个模型版本。这就引出了以下管理挑战:
- 如何追踪不同模型使用了哪些数据进行训练?
- 如何追踪各模型的性能?
- 如何区分性能差异是源于数据本身的特性还是偶然波动?
- 如何通过监控面板和报告来了解机器学习系统的实际影响?
因此,对于机器学习从业者而言,不仅要关注算法使用、方法编写和特征选择,还必须思考如何有效追踪和管理模型,确保它们持续为所构建的系统提供价值。
总结 📝


本节课中我们一起学习了机器学习模型部署后的关键工作。我们了解到,部署只是开始,后续需要通过监控和评估(特别是基于真实用户行为的在线指标)来管理模型。我们探讨了利用反馈循环更新模型的必要性,并介绍了通过 A/B 测试 等方法来科学决策模型更新的流程。最后,我们认识到生产环境中的模型管理具有复杂性,需要建立系统的追踪和评估体系来确保机器学习应用持续创造价值。
第一部分 114:机器学习中的开放性挑战 🧠


在本节课中,我们将探讨机器学习领域目前面临的一些主要开放性挑战。尽管我们已经学习了许多机器学习方法和应用,但该领域仍存在许多未解决的问题和挑战。
模型选择难题 🤔
上一节我们介绍了多种机器学习方法,本节中我们来看看模型选择带来的挑战。在实际应用中,我们经常需要从众多可能的模型中选择一个。例如,在推荐产品时,我们可以使用分类模型,也可以使用矩阵分解模型,或者结合两者的特征化矩阵分解模型。
以下是几种可能的模型选择:
- 分类模型:
预测 = 分类器(用户特征, 产品特征) - 矩阵分解模型:通过学习用户和产品的潜在特征进行推荐。
- 特征化矩阵分解模型:结合了上述两种思路。
可供考虑的模型列表通常非常庞大,这使得实践者难以抉择。如何在这个庞大的可能选择集合中进行有效搜索,仍然是机器学习中的一个开放性挑战。
数据表示困境 📊
模型选择之后,我们面临的另一个核心挑战是如何表示数据。数据的表示方式会显著影响我们基于该数据做出的推断。
以文档建模和检索任务为例,我们有以下多种表示方式:
- 原始词频:直接计算单词出现的次数。
- 归一化向量:对词频向量进行标准化处理。
- TF-IDF变体:
TF-IDF = 词频(TF) × 逆文档频率(IDF),用于降低常见词的权重,提升重要词的权重。但TF-IDF本身存在许多不同的计算变体。
此外,我们还可以考虑使用二元组、三元组等更复杂的表示方法。对于图像、社交网络等不同类型的数据,如何找到有效的表示形式同样充满挑战。目前,还没有一种通用方法能为所有数据选择“正确”的表示形式。
大规模数据与模型的扩展性挑战 📈
随着数据量和模型复杂度的爆炸式增长,如何实现高效扩展成为机器学习的关键挑战。
数据规模的扩大
我们正面临数据量急剧增长的局面,数据来源日益多样化:
- 社交媒体与众包平台:人们通过分享照片、视频、评论等方式不断产生新数据。
- 在线市场:如亚马逊等电商平台收集了海量的产品、客户和交易数据。
- 可穿戴设备与物联网:智能手表、眼镜等设备持续监测并生成个人活动数据,各种互联设备也在不断交换信息。
- 电子健康记录:医疗记录数字化,形成了可供分析和利用的大规模数据集。
我们需要能够分析这些大规模、结构独特且可能含有噪声的数据集的方法。
模型复杂度的增加
为了从这些日益复杂和庞大的数据源中提取信息,模型本身也变得更大、更复杂。
例如,在分析随时间记录的大脑活动数据时,所使用的模型可能包含大量的节点和连接,结构非常复杂。这意味着我们需要更强大的计算能力来处理这些大模型。
计算资源的瓶颈与并行化


虽然数据模型都在变大,但单个处理器的速度提升在约十年前已趋于平缓,现在每年的增速非常有限。因此,我们必须寻找新的扩展途径。
当前主要依赖处理器集群,利用GPU、多核CPU、计算集群、云计算和超级计算机等资源。然而,这带来了新的挑战:
- 算法并行化:如何将机器学习算法有效地分布到不同的处理器上并协调运行。
- 数据分布:如何将数据分布到不同的机器上。
- 容错性:如何使整个系统能够容忍单个机器的故障。
这些都是在利用现代计算资源进行机器学习时亟待解决的问题。
总结 ✨
本节课中,我们一起学习了机器学习领域当前面临的几个核心开放性挑战:
- 模型选择:从众多可能模型中选择合适模型的困难。
- 数据表示:为不同类型数据寻找有效表示形式的复杂性。
- 扩展性:处理大规模数据、复杂模型时,在算法和计算架构上面临的扩展性与并行化挑战。


这些挑战既是当前研究的焦点,也预示着机器学习领域未来充满机遇的发展方向。
第一部分 115:机器学习的发展方向 🚀

在本节课中,我们将探讨机器学习的当前应用与未来发展方向。我们将从机器学习的普及现状出发,分析其在多个前沿领域的潜在应用,并讨论实现这些愿景所面临的技术挑战。
机器学习的现状 🌐
上一节我们回顾了机器学习的历史,本节中我们来看看它的现状。机器学习已深度融入日常生活。每次打开网页应用或使用手机时,其背后都有机器学习系统在运行。这些系统可能部署在本地设备,也可能由云端支持。
可穿戴设备是当前应用的典型例子。例如,智能手表能追踪用户活动,判断用户是在跑步、休息还是睡眠。所有这些功能都依赖于机器学习算法。

尽管应用广泛,但我们目前可能只触及了机器学习潜力的表面。
机器学习的未来方向 🔮


以下是机器学习几个关键的未来发展方向,每个方向都伴随着独特的机遇与挑战。
1. 自动驾驶汽车 🚗
自动驾驶技术是机器学习的一个重要应用领域。其核心目标是让车辆能够感知环境、做出决策并自主行驶。这涉及到复杂的计算机视觉、传感器融合和实时决策算法。
核心挑战包括处理复杂的道路环境、确保安全以及应对各种极端天气和光照条件。
2. 个性化医疗 🏥
当前医疗实践中,针对同一种疾病,不同患者往往接受相似的治疗方案。个性化医疗旨在改变这一现状。


其目标是基于每个人的独特信息定制治疗方案,这些信息包括:
- 生活方式
- 身体类型
- 基因构成(DNA)
然而,实现个性化医疗面临巨大挑战。医疗数据通常非常嘈杂且不完整,原因可能包括:
- 医生记录的主观性和差异性。
- 患者可能错过检查。
- 数据录入可能存在错误或不一致。
因此,未来的机器学习算法必须能够解析这些复杂、有噪声且不完整的数据,以实现精准的个性化治疗。
3. 高度个性化的体验 🌍



随着数据收集能力的增强和算法的进步,未来的技术将更加贴合个人需求。无论是网页浏览、购物还是其他服务,体验都将变得高度个性化。
这意味着技术将主动适应我们,而非让我们去适应技术,从而减少技术带来的困扰。
4. 实时多模态数据处理 ⚡
另一个激动人心的方向是处理实时、多模态的数据流。这不仅仅是重复现有的推荐任务,而是在更复杂、更快速的环境中进行。
这涉及到整合多种类型的数据,例如:
- 时序数据:随时间变化的数据。
- 空间数据:与位置相关的数据。
- 多模态数据:如图像、视频、音频和各种传感器数据。
核心挑战在于开发能够实时融合这些异构数据源并做出预测的新算法。这是一个当前非常活跃的研究领域。

5. 算法的可扩展性与易用性 🛠️
为了实现上述愿景,我们开发的机器学习方法必须具备以下特性:
- 可扩展性:能够处理海量数据集。
- 鲁棒性:对数据中的噪声和不完整性具有容错能力。
- 易用性:不应要求使用者必须具备机器学习博士学位。算法需要足够健壮和易用,让更广泛的开发者,即使没有深厚的理论背景,也能构建出智能的应用程序。这是让机器学习技术真正普及的关键。


总结 📝


本节课中我们一起学习了机器学习的现状与未来。我们看到,机器学习已无处不在,但其潜力远未完全发掘。未来,它将在自动驾驶、个性化医疗、定制化体验等领域发挥更大作用。同时,处理实时多模态数据、提升算法的可扩展性与易用性,是推动这些发展必须克服的核心技术挑战。机器学习的未来充满机遇,也要求我们持续创新,以应对复杂的数据和现实问题。
第一部分 116:机器学习专业课程概览 🧠

在本节课中,我们将介绍华盛顿大学机器学习专业课程后续内容的核心模块。课程将深入探讨回归、分类、聚类与检索、推荐系统与降维,以及最终的顶点项目。每个模块都将扩展我们在基础课程中学到的概念,并引入新的算法与实际问题解决方案。
回归课程 📈


上一节我们介绍了机器学习的基础概念,本节中我们来看看回归课程的详细内容。在回归课程中,我们将深入探讨模型的不同构建方式,例如如何处理大量特征。我们还将详细讨论用于拟合这些模型的算法。
以下是回归课程将涵盖的核心内容:
- 模型公式化:探讨如何应对大量特征,这是基础课程中提及过的问题。
- 优化算法:我们将讨论不同的优化算法,例如梯度下降和坐标下降,用于实际执行优化。其核心思想是最小化成本函数,例如残差平方和(RSS)。
- 梯度下降公式:
θ = θ - α * ∇J(θ),其中θ是参数,α是学习率,∇J(θ)是成本函数J的梯度。
- 梯度下降公式:
- 案例研究:通过预测房价的案例研究,我们将涵盖许多对机器学习各个领域都至关重要的基础概念。
在预测房价的案例中,我们将探索如何衡量成本、如何在模型之间进行选择以及如何处理模型过拟合。这些思想不仅适用于回归问题,也广泛适用于其他机器学习任务。

分类课程 🏷️
接下来,我们将转向分类课程。本节将讨论线性分类器的具体示例,以及如何扩展到使用大量特征并在高维特征表示中创建分类器的方法。
以下是分类课程的重点:

- 线性分类器:学习具体的线性分类模型。
- 特征扩展:探索如何扩展到使用海量特征。
- 分类算法:讨论执行此类分类的算法,特别是关注一种能够扩展到真正大型数据集的优化算法。
- 模型融合:介绍如何使用提升(Boosting)方法来融合不同模型。
- 在线学习:探讨一种非常有趣的概念——在线学习,即如何处理持续流入的数据流并随之持续进行推断。
聚类与检索课程 🔍
在了解了聚类和文档检索任务的基础思想后,本课程将进一步深化。例如,在考虑文档聚类时,一个文档可能不仅仅是关于体育、世界新闻、科学或娱乐,它可能混合了不同的主题。

以下是本课程的核心内容:

- 复杂结构建模:学习如何对数据中可能存在的更复杂结构进行建模。
- 高效检索算法:在执行检索任务时,探索非常高效的数据搜索方法。
- 聚类算法:学习多种用于实现我们所讨论的聚类模型的算法。
- 大规模扩展:一个关键概念是思考如何使用 MapReduce 等技术,将聚类扩展到真正海量的文档集合。
推荐系统与降维课程 🎯
本课程将超越我们已经讨论过的协同过滤和矩阵分解类型。我们将探讨处理高维数据集的方法,并思考如何用一些低维表示进行建模。

以下是本课程的要点:
- 降维算法:思考用于执行这种降维的不同算法。
- 矩阵分解模型拟合:讨论用于拟合我们在本课程中描述的矩阵分解模型的算法。
- 核心概念:我们将深入研究一些重要概念,特别是在思考矩阵分解时,如何执行矩阵补全(即填充所有未知方格)。此外,还有一个更普遍的问题——冷启动问题,即在推荐系统中,我们可能没有关于用户或产品的任何信息,却需要形成推荐。

顶点项目 🏆
最后,我们将进入顶点项目。希望你们已经感受到,这将是非常酷的部分。在完成了本课程后,你们已经理解了构成这个顶点项目的一些概念。
顶点项目将构建一个推荐系统,该系统结合了文本情感分析的思想和计算机视觉中搜索不同图像的重要思想。为此,我们将使用深度学习。在顶点项目中,将提供关于深度学习的一些非常重要且更详细的信息。
完成这一切将使你能够构建一个真正智能的Web应用程序并将其部署,做出一些不仅能给朋友和家人留下深刻印象,也能吸引潜在雇主的事情。当然,这对一些人来说是潜在的奖励,但这真的会很有趣。我们希望你能达到那个阶段,并享受顶点项目。


在本节课中,我们一起学习了机器学习专业课程后续四个核心模块(回归、分类、聚类与检索、推荐系统与降维)以及顶点项目的主要内容。每个模块都旨在深化基础概念,引入强大的新工具(如梯度下降、Boosting、MapReduce、深度学习),并通过实际案例研究(如房价预测、智能推荐系统)将理论应用于实践。完成整个系列课程,你将具备构建和部署复杂机器学习应用的能力。
机器学习基础篇(第1课/共4课)|课程总结与展望 🎓

在本节课中,我们将对机器学习专项课程的第一门课程进行总结,并展望后续的学习路径。

我们希望你喜欢这门机器学习专项课程的第一门课程。你不仅学习了许多不同的机器学习方法,而且真正将它们付诸实践。我们非常感谢你的努力。
我们知道你学习非常刻苦。你实现了很多不同的机器学习算法,认真完成了那些练习,不仅理解了概念,还掌握了如何应用它们,以及如何评估你构建的模型是否真正有效,并能提供你所期望的机器学习价值。现在,你已经准备好构建自己的智能应用,并将其真正部署到实践中。
😊 但是,在这个专项课程中,我们还有更多内容要学习,旨在将你们培养成机器学习专家,使你们能够实际设计和部署新的方法。
我们都对你们即将在这个专项课程中与我们共同开启的旅程感到兴奋。这段旅程将非常有意义。很高兴有你们加入我们。感谢你们参加第一门课程,我们期待在后续课程中见到你们,并看到你们在最终的顶点项目中构建出的出色成果。
感谢你们的辛勤付出。我们很快再见。


本节课中,我们一起回顾了第一门课程的学习成果,并对整个机器学习专项课程的后续学习进行了展望。你已经掌握了基础方法并付诸实践,为成为能够设计和部署解决方案的专家奠定了坚实基础。我们期待在接下来的旅程中继续与你同行。
第一部分 12:Python变量创建 🐍

在本节课中,我们将学习如何在Python中创建和使用变量。Python是一种脚本编程语言,它使得创建变量和原型设计变得非常简单。我们将从基本数据类型开始,然后介绍一些更高级的数据结构,最后了解如何进行格式化输出。
基本数据类型
上一节我们了解了Python作为脚本语言的特点。本节中,我们来看看Python中最基础的几种数据类型。
以下是创建基本数据类型变量的示例:
i = 4:创建一个整数变量。在Python中,注释可以用井号#开头,例如# int。f = 4.1:创建一个浮点数变量。b = True:创建一个布尔变量。s = "This is a string":创建一个字符串变量。字符串可以用单引号或双引号定义。
你可以使用 type() 函数来查看任何变量的类型,例如 type(i) 会返回 <class 'int'>。
高级数据类型
了解了基本类型后,我们来看看Python中一些更常用和强大的高级数据类型。
以下是两种常见的高级数据类型:
- 列表:列表可以包含任意类型的元素,例如数字、字符串等。创建列表的语法是使用方括号
[]。L = [3, 1, 2] # 一个整数列表 - 字典:字典是一种键值对集合,类似于哈希表。创建字典的语法是使用花括号
{},键和值之间用冒号:分隔。
你可以通过键来访问字典中的值,例如D = {'foo': 1, 'bar': 2.3, 's': 'My first Dictionary'}D['foo']会返回1。字典中的元素是无序的。
此外,Python还有一个特殊的类型叫 None,表示空值或无值。
n = None
type(n) # 返回 <class 'NoneType'>
格式化输出
我们已经学会了如何创建变量,现在让我们看看如何更灵活地打印它们,将变量值嵌入到字符串中。
在Python中,可以使用 % 操作符进行基本的字符串格式化。在字符串中,%s 是一个占位符,表示此处将插入一个值。在字符串末尾使用 % 并跟上要插入的变量(通常放在元组中),即可完成替换。
以下是一个格式化输出的例子:
print("Our float value is %s, and our integer value is %s" % (f, i))
这行代码会输出:Our float value is 4.1, and our integer value is 4。第一个 %s 被变量 f 的值替换,第二个 %s 被变量 i 的值替换。
Python还支持更多高级的字符串格式化方法,值得你自己去探索,这非常有趣且实用。


本节课中我们一起学习了Python变量的创建。我们从整数、浮点数、布尔值和字符串这些基本类型开始,然后探索了列表和字典这两种强大的数据结构,最后了解了如何使用格式化输出来更清晰地展示信息。Python以其简洁易用的语法,成为了快速原型设计和机器学习的绝佳工具。
第一部分 13:Python中的条件语句和循环 🐍

在本节课中,我们将要学习Python编程中的两个核心控制结构:条件语句和循环。我们将通过具体的例子,了解如何使用if、else、for和while来控制程序的执行流程。
条件语句
上一节我们介绍了变量类型和简单的转换,本节中我们来看看如何让程序根据不同的条件做出决策,这就是条件语句的作用。
在Python中,有多种方式构建条件语句,其复杂程度取决于你的需求。让我们从一个简单的例子开始。
假设我们想检查之前创建的整数变量i是否等于1,同时检查浮点数变量f是否大于4。条件语句的写法非常直观易读。
if i == 1 and f > 4:
在Python中,if语句后面需要加上冒号:。与C或Java等语言不同,Python不使用花括号{}来定义代码块,而是依靠缩进(空格或制表符)来区分。下一行开始的缩进部分,就相当于其他语言中花括号内的代码。IPython Notebook会自动帮你处理缩进。
如果上述条件成立,我们执行一些操作,例如打印一条信息。
print("The value of i is 1 and f is greater than 4.")
我们还可以添加其他条件。Python允许你将多个elif(即“else if”)串联起来。这是一种简洁的语法糖。
如果第一个条件不成立,我们可以询问下一个问题:i是否大于4?或者f是否大于4?这里我们使用逻辑运算符and和or,它们就是简单的英文单词,没有其他特殊符号。
elif i > 4 or f > 4:
print("i and f are both greater than 4.")
最后,我们可以添加一个else语句来处理所有其他情况。
else:
print("Both i and f are less than or equal to 4.")
现在,让我们回顾一下变量i和f的值。之前我们打印过,i是4,f是4.1。因此,程序会这样执行:
- 检查第一个条件:
i == 1 and f > 4?不成立。 - 检查第二个条件:
i > 4 or f > 4?f > 4成立,所以条件成立。 - 执行对应的打印语句:“i and f are both greater than 4.”
运行这段代码,我们成功构建了第一个条件判断结构。
循环
掌握了条件语句后,让我们进入下一个主题:循环。循环允许我们重复执行某段代码,这在处理数据集合或需要重复操作时非常有用。
在Python中,我们可以使用for循环和while循环。
For 循环
首先,我们来看for循环。还记得我们之前创建的列表L吗?让我们先打印它来回忆一下。
L = [3, 1, 2]
print(L)
现在,我们创建一个for循环来遍历这个列表中的每一个元素。
for element in L:
print(element)
这段代码的意思是:对于列表L中的每一个element(元素),执行打印操作。变量名element可以任意命名,比如e。循环会依次取出3、1、2并打印。在Python中,print()函数默认会在每次输出后换行,所以你会看到三个数字各自独占一行。
While 循环
接下来,我们创建一个简单的while循环。while循环会在条件为真时一直执行。
例如,我们想让一个计数器从某个数开始,一直打印并增加1,直到它不小于10为止。
while counter < 10:
print(counter)
counter += 1 # 这等同于 counter = counter + 1
但是,我们注意到代码中使用了变量counter,却没有先给它赋一个初始值。这会导致错误。让我们运行一下看看。
果然,程序报错了。Python的错误信息有时看起来有点吓人,但关键是要找到错误类型和发生位置。这里错误类型是NameError,提示counter未定义。它还会指出错误发生的代码行。
我们需要回到代码中,在while循环之前初始化counter,比如设为6。
counter = 6
while counter < 10:
print(counter)
counter += 1
现在再次执行,你会看到程序打印出6、7、8、9,当counter达到10时,条件counter < 10不再为真,循环停止。
总结
本节课中我们一起学习了Python中控制程序流程的两个重要工具。
我们首先学习了条件语句,使用if、elif和else来让程序根据不同条件执行不同的代码块,并了解了Python依靠缩进来定义代码结构的特点。
接着,我们探索了循环。for循环用于遍历序列(如列表)中的每个元素,而while循环则在指定条件为真时重复执行代码块。我们还实践了如何初始化变量以避免运行时错误。

掌握这些基础控制结构,是编写更复杂、更智能程序的关键一步。
第一部分 14:在Python中创建函数和lambda表达式 🐍

在本节课中,我们将要学习如何在Python中创建函数。函数是组织代码、实现代码复用的核心工具。我们将介绍两种定义函数的方法:使用 def 关键字和 lambda 表达式。
希望前面的内容能帮助你开始使用Python编程语言、IPython笔记本以及控制台。反复使用控制台是一种管理数据、与数据交互的简单有趣的方式。在Python生态中,有大量用于可视化、导航和进行机器学习的工具,因此它对我们来说是一门非常出色的编程语言。
事实上,近期有很多调查显示,Python是数据科学领域的首选编程语言,这也是我们为本课程选择它的原因。
作为最后一步,让我们来讨论如何在Python中创建函数。在Python中创建各种函数实际上相当容易,而且非常自然。有两种方法可以实现,让我们开始学习。
使用 def 关键字定义函数
第一种方法是使用 def 命令来定义函数。这允许我们创建具有名称和明确逻辑结构的可重用代码块。
以下是使用 def 定义函数的基本步骤:
- 以
def关键字开头,后跟函数名和括号。 - 在括号内列出函数的参数(例如
x,也可以是x, y, z等)。 - 在参数列表末尾加上冒号
:。 - 像处理循环一样,将函数体代码缩进(通常是一个制表符或4个空格)。
- 在函数体内编写要执行的代码,并使用
return语句返回结果。
例如,我们可以定义一个名为 add2 的函数,它接受一个参数 x 并返回 x + 2 的结果。
def add2(x):
y = x + 2
return y
定义好函数后,我们就可以调用它了。假设我们有一个变量 i 等于5,那么调用 add2(i) 将返回7。
i = 5
result = add2(i) # result 的值为 7
使用 lambda 表达式定义函数
上一节我们介绍了如何使用 def 关键字定义标准函数。本节中我们来看看第二种方法:使用 lambda 表达式。lambda 适用于定义简单的、单行的匿名函数,在很多需要简单转换的场景中非常有用。
lambda 表达式的语法更简洁。它使用 lambda 关键字,后跟参数列表、一个冒号 :,以及一个单一的返回值表达式。
例如,我们可以用 lambda 快速定义一个计算平方的函数 square:
square = lambda x: x * x
这行代码定义了一个函数,它接受输入 x 并返回 x * x 的结果。现在,我们可以像使用普通函数一样使用 square。例如,计算3的平方:
result = square(3) # result 的值为 9
总结
本节课中我们一起学习了在Python中创建函数的两种核心方法。
- 我们首先学习了使用
def关键字来定义具有名称和完整逻辑的函数,这是构建复杂功能的基础。 - 接着,我们探讨了使用
lambda表达式来快速创建简单的匿名函数,这种方法代码简洁,适用于简单的数据转换场景。

掌握这两种定义函数的方式,你就具备了利用Python进行基础编程和完成本课程所有作业所需的核心技能。函数是模块化代码和实现复杂算法的基石,请务必多加练习。
第一部分 15:启动Turi Create与加载SFrame 🚀

在本节课中,我们将学习如何启动Turi Create(原GraphLab Create)并加载SFrame,这是处理大规模表格数据的核心工具。我们将通过简单的步骤,了解如何导入库、加载数据以及查看数据的基本信息。
启动Turi Create
上一节我们介绍了本课程将使用的Python工具。本节中,我们来看看如何启动Turi Create。

首先,我们需要导入graphlab库。这个库提供了SFrame数据结构和本课程中将用到的多种机器学习算法。
import graphlab

执行上述代码后,Turi Create的所有工具,包括SFrame和机器学习算法,便可供我们使用。
加载数据
成功启动Turi Create后,下一步是从磁盘加载数据集。加载表格数据到SFrame非常简单。
我们将加载一个CSV格式的文件,这是一种常见的逗号分隔值文件格式。假设文件people-example.csv位于当前工作目录中。
以下是加载数据的代码:
sf = graphlab.SFrame('people-example.csv')
执行这行代码后,SFrame会解析文件并将其内容加载到变量sf中。控制台会显示解析过程的日志信息。
SFrame基础操作
现在数据已加载完毕,让我们学习一些SFrame的基础操作,以便查看和理解数据内容。
以下是查看数据的基本方法:
- 查看表格前几行:直接输入SFrame变量名或使用
.head()方法。sf # 或 sf.head() - 查看表格后几行:使用
.tail()方法。sf.tail()
对于小型数据集,这些命令可能会显示所有行。.head()和.tail()在查看大型数据集的开头和结尾时尤其有用。
总结
本节课中,我们一起学习了机器学习实践的第一步:启动Turi Create并加载数据。我们掌握了三个关键操作:
- 使用
import graphlab启动Turi Create。 - 使用
graphlab.SFrame('filename.csv')加载CSV格式的数据。 - 使用
sf.head()和sf.tail()查看数据的前几行和后几行。

这些是构建后续所有机器学习应用的基础。在下一课中,我们将学习如何探索和操作SFrame中的数据。
第一部分 16: 数据可视化画布 📊

在本节课中,我们将学习如何使用GraphLab Create的数据可视化画布(Canvas)来直观地探索和展示数据集。我们将从启动画布开始,逐步学习如何查看数据、分析列信息,以及如何将可视化结果嵌入到Python笔记本中。
我们已经快速浏览了数据集,现在让我展示一个非常实用的功能。
接下来介绍GraphLab Create的画布(Canvas)。
我们拥有表格数据、图数据、文本数据和图像数据等多种数据类型,可视化方式也多种多样。GraphLab Create内置了一个数据可视化工具,能以多种方式查看数据。
对于GraphLab Create中创建的任何数据结构,只需在其后输入.show()即可启动画布,并提供该数据结构的可视化视图。
以这个简单的数据集为例,输入.show()后,画布会生成一个链接,指向展示数据的新网页。

我将稍微减小字体大小,可以看到这个数据集包含四列:名、姓、国家以及年龄。数据显示,最大年龄为25岁,平均年龄为22岁,中位数为23岁,众数为23岁(占比42.857%)。

点击“表格视图(Tabular View)”,可以实际查看数据。这个功能非常强大,即使你有百万行数据,也能轻松滚动浏览,理论上甚至能处理十亿行数据。

现在,如果我点击任意一列,例如年龄列,它会提供该列的分析视图。刚才我误操作了,重新加载一下。
如果选择“分类(Categorical)”视图,数据会按最常见值排序。可以看到,最常见的年龄是23岁,共有3人,占数据的42%。你应该多尝试使用画布,以各种方式可视化数据。
对于我们现在录制的笔记本教程,画布在新窗口中弹出会使得来回切换不太方便。因此,我将展示如何将画布或可视化结果直接嵌入到Python笔记本中。
我将调用一个命令:graphlab.canvas.set_target(‘ipynb’)。这个命令会将后续所有可视化的目标设置为当前的IPython笔记本。

让我们再次可视化年龄列,但这次是在笔记本内部进行。操作很直观:我选取这个SFrame(sf),使用方括号[]来选择特定列(这里选择‘age’列),然后在其后输入.show(),并指定我想要“分类排序(sorted categorical)”视图。
结果出来了:我们可以看到23岁是最常见的年龄,有3人,占数据的42%。
至此,我们已经学习了如何使用GraphLab Create进行初步的数据可视化。在本课程中,我们还将看到GraphLab Create及其他工具提供的更多可视化方法。
本节课总结
本节课我们一起学习了:
- 如何启动并使用GraphLab Create的数据可视化画布(Canvas)。
- 如何通过
.show()方法查看数据集的整体概况和统计信息。 - 如何利用画布的表格视图(Tabular View) 浏览大量数据。
- 如何通过点击列名,查看特定列(如年龄)的详细分析(如分类视图/Categorical View)。
- 如何使用
graphlab.canvas.set_target(‘ipynb’)命令,将可视化结果嵌入到Jupyter Notebook中,方便在教程或分析中直接查看。 - 掌握了通过
sf[‘column_name’].show()语法对单列数据进行快速可视化的方法。

通过这些步骤,你可以开始以直观的方式探索和理解你的数据,这是机器学习工作流程中至关重要的一步。
第一部分 17:与SFrame的列交互 📊

在本节课中,我们将学习如何与SFrame数据集的列进行交互。具体内容包括:查看列数据、对列进行基本计算,以及创建新的列。这些操作是数据预处理和特征工程的基础。
查看数据列 🔍
上一节我们介绍了SFrame的基本结构,本节中我们来看看如何查看其中的列数据。
输入以下代码可以查看名为“country”的列:
sframe['country']
执行后,该列的所有值会以水平方式打印出来,例如:United States, Canada, England, USA, Poland, United States, Switzerland。
同样,我们可以查看“age”列:
sframe['age']
这会显示年龄数据:24, 23, 22, 23, 23, 22, 25。
对列进行计算 🧮
查看数据后,我们可以对列进行一些基本的统计计算。
以下是计算“age”列平均值的方法:
sframe['age'].mean()
计算结果约为23.14。
接下来,计算“age”列的最大值:
sframe['age'].max()
最大值为25。
创建新列(特征工程)⚙️
在机器学习中,经常需要基于现有列创建新的列,这个过程称为特征工程。
假设我们的数据集中有“first_name”和“last_name”列,但没有“full_name”列。我们可以轻松创建一个。
以下是创建“full_name”列的步骤:
sframe['full_name'] = sframe['first_name'] + ' ' + sframe['last_name']
这段代码将“first_name”列、一个空格和“last_name”列连接起来,形成新的“full_name”列。创建后,SFrame的末尾会新增这一列,例如第一个条目会是“Bob Smith”。
对列进行数学运算 ➕➖✖️➗
除了拼接字符串,我们还可以对数值列进行数学运算。
例如,将“age”列的每个值加2:
sframe['age'] + 2
这不会修改原数据,但会输出每个年龄加2后的结果。
我们也可以计算“age”列的平方:
sframe['age'] * sframe['age']
或者更简洁地:
sframe['age'] ** 2
结果会显示每个年龄值的平方,例如576, 529等。

本节课中我们一起学习了如何与SFrame的列进行交互:包括查看列数据、进行基本的统计计算(如求平均值和最大值),以及通过拼接或数学运算创建新的列。这些是数据预处理中非常实用和基础的操作。
第一部分 18:使用apply进行数据转换 📊

在本节课中,我们将学习如何使用apply函数对数据进行高级转换。我们将通过一个具体示例,演示如何统一数据集中不一致的国家名称,从而为后续的机器学习模型构建打下良好基础。
上一节我们介绍了如何对数据进行简单的数学运算转换。本节中,我们来看看如何使用apply函数执行更复杂的数据清洗操作。
数据集中有时会存在不一致的条目。例如,在“country”(国家)这一列中,有些行记录为“United States”,有些则记录为“USA”。对于机器学习模型而言,这会被视为两个不同的类别,因此我们需要将其统一。
以下是解决此问题的步骤:
首先,我们需要创建一个函数,用于将“USA”转换为“United States”。
def transform_country(country):
if country == 'USA':
return 'United States'
else:
return country
这个函数接收一个表示国家的字符串作为输入。如果输入是“USA”,则返回“United States”;否则,原样返回输入值。
我们可以测试一下这个函数:
- 输入
transform_country('Brazil'),输出'Brazil'。 - 输入
transform_country('USA'),输出'United States'。
接下来,我们需要将这个函数应用到数据集的每一行。虽然可以使用for循环,但使用apply函数更为高效。
以下是具体操作:
# 将transform_country函数应用到‘country’列的每一行
data['country'] = data['country'].apply(transform_country)
这行代码的作用是:获取data数据框中名为'country'的列,对其中的每一个值调用transform_country函数,并将返回的结果重新赋值给'country'列。执行后,数据集中所有的“USA”都会被替换为“United States”。

本节课中我们一起学习了如何定义函数,并使用apply方法对数据框(DataFrame)中的列进行批量转换。这种创建和操作数据框的技能,将是本课程后续构建智能应用的基础,我们会反复使用并看到它的多种应用方式。
第一部分 18:预测房价 - 回归案例研究 🏠

在本节课中,我们将要学习回归这一核心的机器学习工具。回归是一种应用极其广泛的统计方法,其核心思想非常简单:我们拥有一些特征,并希望建立一个模型,来描述与这些特征相关联的观测值如何随着特征值的变化而变化。
为了更具体地理解回归,我们将以一个预测房价的案例研究作为基础。你可以想象,一栋房子拥有许多特征,例如房屋面积、卧室数量、浴室数量等等。而我们希望预测的观测值,就是房屋的价值或销售价格。
然而,回归工具的用途远不止于预测任务。正如我们将在后续的分类课程中看到的,回归工具也可以用于分类问题。例如,我们有一封电子邮件,希望判断它是否是垃圾邮件。这封邮件可以看作拥有许多文本特征,这些特征能指示它是否为垃圾邮件。此外,回归还可以用于分析特征本身的重要性,我们将在回归课程中对此进行更深入的探讨。
什么是回归?📈
上一节我们介绍了回归的基本概念和应用场景。本节中,我们来看看回归的正式定义和核心思想。
回归分析旨在建立一个模型,来描述一个因变量(或称目标变量、输出)与一个或多个自变量(或称特征、输入)之间的关系。在房价预测的例子中,房价是因变量,而房屋面积、卧室数量等是自变量。
其核心目标是找到一个函数 f,使得:
房价 ≈ f(房屋面积, 卧室数量, 浴室数量, ...)
这个函数 f 就是我们的回归模型。通过这个模型,当我们输入一套新房子的特征时,就可以预测出它的价格。
回归的应用场景 🌍
我们已经知道回归可以用于预测房价。以下是回归分析其他几个重要的应用领域:
- 金融:预测股票价格、评估投资风险。
- 医疗:根据患者的年龄、体重、病史等特征预测疾病风险或药物剂量。
- 市场营销:分析广告投入、促销活动对销售额的影响。
- 社会科学:研究教育水平、收入等因素对个人幸福感的影响。
构建回归模型的步骤 🛠️
理解了回归是什么以及它能做什么之后,本节我们来看看构建一个回归模型通常包含哪些步骤。这是一个系统化的过程:
以下是构建一个回归模型的关键步骤:
- 问题定义与数据收集:明确你要预测的目标是什么,并收集相关的特征数据。
- 数据探索与清洗:检查数据质量,处理缺失值和异常值,初步观察特征与目标之间的关系。
- 特征工程:选择和构造对预测目标最有用的特征。例如,从“总房间数”和“卧室数”衍生出“平均每间卧室面积”。
- 模型选择:根据问题的特点选择合适的回归算法,例如线性回归、决策树回归等。
- 模型训练:使用收集到的数据来“训练”或“拟合”模型,即找到函数 f 的最佳参数。
- 模型评估:使用未参与训练的数据来测试模型的预测性能,常用指标包括均方误差(MSE)、R平方等。
- 模型部署与监控:将训练好的模型应用到实际问题中,并持续监控其在新数据上的表现。
总结 📝
本节课中,我们一起学习了机器学习中的回归方法。我们从预测房价的案例入手,理解了回归的核心思想是建立特征与观测值之间的数学模型。我们探讨了回归不仅可用于预测任务,还能应用于分类和特征重要性分析。最后,我们概述了构建一个回归模型的完整流程,从数据准备到模型评估。

掌握回归是理解更复杂机器学习模型的重要基础。在接下来的课程中,我们将深入探讨具体的回归算法及其实现。
第一部分 20:目标是什么以及如何初步应对 🏠

在本节课中,我们将学习如何通过观察历史数据来预测房屋价值。这是一个典型的回归问题,我们将探讨如何利用房屋面积这一特征来估计其销售价格。
问题背景

预测房屋价值是一个重要问题。在美国,家庭财富的近50%投资于房地产。这对消费者个人和政策制定者都至关重要。
假设我打算出售房屋,但不确定其市场价值。合理的做法是参考附近区域的近期房屋销售记录。
数据收集与可视化

为了估计房屋价值,我记录了附近近期每笔房屋销售的两个关键信息:销售价格和房屋面积。在美国,房屋面积通常以平方英尺为单位。
作为统计学家,我将这些观察结果绘制成散点图。横轴(X轴)代表房屋面积(平方英尺),纵轴(Y轴)代表销售价格。图中每个点代表一次具体的房屋销售。
以下是相关术语介绍:
- 特征(Feature):变量X,也称为协变量(Covariate)、预测变量(Predictor)或自变量(Independent Variable)。在本例中,指房屋面积。
- 观察值(Observation):变量Y,也称为响应(Response)或因变量(Dependent Variable)。在本例中,指销售价格。
初步应对策略及其局限性
如何利用这些数据来估计我的房屋价值?一个直观的想法是:查找与我房屋面积完全相同的其他销售记录。
然而,很可能不存在面积完全相同的销售记录。因此,我需要更灵活的方法。
接下来,我考虑查看面积在我房屋面积附近一个区间内的所有销售记录。但即使采用这种方法,如图中所示,可能也只有两笔销售记录可供参考,这不足以让我做出可靠的估计。
更重要的是,这种方法实际上丢弃了区间外的所有其他观察数据,仿佛它们与我的房屋价值毫无关系。这合理吗?我们真的认为这些数据不包含任何信息吗?
观察整体数据时,我希望利用所有可获得的信息来做出更好的预测。
总结

本节课中,我们一起学习了回归问题的基本设定:通过特征(如房屋面积)预测一个连续值(如房屋价格)。我们认识到,仅依靠与目标完全相同的样本或一个狭窄区间内的样本进行预测存在局限性,即数据利用不充分且估计可能不可靠。这引出了我们需要一个能够利用所有数据进行预测的模型,这将是后续课程的重点。
第一部分 21:线性回归 - 基于模型的方法 📈

在本节课中,我们将学习线性回归的基本概念。这是一种通过拟合直线来建模特征与目标之间关系的简单而强大的方法。我们将探讨如何定义模型、评估拟合质量,并利用模型进行预测。
模型定义与参数
上一节我们讨论了直接分析数据的方法,本节中我们来看看如何通过建模来理解房屋面积与售价之间的关系。最简单的方法是使用线性回归,即用一条直线来拟合数据。

这条直线由两个参数定义:截距(W₀)和斜率(W₁)。斜率 W₁ 也称为回归系数,它表示特征 X(房屋面积)每变化一个单位,对观测到的房屋售价 Y 产生的影响大小。
我们可以将线性函数明确表示为:
f_W(x) = W₀ + W₁ * x
其中下标 W 表示该函数由参数集合 W = {W₀, W₁} 决定。
如何选择“最佳”直线?
面对数据,我们可以画出许多不同的直线,每条线对应一组不同的参数 W。那么,哪条线才是最适合数据集的“好”线呢?
为了回答这个问题,我们需要定义一个衡量直线拟合好坏的成本(或损失)。一个非常常用的指标是残差平方和。
以下是计算残差平方和的步骤:
- 对于数据集中的每一个观测点(即每一栋房屋),计算模型预测值(直线上对应的点)与实际观测值(真实售价)之间的差值,这个差值称为残差。
- 将所有残差进行平方(这能放大较大误差的影响并避免正负抵消)。
- 将所有平方后的残差求和。
用公式表示如下:
RSS(W) = Σ (price_i - (W₀ + W₁ * sqft_i))²
其中,price_i 是第 i 栋房屋的观测售价,sqft_i 是其面积,(W₀ + W₁ * sqft_i) 是模型对该房屋售价的预测值。
我们的目标是找到一组参数 Ŵ = {Ŵ₀, Ŵ₁},使得残差平方和 RSS(W) 最小。这组参数对应的直线就是对数据的最佳拟合(在最小二乘意义下)。存在高效、成熟的算法(如正规方程或梯度下降)来求解 Ŵ,这些算法将在后续回归课程中详细讨论。
利用模型进行预测
一旦我们通过最小化残差平方和得到了估计的模型参数 Ŵ₀ 和 Ŵ₁,就可以使用这个拟合好的模型进行预测了。
例如,现在我想预测自己房屋的售价。我已知自己房屋的面积(sqft_my_house)。预测过程非常简单直接:
- 在图中找到对应房屋面积的点。
- 该点在拟合直线上的对应值,就是模型给出的最佳房价预测。
用公式计算预测值:
predicted_price = Ŵ₀ + Ŵ₁ * sqft_my_house
总结

本节课中我们一起学习了线性回归的核心思想。我们介绍了如何用带参数的线性函数 f_W(x) = W₀ + W₁ * x 来建模变量间的关系。为了找到最佳参数,我们引入了残差平方和 RSS(W) = Σ (y_i - (W₀ + W₁ * x_i))² 作为衡量模型拟合好坏的成本函数,并通过最小化该函数来求解最优参数 Ŵ。最后,我们学会了如何使用训练好的模型 predicted_price = Ŵ₀ + Ŵ₁ * x_new 对新数据进行预测。线性回归是机器学习中最基础、最重要的工具之一,为理解更复杂的模型奠定了基础。
第一部分 22:添加高阶效应 📈


在本节课中,我们将要学习如何通过添加高阶效应(如二次项、高次多项式)来改进线性回归模型。我们将探讨为什么有时简单的线性拟合可能不够,以及如何通过引入更多特征来捕捉数据中的非线性关系。同时,我们也会讨论高阶拟合可能带来的问题。

概述
到目前为止,我们只考虑了用直线拟合数据。问题是,这是一个好的选择吗?

我对自己的分析感觉相当不错。我拟合了这条线,最小化了残差平方和,并对我的房屋价值做出了预测。在这个过程中,我利用了所有我记录下来的近期房屋销售观测数据。然后我去找卡洛斯,对他说:“嘿,看看我的分析,这是我对我们房屋价值的估计。”😊
卡洛斯的质疑
卡洛斯回答说:“嗯,我不太确定。对我来说,我不确定这是线性趋势。”实际上,根据我的漫画,他说:“伙计,那不是线性关系。”当然,卡洛斯可能不会说“伙计”,但重点是,卡洛斯不认为这是线性关系。
他认为,也许这是二次关系。他问:“你试过二次拟合吗?”我回答:“没有。”我看着他在屏幕上展示的图,然后说:“实际上,那看起来很不错。”
二次拟合
我需要做什么?我需要找出最适合这些数据的二次拟合。我该怎么做?我将再次去最小化我的残差平方和。
我正准备去最小化我的残差平方和。让我们谈谈这涉及到什么。因为当我看一个二次函数时,我现在有三个参数。
- 我仍然有我的截距
W0,它决定了这条曲线在Y轴上的上下位置。 - 然后我有
x的线性项W1*x。 - 现在我还有这个额外的项
W2*x^2,这就是二次项的来源。
这里我想快速说明一点:这实际上仍然被称为线性回归。原因是我们把 x^2 仅仅看作是另一个特征。我们看到 W 总是以 w 的形式出现,而不是 w^2 或其他 W 的函数。我们将在回归课程中更详细地讨论这一点,但请记住,即使我们讨论的是对数据的二次函数拟合,这仍然被称为线性回归。
关键点在于,当我要最小化残差平方和时,我现在有三个参数。我必须在三个不同事物的组合空间中搜索,找到能最小化残差平方和的最佳 W0、W1 和 W2,从而确定二次拟合。
好的,我正准备进行这个计算,结果证明它也是高效的。同样,我们将在回归课程中讨论其通用性。
高阶多项式拟合
然后卡洛斯有了一个绝妙的主意,他说:“等等,等等。我告诉过你二次拟合,但你试过13阶多项式吗?”我回答:“不,我没有。”这确实很有道理。看看这个,这相当不错。

这是卡洛斯用他的13阶多项式得到的拟合。他说:“我只是最小化了你的残差平方和。很不错,对吧?我的残差平方和基本上为零。”😊
但是,我个人对此感觉不太好,因为我在看,并且说:“我的房子不值这么少,我知道的。”是的,我们讨论过残差平方和是拟合的成本,是的,卡洛斯似乎真的、真的、真的最小化了我的残差平方和。但有些地方让我觉得不对劲,这个函数看起来太疯狂了。
总结

本节课中,我们一起学习了如何通过添加高阶项(如 x^2)将线性回归扩展到非线性关系。我们了解到,即使模型包含特征的幂次项,只要参数是线性的,这仍然属于线性回归的范畴。同时,我们也看到了过度拟合的风险:使用非常高阶的多项式(如13阶)可以完美拟合训练数据(残差平方和接近零),但得到的模型可能非常复杂、不直观,并且在新数据上的预测性能可能很差。这引出了机器学习中的一个核心问题:如何在模型复杂度和泛化能力之间取得平衡。
第一部分 23:通过训练/测试集分割评估过拟合 📊

在本节课中,我们将学习一个机器学习中的核心问题——过拟合,并介绍如何使用训练集和测试集分割的方法来评估模型的好坏,从而选择更合适的模型复杂度。
过拟合问题

上一节我们介绍了使用高次多项式拟合数据可能带来的问题。我们面临的问题被称为过拟合。具体来说,我们采用了一个模型,并使其极度精确地贴合了我们的实际观测数据。但这个模型不能很好地推广到新的预测上。
这个问题实际上超出了仅仅做出奇怪预测的范畴。我们将在回归课程中更详细地讨论这一点。但需要指出,这是任何机器学习模型或统计模型都可能面临的真实问题。在这些情况下,我们希望将模型拟合到数据上,但我们不希望模型过于专门针对我们拥有的这一个数据集,以至于它不能很好地推广到我们可能获得的新观测数据上。
评估模型合理性
让我们回到这个13次多项式拟合。一个问题是:我们真的相信这个模型吗?我们认为这可能是一个对数据的合理拟合吗?正如之前提到的,答案很可能是否定的。尽管它最小化了残差平方和,但它最终导致了非常糟糕的预测。
我在这里思考,我们之前得到的二次拟合,即使它没有像13次多项式那样最小化我的残差平方和,我的直觉仍然认为这在某种程度上是一个更好的模型。那么问题来了:这里发生了什么?我们如何思考选择正确的模型阶数或模型复杂度?
我们当然想要好的预测,这是我们的目标。但我们实际上无法观测未来。所以,在我们真正进行预测之前,我们无法实际观测到我们想要做出的预测,并判断我们是否做得好。因此,当我们在思考选择模型时,我们只能利用我们已有的数据。那么,在这种情况下,我们如何思考尝试选择一个好模型呢?
我们可以做的是模拟预测。
模拟预测:训练集与测试集
我们将取我们拥有的数据集,并移除其中一些房屋。这些被灰化的房屋将被暂时移除。
我们将使用剩余的房屋来拟合我们的模型。我们将使用之前讨论过的完全相同的方法来拟合模型。然后,我们将进行预测。我会擦掉这些“x”标记,换上问号。然后问:从我刚刚在圈出的房屋上学到的模型中,我对这些问号预测了什么值?接着,我可以与实际的观测值进行比较,因为这些房屋就在我的数据中。


这样,我可以将其作为对尚未收集的数据进行真实预测的替代方法。当然,这种方法只有在有足够多的观测数据用于拟合和测试预测时才能很好地工作。
术语定义
让我们引入一些术语。我们用来拟合模型的房屋,我们称之为训练集。我们用作预测代理的房屋,即我们预留的那些,我们称之为测试集。
训练误差与测试误差
让我们更深入地探讨如何进行这种分析。首先,我们可以查看所谓的训练误差。
我们将检查测试数据集中的每一栋房屋。我们的训练房屋在这里用蓝色圆圈表示。在定义训练误差时,我们只关注这些房屋。具体来说,我们将查看在这些房屋上产生的误差。这仅仅是训练数据集中房屋的残差平方和,被称为训练误差。具体来说,训练误差看起来与我们之前计算残差平方和时完全一样,但我们只包含训练数据集中的房屋。
那么,对于任何给定的模型,例如线性拟合、二次拟合等,我们可以做的是,将估计模型参数视为那些最小化训练误差的参数。这等同于我们之前讨论的最小化残差平方和,但这里我们只关注训练数据集中的房屋。这样,我们就得到了估计的模型参数 Ŵ。
但我们接下来要做的是,取这些估计的模型参数,并评估我们的表现如何。记住我们说过要做什么:我们将查看我们预留的观测数据。这些灰色圆圈是测试集中的房屋。这些房屋没有被用来拟合这个模型。我们要问:我们预测这些实际房屋销售情况的效果如何?
我们的预测是什么?回想一下,当我们考虑进行预测时,我们只使用了拟合值,即直线上的点。
为了评估我们预测这些预留观测数据(即测试数据)的效果,我们将查看一个看起来也完全像残差平方和的东西,但它被称为我们的测试误差。我们取这些估计的模型参数 Ŵ,并对测试数据集中所有房屋的残差平方和进行求和。这就是我们的测试误差。
我们可以思考的是:测试误差和训练误差如何随着模型复杂度的变化而变化?
总结


本节课中,我们一起学习了过拟合的概念,即模型过于复杂,完美拟合了训练数据但无法泛化到新数据。为了解决这个问题,我们引入了训练集和测试集分割的方法。通过将数据分为两部分,一部分用于训练模型(训练集),另一部分用于评估模型在未见数据上的表现(测试集),我们可以计算训练误差和测试误差。通过观察这两种误差随模型复杂度变化的趋势,我们可以更好地选择既能拟合数据又能良好泛化的模型,避免过拟合。
第一部分 24:训练与测试曲线 📈

在本节课中,我们将要学习模型复杂度如何影响训练误差和测试误差。我们将通过观察不同阶数模型的误差变化,理解过拟合现象,并初步探讨如何选择合适的模型复杂度。
训练误差随模型复杂度变化
上一节我们介绍了不同阶数的多项式模型。本节中我们来看看训练误差如何随模型复杂度增加而变化。
对于每一个可能考虑的模型阶数,例如线性模型、二次模型,一直到非常复杂的13阶多项式模型(当然我们也可以考虑更高阶的模型),训练误差会如何变化?
随着模型阶数增加,模型能够越来越好地拟合训练数据集中的观测值。因此,我们的训练误差会随着模型复杂度的增加而下降。
还记得我们之前看到的曲线吗?从线性拟合、二次拟合一直到13阶多项式拟合(该模型几乎穿过了每一个观测点),我们看到残差平方和(RSS)在不断下降。即使我们预留一部分数据作为测试集,仅观察训练数据集,这个结论依然成立:随着模型灵活性增加,训练误差会不断减小。
我们用 \(\hat{w}\) 表示通过训练数据估计得到的模型参数。对于每一种模型复杂度(如线性、二次等),我们通过优化来找到参数 \(\hat{w}\)。对于线性模型,我们搜索所有可能的直线,以最小化训练误差。这就是我们估计模型参数的方式:最小化训练数据集上的误差。我们得到线性模型的 \(\hat{w}\),并计算与之相关的训练误差。对于二次模型,我们搜索所有可能的二次曲线拟合,最小化训练误差,得到二次模型的 \(\hat{w}\),并绘制其训练误差,以此类推。
以下是训练误差变化的要点:
- 训练误差随模型复杂度增加而单调下降。
- 模型参数 \(\hat{w}\) 是通过最小化训练集上的误差得到的。
- 高阶模型在训练集上可以达到极低的误差。
测试误差随模型复杂度变化
理解了训练误差的变化后,我们再来看看测试误差。这里的情况稍微复杂一些,因为当我们不断增加模型阶数时,测试误差会如何变化?
回想一下那个非常曲折的13阶多项式拟合线,它做出了非常糟糕的预测。当我们考虑预留的测试数据时,仅在训练数据上拟合一个13阶多项式,我们会得到一个非常曲折、奇怪的拟合线。然后,当我们观察那些被预留的测试观测值(那些房屋)时,我们对实际值的预测可能会非常差。
因此,我们预期在某个点之后,我们的测试误差很可能会上升。测试误差的曲线往往呈现以下形态:误差在一段时间内下降,但在某个点之后,误差开始再次增加。
这条曲线代表的是我们测试误差,而这些模型是使用训练数据拟合得到的。
以下是测试误差变化的要点:
- 测试误差随模型复杂度增加先下降后上升。
- 存在一个“最佳点”,使得测试误差最小。
- 超过该点后,模型开始过拟合训练数据,导致测试性能变差。
总结与展望
本节课中,我们一起学习了训练误差和测试误差随模型复杂度变化的典型曲线。我们看到,训练误差随模型变复杂而持续下降,但测试误差会先降后升,形成一条U形曲线。这直观地展示了模型过拟合的现象。

关于如何利用这些概念来实际选择模型或其复杂度以进行预测,我们将在后续的回归和分类课程中进行更详细的讨论。理解这些曲线是评估模型性能和进行模型选择的基础。
第一部分 25:添加其他特征 🏠📈


在本节课中,我们将学习如何在机器学习模型中添加更多特征,以提升预测的准确性。我们将从单一特征模型扩展到多特征模型,并介绍如何通过引入额外信息来改进预测结果。
从单一特征到多特征
上一节我们介绍了如何使用房屋面积(平方英尺)作为唯一特征来预测房价。本节中,我们来看看如何通过添加更多特征来改进模型。
假设我们深入分析数据,发现一个与我的房屋面积非常相似的房源。该房源对预测我的房价产生了显著影响。然而,该房源仅有一个卫生间,而我的房屋有三个卫生间。因此,该房源的售价不应作为预测我房屋售价的可靠参考。
为了解决这个问题,我们可以考虑添加更多特征。除了房屋面积与价格的关系外,我们还可以加入卫生间数量。对于之前查看的每个房源,我们需要记录其面积和卫生间数量,并将这些数据点绘制在三维空间中。这个空间是一个超立方体,维度包括面积、卫生间数量和价格。
现在,如果我们考虑一个简单模型,不再拟合一条直线,而是拟合一个超平面。这个超平面是空间中的一个切片,其方程如下:
公式: 价格 = w0 + w1 × 面积 + w2 × 卫生间数量
其中:
w0是截距,表示超平面在Y轴上的位置。w1是面积的权重。w2是卫生间数量的权重。
特征选择的问题
但问题在于,我们应该在何处停止添加特征?是否仅添加卫生间数量作为额外特征?实际上,我们可以考虑许多可能影响房价的因素。
以下是可能影响房价的其他特征示例:
- 卧室数量
- 地块大小
- 房屋年龄
- 以及其他可能影响房屋价值的属性
然而,我们将暂时搁置哪些特征对回归任务重要的问题,直到进入回归课程再深入探讨。请前往回归课程以了解更多相关内容。


总结


本节课中,我们一起学习了如何通过添加更多特征来改进机器学习模型。我们从单一特征模型扩展到多特征模型,介绍了拟合超平面的概念,并讨论了特征选择的重要性。通过引入额外信息,我们可以更准确地预测目标变量,为后续学习更复杂的回归模型打下基础。
第一部分 26:其他回归示例 📊

在本节课中,我们将探讨回归模型在多个不同领域的应用示例。回归不仅可用于预测房价,还能应用于薪资预测、股票价格分析、社交媒体影响力评估,甚至智能家居环境控制等多个场景。
回归模型回顾 🔄
上一节我们详细讨论了如何使用回归模型预测房价。回归的核心思想是建立一个线性模型,通过输入特征来预测连续型目标变量。其基本公式为:
y = W₀ + W₁x₁ + W₂x₂ + ... + Wₙxₙ

其中,y 是预测值,W₀ 是截距项,W₁ 到 Wₙ 是各特征对应的权重,x₁ 到 xₙ 是输入特征。
回归应用示例 🌟
以下是回归模型在不同领域的具体应用示例,每个示例都展示了如何将实际问题转化为回归任务。
1. 薪资预测 💼
预测完成机器学习专项课程后的薪资水平。薪资可能取决于课程表现、毕业项目质量、论坛参与度等因素。
模型参数包括截距 W₀ 以及对应课程表现 W₁、项目质量 W₂ 和论坛参与 W₃ 的权重。我们可以利用以往学员的课程表现和最终薪资数据来估计这些参数。
2. 股票价格预测 📈
预测明日股票价格。价格可能受近期股价历史、新闻事件、全球形势以及其他相关商品价值的影响。


3. 社交媒体转发量预测 🐦
预测一条推文最终获得的转发数量。这可能取决于你的粉丝数、粉丝的粉丝数、推文文本特征、所包含话题标签的流行度,以及你历史推文的转发情况等。
事实证明,这类模型能有效预测推文的最终转发量。
4. 智能家居温度预测 🏠
在拥有多种传感器和控制装置(如温控器、通风口、百叶窗)的智能家居中,预测书桌处的温度。由于书桌处没有直接传感器,可以通过建立空间回归模型来预测。

该模型可能依赖于房屋温控器设置、百叶窗开合状态、室外温度、通风设置以及一天中的时间等特征。
总结 ✨

本节课我们一起探讨了回归模型在薪资预测、股票分析、社交媒体和智能家居等领域的多样化应用。这些示例仅触及了回归应用领域的冰山一角,但它们充分展示了回归作为一个强大工具的广泛适用性和实用性。
第一部分 27:回归机器学习模块图 📊

在本节课中,我们将学习回归机器学习模块图。我们将了解如何从数据出发,通过特征提取、模型构建、质量评估和参数调整,最终得到预测结果。这个过程是机器学习的基础,适用于多种应用场景。

从数据到智能的流程
在课程介绍中,卡洛斯提出了一个机器学习流程:我们从数据开始,将其输入到某种机器学习方法中,从而获得智能。现在,让我们深入探讨这个模块图,并扩展它,因为我们已经在更多细节上了解了一些机器学习工具。

训练数据集

我们实际用于拟合数据的是训练数据集。在预测房价的住房应用中,我们收集的数据是一个表格。


这个表格包含房屋ID、一系列房屋属性以及房屋的销售价格。我们为社区中的许多房屋收集了这些数据,并将其整理成一个表格。这个表格代表了我们的训练数据集。
特征提取器
接下来,我们获取这些数据,并通过特征提取器进行处理。在这个例子中,特征提取器非常简单:我们只选择房屋属性的一个子集。
以下是我们在本模块中考察的两个特征示例:
- 房屋面积(平方英尺)
- 浴室数量
我们讨论了可能使用更多特征,这将在回归课程中进一步探讨。
机器学习模型与预测
我们的目标是利用这些特征,通过某种模型来预测房价。因此,我们输出的智能就是预测的房价。
我们将对训练数据集中的每一栋房屋进行此操作:获取其相关特征,输入到这个机器学习模型中,并预测其价格。我们讨论的机器学习模型就是回归。
模型参数
这个机器学习模型有一组参数,我们称之为 W,即特征的权重。例如,它是房屋面积或浴室数量的权重。更专业地说,这些被称为回归系数。
我们讨论了如何从数据中估计这些参数。W_hat 就是我们对这些参数的估计值。
质量评估与参数更新
我们获取预测的输出(即预测的房价),并将其与真实的房价(即我们在训练数据表中记录的实际销售价格)进行比较。y 代表训练数据中房屋的实际销售价格。
我们比较预测房价和实际房价,并使用一个质量指标来衡量我们预测的效果。我们讨论的误差指标是残差平方和,即对训练数据中所有房屋,计算实际销售价格与预测销售价格之差的平方和。
我们的质量指标接收预测值和实际房屋销售观测值,输出这个误差。然后,这个误差将输入到一个机器学习算法中,用于更新权重,即更新我们模型的参数。
我们将在实际的回归课程中更多地讨论这个机器学习算法或其不同变体。但这就是我们房屋预测问题的机器学习方法的整体流程图。
迭代优化过程
这个循环——获取预测值,计算相对于实际房价的误差,并更新权重或模型参数——通常以迭代的方式进行,即我们反复更新这些值。
抽象流程总结
如果我们进行抽象,可以看到:我们有一些训练数据,一个特征提取过程,一个机器学习模型。模型将产生一些智能(在本例中是预测)。我们将使用某种质量度量来评估我们智能的质量,并利用该误差(或准确度,取决于我们的衡量方式)通过某种算法来调整我们的模型参数。我们将在机器学习中反复看到这种类型的流程。


课程总结
在本模块中,我们学习了如何获取数据,并使用一种称为回归的方法来获得智能。我们有一个将特征与输出关联起来的模型。我们在预测房屋价值的背景下讨论了这一点,并且您还完成了一个非常有趣的 iPython 笔记本练习。现在,您应该能够在实践中部署真正有趣的回归模型了。
第一部分 28:加载并探索房屋销售数据 🏠

在本节课中,我们将学习如何使用Python和GraphLab Create来加载并探索真实的房屋销售数据,为后续的房价预测模型做准备。


启动环境与加载数据

上一节我们介绍了回归分析的基本概念。本节中,我们将动手操作,使用King County(美国西雅图所在区域)的公开房屋销售记录数据,共同构建一个用于预测房价的iPython Notebook。
首先,我们需要启动GraphLab Create工具,并加载数据。
以下是启动GraphLab Create的代码:
import graphlab
接下来,我们加载房屋销售数据。我们将使用GraphLab Create中的SFrame数据结构来存储这些表格数据。
sales = graphlab.SFrame('home_data.gl/')
执行上述代码后,数据将被加载到名为sales的变量中。我们可以通过输入变量名来查看数据内容。
数据包含了每笔房屋交易的多个特征,例如:
- 交易ID
- 销售日期
- 销售价格
- 卧室数量
- 卫生间数量
- 房屋居住面积(平方英尺)
- 土地面积(平方英尺)
- 楼层数
- 房屋是否有景观
- 房屋所在坡度等级
数据探索与可视化
加载数据后,下一步是进行初步探索,以理解数据特征和变量之间的关系。我们将使用GraphLab Canvas进行可视化。
为了将图表直接显示在Notebook中,我们需要设置Canvas的目标输出。
graphlab.canvas.set_target('ipynb')
设置完成后,我们可以创建散点图来探索两个关键变量之间的关系:房屋居住面积和销售价格。
sales.show(view='Scatter Plot', x='sqft_living', y='price')
生成的散点图以房屋面积为X轴,价格为Y轴。通过观察图表,我们可以发现以下规律:
- 总体上,房屋面积越大,其销售价格也倾向于越高。
- 大多数房屋的面积集中在1000到3000平方英尺之间。
- 数据中存在一些异常值。例如,一个面积约为1910平方英尺的房屋售价高达150万美元,而另一个面积相近(约1700平方英尺)的房屋仅售14.9万美元。
- 数据集中最大的房屋面积约为3730平方英尺,售价为250万美元。
总结

本节课中,我们一起学习了如何启动GraphLab Create环境、加载真实的房屋销售数据集,并通过可视化工具初步探索了数据特征,特别是房屋居住面积与销售价格之间的关系。这为下一节课构建具体的回归预测模型打下了基础。
第一部分 29:将数据分为训练集和测试集 📊

在本节课中,我们将学习构建简单回归模型的第一步:如何将数据集划分为训练集和测试集。这是机器学习工作流程中至关重要的一环,能帮助我们评估模型的真实性能。
数据探索与模型目标
我们已构建了一个简单的散点图,对数据分布有了初步了解。
现在的问题是:能否利用这个散点图,根据居住面积来预测销售价格?我们将构建一个简单的回归模型来实现这个目标。
划分数据集的重要性
在开始对数据进行任何建模操作之前,首先要做的是将其划分为训练集和测试集。
请记住,永远不要在测试数据上进行训练或学习。所有训练和参数调整都应仅在训练数据上进行,测试数据仅用于最终评估模型在未见数据上的表现。
执行数据划分
接下来,我们将数据分割为训练数据和测试数据。具体方法是调用一个名为 random_split 的函数。
以下是执行步骤:
- 对数据框(例如
sales)应用.random_split方法。 - 指定分割比例,例如
0.8,这意味着80%的数据用于训练,20%用于测试。 - (可选但推荐)为随机分割设置一个种子值,以确保结果可重现。
代码示例:
train_data, test_data = sales.random_split(0.8, seed=0)
关于代码的说明:
0.8参数指定了训练集的比例。seed=0设置了随机数生成器的种子。种子可以是任意数字(如2015)。设置种子后,每次运行代码都会得到完全相同的随机划分结果,这在家庭作业和需要复现实验时非常有用。

本节总结

本节课中,我们一起学习了机器学习建模的预备步骤:划分训练集与测试集。我们理解了为何要这样做(避免在测试集上训练),并掌握了使用 random_split 函数进行划分的具体方法,同时通过设置 seed 参数确保了结果的可重现性。这是构建可靠评估模型的基础。
第一部分 30:学习简单回归模型以根据房屋大小预测房价 🏠

在本节课中,我们将学习如何构建一个简单的线性回归模型,用于根据房屋的居住面积(平方英尺)来预测其价格。我们将使用训练数据来训练模型,并理解其背后的核心概念。
构建回归模型
上一节我们介绍了训练数据和测试数据。本节中,我们来看看如何使用这些数据构建一个回归模型。
GraphLab Create 提供了许多预实现的机器学习算法,适用于各种任务。你也可以根据需要实现自己的算法。在本课程中,我们将主要使用预实现的算法,以便专注于理解机器学习的工作原理。
我们将构建一个名为“平方英尺模型”的预测模型。在 GraphLab Create 中,可以使用线性回归算法。线性回归是我们在模块教学中深入探讨并理解透彻的方法。
要创建线性回归模型,我们使用 linear_regression.create 函数。这个函数需要指定输入数据、预测目标以及特征。
以下是创建模型的具体步骤:
- 指定训练数据。
- 定义预测目标(
target),这里我们预测的是价格(price)。 - 定义特征(
features),即模型的输入。如果不指定,模型将使用数据中的所有列作为特征。但在这里,我们只希望使用“居住面积平方英尺”这一特征。
注意,特征名称需要以字符串形式传入。GraphLab Create 的函数参数支持标签自动补全功能,这非常方便。
执行创建命令后,GraphLab Create 会自动选择一个合适的算法(例如牛顿法)来拟合数据并生成模型。这个训练好的模型随后就可以用来对数据进行预测。
总结

本节课中,我们一起学习了如何利用 GraphLab Create 的线性回归工具,根据房屋面积这一单一特征来构建房价预测模型。我们明确了构建模型所需的三个关键要素:训练数据、预测目标(target) 以及 特征(features)。通过这个过程,我们实践了从数据到模型的基本机器学习流程。
第一部分 31:评估简单模型的误差(RMSE)📊

在本节课中,我们将学习如何评估一个已训练的简单线性回归模型。我们将使用测试数据集,计算模型的预测误差,并重点理解均方根误差(RMSE) 这一核心评估指标。
上一节我们介绍了如何训练一个基于房屋面积的线性回归模型。本节中,我们来看看如何评估这个模型的性能。
首先,我们需要使用测试数据。请记住,我们之前已经将数据分割为训练集和测试集。让我们先了解一下测试数据的基本情况。
以下是查看测试数据中房价基本统计信息的步骤:
# 计算测试数据中房价的平均值
average_price = test_data['price'].mean()
print(average_price)
执行上述代码后,我们得到西雅图测试数据中房屋的平均价格约为 543,000美元。这表明该地区的平均房价相当昂贵。
现在,我们已经建立了基于面积的模型,接下来需要在这个测试集上评估它。
我们将调用一个评估函数。该函数可以接收测试数据集,并计算、返回一系列反映模型拟合效果的统计量。
以下是评估模型的具体操作:
# 使用评估函数计算模型在测试集上的表现
print(model.evaluate(test_data))
评估结果显示,模型在所有测试房屋上的最大误差为 410万美元。这表明存在一个预测极不准确的异常值样本。
而平均误差,即我们讨论过的均方根误差(RMSE),为 255,000美元。
RMSE 的计算公式为:
其中,\(y_i\) 是真实值,\(\hat{y}_i\) 是模型预测值,\(n\) 是样本数量。
我们构建的这个简单模型具有较高的RMSE。为了更直观地理解,我们可以查看模型对部分数据做出的具体预测。


本节课中我们一起学习了如何评估线性回归模型。我们使用了独立的测试数据集,计算了最大误差和关键的均方根误差(RMSE) 指标,从而量化了模型的预测准确性。
第一部分 32:使用Matplotlib可视化简单模型的预测 📊

在本节课中,我们将学习如何使用Python的Matplotlib库来可视化一个简单线性回归模型的预测结果。我们将通过绘制测试数据点和模型预测线,直观地展示模型的表现。
上一节我们介绍了如何使用GraphLab Canvas进行数据可视化。本节中,我们来看看如何使用另一个常用的Python工具——Matplotlib,来可视化模型的预测结果。
首先,我们需要导入Matplotlib库中的绘图模块。在Python中,我们通常使用import语句来导入库,并通过as关键字为其设置一个简短的别名,以便后续调用。
以下是导入Matplotlib并设置其在Jupyter Notebook中内嵌显示的代码:
import matplotlib.pyplot as plt
%matplotlib inline
代码%matplotlib inline是一个魔法命令,它确保图形直接显示在Notebook中,而不是弹出一个新窗口。
导入完成后,我们就可以开始绘制图形了。我们将创建一个图表,其中包含两组数据:实际的测试数据点和模型的预测线。
以下是绘制图形的步骤:
- 首先,我们绘制测试数据。我们将房屋的居住面积(
sqft_living)作为X轴,将房屋价格(price)作为Y轴,并使用圆点(‘.‘)来表示每个数据点。 - 接着,我们在同一张图上绘制模型的预测结果。X轴同样是居住面积,但Y轴是模型对每个测试房屋的预测价格。我们将使用虚线(
‘—‘)来绘制这条预测线。
以下是实现上述步骤的代码:
plt.plot(test_data[‘sqft_living‘], test_data[‘price‘], ‘.‘, label=‘test data‘)
plt.plot(test_data[‘sqft_living‘], sqft_model.predict(test_data), ‘—‘, label=‘predicted‘)
plt.legend()
执行这段代码后,我们将得到一张图表。图表中的蓝色圆点代表测试集中的真实房屋数据,而绿色虚线则代表我们的线性回归模型根据居住面积做出的价格预测。

本节课中,我们一起学习了如何使用Matplotlib库来可视化机器学习模型的预测。我们通过绘制测试数据散点图和模型预测线,直观地看到了一个简单线性回归模型(仅使用居住面积一个特征)的拟合情况。这种可视化方法有助于我们快速评估模型的表现和理解其预测趋势。
第一部分 33:检查学习到的模型系数 🧮

在本节课中,我们将学习如何查看线性回归模型学习到的系数,并理解这些系数的实际含义。通过分析模型系数,我们可以更好地解释模型如何根据输入特征进行预测。
上一节我们介绍了如何构建一个简单的线性回归模型。本节中,我们来看看如何查看并理解模型学习到的具体参数。
事实上,我们可以查看模型所拟合直线的系数。以我们构建的“房屋面积”模型为例,我们可以调用函数来获取这些系数。
以下是获取模型系数的步骤:
- 调用模型的
get函数。 - 获取并查看系数值。
这些系数在课程中被称为权重。对于这个简单的线性回归模型,共有两个系数。
第一个系数是截距。它代表直线与y轴的交点。在本例中,截距值为 -44000。
第二个系数是房屋面积的系数。它决定了直线的斜率。具体到本例,可以将其解释为每平方英尺的房价,即每增加一平方英尺的面积,房屋价格会增加多少。该系数值为 280。
这意味着,根据此回归模型,西雅图地区的房屋平均每平方英尺价格约为280美元。当然,实际市场中,有些房屋(如图中位置较高的点)每平方英尺价格更高,有些则更低,但此模型给出的平均估值是280美元每平方英尺。

本节课中,我们一起学习了如何检查线性回归模型的系数。我们了解到,截距表示预测的基准值,而特征系数则量化了该特征对预测目标的影响程度。理解这些系数是解释模型行为的关键一步。
第一部分 34:探索数据的其他特征 🏠

在本节课中,我们将学习如何探索数据集中除居住面积之外的其他特征。我们将通过可视化工具来观察这些特征与房价之间的关系,并理解不同特征对房价的影响。
我们已经完成了一些简单的回归分析。之前的回归分析仅使用了居住面积这一特征。但请记住,我们的数据集包含许多其他列或特征。接下来,我们将探索数据中的其他特征。
我们将探索一组可能用于预测房价的特征。以下是我们要探索的特征列表:
- 卧室数量 (
bedrooms) - 浴室数量 (
bathrooms) - 居住面积 (
sqft_living) - 这是我们之前一直在使用的特征 - 地块面积 (
sqft_lot) - 房屋周围的土地面积 - 楼层数 (
floors) - 邮政编码 (
zipcode) - 在美国代表地区编码
现在,让我们查看这些特征列的数据概览。通过调用 .show() 方法,我们可以直观地看到每个特征的分布情况:
- 卧室数量:数据集中有13种不同的卧室数量。大多数房屋有3间卧室,其次是4间和2间,拥有10间卧室的房屋非常罕见。
- 浴室数量:在美国,浴室数量可以是小数。例如,2.5个浴室最为常见,这通常意味着房屋包含一个完整浴室(带浴缸)和另一个只有洗手池和马桶的“半卫”。
- 居住面积:我们可以看到房屋居住面积的分布范围。
- 楼层数:大多数房屋是单层,部分为两层。
- 邮政编码:最常见的邮政编码是98103,这是西雅图一个人口密集的区域。
我们已经从高层面上查看了数据各列的分布情况。接下来,让我们探索数据之间的其他关系,进行一些有趣的可视化分析。

我们将创建一个箱线图来观察两个变量之间的关系。在X轴上,我们将使用邮政编码;在Y轴上,我们将绘制房价。这样,我们就能看到房屋所在地(邮政编码)与价格之间的关系。
运行代码后,生成的箱线图清晰地展示了不同地区的房价差异:
- 例如,邮政编码为98003的区域,平均房价较低(红线表示中位数),且价格波动范围较小。
- 而邮政编码98004的区域,平均房价要高得多,大约在110万美元左右,并且价格波动范围非常大,从约80万美元到近400万美元不等。
- 当我们向下滚动查看更多邮政编码时,会发现一个异常值:邮政编码98039的区域,其房价高得惊人,甚至超出了图表范围,有些房屋价格高达约700万美元。我们将在本课程末尾再次提到这个有趣的发现。


本节课中,我们一起学习了如何探索数据集中除核心特征外的其他属性。我们通过创建特征列表并利用可视化工具(如.show()概览和箱线图),直观地分析了卧室数量、浴室数量、地理位置(邮政编码)等特征与房价的分布及关联关系。特别是通过箱线图,我们发现了不同邮政编码区域房价存在的显著差异,这为后续构建更复杂的模型提供了重要的特征选择依据。
第一部分 35:使用更多特征预测房价 🏠

概述
在本节课中,我们将学习如何构建一个使用多个特征来预测房价的回归模型。我们将从之前仅使用“居住面积”的简单模型出发,探索加入更多特征(如卧室数量、浴室数量、邮政编码等)后,模型性能如何提升。
回顾简单模型
上一节我们介绍了仅使用“居住面积”这一特征来预测房价的简单线性回归模型。该模型的公式可表示为:
price = w0 + w1 * sqft_living
其中,w0 是截距,w1 是“居住面积”特征的权重。
引入更多特征
然而,仅凭面积预测房价显然不够精确。我们探索了其他特征,例如“邮政编码”和“卧室数量”,发现它们对房价有显著影响。本节中,我们来看看如何将这些特征整合到一个模型中,以期获得更好的预测效果。
我们将构建一个使用更多特征的回归模型。以下是我们要使用的特征列表:
- 卧室数量
- 浴室数量
- 居住面积
- 地块面积
- 楼层数
- 邮政编码
构建多特征模型
我们将使用 graphlab 库中的线性回归工具来创建这个“多特征模型”。代码实现如下:
my_features_model = graphlab.linear_regression.create(
training_data,
target='price',
features=my_features
)
在这段代码中:
training_data是我们的训练数据集。target='price'指定了我们要预测的目标变量是房价。features=my_features指定了用于建模的特征列表,即我们上面列出的那些特征。
执行这段代码后,模型将基于提供的特征进行训练。
模型性能对比
现在,我们有了两个模型:仅使用面积的“平方英尺模型”和使用多个特征的“多特征模型”。如何比较它们的性能呢?
我们将使用测试数据集对两个模型进行评估,并比较它们的预测误差。以下是评估代码:

# 评估平方英尺模型
print(sqft_model.evaluate(test_data))
# 评估多特征模型
print(my_features_model.evaluate(test_data))
结果分析
对比两个模型的评估结果,我们可以观察到性能的提升:
- 最大误差:在简单的平方英尺模型中,最大误差约为 404万美元。而在多特征模型中,最大误差下降至约 334万美元。
- 均方根误差:平方英尺模型的均方根误差约为 25.5万美元,这可以看作是一种平均误差。多特征模型的均方根误差则下降到了 17.9万美元。
这些结果表明,通过添加更多相关特征,模型的预测准确性得到了显著改善。理论上,随着加入的特征越来越多,并且数据量充足,模型的误差有望进一步降低。但即使只是添加了几个额外特征,也已经对我们的模型性能带来了积极影响。
总结
本节课中,我们一起学习了如何构建一个使用多个特征的线性回归模型来预测房价。我们从单一特征模型出发,通过引入卧室、浴室、邮政编码等特征,构建了更复杂的模型,并验证了多特征模型在降低预测误差方面的有效性。这体现了特征工程在机器学习中的重要性:选择合适的特征能极大地提升模型性能。
第一部分 36:应用学习模型预测平均房屋价格 🏠

在本节课中,我们将学习如何应用已训练的回归模型来预测具体房屋的价格。我们将使用两个模型:一个仅基于居住面积的简单模型,另一个基于更多特征的复杂模型。通过对比它们对三套不同房屋的预测结果,我们可以直观地理解模型在实际应用中的表现。
上一节我们介绍了如何构建回归模型,本节中我们来看看如何将这些模型应用于具体的预测任务。
我们将应用已学习的模型来预测数据集中三套房屋的价格。以下是三套不同的房屋,它们具有不同的面积、属性和地理位置。
首先,我们从数据集中选择第一套房屋。这套房屋的ID为“5309101200”,我们通过该ID在销售数据中定位它。
在Python笔记本中,我们不仅可以嵌入文本和代码,还可以嵌入HTML和图像。以下是为该房屋添加的图片示例。

这套房屋于2014年以620,000美元售出,拥有4间卧室、2.25间浴室,建于1929年。
现在,让我们看看模型对它的预测结果。
首先,打印房屋的真实价格作为参考。
print("房屋真实价格: $620,000")
接下来,应用第一个模型进行预测。该模型仅基于居住面积构建。
prediction_simple = model_simple.predict(house1_features)
print("简单模型预测价格: $", prediction_simple)
模型预测价格为628,000美元,与真实价格非常接近。
然后,应用第二个模型进行预测。该模型基于更多特征构建。
prediction_advanced = model_advanced.predict(house1_features)
print("复杂模型预测价格: $", prediction_advanced)
模型预测价格为720,000美元。对于这套特定房屋,简单模型的预测结果反而比复杂模型更准确。
这说明,尽管平均而言,添加更多特征通常会提升模型性能,但对于个别案例,简单模型有时可能表现更好。这是可以预期的现象。
以下是预测步骤的总结:
- 选择目标房屋:根据唯一ID从数据集中定位具体房屋。
- 提取特征:获取该房屋用于预测的特征值(如面积、卧室数量等)。
- 应用模型:将特征输入到训练好的模型中。
- 获得预测:模型输出预测的房屋价格。
- 对比分析:将预测价格与真实价格对比,评估模型表现。

本节课中,我们一起学习了如何应用回归模型进行实际预测。我们看到了简单模型与复杂模型在特定案例上的不同表现,并理解了模型预测结果存在波动是正常现象。关键在于,在平均意义上,更丰富的特征通常能带来更可靠的预测能力。
第一部分 37:应用模型预测两个高档房屋价格 🏠

在本节课中,我们将学习如何应用已构建的机器学习模型来预测两个高档房屋的价格。我们将看到不同复杂度的模型在面对不同特征房屋时的表现差异,并最终尝试预测比尔·盖茨的豪宅价格。
上一节我们介绍了如何构建和评估房屋价格预测模型。本节中,我们来看看如何将这些模型应用于具体的房屋实例进行价格预测。
预测第二套高档房屋
首先,我们来看第二套房屋。这套房屋在销售数据中的ID是1925069082。
以下是该房屋的具体信息:
- 房屋于2015年售出,售价为220万美元。
- 拥有5间卧室。
- 拥有4.25间浴室。
- 居住面积为4640平方英尺(约460平方米),是一套相当大的房屋。
以下是房屋的图片:

记得上一套房屋售价62万美元,而这一套售价220万美元。从图片看,它更豪华,并且位于水滨,这解释了其高昂的价格。
现在,让我们看看我们的模型对这套房产的估值预测。
首先,打印仅基于面积的模型(sqft_model)的预测结果。我们使用 .predict() 方法。
sqft_model.predict(house2)
该模型预测价格仅为125万美元,表现不佳。
接下来,我们看看包含更多特征的进阶模型(my_features_model)的预测。在执行前可以思考一下:对于上一套西雅图地区较普通的房屋,多特征模型并未带来显著提升。但这套房屋非常特别,拥有水滨、大量浴室和卧室等难以仅用面积来捕捉的特征。因此,我们预期多特征模型在这里会有更好的表现。
运行多特征模型的预测:
my_features_model.predict(house2)
模型预测价格为138万美元,虽然仍有差距,但比仅用面积的模型更接近真实价格,表现稍好一些。
预测比尔·盖茨的豪宅
为了总结,让我们来看一套更豪华的房屋——比尔·盖茨的豪宅。比尔·盖茨居住在西雅图地区,我们将尝试预测其房屋价格。
以下是比尔·盖茨房屋的特征信息(以字典形式表示):
- 8间卧室。
- 25间浴室。
- 50,000平方英尺的居住面积(约5000平方米)。
- 4层楼。
- 包含许多其他设施。
以下是房屋的图片:

现在,让我们看看模型对比尔·盖茨房屋的价格预测。我们需要将描述房屋的字典转换为SFrame格式,因为模型接收这种格式的输入。
graphlab.SFrame(bill_gates)
然后使用多特征模型进行预测:
my_features_model.predict(graphlab.SFrame(bill_gates))
模型预测其价值约为300万美元。这个数字听起来很大,但实际价值可能远不止这些。

本节课中,我们一起学习了如何应用基于县数据构建的两个房屋价格预测模型。我们探索了数据,使用了模型,并将其应用于预测具体房屋价格的任务,甚至尝试估算了比尔·盖茨豪宅的可能价值。


第一部分 38:分析评论情感:分类案例研究 📊
在本节课中,我们将要学习机器学习中的一个核心领域——分类。分类是机器学习中最常见、最实用且最直观的应用之一,例如判断邮件是否为垃圾邮件,或确定文档主题属于体育、政治还是娱乐等。本节我们将通过一个餐厅评论情感分析的案例,来具体了解分类任务的基本概念和流程。

上一节我们介绍了分类的基本概念,本节中我们来看看如何将分类应用于实际场景。我们将以餐厅评论的情感分析为例,展示分类任务的具体步骤。
分类任务概述 📝
分类是机器学习的一种方法,其目标是将数据点分配到预定义的类别中。在情感分析中,我们通常将评论分为“正面”或“负面”两类。这个过程涉及从原始文本中提取特征,并使用这些特征训练一个分类模型。
以下是分类任务的核心步骤:
- 数据收集:获取带有标签的评论数据集,例如“正面”或“负面”。
- 特征提取:将文本评论转化为机器学习模型可以理解的数值特征。常用方法是词袋模型。
- 模型训练:使用带标签的数据训练一个分类器,例如逻辑回归或朴素贝叶斯。
- 模型评估:使用测试数据评估模型的性能,常用指标包括准确率、精确率和召回率。
- 预测应用:使用训练好的模型对新的、无标签的评论进行情感预测。
特征提取:从文本到数字 🔢
在机器学习中,模型无法直接理解文本。因此,我们需要将文本数据转换为数值特征。最常用的方法是词袋模型。
词袋模型将一段文本表示为一个向量,其中每个维度对应一个单词,值表示该单词在文本中出现的次数(或是否出现)。其核心思想是忽略单词的顺序和语法,只关注单词的出现情况。
公式表示:
假设我们的词汇表包含三个单词:[“好吃”, “服务”, “差”]。
评论“好吃但服务差”可以表示为向量:[1, 1, 1]。
评论“服务很好”可以表示为向量:[0, 1, 0]。
代码示例(Python伪代码):
from sklearn.feature_extraction.text import CountVectorizer
# 示例评论数据
reviews = [“好吃但服务差”, “服务很好”]
# 创建词袋模型转换器
vectorizer = CountVectorizer(vocabulary=[“好吃”, “服务”, “差”])
# 将文本转换为特征向量
features = vectorizer.fit_transform(reviews)
print(features.toarray()) # 输出:[[1 1 1], [0 1 0]]
模型训练与预测 🧠
提取特征后,我们就可以使用这些带标签的特征向量来训练分类模型。以逻辑回归模型为例,它通过学习特征与标签之间的关系,来预测新数据所属的类别。
核心概念:逻辑回归模型会为每个特征学习一个权重(w),并计算一个分数(z),最后通过Sigmoid函数将分数映射到0到1之间的概率。
公式表示:
z = w1*x1 + w2*x2 + ... + wn*xn + b
P(正面) = 1 / (1 + e^(-z))
其中,x1, x2, ..., xn 是特征值,w1, w2, ..., wn 是对应的权重,b 是偏置项。如果 P(正面) > 0.5,则预测为正面评论,否则为负面。

总结与回顾 ✅

本节课中我们一起学习了机器学习中的分类任务。我们从分类的直观概念入手,通过餐厅评论情感分析的具体案例,详细介绍了从数据准备、特征提取(词袋模型)到模型训练(逻辑回归)的完整流程。
我们了解到,分类的核心在于利用已有标签的数据,让模型学习特征与类别之间的关联,从而能够对新的未知数据进行自动归类。情感分析是分类的一个典型应用,其思路和方法可以推广到垃圾邮件过滤、新闻分类等诸多领域。掌握分类是理解更复杂机器学习模型的重要基础。
第一部分 39:什么是智能餐厅评论系统 🍣


在本节课中,我们将学习如何构建一个智能的餐厅评论系统。这个系统不仅能提供餐厅的整体评分,还能分析评论中关于特定方面(例如寿司)的情感,从而为用户提供更个性化的推荐。
目前市面上存在许多餐厅评论系统。

今天我们将讨论一个可以构建的、相当新颖且令人兴奋的系统。
假设今天是一个重要的日子,我们想预订一家日本餐厅。我们喜爱日本料理,并希望找到一个享用日料的绝佳地点。
我们生活在西雅图,这座城市以出色的日本料理而闻名,因此有许多寿司店可供选择。事实上,许多餐厅都拥有很高的评分,例如四星。
因此,当我在考虑去哪家餐厅时,我不仅会考虑餐厅的整体星级,还会思考它在食物、氛围方面的表现,尤其是我真正关心的寿司质量。
我热爱寿司,希望获得最新鲜的鱼和最棒的创新寿司。

当我们谈论餐厅的好评时,以西雅图一家我们喜爱的餐厅为例,一条评论可能这样写道:“观看厨师们创作出令人难以置信、可食用的艺术品,真是一次独特的体验。” 这表明用餐体验非常积极。
然而,这条评论可能还会继续写道:“我妻子尝试了拉面,但味道平平无奇。” 这意味着拉面并不出色。
评论继续写道:“所有的寿司都很美味,是西雅图最好的寿司。” 这表明寿司获得了极高的评价。
我不关心拉面,我去这家店不是为了吃拉面。我不在乎评论者或其妻子不喜欢拉面。我真正关心的是良好的体验和美味的寿司,所以这条评论对我而言非常有价值。
因此,当我查看餐厅评论时,我希望理解餐厅各方面是积极还是消极的,并思考哪些方面真正影响我的兴趣。如果我将所有餐厅评论输入这个新颖且令人兴奋的推荐系统,它会告诉我:体验很好(四星),拉面一般(但谁在乎呢),而我真正关心的寿司,则是五星。
不仅如此,它还能提供一些有趣的反馈,例如:“这无疑是西雅图最好的寿司。” 这正是我想去的地方。
那么,我们如何构建这样一个智能的餐厅评论系统呢?

我们将从所有评论开始,首先将它们分解成句子。每条评论都由多个句子组成,其中一些句子描述了餐厅的不同方面。
例如,对于“这无疑是西雅图最好的寿司”这个句子,我们将把它输入一个情感分类器。情感分类器会判断这个句子是积极的还是消极的。
现在,我们有了一个可以接收句子并判断其情感倾向的分类器。那么,如何构建这种新颖的餐厅评论体验呢?


我们首先将所有评论分解成句子,然后从中筛选出描述我关心方面(例如寿司)的句子。这些句子只是所有句子中的一个子集。

接着,我将这些筛选出的句子逐一输入情感分类器,然后对结果取平均值。
在这个例子中,所有关于寿司的句子都是积极的,因此我会说,在寿司方面,这是一家五星级餐厅。
不仅如此,我还可以查看关于寿司的句子,并找出其中最积极的那些。例如,“这无疑是西雅图最好的餐厅”可能是最积极的句子,我可以展示它。同时,我也可以展示最消极的句子,不过在这个案例中,关于寿司并没有什么负面评价。

总结
本节课中,我们一起学习了智能餐厅评论系统的核心概念。该系统通过以下步骤工作:
- 分解评论:将每条用户评论拆分成独立的句子。
- 筛选相关句子:根据用户兴趣(如“寿司”)筛选出相关的句子。
- 情感分析:使用情感分类器对每个相关句子进行情感判断(积极/消极)。
- 汇总与展示:计算这些句子的平均情感得分,并可以突出显示最积极或最消极的评论片段。
这种方法超越了简单的整体评分,能够针对用户关心的特定方面提供深入洞察,从而实现更个性化的推荐。
第一部分 40:分类任务示例 🧠


在本节课中,我们将要学习分类任务的基本概念及其在不同领域的应用。分类是机器学习中的核心任务之一,它通过模型将输入数据映射到预定义的类别中。
什么是分类器? 🤖
上一节我们介绍了分类任务的基本概念,本节中我们来看看分类器的具体工作原理。
分类器接收输入 X(例如,一段评论句子),通过一个模型处理后,输出我们试图预测的值 y,这里 y 是一个类别。例如,在情感分析中,y 可以是“正面”或“负面”。
# 分类器的基本形式
y = model.predict(X)
在情感分析的例子中,“正面”对应好评(竖起大拇指),“负面”对应差评(拇指向下)。但这只是分类的一个例子。
分类的多样化应用 🌐
分类任务的应用非常广泛,不仅限于情感分析。以下是几个典型的应用场景:
文本分类
例如,对网页内容进行分类。我们可以将网页划分到不同的类别,如教育、金融或技术等。分类的类别数量可以是两个、三个,甚至成千上万个。
垃圾邮件过滤
垃圾邮件过滤是深刻影响我们生活的分类应用。早期的过滤器基于简单规则(如特定关键词),但效果不佳。机器学习分类器通过分析邮件内容、发件人、IP地址等多种特征,极大地提升了过滤准确性。
计算机视觉
在计算机视觉中,分类任务用于识别图像内容。输入 X 是图像的像素,分类器可以预测图像中的物体,例如判断图片中是狗(如拉布拉多犬)还是其他物体。深度学习方法在此领域实现了极高的准确率。
医疗诊断

分类也应用于医疗诊断系统。医生通过体温、X光片、化验结果等数据,预测患者的健康状况(如健康、感冒、流感或肺炎)。现代个性化医疗还能结合个人的DNA序列和生活方式数据,做出更精准的预测。
脑机接口与读心术
分类技术甚至能用于解读大脑活动。通过功能性磁共振成像(fMRI)等脑部扫描技术,分类器可以预测一个人正在阅读的词语(如“锤子”或“房子”)或观看的图片,这为理解大脑工作原理开辟了新前沿。
总结 📝

本节课中我们一起学习了分类任务的基本原理及其广泛的应用场景。我们了解到,分类器通过模型将输入数据映射到特定类别,这个过程在情感分析、网页分类、垃圾邮件过滤、图像识别、医疗诊断乃至脑科学研究中都发挥着关键作用。掌握分类是理解机器学习的重要一步。
第一部分 41:线性分类器 📊


在本节课中,我们将要学习机器学习中最常见的分类器类型之一:线性分类器。我们将从情感分析这一具体应用场景出发,理解线性分类器的基本工作原理、核心公式,并探讨其优势与局限性。

线性分类器的基本思想 🤔
上一节我们介绍了分类器的概念,本节中我们来看看线性分类器是如何表示和工作的。
在情感分析任务中,分类器的目标是判断一个句子是积极的还是消极的。我们可以想象一种非常简单的阈值分类器。

以下是其工作原理:
- 假设我们有一个已知的积极词汇列表(如“great”、“awesome”、“good”)和一个消极词汇列表(如“bad”、“terrible”、“disgusting”)。
- 对于一个输入句子,我们分别统计其中出现的积极词数量和消极词数量。
- 如果积极词数量多于消极词数量,则预测句子为积极;反之,则预测为消极。
例如,对于句子“The sushi was great, the food was awesome, but the service was terrible”,我们统计到两个积极词(great, awesome)和一个消极词(terrible)。因此,积极词胜出,我们预测该句子为积极。
然而,这种简单的阈值分类器存在一些局限性:
- 积极词和消极词列表从何而来?
- 不同词语的“积极”或“消极”程度不同(例如,“amazing”可能比“good”更积极),如何为它们分配不同的权重?
- 仅靠单个词语可能不足以做出准确分类(例如,“not good”是消极的,但其中包含“good”这个积极词)。
前两个问题(词表来源和权重分配)可以通过学习一个分类器来解决,我们将在接下来讨论。第三个问题则需要使用比单个词语更复杂的特征,我们将在本模块的后续部分进行探讨。
线性分类器的工作原理 ⚙️
上一节我们看到了简单阈值分类器的不足,本节中我们来了解线性分类器如何通过引入权重来解决这些问题。
线性分类器不再使用简单的积极/消极词列表,而是为所有词语分配一个权重值。
例如:
- “good”的权重可能是 +1.0
- “great”的权重可能是 +1.5
- “awesome”的权重可能是 +2.7
- “bad”的权重可能是 -1.0
- “terrible”的权重可能是 -2.1
- “awful”的权重可能是 -3.3
- 与情感无关的词语(如“the”、“was”)的权重则为 0
假设我们已经通过某种方式获得了每个词的权重(我们稍后会讨论如何学习这些权重),那么如何判断一个句子的情感呢?这里我们引入“评分”的概念。
对于一个输入句子,我们计算其得分。具体方法是:找出句子中出现的所有词,将它们对应的权重相加,得到总分。
公式表示如下:
score(x) = Σ (weight_i * count_of_word_i_in_x)

其中,x 代表输入句子,weight_i 是第 i 个词的权重。
决策规则如下:
- 如果
score(x) > 0,则预测句子为积极(ŷ = +)。 - 如果
score(x) < 0,则预测句子为消极(ŷ = -)。
让我们用之前的例子来演示。句子是:“The sushi was great, the food was awesome, but the service was terrible.”
- “great”出现,加 +1.5
- “awesome”出现,加 +2.7
- “terrible”出现,加 -2.1
- 其他词(the, sushi, was, food, service)权重为0,不影响得分。
计算总分:1.5 + 2.7 - 2.1 = 0.8。因为 0.8 > 0,所以我们预测该句子为积极。
这种分类器之所以被称为“线性”分类器,是因为其输出(得分)是输入特征(词语)的加权线性求和。

总结 📝
本节课中我们一起学习了线性分类器的核心概念。
我们从一个简单的基于词频计数的阈值分类器入手,指出了其在词表来源、词语权重和特征表达能力上的局限性。
随后,我们引入了正式的线性分类器模型。它的核心是为每个特征(如词语)分配一个可学习的权重。分类决策基于输入句子所有特征权重的加权和(即得分):
- 计算得分:
score(x) = Σ (weight_i * feature_i(x)) - 做出预测:如果
score(x) > 0,预测为积极;如果score(x) < 0,预测为消极。

线性分类器通过为不同词语赋予不同权重,更精细地捕捉了语言的情感倾向,为后续学习如何自动从数据中获取这些权重奠定了基础。
第一部分 42:决策边界 🧠

在本节课中,我们将要学习分类器如何做出决策,特别是线性分类器中的决策边界概念。我们将通过简单的例子和直观的图示,帮助你理解分类器是如何将数据划分为不同类别的。


分类器的决策作用
分类器的核心任务是做出决策。例如,判断一个句子是正面还是负面,或者根据一系列实验室测试、X光片和测量结果,判断患者是否患有流感或感冒等疾病。这些都需要分类器进行明确的决策。
上一节我们介绍了分类器的基本概念,本节中我们来看看分类器,特别是线性分类器,是如何具体做出这些决策的。
理解决策边界
为了理解决策边界,我们假设一个简单的场景:分类器只考虑两个具有非零权重的词。
- “awesome”这个词具有正权重,设为 1。
- “awful”这个词具有负权重,设为 -1.5。
在这种情况下,一个句子的得分(score)计算公式为:
score = 1 × (句子中“awesome”的数量) - 1.5 × (句子中“awful”的数量)
我们可以将句子在这个二维坐标系中表示出来:横轴(awesome轴)代表“awesome”的数量,纵轴(awful轴)代表“awful”的数量。
以下是几个例子在坐标系中的位置:
- 句子“The sushi was awesome, the food was awesome, but the service was awful”包含2个“awesome”和1个“awful”,其坐标为 (2, 1)。
- 一个包含3个“awful”和1个“awesome”的句子,坐标为 (1, 3)。
- 一个包含3个“awesome”和0个“awful”的句子,坐标为 (3, 0)。
现在,让我们更深入地理解如何计算句子得分,以及这对我们的决策意味着什么。
以坐标 (3, 0) 的句子为例,它有3个“awesome”,0个“awful”,其得分为正(大于0),因此被预测为正面。
实际上,在坐标系中,所有位于右下区域的点(得分大于0)都会被预测为正面。而所有位于左上区域的点(得分小于0)则被预测为负面。例如,坐标 (1, 3) 的句子得分为负,因此被标记为负面。
分隔正面预测和负面预测的,是一条特殊的线。在这条线上,得分恰好等于0,我们无法确定预测结果是正面还是负面,因此称之为决策边界。决策边界的一侧我们预测为正面,另一侧预测为负面。
请注意,这条决策边界的方程是 1 × awesome - 1.5 × awful = 0,这是一条直线。正因为决策边界是线性的,所以这类分类器被称为线性分类器。


决策边界的维度扩展
决策边界的作用是分隔正面预测和负面预测。在只有两个特征的情况下,我们看到决策边界是一条直线。
当我们增加特征数量时,情况会有所不同。在三维空间中,假设我们有三个具有非零权重的词,那么决策边界就变成了一个平面。虽然难以在三维图中精确绘制,但可以想象:正面预测位于平面的上方,负面预测位于平面的下方,而这个平面在空间中以某种角度倾斜。
在实际应用中,我们通常不会只有两三个非零权重的词,而是有成千上万个。在这种情况下,决策边界就变成了超平面——一种存在于极高维空间中的分隔面。

当然,分类器并不局限于线性的。我们可以使用更复杂的分类器,它们的决策边界不再是简单的直线或平面,而是具有更复杂的形状或弯曲的分隔面。我们将在后续的分类课程中学习更多相关内容。
总结
本节课中我们一起学习了决策边界的概念。我们了解到,线性分类器通过一个线性方程(在二维是直线,三维是平面,更高维是超平面)来划分数据点,从而做出分类决策。决策边界是分类器进行预测的核心依据,理解它有助于我们直观把握分类器的工作原理。
第一部分 43:训练与评估分类器 🧠

在本节课中,我们将学习如何训练一个分类器,并评估其性能。我们将重点讨论分类任务中的误差衡量方法,包括错误率与准确率,并通过具体例子说明如何计算这些指标。
在回归模型中,我们讨论了预测房价并拟合回归模型的方法,并使用平方误差来衡量误差。在分类任务中,误差的衡量方式有所不同,因为分类关注的是预测正确与错误的输入数量。因此,本节我们将详细探讨分类中的误差衡量方法。

训练与测试数据集 📊
当我学习一个分类器时,会得到一组输入数据。这些数据是标记为正面或负面情感的句子。与回归类似,我们将数据分为训练集和测试集。


我将训练集输入到正在学习的分类器中,该算法将学习单词的权重。例如,算法可能学习到“good”的权重为1.0,“awesome”为1.7,“bad”为-1.0,“awful”为-3.3。这些权重将用于对测试集中的每个元素进行评分,并评估分类效果。
分类误差的衡量方法 ⚖️
接下来,我们讨论如何衡量分类误差。我们有一组测试样例,例如“Sushi was great”是一个正面句子。我们需要统计在这些测试句子中,有多少被正确分类,有多少被错误分类。
以下是具体步骤:
首先,将句子“Sushi was great”输入到已学习的分类器中,但隐藏其真实标签。分类器预测该句子为正面(y_hat = positive),而真实标签也是正面,因此预测正确。正确分类的句子数量增加一。
其次,考虑另一个测试样例“The food was okay”,这是一个负面句子。将句子输入分类器并隐藏真实标签。分类器可能将其预测为正面,但真实标签是负面,因此出现错误。错误分类的数量增加一。
对语料库中的每个句子重复此过程,统计正确和错误分类的数量。
常见的分类质量指标 📈
以下是两种常见的分类质量衡量指标:
错误率衡量我们在测试样例上犯错误的比例。计算公式为:

错误率 = 错误分类数 / 测试句子总数
例如,如果有100个测试句子,犯了10个错误,则错误率为0.1或10%。最佳错误率为0,即没有错误。
准确率衡量正确分类的比例。计算公式为:
准确率 = 正确分类数 / 测试句子总数
与错误率不同,准确率的最佳值为1,表示所有句子都被正确分类。错误率与准确率之间存在简单关系:
错误率 = 1 - 准确率
反之亦然。
总结 ✨


本节课中,我们一起学习了如何训练分类器并评估其性能。我们介绍了分类任务中误差的衡量方法,包括错误率和准确率,并通过具体例子演示了如何计算这些指标。理解这些基本概念是进一步学习机器学习分类模型的基础。
第一部分 44:什么是好的准确率?🤔

在本节课中,我们将探讨如何评估分类器的性能。我们将学习如何判断一个准确率数值是否“足够好”,并介绍几个关键的基准比较方法。

我们已经讨论了使用错误率和准确率来评估分类器。准确率的计算公式为:
准确率 = (正确预测的样本数) / (总样本数)
现在,理解你从分类器中得到的准确率或错误率非常重要。你需要深入思考,这些数值在你的具体情境下是否真的代表了良好的性能。
上一节我们介绍了准确率的基本概念,本节中我们来看看如何判断一个准确率是否“足够好”。
一个常见的错误是孤立地看待分类器的准确率。当你构建一个分类器时,第一个应该做的基准比较是与随机猜测进行比较。
以下是几种基准比较方法:
- 随机猜测:对于一个二分类问题(例如,判断句子情感是积极还是消极),随机猜测的平均准确率是50%。对于有K个类别的问题,随机猜测的准确率是 1/K。你的分类器性能至少应该显著优于随机猜测,否则你的方法基本没有意义。

- 多数类预测:在某些存在类别不平衡的问题中,简单地预测出现次数最多的类别(多数类)就能获得很高的准确率。例如,在2010年的数据中,90%的邮件是垃圾邮件。如果一个垃圾邮件过滤器简单地将所有邮件都预测为垃圾邮件,它就能获得90%的准确率。这个数值看起来很高,但实际上这个分类器毫无用处。
因此,你必须非常谨慎,在判断准确率是否良好时,需要检查你的数据是否存在类别不平衡。
当然,如果你知道多数类是哪个,这种“多数类预测”方法的表现也会优于随机猜测。
你应该始终深入研究你的问题,理解你得到的预测结果,并思考这个准确率对你的问题是否真的有意义。
你可以问自己以下几个问题:
- 我的数据是否存在类别不平衡?
- 我的模型性能与随机猜测、多数类预测等基线方法相比如何?
- 最重要的是,结合你的应用场景思考:需要多高的准确率才能让我的用户真正满意?
例如,在垃圾邮件过滤中,如果准确率不够高,可能会导致重要邮件被误判进入垃圾文件夹,这可能造成严重的后果。

本节课中我们一起学习了如何评估分类器的准确率。我们了解到,不能孤立地看待准确率数字,而应该将其与随机猜测和多数类预测等基线进行比较,并充分考虑数据中的类别不平衡问题以及实际应用场景对性能的要求。始终要问:这个准确率对我的具体问题来说,是否真的“足够好”?
第一部分 45:假阳性、假阴性及混淆矩阵 📊


在本节课中,我们将学习分类器可能犯的不同类型的错误,特别是假阳性和假阴性,并介绍如何通过混淆矩阵来系统分析这些错误。理解这些概念对于评估分类器在实际应用中的表现至关重要。
分类器的错误类型
上一节我们讨论了分类器的准确率和错误。然而,错误并非只有一种,分类器可能犯不同类型的错误。

以下是两种主要的错误类型:
- 假阴性:真实标签为正类,但分类器预测为负类。
- 公式表示:
真实标签 = 正类,预测标签 = 负类。
- 公式表示:
- 假阳性:真实标签为负类,但分类器预测为正类。
- 公式表示:
真实标签 = 负类,预测标签 = 正类。
- 公式表示:
假阳性和假阴性在实际应用中可能带来不同的影响。

错误类型的实际影响
为了理解这两种错误的重要性,我们来看两个实际应用的例子。
以下是两个场景中假阳性和假阴性带来的不同代价:
-
垃圾邮件过滤
- 假阴性:一封垃圾邮件被错误地放入了收件箱。这令人烦恼,但代价相对较低。
- 假阳性:一封正常邮件被错误地标记为垃圾邮件并进入垃圾箱,导致用户可能永远错过这封邮件。这种错误的代价更高。
-
医疗诊断
- 假阴性:患者实际患病,但未被检测出来。这可能导致疾病得不到治疗,后果可能非常严重。
- 假阳性:健康人被误诊为患病。这可能导致患者接受不必要的、可能带有严重副作用的治疗。
在医疗诊断等场景中,哪种错误更严重取决于治疗的成本、副作用以及疾病本身的危害程度。
混淆矩阵
真实标签与预测标签之间的关系,包括假阳性和假阴性,可以通过混淆矩阵来清晰展示。
让我们通过一个二分类的例子来理解混淆矩阵。假设我们有100个测试样本,其中60个真实标签为正类,40个为负类。
以下是分类器的预测结果:
- 在60个真实正类中,分类器正确预测了50个(真阳性),错误预测了10个为负类(假阴性)。
- 在40个真实负类中,分类器正确预测了35个(真阴性),错误预测了5个为正类(假阳性)。
根据这些数据,我们可以计算:
- 准确率 = (50 + 35) / 100 = 0.85 或 85%。
- 假阴性数量为10,假阳性数量为5。
混淆矩阵清晰地展示了错误的具体类型和数量。
多分类问题的混淆矩阵
假阳性和假阴性的概念主要适用于二分类问题。然而,混淆矩阵同样适用于具有多个类别的分类问题。
让我们看一个医疗诊断的三分类例子。假设有100个测试样本,真实分布为:70人健康,20人感冒,10人患流感。
以下是分类器的预测结果构成的混淆矩阵:
- 健康:60人被正确分类。在10个错误中,8人被误判为感冒,2人被误判为流感。
- 感冒:12人被正确分类。在8个错误中,4人被误判为健康,4人被误判为流感。
- 流感:8人被正确分类。在2个错误中,0人被误判为健康,2人被误判为感冒。
总准确率为 (60 + 12 + 8) / 100 = 0.80 或 80%。通过这个混淆矩阵,我们可以深入分析错误模式,例如,健康人更容易被误判为感冒而非流感。
总结


本节课我们一起学习了分类器评估中的关键概念。我们明确了假阳性和假阴性这两种错误类型的定义及其在不同应用场景(如垃圾邮件过滤和医疗诊断)中可能带来的不同代价。更重要的是,我们引入了混淆矩阵这一强大工具,它不仅能用于二分类问题,也能扩展到多分类问题,帮助我们系统、直观地分析分类器所犯错误的具体类型和分布,从而对模型性能有更深入的理解。
第一部分 46:学习曲线 📈

在本节课中,我们将要学习学习曲线的概念。学习曲线描述了训练数据量与模型测试误差之间的关系,是理解模型性能和数据需求的重要工具。我们将探讨数据量如何影响模型表现,以及模型复杂度与数据量之间的权衡。

数据量与模型质量的关系
在回归模块中,我们讨论了误差或准确率与模型复杂度之间的关系。本节中,我们来看看数据量对学习效果的影响。
我们探索了“需要多少数据才能有效学习”的问题。这在机器学习中是一个复杂且困难的问题。当然,在数据质量良好的前提下,数据越多越好。质量差的大量数据,远不如少量但高质量的数据点。虽然存在一些理论技术来分析所需数据量,但它们通常过于宽泛,难以直接应用于实践。在实践中,我们使用一些经验性技术来理解误差的大小和性质。在后续课程中,我们将深入探讨这些技术。现在,让我在分类任务的背景下,为你提供一些指导和见解。
什么是学习曲线?📊
数据与质量关系的一个重要表示方法就是学习曲线。学习曲线将我们用于训练的数据量与所犯的误差联系起来,这里我们指的是测试误差。
如果你用于训练的数据很少,那么你的测试误差会很高。如果你有大量训练数据,你的测试误差则会降低。随着数据越来越多,曲线会变得越来越好。
以下是一个示例学习曲线,展示了随着数据增加,模型质量(误差降低)得到改善。




误差的极限:偏差
你可能会问,是否存在极限?质量是否会随着数据无限增加而永远变好?我们知道,测试误差会随着数据增加而减少。然而,这里存在一个差距,问题是这个差距能否变为零。答案通常是:不能。这个差距被称为偏差。
直观地说,这意味着即使拥有无限数据,测试误差也不会降至零。让我们来理解一下原因。
更复杂的模型往往具有更小的偏差。以我们一直在构建的情感分析分类器为例,如果你只使用“awesome”、“good”、“great”、“terrible”、“awful”等单词,它可能表现尚可,甚至很好。但即使你拥有世界上所有的数据(无限数据),你也永远无法正确判断“The sushi was not good”这个句子。因为你的模型只看单个单词“good”和“not”,而没有看单词对。

复杂模型与数据需求
更复杂的模型,例如处理单词组合的模型(如二元模型,它关注像“not good”这样的连续单词对),可以表现得更好。它们可能为“good”设置一个参数(例如0.15),为“not good”设置另一个参数(例如-2.1),从而正确判断“The sushi was not good”这个句子。因此,它们偏差更小,能够表示原本无法表示的句子,潜在地更准确。
但是,它们需要更多数据来学习,因为参数更多。这不仅仅是“good”一个参数,还有“not good”以及所有可能的单词组合参数。一般来说,模型参数越多,学习所需的数据就越多。

让我们回到之前的例子。
单字模型与二元模型的对比
我们讨论了训练数据量对测试误差的影响。假设我正在构建一个基于单个单词的分类器。问题是,这与基于单词对的分类器相比如何?
对于基于二元模型的分类器,当数据较少时,由于需要拟合更多参数,它的表现不会那么好。但当数据更多时,它会表现得更好,因为它能够捕捉像“The sushi was not good”这样的情况。因此,你将看到的行为大致如下:
在某个点上,二元模型的性能会超过单字模型,形成一个交叉点。但请注意,二元模型在这里仍然存在一些偏差,尽管这个偏差更小。

总结
本节课中,我们一起学习了学习曲线的核心概念。我们了解到:
- 学习曲线展示了训练数据量与测试误差之间的关系。
- 增加数据量通常能降低测试误差,提升模型性能。
- 误差存在一个下限,称为偏差,即使拥有无限数据也无法消除。
- 模型复杂度与数据需求之间存在权衡:更复杂的模型(如二元模型)偏差更小,潜力更大,但需要更多数据来有效学习;而简单模型(如单字模型)在数据较少时可能表现更好,但存在固有的性能上限。

理解学习曲线有助于我们评估模型性能、诊断问题(如高偏差或高方差),并做出关于是否收集更多数据或尝试更复杂模型的明智决策。
第一部分 47:类别概率 🎯

在本节课中,我们将学习分类任务中一个重要的进阶概念:类别概率。我们将探讨如何不仅预测一个样本属于哪个类别,还能评估模型对该预测的置信度。通过引入概率,我们可以更细致地理解模型的判断,并为后续的决策优化(如调整分类阈值)奠定基础。
从硬分类到概率预测 🔄
上一节我们介绍了基本的分类任务,即模型直接输出样本的类别标签(例如“正面”或“负面”)。然而,在实际应用中,我们常常希望了解模型做出这个判断的把握有多大。
分类器通常不会只输出“正面”或“负面”这样的硬性判断,而是会输出一个置信度或概率。这表示模型对预测结果的确定程度。
一种实现方法是计算条件概率。其核心思想是:给定输入数据 x(例如一个句子),模型输出该数据属于某个类别 y 的概率。

用公式可以表示为:
P(y | x)
其中,y 是输出标签(如“正面”),x 是输入句子。

概率预测的实例说明 📊
以下是两个具体的例子,展示了不同置信度下的概率输出:
-
高置信度正面评价:
对于句子 “The sushi and everything else were awesome.”,模型非常确定这是一个正面评价。因此,它可能会输出:P(正面 | x) = 0.99 -
低置信度正面评价:
对于句子 “The sushi is good, the service was okay.”,模型觉得它可能是正面评价,但不太确定。因此,它可能会输出一个接近中性的概率:P(正面 | x) = 0.55
概率预测的重要性 ⚖️
预测概率或置信度极其重要。在后续的分类课程中我们会看到,掌握概率信息使我们能够做很多事情。
例如,当我们知道了样本属于各个类别的概率后,就可以做出更优的决策:
- 如何设定一个最佳的决策边界,来权衡假阳性(False Positive)和假阴性(False Negative)?
- 如何在两类错误之间取得平衡?
这些决策都依赖于模型输出的概率信息,而不仅仅是简单的类别标签。
本节总结 ✨
本节课中,我们一起学习了类别概率的概念。我们明白了分类任务不仅是预测“是或否”,更重要的是评估预测的置信度,这通常通过计算条件概率 P(y | x) 来实现。概率输出为我们提供了更丰富的信息,是进行高级模型评估和决策优化的基础。在接下来的课程中,我们将看到如何具体应用这些概率。
第一部分 48:分类机器学习模块图详解 🧠

在本节课中,我们将学习分类机器学习的基本流程,特别是如何通过一个模块图来理解分类算法(如情感分析)的工作方式。我们将以情感分析为例,详细解析从数据输入到模型预测,再到参数优化的完整循环。

从回归到分类:模块图的通用性 🔄
在回归部分,我们曾介绍过一个描述机器学习算法如何迭代处理数据的模块图。现在,我们将使用相同的模块图框架,来阐述它在分类任务(特别是情感分析)中是如何运作的。
分类任务中的模块图解析 📊
以下是分类机器学习模块图的核心组成部分及其工作流程。
数据与特征提取
在情感分析任务中,数据是评论文本的集合。每条评论都对应一个已标注的情感标签(如正面或负面)。特征提取阶段将这些文本转化为算法可处理的输入 x。具体来说,x 是每个评论的词频统计。
代码示例:特征提取
# 假设 reviews 是评论文本列表
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(reviews) # X 即为词频特征矩阵
机器学习模型与预测
模型接收输入数据 x(词频)以及一组参数 Ŵ(每个词的权重)。通过结合这两者,模型会输出一个预测分数。在情感分析中,我们设定一个简单的规则:如果分数大于0,则预测为正面情感;如果分数小于0,则预测为负面情感。
公式:预测规则
[
\text{预测情感} =
\begin{cases}
\text{正面}, & \text{如果 分数} > 0 \
\text{负面}, & \text{如果 分数} < 0
\end{cases}
]
评估与反馈循环

如果仅使用模型进行预测,流程到此结束。但在机器学习算法阶段,我们需要评估预测结果,并利用反馈来优化模型参数。
我们将模型的预测情感 ŷ 与真实的情感标签 y 进行比较。评估指标通常使用分类准确率。
公式:分类准确率
[
\text{准确率} = \frac{\text{正确预测的数量}}{\text{总预测数量}}
]
机器学习算法(我们将在分类课程中详细讨论)会接收这个准确率评估结果,并试图通过更新参数 Ŵ 来提高它。这样就形成了一个“预测 -> 评估 -> 优化”的完整循环。
本章内容回顾与总结 🎯
在本模块中,我们深入探讨了分类任务的执行方法。我们查看了分类在各种场景下的应用实例,重点讨论了在情感分析背景下构建分类器的几种模型。通过实际演示和动手构建分类器的实践,我们完整地体验了从数据到分析的全过程。
掌握这些知识后,你已经具备了构建一个以分类器为核心的智能应用的基础能力。
第一部分 49:加载并探索产品评论数据 🎯

在本节课中,我们将学习如何加载并探索产品评论数据集,为后续构建情感分析工具做准备。我们将使用真实的数据集,并通过简单的步骤了解其结构。


上一节我们介绍了情感分析的基本概念,本节中我们来看看如何实际操作数据。

首先,我们需要导入必要的库并加载数据。以下是初始步骤:
import graphlab
products = graphlab.SFrame('amazon_baby.gl')
数据加载完成后,我们可以开始进行初步的探索。
以下是数据探索的具体步骤:
-
查看数据表的前几行:这有助于我们了解数据的整体结构和内容。
products.head() -
观察数据列:数据集包含三列信息:
name:产品名称。review:用户撰写的文本评论。rating:用户给出的评分(1到5星)。
通过查看数据头部,我们发现例如“Plantwise Flanno Wipes”这款产品的评分为3星(中等评价),而另一款产品“Plantwise Wipe Pouch”的评分为5星(高度评价)。这直观展示了数据的基本形式。


本节课中我们一起学习了如何加载一个真实的产品评论数据集,并使用head()方法进行了初步的数据探索。我们了解到该数据集包含产品名称、评论文本和星级评分三列关键信息,这为后续分析情感倾向奠定了数据基础。
第一部分 50:创建词频向量 📊

在本节课中,我们将学习如何为文本数据创建词频向量。词频向量是文本分析中的基础工具,它将每篇评论转换为一个数值向量,其中每个元素代表一个特定单词在该评论中出现的次数。通过这种方式,我们可以将非结构化的文本数据转化为结构化的数值数据,以便后续的机器学习模型进行处理。
上一节我们介绍了文本数据的基本概念,本节中我们来看看如何具体构建词频向量。
构建词频向量的过程通常包括逐篇审阅评论、将句子分割成单词(这个过程称为“分词”),然后统计每个单词的出现次数以构建向量。然而,在本课程使用的工具中,我们可以通过一个简单的命令来完成所有这些步骤。
在 products 数据框中,我们将添加一个名为 word_count 的新列,用于存储词频统计结果。我们使用 graphlab 库中的 text_analytics 工具箱,它包含了许多文本分析函数。其中有一个函数叫做 count_words。此外,如果你希望使用二元组或三元组,还有一个名为 count_ngrams 的函数可供选择。
以下是具体操作步骤:
- 我们调用
graphlab.text_analytics.count_words函数。 - 将
products数据框作为输入传递给该函数。 - 指定对
review列中的文本进行词频统计。
执行上述命令后,操作即告完成。现在,如果我们再次查看 products 数据表,会发现表中新增了第四列,即 word_count 列。我们稍后会对此进行更深入的探索。从第一行数据可以看到,单词“love”出现了5次,单词“it”出现了1次,这或许解释了为何该产品评价不高。数据表中还包含其他许多类似的词频统计信息。


本节课中我们一起学习了如何为产品评论数据创建词频向量。我们利用 graphlab 库的 count_words 函数,高效地将文本评论转换成了结构化的词频数据,为后续的机器学习建模任务做好了准备。
机器学习基础篇(第1课/共4课)📊:探索最受欢迎的产品

在本节课中,我们将学习如何使用数据可视化工具来探索数据集,并聚焦于分析特定产品(如一款名为“Vulli Sophie”的牙胶长颈鹿)的客户评价。我们将通过构建直方图来查看产品评价的分布,并初步了解后续进行情感分析的基础。
查看现有产品与评价
首先,我们需要查看数据集中包含哪些产品以及对应的评价。我们将再次使用Canvas工具进行可视化操作。
与之前一样,我将在iPython笔记本环境中调用GraphLab Canvas,并将输出目标设置为当前笔记本,以便结果直接显示在这里。
现在,我们可以选取产品数据框(SFrame)中的某一列进行分析。例如,我们可以选取产品名称这一列,并对其调用.show()方法。
这将生成一个直方图,展示数据中不同产品名称的分布情况。
例如,从图中我们可以看到,名为“Vulli Sophie”的特定产品获得了最多的评价,共785条。相比之下,类似“Simple Wishes”的产品获得了562条评价。其他产品如Fisher-Price系列分别获得了489条和450条评价。这些都是我们正在分析的不同婴儿产品。该直方图清晰地展示了不同产品所获评价数量的差异。
深入分析最受欢迎的产品
接下来,让我们深入了解这款获得最多评价的产品——“Vulli Sophie”究竟是什么。
这款所谓的“Vulli Sophie”是一款极其受欢迎的产品。我这里恰好有一个实物。这是一个Vulli Sophie牙胶长颈鹿,它是一个塑料小长颈鹿,是亚马逊上赠送给婴儿的最常见礼品。作为牙胶,婴儿喜欢啃咬它,因此这款长颈鹿获得了大量评价。它由塑料制成,可以挤压发声。
我们今天将重点讨论这个长颈鹿产品。
现在,让我们专门查看这款长颈鹿的评价。我将创建一个名为giraffe_reviews的变量来存储这些数据。
我将从所有产品评价中,通过一个筛选条件,选择出那些产品名称等于“Vulli Sophie the Giraffe Teether”的行。这就是我们一直在讨论的产品。
如果我们快速查看一下这个新数据表giraffe_reviews的长度,可以看到这款塑料玩具有785条评价。
分析产品评分分布
现在,让我们查看这款长颈鹿产品的评分情况。我将从giraffe_reviews中提取rating(评分)列,并像之前一样对其调用.show()方法进行可视化。
这次,我想使用一种特定的视图——分类视图。这种视图将提供一个分类直方图,展示不同评分等级(如1星到5星)分别获得了多少条评价。
观察这个小直方图,你会发现一些有趣的现象:人们非常喜爱这个产品。有535条评价是五星,这是最多的。其次是四星评价,然后是三星。有趣的是,一星评价的数量超过了二星评价。这意味着有相当数量的人非常讨厌这个产品,但绝大多数人喜爱它。
因此,进行情感分析会很有趣,可以帮助我们理解那些极端负面或极端正面的评价究竟在谈论什么,就像我们在这个模块课程中讨论过的那样。
为了实现这个目标,我们接下来将构建一个情感分类器。
总结

本节课中,我们一起学习了如何利用可视化工具探索数据集中的产品与评价分布。我们聚焦于最受欢迎的产品“Vulli Sophie牙胶长颈鹿”,通过直方图分析了其评分的分布情况,发现评价呈现两极分化。这为我们下一阶段构建情感分类器来分析评价文本的情感倾向奠定了基础。
第一部分 52:定义情感正负向 🎯

在本节课中,我们将学习如何为情感分类任务定义正面和负面情感。具体来说,我们会基于产品评分数据,通过数据工程的方法,明确区分哪些评论代表正面情感,哪些代表负面情感。
构建情感分类器 🛠️
上一节我们介绍了情感分类器的基本概念。本节中,我们来看看如何具体定义正面和负面情感。
情感分类器通常处理的是正面和负面情感,例如“点赞”和“点踩”。但需要注意的是,我们使用的产品评分数据并非直接以“正面”或“负面”的形式存在,而是数值型的评分。
例如,如果我们查看所有产品的评分分布:
# 查看所有产品评分的分布(以长颈鹿产品为例的扩展)
products['rating'].show(view='Categorical')
运行上述代码后,我们会得到一个所有评论评分的直方图。快速浏览该图可以发现,大多数评论都是正面的:有107,000条评论是五星好评。这符合常见现象,人们通常更倾向于为他们喜欢的产品撰写评论,而不是为他们不喜欢的产品写评论。
接下来,四星评论约有33,000条,然后是三星评论。同时,也有相当数量的人撰写非常负面的评论,即一星和两星评论。如果你真的讨厌一个产品,给两星和一星本质上没有太大区别,我们在直方图中也观察到了这一点。
然而,为了进行情感分析,我们必须明确界定什么是“点赞”(正面),什么是“点踩”(负面)。这里,我将做出一个主观的定义:
- 我们将四星或五星评论视为人们喜欢的,即正面情感。
- 将一星或两星评论视为负面情感。
- 至于三星评论,它们处于中间地带,比较模糊。因此,我们选择忽略这些三星评论。
这个过程就是我们所说的数据工程的一部分,即通过定义和转换数据来适应我们的机器学习任务。
实施数据工程步骤 ⚙️
现在,让我们开始实施上述定义。首先,我们需要从数据中移除三星评论。
以下是具体步骤:
第一步,忽略三星评论。我们从产品数据表 products 中,筛选出所有评分不等于3的记录。
# 第一步:过滤掉三星评论
products = products[products['rating'] != 3]
完成第一步后,我们的数据中只剩下了一星、二星、四星和五星的评论。接下来是此任务的核心步骤:定义正面和负面情感。
第二步,定义情感标签。我们将在数据表中添加一个新的列,名为 sentiment(情感)。这是一个二进制的列,取值为0或1。
我们这样定义它:
- 如果评分
rating大于或等于4(即四星或五星),则sentiment为 1(代表正面)。 - 如果评分
rating小于4(即一星或二星),则sentiment为 0(代表负面)。
用代码实现如下:
# 第二步:添加情感列,1代表正面(4-5星),0代表负面(1-2星)
products['sentiment'] = products['rating'] >= 4
# 将布尔值转换为整数(True->1, False->0)
products['sentiment'] = products['sentiment'].astype(int)
现在,如果我们再次查看数据表的前几行:
products.head()
你应该能看到新增了一个名为 sentiment 的列。正如我们之前观察到的,大多数情感标签是正面的(1),但也有不少是负面的(0)。
总结 📝

本节课中,我们一起学习了为情感分类任务准备数据的关键步骤。我们首先分析了评分的分布情况,然后通过数据工程的方法,定义了正面情感(四星和五星,对应标签1)和负面情感(一星和二星,对应标签0),同时移除了含义模糊的三星评论。最后,我们在数据集中创建了一个新的二进制 sentiment 列来存储这些标签。
现在,数据已经准备就绪,我们终于可以开始训练我们的情感分类器了。
第一部分 53:训练情感分类器 🧠

在本节课中,我们将学习如何训练一个情感分类器。我们将分两步进行:首先对数据进行训练集与测试集的划分,然后使用逻辑分类器构建情感模型。整个过程将使用GraphLab Create库完成,适合机器学习初学者。
数据划分:训练集与测试集 📊
上一节我们介绍了情感分析的基本概念,本节中我们来看看如何准备数据。首先,我们需要将数据集划分为训练集和测试集,这与回归课程中艾米丽讲解的方法一致。
以下是具体步骤:
- 我们使用产品评论数据表
products。 - 执行随机划分,80%的数据用于训练,20%用于测试。
- 为确保结果可复现,设置随机种子
seed=0。在实际应用中,您可以选择其他随机种子。
train_data, test_data = products.random_split(0.8, seed=0)
完成数据划分后,我们就可以开始构建情感分类模型了。
构建情感分类模型 🏗️
现在,我们使用GraphLab Create库来构建著名的情感分类模型。我们将使用一种特定的分类器——逻辑分类器。在后续的分类课程中,我们会学习更多分类器,如逻辑回归、支持向量机和决策树等。
以下是创建分类器的关键参数:
- 训练数据:使用上一步得到的
train_data。 - 目标:指定我们要预测的列是
sentiment(情感)。 - 特征:使用我们之前创建的
word_count(词频)列。 - 验证集:提供
test_data作为验证集,用于在训练过程中评估模型性能。
sentiment_model = graphlab.logistic_classifier.create(train_data,
target='sentiment',
features=['word_count'],
validation_set=test_data)
执行以上代码后,模型将开始训练。这个过程通常只需几秒钟。您会看到迭代过程以及随着训练进行,验证准确率逐步提升。
模型评估与总结 📈
训练完成后,我们可以对模型进行重新评估,以确认其最终性能。

本节课中我们一起学习了情感分类器的完整训练流程。我们首先将数据划分为训练集和测试集,然后使用逻辑分类器和词频特征构建了一个情感分析模型。通过观察训练过程中的验证准确率,我们看到了模型性能的逐步提升,这为后续更复杂的模型学习打下了基础。
第一部分 53:评估分类器:ROC曲线 📊

在本节课中,我们将学习如何评估已构建的情感分析模型。我们将重点介绍一种名为ROC曲线的评估方法,它帮助我们理解分类器在假阳性与真阳性之间的权衡。
模型评估概述
上一节我们讨论了分类错误率、精确度、假阳性和假阴性等概念。本节中,我们将通过实际演示来探索这些指标,并学习如何使用ROC曲线评估模型性能。
我们的情感模型提供了一个名为evaluate的函数,该函数允许我们在测试数据上评估模型质量,并使用特定的评估指标——ROC曲线。
理解ROC曲线
ROC曲线是一种可视化工具,用于探索假阳性和真阳性之间的关系,以及我们之前讨论的混淆矩阵。以下是ROC曲线的核心概念:
- 真阳性(True Positives, TP):模型正确预测为正类的样本数量。
- 假阳性(False Positives, FP):模型错误预测为正类的负类样本数量。
- 真阳性率(True Positive Rate, TPR):在所有实际为正类的样本中,被模型正确预测的比例。计算公式为:
TPR = TP / (TP + FN)。 - 假阳性率(False Positive Rate, FPR):在所有实际为负类的样本中,被模型错误预测为正类的比例。计算公式为:
FPR = FP / (FP + TN)。
ROC曲线描绘了在不同分类阈值下,TPR与FPR之间的关系。
可视化评估结果
文本形式的评估结果可能不够直观,因此我们使用可视化工具来展示。通过调用sentiment_model.show()并指定评估视图,我们可以清晰地看到ROC曲线和混淆矩阵。
以下是评估结果的关键数据点:
- 真阳性数:26455
- 真阴性数:4000(总负类样本为30965,这是一个高度不平衡的数据集)
- 假阳性与假阴性数:大致相同
- 整体准确率:91.1%(即0.911)
此外,我们还看到了一些其他指标,如精确度、召回率和F1分数,这些我们将在课程后续部分深入探讨。
探索分类阈值
关于假阳性和假阴性,一个关键点在于我们可以自然地调整分类阈值,即模型判定一个样本从负类转变为正类的临界点。
通过ROC曲线,我们可以直观地看到阈值变化的影响:
- 如果我们非常担心假阳性,可以设置一个非常保守的阈值。这样可以得到极低的假阳性率,但代价是只能捕获较少的真阳性(即真阳性率也较低)。
- 随着阈值逐渐放宽,我们沿着曲线移动,到达一个“拐点”。在这个点附近,我们可以用相对较少的假阳性增加,换取真阳性率的大幅提升。
- 如果我们设置一个非常宽松的阈值(例如,将所有样本都预测为正类),那么我们可以捕获所有的真阳性(真阳性率为1),但同时也引入了大量的假阳性。
你可以通过交互工具调整右侧的阈值滑块,并观察点在ROC曲线上移动,从而深刻理解这条曲线的含义。
课程总结

本节课中,我们一起学习了如何使用ROC曲线来评估分类器性能。我们了解到,ROC曲线通过描绘真阳性率与假阳性率在不同分类阈值下的变化,帮助我们直观地理解模型在识别正类样本时的能力与代价。通过调整阈值,我们可以在减少假阳性错误和捕获更多真阳性样本之间进行权衡,这对于实际应用中的模型调优至关重要。
机器学习基础篇(第1课/共4课)|应用模型查找产品最正面和最负面的评论 📊

在本节课中,我们将学习如何应用已训练好的情感分析模型,来识别产品评论中最正面和最负面的内容。我们将使用长颈鹿玩具的评论数据集作为示例,通过模型预测的情感评分对评论进行排序,从而快速定位极端的用户反馈。
应用模型预测评论情感
上一节我们介绍了如何构建并评估情感分析模型,其准确率约为91.1%。本节中,我们来看看如何实际应用这个模型来完成一项有趣的任务:分析用户对长颈鹿玩具的情感倾向。
首先,我们需要在已有的长颈鹿评论数据集上应用训练好的模型,生成一个新的列来存储预测的情感评分。
以下是具体步骤:

- 加载长颈鹿评论数据集。
- 调用之前训练好的
sentiment_model。 - 使用模型的
.predict()方法,并设置output_type='probability'参数,以获得更精细的情感概率预测,而不仅仅是0或1的分类结果。

# 应用模型预测情感概率
giraffe_reviews['predicted_sentiment'] = sentiment_model.predict(giraffe_reviews, output_type='probability')
运行以上代码后,数据集中将新增一个 predicted_sentiment 列。该列的值介于0到1之间,数值越接近1,代表模型预测该评论越正面;越接近0,则代表越负面。
查看与理解预测结果
现在,让我们查看添加了预测评分后的数据表。我们可以使用 .head() 方法预览前几行数据。
# 查看数据表的前几行
print(giraffe_reviews.head())
在输出中,你会看到每条评论都对应一个预测的情感概率值。例如,某些高度正面的评论得分可能高达0.999,而一些负面评论的得分可能低至0.001。这比简单的星级评分提供了更细致的洞察。

根据情感评分排序评论
拥有了连续的情感概率评分后,我们可以对评论进行排序,从而轻松找出最正面和最负面的评价。
以下是具体操作:
我们将根据 predicted_sentiment 列对数据集进行降序排序,这样最正面的评论会排在最前面。
# 根据预测情感评分降序排序
giraffe_reviews_sorted = giraffe_reviews.sort('predicted_sentiment', ascending=False)
参数 ascending=False 确保了排序顺序为从大到小(降序)。排序完成后,再次查看数据表的前几行,现在显示的就是预测为最正面的评论。
# 查看排序后最正面的几条评论
print(giraffe_reviews_sorted.head())
通过这个排序列表,产品经理或分析师可以快速聚焦于用户热情赞扬的方面,了解产品的优势所在。
查找最负面的评论
同理,如果我们想找出最负面的反馈,只需进行升序排序,让情感评分最低的评论排在最前面。
# 根据预测情感评分升序排序(找出最负面评论)
giraffe_reviews_sorted_negative = giraffe_reviews.sort('predicted_sentiment', ascending=True)
print(giraffe_reviews_sorted_negative.head())
查看这个列表的开头部分,就能迅速定位到那些表达强烈不满的评论。例如,可能会发现用户对产品尺寸、材质或功能有特定抱怨,这些是急需改进的关键点。
总结
本节课中,我们一起学习了如何将训练好的机器学习模型应用于实际业务场景。我们通过预测评论的情感概率,并对结果进行排序,高效地识别出了产品评论中的极端反馈——无论是高度赞扬还是强烈批评。
这种方法的价值在于:
- 精细化分析:概率评分比二元分类或星级评分提供了更丰富的信号。
- 提高效率:自动化处理海量评论,快速定位关键意见。
- 驱动决策:基于数据洞察,明确产品改进方向或营销重点。
掌握如何应用模型解读数据,是机器学习从理论走向实践的重要一步。
机器学习基础篇(第1课/共4课)📚:P57 - 文档检索:聚类与相似度度量案例研究
在本节课中,我们将学习聚类与相似度的概念,并通过一个真实的文档检索案例来理解其应用。我们将探讨如何从大量观测数据中推断出潜在的结构,特别是如何识别出相关的观测群组或“簇”。
概述

在数据科学中,我们常常面对大量的观测数据。为了理解这些数据,我们需要从中推断出某种潜在的结构。本节课将聚焦于一种特定的结构:由相关观测数据组成的群组,即“聚类”。我们将通过一个文档检索的实际案例来展开学习。
聚类与相似度的动机
上一节我们介绍了从数据中推断结构的目标。本节中,我们来看看一个具体的应用场景,它将帮助我们理解聚类和相似度度量的重要性。
我们以一个现实世界的应用——文档检索任务——作为案例研究。假设我们拥有大量文档,目标是快速找到与特定主题或查询相关的文档。手动完成这项任务效率低下,因此我们需要借助计算方法。

核心思想是:如果我们将文档视为高维空间中的点(例如,每个单词是一个维度),那么内容相似的文档在这个空间中的位置就会彼此靠近。我们的任务就是度量这种“靠近”的程度,并将靠近的文档归为一类。
核心概念:相似度度量
为了将文档分组,我们首先需要一种方法来量化两个文档之间的相似程度。以下是几种常见的相似度度量方法:
1. 欧几里得距离
这是最直观的距离度量,计算空间中两点之间的直线距离。
distance = sqrt((x1-y1)² + (x2-y2)² + ... + (xn-yn)²)
对于文档向量,距离越小,表示文档越相似。
2. 余弦相似度
在文本分析中更常用。它测量的是两个向量在方向上的差异,而非绝对距离。
similarity = (A·B) / (||A|| * ||B||)
其中 A·B 是点积,||A|| 是向量A的模长。值越接近1,表示方向越一致,内容越相似。
聚类算法简介
有了相似度度量方法,我们就可以使用聚类算法来发现文档中的自然分组。以下是两种基础算法的简要说明:
K-均值聚类 (K-Means)
- 预先指定希望找到的簇的数量K。
- 随机初始化K个中心点。
- 将每个数据点分配给最近的中心点,形成K个簇。
- 重新计算每个簇的中心点(即该簇所有点的均值)。
- 重复步骤3和4,直到中心点不再发生显著变化。
层次聚类 (Hierarchical Clustering)
这种方法不需要预先指定簇的数量。它通过连续合并或分裂簇来构建一个树状的聚类结构(树状图)。可以从树状图的任意层次切割,以获得不同粒度的聚类结果。
案例研究:文档检索系统
现在,让我们将理论应用于实践。在文档检索案例中,流程通常如下:
- 文本向量化:将每篇文档转换为数值向量。常用方法是词袋模型或TF-IDF(词频-逆文档频率)。
- 计算相似度矩阵:使用余弦相似度计算所有文档对之间的相似度。
- 应用聚类算法:使用K-均值或层次聚类算法对文档向量进行分组。
- 检索与查询:当用户提交一个查询时,将查询文本也转换为向量,并计算它与各个文档簇中心点的相似度。返回相似度最高的簇中的文档,或直接计算与所有文档的相似度并排序。
这种方法的好处是,通过预先聚类,系统可以快速将查询与最相关的几个簇进行比较,而不必与海量文档逐一对比,从而提高了检索效率。


总结
本节课中,我们一起学习了聚类与相似度度量的基础知识。我们从文档检索的实际问题出发,理解了如何通过相似度度量(如余弦相似度)来量化文档间的关联,并介绍了K-均值和层次聚类这两种基本的聚类算法来发现文档中的自然群组。通过这个案例,我们看到了机器学习如何帮助我们从无结构的数据中提取有价值的信息结构,并解决像信息检索这样的实际问题。
第一部分 58:什么是文档检索任务 📄🔍

在本节课中,我们将详细探讨文档检索任务。我们将了解该任务的基本定义、核心挑战以及实现自动文档推荐所需考虑的关键问题。

任务描述

上一节我们介绍了机器学习的基本概念,本节中我们来看看一个具体的应用场景:文档检索任务。
让我们更详细地描述这个任务。
假设我们正在阅读一篇文章。
实际上是卡洛斯正在阅读这篇文章,因为这是一篇关于足球的文章。
或者,按照他的说法,是“football”。如果他穿着阿根廷球衣,或者“Fucci ball”,如果他穿着巴西球衣。显然这两个词的发音我都不准确,卡洛斯稍后可以纠正我。但重点是,他喜欢这篇文章,而我们想要做的是检索另一篇他可能感兴趣的文章。

核心挑战
然而,问题在于我们如何做到这一点?世界上有大量的文章,我们不能指望他去阅读每一篇并判断是否感兴趣。因此,我们需要找到一种方法来自动检索他可能感兴趣的文档。
以下是实现自动文档推荐需要解决的两个核心问题:
-
如何衡量文章之间的相似性?
我们需要这个标准,才能判断某篇文章与他正在阅读的文章相似,从而可能引起他的兴趣;或者判断一大批文章与他当前阅读的内容差异很大,可能不会引起他的兴趣。 -
如何在现有文章中搜索并检索出下一篇要推荐的文章?
总结

本节课中,我们一起学习了文档检索任务的基本定义。我们了解到,该任务的核心目标是根据用户当前阅读的文档,自动推荐其可能感兴趣的其他文档。实现这一目标需要解决两个关键问题:定义文档间的相似性度量方法以及设计高效的搜索与检索策略。在接下来的课程中,我们将深入探讨解决这些问题的具体技术。
机器学习基础篇(第1课/共4课):用于度量相似度的词频表示 📚

在本节课中,我们将学习如何表示文本文档,以及如何基于这种表示来度量不同文档之间的相似度。这是信息检索和文档推荐等任务的基础。
文档表示:词袋模型 📄

首先,我们需要描述如何表示我们正在查看的文档。
最流行的文档表示模型之一是词袋模型。在这个模型中,我们简单地忽略文档中单词出现的顺序。之所以称为“词袋”,是因为我们可以想象将文档中的所有单词扔进一个袋子,摇晃均匀。这样,单词顺序被打乱后形成的新文档,其表示方式与原始有序文档的表示方式完全相同。
从结构到计数
我们不考虑单词的结构和顺序,而是简单地统计文档中每个单词出现的次数。

让我们看一个具体的例子。假设我们有一个非常短的文档,内容如下:
Carlos calls the sport football. Emily calls the sport soccer.
实际上,这是两个句子,但我们将它视为整个文档。为了统计这个短文档中的单词出现次数,我们将使用一个向量。这个向量基于我们所使用语言的词汇表来定义。
例如,在我们的词汇表中:
- 一个位置对应单词 “Carlos”。
- 另一个位置对应单词 “sport”。
- 还有位置对应 “football”、“Emily”、“calls”、“the” 和 “soccer”。
以下是该文档的词频统计向量:
- Carlos: 1
- calls: 2
- the: 2
- sport: 2
- football: 1
- Emily: 1
- soccer: 1
这个向量非常长且稀疏,因为它包含了词汇表中所有单词的位置,而大多数单词(如 “cat”、“dog”、“tree”)在该文档中的计数为零。

度量文档相似度 📏
上一节我们介绍了如何使用原始词频向量来表示文档。本节中,我们来看看如何度量不同文档之间的相似度,因为我们将利用这一点来查找彼此相关的文档。
想象一下,Carlos 正在阅读一篇关于著名阿根廷球员梅西的足球文章,我们有一个对应的词频向量。同时,还有另一篇关于著名足球球员帕韦(Pave)的蓝色文章及其词频向量。
相似度计算方法
我们可以通过计算两个向量的逐元素乘积之和来度量相似度。具体来说,对于向量中的每个元素,我们将两个不同计数向量中对应位置的数值相乘,然后将所有元素的乘积结果相加。
公式:
相似度 = Σ (向量A[i] * 向量B[i]),其中 i 遍历词汇表中的所有单词。
示例计算:
假设两篇足球文章的词频向量在 “Carlos” 位置分别是 1 和 3,在 “sport” 位置分别是 5 和 2,其他位置大多为 0。
那么相似度 = (1 * 3) + (5 * 2) + ... = 13。
现在,如果我们比较足球文章和另一篇关于非洲冲突的文章,由于它们没有共享重要的词汇,计算出的相似度很可能为零。这表明我们的方法能够区分不同主题的文档。
原始词频的问题与归一化解决方案 ⚖️

然而,使用原始词频度量相似度存在一个问题。让我们再次审视之前那两篇关于足球的绿色和蓝色文章。
我们之前计算出的相似度是 13。现在,假设我们将其中一篇文档的长度简单地加倍(即每个单词都出现两次),那么其词频向量也会变为原来的两倍。
问题:
当我们计算长文档与原始短文档的相似度时,结果会变成 52,远高于两个短文档之间的相似度(13)。这意味着,仅仅因为一篇文档更长,它就被认为与另一篇文档“更相似”。这在文档检索中是不合理的,因为它会强烈偏向于长文档。
如何解决:向量归一化
一个直接的解决方案是归一化词频向量。我们计算向量的范数(长度),然后用每个元素除以这个范数。
向量范数公式:
对于一个向量 v = (v1, v2, ..., vn),其范数(L2范数)为:
||v|| = sqrt(v1² + v2² + ... + vn²)
归一化公式:
v_normalized = v / ||v||
示例:
对于向量 (1, 5, 3, 1),其范数为 sqrt(1² + 5² + 3² + 1²) = sqrt(36) = 6。
归一化后的向量为 (1/6, 5/6, 3/6, 1/6)。
归一化操作将所有文档向量都缩放到单位长度,使得不同长度的文档能够站在同一起跑线上进行比较。之后,我们使用这些归一化后的向量进行相似度计算(即计算点积,其结果就是余弦相似度)。
总结 📝

本节课中我们一起学习了:
- 词袋模型:一种忽略单词顺序、仅统计词频的文档表示方法。
- 相似度度量:通过计算两个词频向量的逐元素乘积之和(点积)来量化文档间的相似性。
- 原始词频的局限性:直接使用原始词频会偏向于长文档。
- 归一化解决方案:通过计算向量的 L2 范数并除以它,将文档向量归一化到单位长度,从而公平地比较不同长度的文档,为后续的余弦相似度计算打下基础。
第一部分 60:使用TF-IDF优先考虑重要词语 📊

在本节课中,我们将学习如何通过TF-IDF方法,在文档表示中优先考虑重要词语。我们将探讨为何简单的词频统计存在局限,以及如何通过结合词语在文档中的局部频率和在整个语料库中的全局稀有性,来更准确地捕捉文档的核心内容。
上一节我们介绍了归一化词频向量,它解决了原始词频统计的一些问题。本节中,我们来看看如何进一步强调文档中的重要词语。


我们刚刚描述的归一化词频向量,有助于解决最初仅使用原始词频作为文档表示方案的一些问题。但还存在另一个问题:我们通常希望真正强调文档中的重要词语。因此,我们将讨论一下“重要词语”意味着什么,以及如何考虑强调它们。
在讨论重要词语之前,让我们先谈谈稀有词语。

再次想象我们正在阅读一篇关于足球的文章。这篇文章中有大量常见词语,如“the”、“player”、“field”、“goal”。所谓常见词语,指的是在整个语料库中频繁出现的词。“语料库”是我们在进行检索任务时所查看的所有文档的术语。
然而,当我们与其他文档进行比较时,这些常见词语会主导我们之前讨论过的相似性度量。正如我所说,这些词语出现在非常多的文档中。相比之下,我们正在查看的这篇文档中有一些非常稀有的词语,例如“football”和特定球员“Messi”。这些词语完全被所有常见词语淹没了。像“football”和“Messi”这样的词语被淹没,是因为它们在语料库中出现的频率非常低。因此,让我们思考如何增加这些稀有词语的重要性,因为它们通常是真正相关、能描述这篇文章独特之处、并可能指示Carlos(例如)有兴趣阅读的其他文章的词语。
那么,正如我们所说,稀有词语的特征在于它在语料库中不常出现。我们想要做的是以某种方式提升这些稀有词语的权重。等价地,除了强调只出现在少数文档中的词语,我们还可以考虑根据每个词语在整个语料库中出现的文档数量,来折减该词语的权重。


问题是,我们真的只想强调稀有词语吗?显然,我们不想强调那些非常常见的词语,比如“the”、“you”、“it”等等。我们想要包含的是对该文档非常相关的内容,不仅仅是像“Messi”这样的词,可能还包括“soccer”、“field”、“goal”等描述我们所关注运动的词语,这些可能不同于另一篇关于篮球、谈论“basketball hoop”和“court”等词语的体育文章。
在这种情况下,我们想要强调我称之为“重要词语”的东西。因此,我们将在这里进行权衡:我们将考虑那些在文档中出现频率很高的词语(即与当前阅读的文档相关),我称之为局部常见。

同时,我们希望它们在语料库中相对较少出现,我称之为全局稀有。所谓“重要”词语的特征,就是这种局部频率和全局稀有性之间的某种权衡。
核心概念与公式
基于以上讨论,TF-IDF的核心思想可以总结如下:
- 词频 (Term Frequency, TF):衡量一个词语在当前文档中出现的频率。频率越高,可能越重要。
- 常用计算方式之一:
TF(t, d) = (词语 t 在文档 d 中出现的次数) / (文档 d 中的总词数)
- 常用计算方式之一:
- 逆文档频率 (Inverse Document Frequency, IDF):衡量一个词语的普遍重要性。出现在越少文档中,IDF值越大,重要性越高。
- 常用计算方式:
IDF(t, D) = log( (语料库中文档总数 N) / (包含词语 t 的文档数 + 1) )
- 常用计算方式:
- TF-IDF:将两者结合,得到词语的最终权重。
TF-IDF(t, d, D) = TF(t, d) * IDF(t, D)
这个公式体现了我们追求的权衡:一个词语在当前文档中频繁出现(TF高),但在整个语料库中很少出现(IDF高),那么它的TF-IDF值就会很高,被认为是对该文档非常重要的词语。

总结
本节课中,我们一起学习了TF-IDF方法的核心思想。我们认识到,仅依赖词频或归一化词频不足以识别文档的独特内容,因为常见词语会干扰判断。TF-IDF通过结合词频(TF) 和逆文档频率(IDF),巧妙地权衡了词语的局部常见性和全局稀有性,从而能够优先考虑并提升那些真正能代表文档主题的重要词语的权重。这为后续的文档检索、分类等任务提供了更有效的文本表示方法。
第一部分 61:计算TF-IDF向量 📊


在本节课中,我们将学习一种在文本处理中常用的特征表示方法:TF-IDF(词频-逆文档频率)。这种方法能有效平衡词语在单个文档中的重要性与其在整个文档集合中的普遍性。
概述
上一节我们讨论了如何用词袋模型表示文本。本节中,我们来看看如何通过TF-IDF来改进这种表示,使其能更好地捕捉词语的重要性。
TF-IDF的核心思想是:一个词语的重要性,随着它在单个文档中出现的次数(词频)增加而提高,但随着它在整个文档集合中出现的频率(文档频率)增加而下降。这能帮助我们突出那些在特定文档中频繁出现,但在整个文档集合中却很少见的词语,这些词语往往具有更高的信息价值。
计算词频(Term Frequency)
首先,我们关注局部信息,即只查看用户当前正在阅读的单个文档。词频的计算很简单,就是统计目标词语在该文档中出现的次数。
公式:
TF(词, 文档) = 词在文档中出现的次数
这和我们之前做的词频统计是一样的,只是一个简单的计数因子。
计算逆文档频率(Inverse Document Frequency)
接下来,我们需要根据词语的全局稀有性来调整上述词频的权重。为此,我们要查看语料库中的所有文档,并计算逆文档频率。
公式:
IDF(词) = log( 语料库中文档总数 / (1 + 包含该词的文档数量) )
让我们分析一下这个公式的设计逻辑:
- 对于非常常见的词:假设一个词出现在几乎所有文档中。那么公式中的分子(文档总数)和分母(1 + 包含该词的文档数)会非常接近,结果近似于
log(1),也就是 0。这意味着,我们会将那些在所有文档中都频繁出现的词语的权重强烈下调至接近零。 - 对于非常罕见的词:假设一个词只在极少数文档中出现。那么分子(文档总数,一个大数)除以分母(1 + 一个很小的数),结果会是一个较大的数。取对数后,仍会得到一个非零且较大的数值。
- 公式中分母加 1 的原因是为了避免除零错误,因为我们不能假设词汇表中的每个词都一定出现在语料库的某个文档里。
TF-IDF向量的计算
现在,我们来看一个具体的例子,将词频和逆文档频率结合起来。
假设在某个文档中:
- 词语 “the” 出现了 1000 次。
- 词语 “messy” 出现了 5 次。
我们假设整个语料库共有 64 个文档。
计算“the”的IDF:
假设“the”这个词出现在除1个文档外的所有文档中(即出现在63个文档中)。那么其IDF为:
IDF("the") = log(64 / (1 + 63)) = log(64/64) = log(1) = 0
计算“messy”的IDF:
假设“messy”这个词只出现在 3 个文档中。那么其IDF为(以2为底的对数):
IDF("messy") = log(64 / (1 + 3)) = log(64/4) = log(16) = 4
计算TF-IDF:
要得到该文档的TF-IDF向量表示,我们只需将每个词的词频(TF)乘以其逆文档频率(IDF)。
- 对于 “the”:
TF-IDF = 1000 * 0 = 0 - 对于 “messy”:
TF-IDF = 5 * 4 = 20
以下是计算过程的总结:
- 计算词频(TF):统计词语在单个文档中的出现次数。
- 计算逆文档频率(IDF):基于整个语料库,衡量词语的普遍性。
- 计算TF-IDF:将TF与IDF相乘,得到最终的权重值。


如图所示,在最终的TF-IDF向量中,像 “the” 这样的常见词权重被下调至零,而像 “messy” 这样罕见且可能重要的词则被赋予了更高的权重。我们对词汇表中的所有其他词也进行同样的计算。
总结
本节课我们一起学习了TF-IDF向量的计算方法。我们了解到,TF-IDF通过结合词语的局部词频(TF)和全局逆文档频率(IDF),能够有效地对词语的重要性进行加权。这种方法可以抑制像“的”、“是”这类常见但信息量低的词语,同时提升那些在特定文档中关键且独特的词语的权重,从而为后续的机器学习任务(如文本分类、信息检索)提供更好的特征表示。
第一部分 62:使用最近邻搜索检索相似文档 📄🔍

在本节课中,我们将学习如何利用最近邻搜索算法,根据用户正在阅读的文章,从文档库中检索并推荐相似的文章。我们已经介绍了文档的表示方法以及文档间相似度的度量方式,现在我们将转向实际的任务——文档检索。

从文档表示到检索
上一节我们讨论了如何表示文档以及如何度量文档间的相似性。本节中,我们来看看如何将这些概念应用于实际的文档检索任务。假设用户正在阅读一篇文章,并且喜欢它,我们的目标是向他们推荐另一篇相关的文章。
什么是最近邻搜索?
一种非常流行的推荐方法是最近邻搜索。在这个任务中,我们有一个查询文章(即用户正在阅读的文章)和一个文档库(即我们想要从中搜索并推荐新文章的所有文档集合)。最近邻搜索需要指定一个距离度量(即我们之前讨论过的相似性度量方法),该算法将输出一组相关的文章。

最近邻搜索的算法
以下是两种基本的最近邻搜索方法。
1-最近邻搜索
1-最近邻搜索是最简单的形式。给定查询文章,算法从文档库中返回唯一一篇与查询文章最相关的文章。
其算法非常直接:
- 遍历文档库中的每一篇文章。
- 使用之前描述的方法,计算查询文章与当前被考察文章之间的相似度。
- 如果当前相似度高于迄今为止找到的最佳相似度,则将当前文章更新为最佳匹配文章。
- 遍历完所有文章后,将找到的最佳匹配文章推荐给读者。
K-最近邻搜索
K-最近邻搜索是1-最近邻搜索的一个直接变体。它不单单输出最相关的一篇文章,而是向读者推荐K篇最相关的文章。
其算法与1-最近邻搜索几乎相同,区别在于:
- 我们不再只保留最相关的一篇文章,而是维护一个优先队列,用于动态保存迄今为止找到的前K篇最相关文章。
总结

本节课中,我们一起学习了如何使用最近邻搜索进行文档检索。我们介绍了1-最近邻和K-最近邻两种基本算法,它们都基于文档的向量表示和相似度计算,从大型文档库中高效地找到与查询文章最相似的文档,从而实现个性化推荐。
第一部分 63:文档聚类任务概述 📄

在本节课中,我们将要学习文档聚类任务的基本概念。文档聚类是一种无监督学习方法,旨在将大量未标记的文档自动分组,使得同一组内的文档内容相似,不同组之间的文档内容差异较大。这种方法可以帮助我们组织和理解大规模文本数据。
上一节我们介绍了如何通过相似度度量来检索相关文档。本节中,我们来看看另一种处理文档集合的方法:文档聚类。
文档聚类的主要目标是将内容相关的文档自动分组。例如,我们可能有许多关于体育、国际新闻或其他主题的文章。如果我们能够以这种方式组织文档集合,当用户阅读一篇体育文章时,我们可以快速搜索所有其他体育类文章,而无需遍历整个文档库中的所有文章。
然而,这里的一个挑战是这些文章通常没有预定义的标签。不像《纽约时报》那样,每篇文章都有明确的分类标签(如“教育类文章”)。我们只有原始的文章文本,我们的目标是发现这些文章背后潜在的主题分组。
目标:发现相关文章的分组或聚类。例如,一个聚类可能代表所有关于体育的文章,另一个聚类则代表所有关于国际新闻的文章。


上一节我们讨论了无标签情况下的聚类挑战。现在,让我们暂时假设有人为我们提供了标签。
假设有人通读了我们文档库中的每篇文章(或至少大部分文章),并为它们添加了标签。例如,这些文章被标记为“体育”、“国际新闻”、“娱乐”和“科学”。这样,我们就拥有了一组带有标签的文章。
在这种情况下,当我们有一篇查询文章并希望将其分配到一个聚类时,问题就变成了一个多类别分类问题。因为核心问题是:这里有一篇查询文章,我不知道它的标签,但我有一批带有已知标签(如世界新闻、科学、体育、娱乐、技术)的文档。我只需要判断这篇文章属于哪个类别。
核心问题:这本质上是一个多类别分类问题。其形式化描述可以视为:
给定带标签的训练集 D = {(x_i, y_i)}, 其中 y_i ∈ {C1, C2, ..., Ck}, 学习一个模型 f: X -> Y, 以对新的查询文档 x_q 预测其类别 y_q。
如果情况如上所述,即我们拥有带标签的训练数据,那么这将是一个监督学习问题的典型例子。我们利用已知的输入(文档特征)和输出(类别标签)来训练一个分类器,然后用它来预测新文档的类别。

本节课中我们一起学习了文档聚类任务的基本概念。我们了解到,文档聚类的核心目标是在无标签的情况下发现文档的内在分组结构,这属于无监督学习。同时,我们也看到,如果拥有文档的预定义标签,那么同样的任务可以转化为一个监督式的多类别分类问题。理解这两种视角的差异,是掌握后续聚类算法和文本分类方法的基础。
第一部分 64:文档聚类:无监督学习任务 📚


在本节课中,我们将学习一种称为文档聚类的无监督学习任务。我们将了解其基本概念、输入输出形式,以及两种常见的聚类判定方法。
概述
文档聚类的目标是在没有预先提供标签的情况下,自动将相似的文档分组。输入是文档的词频向量,输出是为每个文档分配的聚类标签。
输入与输出
上一节我们介绍了无监督学习的基本概念,本节中我们来看看文档聚类的具体形式。
输入数据是文档的词频向量。每个观测点(即一篇文档)都由其在词汇表上各单词的计数向量表示。为便于可视化,我们假设词汇表仅包含两个单词,因此可以在二维平面上表示这些向量。横轴代表单词1的计数,纵轴代表单词2的计数。现实中,词汇表通常非常庞大,向量存在于高维空间。
以下是输入数据的图示说明:

算法的输出是聚类标签。每个文档都会被分配一个标签,表示其所属的组别。
以下是输出结果的图示说明:

例如,图中所有红色点被标记为“聚类1”,蓝色点被标记为“聚类2”,绿色点被标记为“聚类3”。这些标签是算法运行后自动生成的,属于无监督学习任务。我们可以在事后查看每个聚类中的文章,例如,可能发现“聚类1”中的文章都与体育相关。
聚类的定义
每个聚类由两个核心要素定义:聚类中心和聚类形状。
聚类中心通常可以视为该组数据的“平均”或“代表”点。聚类形状描述了组内数据点的分布情况,在图中常用椭圆来表示。
以下是聚类中心与形状的图示:

分配文档到聚类的方法
决定一个文档应属于哪个聚类,主要有两种思路。
方法一:基于聚类中心和形状
这种方法同时考虑文档到聚类中心的距离以及聚类的形状(即分布)。算法会为每个观测点基于目标聚类的中心和形状计算一个“得分”。
例如,在下图中,尽管粉色点距离红色聚类中心更近,但由于绿色聚类呈细长的椭圆形,该点最终被分配给了绿色聚类。


方法二:仅基于聚类中心
这是一种更常见且简单的方法。它只计算文档到各个聚类中心的距离,并将其分配给距离最近的中心。
以下是仅基于中心距离进行分配的图示:

在这种情况下,对于某些边界点(如图中粉色点),判断它属于红色还是绿色聚类会比较困难。但对于明显更靠近某一中心的点(如图中上方的点),分配则非常明确。
总结

本节课我们一起学习了文档聚类这一无监督学习任务。我们明确了其输入是文档的词频向量,输出是聚类标签。同时,我们探讨了聚类的两个定义要素——中心和形状,并介绍了两种将文档分配到聚类的方法:一种是综合考虑中心和形状,另一种是仅基于到聚类中心的距离。理解这些基础概念是掌握更复杂聚类算法的关键。
第一部分 65:K-means聚类算法 🧩


在本节课中,我们将学习一种名为K-means的聚类算法。该算法通过计算数据点到聚类中心的距离来对数据进行分组。我们将详细介绍算法的初始化、迭代过程以及收敛条件,确保初学者能够轻松理解。
算法概述
K-means算法是一种基于距离度量的聚类方法。它假设最终会得到K个聚类,因此需要预先指定聚类的数量。算法的名称来源于“K个聚类”和“聚类中心(均值)”这两个概念。
上一节我们介绍了聚类的基本概念,本节中我们来看看K-means算法的具体步骤。
初始化算法
首先,我们需要初始化聚类中心。初始化方法有多种,但为了简化,我们通常随机选择K个点作为初始聚类中心。例如,如果我们使用K=3,就随机指定三个聚类中心。
以下是初始化步骤的简要说明:
- 随机选择K个点作为初始聚类中心。
- 这些中心点将作为后续迭代的起点。
分配数据点到最近中心
初始化后,第一步是将每个数据点分配到距离最近的聚类中心。这个过程类似于构建一个Voronoi图(泰森多边形)。
我们可以这样理解:以聚类中心为基点,将整个空间划分为多个区域。每个区域内的任何点,其最近的聚类中心都是该区域的基点。
以下是分配过程的要点:
- 计算每个数据点到所有聚类中心的距离。
- 将数据点分配给距离最近的聚类中心。
- 根据分配结果,数据被初步划分为K个组。
更新聚类中心
分配完成后,我们得到了一组初步的聚类结果。但由于初始中心是随机选择的,这些聚类可能无法准确反映数据的真实结构。
因此,我们需要迭代这个过程。下一步是基于当前分配到每个聚类的所有数据点,重新计算该聚类的中心。新的聚类中心通常是该簇所有点的“质心”(即坐标平均值)。
以下是更新步骤的说明:
- 对于每个聚类,计算其所有成员点的平均值。
- 将这个平均值点设置为该聚类的新中心。
- 例如,如果一个聚类只有一个点,那么新中心就移动到这个点的位置;如果一个聚类包含多个点,新中心则移动到这些点的中心位置。
迭代与收敛
得到新的聚类中心后,我们可以重复上述步骤:
- 根据新的中心点,重新划分Voronoi区域,并将所有数据点重新分配到最近的新中心。
- 基于新的分配结果,再次更新每个聚类的中心点。
我们将这个过程不断重复,直到算法收敛。收敛通常意味着聚类中心不再发生显著变化,或者数据点的分配情况保持稳定。
总结
本节课中我们一起学习了K-means聚类算法。我们了解到,该算法需要预先指定聚类数量K,并通过“分配-更新”的迭代过程,不断优化聚类中心的位置,直到结果稳定。其核心步骤可以概括为:
- 初始化:随机选择K个初始聚类中心。
- 分配:将每个点分配到最近的聚类中心。
- 更新:根据分配结果,重新计算每个聚类的中心点。
- 迭代:重复步骤2和3,直至收敛。


K-means算法以其简单高效的特点,成为最常用的聚类方法之一。
第一部分 66:聚类的其他应用示例 🎯


在本节课中,我们将学习聚类算法在不同领域中的多种应用示例。通过了解这些实际案例,你将更深入地理解聚类技术的广泛用途和实际价值。
上一节我们详细讨论了聚类在文档检索中的应用。本节中,我们来看看聚类在其他领域的几个典型示例。

以下是聚类的一些重要应用场景:

- 图像搜索:例如,在谷歌图片搜索中,如果我们能根据“海洋”、“粉红色花朵”、“狗”、“日落云彩”等类别对所有图片进行聚类和结构化,将极大地提升搜索的效率和准确性。
- 患者分组:目标是根据患者的医疗状况进行分组,以更好地描述亚群和不同疾病。例如,我们可以研究一群癫痫患者。

上图展示了三位不同患者的大脑,他们有不同的记录装置来测量癫痫活动。

对于每位患者,我们获得了一系列他们随时间表现出的不同癫痫发作记录。每个彩色方块代表一次不同的癫痫发作记录。在这些不同患者之间,可能存在相似的癫痫发作类型。
我们可以收集所有三位患者的癫痫发作记录并进行聚类分析。通过这种方式识别出不同类型的癫痫,可以帮助我们根据患者表现出的癫痫类型来更好地进行治疗。
- 产品推荐:例如,在亚马逊上,许多第三方卖家会发布待售产品并为其提供标签。假设有人想出售一张婴儿床,并合理地将其标签为“家具”类。但如果我们查看购买此商品的用户及其购买历史,并对比具有相似购买历史的其他人,可能会发现购买此婴儿床的用户也购买了婴儿汽车座椅。那么,我们可以推断,这张被标记为“家具”的婴儿床,更好的标签应该是“婴儿产品”。
除了根据购买历史发现相关的产品组,我们还可以用此方法来发现亚马逊上相关的用户群组,并用于向这些用户定向推荐产品。

- 结构化网络搜索结果:例如,搜索词可能有多重含义,比如单词“cardinal”。在谷歌中搜索该词,用户可能想查找关于“红衣主教鸟”的文章,也可能是关于“棒球队”或“宗教人物红衣主教”的信息。


如果我们能基于文章内容,运用本模块讨论过的同类思想对其进行聚类和结构化,就可以为用户提供更精准的搜索结果。
应用列表还可以继续延伸。另一个非常有趣的应用是考虑社区集合。在多个场景中,我们都需要发现相似的社区。

- 房价估算:当我们想在非常局部的地域层面估算房屋价格时,面临的挑战是,在一个很小的社区内,我们通常只有很少甚至没有房屋销售观测数据。因此,要估算该社区在某个时间点的房屋价值非常困难,因为缺乏该社区内其他房屋数据作为估算基础。然而,如果我们能发现具有相似类型房屋动态(房价动态)的其他社区,就可以利用从这些被发现与当前社区相关的其他社区中获取的信息,来对销售数据稀少或没有销售的社区内的房屋进行良好估算。其核心思想是发现社区集群,然后在集群内共享信息(如房屋销售信息)以形成更好的估计。这里描述的解决方案是:对具有相似趋势的区域进行聚类,然后在聚类内共享信息。
- 犯罪预测与警力部署:同样的发现相关区域的思路,可用于帮助预测暴力犯罪,从而更好地向不同区域部署警力。同样,一旦我们发现具有非常相似犯罪动态的不同社区,就可以对这些社区的暴力犯罪率形成更好的预测,并利用该信息向这些区域分派警力。

本节课中,我们一起学习了聚类算法在图像搜索、医疗分组、产品推荐、搜索结果优化、社区分析与房价估算、犯罪预测等多个领域的实际应用。这些示例表明,聚类作为一种强大的无监督学习技术,能够帮助我们从数据中发现内在结构、识别相似群体,并为各种决策提供支持,其应用范围极为广泛。
第一部分 67:聚类与相似度 📊

在本节课中,我们将学习聚类算法的完整工作流程。我们将从文档聚类任务出发,探讨如何通过无监督学习发现数据中的潜在结构,并详细介绍K-means算法的核心机制。


概述:聚类算法工作流程
在本模块中,我们讨论了文档检索任务,并介绍了聚类的概念——即试图揭示数据中的潜在结构。我们探讨了聚类在许多不同领域中的广泛应用。现在,让我们深入理解聚类算法的工作流程。
如果你觉得已经掌握了这部分内容,因为你在其他模块中也见过类似的工作流程,那么请注意,本节内容将有所不同。
训练数据与特征提取
首先,我们来看聚类任务的训练数据。对于文档聚类任务,训练数据通常包括文档ID和文档文本。我们拥有大量文档,以及每篇文档对应的全部文本内容。
接下来,我们需要从文档中提取特征。我们讨论过多种文档表示方法,但这里我们以TF-IDF(词频-逆文档频率)表示法为例。其核心思想是衡量一个词在文档中的重要程度。
TF-IDF公式:
TF-IDF(t, d) = TF(t, d) * IDF(t)
其中:
TF(t, d)是词t在文档d中的词频。IDF(t)是词t的逆文档频率,计算公式为log(N / (df(t) + 1)),N是文档总数,df(t)是包含词t的文档数。
提取特征后,我们将基于这些特征表示对文档进行聚类。这意味着我们要将这些特征输入某个机器学习模型——在本例中是聚类模型。
模型输出与无监督学习挑战
模型的输出是为每篇文档分配一个聚类标签。这个输出,我们称之为预测的或估计的聚类标签。
然而,这里出现了一个关键问题:我们如何评估这些聚类标签的准确性?在聚类任务中,我们并没有真实的、已知的聚类标签可供比较。这是因为我们处于无监督学习的设置中。我们无法获得那个用于对比的“真实答案”。
评估聚类质量:内聚性度量
既然没有真实标签,我们如何评估聚类的质量呢?让我们通过K-means算法中的Voronoi图来理解。
假设我们有一些聚类中心和一些数据点。一个良好的聚类算法会使得每个数据点与其所属聚类中心之间的距离非常小。因此,我们的目标是最小化这些距离。
为了度量这个“准确性”或质量,我们需要两样东西:
- 我们的数据,即TF-IDF向量。
- 当前的聚类中心,这是K-means算法中的模型参数。
我们将文档表示和聚类中心代入一个质量度量函数,该函数计算所有数据点到其对应聚类中心的距离。这个距离总和(或平均距离)就是我们对聚类质量的度量。它并非传统意义上的“误差”,而是一种内聚性的衡量标准。
K-means算法详解
我们讨论的算法是K-means,它是一种常用的聚类方法。K-means的目标正是最小化上述提到的距离总和。它是如何做到的呢?通过迭代优化。
算法流程如下:
- 初始化聚类中心。
- 分配步骤:将每个数据点分配给距离最近的聚类中心。
- 更新步骤:重新计算每个簇中所有点的均值,并将该均值设为新的聚类中心。
- 重复步骤2和3,直到聚类中心不再发生显著变化或达到预定迭代次数。
用伪代码描述核心更新过程:
# 假设有数据点X和当前聚类中心centroids
# 分配步骤
labels = assign_each_point_to_nearest_centroid(X, centroids)
# 更新步骤
new_centroids = compute_mean_of_points_in_each_cluster(X, labels)

这个过程不断循环,通过观察数据点到当前聚类中心的距离来更新聚类中心(即模型参数),从而逐步提升聚类的内聚性。

总结与拓展
在本模块中,与之前一些模块不同,我们深入探讨了方法背后的算法细节。具体来说,对于聚类,我们详细讲解了K-means算法;对于文档检索任务,我们还讨论了最近邻搜索及其算法细节,并让你在IPython笔记本中具体探索了维基百科条目检索的实现。
至此,你应该能够着手构建一个非常酷的检索系统,用于新闻文章检索或任何其他你能想到的、有趣的应用场景。当然,现实中存在大量有趣的例子,期待你去探索那些我此刻尚未想到的创意。
本节课我们一起学习了聚类算法的工作流程,理解了在无监督设置下如何通过内聚性度量评估模型,并掌握了K-means算法的核心迭代机制。这些是构建更复杂数据理解系统的基础。
第一部分 68:加载并探索维基百科数据 📚

在本节课中,我们将学习如何加载一个维基百科人物数据集,并对其进行初步探索。我们将使用Python和GraphLab Create库来操作数据,并查看其中包含的具体内容。

上一节我们介绍了本课程的目标,本节中我们来看看如何实际操作数据。


首先,我们需要导入必要的库并加载数据。
import graphlab
以下是加载数据的具体步骤:
people = graphlab.SFrame('people_wiki.gl/')
数据加载完成后,我们可以先查看数据的前几行,以了解其结构。
people.head()
你会看到数据包含三列:URI(维基百科页面链接)、name(人物姓名)和text(页面正文文本)。这个数据集包含了大约59,000个人物的信息。
现在我们已经加载了数据,接下来让我们更深入地探索其中的内容。
我们可以查看特定人物的页面信息。例如,让我们查看美国前总统巴拉克·奥巴马(Barack Obama)的页面。
以下是筛选并查看奥巴马页面的代码:
obama = people[people['name'] == 'Barack Obama']
obama['text']
输出显示:“Barack Hussein Obama was born on August 4th, 1961 and is the 44th and current president of the United States.” 这正是我们期望看到的维基百科文本格式。

为了进一步理解数据集的多样性,我们可以再查看另一位人物的信息。
让我们查看演员乔治·克鲁尼(George Clooney)的页面。
以下是相应的代码:
clooney = people[people['name'] == 'George Clooney']
clooney['text']
输出显示:“George Timothy Clooney was born in 1961... He is an American actor, writer, producer, director, and activist.” 通过对比,我们可以看到数据集包含了来自不同领域的人物信息。

本节课中我们一起学习了如何加载维基百科人物数据集,并使用简单的筛选操作来探索特定人物的页面内容。我们看到了数据的结构,并初步了解了文本信息的形式。在接下来的课程中,我们将基于这些数据构建更复杂的文档检索系统。
第一部分 69:探索词频 📊

在本节课中,我们将学习如何探索文本数据中的词频。我们将使用维基百科上关于巴拉克·奥巴马的文章作为示例,通过计算和排序词频来理解文本内容。同时,我们还将介绍一个实用的数据处理技巧,帮助您更高效地处理字典类型的数据。
数据概览
我们正在处理一个相当整洁的数据集。在之前的讲座中,Emily 提到了构建词频计数及其面临的一些挑战。本节中,我们首先快速查看一下词频计数。
以下是我们要分析的维基百科文章数据示例。

计算奥巴马文章的词频
首先,我们以维基百科上关于巴拉克·奥巴马的文章为例,快速查看其词频计数。
我们创建一个名为 Obama 的变量,并为其添加一个名为 word_count 的新列。这个列将用于存储巴拉克·奥巴马文章的词频计数。
我们可以通过调用文本分析工具箱中现成的函数 count_words 来实现。虽然您也可以像在情感分析分类笔记中展示的那样,自己编写函数来计算词频,但为了快速开始,我们直接使用这个现成的函数。
# 调用 count_words 函数计算词频
Obama['word_count'] = count_words(Obama['text'])
现在,我们已经计算了词频。让我们快速打印出来看看。
print(Obama['word_count'])
执行后,您会看到类似“operations”出现1次、“represent”出现1次、“office”出现2次、“unemployed”出现1次等结果。目前,这些数据看起来并不直观。接下来,我们将进一步处理这些数据,并在此过程中展示一个在其他领域也可能有用的数据处理技巧。
排序词频数据
为了更好地理解词频数据,我们需要对其进行排序。请注意,word_count 是一个类似 Python 字典的结构,其中键是单词(例如“Honolulu”、“marriage”等),值是该单词出现的次数(例如1、2、3、5、30等)。
为了对这些单词进行排序,我们需要将其转换为一个表格,其中一列是单词(字典的键),另一列是计数。然后,我们将对这个表格进行排序。
有多种方法可以在 Python 中实现这一点。下面我将展示一个快速且实用的小技巧。
首先,我创建一个名为 Obama_word_count_table 的新表格。
# 从 Obama 表中选择 word_count 列,并利用 stack 函数转换
Obama_word_count_table = Obama[['word_count']].stack(column_name='word_count', new_column_name=['word', 'count'])
stack 函数非常有用。它接受 SFrame 中包含字典的一列,并将其堆叠成多列(本例中是两列:word 和 count)。我们需要指定要堆叠的列名(这里是 word_count)以及新列的名称(word 和 count)。
执行后,我们查看这个新表的前几行。
print(Obama_word_count_table.head())
您会看到单词如“normalize”、“sort”、“combat”等,但表格尚未排序。接下来,我们只需按 count 列对这个表格进行排序。
# 按计数降序排序
Obama_word_count_table = Obama_word_count_table.sort('count', ascending=False)
我们之前已经见过排序操作,这很简单。我们调用 sort 函数,按 count 列排序,并设置 ascending=False 以实现降序排序(从高到低,例如3、2、1),而不是默认的升序排序(1、2、3)。
按下回车后,您会看到最常见的单词是“the”,其次是“in”、“and”、“of”、“to”、“his”,最后才是“Obama”等。这些单词信息量不大。在讲座中,Emily 曾提到,这些无信息的单词可能会淹没重要的单词,这正是我们引入 TF-IDF 概念的原因。
总结
本节课中,我们一起学习了如何探索文本数据的词频。我们从计算奥巴马文章的词频开始,然后通过一个实用的 stack 函数技巧将字典数据转换为表格格式并进行排序。最后,我们观察到简单词频计数的局限性,即常见但信息量少的单词(如“the”、“in”)会占据主导,从而引出了下一节将要深入学习的 TF-IDF 概念,该概念能更好地衡量单词在文档中的重要性。




第一部分 70:计算与探索TF-IDF 📊

在本节课中,我们将学习如何为一个文档集合(语料库)计算TF-IDF值,并探索其在文本分析中的应用。我们将使用GraphLab Create库来简化计算过程,并通过实际例子展示TF-IDF如何帮助我们识别文档中的关键词语。
计算整个语料库的TF-IDF
上一节我们介绍了TF-IDF的基本概念,本节中我们来看看如何为一个完整的文档集合计算TF-IDF值。需要注意的是,不能孤立地计算单篇文章的TF-IDF,因为TF-IDF依赖于整个语料库。具体来说,IDF(逆文档频率)的计算需要知道每个词语在所有文档中出现的频率。
因此,我们必须对整个语料库进行计算。我们将分两步完成:
- 为语料库中的每篇文章计算词频。
- 基于词频计算TF-IDF值。
以下是具体步骤:
首先,我们需要为整个语料库计算词频。我们将为people数据表添加一个名为word_count的新列,用于存储每篇文章的词频字典。
people['word_count'] = graphlab.text_analytics.count_words(people['text'])
print people.head()
执行上述代码后,数据表中将新增一个word_count列,其中包含了每篇文章的词语计数字典。
接下来,我们将计算TF-IDF。与计算词频类似,GraphLab Create库提供了内置的tf_idf函数,可以快速完成计算。我们只需将上一步得到的word_count列作为输入即可。
tfidf = graphlab.text_analytics.tf_idf(people['word_count'])
计算完成后,我们会得到一个包含每篇文章TF-IDF字典的新表。为了便于管理,我们将这个新列添加到people表中。
people['tfidf'] = tfidf['docs']
现在,people表中已经存储了所有文档的TF-IDF值,我们可以开始进行探索性分析了。
探索奥巴马文章的TF-IDF结果
在计算了所有文档的TF-IDF之后,让我们聚焦于奥巴马的文章,看看TF-IDF值如何帮助我们识别关键词语。
首先,我们从people表中提取出奥巴马的文章数据。
obama = people[people['name'] == 'Barack Obama']
接着,我们提取并整理奥巴马文章的TF-IDF数据。我们将TF-IDF字典展开为两列(词语和TF-IDF值),并按TF-IDF值降序排列,以便查看最重要的词语。
obama_tfidf_table = obama[['tfidf']].stack('tfidf', new_column_name=['word', 'tfidf']).sort('tfidf', ascending=False)
当我们执行这段代码并查看结果时,会发现一个显著的变化:排名最高的词语是“Obama”,这非常合理,因为文章就是关于他的。紧随其后的词语包括“Act”、“Iraq”、“control”、“law”、“order”、“military”、“involvement”、“response”、“Democratic”等。
这些词语清晰地揭示了文章的核心内容:奥巴马在军事、法律、伊拉克问题以及民主党事务上的行动和参与。与单纯基于词频的排序(其中充斥着“the”、“and”、“in”等常见但信息量低的词语)相比,TF-IDF有效地过滤了常见词,突出了具有实际信息价值的关键词。
总结


本节课中我们一起学习了如何为整个文档集合计算TF-IDF,并探索了其结果。我们了解到,TF-IDF的计算必须基于整个语料库,而不能孤立进行。通过使用GraphLab Create库,我们可以高效地完成词频统计和TF-IDF计算。最后,通过对奥巴马文章TF-IDF结果的分析,我们看到了TF-IDF如何有效地从文档中提取出最具信息量的关键词语,这比单纯依赖词频能提供更深刻的文本洞察。
第一部分 70:计算维基百科文章之间的距离 📏

在本节课中,我们将学习如何利用TF-IDF向量计算维基百科文章之间的距离。我们将通过手动计算几位知名人物文章间的相似度,直观理解TF-IDF向量的含义,并最终使用最近邻模型实现自动化的文档检索。
手动计算人物文章距离
上一节我们介绍了TF-IDF向量的计算。本节中,我们来看看如何利用这些向量计算文档之间的距离。我们将手动选取三位人物——巴拉克·奥巴马、比尔·克林顿和大卫·贝克汉姆,并计算他们对应文章之间的余弦距离。
首先,我们需要从数据中提取这三位人物的TF-IDF向量。假设我们已经有一个名为people的数据集,其中包含name列和tfidf列。
以下是选取克林顿和贝克汉姆向量的代码示例:

clinton = people[people['name'] == 'Bill Clinton']
beckham = people[people['name'] == 'David Beckham']
现在,我们有了代表奥巴马、克林顿和贝克汉姆文章的三个TF-IDF向量。我们的目标是计算奥巴马与克林顿、以及奥巴马与贝克汉姆之间的余弦距离。



计算余弦距离
有多种方法可以衡量两个向量(或文档)之间的距离。我们将使用余弦距离。请注意,余弦距离是余弦相似度的变体:距离值越低,表示两篇文章越相似;最高距离值为1。
我们将使用工具库中现成的函数来计算距离,无需自己实现。
以下是计算奥巴马与克林顿之间余弦距离的代码:
obama_tfidf = people[people['name'] == 'Barack Obama']['tfidf'][0]
clinton_tfidf = clinton['tfidf'][0]
beckham_tfidf = beckham['tfidf'][0]
# 计算余弦距离
dist_obama_clinton = graphlab.distances.cosine(obama_tfidf, clinton_tfidf)
dist_obama_beckham = graphlab.distances.cosine(obama_tfidf, beckham_tfidf)
print("奥巴马与克林顿的余弦距离:", dist_obama_clinton)
print("奥巴马与贝克汉姆的余弦距离:", dist_obama_beckham)
运行上述代码后,我们可能会得到类似以下的结果:
- 奥巴马与克林顿的余弦距离:0.83
- 奥巴马与贝克汉姆的余弦距离:0.97
这个结果符合我们的直觉:作为两位美国总统,奥巴马的文章与克林顿的文章更相似(距离0.83),而与英国足球运动员贝克汉姆的文章差异较大(距离0.97)。
从手动计算到自动化检索
我们手动验证了TF-IDF向量能够有效反映文档间的语义相关性。然而,对于包含成千上万篇文章的数据集,手动计算是不现实的。
在课程中,Emily老师介绍过最近邻模型可用于文档检索。接下来,我们将利用一个简单的最近邻模型,自动化地找出与任何给定文章最相似的其他文章。
具体来说,我们将:
- 使用所有文章的TF-IDF向量构建一个最近邻模型。
- 输入某个人物的名字(例如“Barack Obama”)。
- 模型会自动返回与其文章最相似的其他人物列表。
这使我们能够快速探索数据集中复杂的关联关系,而无需进行繁琐的手动比较。
总结
本节课中我们一起学习了:
- 手动计算文档距离:通过选取特定人物的TF-IDF向量,并计算他们之间的余弦距离,直观理解了向量相似度的含义。
- 理解余弦距离:认识到余弦距离值越小,文档越相似;并验证了TF-IDF特征在区分不同主题人物上的有效性。
- 引入自动化工具:认识到对于大规模数据,需要借助如最近邻模型这样的机器学习模型来实现高效的相似文档检索。


通过本讲,我们为下一阶段使用机器学习模型进行自动化文档分析与检索打下了坚实的基础。
第一部分 72:为维基百科文章构建并探索最近邻模型 🧠📚

在本节课中,我们将学习如何为维基百科文章构建一个最近邻模型,并使用该模型进行文档检索。我们将使用TF-IDF特征,并通过GraphLab Create库中的现有实现来快速完成这一任务。
构建最近邻模型 🔧
上一节我们介绍了最近邻模型及其在文档检索中的应用。本节中,我们来看看如何实际构建这样一个模型。
以下是构建最近邻模型的步骤:
- 导入必要的库和数据集。
- 使用TF-IDF特征作为模型的输入。
- 指定一个标签列(例如人名),以便模型返回可读的结果。
我们将使用GraphLab Create库中名为nearest_neighbors的模型。创建模型的代码如下:
model = graphlab.nearest_neighbors.create(people,
features=['tfidf'],
label='name')
这段代码以people数据表为输入,使用tfidf列作为特征,并指定name列作为标签。模型构建完成后,我们就可以用它进行查询了。
应用模型进行检索 🔍
模型构建完成后,我们就可以用它来查找与特定人物最相似的其他维基百科文章了。
以下是进行查询的步骤:
- 使用模型的
.query()方法。 - 输入一个查询对象(例如一个人名)。
- 模型将返回最相似的邻居及其标签。
让我们进行第一个查询:找出与奥巴马最相似的人物。
obama_neighbors = model.query('Barack Obama')
print obama_neighbors
查询结果会快速返回。不出所料,与奥巴马最相似的人是他自己。紧随其后的是美国副总统乔·拜登,这很合理。结果中还包含其他一些政治家,例如我们之前看到过的前总统比尔·克林顿。
总结 📝


本节课中,我们一起学习了如何为维基百科文章构建并应用一个简单的最近邻模型进行文档检索。我们使用了TF-IDF特征来量化文档,并利用现有的库工具快速实现了模型的构建和查询。通过查询“奥巴马”,我们验证了模型能够返回语义上相近的人物,这展示了最近邻模型在信息检索中的实用性和直观性。
第一部分 73:文档检索实际应用示例 📄➡️🔍

在本节课中,我们将通过几个具体的例子,学习如何将之前介绍的TF-IDF和最近邻模型应用于实际的文档检索任务。我们将看到,这个简单的系统能够根据文档内容,有效地找到相似的人物。
上一节我们介绍了文档检索的基本原理,本节中我们来看看它在真实数据上的表现。我们将使用一个包含维基百科人物简介的数据集,通过查询特定人物,来查找与其最相似的其他人物。
以下是第一个检索示例:
- 查询对象:歌手 泰勒·斯威夫特 (Taylor Swift)。
- 检索结果:系统返回了与她最相似的人物列表。
- 结果分析:列表中出现的是凯莉·安德伍德 (Carrie Underwood)、艾丽西亚·凯斯 (Alicia Keys) 等女性歌手。这表明系统成功捕捉到了“女性流行歌手”这个核心特征,并找到了具有相似职业和时代背景的人物。
接下来,我们看另一个例子:
- 查询对象:演员 安吉丽娜·朱莉 (Angelina Jolie)。
- 检索结果:运行查询后,系统返回了最近邻人物。
- 结果分析:最相似的人物是布拉德·皮特 (Brad Pitt),随后是朱丽安·摩尔 (Julianne Moore)、比利·鲍伯·松顿 (Billy Bob Thornton) 等。这个结果很有趣,它不仅找到了其他知名演员,还反映了人物之间的公开关系(朱莉与皮特曾为夫妻),说明模型从文本中捕捉到了深层的关联信息。
最后,我们来看一个能体现人物多重身份的复杂例子:
- 查询对象:阿诺德·施瓦辛格 (Arnold Schwarzenegger)。
- 检索结果:查询其最近邻人物。
- 结果分析:结果中包含了杰西·文图拉 (Jesse Ventura)(同为摔跤手、演员),以及美国俄勒冈州、罗德岛州的前州长等政治人物。这个结果准确地反映了施瓦辛格的多重身份:健美运动员、演员和政治家(加州前州长)。模型成功地从其文档中识别出这些特征,并找到了在不同维度上相似的人物。

本节课中我们一起学习了文档检索系统的实际应用。通过泰勒·斯威夫特、安吉丽娜·朱莉和阿诺德·施瓦辛格三个例子,我们看到了如何利用 TF-IDF 向量化和 最近邻 (Nearest Neighbor) 搜索,从一个大型文档集合(如维基百科)中,快速找到与查询对象内容相似的其他文档。这个简单的流程展示了机器学习在信息检索中的强大和实用之处。
第一部分 74:推荐系统概述 📚

在本节课中,我们将要学习推荐系统的基本概念。推荐系统是机器学习中一个非常实用且广泛应用的领域,它能够根据用户的历史行为和其他用户的数据,为用户推荐可能感兴趣的产品或内容。
什么是推荐系统? 🤔
推荐系统的一个典型应用场景是产品推荐。想象一下,你拥有大量产品,同时有许多用户,你希望向这些用户推荐一部分产品。那么,问题来了:我们该如何实现这一目标?我们将探讨如何利用机器学习技术,结合你个人的购买历史以及其他用户的购买记录,来决定向你推荐哪些产品。
推荐系统的应用范围非常广泛,在过去十年中,其受欢迎程度急剧上升。亚马逊是这一领域的早期先驱,专注于我们将要讨论的产品推荐应用。另一个使推荐系统广为人知的例子是Netflix在2006年至2009年间举办的竞赛,该竞赛提供了100万美元的奖金,奖励那些能为用户推荐电影的最佳推荐系统。在本模块中,我们将简要讨论这一应用,它确实推动了该领域的大量活动,促进了新推荐系统的开发以及后续的许多研究。
推荐系统的核心应用 🌟
以下是推荐系统的一些核心应用领域:
- 产品推荐:例如,电商平台根据用户的浏览和购买历史,推荐相关商品。
- 内容推荐:例如,流媒体平台根据用户的观看记录,推荐电影或视频。
- 个性化服务:通过分析用户行为,提供定制化的信息或服务。
总结 📝

本节课我们一起学习了推荐系统的基本概念。我们了解到,推荐系统通过分析用户的历史数据和其他用户的行为,能够智能地向用户推荐他们可能感兴趣的产品或内容。从亚马逊的产品推荐到Netflix的电影推荐竞赛,推荐系统已经成为现代数字生活中不可或缺的一部分。在接下来的课程中,我们将深入探讨推荐系统背后的具体机器学习算法和实现原理。
第一部分 75:推荐系统应用场景 🎯

在本节课中,我们将要学习推荐系统在现实世界中的多种应用场景。推荐系统通过个性化技术,帮助用户在海量信息中发现感兴趣的内容,其应用已深入我们生活的方方面面。

个性化:应对信息过载的关键 🔑
上一节我们介绍了推荐系统的核心目标,本节中我们来看看个性化技术为何如此重要。信息过载是当今数字时代的主要挑战,用户无法手动浏览所有可用内容。
例如,YouTube每分钟约有100小时的新视频上传。用户访问YouTube时,只希望观看自己感兴趣的视频。传统浏览方式已无法应对如此庞大的内容量。
因此,需要一种方法来自动发现与用户相关的内容。这就是个性化的核心理念:将用户(如访问YouTube的我)与项目(如YouTube上的视频)连接起来。

个性化将在推荐系统中扮演关键角色。
经典推荐系统应用实例 🛒
以下是推荐系统非常重要的几个经典例子。
- Netflix视频推荐:用户观看视频,Netflix的目标是推荐可能感兴趣的电影或电视节目。关键问题是如何实现这些推荐。
- 亚马逊产品推荐:用户在亚马逊购买产品后,网站会推荐其他可能感兴趣的产品。但推荐时不仅要考虑用户单次会话的兴趣(例如,购买网站建设书籍的用户可能对Web应用书籍感兴趣),更要结合用户长期的购买历史。例如,我最近为儿子购买了鞋子,但这并非我唯一的兴趣。通过分析我的完整购买历史,可以做出比仅基于单次会话更好的推荐。
- 推荐随时间变化:推荐需要随时间适应。例如,一年前我购买了大量新生儿产品,但今天很可能不再需要。因此,亚马逊今天展示给我的推荐必须随之调整。
流媒体音频与社交网络中的推荐 🎵


除了点播视频,许多网站也提供带个性化推荐的流媒体音频服务。然而,与点播视频不同,流媒体音频希望一首歌接一首歌地连续播放。
我们需要一个连贯的歌曲流。我希望播放我喜欢的歌曲或类似歌曲,而不希望风格快速切换(例如,从独立咖啡馆音乐突然切换到重金属音乐)。同时,我也不想反复听到同一首歌。
因此,推荐需要具有连贯性,同时也需要提供多样化的歌曲序列供我聆听。
推荐系统发挥重要作用的另一个关键领域是社交网络。
例如,Facebook拥有海量用户,我们需要在这些用户之间建立连接。下图可能是Facebook用户间的连接图,假设我是这个粉色节点,Facebook希望推荐我可能感兴趣连接的其他用户。
在这个应用中,值得注意的是,用户和“项目”属于同一类型——都是人。当我是Facebook用户时,推荐给我的“项目”是其他人。因此,在这个应用中,用户和项目最终是完全相同的类型。
超越在线媒体:推荐系统的多样化应用 💊
我们讨论的推荐系统主要集中于在线媒体,但越来越多的人认识到推荐系统在其他领域也能发挥重要作用。
一个例子是所谓的“药物-靶点相互作用”。假设我们有一种已被充分研究的药物,例如阿司匹林,它作为头痛治疗药物已被熟知。但如果发现它可能具有其他用途呢?例如,用于心脏病患者的血液稀释。
如果我们能发现这类关系,将这种药物重新用于其他治疗,将非常有用。因为获得FDA对一种全新药物的批准是一个成本高昂且漫长的过程。但如果能利用一种副作用和潜在风险已得到充分研究和了解的药物,就更容易获得用于治疗其他病症的批准。
在这种情况下,我们或许可以说:如果你喜欢用阿司匹林治头痛,你可能也会喜欢用它治疗心脏问题。
这只是推荐系统应用多样性的一个例子,表明这类系统正在医疗等领域发挥着积极作用。
总结 📝

本节课中我们一起学习了推荐系统的广泛应用场景。我们从应对信息过载的个性化需求谈起,探讨了Netflix、亚马逊等经典案例,了解了推荐如何随时间变化。接着,我们分析了流媒体音频对推荐连贯性与多样性的特殊要求,以及社交网络中推荐“同类项”(用户推荐用户)的特点。最后,我们看到了推荐系统如何超越在线媒体,在药物重定位等医疗领域展现价值。这些例子共同说明了推荐系统技术的普适性与重要性。
第一部分 76:通过分类构建推荐系统 📚


在本节课中,我们将学习如何利用分类模型构建个性化推荐系统。我们将从最简单的基于流行度的推荐方法开始,逐步引入更复杂的分类模型,并探讨其优势与局限。
基于流行度的推荐方法 📊
上一节我们介绍了推荐系统的多种应用场景,本节中我们来看看如何实际构建一个推荐系统。构建推荐系统的方法多种多样,我们先从最基础的方法开始讨论。
第一种零级方法是根据产品的流行度进行推荐。这种方法在新闻网站等平台上非常常见。
以下是基于流行度推荐的具体做法:
- 例如,《纽约时报》网站上会列出“最受欢迎文章”列表,并按不同主题(如“最多邮件转发文章”)进行排序。
- 当我们考虑向其他读者推荐文章时,我们只是根据这些文章被《纽约时报》读者分享的频率进行排序。
这种方法效果尚可,用户可能确实会发现感兴趣的文章。但它的一个明显缺陷是完全缺乏个性化。因为所有推荐都基于整个《纽约时报》读者群体的行为,而读者群体本身非常多样化。因此,我们自然希望有一种能更了解我个人兴趣的推荐方法。
引入分类模型实现个性化推荐 🤖

为了增加个性化,我们可以尝试使用分类模型。该模型将同时利用产品和用户的特征来进行推荐。这个分类模型与你刚刚从卡洛斯那里学到的用于情感分析的分类模型完全一样,但在这里,我们将用它来分类判断一个人是否喜欢某个产品。
这个分类模型将接收关于用户的特征、该用户过去的购买记录特征、我们考虑推荐的产品特征,以及许多其他潜在特征。我们将所有这些特征输入分类模型,模型将输出“是”(我认为这个人会喜欢这个产品)或“否”(我认为他们不会喜欢)。
这种分类方法有很多优点。
以下是分类推荐方法的主要优势:
- 高度个性化:我们使用了用户特征及其购买历史。
- 能捕捉上下文:例如,我们可以考虑一天中的时间、用户刚刚浏览的内容。比如,我可能在白天更可能购买教科书,在晚上更可能购买家居产品。
- 能处理有限的用户历史:例如,假设我是亚马逊用户,过去购买物品不多。对于许多方法来说,很难确定我的兴趣。但如果你有我的年龄等信息,仅凭这一点就可能非常有助于预测我的喜好。
然而,这种方法也有局限性。其中一个重要的限制是,我们讨论的这些对预测喜好非常有用的特征,可能无法获得。
以下是分类推荐方法面临的主要挑战:
- 例如,你可能不知道我的年龄或性别,此类信息可能缺失。
- 同样,对于产品,你可能也缺少信息,或者产品描述质量很差(尤其是在亚马逊这类平台上,许多卖家销售不同产品,信息质量可能较低)。
因此,我们实际更常见的是使用一种称为“协同过滤”的方法,我们接下来会讨论,它通常比这种分类方法效果更好。
总结与展望 🎯
本节课中,我们一起学习了构建推荐系统的初步方法。我们从简单的基于流行度的非个性化推荐开始,然后引入了利用用户和产品特征的分类模型来实现个性化推荐,并分析了该模型的优势与数据依赖性强等局限。


这为我们理解更强大的协同过滤方法奠定了基础,我们将在下一节中进行探讨。
第一部分 77:协同过滤:购买此商品的人也购买了 🛒

在本节课中,我们将要学习协同过滤的基本概念,特别是如何利用“购买此商品的人也购买了”这类信息来构建推荐系统。我们将从直观理解开始,逐步深入到如何构建和使用一个“共现矩阵”来生成推荐。

协同过滤的基本概念
协同过滤的核心思想是,通过利用其他用户在商品推荐(或更广义的用户与物品之间的关联)中的行为,来为当前用户生成推荐。
当我们考虑进行商品推荐时,一个非常直观的想法是:如果一个人购买了某件商品,那么他很可能也对其他某些商品感兴趣。这是因为我们过去观察到大量用户同时购买这些商品对的例子。这里的“同时”不一定指同一时刻,也可能是在他们的购买历史中先后发生。
上一节我们介绍了协同过滤的直观想法,本节中我们来看看如何具体实现它。
构建共现矩阵
为了利用这种购买共现关系,我们需要构建一个共现矩阵。这个矩阵将存储关于哪些商品被用户一起购买的所有信息。
这个矩阵 C 是一个“物品 × 物品”的矩阵。矩阵的行和列都代表所有不同的商品。
例如,矩阵的某一行可能对应“尿布”。如果这是矩阵的第三行,那么矩阵的第三列也同样对应“尿布”。
如果我们想说很多人同时购买了尿布和婴儿湿巾,我们就查看“尿布”所在的行,然后找到“婴儿湿巾”所在的列。这个交叉位置的条目会有一个数字,它代表同时购买了尿布和婴儿湿巾的用户数量。
这里有一个关键点:同时购买尿布和婴儿湿巾的用户数量,与同时购买婴儿湿巾和尿布的用户数量是相同的。这意味着这个矩阵是一个对称矩阵。如果我们沿着主对角线(从左上到右下的对角线)折叠这个矩阵,两边的数字会完全对应。
以下是构建这个矩阵的方法:
- 我们将遍历所有用户的购买历史。
- 每当看到一个用户购买了尿布,我们就检查他购买历史中的所有其他商品。
- 对于每一对(尿布,其他商品),我们在矩阵的对应位置计数加一。
- 在遍历所有用户的过程中,我们不断累加这个矩阵。
利用共现矩阵进行推荐
现在,让我们讨论如何利用这个共现矩阵来生成推荐。这个过程非常直接。
假设一个用户刚刚购买了“尿布”,我想为他推荐其他商品。我会执行以下操作:
- 查看共现矩阵中“尿布”对应的那一行。
- 这一行是一个向量,它包含了所有其他商品与尿布被一同购买的次数。
- 例如,婴儿湿巾的计数可能是100。
- 奶嘴的计数可能是4。
- 某个DVD的计数可能是0。
- 我们得到了一个包含所有商品共现次数的向量。
利用这个向量,我们可以非常直接地生成推荐:我们只需对这个向量进行排序,然后推荐那些计数最高的商品。
例如,对于刚刚购买尿布的用户,我们可能会推荐婴儿湿巾、牛奶、婴儿食品等商品。

本节课中我们一起学习了协同过滤中基于物品共现的推荐方法。我们首先理解了其核心是利用群体行为模式,然后详细介绍了如何构建一个对称的共现矩阵 C 来量化物品之间的关联强度,最后说明了如何通过查询矩阵的特定行并排序来为单个用户生成个性化推荐。这种方法简单有效,是许多推荐系统的基础。
第一部分 78:热门商品的影响 🧸

在本节课中,我们将要学习共现矩阵的一个关键问题:热门商品对推荐结果的影响。我们将探讨为何需要标准化处理,以及如何使推荐更加个性化。
上一节我们介绍了共现矩阵的基本概念,本节中我们来看看一个常见问题:热门商品可能淹没其他商品的信号。
共现矩阵需要标准化处理。原因在于热门商品的影响过大。以婴儿用品为例,尿布是非常热门的商品。在亚马逊上,购买任何婴儿用品的用户很可能也购买过尿布。
但考虑另一个商品:Sophie the Giraffe(长颈鹿牙胶)。这是亚马逊上最受欢迎的婴儿礼物之一。它是一个牙胶,婴儿喜欢咬这个橡胶玩具,它会发出吱吱声吸引婴儿。
当我们查看Sophie的购买向量时,情况如下:
以下是Sophie的共现计数向量示例:
- DVD(无人购买)
- 尿布:计数极高(例如1,000,000)
- 婴儿湿巾
- 其他各种商品
问题在于,无论用户刚刚购买了什么商品(Sophie、叠叠乐玩具,还是可爱的鳄鱼摇铃),根据我们之前描述的推荐流程,系统都极有可能推荐尿布。
这导致推荐结果不够个性化。每个人都购买尿布,并不意味着我刚买了Sophie就特别需要尿布。
因此,我们需要处理这个问题。核心在于,热门商品的巨大计数会淹没所有其他效应,使得推荐系统退化为简单地基于流行度进行推荐,而这正是我们试图通过不同类型的推荐系统来解决的问题。

本节课中我们一起学习了共现矩阵中热门商品带来的挑战。热门商品的高计数会主导推荐结果,使推荐失去个性化。为了解决这个问题,我们需要对矩阵进行标准化处理,这在后续课程中会详细展开。
第一部分 79:归一化共现矩阵与利用购买历史 📊

在本节课中,我们将学习如何处理推荐系统中“热门商品”带来的偏差,以及如何利用用户的完整购买历史来改进推荐。我们将介绍归一化共现矩阵的经典方法,并探讨如何通过加权平均来整合历史信息。
处理热门商品:归一化共现矩阵 🎯
上一节我们介绍了基于共现矩阵的简单推荐方法。本节中我们来看看,当某些商品非常热门时,如何通过归一化来修正共现矩阵的偏差。
一种常用的归一化方法是 Jaccard相似度。其核心思想与我们之前在聚类和相似性模块中讨论的 TF-IDF(词频-逆文档频率) 非常相似。在TF-IDF中,我们通过调整常见词的权重,避免它们淹没其他重要词汇。在这里,我们同样需要处理“热门商品”主导推荐结果的问题。
Jaccard相似度的计算方式非常直观。我们定义:
Jaccard相似度(I, J) = 购买过商品I和J的用户数 / 购买过商品I或J的用户数
用公式表示如下:
Jaccard(I, J) = |Users(I) ∩ Users(J)| / |Users(I) ∪ Users(J)|
我们可以通过一个简单的韦恩图来理解:
- 设圆圈A代表购买过商品I的所有用户。
- 设圆圈B代表购买过商品J的所有用户。
- 两个圆的重叠部分(A ∩ B)代表同时购买I和J的用户数,即我们之前共现矩阵中的原始计数,作为分子。
- 两个圆的整个覆盖区域(A ∪ B)代表购买过I或J中任意一个的所有独立用户数,作为分母。


这样,我们就用同时购买的比例,替代了原始的绝对购买次数,从而降低了热门商品的影响。当然,还有其他归一化方法,如余弦相似度,我们将在课程后续部分详细讨论。
整合用户历史:加权平均方法 📈


然而,仅基于当前页面或最后一次购买的方法有其局限性。它没有利用用户完整的购买历史来为推荐提供信息。
接下来,我们讨论一种改进方法,通过加权平均来整合用户的购买历史。
一个非常简单的方法是:对于待推荐的每一个商品,计算一个基于我历史购买记录的加权平均得分。
以下是具体步骤:
- 确定历史商品:列出用户过去购买过的所有商品(例如:尿布和牛奶)。
- 计算单项得分:对于待推荐商品(例如:婴儿湿巾),分别查看它与每个历史商品的共现关系。
- 查看“尿布”对应的行,找到“婴儿湿巾”的共现计数(或Jaccard相似度)。
- 查看“牛奶”对应的行,找到“婴儿湿巾”的共现计数(或Jaccard相似度)。
- 计算加权平均:将上述两个得分进行平均,得到最终推荐分数。这个分数反映了基于我全部购买历史,我购买“婴儿湿巾”的可能性。
我们可以用伪代码描述这个过程:
def weighted_average_score(user_history, target_item, cooccurrence_matrix):
total_score = 0
for historical_item in user_history:
# 从共现矩阵中获取 historical_item 与 target_item 的相似度
score = get_similarity(cooccurrence_matrix, historical_item, target_item)
total_score += score
average_score = total_score / len(user_history)
return average_score
当然,我们可以对此方法进行变体改进,例如,为最近的购买记录赋予更高的权重,以考虑上下文变化。最终,我们根据这个加权平均分数对所有候选商品进行排序,并推荐得分最高的商品。
当前方法的局限性与冷启动问题 ⚠️
虽然加权平均方法结合了用户历史,但它仍然存在一些明显的局限性。
以下是该方法的主要问题:

- 缺乏上下文信息:它没有直接利用诸如一天中的时间、用户地理位置等上下文信息。
- 忽略用户与商品特征:该方法在构建共现矩阵时将所有用户和商品混在一起考虑,没有利用用户年龄、性别或商品类别、价格等特征信息来驱动推荐。
- 冷启动问题:这是推荐系统乃至许多其他领域面临的一个核心挑战。
冷启动问题具体指:
- 新商品问题:当一个全新商品上架时,没有任何购买记录,因此它在共现矩阵中与其他商品的关联度为零,系统无法有效地推荐它。
- 新用户问题:当一个新用户注册后,我们没有任何关于他/她的历史购买数据,因此无法基于历史为其提供个性化推荐。
总结 ✨
本节课中我们一起学习了:
- 归一化共现矩阵:通过引入 Jaccard相似度 来降低热门商品在推荐中的过度影响,其核心是计算同时购买与总购买用户的比例。
- 利用购买历史:通过加权平均的方法,整合用户所有的历史购买记录来计算对某个商品的推荐分数,使推荐更加个性化。
- 认识局限性:我们指出了基于共现和历史的推荐方法在利用上下文信息、用户商品特征方面的不足,并重点介绍了推荐系统中至关重要的冷启动问题。

理解这些基础概念和方法,是构建更复杂、更智能推荐系统的重要第一步。
第一部分 79:矩阵补全任务 🎬

在本节课中,我们将学习矩阵补全任务。我们将探讨如何利用用户和物品的特征来驱动推荐,而不仅仅是依赖购买和用户历史的共现关系。我们将通过电影推荐任务来具体说明这一方法,并学习如何填充一个稀疏的用户-电影评分矩阵。
从共现方法到特征学习 🔄

在之前讨论的共现方法中,我们并没有考虑用户的不同特征或产品的属性如何影响推荐。相反,我们只是简单地统计购买和用户历史的共现次数。
一个自然的问题是,我们是否可以利用“我是谁”以及“产品是什么”的某些方面来驱动推荐,就像在分类方法中讨论的那样。这样,我们就有了用户和产品的一组特征,但在这里,我们希望从数据中学习这些特征,以帮助我们应对可能没有可用特征的问题。
此外,我们希望考虑用户和物品之间的交互,就像在共现应用或共现方法中所做的那样。因此,我们将在电影推荐任务的背景下讨论这一点,因为对于我们将要描述的方法来说,这个应用非常直观。
电影推荐任务的数据结构 🎥
在这个应用中,我们的数据是一个大表格,其中有许多用户观看了一些电影并给出了评分。我们的表格看起来像这样:绿色用户观看了三部不同的电影,分别给出了三星、五星和两星的评分;蓝色用户观看了两部不同的电影;粉色用户观看了四部不同的电影。
我们有一个非常大的用户-电影评分组合表格。然而,每个用户只观看了可用电影中的一小部分。因此,我们将把这个数据表转换成一个非常大的用户×电影评分矩阵。
这个矩阵之所以非常大,是因为通常有很多用户和很多电影。但同时,这个矩阵非常稀疏,因为电影数量众多,而每个用户只观看了少数几部电影。
用户-电影评分矩阵的表示 📊
如果我们看这个矩阵,它是一个用户×电影的矩阵。例如,这一行代表用户U,这一列代表电影V。这里的黑色方块代表用户U给电影V的评分。所以,这是电影V由用户U给出的评分。
这些黑色方块只有少数,而白色方块非常多。白色方块代表一个问号,表示用户没有观看该电影,或者至少没有提供该电影的评分。
需要明确的是,所有白色方块代表未知评分,不代表评分为零。并不是用户不喜欢那部电影,只是我们不知道用户对那部电影的看法。
矩阵补全的目标 🎯
我们将评分U,V定义为用户U给电影V的评分。对于黑色方块,这些评分是已知的;对于白色单元格,这些评分是未知的。
我们的目标是填充所有这些问号,即所有白色单元格。我们将通过利用用户提供的所有评分(即该用户的所有黑色方块)来实现这一目标。我们将使用这些评分来预测这些问号的评分,实际上,我们将使用该用户的历史评分以及所有其他用户的历史评分来填充所有这些问号。
我们正在填充一个问号,并且要重申的是,我们不仅仅使用该用户的评分,而是使用所有这些评分来进行预测。虽然我不会为每个黑色单元格画上洋红色的框,但请知道,我们正在使用所有这些信息来填充这个非常大的稀疏矩阵。
总结 📝


在本节课中,我们一起学习了矩阵补全任务。我们探讨了如何从共现方法过渡到特征学习,以更有效地进行推荐。我们通过电影推荐任务具体说明了用户-电影评分矩阵的结构,并明确了矩阵补全的目标:利用已知评分预测未知评分,从而填充稀疏矩阵。这一方法不仅考虑了单个用户的历史,还整合了所有用户的信息,以提高预测的准确性。
第一部分 80:基于已知用户-商品特征的推荐 🎬

在本节课中,我们将学习如何利用已知的用户特征和商品(电影)特征来预测用户对未观看电影的评分,并以此为基础构建推荐系统。
上一节我们介绍了推荐系统的基本概念,本节中我们来看看如何利用特征向量进行评分预测。
特征向量表示
假设我们拥有每部电影和每位用户的一组特征。例如,电影《肖申克的救赎》可以表示为一个向量,其中包含对不同类型(如动作、浪漫、剧情)的隶属度。同样,每位用户也可以表示为一个向量,描述其对各类电影的偏好程度。
我们定义:
- 电影向量为 r_v,表示电影v的特征。
- 用户向量为 l_u,表示用户u的偏好。
评分预测方法
为了预测用户u对电影v的评分,我们可以计算电影向量与用户向量的点积。点积结果越大,表示用户偏好与电影特征越匹配,预测评分就越高。
预测评分的计算公式为:
\hat{r}_{u,v} = r_v \cdot l_u
其中,\hat{r}_{u,v} 表示预测评分。
以下是计算过程的分解:
- 将电影向量和用户向量对应元素相乘。
- 将所有乘积结果相加,得到最终预测分数。
例如,若电影向量为 [0.3, 0.01, 1.5],用户向量为 [2.5, 0, 0.8],则预测评分为 (0.3*2.5) + (0.01*0) + (1.5*0.8) = 0.75 + 0 + 1.2 = 1.95。
生成推荐列表
获得所有电影的预测评分后,生成推荐列表的步骤如下:
- 为用户u计算其未观看过的所有电影的预测评分。
- 根据预测评分对所有电影进行降序排序。
- 将排名靠前(即预测评分最高)的电影推荐给该用户。
需要指出的是,这种基于点积的模型预测出的分数可能超出实际的评分范围(例如0-5星)。但这并不影响推荐功能,因为我们只需要比较分数的相对大小,找出最可能被用户喜爱的电影。

本节课中我们一起学习了如何利用用户和商品的特征向量,通过点积运算来预测评分并构建推荐列表。这种方法的核心在于衡量用户偏好与商品特征之间的匹配程度。
第一部分 82:矩阵形式的预测 📊

在本节课中,我们将学习如何用矩阵形式来表示推荐系统中的预测评分。我们将从具体的用户-电影评分出发,扩展到整个用户和电影集合的预测表示,并引入线性代数的基本概念来简化这一过程。
从单个评分到矩阵表示
上一节我们讨论了如何为一个特定用户和电影组合预测评分。本节中,我们来看看如何将这种预测扩展到所有用户和所有电影,并用矩阵形式进行统一表示。
对于一个特定用户 U 和电影 V,我们预测的评分公式如下:
预测评分 = Σ (用户向量 L_u 的元素 × 电影向量 R_v 的元素)
用数学符号可以简洁地表示为:
ŷ_uv = L_u · R_v
这里的点乘(·)表示对两个向量进行逐元素相乘,然后将所有乘积结果求和。
理解向量与矩阵
用户向量 L_u 是一个行向量,它代表了用户 U 对不同电影特征(如动作、浪漫等)的偏好程度。
电影向量 R_v 是一个列向量,它代表了电影 V 在不同特征上的强度。
当我们计算 L_u 和 R_v 的点积时,实际上是在计算一个矩阵乘法中特定位置(第 U 行,第 V 列)的元素值。
扩展到完整矩阵
为了给所有用户和所有电影进行预测,我们可以将所有的用户向量堆叠起来形成一个矩阵 L,其中每一行代表一个用户。
同样地,将所有的电影向量堆叠起来形成另一个矩阵 R,其中每一列代表一部电影。
通过矩阵乘法,我们可以一次性得到完整的预测评分矩阵 Ŷ:
Ŷ = L × R
以下是这个过程的几个关键点:
- 矩阵 L: 行数等于用户数,列数等于特征数(如电影类型)。
- 矩阵 R: 行数等于特征数,列数等于电影数。
- 结果矩阵 Ŷ: 行数等于用户数,列数等于电影数。矩阵中位于第 i 行、第 j 列的元素 ŷ_ij,就是我们对用户 i 给电影 j 的评分预测。
这种表示方法非常紧凑和高效。它允许我们利用线性代数的工具,对整个数据集进行统一的运算和分析,而不是逐个处理单个评分。
总结
本节课中,我们一起学习了如何将推荐系统的评分预测从单个计算,转化为高效的矩阵运算形式。
我们首先回顾了单个评分的预测公式,然后引入了用户偏好矩阵 L 和电影特征矩阵 R 的概念。最后,我们了解到,通过矩阵乘法 L × R,可以直接得到包含所有用户对所有电影预测评分的完整矩阵 Ŷ。

这种矩阵形式的表示是许多现代机器学习算法的基础,它使得处理大规模数据成为可能,并为后续更复杂模型的学习做好了准备。
第一部分 83:通过矩阵分解发现隐藏结构 🧩

在本节课中,我们将要学习如何通过矩阵分解模型,从用户对电影的评分数据中,自动发现用户和电影的隐藏特征(或称“主题向量”),并用这些特征来预测缺失的评分。
从已知特征到未知参数
上一节我们介绍了在已知用户和电影特征向量(即主题向量)的情况下,如何通过点积运算来预测评分。然而,关键问题在于,我们实际上并不拥有这些关于用户或电影的特征信息。
因此,我们需要将问题反过来思考。我们将尝试估计这些矩阵——用户特征矩阵 L 和电影特征矩阵 R。这等同于基于我们观测到的评分数据,为每一位用户和每一部电影估计其对应的特征向量。
这些矩阵(即特征向量的集合)就是我们模型的参数。回想我们在回归模型中学到的内容:模型有其关联的参数,我们需要从数据中估计这些参数。这里的思路非常相似。
- 我们的数据:观测到的评分(即下图中的黑色方格)。
- 我们的参数:所有用户的特征向量(构成矩阵 L)和所有电影的特征向量(构成矩阵 R)。
我们的目标是:仅利用这些黑色方格的观测评分,来估计出矩阵 L 和 R。

如何估计参数:定义拟合度量
那么,我们如何进行估计呢?和回归模块一样,我们需要一个衡量模型拟合好坏的度量标准。
在回归中,我们使用了残差平方和。在那个例子里,我们有房屋特征、特征权重(参数),我们预测房价,然后计算预测值与实际售价之差的平方,并对所有房屋求和。
在这个评分预测问题中:
- 模型参数是 L 和 R。
- 我们对用户 u 给电影 v 的评分预测是:
预测评分 = L_u · R_v(即用户特征向量与电影特征向量的点积)。 - 观测到的实际评分是
Y_{u,v}。
因此,我们可以定义参数 L 和 R 的残差平方和 RSS 为:
RSS(L, R) = Σ_{(u,v) ∈ 有评分的数据} (Y_{u,v} - L_u · R_v)²
这个求和遍历所有拥有观测评分(即所有“黑色方格”)的用户-电影对。
这个公式的含义是:给定一组参数 L 和 R,我可以为所有已有评分的项目做出预测,然后计算这些预测值与真实值之间的总误差。
参数估计与矩阵分解
为了找到最佳的参数,我们需要在所有可能的用户特征向量和电影特征向量的组合空间中,搜索能使上述 RSS 最小化的那一组 L 和 R。这个过程与回归中寻找最优权重系数在本质上是相同的。
这种方法之所以被称为矩阵分解模型,是因为我们正在将庞大的评分矩阵(包含已知的黑色方格和待预测的白色方格)近似分解为两个更小矩阵的乘积:评分矩阵 ≈ L × Rᵀ。
模型的输出就是一组估计出的参数 L_hat 和 R_hat。
值得注意的是,存在许多高效的算法(例如交替最小二乘法、随机梯度下降法)来执行这种矩阵分解。我们将在后续关于推荐系统或矩阵分解的课程中详细讨论它们。
进行预测
一旦我们得到了估计的参数 L_hat 和 R_hat,我该如何填充所有初始目标中的“白色方格”(即进行预测)呢?
方法非常简单直接:使用我们估计出的特征向量,按照最初假设已知特征时的公式进行计算。
对于用户 u 对电影 v 的预测评分为:预测评分 = L_hat_u · R_hat_v
矩阵分解的局限性:冷启动问题 🥶
矩阵分解是一个非常强大的工具,已在众多应用中被证明有效。但它也存在一个局限,即我们之前略微提及的冷启动问题。

这个模型仍然无法很好地处理以下情况:当系统出现一个新用户或一部新电影时。

对于新用户或新电影,我们没有任何历史评分数据(上图中新增加的行或列全为白色)。因此,模型无法为他们/它们估计出有意义的特征向量,从而难以做出可靠的预测。这对于像 Netflix 这样的服务来说是一个持续面临的重要挑战。



总结
本节课中我们一起学习了:
- 问题转换:将评分预测问题从“已知特征”转换为“从数据中估计特征(参数)”。
- 模型定义:引入了矩阵分解模型,其目标是找到用户特征矩阵 L 和电影特征矩阵 R,使它们的乘积能最好地拟合观测到的评分。
- 损失函数:使用残差平方和作为衡量预测评分与真实评分之间差异的度量标准,并以此指导参数估计。
- 预测方法:在估计出参数后,通过简单的向量点积
L_u · R_v即可对任意用户-电影对进行评分预测。 - 模型局限:认识到矩阵分解模型仍受冷启动问题的困扰,无法有效处理完全没有评分记录的新用户或新项目。

通过矩阵分解,我们能够从稀疏的交互数据中自动发掘隐藏的潜在结构,这是构建现代推荐系统的核心思想之一。
第一部分 84:综合应用——特征化矩阵分解 🎯

在本节课中,我们将学习如何将基于特征的分类方法与矩阵分解方法相结合,以构建更强大的推荐系统。我们将探讨这种综合方法的优势、实现思路,并通过一个经典案例了解其实际应用价值。
概述:两种方法的优势与局限
上一节我们介绍了基于特征的分类方法和矩阵分解方法。基于特征的分类方法能够处理用户数据非常有限的情况,而矩阵分解方法则能捕捉用户与物品之间的关系,并学习用户和物品的潜在特征。
基于特征的分类方法可以捕捉诸如上下文、时间、用户近期行为和历史购买记录等信息。其核心公式可表示为:
预测评分 = 基于用户特征和物品特征的函数
而矩阵分解方法发现的潜在特征,能够捕捉行为相似的用户群体,例如“来自西雅图、从事教育工作的母亲们”。其核心模型通常表示为:
评分矩阵 R ≈ 用户特征矩阵 U × 物品特征矩阵 V^T
一个自然的问题是:我们能否将这两种方法结合起来,从而兼得两者的优势?
综合方法:结合用户指定特征与学习特征
结合这两种方法非常直观。我们可以根据用户数据的丰富程度,动态调整两种方法的权重。
以下是具体的实现思路:
- 对于新用户:由于没有历史购买信息,我们可以主要依赖用户指定的特征(如年龄、性别等)来预测其可能的评分。
- 随着数据积累:当我们从该用户那里获得越来越多的数据时,可以逐渐增加矩阵分解方法的权重,在形成推荐时更强调那些学习到的潜在特征。
简而言之,就是将基于用户指定特征的模型与从矩阵分解中学习到的特征模型相结合,并根据每个用户或每个产品的可用数据量,在两者之间进行平滑过渡。
这种模型融合的思想在实践中非常流行。
经典案例:Netflix 大奖赛
这种混合模型的思想在推荐系统中被证明极具影响力,一个经典的例子就是我们在本模块开头提到的 Netflix 大奖赛。
这项竞赛的目标是为 Netflix 用户提供最准确的电影评分预测。数据集包含:
- 1亿条 不同的用户电影评分
- 近 18,000部 不同电影
- 近 50万名 独立用户
竞赛目标是最高精度地预测 300万条 评分,优胜奖金高达 100万美元,因此吸引了众多团队参与。
最终,领先团队的成绩是通过融合超过100个不同的模型而取得的。下表展示了这一结果:


这种集成方法我们将在分类模块中进一步讨论。但核心思想是:通过组合多个模型,获得的性能往往能超过其中任何一个单一模型的性能。这是一种非常常见且强大的技术。
总结
本节课中,我们一起学习了如何构建一个综合的推荐系统。我们探讨了将基于明确特征的分类模型与从数据中学习潜在特征的矩阵分解模型相结合的方法。这种混合策略允许我们在用户数据稀缺时依赖已知属性,在数据丰富时利用复杂的交互模式。最后,通过 Netflix 大奖赛的实例,我们看到了模型融合在实际竞赛中取得的巨大成功,这证明了集成学习在提升预测性能方面的强大能力。
第一部分 85:推荐系统的性能指标 📊

在本节课中,我们将学习如何评估推荐系统的性能。我们将介绍两个核心指标:召回率和精确率,并解释为什么传统的分类准确率不适用于推荐系统场景。
推荐系统评估的挑战
上一节我们介绍了多种推荐系统的预测方法。本节中,我们来看看如何评估这些不同系统的性能差异。
假设我们需要向一位新父母推荐产品,所有可能推荐的产品集合如下图所示。用户真正喜欢的产品是其中的一个子集,在图中用洋红色方块表示。我们的目标是通过用户的购买记录,发现他们喜欢的产品,因为我们实际上并不知道用户具体喜欢哪些产品。
那么,为何不能直接使用分类准确率来衡量推荐系统的性能呢?例如,我们可以计算系统猜测用户喜欢与不喜欢的物品数量,并与实际情况进行比较。Carlos在情感分析案例研究中曾讨论过使用此类指标。
但这里的问题是多方面的:
- 我们更关心用户喜欢什么,而非他们不喜欢什么。而且,我们常常面临类别极不平衡的情况。例如,产品数量极其庞大,但用户通常只喜欢其中很小一部分。如果使用分类准确率,系统只需预测用户不喜欢任何物品(即不推荐任何东西),就能在此指标上获得很好的表现,但这显然不是我们想要的。
- 另一个问题涉及不同决策带来的成本差异。我们通常假设用户的注意力是有限的,因此只能推荐有限数量的物品给用户查看。在这种情况下,如果在我们允许推荐的这一小批物品中,没有包含任何用户喜欢的物品,其代价远高于在推荐列表中遗漏了部分用户喜欢的物品。
因此,我们将转而讨论一组不同的指标,即精确率和召回率。
理解召回率
首先讨论召回率。对于一个给定的推荐系统,它会向我推荐一组产品。在图中,我用彩色图片高亮显示了这些被推荐的产品(例如,这是一个推荐项,这也是一个推荐项),而灰色图片则表示未被推荐给我的物品。
测量召回率时,我们需要关注所有我喜欢的物品(即所有洋红色方块),并计算其中有多少被实际推荐给了我的比例。

以下是计算步骤:
- 统计所有我喜欢的物品(洋红色方块)总数。
- 统计这些喜欢的物品中被推荐的数量。
- 计算比例:
召回率 = 被推荐的喜欢物品数量 / 喜欢的物品总数
在示例中,共有5个喜欢的物品,其中3个被推荐。因此,召回率为 3/5。
召回率衡量的是推荐物品集合覆盖我感兴趣(真正喜欢)物品的程度。
理解精确率
接下来我们看看精确率。讨论召回率时,我们关注的世界是“所有喜欢的物品”(洋红色方块)。而讨论精确率时,我们关注的世界变成了“所有被推荐的物品”(图中绿色高亮框)。
测量精确率时,我们需要在所有被推荐的物品中,计算其中有多少是我喜欢的物品的比例。
以下是计算步骤:
- 统计所有被推荐的物品总数。
- 统计这些被推荐的物品中,用户喜欢的数量。
- 计算比例:
精确率 = 被推荐的喜欢物品数量 / 被推荐的物品总数
在示例中,共有11个被推荐的物品,其中3个是用户喜欢的。因此,精确率为 3/11。
精确率衡量的是,在用户注意力有限的情况下,他们需要浏览多少“垃圾信息”(不喜欢的物品)才能找到喜欢的内容。它反映了推荐列表的“纯净度”。
总结
本节课中,我们一起学习了推荐系统的核心性能指标:
- 召回率:关注用户喜欢的物品,衡量系统找出这些物品的能力。公式为:
召回率 = (被推荐的喜欢物品数) / (用户喜欢的物品总数) - 精确率:关注系统推荐的物品,衡量推荐列表的准确性。公式为:
精确率 = (被推荐的喜欢物品数) / (被推荐的物品总数)

理解这两个指标有助于我们在构建推荐系统时,在“尽可能覆盖用户喜好”(高召回率)和“确保推荐内容精准”(高精确率)之间做出权衡与优化。
第一部分 85:最优推荐器 📈

在本节课中,我们将探讨如何构建一个最优的推荐系统。我们将回顾召回率(Recall)和精确率(Precision)这两个核心概念,并分析两种极端情况下的推荐策略。通过对比,我们将理解为什么单纯追求高召回率或高精确率都不是最佳策略,并最终揭示最优推荐器的特征。
如何最大化召回率? 🤔
上一节我们介绍了召回率的概念,它衡量的是在所有用户喜欢的物品中,有多少被成功推荐。本节中我们来看看,如何最大化召回率。
最大化召回率有一个非常简单的方法:推荐所有物品。如果你推荐所有物品,那么你一定能推荐到用户喜欢的产品。
以下是这种策略下的结果分析:
- 召回率:为 1。因为用户喜欢的全部五个产品都被推荐了。
- 精确率:可能非常小。因为如果平台上有海量产品,而用户只喜欢其中极少一部分,那么推荐所有物品会导致绝大多数推荐都是用户不感兴趣的,从而使得精确率极低。
因此,虽然这种策略能获得完美的召回率,但其极低的精确率使其并非一个理想的策略。
什么是最优推荐器? 🏆
既然推荐所有物品不是好办法,那么什么才是我们能想象到的最佳推荐器呢?
最优的推荐器应该做到:推荐所有用户喜欢的物品,并且只推荐用户喜欢的物品。这意味着,所有用户不喜欢的物品都不会出现在推荐列表中。
以下是这种理想策略的结果分析:
- 精确率:为 1。因为推荐列表中的物品都是用户喜欢的。
- 召回率:为 1。因为用户喜欢的所有物品都被推荐了。
你可以使用前面幻灯片中的公式来验证这一点。这样的推荐器不会浪费任何展示机会,能完全捕捉用户的喜好,无疑是一个能创造巨大价值的系统。

总结 📝

本节课中我们一起学习了推荐系统评估的两个关键指标——召回率与精确率。我们分析了两种极端策略:通过“推荐一切”来最大化召回率,会导致精确率暴跌;而理想的“最优推荐器”则能同时实现精确率和召回率均为1。这为我们后续设计更平衡、更实用的推荐算法提供了重要的思考基础。
第一部分 87:准确率-召回率曲线 📊

在本节课中,我们将学习如何使用准确率(Precision)和召回率(Recall)这两个指标来比较不同的推荐算法。我们将重点介绍准确率-召回率曲线的绘制方法、含义,以及如何利用该曲线评估算法性能。
概述:准确率与召回率回顾
上一节我们介绍了准确率和召回率这两个核心评估指标。准确率衡量的是推荐物品中用户真正喜欢的比例,公式为:
准确率 = 推荐且喜欢的物品数 / 推荐的物品总数
召回率衡量的是系统成功找出的用户喜欢物品占所有喜欢物品的比例,公式为:
召回率 = 推荐且喜欢的物品数 / 用户喜欢的物品总数
本节中,我们将看看如何通过绘制准确率-召回率曲线,直观地比较不同算法在不同推荐数量下的表现。
什么是准确率-召回率曲线?
准确率-召回率曲线描述的是,当我们改变推荐系统允许推荐给用户的物品数量阈值时,准确率和召回率的变化关系。
以下是绘制该曲线的步骤说明:
- 首先,系统会对所有候选物品(例如亚马逊上的所有婴儿产品)进行排序。
- 然后,我们设定一个阈值
k,只允许系统推荐排名前k的物品。 - 对于每个不同的
k值(例如k=1, 2, 3...),我们分别计算其对应的准确率和召回率。 - 最后,将所有
(召回率, 准确率)的点连接起来,就形成了准确率-召回率曲线。
理想情况下的曲线
让我们先看看一个理想推荐系统的曲线会是什么样子。假设这个系统只推荐用户喜欢的产品。
- 当
k=1(只推荐1个产品)时,这个产品用户喜欢,所以准确率 = 1。假设用户总共喜欢10个产品,那么此时召回率 = 1/10 = 0.1。 - 随着
k增加,系统推荐更多用户喜欢的产品,准确率始终保持为1,而召回率会逐渐增加。 - 最终,当
k足够大,覆盖了所有用户喜欢的产品时,召回率达到1,准确率仍为1。
因此,理想系统的曲线是一条从点 (0.1, 1) 到点 (1, 1) 的水平线,这代表了最优性能。

现实情况下的曲线
现在,我们来看一个更现实的推荐系统。它的表现不会那么完美。
- 最初推荐的几个产品可能用户并不喜欢,所以准确率较低。
- 随着推荐数量
k增加,系统终于推荐了一个用户喜欢的产品,此时准确率和召回率都会上升。 - 但接下来,系统可能又推荐了一个用户不喜欢的物品。这时,召回率保持不变(因为没有发现新的喜欢物品),但准确率会立刻下降,因为分母(推荐总数)变大了,而分子(喜欢的物品数)没变。
这个过程会不断重复,导致曲线呈现出锯齿状的形态:先上升(发现喜欢物品),再垂直下降(混入不喜欢物品),如此反复。

如何比较不同算法?
我们已经知道,准确率和召回率都越高越好。但在比较两条不同的锯齿状曲线时,一条曲线并不总是在所有点上都优于另一条。
例如,蓝色曲线可能在召回率较低时表现更好,而绿色曲线在召回率较高时更优。那么,如何判断哪个算法整体上更好呢?
以下是两种常用的比较方法:
1. 曲线下面积
一种方法是计算曲线下面积。面积越大,代表算法在不同推荐数量阈值下的综合表现越好。我们可以通过比较不同算法曲线的面积大小来进行排序。
2. 特定操作点的精度
在某些实际应用中,我们可能明确知道需要推荐多少物品。例如:
- 网站页面的布局只允许展示10个推荐位。
- 根据用户注意力研究,决定最多只推荐20个产品。
在这种情况下,我们并不关心整个曲线,而只关心在特定推荐数量 k 下的准确率。我们会选择在该 k 值下准确率最高的算法。
总结

本节课中,我们一起学习了准确率-召回率曲线。我们了解了它的绘制原理,看到了理想情况与现实情况下的曲线差异。最后,我们掌握了两种利用该曲线比较算法性能的方法:比较曲线下面积和比较特定操作点下的准确率。这些工具能帮助我们在实际场景中选择最合适的推荐算法。
第一部分 88:推荐系统模块图解析 🧠

在本节课中,我们将学习推荐系统的核心概念,特别是协同过滤的基本思想及其在机器学习工作流中的位置。我们将通过一个具体的例子——电影和歌曲推荐系统——来理解如何利用用户与产品的交互数据来预测评分。
机器学习工作流在推荐系统中的体现 🔄
上一节我们介绍了协同过滤的基本概念,本节中我们来看看推荐系统如何融入标准的机器学习工作流。
在推荐系统的场景下,我们的训练数据是用户-产品评分表。


我们的目标是提取一组特征,这里具体是用户ID和产品ID的组合对。模型的任务是预测某个用户对某个产品的评分。
公式表示:
预测评分 = 模型(用户ID, 产品ID)
推荐系统模型与参数 ⚙️
我们讨论过多种模型,其中将在矩阵分解课程中深入探讨的一个模型是矩阵分解。
矩阵分解模型有一组参数 Ŵ(代表估计参数)。这些参数具体包括:
- 每个用户的一组特征向量。
- 每个产品的一组特征向量。
此外,我们还讨论过矩阵分解的特征化版本。在这种情况下,除了用户ID和产品ID,我们还可以考虑其他特征。
以下是可能纳入模型的其他特征示例:
- 用户的年龄
- 用户的性别
- 产品的描述文本
对于这些附加特征,模型还需要另一组权重参数,我们可以称之为 W₀。这些权重也是模型参数的一部分。
模型评估与优化 📊
得到预测评分后,我们需要评估模型对数据的拟合程度。评估方法是比较预测评分与训练数据集中的实际观测评分。
我们使用一个误差度量来衡量预测值与观测值之间的差异。一个常用的度量是残差平方和,这与回归分析中的概念类似。
公式表示:
误差 = Σ(实际评分 - 预测评分)²
当然,也存在其他评估指标,我们可以在后续课程中讨论。
核心思想是:基于预测值与观测值之间的某种误差定义,机器学习算法会迭代地更新用户和产品的特征向量。
算法目标:
迭代更新用户/产品特征,直至预测评分与实际评分达成良好一致。
总结与展望 🎯
本节课中我们一起学习了如何在实践中实现协同过滤。现在,你已经可以着手构建自己的推荐系统了。
你可以为家人创建一个礼物推荐系统,让节日购物变得轻松;也可以开发一个比课程演示更出色的歌曲推荐器。协同过滤技术为实现这些酷炫的应用提供了强大的支持。




第一部分 89:构建歌曲推荐器 🎵

概述

在本节课中,我们将学习如何构建一个歌曲推荐系统。我们将从加载和探索一个真实的音乐数据集开始,为后续构建推荐算法打下基础。



加载音乐数据 🎶
上一节我们介绍了推荐系统的概念,本节中我们来看看如何获取和处理数据。
首先,我们需要导入必要的库并加载数据。
import graphlab
song_data = graphlab.SFrame('song_data.csv')
我们加载的数据集名为“百万歌曲数据集”。变量song_data是一个GraphLab SFrame对象,用于存储数据。
探索数据 🔍
数据加载完成后,我们需要对其进行初步探索,以了解其结构和内容。
以下是查看数据前几行的步骤:
song_data.head()
执行上述代码后,我们可以看到数据表包含以下列:user_id(用户ID)、song_id(歌曲ID)、title(歌曲标题)、artist(艺术家)和listen_count(收听次数)。该表格记录了每位用户收听不同歌曲的频率。


分析歌曲流行度
为了更直观地了解数据,我们可以查看歌曲的收听分布情况。
以下是生成歌曲收听次数直方图的步骤:
graphlab.canvas.set_target('ipynb')
song_data['song'].show()
直方图显示了不同歌曲的播放次数。例如,某些歌曲被播放了数千次,这表明数据集中包含了一些非常受欢迎的歌曲。
探索用户数据 👥
除了歌曲,了解数据集中用户的数量和分布也同样重要。
以下是计算数据集中唯一用户数量的方法:
users = song_data['user_id'].unique()
len(users)
unique()命令用于提取所有不重复的用户ID。通过计算其长度,我们得知该数据集包含66,346位独立用户,对应着约一百万条收听记录。
总结
本节课中我们一起学习了如何为歌曲推荐系统准备数据。我们完成了数据加载,并通过对歌曲流行度和用户基数的探索,对数据集有了初步了解。在接下来的课程中,我们将利用这些数据构建不同类型的推荐算法。


第一部分 90:创建并评估基于流行度的歌曲推荐器 🎵

在本节课中,我们将学习如何创建一个简单的基于流行度的推荐系统,并使用训练集和测试集对其进行评估。我们将使用一个歌曲数据集,通过分析最受欢迎的歌曲来为用户提供推荐。
数据准备与分割
首先,我们拥有一个数据集。下一步是创建一个推荐系统。
我们首先进行训练集和测试集的分割。我们将对歌曲数据执行随机分割,其中80%用于训练,20%用于测试。设置随机种子为0,以确保结果可复现。
train_data, test_data = song_data.random_split(0.8, seed=0)
完成分割后,我们准备开始训练推荐模型。
创建基于流行度的推荐器
上一节我们介绍了数据分割,本节中我们来看看如何构建一个简单的基于流行度的推荐模型。这种模型在许多网站上都很常见,例如展示“最热门故事”或“今日最常用标签”。
以下是创建该模型的步骤:
- 导入必要的库并初始化推荐器。
- 指定数据集中代表用户ID和物品ID的列名。
- 使用训练数据来拟合模型。
popularity_model = graphlab.popularity_recommender.create(train_data,
user_id='user_id',
item_id='song')
这个模型创建得非常快,它是一个简单的基于流行度的推荐系统。
使用模型进行推荐
现在,让我们使用这个模型为特定用户进行推荐。
首先,我们为用户0推荐歌曲:
recommendations_user0 = popularity_model.recommend(users=[users_array[0]])
模型为用户0推荐了来自Harmonia、Bjork、King of Leon等艺术家的歌曲。
接下来,我们为用户1进行推荐:
recommendations_user1 = popularity_model.recommend(users=[users_array[1]])
在执行前,我们可以思考一下:基于流行度的模型会返回什么结果?答案是,所有用户都会获得完全相同的推荐列表,因为模型只是推荐最受欢迎的物品。
结果显示,用户1同样被推荐了Harmonia、Bjork、Dwightcom、King of Leon的歌曲。这揭示了该模型的主要问题:它缺乏个性化,为所有用户提供相同的推荐。
总结


本节课中我们一起学习了如何构建和评估一个基于流行度的推荐器。我们首先将数据分割为训练集和测试集,然后使用graphlab.popularity_recommender.create函数训练模型。最后,我们通过为不同用户生成推荐结果,观察并理解了这种简单模型的核心局限性——它无法提供个性化的推荐,所有用户收到的都是基于全局流行度的相同物品列表。
第一部分 91:创建并评估个性化歌曲推荐器 🎵

在本节课中,我们将学习如何构建一个个性化的歌曲推荐系统。我们将从基础的流行度推荐模型过渡到更高级的基于物品相似度的个性化推荐模型,并演示如何为用户生成定制化的歌曲推荐,以及如何查找相似歌曲。
从流行度推荐到个性化推荐
上一节我们介绍了如何创建一个基于歌曲整体流行度的推荐器。这种模型会向所有用户推荐相同的热门歌曲,缺乏个性化。
本节中,我们将构建一个个性化推荐器,它能根据每位用户的历史行为,提供独特的歌曲推荐。
以下是创建个性化推荐器的步骤:
- 初始化模型:我们将使用物品相似度模型,而非之前的流行度模型。
- 配置模型:需要指定数据集中代表用户ID和物品(歌曲)ID的列名。
- 训练模型:使用训练数据来构建模型。
具体实现代码如下:
# 创建个性化推荐模型(基于物品相似度)
personalized_model = graphlab.item_similarity_recommender.create(
train_data,
user_id='user_id',
item_id='song'
)
应用个性化模型进行推荐
模型训练完成后,我们可以用它来为特定用户生成推荐。与流行度模型不同,个性化模型为不同用户推荐的歌曲列表会截然不同。
例如,为用户0和用户1生成推荐:
# 为用户0推荐歌曲
recommendations_user_0 = personalized_model.recommend(users=[0])
# 为用户1推荐歌曲
recommendations_user_1 = personalized_model.recommend(users=[1])
运行后你会发现,用户0可能收到如“Doctor Feel Good”等歌曲的推荐,而用户1则可能收到一系列来自“Florence and the Machine”乐队的歌曲。这清晰地展示了模型的个性化能力。
探索相似物品
个性化推荐器的另一个强大功能是能够查找相似的物品。这意味着,如果你喜欢某首歌曲,模型可以找出其他被相似用户群体喜爱的歌曲。
以下是查找相似歌曲的方法:
- 调用方法:使用
get_similar_items函数。 - 指定歌曲:提供一个你喜欢的歌曲列表作为输入。
例如,如果你喜欢U2乐队的歌曲“With or Without You”,模型会推荐其他U2的歌曲:
# 查找与指定歌曲相似的歌曲
similar_songs = personalized_model.get_similar_items(items=['With or Without You - U2'])
结果可能包含“I Still Haven‘t Found What I’m Looking For”、“Vertigo”等U2的其他热门歌曲。
再举一个例子,如果你喜欢Buena Vista Social Club的歌曲“Chan Chan”,模型不仅会推荐该乐队的其他歌曲,还可能推荐风格相近的艺术家(如Gotan Project、Gypsy Kings)的作品,这体现了模型在音乐风格和听众品味上的深度关联挖掘能力。
总结


本节课中,我们一起学习了如何构建和评估一个个性化的歌曲推荐系统。我们从简单的流行度模型出发,进阶到基于物品相似度的个性化模型。我们不仅学会了如何为不同用户生成定制化的歌曲推荐列表,还掌握了如何根据一首歌曲来发现与之相似的其他歌曲。这个流程展示了推荐系统如何从“千人一面”进化到“千人千面”的核心思想。
第一部分 92:使用准确率-召回率比较推荐模型 📊

在本节课中,我们将学习如何对推荐模型进行定量比较。我们将使用准确率-召回率曲线这一指标,来评估个性化推荐模型与基于流行度的推荐模型的性能差异。
从定性评估到定量比较 🔄
上一节我们通过具体例子对模型进行了定性评估。本节中,我们将对个性化模型和流行度模型进行更精确的定量比较。
在比较推荐系统时,一个常用的评估指标是准确率-召回率。我们将为这两个模型绘制准确率-召回率曲线。
准备绘图环境 📈
我们将使用 Matplotlib 库来绘制图表。首先需要导入库并设置环境,以确保图表能正确显示在笔记本中。
import matplotlib.pyplot as plt
%matplotlib inline
计算模型性能 ⚙️
我们将使用推荐系统工具库中的 compare_models 函数来评估模型性能。这个函数可以方便地比较不同推荐模型在测试集上的表现。
以下是具体步骤:
- 定义要比较的模型列表。
- 在测试数据的一个子集上进行评估,以加快计算速度。
# 假设已导入相关库并准备好测试数据
from recommenders.evaluation import compare_models
# 定义要比较的模型
models_to_compare = [popularity_model, personalized_model]
# 使用部分测试用户进行评估
model_performance = compare_models(test_data, models_to_compare, user_sample=0.05)
解读准确率-召回率曲线 📉
代码运行后,我们会得到一条准确率-召回率曲线。图中通常用不同颜色代表不同模型。
- 蓝色曲线:代表流行度模型。
- 绿色曲线:代表个性化模型。
如何解读曲线:
曲线越靠近图表的顶部,说明模型的性能越好。从图中可以清晰地看到,绿色曲线(个性化模型)的整体位置高于蓝色曲线(流行度模型)。
这表明,加入个性化信息显著提升了推荐系统的性能。仅仅推荐热门物品的效果远不如根据用户个人喜好进行推荐。
总结与探索 🎯
本节课中,我们一起学习了如何使用准确率-召回率曲线对推荐模型进行定量比较。
我们构建了一个歌曲推荐系统,并通过比较发现,个性化推荐模型在性能上明显优于简单的流行度推荐模型。你可以尝试使用这个系统,输入自己的音乐偏好,探索它为你推荐的其他歌曲。

通过本节课,我们掌握了评估推荐模型的一个核心定量方法,这有助于我们理解不同推荐策略的有效性。
第一部分 93:图像搜索:深度学习案例研究 🖼️🔍
在本节课中,我们将要学习一个近年来机器学习领域最令人兴奋的新方向——深度学习。我们将通过一个具体的应用案例来理解其原理:如何仅基于图像相似性来搜索和推荐产品。
什么是深度学习?🧠
上一节我们介绍了本节课的主题。本节中,我们来看看深度学习的核心概念。

深度学习是机器学习的一个分支。它使用被称为“神经网络”的模型,这种模型的结构受到人脑的启发。与传统的机器学习方法相比,深度学习模型能够自动从原始数据(如图像像素)中学习到复杂的特征和模式,而无需过多的人工特征工程。
其核心思想可以用一个简化的神经网络公式表示:
输出 = 激活函数(权重 * 输入 + 偏置)
这个公式在网络的每一层中重复计算,通过多层“深度”的非线性变换,模型能够学习到数据中高度抽象的表示。
基于图像的购物搜索案例 🛒
理解了深度学习的基本概念后,我们来看一个具体的应用:基于图像的产品搜索。
想象一下,你看到一件喜欢的衣服或家具,但不知道它叫什么或在哪里购买。你可以拍下它的照片,然后使用一个应用程序来搜索外观相似的产品。这个功能背后的核心技术就是深度学习。
以下是实现这一功能通常涉及的几个关键步骤:
- 图像特征提取:使用一个预先训练好的深度卷积神经网络(CNN)模型来处理输入图片。这个网络会将图片转换成一个高维度的数值向量,这个向量被称为“特征向量”或“嵌入”,它编码了图像的核心视觉信息。
- 构建产品图像库:商家需要提前用同样的CNN模型处理所有商品图片,为每张商品图生成对应的特征向量,并存入数据库。
- 相似度计算与搜索:当用户上传一张查询图片时,系统会计算其特征向量与数据库中所有商品特征向量之间的“距离”(例如,使用余弦相似度公式)。距离越近,表示图像越相似。
- 返回结果:系统将距离最近(即最相似)的几个商品图片和链接返回给用户。
为什么深度学习在此表现出色?🌟
传统的图像搜索方法可能依赖于颜色直方图或手工设计的纹理特征。这些方法在复杂场景下往往效果不佳。
深度学习,特别是卷积神经网络,能够自动学习到图像的层次化特征。浅层网络可能识别边缘和角落,中层网络组合成纹理和部件,而深层网络则能理解整个物体或场景。这种自动学习强大特征的能力,使得它在图像相似性匹配任务上取得了革命性的成功。
总结 📚

本节课中,我们一起学习了深度学习在图像搜索中的一个精彩案例。
我们首先介绍了深度学习是使用深层神经网络来自动学习数据特征的机器学习方法。接着,我们详细探讨了如何利用这项技术实现“以图搜物”的产品搜索功能,其核心流程包括提取图像特征、构建特征库以及计算相似度。最后,我们分析了深度学习在此类任务上超越传统方法的原因在于其强大的特征自动学习能力。
通过这个案例,我们可以看到深度学习如何将看似复杂的视觉问题,转化为可计算、可搜索的数学问题,从而创造出实用的智能应用。
第一部分 94:什么是视觉产品推荐器 👟👗


在本节课中,我们将学习一种新的购物方式——视觉产品推荐器。它利用图像相似性搜索技术,帮助用户找到符合个人风格和喜好的商品,而无需依赖传统的关键词搜索。
如今购物方式多种多样,但通常需要使用关键词搜索。用户在搜索引擎中输入查询,试图找到感兴趣的商品。
但让我们看看新的购物方式。例如,假设我想买一双鞋。有些人非常在意鞋子。我有很多鞋,比如一双酷炫的黑色鞋子,很有风格。另一双黑色鞋子,在你看来可能几乎一样,但风格完全不同。我还有一双看似透明、实则是很酷的蓝色调的礼服鞋。一双我喜爱的双色运动鞋,以及一双在香港买的很有趣的运动鞋。大家都知道我喜欢紫色,所以我甚至有一双紫色靴子。我有很多鞋,但我需要更多。

网上有大量鞋子,很难找到那些有趣、时尚、与众不同且符合我风格的款式。

如果我使用关键词搜索,输入“礼服鞋”,帮助不大,只会找到一堆普通常见的鞋子。尽管左上角那双有点意思和时尚感,但我想要找些不同的东西,却不知道输入什么关键词或如何搜索。
那么我该怎么办?

让我先展示一个基于相似性搜索的新购物方式的酷炫演示。

让我们讨论比买鞋更复杂的事情。

我姐姐是时装设计师,她的生日快到了,我想给她买一件她可能会喜欢的、非常有趣又酷的礼物。

也许我想给她买一条裙子。如果我仅仅使用传统的关键词搜索,尝试寻找裙子。

我会找到很多裙子,但我真的不知道如何仅根据这里展示的属性来选择一条她喜欢的裙子。


我不知道如何描述它。我该如何描述我姐姐喜欢的裙子风格?
现在,我可以说也许她喜欢碎花裙。即使我说“碎花裙”。
我仍然会面对许多选项和不同种类的碎花裙,而她的风格相当独特,我该如何找到一条她真正会喜欢的裙子呢?
如果我向下滚动这个列表,也许我会看到一些吸引眼球的东西。
哦,这里有一条碎花裙看起来很不错。我要点击它。接下来,我将不再仅仅基于关键词搜索寻找裙子,而是使用图像相似性来寻找相似的裙子。这些裙子仅基于图像特征,看起来与这条相似。现在,我们得到的裙子确实具有相似的属性,这让我更容易找到她可能喜欢的东西。当然,其中许多裙子有点太普通,她可能想要更有趣一点的。例如,这条裙子有多个图案。



现在我们找到了相似的裙子,可以看到它们在一条裙子内融合了多种风格。我原本不知道如何描述这种风格。让我在这个集合中继续搜索,看,这条看起来很不错。
如果我点击它,你会看到其他与这条在视觉上相似的裙子。但这条看起来特别好,而且模特也有点像我姐姐,所以是送给她的完美礼物。



本节课中,我们一起学习了视觉产品推荐器的基本概念。它通过分析商品图片的视觉特征,计算相似度,帮助用户发现符合个人偏好的商品,解决了传统关键词搜索在表达抽象风格或视觉偏好时的局限性。这种技术为个性化购物体验开辟了新的可能性。
第一部分 95:使用神经网络学习高度非线性特征 🧠

在本节课中,我们将学习如何利用神经网络来学习高度非线性的特征表示。我们将从数据表示的基础概念开始,逐步深入到神经网络的构建与应用,特别是如何通过多层网络结构解决线性分类器无法处理的复杂问题。


数据表示与特征
在机器学习中,特征是我们用来描述数据的表示方式。这些特征被输入到分类器中,用于进行预测或分类。


例如,在文本分析中,我们使用词袋模型或TF-IDF来表示文本数据。在图像分类中,特征可以是像素值或其他更复杂的表示。


线性分类器回顾
上一节我们介绍了数据表示的基本概念,本节中我们来看看线性分类器的工作原理。线性分类器通过一个线性决策边界来区分不同的类别。
决策边界由以下公式定义:
score = w₀ + w₁ × x₁ + w₂ × x₂ + ... + w_D × x_D
当得分大于0时,我们预测为正类;当得分小于0时,预测为负类。
在神经网络中,我们可以用图的形式来表示这样的分类器。每个特征对应一个节点,输出节点表示预测结果。权重被放置在连接特征节点和输出节点的边上。

单层神经网络
单层神经网络本质上等同于我们之前讨论的线性分类器。它可以表示一些简单的逻辑函数。
以下是单层神经网络可以表示的两个基本逻辑函数:
- 逻辑或 (x₁ OR x₂):通过设置权重(例如,w₁=1, w₂=1, w₀=-0.5)可以实现。
- 逻辑与 (x₁ AND x₂):通过设置权重(例如,w₁=1, w₂=1, w₀=-1.5)可以实现。
线性分类器的局限性
虽然单层神经网络可以表示“与”和“或”函数,但它无法表示某些简单的非线性关系。
一个经典的例子是异或 (XOR) 函数。异或函数的真值表显示,不存在一条直线能够完美地将正例(输出为1)和负例(输出为0)分开。这表明线性特征对于此类问题是不够的。

构建多层神经网络
为了解决异或问题,我们需要引入非线性特征。这可以通过构建多层神经网络来实现。
我们不是直接从输入x₁和x₂预测输出y,而是引入中间层节点z₁和z₂。
以下是构建一个能够表示异或函数的两层神经网络的步骤:
- 定义中间变量:令 z₁ = x₁ AND (NOT x₂),令 z₂ = (NOT x₁) AND x₂。
- 构建第一层网络:设计两个单层神经网络,分别计算z₁和z₂。这需要为每个网络设置特定的权重,以表示“与”和“非”的组合逻辑。
- 构建第二层网络:将z₁和z₂作为新的输入特征,构建另一个单层神经网络来计算 y = z₁ OR z₂。
通过这种分层结构,我们成功构建了一个能够解决异或问题的深度神经网络(虽然只有两层)。神经网络的核心思想正是通过多层变换,逐步从原始数据中学习并构建出强大的非线性特征。
深度学习的复兴
神经网络的概念已经存在了大约50年。然而,在20世纪90年代,由于难以获得高精度,它们一度失宠。
大约10年前,两个关键因素推动了深度神经网络的复兴:
- 海量数据:深度网络拥有大量参数(例如,一个网络可能有6000万个参数),需要海量数据进行训练。互联网的普及提供了这样的数据源。
- 强大的计算资源:图形处理器(GPU)最初为加速游戏图形而设计,但其并行计算能力恰好非常适合训练大规模神经网络和处理海量数据。
得益于GPU和数据的增长,深度神经网络取得了突破性进展,并对现实世界产生了巨大影响。
总结
本节课中,我们一起学习了:
- 特征在机器学习中的核心作用。
- 线性分类器与单层神经网络的等价关系及其局限性。
- 通过构建包含中间层的深度神经网络,我们可以学习高度非线性的特征,从而解决像异或这样的复杂问题。
- 海量数据和GPU计算能力的提升是推动现代深度学习成功的关键因素。

在接下来的课程中,我们将看到神经网络在计算机视觉等领域的实际应用示例。
第一部分 96:深度学习在计算机视觉中的应用 🖼️

在本节课中,我们将要学习深度学习,特别是神经网络,如何在计算机视觉领域产生巨大影响。我们将从图像特征的基本概念开始,逐步了解传统方法与深度学习方法之间的区别,并最终理解神经网络如何自动学习复杂的图像特征。


图像特征是什么?🔍
上一节我们介绍了神经网络在计算机视觉中的重要性,本节中我们来看看图像特征的基本概念。
在计算机视觉中,图像特征类似于局部检测器,它们被组合起来以进行预测。
假设我们有一张特定图像,我们想预测它是否是一张人脸图像。我们可以运行一些小的检测器,例如鼻子检测器、眼睛检测器、嘴巴检测器。如果所有这些检测器都被激活,我们可以通过一个小型神经网络判断这是一张人脸。这就是我们的预测。
这是一个构建图像分类器的简单示例。但在现实中,我们并没有显式的鼻子检测器或眼睛检测器。实际使用的是被称为图像特征或兴趣点的东西。它们有各种名称,但本质上都是试图找到局部图像片段或小块,这些部分非常独特,例如可能找到一个角落。
眼睛周围可能有角落,鼻子周围也可能有角落。如果你有许多这样的角落检测器,一张人脸就是由许多角落组成的。如果足够多的检测器以特定模式被激活,你就会发现这是一张人脸。这就是计算机视觉通常的工作方式,也是分类的基本原理。当然,还有更通用和更复杂的模型,但这是基本思想。
多年来,这些类型的检测器或局部特征都是手工构建的。一个非常流行的方法叫做SIFT特征,它彻底改变了计算机视觉领域,因为它们非常实用且效果出色。后来还有许多其他方法提高了其准确性。
传统特征的使用方法 📊
上一节我们了解了图像特征的概念,本节中我们来看看这些手工创建的特征(如SIFT特征)通常如何用于分类。
以下是使用SIFT特征进行分类的典型步骤:
- 我们在图像上运行SIFT检测器,它会在不同位置被激活。例如,在眼睛和嘴巴的角落。
- 然后,我们根据这些激活的位置创建一个描述图像的向量。这个向量可能在某些位置有激活,在其他位置没有激活。
- 这可以类比于文档中的词语。就像“messy”或“football”这些词是否出现一样,图像中特定位置是否出现一个角落。
- 一旦我们有了这个图像描述,就将其输入到一个分类器中。例如,一个简单的线性分类器,就像我们在本模块早些时候讨论过的那样。这些分类器有诸如逻辑回归、支持向量机等名称。
- 最终,我们得到一个检测结果,判断这张图像是否是人脸。
这听起来相当令人兴奋,并且确实对计算机视觉领域产生了重大影响。

手工构建特征的挑战与神经网络的解决方案 🤖
上一节我们介绍了传统特征的使用流程,本节中我们来看看其面临的挑战以及神经网络如何提供解决方案。
然而,挑战在于,创建这些手工构建的图像特征是一个非常复杂的过程,需要多篇博士论文才能做好。
神经网络将自动发现和学习这些特征。
让我给你一个例子。假设你输入一张图像,我将其通过一个三层神经网络进行预测。通常发生的情况是,网络会学习到局部特征检测器。这些检测器类似于SIFT,但在不同层、不同级别上学习,它们检测图像的不同属性。
- 在第一层,你可能会学习到看起来像小块的检测器,它们对对角线边缘等特征反应强烈。例如,这里的第一个检测器主要捕捉对角线边缘,中间那个捕捉另一个方向的对角线边缘,最后一个捕捉从暗色到绿色的颜色过渡。
- 在下一层,你将结合这些对角线边缘检测,形成更复杂的检测器。例如,在这一层中,我们发现了波浪线和图案检测器,也发现了对角落反应强烈的检测器,它们倾向于检测图像中的角落。
- 在最后的层,你会得到更复杂的检测器。对于各种图像,你最终可能会得到对树木和面孔有反应的检测器,或者如果你有一个更大的数据集,甚至可能对珊瑚图像有反应的检测器。
因此,神经网络在不同层捕获不同类型的图像特征,并且这些特征是自动学习得到的。
总结 📝

本节课中我们一起学习了深度学习在计算机视觉中的应用。我们从图像特征的基本概念入手,了解了传统手工特征(如SIFT)如何用于图像分类。随后,我们探讨了手工构建特征的复杂性挑战,并重点学习了神经网络如何通过其分层结构,自动从数据中学习从简单边缘到复杂物体(如人脸、树木)的各级特征。这体现了深度学习在特征学习方面的强大自动化和表达能力。
第一部分 97:深度学习性能 🚀

在本节课中,我们将要学习深度学习在计算机视觉领域的性能表现,特别是通过几个关键案例来理解其突破性进展。
深度学习的吸引力

深度学习之所以令人兴奋,是因为它能够学习图像的复杂特征。正如我们之前讨论的,近年来深度学习在各种计算机视觉应用中产生了巨大影响。
以下是几个早期示例。

- 交通标志识别:幻灯片顶部展示了一个基于神经网络的交通标志识别示例。这是一个德国交通标志数据集,目标是对每张图像识别出具体是哪种标志。使用深度神经网络,他们能够达到 99.5% 的准确率,这非常出色。
- 街景门牌号识别:底部展示的是谷歌基于街景数据识别门牌号的工作示例。这些数据是谷歌通过汽车在世界各地拍摄街道获得的。可以看到图像相当复杂,但他们仍然在单个字符级别上达到了 97.8% 的准确率。
这些成果令人振奋,但真正改变一切、激发整个领域热情的事件发生在2012年。
2012年的突破:ImageNet竞赛
多年来,有一个名为ImageNet的图像识别竞赛。2012年,该竞赛包含了来自大约100个不同类别的 120万张 训练图像。其目标是进行精细分类,例如,不仅要识别出是狗,还要识别出是金毛猎犬还是拉布拉多犬。
当时有许多团队参赛,以下是前三名团队的表现。

- 牛津VGG团队:取得了相当不错的准确率。如果看他们预测概率最高的五个答案(Top-5),错误率大约为 25%。
- ISI团队:表现稍好一些。这些团队使用的是传统技术,例如更复杂的类SIFT特征。
然而,那一年出现了一个名为 SuperVision 的团队。
SuperVision团队的革命性成果
SuperVision团队使用了深度神经网络,并取得了相对于竞争对手的巨大优势。


这一表现真正点燃了在计算机视觉中使用深度神经网络的热情,因为模型不再需要依赖手工编码的特征,而是可以自动学习这些特征。
获胜网络:AlexNet
SuperVision团队赢得比赛的神经网络被称为 AlexNet。

以下是该网络的关键信息:
- 网络结构:包含 8层。
- 参数量:高达 6000万 个参数。
- 实现关键:这种规模的网络之所以成为可能,得益于能够处理大量图像和参数的新训练算法,以及他们的 GPU 实现,这使其能够真正扩展到大型数据集。
总结

本节课中,我们一起学习了深度学习在图像识别任务上的卓越性能。我们回顾了早期在交通标志和门牌号识别上的成功应用,并重点分析了2012年ImageNet竞赛中AlexNet的突破性胜利。这次胜利的关键在于深度神经网络能够自动学习特征,并借助GPU和大规模数据进行高效训练,从而开启了深度学习在计算机视觉领域的新纪元。
第一部分 98:在ImageNet数据上展示深度学习模型 🖼️

在本节课中,我们将通过一个实际演示,了解深度学习模型在ImageNet数据集上的预测能力。我们将看到模型如何准确识别上千种不同类别的图像,并探讨其实际应用潜力。
深度学习在ImageNet竞赛中的影响
上一节我们介绍了深度学习的基本概念,本节中我们来看看它在ImageNet竞赛中的具体表现。深度学习对ImageNet竞赛产生了巨大影响,使得研究人员能够利用深度神经网络处理海量图像数据,并在预测1000个不同类别时取得惊人性能。

演示:基于AlexNet的图像识别服务
以下是基于ImageNet数据集训练的AlexNet模型部署为服务的演示。该服务托管在网站上,每次点击图像都会将其发送至运行在GPU上的服务端,并快速返回预测结果。

预测示例分析
我们将通过几个具体示例,展示模型的预测效果。
示例一:停车计时器
点击下图中的图像,将其发送至托管在Amazon AWS上的服务:

模型返回的预测结果是“停车计时器”,这是正确的标签。第二可能的预测是“挂锁”,虽然图像中部分结构类似挂锁,但模型准确识别为停车计时器。
示例二:显示屏
点击另一张图像,发送至服务后返回的预测是“屏幕”或“显示器”。虽然“屏幕”和“显示器”的区分不明确,但预测基本正确。
示例三:琵鹭
点击下图中的图像:
模型非常确信这是一只“琵鹭”,预测结果正确。
示例四:啤酒瓶
点击图像后,模型预测为“啤酒瓶”或“汽水瓶”,真实标签是“啤酒瓶”,预测准确。
模型在未知图像上的泛化能力
以上示例均来自原始ImageNet数据集。现在,我们测试一张不在原始数据集中的图像:
点击下图中的图像(我的狗),将其发送至服务:
模型返回的预测是“拉布拉多寻回犬”。这是我的狗,图像中的狗与数据中的拉布拉多寻回犬相似。可以看到,即使对于不在原始数据集中的图像,模型仍能给出有趣的预测。
总结与应用展望
本节课中我们一起学习了深度学习模型在ImageNet数据集上的强大识别能力。通过实际演示,我们看到模型不仅能准确识别训练过的图像类别,还展现出一定的泛化能力。
在您的实践项目中,可以构建类似的服务,但不仅限于图像识别。例如,可以结合深度学习方法处理产品图像和文本,构建推荐系统,并部署为在线服务。这样,任何人都能通过类似网站体验您所构建的机器学习应用,亲身感受机器学习技术的实际威力。
第一部分 99:深度学习在计算机视觉中的其他应用示例 🖼️

在本节课中,我们将探讨深度学习在计算机视觉领域,除了图像分类之外的几种其他强大应用。我们将了解神经网络如何解析图像内容、理解场景,以及实现基于内容的图像检索。
上一节我们介绍了神经网络在图像分类任务中的应用。本节中,我们来看看它在计算机视觉中的其他创造性用途。
图像解析与场景理解 🧩
神经网络不仅能识别图像中的物体,还能对图像的每一个像素进行分类,从而实现更精细的图像解析。
在下面展示的示例中,系统试图为图像中的每个像素分类,并识别出不同的区域。

例如,在中间靠上的图像里,你可以看到一片被标记为“天空”的区域,另一片是“草地”,等等。
这种为图像生成详细描述的技术,也被称为场景理解,它非常酷。神经网络在此类任务上再次带来了显著的性能提升。

图像检索:寻找相似物品 👟
现在,让我们回到本模块开始时讨论的那个场景:一种新的购物方式。其核心功能其实是检索相似图像。
以下是实现此功能的核心概念:系统学习将图像转换为一个数字向量(称为“嵌入”),相似物品的向量在数学空间中也彼此接近。计算相似度通常使用余弦相似度公式:
相似度 = (A·B) / (||A|| ||B||)
其中 A 和 B 是两个图像的向量表示。

具体来说,如果我输入一张模糊的黑色鞋子图片,经过训练的深度神经网络能够输出一系列与之相似的鞋子图片,如下方所示,结果是一堆各式各样的黑色鞋子。

如果输入一张更时尚的靴子图片,它会给出各种有趣的长靴。同理,对于高跟鞋、棕色鞋子或运动鞋也是如此。

这正是我们在模块开头演示中使用的核心概念。


本节课中我们一起学习了深度学习在计算机视觉中的两个扩展应用:精细到像素的图像解析与场景理解,以及基于向量相似度的图像检索技术。这些应用展示了神经网络如何超越简单分类,实现对图像内容更深层次的理解和利用。
机器学习专项课程:第2课:回归课程介绍 🎯

在本节课中,我们将要学习回归分析,这是从数据中提取信息最广泛使用的统计学和机器学习工具之一。我们将深入探讨其背后的模型与算法,而不仅仅是停留在表面的应用。
欢迎来到机器学习专项课程的回归部分。回归是从数据中获取信息最广泛使用的统计学和机器学习工具之一。其方法应用广泛,从预测股票价格到理解基因调控网络均可实现。

在专项课程的第一课中,我们从宏观层面讨论了回归并实现了一些方法。在本课程中,我们将深入更多细节,真正探究支撑我们完成回归任务的底层模型和算法。
本课程是机器学习专项课程的一部分,该系列课程设计为按特定顺序学习。虽然你可以将本课程作为独立课程学习,但为了获得我们预期的完整学习体验,我们强烈建议你按顺序学习整个专项课程。
具体来说,我们假设你已经学习了“基础”课程的内容。该课程对本专项将涵盖的所有内容进行了宏观概述,并让你对不同方法进行了实践练习。

本课程聚焦于回归分析。作为课程的一部分,我们将教授一系列在机器学习多个领域都非常有用的通用概念。虽然我们将在回归模型和算法的背景下描述这些内容,但其中一些概念将贯穿整个专项课程。
后续课程将包括分类、聚类与检索、推荐系统等。所有这些内容将以一个顶点项目作为总结,该项目涉及深度学习,并将融合本专项其他方面的知识。

本节课中,我们一起学习了回归课程的整体介绍、它在专项课程中的位置以及即将学习的核心内容。我们了解到,回归是一个强大的数据分析工具,本课程将深入其原理,并学习对后续机器学习领域至关重要的通用概念。
机器学习(回归):第2课:课程内容是什么 🎯


在本节课中,我们将要学习回归分析的基本概念及其在机器学习中的应用。我们将通过具体案例,理解如何利用数据特征预测连续值输出,并初步了解本课程的核心案例——房价预测。
现在,让我们深入探讨本课程的主要内容。
在基础课程中,我们讨论了机器学习如何从数据中提取智能。在本课程中,我们将重点关注的机器学习方法是回归分析。回归分析的核心假设是:我们拥有从数据中提取的某些特征,这些特征作为回归模型的输入;我们的目标是预测一个连续的数值输出或对输入的响应。
我们将通过学习输入 X 与输出 Y 之间的关系来实现这一目标。
例如,你可能想知道学习这门机器学习专项课程最终会为你带来什么回报。你正在投入大量努力,并好奇这会引领你走向何方。一个你可能感兴趣的问题是:完成此专项课程后,你的薪资会是多少?
我们可以考虑基于以下特征来预测你的薪资:你在各门课程中的表现、你的毕业项目质量、你参与了多少次论坛回复等。这些特征将作为回归模型的输入,而我们试图预测的输出则是你完成此专项课程后的预期薪资。
另一个例子是预测股票价格。要形成这个预测,我们可能预期它会依赖于该股票的历史价格、最近的新闻事件以及其他相关商品的趋势。
或者,也许你发布了一条推文,想知道会有多少人转发。这可能取决于你的粉丝数量、你粉丝的粉丝数量、你的粉丝网络结构、你使用的标签、你过去获得的转发次数等特征。
本课程将讨论的另一个非常酷的例子是“读心术”。当你进行某种脑部扫描(如fMRI或MEG)时,我们可以将其视为生成一张你的大脑图像。我们可以将所有不同的像素强度作为回归模型的输入,而模型的输出目标是预测你在接受扫描时,对所展示事物的感受是快乐还是悲伤。这之所以是“读心术”,是因为我们想仅从大脑图像中猜测你的感受。
但在本课程中,我们将聚焦于一个具体案例研究:预测房价。
具体来说,我们要回答的问题是:一栋给定房屋的价值是多少?也许你想出售房屋,并需要确定挂牌价格。我们将通过查看数据来获取这种智能。我们将查看的数据包括:
以下是用于预测房价的关键数据输入:
- 其他房屋的销售记录:我们将获取大量其他房屋的销售价格。
- 这些房屋的属性特征:例如面积、卧室数量、地理位置等。
从这些房屋属性输入中,我们将学习房屋属性与输出(销售价格)之间的关系,并利用这个学习到的模型来预测你的房屋价值。
本课程的全部内容就是关于如何建立输入与输出之间的这种关系。


本节课中,我们一起学习了回归分析的基本目标:利用输入特征预测连续值输出。我们通过薪资、股票价格、社交媒体互动甚至“读心术”等生动例子,理解了回归的广泛应用。最后,我们明确了本课程将围绕房价预测这一核心案例,学习如何从房屋属性数据中建立模型,以预测其销售价格。在接下来的课程中,我们将深入探讨实现这一目标的具体方法。
机器学习(回归):第2课:课程前半部分概述 📚


在本节课中,我们将预览机器学习回归课程前半部分的核心内容。课程包含六个不同的模块,我们将逐一介绍每个模块的主题和目标。
模块一:简单回归 📈
首先,我们将讨论简单回归。之所以称为“简单”回归,是因为我们只关注单个输入变量,例如房屋面积。在定义这个单一输入与输出(如房屋售价)之间的关系时,我们仅考虑用一条简单的直线来拟合数据,因此得名简单回归。
为了找到最佳拟合线,我们需要定义一个拟合优度度量。这个度量标准允许我们判断某些直线比其他直线拟合得更好。根据这个度量,我们可以搜索所有可能的直线,以找到对数据拟合最佳的那一条。
模块二:优化技术 ⚙️
在定义了拟合优度度量的背景下,我们将讨论一些重要的优化技术。这些技术比回归本身更具普适性,是本专项课程中会反复出现的核心概念之一。
我们将在此探索的方法是梯度下降法。在我们的回归问题中,对于一条简单的直线,核心问题是:什么样的斜率和截距能使拟合优度度量最小化?下图中的蓝色曲线展示了拟合优度,数值越低代表拟合越好。
我们将尝试在所有可能的截距和斜率组合中,找到拟合最佳的组合。梯度下降法是一种迭代算法,它将通过多个步骤最终找到使拟合度量最小化的最优解。
模块三:参数解释与预测 🔮
一旦我们找到了最小值,即确定了最佳截距和斜率,接下来将讨论如何解释这些估计参数,以及如何利用这些参数进行预测。
模块四:多元回归 🏠
我们将从简单回归过渡到多元回归。多元回归允许我们拟合输入与输出之间更复杂的关系(不仅仅是直线),并能在模型中考虑更多的输入变量。
例如,在房价预测应用中,除了房屋面积,我们可能还想纳入卧室数量、浴室数量、地块大小、建造年份等一系列不同的房屋属性。多元回归使我们能够将这些因素整合到预测模型中。
模块五:模型评估与过拟合 ⚖️
在学习了如何将模型拟合到数据之后,我们将转向如何评估拟合的好坏,尤其是在进行预测时。
例如,下图所示的房屋面积与房价之间的拟合看起来相当不错。但如果我们使用一个复杂得多的模型,可能会发现它做出了非常奇怪的行为。仔细观察,这个复杂的拟合函数确实很好地解释了我们的观测数据(图中的圆圈)。然而,它无法推广到预测我们未观测到的新房屋。至少,我不会用这个模型来预测我的房屋价值,因为我不相信这是房屋面积与价格之间的真实关系。
这里出现的问题被称为过拟合。在本模块中,我们将详细讨论这个问题。
具体来说,我们将定义三种不同的误差度量:
- 训练误差
- 测试误差
- 泛化误差(或真实误差),这是我们真正希望得到的误差。
我们将证明,泛化误差实际上是我们无法直接获得的,必须使用代理指标(如测试误差)来代替。我们将通过观察误差度量随模型复杂度变化的趋势,来描述过拟合的概念。
模块六:偏差-方差权衡 ⚖️
最后,我们将在偏差-方差权衡的背景下讨论这些概念。这个权衡描述了以下事实:简单模型通常行为良好,但往往过于简单,无法描述我们感兴趣的真实关系;另一方面,非常复杂的模型非常灵活,有潜力拟合非常复杂的关系,从而很好地描述数据,但不幸的是,这些极其复杂的模型可能表现出非常奇怪的行为。
因此,这导致了所谓的偏差-方差权衡。机器学习在很大程度上就是探索这种权衡。

本节课总结:我们一起预览了机器学习回归课程前半部分的六个核心模块,从基础的简单回归和优化方法,到更复杂的多元回归,再到关键的模型评估、过拟合问题以及机器学习中核心的偏差-方差权衡概念。
机器学习:第2课:课程后半部分概述

在本节课中,我们将学习回归分析中几个核心的高级概念与方法。我们将探讨如何平衡模型复杂度与拟合度,如何选择重要特征,以及一些强大的回归技术。这些内容将帮助我们构建更准确、更高效的预测模型。
处理偏差-方差权衡:岭回归
上一节我们介绍了模型拟合与复杂度之间的权衡。本节中,我们来看看一种具体处理此问题的方法:岭回归。
岭回归不仅包含衡量函数对数据拟合程度的项,还引入了一个编码模型复杂度的项。其核心目标函数公式如下:
目标函数 = 拟合误差项 + λ × 模型复杂度惩罚项
其中,λ 是一个关键参数,用于平衡“拟合数据”和“控制模型复杂度”这两个目标。λ 值越大,对复杂模型的惩罚越重。
选择平衡参数:交叉验证
那么,如何确定这个平衡参数 λ 的最佳值呢?我们将使用一种称为交叉验证的方法。
交叉验证是一种通用的工具,不仅限于回归问题,它适用于任何需要选择调优参数的机器学习模型。以下是交叉验证的基本步骤:
- 将数据集随机分成若干份(例如5份)。
- 依次将其中一份作为验证集,其余作为训练集。
- 用训练集训练不同 λ 值的模型,并在验证集上评估性能。
- 选择在验证集上平均性能最好的 λ 值。
识别重要特征:特征选择任务
在实际问题中,我们可能拥有大量特征。例如,预测房价时,特征可能包括面积、卧室数量、是否有微波炉等。特征选择的目标是找出对预测真正有信息量的特征子集。
这样做有两个好处:一是提高模型的可解释性,二是使用更少的特征可以显著提升预测效率。
为了完成特征选择,我们首先会讨论如何显式地搜索包含不同特征集的模型。接着,我们将转向一种与岭回归思想相似,但能隐式进行特征选择的方法。
隐式特征选择:套索回归
这种方法就是套索回归。与岭回归类似,它的目标函数也包含数据拟合项和模型复杂度惩罚项,但惩罚项的定义不同。
套索回归使用的惩罚项会导致所谓的稀疏解,即最终模型中只有少数特征的系数不为零,从而自动实现了特征选择。其目标函数可表示为:
目标函数 = 拟合误差项 + λ × Σ|系数|
优化新方法:坐标下降法
我们将以套索回归为例,学习另一种重要的优化算法——坐标下降法。
之前我们介绍了梯度下降法。坐标下降法是另一种迭代优化算法,其核心思想是:不直接求解高维优化目标,而是逐个坐标(即逐个变量)进行优化。在每次迭代中,它沿着坐标轴方向移动,依次优化每个参数。
简单而强大的技术:最近邻回归
最后,我们将讨论一种非常简单但功能强大的技术:最近邻回归。
在最简单的情况下,如果我想预测我的房子的价格,我会在数据集中找到与我的房子最相似的房子,然后直接将该房子的售价作为我的预测值。
我们可以将这个思想推广:不是只看最相似的房子,而是看一组相似的房子,然后取这些房子价格的平均值作为预测。更进一步,可以使用核回归:数据集中每一个观测值都会影响预测值,但在计算平均值时,会根据每个房子与目标房子的相似度进行加权。非常相似的房子权重很高,非常不相似的房子权重则很低。
这种方法能产生非常漂亮的回归拟合结果,并且具有很好的适应性:随着数据增多,它可以描述越来越复杂的关系。当拥有大量数据时,这些方法非常有用。在本模块中,我们也将讨论数据量与模型复杂度之间的权衡。
总结


本节课中,我们一起学习了回归分析中多个重要的领域。我们不仅讨论了岭回归、套索回归、最近邻回归等多种回归模型,还介绍了梯度下降、坐标下降等通用优化算法。同时,我们深入理解了机器学习的一些基础核心概念,包括偏差-方差权衡、用于选择调优参数的交叉验证、稀疏性、过拟合以及模型与特征选择。这些内容构成了我们专业课程体系中非常重要的一部分。
机器学习(回归):第2课:课程背景知识要求 📚


在本节课中,我们将介绍成功学习本课程所需具备的背景知识。了解这些前提条件有助于你更好地准备并跟上课程进度。
数学背景要求
上一节我们介绍了课程的整体情况,本节中我们来看看对数学基础的要求。我们假设你具备非常基础的微积分知识。
以下是具体的数学知识要求:
- 基础微积分:例如,知道如何对单变量函数求导。课程会以较慢的节奏回顾这些内容,但如果你还记得会很有帮助。
- 基础线性代数:例如,知道如何进行向量或矩阵的乘法,以及理解矩阵和向量的基本概念。同样,课程初期会逐步讲解这些内容。
编程背景要求
在明确了数学要求后,我们接下来看看编程方面的要求。我们努力使本课程对各种编程语言偏好的学习者都尽可能开放。
以下是编程相关的具体说明:
- 推荐语言:我们鼓励使用 Python,但这并非强制要求。
- 起始代码:所有编程作业都会提供一些起始代码,这些代码将使用 Python 编写。因此,熟悉 Python 会很有帮助,但你也可以使用任何你喜欢的语言。
- 课程重点:我们的重点是教授机器学习的概念,而非具体的实现细节。
- 与前一课程的关系:如果你完成了本专项课程第一门课的编程作业,那么你已经具备了学习本课程所需的编程基础。
- 实现深度:在第一门课中,我们依赖了如
GraphLab Create这样的预实现算法。而在本课程中,我们将教授你所有算法的细节以及如何实现它们,以便你能自己编写代码。
工具与作业结构
了解了背景知识后,我们来看看课程中将使用的工具以及作业的组织方式。
以下是关于工具和作业结构的详细信息:
- 数据工具:本课程建议你使用 SFrame(一个开源库,可实现可扩展且高效的数据操作)。你也可以使用任何你喜欢的数据结构或库,例如 pandas。
- 作业结构:作业结构分为两部分。
- 第一部分:探索高级概念。我们鼓励使用预实现的算法,以便你能在不被自己实现中潜在错误困扰的情况下测试这些高级概念。
- 第二部分:实现算法细节。在探索了相关概念后,你将从头开始实现所有算法,而不依赖任何预实现的方法。
- Python 库:如果你使用 Python,你将使用 NumPy 库来操作矩阵和向量。
最终,在本课程中,你将亲自动手实现专项课程第一门基础课中见过的所有回归相关方法,以及本课程将要探索的一系列新方法。
计算资源要求
最后,我们来讨论一下所需的计算资源。这里有两个选项可供选择。
以下是两种计算资源方案:
- 使用自己的计算机:你可以使用自己的电脑,配置可以相当基础。但如果你打算使用 SFrame,则需要一台 64 位 的机器。此外,你还需要:
- 能够访问互联网(用于观看视频和完成编程作业)。
- 能够安装并运行 Python 及相关库。
- 能够存储几 GB 的数据。
- 使用云端机器:特别是如果你没有 64 位机器,我们提供了一组云端机器,它们已预配置好本课程所需的一切。你只需要能访问互联网来使用这些云端机器即可。

总结

本节课中,我们一起学习了成功学习本回归课程所需的背景知识。我们明确了所需的数学基础(微积分和线性代数)、编程准备(推荐Python,但非强制)、课程将使用的工具(如SFrame、NumPy)以及作业的结构(先探索概念,再动手实现)。最后,我们了解了两种满足计算资源需求的方案:使用自己的64位计算机或使用我们提供的云端机器。现在,让我们正式开始课程的学习。
机器学习:回归:第2课:预测房价的案例研究 🏠

在本节课中,我们将开始学习回归分析的第一部分——简单回归。我们将通过一个预测房价的案例研究,来理解回归模型的基本概念和应用。
概述
简单回归,顾名思义,是回归分析中最简单的形式。它假设我们只有一个输入特征,并试图拟合一条直线来描述数据。在深入探讨简单回归模型之前,我们先回顾一下我们的核心任务:预测房价。
案例研究:预测房价
我们的案例研究围绕如何预测房价展开。具体来说,我们有一套房子想要出售,但不确定它的市场价值。
正如我们在本系列课程的第一课中详细讨论的,解决这个问题的标准方法是:参考近期售出的其他房屋的数据。我们将分析这些已售房屋的售价及其各种特征(例如面积、卧室数量等),然后利用这些数据来为我们想要出售的房屋制定一个合理的挂牌价格。
上一节我们介绍了回归分析的整体目标,本节中我们来看看如何将这个目标应用到一个具体的预测问题中。
简单回归模型简介
简单回归模型是我们处理这类预测问题的起点。它只考虑一个输入特征(例如房屋面积)与输出目标(例如房屋售价)之间的关系,并用一条直线来拟合这种关系。
以下是构建简单回归模型的核心步骤:
- 收集数据:获取包含输入特征(如房屋面积)和对应输出(如售价)的历史数据。
- 选择模型:假设特征与目标之间存在线性关系,模型形式为
y = w0 + w1 * x。- y 是预测的房价(目标变量)。
- x 是房屋面积(输入特征)。
- w0 是截距(模型参数)。
- w1 是斜率(模型参数),表示面积每增加一单位,房价的平均变化。
- 拟合模型:通过算法(如最小二乘法)找到最佳的
w0和w1参数,使得模型预测的房价与实际售价之间的误差最小。 - 进行预测:将我们新房子的面积
x_new代入拟合好的模型公式y_pred = w0 + w1 * x_new中,计算出预测的房价y_pred。


总结

本节课中我们一起学习了回归分析的入门知识。我们通过预测房价的案例研究,引出了简单回归模型的概念。简单回归模型使用单一输入特征来预测输出目标,并通过拟合一条直线来揭示两者之间的关系。理解这个基础模型是后续学习更复杂回归方法的关键。在接下来的课程中,我们将深入探讨如何具体构建和评估这个模型。
机器学习(回归):第2课:回归基础:数据与模型

在本节课中,我们将学习回归分析的基础知识,包括理解数据、模型以及我们感兴趣的任务。我们将从最简单的线性回归入手,探讨如何利用房屋面积来预测其售价。
数据与模型
首先,我们需要收集数据。假设我们观察了近期售出的一系列房屋,对于每一栋房屋,我们记录两个信息:房屋的面积(以平方英尺为单位)和它的最终售价。



- 输入变量 (X):这是我们用于预测的变量,在本例中是房屋面积。
- 输出变量 (Y):这是我们想要预测的目标变量,即房屋售价。

输出变量 Y 是我们关心的核心目标。我们假设可以根据输入变量 X 来预测 Y,也就是说,我们可以根据房屋的面积来预测其售价。
接下来,我们将数据绘制在图上,X 轴代表房屋面积,Y 轴代表售价。图中的每一个点代表一栋已售出的房屋。

例如,图中某个特定的点代表数据中的第 i 栋房屋。这栋房屋拥有特定的面积 Xi 和特定的售价 Yi。
我们的模型旨在揭示 X 和 Y 之间预期的关系。因为一旦掌握了这种关系,我们就可以用它来预测我想挂牌出售的房屋价格。
我们假设存在某种函数关系,记作 F(x)。这个函数 F(x) 代表了 X 和 Y 之间预期的关系。
模型与误差
为了更清晰地说明,让我们看另一栋房屋,比如第 j 栋房屋,它的数据点是 (Xj, Yj)。现在,我们关注第 i 栋房屋,它的售价是 Yi。
根据我们的模型,我们假设 Yi 近似等于 F(Xi),即房屋面积 Xi 与其售价 Yi 之间的函数关系。
但是,我们承认模型并非 100% 准确。很容易想象模型会存在误差,因为即使两栋房屋面积完全相同,也可能因售出时间、卧室数量、浴室数量、院子大小、具体地理位置、学区等众多未纳入模型的因素而以不同价格售出。
因此,我们的模型只是我们用于预测的一种信念或工具,它并不完美,存在误差。
具体来说,图中的 F(Xi) 是函数在 Xi 处的精确值。而我们观察到的数据点 Yi 并不完全落在这条由 F 定义的曲线上,它们之间存在一个误差。
我们将这个针对第 i 栋房屋的误差称为 εi。
所以,我们的回归模型假设是:我们的观测值 Yi 等于预期的关系 F(Xi) 加上某个误差 εi。
用公式表示就是:
Yi = F(Xi) + εi
我们进一步将这个误差 εi 视为一个随机变量,并假设它的期望值(即所有可能误差值的加权平均,权重为各值出现的概率)为零。
这意味着,对于任何一栋房屋的销售,出现正误差(预测值低于实际售价)和负误差(预测值高于实际售价)的可能性是相等的。
这也就意味着,我们得到的任何一个具体观测值 Yi,其高于或低于由 F 定义的函数关系的可能性是相同的。
需要明确的是,上面描述的这一切(Yi = F(Xi) + εi 且 E[εi] = 0)只是我们关于世界如何运作的一种假设模型。正如乔治·博克斯那句名言所说:“所有的模型都是错的,但有些是有用的。” 这意味着,没有一个模型能完全精确地反映现实世界。即使你纳入了更多变量,世界运作中总存在各种特例。然而,模型代表了变量之间(例如面积与价格)一种有用的抽象关系,对于像预测这样的任务是有价值的。
总结
本节课中,我们一起学习了回归分析的基本框架:
- 我们定义了输入变量 (X) 和想要预测的输出变量 (Y)。
- 我们引入了一个函数模型
F(x)来描述 X 和 Y 之间预期的关系。 - 我们认识到模型不可能完美,因此引入了误差项
ε,并假设其期望值为零,这意味着模型预测可能 equally likely 地高于或低于真实值。 - 我们理解了建立模型的目的在于获得对现实世界有用的抽象,而非追求绝对精确。

在接下来的课程中,我们将探讨如何具体定义函数 F(x),以及如何从数据中学习到这个函数的最佳参数。
机器学习:第2课:回归基础:任务

在本节课中,我们将学习回归分析中的核心任务。我们将探讨如何为数据选择合适的模型,以及如何根据数据估计出模型的具体参数。

我们面临的第一个回归任务是确定使用何种模型。我们需要判断平方英尺与房价之间是恒定关系、线性关系,还是更复杂的多项式关系。
以下是几种可能的模型假设:
- 恒定关系:无论房屋面积大小,预期售价都相同。
- 线性关系:房价随面积增加而按固定速率增长。
- 二次或更高阶多项式拟合:关系曲线更为复杂。
我们可以考虑的模型列表非常长。本课程的部分内容就是探索数据建模的各种不同选择。
因此,一项核心任务是从所有可能考虑的模型空间中,为给定的数据和任务选择最合适的模型。
上一节我们讨论了模型选择。现在,让我们假设已经选定了模型。例如,我们决定使用二次函数进行拟合。
那么,我们的下一个任务就是从数据中估计出一个具体的二次拟合曲线。
模型本身只规定了函数的形式,它由一组参数定义。我们需要根据数据来估计这些参数的具体值,从而得到一个具体的拟合结果。
例如,下图中的曲线就是我们根据特定数据集估计出的二次拟合函数,我们称之为 F_hat(x)。

当然,我们也有可能拟合出另一条不同的曲线。本课程将详细讨论如何将模型 F 拟合到数据的方法。
核心要点是:首先,我们必须选择一个模型;其次,我们必须提供某种程序或算法,将该模型拟合到数据中,并得出一条用于预测等任务的具体曲线。

本节课中,我们一起学习了回归分析的两大核心任务:模型选择和参数估计。我们了解到,模型定义了关系的整体形式,而拟合过程则根据数据确定该形式的具体参数,最终得到一个可用于预测的估计函数。
机器学习(回归):第2课:回归机器学习模块图 📊

在本节课中,我们将学习回归任务在机器学习中的标准流程,即模块图。我们将详细拆解从原始数据到最终预测的每一个步骤,并理解每个组成部分的作用。
上一节我们介绍了回归的基本概念,本节中我们来看看如何将这个过程形式化为一个清晰的模块图。

在本专项课程的第一门课中,我们介绍了这个用于回归以及其他机器学习任务的模块图或流程图。现在,我们将再次详细梳理它。
我们假设我们拥有一些训练数据。训练数据的概念在专项课程的第一门课中已从高层次讨论过。在本课程中,我们将详细讨论训练数据、测试数据、验证集等概念,以及评估模型拟合度、在模型间进行选择等众多主题。目前,我们只需理解我们拥有一些训练数据,并正在使用这些数据来拟合一个特定的模型。在本模块的其余部分,我们将只关注训练数据。
因此,当我们谈论数据时,我们指的是已经完成某种划分后得到的训练数据集。
我们拥有训练数据。在这个案例中,数据是一个包含以下信息的表格:
- 房屋ID
- 房屋面积(平方英尺)
- 房屋销售价格
我们有一个包含所有这些数量的大表格。
接下来,我们要做的是提取一些特征。在这一点上,与其具体说“面积”,不如说存在一组房屋属性。我们可能除了面积之外还有其他属性。因此,我们必须做的一个步骤是确定将什么作为回归模型的输入。我们将在课程后面讨论更一般的特征,但现在我们假设一个简单的设置:我们将选择房屋属性中的一个作为回归模型的输入,并在此基础上进行工作。我们讨论过使用面积作为选定的输入。
然后,我们将使用我们的机器学习模型——即回归——来预测房屋销售价格。y_hat 代表我们预测的房屋销售价格。
我们如何预测它呢?基于某条估计的直线或曲线。这个 f_hat 就是我们根据数据集(具体来说是训练数据集)拟合得到的估计函数。
我们如何确定 f_hat,即如何估计这个函数呢?首先,我们需要定义一个质量度量标准。我们已经提前提到过这一点,现在让我们明确地写下来。y 是房屋的实际销售价格。我们将使用任何给定的 f_hat 来比较实际销售价格和预测销售价格,并评估我们做得有多好。这就是质量度量标准的作用。
我们的预测值会存在一些误差。我们将用来拟合这些回归模型的机器学习算法,将尝试最小化这个误差。也就是说,它将在所有可能的函数中进行搜索,以减少预测值中的误差。
这就是我们的整体流程图。我们将在本模块以及本课程后续更深入的部分中,逐步讲解这个流程图的各个组成部分。




本节课中我们一起学习了回归的机器学习模块图。我们明确了从训练数据出发,经过特征选择,输入到回归模型中生成预测 y_hat 的流程。整个过程的核心是定义一个质量度量标准(即误差)并使用算法去最小化它,从而得到最优的估计函数 f_hat。这个框架是理解后续所有回归建模技术的基础。
机器学习:第2课:简单线性回归模型 🏠

在本节课中,我们将学习简单线性回归模型的基本概念。我们将了解模型的形式、参数以及如何用数学公式表示它。通过本课,你将掌握线性回归的核心思想,为后续更复杂的内容打下基础。
上一节我们介绍了机器学习模块的概览,本节中我们来看看简单线性回归的具体含义。回到我们的流程图,现在要讨论的是机器学习模型本身。图中绿色高亮部分代表模型,其余部分暂时可以忽略。我们只关注模型及其形式。
简单线性回归模型非常直观。我们假设只有一个输入特征(例如房屋面积)和一个输出目标(例如房屋售价)。模型的目标是拟合一条直线,而不是之前讨论过的二次函数或更高阶多项式。这条直线的方程是截距加斜率乘以输入变量。
以下是线性回归模型的数学表示:
公式: y = w0 + w1 * x
其中:
y是预测的输出(例如房屋售价)。x是输入特征(例如房屋面积)。w0是截距。w1是斜率。

回归模型进一步说明,每个观测值 Yi 是函数在 Xi 处的值加上误差项 εi。
公式: Yi = w0 + w1 * Xi + εi
这里的误差项 εi 表示具体观测值到拟合直线的垂直距离。
模型的参数是 w0 和 w1,分别称为截距和斜率,统称为回归系数。这概括了我们的简单线性回归模型,它非常直接和简单,后续我们会探讨更复杂的内容。

本节课中我们一起学习了简单线性回归模型的基本形式。我们了解了模型如何用一条直线拟合数据,以及如何用数学公式 y = w0 + w1 * x + ε 表示它。我们还明确了模型参数 w0 和 w1 的含义。这些知识是理解更复杂回归模型的基础。
机器学习:第2课:使用给定直线的成本


在本节课中,我们将学习如何衡量一条直线对数据的拟合质量。我们将介绍一个核心的质量度量指标——残差平方和,并理解它如何帮助我们找到最佳的拟合直线。
上一节我们介绍了简单线性回归模型,本节中我们来看看如何衡量一条特定直线的拟合质量。在讨论具体的拟合算法之前,我们需要一个标准来评估拟合的好坏,这个标准就是成本函数。
现在,我们的函数由参数 W(即截距 w0 和斜率 w1)决定。因此,预测值不再用估计函数 f_hat 表示,而可以用估计参数 W_hat 表示。所以,我们的目标转变为估计这些参数 W。
那么,使用一条特定直线的“成本”是什么呢?在本课程中,我们重点介绍残差平方和。其核心思想是:计算我们根据直线预测的房价与实际观测到的房价之间的所有误差,将这些误差(或称残差)平方后求和。
以下是残差平方和的计算公式:
RSS(w0, w1) = Σ (y_i - (w0 + w1 * x_i))^2
其中:
Σ表示对训练数据集中所有房屋(i = 1到N)求和。y_i是第i个房屋的实际售价。x_i是第i个房屋的面积(平方英尺)。(w0 + w1 * x_i)是我们的直线对该房屋售价的预测值。
简单来说,残差平方和就是:对于数据集中的每一个点,计算其实际值与直线预测值之差的平方,然后将所有这些平方差加起来。
现在,我们有了这个成本函数。对于任意给定的一组参数 (w0, w1),即任意一条直线,我们都能计算出一个对应的 RSS 值。
例如:
- 直线 A(参数为
w0=0.97,w1=0.85)对应一个 RSS 值(假设为 100)。 - 直线 B(不同的参数)对应另一个 RSS 值(假设为 150)。
- 直线 C(另一组参数)也对应一个 RSS 值(假设为 80)。
我们的目标是从所有可能的直线(即所有可能的 w0 和 w1 组合)中,找到使残差平方和 RSS 最小的那一条。在上述例子中,我们会选择直线 C,因为它的成本(80)最小。


本节课中我们一起学习了衡量线性回归模型拟合质量的核心指标——残差平方和。我们了解到,RSS 是预测值与实际值之差的平方和,我们的目标是找到能使 RSS 最小化的那组参数。在接下来的课程中,我们将探讨如何系统地找到这组最优参数。
机器学习:第2课:使用拟合直线 📈

在本节课中,我们将学习如何使用已拟合的简单线性回归模型进行预测和解释。我们将从区分模型与拟合直线开始,然后探讨如何利用拟合直线进行预测,并解释其参数的实际意义。
模型与拟合直线的对比
上一节我们介绍了简单线性回归模型。现在,我们来明确模型本身与拟合直线之间的区别。
我们的模型用参数表示,这些参数是未知的。模型公式为:
[
y_i \approx f(x_i) = w_0 + w_1 x_i
]
其中 ( w_0 ) 和 ( w_1 ) 是待估计的参数。
我们的目标是根据数据估计这些参数,得到具体的数值。这些估计值用 ( \hat{w}_0 ) 和 ( \hat{w}_1 ) 表示,它们定义了具体的拟合直线。例如,一个拟合直线的方程可能是:
[
\hat{f}(x) = -44,850 + 280.076 \times x
]
因此,模型是一个包含未知参数的框架,而拟合直线是该框架下的一个具体实例。
如何使用拟合直线进行预测
现在我们已经有了一个具体的拟合直线,本节中我们来看看如何用它进行预测。
拟合直线的一个主要用途是预测。例如,如果你有一套待售房屋,知道其面积,就可以预测其售价。
预测方法非常直接:只需将房屋面积代入拟合直线的方程即可。预测值 ( \hat{y} ) 等于 ( \hat{f}(x) )。这是因为误差在直线上下的可能性均等,而 ( \hat{f}(x) ) 是基于数据对直线的最佳估计,因此我们对单个房屋价值的最佳猜测就是将其放在直线上。
以下是两种常见的预测场景:
- 预测售价:已知房屋面积,预测其市场价值。
- 估算可购面积:已知预算金额,反向计算用这些钱预计能买到多大面积的房子。


预测实例
让我们通过一个具体例子来演示如何使用拟合直线。
假设我们拥有之前提到的拟合直线:
[
\hat{f}(x) = -44,850 + 280.076 \times x
]
场景一:预测房屋售价
若一套房屋面积为2640平方英尺,其预测售价计算如下:
[
\hat{y} = -44,850 + 280.076 \times 2640 = 696,356
]
场景二:估算可购面积
若你的购房预算为859,000美元,你可以负担的房屋面积估算如下:
首先,将预算金额设为 ( \hat{y} ),然后解方程求 ( x ):
[
859,000 = -44,850 + 280.076 \times x
]
计算可得 ( x \approx 3,219 ) 平方英尺。

本节课中我们一起学习了如何区分线性回归模型与拟合直线,并掌握了使用拟合直线进行正反双向预测的方法:既可以根据自变量预测因变量,也可以根据目标因变量值反推所需的自变量值。
机器学习:第2课:解释拟合直线

在本节课中,我们将学习如何解释线性回归模型中拟合直线的系数。我们将重点关注截距和斜率这两个核心参数的含义,并理解它们的单位如何影响解释。
解释截距
上一节我们介绍了如何拟合一条直线,本节中我们来看看如何解释这条直线的参数。首先,我们讨论截距 W_hat_zero。
截距是当输入变量 X 等于零时,模型的预测值。在房价预测的例子中,它代表零平方英尺(即仅有土地)时的预测房价。其计算公式为:
y_hat = W_hat_zero 当 X = 0
然而,在许多实际场景中,截距可能没有直接的现实意义。例如,在我们的模型中,截距为负值,这暗示“土地”的价值为负,这显然不符合常理。这提醒我们,必须在模型所包含的上下文和数据噪声的背景下解释参数。
解释斜率
接下来,我们看看斜率 W_hat_one,它通常具有更明确的含义。
斜率代表了输入变量每变化一个单位时,预测输出的变化量。在房价模型中,它表示每增加一平方英尺,房屋的预测价格会增加多少。我们可以通过一个简单的计算来理解:
假设我们想比较1001平方英尺和1000平方英尺房屋的预测价值差异。计算过程如下:
预测值(1001) = W_hat_zero + W_hat_one * 1001
预测值(1000) = W_hat_zero + W_hat_one * 1000
差值 = (W_hat_zero + W_hat_one * 1001) - (W_hat_zero + W_hat_one * 1000)
= W_hat_one
因此,斜率 W_hat_one 直接等于预测输出的单位变化量。
系数的单位与量级
理解斜率和截距的量级至关重要,因为它们完全依赖于输入和输出所使用的单位。
以下是关于系数量级的核心要点:
- 截距的单位:与输出变量相同。在我们的例子中是美元。
- 斜率的单位:是“输出单位/输入单位”。在我们的例子中是美元/平方英尺。
当我们使用模型进行预测时,单位必须保持一致:
- 预测房价(美元)= 截距(美元)+ 斜率(美元/平方英尺)* 面积(平方英尺)
- 计算所需面积(平方英尺)= [目标房价(美元) - 截距(美元)] / 斜率(美元/平方英尺)
如果改变单位,例如:
- 将面积单位从平方英尺改为平方米。
- 将货币单位从美元改为人民币元。
那么,原有的系数 W_hat_zero 和 W_hat_one 将不再适用,必须基于新的单位重新拟合模型或转换系数。斜率的数值大小仅在特定的输入/输出单位组合下才有意义。
总结

本节课中我们一起学习了如何解释线性回归模型的系数。我们了解到,截距 W_hat_zero 是零输入时的预测值,但其现实意义需谨慎看待。斜率 W_hat_one 则清晰地表示了输入每增加一单位所导致的预测输出变化量。最重要的是,我们认识到这些系数的数值大小和解释强烈依赖于模型输入和输出所使用的具体单位。
机器学习:回归:第2课:定义最小二乘优化目标

在本节课中,我们将学习如何为线性回归模型定义一个明确的优化目标。我们将理解“残差平方和”的概念,并正式将其表述为一个需要最小化的数学问题。
上一节我们介绍了拟合线及其用途。本节中,我们来看看如何从所有可能的直线中,找到最贴合数据的那一条。具体来说,我们将聚焦于机器学习算法流程图中那个深灰色的方块,即优化算法部分。
我们的目标是定义一个“成本”或“损失”函数,用以衡量任何一条直线对数据的拟合程度。这个函数将帮助我们比较不同的直线,并最终找到最优的那一条。
以下是定义优化目标的核心步骤:
-
定义残差:对于数据中的每一个点,其残差是观测值(真实值)与模型预测值之间的垂直距离。数学上,对于第
i个数据点(x_i, y_i)和一条由参数W0(截距)和W1(斜率)定义的直线,残差r_i的计算公式为:
r_i = y_i - (W0 + W1 * x_i) -
定义成本函数:为了得到一个单一的数值来衡量整条线的拟合好坏,我们计算所有数据点残差的平方和。这被称为残差平方和。公式如下:
RSS(W0, W1) = Σ (y_i - (W0 + W1 * x_i))^2
其中,Σ表示对所有数据点i求和。 -
设定优化目标:我们的目标就是找到能使这个残差平方和
RSS达到最小值的参数W0和W1。这构成了一个优化问题。数学上,我们将其写作:
(Ŵ0, Ŵ1) = argmin_{W0, W1} RSS(W0, W1)
这里的Ŵ0和Ŵ1就是我们寻找的最优参数。
为了更直观地理解,我们可以将 RSS 看作一个关于 W0 和 W1 的二元函数,记作 G(W0, W1)。对于给定的数据集,我们可以绘制出这个函数的图像:以 W0 和 W1 为横纵坐标轴,以 RSS 值为高度,形成一个三维的曲面。
我们的任务就是在这个曲面上找到最低点。这个最低点所对应的 (W0, W1) 坐标,就是我们要找的最优解 (Ŵ0, Ŵ1)。

本节课中我们一起学习了如何为简单线性回归定义优化目标。我们引入了残差平方和作为衡量模型拟合好坏的成本函数,并正式将其表述为一个最小化问题:寻找使 RSS 最小的参数 W0 和 W1。这为我们接下来寻找具体优化算法奠定了基础。
机器学习:第2课:解析法求极值

在本节课中,我们将学习如何通过解析方法(即数学公式)来寻找函数的最小值或最大值。我们将首先理解凸函数和凹函数的概念,这是优化问题中确保解存在且唯一的关键。然后,我们会将这些概念应用到最小化残差平方和(RSS)这一具体任务上。
凸函数与凹函数
在深入探讨如何最小化残差平方和之前,让我们先从更抽象的角度讨论优化问题。我们将以一个通用函数为例,思考如何最小化它,并探讨函数最小值的性质以及达到该最小值的算法。
我们首先要讨论的一个重要概念是凸函数和凹函数。
下图展示了一个关于单一参数或变量(我们称之为 W)的凹函数图像。这个函数是 G(W)。

我记忆凹函数和凸函数的方法是:凹函数看起来像一个洞穴的拱顶,而凸函数则相反。我们可以这样定义凹函数:选取 W 的任意两个值,称为 A 和 B,并观察函数在这两点的值 G(A) 和 G(B)。然后,在 G(A) 和 G(B) 之间画一条线(即图中的绿色线段)。
我们看到,这条线在任意处都位于 G(W) 曲线的下方。凹函数的定义是:对于你选择的任意 A 和 B 值,连接函数上这两点的线段始终位于函数曲线本身的下方。
另一方面,凸函数具有完全相反的性质。下图是一个凸函数的示意图。

同样,这是 W 和 G(W)。如果我连接 G(A) 和 G(B),那么这条线在任意处都位于 G(W) 曲线的上方。
以上就是凹函数和凸函数非常直观的几何定义。当然,也存在既非凹也非凸的函数。
以下是两个例子:

我们如何判断这个函数既非凹也非凸?观察点 A 和点 B,并在这两点之间画一条线。我们可以看到,这条线在曲线的一部分位于其下方,在另一部分又位于其上方。因此,它既不满足凹函数的条件,也不满足凸函数的条件。同样,另一个函数也具有类似的性质。
函数的极值特性
我们讨论优化目标时,通常目标是寻找函数的最小值或最大值。对于凹函数,我们通常关注寻找最大值;对于凸函数,则关注寻找最小值。
让我们看看这个凹函数的最大值是什么。最大值就是图中这个点。我们的目标是求 max over all W G(W)。
在这个最大值点,函数有什么性质?我们知道,在该点函数的导数为零(derivative = 0),即函数在该点的变化率为零。
对于凸函数,如果我们寻求 min over all W G(W),最小值显然是图中这个点。同样,该点的性质也是导数等于零(derivative = 0)。
需要注意的是,对于凹函数和凸函数,导数等于零的点只有一个。相比之下,在前面展示的既非凹也非凸的函数例子中,情况则不同。
对于第一个例子,存在多个位置的导数等于零。我们可以明确地写为:存在 多个解 满足 导数等于零。
对于第二个例子,实际上没有导数等于零的解,函数的变化率处处不为零,即 无解 满足 导数等于零。
核心要点
这里的关键启示是:我们讨论凸函数和凹函数的原因在于,当我们有一个寻找最小值(凸函数)或最大值(凹函数)的目标时,该问题的解将是唯一的,并且我们知道解一定存在。


本节课中,我们一起学习了凸函数与凹函数的定义及其几何直观,并理解了它们在优化问题中的重要性——能保证极值点存在且唯一。下一节,我们将把这些概念应用到具体的回归问题中,学习如何解析地求解最小二乘法的参数。
机器学习:第2课:最大化一维函数:工作示例

在本节课中,我们将通过一个具体的例子,学习如何找到一维函数的最大值。我们将回顾求导的基本步骤,并演示如何通过设置导数为零来求解极值点。
函数定义与求导
首先,我们来看一个具体的函数。函数定义为:
[
g(w) = 5 - (w - 10)^2
]
我们的目标是找到这个函数的最大值。第一步是计算该函数关于变量 ( w ) 的导数。
根据微积分法则,常数项的导数为零。对于形如 ( (f(w))^n ) 的项,其导数为 ( n \cdot (f(w))^{n-1} \cdot f'(w) )。应用此法则:
- 常数项 ( 5 ) 的导数为 ( 0 )。
- 对 ( -(w - 10)^2 ) 求导:
- 首先,将指数 ( 2 ) 作为乘数:( -2 \cdot (w - 10)^{2-1} = -2 \cdot (w - 10)^1 )。
- 然后,乘以内部函数 ( (w - 10) ) 的导数,即 ( 1 )。
- 因此,该项的导数为 ( -2 \cdot (w - 10) \cdot 1 = -2(w - 10) )。
将两部分合并,我们得到函数 ( g(w) ) 的导数:
[
g'(w) = 0 - 2(w - 10) = -2w + 20
]
寻找最大值点
上一节我们计算了函数的导数。本节中,我们来看看如何利用导数找到最大值点。对于可导函数,其极值点(最大值或最小值)通常出现在导数为零的位置。
因此,我们令导数等于零,并求解 ( w ):
[
g'(w) = -2w + 20 = 0
]
解这个方程:
[
-2w + 20 = 0
]
[
2w = 20
]
[
w = 10
]
我们求得 ( w = 10 )。为了确认这是最大值点而非最小值点,我们可以观察函数图像或计算二阶导数。对于这个函数,其图像是一个开口向下的抛物线(凹函数),因此导数为零的点确实是最大值点。
将 ( w = 10 ) 代回原函数,可以求得最大值:
[
g(10) = 5 - (10 - 10)^2 = 5 - 0 = 5
]
所以,函数在 ( w = 10 ) 处取得最大值 ( 5 )。
总结


本节课中,我们一起学习了如何通过求导来寻找一维函数的最大值。我们定义了一个具体的函数 ( g(w) = 5 - (w - 10)^2 ),计算了它的导数 ( g'(w) = -2w + 20 ),并通过令导数为零解出了极值点 ( w = 10 )。最后,我们验证了该点确实是函数的最大值点,其函数值为 ( 5 )。这个过程是优化问题中寻找极值的基础方法。
机器学习(回归):第2课:通过爬山法找最大值 🏔️

在本节课中,我们将学习一种名为“爬山法”的迭代算法,用于寻找函数的最大值或最小值。我们将从直观的几何图像入手,逐步理解其数学原理和实现步骤。
上一节我们介绍了通过求导并令其为零来寻找函数极值点的方法。本节中我们来看看另一种实用的迭代方法——爬山法。
算法概述
爬山法是一种迭代优化算法。其核心思想是:从一个初始点出发,根据函数在当前点的导数(梯度)信息,不断调整参数,以期逐步接近函数的最优值(最大值或最小值)。
算法原理与步骤
首先,我们考虑一个凹函数,目标是找到使函数值最大的参数 W。算法的关键在于决定每一步移动的方向:是增加 W 还是减少 W。
以下是判断移动方向的数学依据:
- 在最优值点
W*的左侧,导数dG/dW > 0。此时应增加W的值以接近最优点。 - 在最优值点
W*的右侧,导数dG/dW < 0。此时应减少W的值以接近最优点。 - 在最优值点
W*处,导数dG/dW = 0。此时已达到最优,无需移动。
基于此原理,我们可以将爬山法描述为一个迭代更新过程。
以下是爬山法算法的核心更新公式:
while not converged:
W_{t+1} = W_t + η * (dG/dW)|_{W=W_t}
其中:
W_t是第t次迭代时的参数值。η(读作“艾塔”)是一个正数,称为步长。它控制着每次更新幅度的大小。(dG/dW)|_{W=W_t}是函数G在W_t处的导数值。
算法运行过程示例
让我们通过一个图像来直观理解算法的运行过程。
- 初始化:算法从最优点左侧的某个
W值开始。 - 迭代更新:
- 计算当前点的导数(此时导数为正且较大)。
- 根据公式
W_new = W_old + η * 导数更新W。由于导数为正,W会增加。由于初始导数较大,这一步的移动幅度也较大。 - 移动到新点后,再次计算导数。
- 接近最优点:随着迭代进行,
W不断增大并接近最优点。此处的导数绝对值逐渐变小,因此即使步长η固定,每次更新的幅度也会越来越小。 - 越过与调整:如果某次更新越过了最优点,到达其右侧,则该点的导数变为负值。接下来的更新公式
W_new = W_old + η * (负数)会使W减小,从而被“拉回”向最优点。 - 收敛:最终,算法会在最优点附近振荡并收敛。因为越接近最优点,导数越接近于零,参数
W的变化也就微乎其微。
总结


本节课中,我们一起学习了用于寻找函数极值的爬山法。我们了解到,该算法通过迭代方式,根据函数在当前点的导数符号来决定参数的更新方向,并利用步长 η 来控制更新的幅度。这是一个直观且基础的重要优化方法,为后续理解更复杂的机器学习优化算法奠定了基础。
机器学习:第2课:通过下山法找最小值

在本节课中,我们将学习如何使用一种名为“下山法”的算法来寻找函数的最小值。我们将通过直观的几何图像和简单的数学公式来理解其工作原理,并重点关注凸函数这一重要概念。
概述
上一节我们讨论了寻找函数最大值的方法。本节中我们来看看如何寻找函数的最小值。我们将使用一种与“爬山法”非常相似的算法,但方向相反,因此称之为“下山法”。我们的目标是找到函数 G(W) 的最小值,即 min over W G(W)。
对于一个凸函数,其最小值点位于函数图像的最低点,如下图所示。

如何决定移动方向
假设我们从某个 W 值开始,我们需要判断是应该向左(减小 W)还是向右(增大 W)移动才能接近最小值点。关键在于观察函数在该点的导数。
以下是判断移动方向的逻辑:
- 当导数为负时:函数在该点处于下降趋势。为了找到更低的值,我们应增大
W的值,即向右移动。 - 当导数为正时:函数在该点处于上升趋势。为了找到更低的值,我们应减小
W的值,即向左移动。
在上图中,最小值点左侧的导数均为负,右侧的导数均为正。因此,我们的移动策略与导数符号相反。
下山法更新公式
基于上述观察,我们可以构建下山法的参数更新规则。它与爬山法非常相似,但符号相反。
更新公式:
W_new = W_old - η * (dG/dW)
其中:
W_old是当前参数值。W_new是更新后的参数值。η(读作“艾塔”)是学习率,一个正数,控制每次更新的步长。dG/dW是函数G在W_old处的导数。
让我们分析这个公式如何实现我们的移动策略:
- 当导数
dG/dW为正时,减去一个正数,W减小。 - 当导数
dG/dW为负时,减去一个负数(即加上一个正数),W增大。
这完美符合我们上一节制定的方向规则。
凸函数的重要性


理解凸函数的图像至关重要。在本课程及整个模块中,我们将频繁遇到凸函数。对于凸函数,其局部最小值就是全局最小值,这使得下山法能够可靠地找到最优解。请务必将本节展示的凸函数图像牢记于心。
总结


本节课中我们一起学习了“下山法”。我们了解到,为了寻找函数的最小值,我们需要沿着与导数符号相反的方向更新参数,其核心更新公式为 W_new = W_old - η * (dG/dW)。同时,我们强调了凸函数在优化问题中的重要性,因为它保证了算法能找到全局最优解,而非陷入局部最优。
机器学习:第2课:选择步长与收敛准则

在本节课中,我们将学习梯度下降算法中的两个关键实践要素:如何选择步长(学习率)以及如何判断算法何时收敛。理解并正确设置这两个参数,对于确保算法高效、稳定地找到最优解至关重要。
步长的选择
上一节我们介绍了梯度下降的基本思想,即沿着负梯度方向更新参数。本节中我们来看看如何选择更新时的步长,即学习率 η。
步长决定了每次迭代中参数 W 的变化幅度。选择不当可能导致收敛缓慢甚至无法收敛。
以下是几种常见的步长选择策略:
固定步长
顾名思义,将步长 η 设置为一个常数,例如 η = 0.1。这种方法简单,但在某些情况下,如果步长设置过大,算法可能会在最优解附近反复震荡,需要较长时间才能收敛。不过,对于本模块中将要处理的大部分“强凸”函数(一种性质良好、形状明确的凸函数),固定步长策略通常是有效的。
递减步长
另一种常见的选择是随着迭代次数增加而减小步长。这被称为步长调度。其思想是:在开始时,我们可能离最优解较远,因此需要较大的步长快速接近;随着迭代进行,我们希望更精细地调整参数以精确收敛到最优解,因此需要减小步长。
以下是两种常用的递减步长公式:
- 公式1:
η_t = α / t - 公式2:
η_t = α / √t
其中,t 是当前迭代次数,α 是一个需要设定的常数。这两种策略都使得步长随着迭代次数 t 的增加而减小。需要注意的是,步长衰减速度不宜过快,否则算法后期步长过小,同样会导致收敛速度变慢。
总而言之,选择步长是一门艺术,需要根据具体问题进行调整。上述策略为实践中常用的方法提供了起点。
收敛准则
算法中另一个需要明确的部分是“何时停止迭代”,即收敛准则。我们知道,函数在最优解处的梯度(导数)为零。但在实际计算中,梯度值会越来越小,无限接近但很难精确等于零。
因此,我们需要设定一个阈值来判断何时“足够接近”最优解。常见的做法是检查梯度的绝对值是否小于一个预设的极小正数 ε。
收敛判断公式:
|∇f(W_t)| < ε
如果上述条件满足,我们就终止算法,并返回当前的参数解 W_t。在实践中,ε 需要根据具体问题设定为一个非常小的值。所谓“非常小”的含义,取决于数据的尺度、函数的形式以及梯度的可能取值范围。
此外,观察目标函数值 f(W) 随迭代次数的变化曲线也是一种直观的辅助判断方法。当函数值在连续多次迭代中基本不再下降时,通常意味着算法已经收敛。
总结

本节课我们一起学习了梯度下降算法中两个重要的实践环节。首先,我们探讨了如何选择步长,介绍了固定步长和递减步长两种策略及其适用场景。接着,我们定义了收敛准则,通过判断梯度绝对值是否小于一个阈值 ε 来决定算法何时停止。正确理解和设置这些参数,是成功应用梯度下降法解决实际优化问题的基础。
机器学习:第2课:梯度:多维导数

在本节课中,我们将学习如何将寻找函数最小值或最大值的思想,从单一变量扩展到多个变量。我们将介绍梯度的概念,它是导数在多维空间中的推广。
从单变量到多变量
上一节我们讨论了单变量函数的导数及其在寻找极值点中的应用。然而,在机器学习中,我们经常需要同时优化多个参数。例如,在最小化残差平方和时,我们有两个模型参数 W0 和 W1。本节中,我们来看看如何处理定义在多个变量上的函数。
梯度的定义
当我们处理高维空间的函数时,不再使用“导数”这一术语,而是使用“梯度”。梯度是一个向量。
对于一个函数 G(w),其中 w 是一个包含多个变量的向量,例如 w = [W0, W1, ..., Wp],其梯度记作 ∇G(w)。
梯度的定义很直接:它是一个由函数 G 对每个变量的偏导数组成的向量。
公式表示:
∇G(w) = [ ∂G/∂W0, ∂G/∂W1, ..., ∂G/∂Wp ]
理解偏导数
那么,什么是偏导数呢?以 ∂G/∂W1 为例:
- ∂G/∂W1 类似于对 W1 求导。
- 关键区别在于,在计算这个导数时,我们将所有其他变量(W0, W2, W3, ..., Wp)都视为常数。
- 这就像在一维求导中,把系数当作固定数字(如5、7、10)来处理一样。
核心概念:
偏导数 ∂G/∂W1 是函数 G 在仅改变 W1 而保持其他所有变量不变时的变化率。
因此,梯度 ∇G(w) 是一个 P+1 维的向量(如果我们从 W0 开始索引到 Wp)。
梯度计算示例
让我们通过一个具体例子来巩固理解。定义函数:
G(w) = 5*W0 + 10*W0*W1 + 2*(W1^2)
我们的目标是计算它的梯度 ∇G(w)。这个函数只有两个变量:W0 和 W1。
以下是计算步骤:
首先,计算对 W0 的偏导数 ∂G/∂W0:
- 第一项 5*W0 对 W0 求导,结果是 5。
- 第二项 10W0W1 中,W1 被视为常数,因此对 W0 求导,结果是 10*W1。
- 第三项 2*(W1^2) 不包含 W0,被视为常数,导数为 0。
- 所以,∂G/∂W0 = 5 + 10*W1。
接着,计算对 W1 的偏导数 ∂G/∂W1:
- 第一项 5*W0 不包含 W1,导数为 0。
- 第二项 10W0W1 中,W0 被视为常数,对 W1 求导,结果是 10*W0。
- 第三项 2*(W1^2) 对 W1 求导,根据幂法则,结果是 4*W1。
- 所以,∂G/∂W1 = 10W0 + 4W1。
因此,函数 G 的梯度为:
∇G(w) = [ 5 + 10*W1, 10*W0 + 4*W1 ]
梯度的几何意义
梯度向量有什么作用呢?在函数的图像(例如一个曲面)上,任意一点 (W0, W1) 都对应一个梯度值。
计算方式:只需将该点的 W0 和 W1 的具体数值代入梯度公式 [ 5 + 10*W1, 10*W0 + 4*W1 ],就能得到一个具体的二维向量。
这个梯度向量指向函数在该点处上升最快的方向,而其反方向则指向函数下降最快的方向。这个性质对于后续我们寻找函数最小值(如成本函数)至关重要。

本节课中,我们一起学习了如何将导数的概念扩展到多维空间,引入了梯度作为由偏导数组成的向量。我们通过一个具体例子演示了如何计算梯度,并理解了梯度向量指向函数最陡上升方向的几何意义。在下一课中,我们将利用梯度来寻找多变量函数的最小值。
机器学习:第2课:梯度下降:多维下山法

在本节课中,我们将学习梯度下降算法在多维空间中的应用。我们将从理解等高线图开始,它为我们提供了观察多维函数的直观方式。接着,我们将把一维的“下山法”推广到多维,并学习如何评估算法的收敛性。
等高线图:二维视角
上一节我们介绍了梯度的概念,本节中我们来看看一种可视化优化曲面的不同方法。
我们不再观察之前使用的三维网格图,而是观察等高线图。这可以被视为我们正在研究函数的鸟瞰图。这里,我们将三维网格转换到了二维平面上。
为了清晰说明,图中横轴是 W0,纵轴是 W1。图中的每一条曲线,都代表从左侧三维曲面中切出的一个切片。在这个切片上,所有点的函数值都相同。
具体来说,沿着这个椭圆上的每一个 W0 和 W1 参数对,其函数 G(W0, W1) 的值都相等,因为它是从我们观察的三维等高面上切出的一个平面切片。
因此,图中的每一个环都代表一个函数值。通常,从蓝色(函数值较低)到红色(函数值较高),环所代表的函数值是递增的。我们通过在不同高度切割函数,得到了这些不同的等高线。
这种图被称为等高线图。它的优势在于,当我们在二维平面上工作时,使用二维表示更便于绘图和操作。
梯度下降算法:从一维到多维
了解了等高线图后,我们就可以讨论梯度下降算法了。它是之前一维“下山法”在多维空间的推广。
我们用函数的梯度替代了一维情况下的导数。除此之外,算法的核心思想完全相同。
以下是算法的步骤:
- 我们有一个参数向量 W。
- 我们同时更新所有参数。
- 更新公式为:W_new = W_old - η * ∇G(W_old)。
- 其中,η 是学习率,∇G(W_old) 是梯度向量。
这个公式就是一维下山法公式的向量形式。
算法可视化
为了更直观地理解,让我们在等高线图上描绘这个过程。
假设我们从一个点开始。该点的梯度向量指向函数值最陡峭上升的方向,即“上山”的方向。然而,我们的梯度下降算法是沿着负梯度方向移动。
因此,算法实际移动的步长方向与梯度方向相反。在图中,这些步长会引导我们朝着函数的最小值(最优值)移动。
这与一维情况完全类似,只不过现在我们是在二维(或更高维)空间中移动。
收敛性判断
在一维情况下,我们通过观察导数的绝对值来判断收敛。在多维情况下,我们需要观察梯度的大小(模长)。
当梯度的大小小于我们设定的某个阈值 ε 时,我们就可以认为算法已经收敛。


本节课中我们一起学习了如何通过等高线图可视化多维函数,并将一维梯度下降法推广到多维空间。我们理解了算法如何通过负梯度方向更新参数,并学会了通过判断梯度模长来评估收敛性。这是优化机器学习模型参数的核心方法之一。
机器学习:第2课:计算RSS梯度 📈

在本节课中,我们将学习如何将优化概念应用于寻找最佳拟合直线的具体场景。我们将重点计算残差平方和(RSS)的梯度,这是梯度下降算法的核心步骤。
上一节我们介绍了优化算法的基础概念,本节中我们来看看如何将这些概念应用到我们的线性回归问题中。
凸函数与唯一解
首先需要明确,我们的目标函数是凸函数。这意味着该最小化问题的解是唯一的。我们知道存在一个唯一的最小值,并且梯度下降算法将收敛到这个最小值。
梯度下降算法将收敛到最小值。
这个性质非常有用,因为它意味着我们可以使用之前描述的简单算法来解决这个看似复杂的问题,即从所有可能的直线中找出最佳拟合线。
梯度的定义与性质
现在,让我们回到成本函数的定义,即关于两个参数 W0 和 W1 的残差平方和(RSS)。在计算梯度之前,需要了解一个关于导数的性质:一个关于变量 W 的函数和的导数,等于各个函数导数的和。
用公式表示如下:
d/dW [ Σ_i G_i(W) ] = Σ_i [ d/dW G_i(W) ]
在我们的案例中,每个函数 G_i 定义为:
G_i(W) = (Y_i - (W0 + W1 * X_i))^2
因此,残差平方和确实是 n 个关于 W0 和 W1 的函数之和。
计算关于 W0 的偏导数
根据上述性质,计算 RSS 关于 W0 的偏导数时,可以将求和符号移到外面。我们使用链式法则进行计算。
以下是计算步骤:
- 将求和符号移到导数运算之外。
- 对平方函数求导,得到系数
2。 - 对内部函数
(Y_i - W0 - W1*X_i)关于W0求导,得到-1。 - 合并系数
2和-1,得到-2。
最终公式为:
∂RSS/∂W0 = -2 * Σ_i [ Y_i - (W0 + W1 * X_i) ]
计算关于 W1 的偏导数
接下来,我们计算 RSS 关于 W1 的偏导数。过程与计算 W0 的偏导数类似,但内部函数关于 W1 的导数不同。
以下是计算步骤:
- 同样,先将求和符号移到外面。
- 对平方函数求导,得到系数
2。 - 对内部函数
(Y_i - W0 - W1*X_i)关于W1求导。此时,-W1*X_i项的导数为-X_i。 - 合并系数
2和-X_i,得到-2 * X_i。
最终公式为:
∂RSS/∂W1 = -2 * Σ_i [ (Y_i - (W0 + W1 * X_i)) * X_i ]
梯度向量
将两个偏导数的结果组合起来,就得到了残差平方和(RSS)的梯度向量。梯度是一个二维向量,因为我们的模型有两个参数 W0 和 W1。
梯度向量的公式如下:
∇RSS(W0, W1) = [ -2 * Σ_i (Y_i - (W0 + W1*X_i)),
-2 * Σ_i (Y_i - (W0 + W1*X_i)) * X_i ]
求解最小值的方法
现在我们已经得到了梯度。我们知道,求解函数最小值的一种方法是将其导数(在一维情况下)或梯度(在多维情况下)设为零并求解。
因此,为了找到使 RSS 最小的 W0 和 W1,我们可以将梯度向量设为零向量:
∇RSS(W0, W1) = [0, 0]
这将产生一个包含两个方程的方程组,通过求解这个方程组,可以直接得到最优参数值,这是解析解方法。另一种方法则是使用我们之前讨论的梯度下降算法进行迭代求解。


本节课中我们一起学习了如何计算线性回归中残差平方和(RSS)的梯度。我们首先回顾了凸函数确保解唯一的特性,然后利用导数求和的法则,逐步推导出了关于截距 W0 和斜率 W1 的偏导数公式,最终得到了完整的梯度向量。这个梯度是后续使用梯度下降算法或直接求解正规方程来找到最佳拟合直线的基础。
机器学习:第2课:方法1:闭式解 📐

在本节课中,我们将学习求解线性回归模型参数的第一种方法:闭式解。我们将通过将损失函数的梯度设为零,直接推导出模型参数 w0 和 w1 的解析解。
概述
我们的目标是找到一条最佳拟合线,以最小化残差平方和。这可以通过求解一个优化问题来实现。本节将展示如何通过数学推导,直接计算出最优参数 w0 和 w1 的闭式解公式。
梯度与最优解
上一节我们介绍了残差平方和作为损失函数。本节中我们来看看如何通过求导并令其为零来找到最小值点。
在三维网格图中,梯度为零的点(图中绿色曲面与零平面相交处)对应着损失函数的最小值。红色圆点即为我们寻找的最优参数点 (w0, w1)。
我们的方法是:对损失函数关于 w0 和 w1 分别求偏导,得到梯度向量,然后令该梯度向量等于零向量。
梯度向量公式如下:
∇RSS(w0, w1) = [ ∂RSS/∂w0, ∂RSS/∂w1 ]^T
= [ -2 * Σ(y_i - w0 - w1*x_i), -2 * Σ((y_i - w0 - w1*x_i) * x_i) ]^T
接下来,我们令这个梯度等于零,并求解 w0 和 w1。
求解参数 w0 和 w1
以下是求解步骤。我们将梯度向量的两个分量分别设为零,并解方程组。
首先,令第一个分量(关于 w0 的偏导)等于零:
-2 * Σ(y_i - w0 - w1*x_i) = 0
经过代数运算,我们可以得到 w0 的估计值 ŵ0 的表达式:
ŵ0 = (Σy_i / n) - ŵ1 * (Σx_i / n)
这里,ŵ0 和 ŵ1 上的“帽子”符号表示它们是参数的估计值。
这个结果具有直观意义:我们的截距估计 ŵ0 等于输出 y(房价)的平均值,减去斜率估计 ŵ1 与输入 x(面积)平均值的乘积。然而,这个表达式仍然依赖于未知的 ŵ1,因此我们需要第二个方程。
接着,我们令第二个分量(关于 w1 的偏导)等于零:
-2 * Σ((y_i - w0 - w1*x_i) * x_i) = 0
将上面得到的 ŵ0 表达式代入这个方程,然后求解 ŵ1。经过推导,我们得到 ŵ1 的闭式解:
核心公式:
ŵ1 = [ Σ(y_i * x_i) - (Σy_i * Σx_i)/n ] / [ Σ(x_i^2) - (Σx_i)^2/n ]
得到 ŵ1 后,再将其代入 ŵ0 的表达式,即可计算出 ŵ0。
计算要点
为了计算 ŵ1 和 ŵ0,我们只需要从训练数据中计算几个简单的统计量:
以下是需要计算的四个关键项:
Σy_i:所有输出值(房价)的总和。Σx_i:所有输入值(面积)的总和。Σ(y_i * x_i):每个样本的输出与输入乘积的总和。Σ(x_i^2):所有输入值平方的总和。
将这些值代入上述公式,就能直接得到最优的参数估计。
总结
本节课中我们一起学习了求解线性回归参数的闭式解法。该方法的核心是:
- 构建残差平方和损失函数。
- 对参数
w0和w1求偏导,得到梯度。 - 令梯度等于零,形成一个方程组。
- 解该方程组,推导出
ŵ0和ŵ1的解析表达式。


这种方法的优点是直接、精确,只需一次计算即可得到全局最优解。我们了解到,最终解可以通过几个基础的数据汇总量(总和、平方和、乘积和)方便地计算出来。
机器学习:第2课:方法2:梯度下降 📉

在本节课中,我们将学习线性回归的第二种核心优化方法:梯度下降。我们将了解其工作原理、更新公式背后的直观含义,以及如何通过迭代过程找到最小化残差平方和的最佳参数。
上一节我们讨论了通过求解梯度为零的方程来找到最佳拟合线。本节中我们来看看另一种迭代方法:梯度下降。其核心思想是沿着残差平方和构成的曲面“下坡”,逐步逼近最小值点。虽然过程中可能会因步长问题而出现反复,但总体方向是明确的。
为了应用梯度下降,我们需要重新审视之前计算过的残差平方和梯度公式。回顾一下,残差平方和关于参数 w0 和 w1 的梯度为:
梯度公式:
∇RSS(w) = [ ∂RSS/∂w0, ∂RSS/∂w1 ]^T
= [ -2 * Σ(y_i - ŷ_i), -2 * Σ((y_i - ŷ_i) * x_i) ]^T
其中,ŷ_i = w0 + w1 * x_i 是使用当前参数 w0 和 w1 对第 i 个观测值的预测值。
我们可以利用这个梯度来设计迭代算法。梯度下降算法的基本框架如下:
以下是梯度下降算法的步骤:
- 初始化:为参数 w0 和 w1 选择初始值(例如,设为0)。
- 迭代更新:在未达到收敛条件时,重复以下步骤:
- 计算当前参数下,所有数据点的预测值 ŷ_i 和残差 (y_i - ŷ_i)。
- 按照以下公式更新参数:
这里,η 是学习率,控制每次更新的步长。w0_new = w0_old + η * 2 * Σ(y_i - ŷ_i) w1_new = w1_old + η * 2 * Σ((y_i - ŷ_i) * x_i)
- 输出结果:当参数变化非常小或达到最大迭代次数时,算法收敛。我们输出最终的 ŵ0 和 ŵ1 作为拟合的回归线参数。
注意,原梯度公式中的负号(-2)与减去梯度(-η * 梯度)中的负号相结合,使得更新公式中出现了加号(+)。这并不改变梯度下降的本质,我们依然是在向梯度反方向(即函数下降最快的方向)移动。
这个公式具有很好的直观解释。考虑截距项 w0 的更新:Σ(y_i - ŷ_i)。如果模型整体上低估了真实值 y(即预测值普遍偏小),那么残差和将为正数。根据更新公式,一个正数会被加到 w0 上,从而使其增大。这完全合理,因为如果回归线整体偏低,我们确实需要将其向上平移,即增加截距 w0。
对于斜率项 w1 有类似的直观解释,但需要乘以对应的 x_i。这考虑了每个数据点对斜率调整的贡献权重。

本节课中我们一起学习了梯度下降法。这是一种通过迭代调整参数来最小化目标函数(如残差平方和)的通用优化算法。我们推导了其在线性回归中的应用公式,并解释了更新步骤背后的直观意义。与直接求解正规方程相比,梯度下降法更适合大规模数据集或更复杂的模型。最终,我们通过算法输出拟合的回归线参数 ŵ0 和 ŵ1。
机器学习:第2课:比较两种优化方法

在本节课中,我们将比较两种用于最小化残差平方和(RSS)的优化方法:解析解法(令梯度等于零)与梯度下降法。我们将分析各自的优缺点,并讨论在不同场景下的适用性。
两种方法的回顾
上一节我们介绍了如何通过最小化残差平方和来拟合线性回归模型。本节中,我们来看看两种实现这一目标的具体方法。
第一种方法是解析解法,即直接对目标函数求导,并令导数等于零,从而解出参数的闭式解。对于线性回归的RSS目标,其梯度公式为:
∇RSS(w) = -2Xᵀ(y - Xw)
令其等于零,可得到最优参数的解析解:
w = (XᵀX)⁻¹Xᵀy*
第二种方法是梯度下降法,这是一种迭代优化算法。它通过反复沿负梯度方向更新参数来逼近最小值。其参数更新规则为:
w_new = w_old - η * ∇RSS(w_old)
其中,η 代表学习率(步长)。
两种方法的比较
以下是两种方法关键特性的对比分析:
1. 解的精确性与形式
- 解析解法:直接提供精确的闭式解。
- 梯度下降法:通过迭代提供近似解,精度取决于收敛准则。
2. 计算复杂度与适用性
- 解析解法:涉及矩阵求逆 (XᵀX)⁻¹。当特征维度很高或矩阵接近奇异时,计算可能非常昂贵或不稳定。
- 梯度下降法:每次迭代计算量较小,尤其适用于特征维度极高或数据量巨大的场景,因为可以避免直接计算矩阵逆。
3. 算法参数需求
- 解析解法:无需设置算法参数。
- 梯度下降法:需要手动选择学习率(步长)和收敛判断准则,这些选择会影响算法的效率与最终结果。
4. 通用性
- 解析解法:仅适用于存在闭式解的目标函数(如线性回归的RSS)。对于更复杂的机器学习模型(如逻辑回归、神经网络),通常不存在闭式解。
- 梯度下降法:是一种通用优化框架,只要目标函数可微,即可应用。它是训练大多数复杂机器学习模型的核心方法。
总结
本节课中我们一起学习了两种优化方法的核心区别。
- 当问题存在简单闭式解且计算可行时(如基础线性回归),解析解法是直接高效的选择。
- 然而,在大多数现代机器学习场景中,面对高维数据、大数据集或复杂模型(其目标函数无闭式解),梯度下降法及其变种因其灵活性和可扩展性而成为不可或缺的工具。其代价是需要谨慎调整学习率等参数。

理解这两种方法的原理与权衡,将帮助你在不同情况下选择合适的优化策略。
机器学习:第2课:高杠杆点的影响:探索数据 🎯

在本节课中,我们将要学习一个重要的概念——高杠杆点的影响。这些点可以被视为有影响力的观测值。为了深入理解这个概念,直接观察一些数据会非常有帮助。
数据加载与初步观察
首先,让我们启动GraphLab并加载一些数据。我们将数据加载到一个SFrame中。我假设大家通过基础课程的学习,已经对这里使用的GraphLab相关代码比较熟悉。需要强调的是,在本课程中,你将学习如何实现这些方法,但为了本次演示以及本课程中的其他演示,我们将使用GraphLab来保持讨论在更高的概念层面。
我们在这个例子中使用的数据集是费城住房数据。具体来说,该数据集包含了费城大都会区一系列城镇的平均房价信息,以及每个城镇的犯罪率数据,还有该城镇距离市中心(Center City,即费城中心城区)的距离。
让我们开始分析这些数据。首先,我们将创建一个散点图,来观察平均房屋售价与犯罪率之间的关系。
以下是创建散点图的步骤:
- 在X轴上,我们绘制犯罪率。每个浅蓝色的圆点代表数据集中的一个不同城镇,我们总共有98个不同的城镇。
- 在Y轴上,我们绘制该城镇的平均房屋价值。
从图中可以看出,犯罪率与房屋售价之间存在一定的关系。具体来说,犯罪率较低的城镇往往拥有较高的房屋价值,反之亦然。这很符合我们的直觉。
拟合回归模型
接下来,让我们尝试拟合犯罪率与房价之间的关系。我们将使用标准的线性回归命令来拟合这个模型。
我们将目标变量(输出)设置为该区域的房价,特征则仅使用该城镇的犯罪率这一项。
现在,我们已经将拟合结果输出到一个名为crime_model的对象中。让我们看看这个拟合的结果是什么。
我们将导入matplotlib库来绘制一些图形。我们将展示之前观察到的数据点,以及我们拟合的直线。
这条绿色的线就是我们拟合的简单线性回归模型。它代表了从犯罪率为0到大约360的范围内,每个犯罪率对应的房价预测值。
我们确实看到了一个趋势:随着犯罪率上升,房屋价值下降。这条线的斜率是负的。但是,我们立刻就能注意到一个现象:这里有一个观测点(那个蓝色的点),它的犯罪率极高,但其房屋价值虽然较低,却不像其他犯罪率显著更低的区域的房屋价值那么低。
我们可以看到,我们拟合的直线被这个位于X轴最远端的观测点“拉”了过去。至少从图片上看,这条直线似乎受到了这个单一观测点的严重影响。
总结

本节课中,我们一起学习了高杠杆点的概念及其对线性回归模型的影响。通过分析费城住房数据,我们观察到,一个在X轴上远离其他数据点的观测值(高犯罪率城镇)会显著地影响回归线的斜率,使其向该点倾斜。这直观地展示了高杠杆点如何对模型拟合产生不成比例的巨大影响。
机器学习:第2课:高杠杆点与影响点分析

在本节课中,我们将学习线性回归中两个重要的概念:高杠杆点和影响点。我们将通过一个具体的房价与犯罪率关系的案例,演示如何识别这些点,并理解它们对回归模型拟合结果的巨大影响。
移除市中心数据点
上一节我们介绍了如何拟合一个简单的线性回归模型。本节中,我们来看看当数据集中存在极端值时会发生什么。
在初始的数据散点图中,我们注意到一个代表“市中心”的观测点。该点的犯罪率远高于其他城镇,同时其房屋价值也呈现出与犯罪率趋势不符的较高水平。这个点可能对回归线产生不适当的影响。
为了探究其影响,我们将执行以下操作:从数据集中移除这个代表市中心的观测点,然后重新拟合回归模型,并比较系数变化。
以下是具体步骤:
- 识别并移除犯罪率为0(即市中心本身)的数据行。
- 在移除该点后的新数据集上重新绘制散点图。
- 使用相同模型(
house_value ~ crime_rate)进行拟合。
比较模型系数
完成新模型的拟合后,我们需要量化移除一个数据点所带来的影响。最直接的方法是比较两个模型的系数。
我们得到了两组回归系数:
- 包含市中心时的模型:斜率为
-576。这意味着,根据该模型,犯罪率每增加一个单位,房屋价值平均下降576美元。 - 移除市中心后的模型:斜率为
-2287。这意味着,根据新模型,犯罪率每增加一个单位,房屋价值平均下降2287美元。
仅仅移除了一个数据点,我们对“犯罪率如何影响房价”的解释就发生了根本性的改变。这引出了我们对高杠杆点和影响点的讨论。
理解高杠杆点与影响点
从上面的对比可以看出,单个数据点有时能极大地改变模型。下面我们来定义并区分两个关键概念。
高杠杆点是指在其输入变量(X轴)上为异常值的点。它的X值(本例中为犯罪率)远大于或远小于数据集中其他观测值。在数学上,简单线性回归的闭式解中包含与X值的质心(即平均值)相关的项。一个极端的X值会显著改变这个质心的位置,从而影响整个回归线的拟合。
影响点是指那些如果从数据集中移除,会导致模型拟合结果发生显著变化的观测点。一个点要成为强影响点,通常需要同时满足两个条件:1)它是高杠杆点(X值异常);2)它的Y值(响应变量)不遵循数据主体所显示的趋势。
需要强调的是:
- 高杠杆点不一定是强影响点。如果它的Y值恰好落在由其他数据点决定的趋势线上,移除它可能不会显著改变拟合结果。
- 非高杠杆点(即X值在典型范围内的点)也可能成为影响点,例如一个Y值极高的异常点。但是,当X值范围内数据点密集时,其他点会共同制约回归线,因此单个点的影响力相对较小。

本节课中我们一起学习了高杠杆点和影响点的概念。我们通过一个实例看到,一个在X轴上异常的观测点(高杠杆点),如果其Y值也偏离趋势,就可能成为强影响点,极大地改变回归模型的系数和我们对变量关系的理解。在分析数据时,识别并理解这些特殊点至关重要。
机器学习:第2课:高杠杆点与影响点分析

在本节课中,我们将学习如何识别和处理线性回归中的高杠杆点与影响点。我们将通过一个实际案例,探讨移除不同类型的数据点对回归模型系数估计的影响,并理解进行数据分析和可视化检查的重要性。
高杠杆点与影响点的回顾
上一节我们介绍了高杠杆点和影响点的概念。高杠杆点是指在自变量(X)空间上远离其他数据点的观测值,它们对回归线的拟合位置有潜在的巨大影响。影响点则是指那些如果被移除,会显著改变模型拟合结果的观测值。
分析高价值城镇的影响
现在,让我们回到数据集中,通过观察具体的观测值来探讨这个问题。下图展示了数据的一部分:

在图的顶部,我们可以看到五个不同的观测值聚集在一起。这代表五个不同的城镇,它们的房屋平均价值远高于数据集中所有其他城镇。
一个关键问题是:尽管这些点因其X值(如犯罪率)处于典型范围内而不是高杠杆点,但它们是否属于影响点?换句话说,如果我们移除这些观测值,模型的拟合结果会发生很大变化吗?接下来,让我们在数据中验证这一点。
移除高价值城镇的实验
我们将执行以下操作:移除这些高价值的异常城镇,并重新进行分析。
以下是具体的操作步骤,我们通过代码创建一个新的数据集:
# 创建新数据集,过滤掉平均价值高于35万美元的城镇
sales_no_high_end = sales_data[sales_data['avg_value'] <= 350000]
我们首先移除了中心城市(Center City),现在进一步过滤掉所有平均价值大于35万美元的城镇。接着,我们用这个新数据集拟合模型。
比较模型系数
现在,我们来比较两个模型的系数。第一个模型是仅移除了中心城市的拟合结果,第二个模型是进一步移除了这些高端城镇后的拟合结果。
比较发现,移除这五个高端城镇确实对估计的系数产生了一些影响,但这种影响远不如之前仅仅移除中心城市那一个观测值时那么显著。
关键发现:
- 我们总共移除了 5 个观测值(数据总量为97个)。
- 犯罪率对房价预测值的影响系数变化了几百美元。
- 这个变化幅度远小于之前仅移除中心城市那1个观测值所带来的巨大变化。
这个实验表明,高杠杆点(如中心城市)即使与数据主体仅有微小偏差,也远比那些处于典型X值范围内的高价值异常点更有可能成为影响点。
核心结论与最佳实践
综上所述,当您拥有数据并进行模型拟合、预测或解释系数时,进行彻底的数据分析至关重要。
以下是进行有效分析的建议步骤:
- 数据可视化:绘制散点图、残差图等,直观检查数据分布和异常点。
- 检查高杠杆点:利用杠杆值统计量(如帽子矩阵的对角线元素)识别在自变量空间上特殊的点。
- 检查影响点:使用库克距离(Cook‘s Distance)等指标量化每个观测值对模型拟合的影响程度。
- 敏感性分析:通过有选择地移除疑似点并重新拟合模型,观察关键系数或预测值的变化幅度。
进行这些检查的原因是,高杠杆点和影响点可能会戏剧性地改变您基于估计模型所做出的解释或预测。忽略它们可能导致模型不稳定、结论不可靠。
课程总结
在本节课中,我们一起学习了:
- 区分了高杠杆点(X空间异常)和影响点(显著改变模型拟合的点)。
- 通过案例实验发现,一个高杠杆点(中心城市)对模型系数的影响,远大于多个处于典型X范围内的高价值异常点。
- 掌握了在回归分析中,通过可视化和统计诊断来识别和处理这些特殊数据点的重要性。




机器学习:第2课:非对称成本函数

在本节课中,我们将要学习成本函数的概念,特别是探讨当预测错误的成本不对称时,会发生什么情况。我们将了解对称成本函数(如残差平方和)的局限性,并引入非对称成本函数的基本思想。
对称成本函数回顾
上一节我们介绍了残差平方和(RSS)作为衡量模型预测误差的标准方法。其公式为:
RSS = Σ(y_i - ŷ_i)²
其中,y_i是真实值,ŷ_i是预测值。
这个函数被称为对称成本函数,因为它假设高估和低估预测值所带来的“成本”或“惩罚”是相同的。例如,在房价预测中,模型认为预测价格比真实价格高10万美元,与预测价格比真实价格低10万美元,所犯的错误程度是一样的。
非对称成本的现实场景
然而,在现实世界的许多决策中,不同类型的错误可能带来截然不同的后果。对称假设并不总是成立。
以下是房价预测中的一个例子,说明成本可能不对称:
- 高估房价的成本:如果将挂牌价定得过高,可能导致无人看房,或看房后无人出价。最终结果可能是房子完全卖不出去,这对于急需卖房的卖家来说是巨大的损失。
- 低估房价的成本:如果将挂牌价定得过低,虽然可能会迅速收到出价,但无法获得房屋应有的最高价值,卖家会损失一部分潜在收益。
在这个场景中,“卖不出去”的成本可能远高于“卖得便宜一些”的成本。因此,高估的错误比低估的错误代价更高。
非对称成本函数的影响
如果我们考虑到这种不对称的成本,并设计一个相应的非对称成本函数,那么模型拟合出的最优结果将会改变。
与最小化对称的RSS得到的拟合线(下图中的虚线)不同,使用一个倾向于惩罚高估错误的非对称成本函数进行优化,会得到一条新的拟合线(下图中的实线)。

如图所示,新的拟合线(实线)整体位于RSS拟合线(虚线)的下方。这意味着模型学会了系统性地给出更保守(更低)的预测,以避免因高估而付出更大代价。
总结

本节课中我们一起学习了成本函数的核心概念。我们回顾了对称成本函数(如残差平方和)的原理与局限。更重要的是,我们通过房价预测的例子,理解了在实际应用中预测错误成本往往不对称。当高估和低估的后果不同时,我们需要使用非对称成本函数来训练模型,这将引导模型学习到不同的、更符合实际业务需求的预测策略。在本课程的后续部分,我们将深入探讨更多不同类型的误差衡量方法。
机器学习:第2课:简单线性回归回顾 🧠
在本节课中,我们将回顾简单线性回归的核心概念。我们将探讨模型定义、衡量拟合优度的方法、如何解释模型并进行预测,以及如何通过优化技术(特别是梯度下降)来拟合数据。尽管简单线性回归是一个基础工具,但其应用非常广泛且强大。

模型定义 📈
上一节我们介绍了机器学习的基本概念,本节中我们来看看简单线性回归的具体模型。
简单线性回归模型描述的是单个输入变量 X 与单个输出变量 Y 之间的关系。该模型通过拟合一条直线来刻画这种关系。
模型公式为:
Y = w₀ + w₁X
其中:
- Y 是预测的输出。
- X 是输入特征。
- w₀ 是截距。
- w₁ 是斜率。

这条直线就是我们的预测模型。
拟合优度与残差平方和 📊
在定义了模型之后,我们需要一个标准来衡量某条特定直线对数据的拟合程度。这个衡量标准就是残差平方和。
残差是指数据点的真实值 Y 与模型预测值 Ŷ 之间的差值。残差平方和则是所有数据点残差的平方之和。
其计算公式为:
RSS = Σ (Yᵢ - Ŷᵢ)²
RSS 的值越小,表明模型的预测直线与数据点的整体偏差越小,即拟合效果越好。
模型解释与预测 🔮
得到拟合直线后,我们可以用它进行两件事:解释关系和做出预测。
- 解释关系:斜率 w₁ 表示当输入 X 增加一个单位时,输出 Y 的平均变化量。截距 w₀ 表示当 X 为 0 时的 Y 的预测值。
- 形成预测:对于任何一个新的 X 值,我们可以将其代入公式 Ŷ = w₀ + w₁X 来计算对应的预测输出 Ŷ。
模型拟合:梯度下降法 ⚙️
前面的小节讨论了如何评估一条线的拟合效果,但最关键的问题是:我们如何找到那条最优的拟合直线?这就需要用到优化技术,核心方法是梯度下降法。
我们的目标是找到能使残差平方和最小化的参数 w₀ 和 w₁。梯度下降法通过迭代更新参数来实现这一目标。
以下是该算法的基本步骤:
- 初始化参数 w₀ 和 w₁(例如,设置为0)。
- 计算当前参数下的损失函数(即RSS)的梯度。
- 沿梯度下降的方向,以学习率 η 为步长,更新参数:
wⱼ := wⱼ - η * (∂RSS/∂wⱼ) - 重复步骤2和3,直到参数收敛或达到预设的迭代次数。
通过最小化残差平方和,我们最终能得到用于预测的拟合直线。

总结 🎯
本节课中我们一起学习了简单线性回归的核心内容。我们首先定义了使用直线进行预测的模型 Y = w₀ + w₁X。接着,我们引入了残差平方和作为衡量模型拟合优度的关键指标。然后,我们探讨了如何解释模型参数并进行预测。最后,我们重点介绍了使用梯度下降这一优化算法来寻找最佳拟合参数的过程。尽管简单线性回归结构简单,但它是一个极其强大且基础的工具,在后续的实践中我们将看到它的广泛应用。
机器学习:第2课:多元回归简介
在本节课中,我们将要学习多元回归。这是一种当你拥有多个特征时的线性回归方法,其中每个特征可以是单个或多个输入的函数。多元回归的概念在实践中至关重要,它可能是目前应用最广泛的统计与机器学习工具之一。

上一节我们介绍了单变量线性回归的基本概念。本节中,我们来看看当数据包含多个特征时,模型应如何扩展。
从单变量到多元回归
在单变量线性回归中,我们使用一个输入特征 x 来预测目标 y,模型形式为:
y = w0 + w1 * x
然而,现实世界中的问题通常更为复杂,一个结果往往受到多个因素的影响。例如,预测房价时,不仅需要考虑房屋面积,还需要考虑卧室数量、房龄、地理位置等。为了处理这种情况,我们需要引入多元回归。
多元回归模型
多元回归模型是单变量模型的自然延伸。它假设目标变量 y 与 d 个输入特征 x1, x2, ..., xd 之间存在线性关系。其模型公式如下:
y = w0 + w1*x1 + w2*x2 + ... + wd*xd
其中:
y是我们要预测的目标变量。x1, x2, ..., xd是d个输入特征。w0是截距或偏置项。w1, w2, ..., wd是每个特征对应的权重或系数,表示该特征对预测结果的影响程度。
为了更简洁地表示,我们通常使用向量形式。将所有特征(包括一个值为1的虚拟特征以代表截距 w0)组合成一个特征向量 x,将所有权重组合成一个权重向量 w,则模型可以表示为:
y = **w**^T **x**
这里,w^T 表示权重向量 w 的转置,w^T x 表示两个向量的点积。
核心概念与解释
以下是理解多元回归的几个关键点:
- 特征函数:模型中的每个
x_j可以是一个原始输入,也可以是原始输入的某个函数(例如平方、对数、交互项)。这提供了极大的灵活性,允许我们捕捉数据中更复杂的模式。 - 权重解释:权重
w_j表示,在保持所有其他特征不变的情况下,特征x_j每增加一个单位,预测值y平均变化w_j个单位。这是多元回归分析中非常重要的因果解释基础。 - 模型训练:与单变量回归类似,我们需要从数据中学习最佳的权重向量 w。这通常通过最小化一个损失函数(如残差平方和)来实现。寻找最优 w 的过程称为“拟合”模型。

实践重要性
多元回归之所以成为最广泛使用的工具之一,是因为它兼具解释性和预测能力。它不仅能给出预测值,还能量化每个因素对结果的影响大小,这对于商业决策、科学研究等领域至关重要。其数学形式相对简单,计算高效,且为许多更复杂的机器学习模型奠定了基础。

本节课中我们一起学习了多元回归的基本概念。我们了解了如何将线性回归从单一特征扩展到多个特征,掌握了多元回归的模型公式及其向量表示,并讨论了权重系数的核心解释。理解多元回归是进入更广阔机器学习世界的重要一步。
机器学习:第2课:多项式回归

在本节课中,我们将要学习多项式回归。这是一种比简单线性回归更灵活的模型,它允许我们使用输入变量的高次幂来拟合数据,从而捕捉更复杂的非线性关系。

上一节我们介绍了简单线性回归模型,它仅用一个输入变量来拟合一条直线。本节中我们来看看如何扩展这个模型,以处理更复杂的函数关系。
从简单线性回归到多项式回归
在上一模块中,我们讨论了简单线性回归。我们的目标是给数据拟合一条直线。在例子中,我们总是讨论房屋面积(平方英尺)与房屋价值之间的关系。
但顾名思义,简单线性回归模型确实非常简单。在许多情况下,我们会对输入变量更复杂的函数关系感兴趣。
多项式回归就是这样一个例子。我们实际上在专项课程的第一门课中已经见过它。当时我们采用了简单线性回归模型并进行了拟合。当然,那时我们还没有学习上一模块中的所有术语,但现在我们知道那是一个简单线性回归模型。

我们把这个拟合结果展示给朋友看,并说:“嘿,看,这太酷了,我有一条拟合数据的直线,现在我可以预测我的房子价值了。”
然而,你的朋友有点怀疑。他看着数据说:“老兄,房屋面积和房屋价值之间不是线性关系。”他不相信这个模型。相反,他认为应该是一个二次拟合。
所以你的朋友是在说,他不相信你使用的模型。他不相信那只是一个线性关系加上误差。他认为存在一个二次函数,其方程描述了房屋面积和房屋价值之间的潜在关系。当然,我们的回归模型会假设这个关系周围存在一些噪声。
你甚至可以考虑更高阶的多项式。例如,这里展示了一个四阶多项式,你可以选择它作为房屋面积与房屋价值之间关系的模型。
多项式回归模型
以下是通用的多项式回归模型。我们将观测值 Yi 建模为输入 X(例如房屋面积)的多项式函数,并假设存在一个误差项 εi,这是与第 i 个观测值相关的误差。
公式:
Yi = w0 + w1*Xi + w2*Xi^2 + ... + wp*Xi^p + εi
我们看到,与简单线性回归模型相比,这个模型中出现了 x 的所有这些幂次。我们可以将这些 x 的不同幂次视为特征。
现在,我们引入“特征”这个新词。特征只是你输入变量的某种函数。具体来说,在这个模型中,我们的特征非常明确:
以下是模型的特征列表:
- 第一个特征是常数
1,称为常数特征。 - 第二个特征是
x,即线性项,就像我们在简单线性回归中一样。 - 第三个特征是
x的平方。 - 我们一直持续到第
p+1个特征,即x的p次幂。
在我们的模型中,与这些特征中的每一个相关联的是一个参数。因此,我们有 p+1 个参数:w0(截距项)一直到 wp(与输入 p 次幂相关的系数)。


本节课中我们一起学习了多项式回归。我们了解到,通过将输入变量的不同幂次(如 x^2, x^3 等)视为新的特征,我们可以将线性回归框架扩展到拟合非线性关系。这使得模型能够更灵活地描述数据中更复杂的模式。
机器学习:第2课:建模季节性 📈

在本节课中,我们将学习如何为时间序列数据建模,特别是如何捕捉数据中随时间变化的趋势和周期性模式(即季节性)。我们将通过一个房价随时间变化的实际案例来演示。
概述:时间序列与季节性
上一节我们介绍了如何通过特征工程来观察单个输入的特征。本节中,我们来看看一个特别有用的应用:为时间序列数据去趋势并建模季节性。
时间序列数据是按时间顺序记录的数据点。在许多情况下,数据不仅会呈现长期趋势(如房价随时间上涨),还会呈现周期性波动(如夏季房价高,冬季房价低)。这种周期性波动被称为季节性。
房价数据示例
我们使用的数据是西雅图都会区的房屋销售数据。每个数据点代表一次房屋销售。
- 输出 Yᵢ:第 i 栋房屋的销售价格。
- 输入 Tᵢ:第 i 次销售发生的时间(按月记录)。
下图中的灰点代表所有房屋销售,黑色曲线代表房价随时间变化的平均值。

从图中可以观察到两个主要效应:
- 长期趋势:房价平均值随时间呈上升趋势。
- 季节性:房价在一年内呈现周期性波动(例如夏季价格高,冬季价格低)。
构建季节性模型
为了同时捕捉趋势和季节性,我们假设房屋售价由以下几个部分组成:
- 趋势成分:用一个关于时间 Tᵢ 的函数来建模长期趋势。为简化,我们可以先使用线性模型:
趋势 = w₀ + w₁ * Tᵢ。 - 季节性成分:用一个正弦函数来建模每年的周期性波动。我们希望这个正弦波每12个月(一年)重复一次。
一个直观的想法是使用如下模型:
价格 = w₀ + w₁ * Tᵢ + sin( (2π * Tᵢ / 12) + φ )
其中,φ(相位)是一个参数,用于控制正弦波峰谷出现的时间点(例如,峰值是在六月还是一月)。
然而,这里存在一个问题:参数 φ 位于 sin() 函数内部,这使得模型不再是关于参数的简单线性形式,拟合起来更复杂。
三角恒等式技巧
为了解决上述问题,我们可以利用一个三角恒等式进行转换。该恒等式为:
sin(A + B) = sin(A)cos(B) + cos(A)sin(B)
应用这个恒等式,我们可以将包含相位 φ 的正弦项重写:
sin( (2π * Tᵢ / 12) + φ ) = sin(2πTᵢ/12) * cos(φ) + cos(2πTᵢ/12) * sin(φ)
现在,cos(φ) 和 sin(φ) 变成了可以线性相乘的系数。我们将其重命名为新的权重参数 w₂ 和 w₃。
于是,我们的模型等价地变为:
价格 = w₀ + w₁ * Tᵢ + w₂ * sin(2πTᵢ/12) + w₃ * cos(2πTᵢ/12)
这个模型又回到了我们熟悉的线性回归形式!只不过我们的特征现在包括了:
- 特征1:常数项(1)
- 特征2:时间本身(Tᵢ)
- 特征3:
sin(2πTᵢ/12) - 特征4:
cos(2πTᵢ/12)
以下是模型转换的总结:

应用于房价数据
现在,让我们将这个模型应用到实际的房价数据中。我们不仅使用了线性项,还使用了更高阶的多项式(例如五阶多项式)来更灵活地捕捉长期趋势,同时加入了正弦和余弦特征来捕捉季节性。
拟合结果如下图所示,深蓝色曲线代表了我们的完整模型。


为了更清楚地观察季节性效应,我们可以放大数据图的某一部分。在放大的视图中,可以清晰地看到房价随着不同年份的季节更替而上下波动的模式,这正是正弦和余弦特征所捕捉到的周期性。
总结
本节课中我们一起学习了如何为时间序列数据建模季节性。核心步骤包括:
- 识别数据中的长期趋势和周期性模式。
- 使用多项式特征(如 Tᵢ, Tᵢ², …)来建模趋势。
- 使用正弦和余弦函数作为特征来建模固定周期(如一年)的季节性波动。
- 利用三角恒等式将带有相位参数的非线性模型转换为关于权重的标准线性回归模型,从而可以利用线性回归工具进行简单高效的拟合。
通过这种特征工程方法,我们可以用线性回归框架来建模复杂的、包含周期性变化的时间序列数据。
机器学习:第2课:季节性效应的广泛应用

在本节课中,我们将探讨回归分析中“季节性”这一核心概念。我们将看到,季节性效应不仅存在于房价预测中,还广泛出现在天气建模、流感监测、电子商务库存管理乃至动作捕捉等多个领域。理解这些应用场景,有助于我们更好地掌握如何为不同问题设计合适的回归模型。
🏠 从房价到更广阔的应用
上一节我们以房价预测为例,介绍了如何使用正弦和余弦函数来捕捉月度或年度周期性变化。实际上,回归分析和季节性建模的应用范围要广泛得多。本节中,我们将看看季节性效应在其他领域是如何体现的。
🌤️ 天气建模中的多尺度季节性
在天气建模中,例如预测温度或降雨量,季节性效应表现得非常明显。温度在一天之内有变化(白天热,夜晚凉),同时在一年之中也有变化(夏季热,冬季凉)。这意味着存在不同时间尺度上的季节性。
为了准确建模,我们可能需要引入多个不同频率的正弦和余弦函数。例如,一个函数捕捉每日循环,另一个函数捕捉每年循环。其核心公式可以扩展为:
y = w0 + w1 * sin(2π * t / T_daily) + w2 * cos(2π * t / T_daily) + w3 * sin(2π * t / T_yearly) + w4 * cos(2π * t / T_yearly) + ...
其中 T_daily 和 T_yearly 分别代表日周期和年周期。
🤒 健康监测中的周期性规律
季节性在健康监测领域也至关重要,例如流感监测。下图展示了美国多个地区的流感发病率随时间的变化。

观察任一地区的数据,都会发现清晰的季节性模式:流感季会出现发病高峰,而在非流感月份则处于低谷。这种周期性规律也出现在许多其他类型的健康监测中。
📦 电子商务与库存管理

在电子商务领域,季节性对库存管理有直接影响。以亚马逊销售滑雪夹克为例,公司需要精准预测库存以优化仓储。
以下是库存决策中考虑季节性的逻辑:
- 冬季月份需要储备更多夹克,因为购买需求更高。
- 夏季月份则需要减少库存,以避免积压。
因此,准确建模销售数据的季节性,对于控制成本和满足客户需求都极为重要。
🎬 动作捕捉中的重复模式
一个可能意想不到的应用领域是动作捕捉。当给人穿上动作捕捉服并记录其行走等动作时,附着在身体各部位的传感器会产生轨迹数据。
下图展示了一个人进行不同行为时,某个传感器的运动轨迹。

可以清晰地看到,随着人物完成抬膝、摆臂、行走等重复动作,传感器数据也呈现出上下波动的季节性模式。建模这种周期性对于分析人体运动规律至关重要。
📝 总结
本节课我们一起探索了季节性效应在多个领域的应用。从直观的天气温度变化、流感的年度流行,到商业中的库存周期,乃至人体运动的重复模式,季节性无处不在。理解这些实例,能帮助我们在面对新问题时,识别出潜在的周期性规律,并运用正弦、余弦函数等工具将其有效地构建到回归模型中,从而做出更准确的预测。
机器学习:第2课:单一输入的一般特征回归

在本节课中,我们将学习如何将回归模型从简单的线性或多项式形式,推广到使用任意函数作为特征的一般形式。我们将理解特征提取的概念,并学习如何用更通用的数学符号来描述回归模型。
上一节我们介绍了多项式回归和季节性回归,它们都使用了输入的不同函数作为特征。本节中,我们来看看如何将这些概念统一到一个更通用的框架中。
我们可以将模型更通用地写为一系列特征的组合。我们用函数 H 来表示每个特征。H₀ 是第一个特征,H₁ 是第二个特征,以此类推,直到第 D 个特征 H_D。
我们可以使用之前介绍过的求和符号更紧凑地表示这个模型:
ŷ = Σ_{j=1}^{D} w_j * H_j(x)
其中,H_j(x) 是我们的第 j 个特征,w_j 是与该特征关联的回归系数或权重。
以下是几个我们已经见过的特征示例:
- H₀(x) = 1:这是我们在所有例子中都使用过的常数特征。
- H₁(x) = x:这是线性项。
- H₂(x) = x² 或 sin(x):这可以是二次项或正弦基函数。
- H_D(x) = x^P:在多项式回归中,这可能是输入的第 P 次幂。
回顾我们之前介绍的回归流程图或框图,有一个部分我们之前没有详细说明,那就是蓝色的“特征提取”框。我们之前简单地说它的输出是 x。但现在,随着我们对回归和特征概念的深入理解,这个特征提取框的真正输出并不是 x,而是 H(x),即我们输入 x 的特征函数集合。
因此,x 实际上是特征提取器的输入,而输出是 x 的某些函数集合 H(x)。在本课程接下来的部分,我们将假设这个特征提取框的输出是 H(x)。

本节课中,我们一起学习了如何将回归模型推广到使用任意特征函数的一般形式。我们定义了特征函数 H_j(x) 和对应的权重 w_j,并用求和公式清晰地表达了模型。最后,我们明确了在机器学习流程中,原始输入 x 需要经过特征提取步骤,转化为特征向量 H(x),才能用于后续的模型训练和预测。理解这个一般化的框架,是学习更复杂模型的基础。
机器学习:第2课:多输入回归的动机 🧠

在本节课中,我们将要学习为什么在回归模型中需要使用多个输入变量。我们将从简单的单输入模型出发,探讨其局限性,并理解引入多个输入如何能帮助我们构建更准确、更强大的预测模型。

从单输入到多输入
上一节我们介绍了使用单一输入(如房屋面积)来预测输出(如房价)的基本线性回归模型。本节中我们来看看,为什么仅使用一个输入往往是不够的。

到目前为止,本课程假设我们只有一个输入(例如平方英尺),并试图用它来预测输出(例如房屋价值)。但通常,我们拥有许多不同的属性和输入,可用于预测某个输出。

我们在第一门课程中讨论过,即使我们使用更复杂的函数(如二次函数)来描述面积与房价的关系,而不是简单的直线,这可能仍然不是一个很好的预测模型。因为你可能会在数据集中发现,即使另一栋房子与你的房子面积非常相似,它本质上也是不同的。例如,图中这栋粉色的房子只有一个浴室,而你的房子有三个浴室。因此,你的房子当然应该比这栋只有一个浴室的房子价值更高。
这表明,我们需要向回归模型添加更多输入。我们不仅要记录平方英尺并用它来预测房屋价值,还要记录其他输入,例如房屋的浴室数量。我们将使用这两个输入来共同预测房价。
具体来说,在这个更高维度的空间中,我们将拟合一个函数,来建模平方英尺数、浴室数量与输出(房屋价值)之间的关系。一个简单的函数模型可以表示为:
房价 = w0 + w1 * 面积 + w2 * 浴室数量
在这个例子中,我们只讨论了面积和浴室数量作为回归模型的输入。当然,与任何房屋相关的还有许多不同的属性和特征,都可以用作回归模型的输入。
多输入回归的广泛应用
多输入回归模型的概念不仅适用于我们在此模块开头提到的住房数据,还有大量应用都使用了多元回归的思想。接下来,我将介绍一个我认为非常酷的应用:“读心术”。
有什么比读心术更酷的呢?你接受一次脑部扫描,可能是脑磁图(MEG)或功能磁共振成像(fMRI)。关键在于,这记录了你大脑的活动。在这种情况下,它是对看到某个单词、图像或类似刺激的反应。我们得到的是你大脑的图像,这个大脑被划分为称为体素的小区域。你可以将它们想象为三维像素,这些小体积区域中的每一个都有与之关联的强度值。
我们将使用这些强度值作为多个输入。这些将成为输入我们模型的不同特征,用于预测你在看到刺激后感到非常悲伤还是非常快乐。
我们拥有一些数据,其中人们被展示图像,并按照从非常悲伤到非常快乐的量表进行回应。我们得到的是这些大脑图像和快乐反应的配对数据。快乐反应是我们的输出,大脑图像是我们回归模型的输入。再次强调,多元回归的用武之地在于,我们不是只有一个输入,而是有一整套输入——即你大脑中所有不同体素的强度值集合。我们正是利用这些来尝试寻找大脑图像与快乐反应之间的关系。
为了明确起见,“读心”的方式是,我们可以考虑获取你的脑部扫描图,并预测你感到快乐还是悲伤。

总结

本节课中我们一起学习了引入多输入回归模型的动机。我们认识到,仅依赖单一输入特征(如房屋面积)进行预测存在局限性,因为现实世界的结果往往由多个因素共同决定。通过引入更多相关输入(如浴室数量),我们可以构建更精确的模型。最后,我们探讨了多元回归在“读心术”等前沿领域的酷炫应用,它通过分析大脑扫描中众多体素的强度(即多个输入)来预测情绪状态。这为我们后续学习如何具体构建和训练多输入回归模型奠定了基础。
机器学习:第2课:定义符号 📝

在本节课中,我们将学习机器学习中,特别是多元回归模型里,用于描述输入、输出和特征的核心符号与表示方法。明确这些符号对于理解后续课程内容至关重要。
概述
我们将介绍用于表示输入向量、输出标量、特征函数以及数据集中特定观测值的符号约定。这些约定将贯穿整个课程。
符号详解
上一节我们介绍了回归的基本概念,本节中我们来看看如何用精确的符号来描述模型中的各个部分。
首先,在多元回归中,我们的输入是多个不同的变量,例如房屋面积、卧室数量、浴室数量等。我们将这些变量组合成一个向量。
以下是输入与输出的符号定义:
- X: 表示一个 D 维的输入向量。其中包含 D 个不同的输入变量。符号使用粗体 X 表示。
- y: 表示一个标量输出。例如房屋价格。符号使用正常的 y 表示,不加粗。
接下来,我们需要定义如何访问向量中的元素以及特征函数。
以下是访问元素与特征函数的符号定义:
- x[j]: 表示从向量 x 中取出第 j 个元素。结果是一个标量,例如某个房屋的面积。这类似于 Python 中的索引操作。
- h_j: 表示第 j 个特征函数。在多元输入的情况下,特征函数通常是整个输入向量 X 的函数,即 h_j(X)。
最后,当我们在数据集的上下文中讨论时,需要指明是哪一个观测值。
以下是数据集中观测值的符号定义:
- X_i: 表示数据集中第 i 个观测值的输入向量。例如数据集中第 i 栋房屋的所有特征值。
- X_i[j]: 表示第 i 个观测值的输入向量中的第 j 个元素。这是一个标量,例如第 i 栋房屋的浴室数量。
总结

本节课中我们一起学习了机器学习回归模型中使用的基本符号。我们明确了用粗体 X 表示输入向量,用 y 表示输出标量,用 x[j] 索引向量元素,用 h_j 表示特征函数,并用下标 i 和 j 来指代数据集中的特定观测值和特征。请务必熟悉这些符号,因为它们将在后续课程中持续使用。
机器学习:第2课:多特征回归模型

在本节课中,我们将学习如何将回归模型从单一输入特征扩展到多个输入特征。我们将介绍模型的基本形式、符号表示,并解释如何构建更复杂的特征。
从简单模型到多输入特征
上一节我们讨论了简单的线性回归模型。本节中,我们来看看当预测目标依赖于多个输入时,如何构建模型。
假设我们想预测房价,输入可能包括房屋面积、浴室数量和卧室数量。最简单的模型是假设第 i 个观测值直接是这些输入的函数,而不是输入的其他函数。模型形式如下:
公式:y_i = w_0 + w_1 * (面积) + w_2 * (浴室数) + w_3 * (卧室数) + ε_i
其中 ε_i 是噪声项。
以下是与此简单超平面模型相关的特征定义:
- 第1个特征是一个常数项(例如
1),用于调整曲线在空间中的位置。 - 第2个特征是第一个输入(例如,房屋面积)。
- 第3个特征是第二个输入(例如,浴室数量)。
- 依此类推,直到最后一个输入成为第
d+1个特征(例如,地块大小)。
超越简单超平面:引入特征函数
与我们可以用多项式替代简单直线一样,我们也可以用 D 维曲线替代简单的超平面。这里 D 表示我们从多个输入中构建的不同特征的数量。
在更通用的模型中,每个特征可以是输入变量的任意函数。例如:
- 第0个特征通常是常数项
1。 - 第1个特征可以是第一个输入本身(如房屋面积)。
- 第2个特征可以是第二个输入,也可以是其他输入的函数(例如,
log(卧室数) * 浴室数)。 - 以此类推,直到第
D个特征,它可以是回归模型中任何输入的函数。
因此,通用的多特征回归模型可以表示为:
公式:y_i = Σ_{j=0}^{D} w_j * h_j(x) + ε_i
其中 h_j(x) 是第 j 个特征函数。这个公式非常重要,将在本模块乃至整个课程中反复使用。
重要符号总结
最后,我们来明确几个关键符号的定义,以确保表述清晰:
- N:表示我们拥有的观测数据数量。
- d:表示原始输入变量的数量。
- D:表示我们从输入中构建的特征总数。


本节课中,我们一起学习了如何构建多特征回归模型。我们从最简单的多输入线性模型出发,引入了特征函数的概念,从而能够构建更复杂的非线性关系模型,并明确了模型的关键公式和符号定义。理解这些基础是后续学习更高级回归技术的关键。
机器学习:第2课:解释多元回归拟合 📊

在本节课中,我们将学习如何解释多元线性回归模型的拟合系数。我们将从简单的线性回归模型开始,逐步过渡到具有多个输入特征的多元模型,并探讨在多项式回归等更复杂模型中解释系数时需要注意的问题。
回顾简单线性回归
上一节我们介绍了简单线性回归模型。现在,我们首先回顾一下如何解释其拟合系数。
在简单线性回归模型中,我们有一个拟合函数,它是一条直线,形式为:
ŷ = ŵ₀ + ŵ₁ * x
其中,ŵ₀ 和 ŵ₁ 是我们估计的模型参数。
ŵ₀是截距,代表当输入x为零时预测的输出值。在我们的房价例子中,可以理解为“零平方英尺”房屋的价值,但这个解释通常不具实际意义。ŵ₁是斜率,其解释为:对于输入x的每一个单位变化,预测输出ŷ的平均变化量。例如,如果x是房屋面积(平方英尺),那么ŵ₁就表示房屋面积每增加一平方英尺,预测的房价平均变化量。
解释多元线性回归系数
现在,我们来看看当模型有两个输入特征时,例如房屋面积(x₁)和卫生间数量(x₂),应如何解释系数。
我们的拟合函数现在是一个三维空间中的平面:
ŷ = ŵ₀ + ŵ₁ * x₁ + ŵ₂ * x₂
为了解释系数 ŵ₂(对应卫生间数量),我们需要固定另一个输入特征 x₁(房屋面积)。这相当于在三维空间中,沿着一个固定的 x₁ 值“切”一刀,得到的截面是一条直线。
以下是解释多元回归系数的关键步骤:
- 固定其他所有输入特征。
- 观察目标特征变化对输出的影响。
因此,ŵ₂ 的解释是:在房屋面积(x₁)保持不变的情况下,每增加一个卫生间,预测房价的平均变化量。这意味着我们考虑的是在不改变房屋总面积的前提下(例如,将某个房间改造为卫生间),增加卫生间对房价的影响。
扩展到更一般的多元模型
对于具有 d 个不同输入特征的更一般模型:
ŷ = ŵ₀ + ŵ₁ * x₁ + ŵ₂ * x₂ + ... + ŵ_d * x_d
解释任何一个系数 ŵ_j(对应特征 x_j)的方法是一致的:
在模型中所有其他特征保持不变的情况下,特征
x_j每增加一个单位,预测输出ŷ的平均变化量。
例如,对于卧室数量(x_j)的系数,其解释是:在房屋面积、卫生间数量等其他所有特征都固定的情况下,每增加一间卧室,预测房价的平均变化量。
理解系数的上下文依赖性 ⚠️
解释系数时,必须极其小心地考虑模型的上下文,即模型中包含了哪些其他特征。同一个特征的系数,在不同的模型中可能有完全不同的符号和含义。
让我们通过一个例子来说明:
-
情景A:模型包含“房屋面积”和“卧室数量”
- 此时,“卧室数量”的系数可能为负数。因为如果房屋总面积固定,增加卧室通常意味着每个卧室的面积变小。对许多买家而言,三间宽敞的卧室可能比四间狭小的卧室更有价值。
- 系数的解释是:在房屋面积不变的情况下,增加卧室对价值的影响。
-
情景B:模型仅包含“卧室数量”(不包含“房屋面积”)
- 此时,“卧室数量”的系数很可能是一个正数。因为卧室数量在这里充当了房屋大小的代理变量。通常,卧室越多的房子总面积也越大,因此价值更高。
- 系数的解释是:不考虑具体面积,卧室数量对价值的总体影响。
核心要点:不能孤立地看待一个系数并得出结论(例如,“哦,卧室越多,房价越低”)。必须结合模型中的其他特征来理解其含义:“在控制了其他变量(如面积)之后,该特征的影响是什么?”
多项式回归中的系数解释
最后,我们探讨一种特殊情况:多项式回归模型。假设我们只有一个原始输入 x(如房屋面积),但特征是其不同次幂:
ŷ = ŵ₀ + ŵ₁ * x + ŵ₂ * x² + ŵ₃ * x³ + ...
在这种情况下,我们无法像之前解释多元线性回归系数那样,去解释 ŵ_j。
原因:我们无法做到“固定其他所有特征”。因为所有特征(x, x², x³, ...)都源自同一个原始变量 x。改变 x 会同时改变所有特征,我们无法在改变 x 的同时保持 x² 或 x³ 不变。
因此,对于多项式回归或任何特征之间存在函数依赖关系的模型,单个系数的独立解释是没有意义的。我们通常将整个多项式函数作为一个整体来解释其形状和趋势。
总结
本节课中,我们一起学习了如何解释回归模型的拟合系数:
- 简单线性回归:系数
ŵ₁表示输入每变化一单位,输出的预测变化量。 - 多元线性回归:系数
ŵ_j表示在固定模型中所有其他特征的情况下,特征x_j每变化一单位,输出的预测变化量。 - 上下文至关重要:系数的符号和大小强烈依赖于模型中包含的其他特征。必须始终在模型上下文中进行解释。
- 多项式回归的局限:当特征之间存在严格的函数关系(如幂次关系)时,单个系数的独立解释不再有效。


理解如何正确解释系数是运用回归模型进行洞察和决策的基础,请务必牢记其条件性和上下文依赖性。
机器学习:回归:第2课:用向量符号重写单一观测模型 🧮


在本节课中,我们将学习如何将多元回归模型用向量和矩阵的符号重写。这是理解后续回归拟合算法(如闭式解和梯度下降)的关键第一步。通过使用线性代数符号,我们可以更简洁、更高效地表示和计算模型。


上一节我们详细讨论了多元回归模型及其系数的解释。本节中,我们来看看如何用向量符号来重写这个模型,为后续推导拟合算法打下基础。
具体来说,我们将重写之前展示的多元回归模型方程。我们注意到,对于第 i 个观测值,其模型可以表示为两个向量的乘积。
以下是构成模型的各个部分:
- 参数向量
w:这是一个包含所有回归系数的列向量,即w0, w1, w2, ..., wD。 - 特征向量
h(x_i):这是一个包含第i个观测值所有特征变换的列向量,即h0(x_i), h1(x_i), h2(x_i), ..., hD(x_i)。 - 误差项
ε_i:这是一个标量,代表第i个观测值的随机误差。
当我们计算这两个向量的内积(即点乘)时,过程如下:
w0 * h0(x_i) + w1 * h1(x_i) + w2 * h2(x_i) + ... + wD * hD(x_i) + ε_i
为了使用标准的线性代数符号,我们通常将参数向量 w 视为列向量。为了计算它与另一个列向量 h(x_i) 的内积,我们需要将其中一个转置为行向量。这里,我们选择转置参数向量 w。
因此,第 i 个观测值的模型可以简洁地写为:
y_i = w^T * h(x_i) + ε_i
其中 w^T 表示参数向量 w 的转置(即行向量),h(x_i) 是特征列向量。这个乘法的结果是一个标量,即预测值。
一个重要的性质是,内积的结果与向量的顺序无关。因此,以下两种写法是等价的:
y_i = w^T * h(x_i) + ε_i
y_i = h(x_i)^T * w + ε_i
两者展开后都会得到相同的求和式。在本课程后续内容中,我们将频繁使用这种向量化表示法。


本节课中,我们一起学习了如何将多元回归模型针对单一观测值的表达式,从冗长的求和形式重写为紧凑的向量内积形式 y_i = w^T * h(x_i) + ε_i。掌握这种表示法是理解后续矩阵运算和拟合算法的基础。下一节,我们将把整个数据集的模型用矩阵形式表示出来。
机器学习:第2课:用矩阵符号重写所有观测的模型

在本节课中,我们将学习如何将适用于单个观测的线性回归模型,扩展到包含所有观测的数据集。我们将使用矩阵和向量的符号来简洁地表示整个模型,这是推导后续算法(如闭式解)的关键一步。
上一节我们介绍了如何用向量形式表示单个观测的模型。本节中我们来看看如何将所有观测堆叠在一起,并用矩阵符号统一表示。
从单个观测到所有观测
之前,我们将单个观测的模型写为:
y_i = h(x_i)^T w + ε_i
其中,h(x_i) 是特征向量,w 是权重向量,ε_i 是误差。
为了处理所有 N 个观测,我们将所有目标值 y_i 堆叠成一个向量 Y,将所有误差 ε_i 堆叠成一个向量 ε。
以下是构建完整模型矩阵表示的关键步骤:
-
构建目标向量 Y:这是一个
N维列向量,包含从第一个到第N个观测的所有目标值。
Y = [y_1, y_2, ..., y_N]^T -
构建设计矩阵 H:这是一个
N × (D+1)的矩阵。每一行对应一个观测,每一列对应一个特征(包括常数项h_0)。
H = [ [h_0(x_1), h_1(x_1), ..., h_D(x_1)], [h_0(x_2), h_1(x_2), ..., h_D(x_2)], ..., [h_0(x_N), h_1(x_N), ..., h_D(x_N)] ] -
构建权重向量 w:这是一个
(D+1)维列向量,包含所有权重参数。
w = [w_0, w_1, ..., w_D]^T -
构建误差向量 ε:这是一个
N维列向量,包含每个观测的误差。
ε = [ε_1, ε_2, ..., ε_N]^T
完整的矩阵模型
利用以上定义的矩阵和向量,我们可以将整个线性回归模型简洁地重写为:
Y = H w + ε
这个公式的含义是:目标值向量 Y 等于设计矩阵 H 乘以权重向量 w,再加上误差向量 ε。设计矩阵 H 的每一行 h(x_i)^T 与权重向量 w 的点积,正是对第 i 个观测的预测值。


本节课中我们一起学习了如何用矩阵符号重写线性回归模型。我们将所有观测的目标值、特征和误差分别组织成向量和矩阵,最终得到了一个紧凑的模型表示 Y = H w + ε。这个表示法是后续求解模型参数(即权重 w)的基础,它使我们能够利用线性代数的工具高效地处理大规模数据集。
机器学习:第2课:计算RSS梯度

在本节课中,我们将学习如何计算多元线性回归中残差平方和(RSS)的梯度。梯度计算是推导模型闭式解以及实现梯度下降算法的关键步骤。
梯度推导概述
上一节我们介绍了多元回归中RSS的矩阵表示法。本节中,我们来看看如何计算这个RSS函数的梯度。梯度是一个向量,它指向函数值增长最快的方向,在优化问题中至关重要。
梯度的矩阵形式
在多元回归中,残差平方和(RSS)的梯度具有以下简洁的矩阵形式:
梯度公式:
∇RSS(w) = -2 * H^T * (y - Hw)
在这个公式中:
H是特征数据矩阵(设计矩阵)。H^T是矩阵H的转置。y是目标值向量。w是待求的权重参数向量。(y - Hw)是残差向量。
这个结果可以直接用于后续的模型求解。
从一维情况理解梯度公式
为了帮助理解这个矩阵梯度公式的由来,我们可以通过一个简化的一维类比来观察其中的模式。
考虑一个仅有一个参数 w 和单个数据点的情况。此时,RSS函数简化为一个标量函数:
RSS(w) = (y - Hw)^2
这里,y 和 H 都是标量。
我们对这个标量函数求关于 w 的导数。根据链式法则,计算过程如下:
求导过程:
- 将平方项的指数2乘到前面。
- 保留内部函数
(y - Hw)的一次方。 - 乘以内部函数
(y - Hw)关于w的导数,即-H。
因此,导数为:
d(RSS)/dw = 2 * (y - Hw) * (-H) = -2H * (y - Hw)
对比一维与多维公式
通过对比,我们可以发现清晰的对应关系:
以下是标量(一维)情况与向量/矩阵(多维)情况的公式对比:
- 标量导数:
-2 * H * (y - Hw) - 梯度(矩阵形式):
-2 * H^T * (y - Hw)
两者的结构非常相似:
- 都有系数
-2。 - 都包含
(y - Hw)项,即残差。 - 主要区别在于:标量情况下的
H,在矩阵情况下变成了其转置H^T。这个变化是为了确保矩阵乘法的维度匹配。
这个类比让我们有理由相信矩阵梯度公式的正确性,而无需深入复杂的线性代数或矩阵微积分证明。
总结

本节课中,我们一起学习了多元线性回归中残差平方和(RSS)梯度的计算。我们得到了核心的梯度公式 ∇RSS(w) = -2H^T(y - Hw),并通过与一维情况的类比,理解了该公式的结构和组成部分。这个梯度表达式是求解回归模型权重参数的基础,无论是通过闭式解方程还是梯度下降迭代法都离不开它。
机器学习:回归:2.3:方法一:闭式解 📐

在本节中,我们将学习求解多元线性回归模型参数的第一种方法——闭式解。我们将通过矩阵运算,直接推导出最优参数 W 的计算公式。
上一节我们介绍了用矩阵形式表示残差平方和。本节中,我们来看看如何通过求导并令其为零,来找到使残差平方和最小的参数 W。
推导闭式解
我们的目标是找到参数 W,使得残差平方和(RSS)的梯度为零。梯度公式如下:
[
\nabla RSS(\mathbf{W}) = -2\mathbf{H}^T\mathbf{y} + 2\mathbf{H}^T\mathbf{H}\mathbf{W}
]
为了找到最小值点,我们将梯度设为零并求解 W:
[
-2\mathbf{H}^T\mathbf{y} + 2\mathbf{H}^T\mathbf{H}\mathbf{W} = 0
]
首先,两边同时除以 2,简化方程:
[
-\mathbf{H}^T\mathbf{y} + \mathbf{H}^T\mathbf{H}\mathbf{W} = 0
]
接着,将 (-\mathbf{H}^T\mathbf{y}) 项移到等式右边:
[
\mathbf{H}^T\mathbf{H}\mathbf{W} = \mathbf{H}^T\mathbf{y}
]
现在,为了解出 W,我们需要在等式两边同时左乘矩阵 (\mathbf{H}^T\mathbf{H}) 的逆矩阵 ((\mathbf{H}T\mathbf{H})):
[
(\mathbf{H}T\mathbf{H}) (\mathbf{H}^T\mathbf{H}) \mathbf{W} = (\mathbf{H}T\mathbf{H}) \mathbf{H}^T\mathbf{y}
]
根据矩阵逆的定义,一个矩阵与其逆矩阵相乘得到单位矩阵 I。同时,单位矩阵乘以任何向量都得到该向量本身。因此,等式左边简化为 W。
于是,我们得到了参数 W 的估计值 (\hat{\mathbf{W}}) 的闭式解:
[
\hat{\mathbf{W}} = (\mathbf{H}T\mathbf{H}) \mathbf{H}^T \mathbf{y}
]
这个公式非常强大,它通过一次矩阵运算,同时求出了从 (w_0) 到 (w_D) 的所有回归系数。
公式的意义与优势
以下是这个闭式解公式的几个关键点:
- 简洁性:它将求解多个参数的问题,压缩成了一个简洁的矩阵方程。
- 高效性:对于中小型数据集,可以直接通过数值计算库(如
numpy.linalg.inv)快速计算出结果。 - 理论保障:在矩阵 (\mathbf{H}^T\mathbf{H}) 可逆(即满秩)的条件下,该解是使得残差平方和全局最小的唯一解。
这也解释了为什么我们要不厌其烦地将问题转化为矩阵形式——它使得推导和计算都变得异常清晰和紧凑。
总结


本节课中我们一起学习了求解多元线性回归参数的闭式解法。我们通过设置梯度为零,推导出了核心公式 (\hat{\mathbf{W}} = (\mathbf{H}T\mathbf{H}) \mathbf{H}^T \mathbf{y})。这个方法在数学上非常优雅,并能一次性计算出所有参数的最优估计值。
机器学习:第2课:讨论闭式解

在本节课中,我们将深入探讨线性回归的闭式解公式,分析其构成、计算复杂性以及在实际应用中的一些注意事项。我们将重点关注公式中的核心矩阵运算及其含义。
闭式解公式回顾
上一节我们介绍了线性回归的闭式解公式。其核心形式如下:
公式: w = (H^T * H)^(-1) * H^T * y
其中:
w是我们要求解的权重向量。H是设计矩阵,包含了所有观测数据的所有特征。y是目标值向量。
深入分析 (H^T * H)^(-1)
现在,让我们仔细看看公式中的 (H^T * H)^(-1) 部分。
矩阵 H 的维度
首先,回顾一下设计矩阵 H 的构成。它是一个大型矩阵,每一行代表一个独立的观测数据,每一列代表一个特征。
- 假设我们有
N个观测数据(样本数)。 - 假设我们有
D个特征。
那么,矩阵 H 的维度就是 N 行 × D 列。
矩阵乘法的结果
当我们计算 H^T * H 时:
H^T(H的转置)的维度是 D 行 × N 列。H的维度是 N 行 × D 列。
根据矩阵乘法规则,一个 D×N 的矩阵乘以一个 N×D 的矩阵,结果是一个 D × D 的方阵。也就是说,结果矩阵的行数和列数都等于特征的数量 D。
矩阵的可逆性
接下来,我们需要对这个 D×D 的方阵求逆,即计算 (H^T * H)^(-1)。
这个矩阵在大多数情况下是可逆的。一个关键条件是:线性独立的观测数据数量必须大于特征的数量 D。
- 简单理解:通常,只要我们的样本数量
N显著大于特征数量D,这个条件就能满足,矩阵就是可逆的。 - 深入说明:严格来说,需要的不是简单的
N > D,而是“线性独立的观测数据”数量大于D。如果某些观测数据是其他数据的线性组合,它们可能不增加新的信息。不过在本课程中,我们通常假设数据满足可逆条件。如果矩阵不可逆,我们会后续讨论其他处理方法。
计算复杂度分析
假设 (H^T * H) 矩阵是可逆的,我们来分析计算其逆矩阵的计算成本。
计算一个 D×D 矩阵的逆,其时间复杂度通常用大O符号表示为 O(D^3)。
这意味着:
计算所需的基本操作次数,与特征数量 D 的三次方成正比。例如,如果特征数量翻倍,计算量大约增加到原来的 8 倍。
对实际应用的影响
这种立方级的复杂度增长,在特征数量非常多(例如成千上万甚至更多)时,会带来严峻的挑战:
- 计算强度极高:求逆运算会变得非常缓慢,消耗大量的计算资源(CPU时间和内存)。
- 可能无法计算:在极端情况下,由于计算资源或时间的限制,直接求逆在实际上可能是“不可能”完成的任务。
因此,虽然闭式解在数学上非常优雅和精确,但在处理大规模、高维度的数据(即特征数 D 很大)时,直接使用这个公式可能并不可行。
替代方案简介
正是由于直接计算闭式解可能面临计算复杂度的挑战,在实际的机器学习应用中,我们通常会采用其他优化算法来求解权重 w,例如:
- 梯度下降法:一种迭代优化算法,通过逐步调整参数来最小化损失函数,特别适合大规模数据集。
- 随机梯度下降法:梯度下降的高效变体,每次迭代只使用一个或一小批样本,速度更快。
这些迭代方法避免了直接计算大型矩阵的逆,从而能够高效地处理海量特征和样本的数据。尽管闭式解存在快速计算逆矩阵的优化算法,但这些简单的迭代替代方案在实践中更为常用和灵活。
本节课总结
在本节课中,我们一起学习了:
- 深入剖析了线性回归闭式解
w = (H^T * H)^(-1) * H^T * y的核心部分。 - 明确了设计矩阵
H的维度(N×D),以及H^T * H运算后得到一个 D×D 的方阵。 - 讨论了
(H^T * H)矩阵可逆的条件:线性独立的观测数需大于特征数D。 - 重点分析了闭式解的主要计算瓶颈:求逆运算的时间复杂度为 O(D^3)。这意味着当特征数量很大时,计算会变得异常昂贵甚至不可行。
- 引出了在实际应用中,面对高维数据时,我们需要使用如梯度下降等迭代算法作为闭式解的替代方案。

理解闭式解的优点和局限性,能帮助我们在不同场景下选择合适的模型训练方法。
机器学习:回归:第2课:方法2:梯度下降

在本节课中,我们将学习用于求解多元线性回归问题的第二种核心方法:梯度下降法。我们将了解其基本思想、更新公式,并理解它如何通过迭代的方式找到最优参数。
概述
上一节我们介绍了通过解析解(正规方程)来求解多元线性回归问题。本节中,我们来看看另一种强大的迭代优化方法——梯度下降法。这种方法通过不断沿着目标函数(残差平方和)梯度的反方向更新参数,逐步逼近最优解。
梯度下降算法原理
梯度下降是一种通用的优化算法。其核心思想是:首先随机初始化参数向量,然后反复沿着目标函数下降最快的方向(即负梯度方向)迈出一步,最终收敛到问题的最优解。
对于多元线性回归,我们的目标是最小化残差平方和(RSS)。梯度下降算法会迭代地更新参数向量 W。
以下是梯度下降算法的通用更新步骤:
while not converged:
W_new = W_old - eta * gradient(RSS(W_old))
其中,eta 是学习率(步长),gradient(RSS(W_old)) 是在当前参数 W_old 处计算的 RSS 梯度。
多元线性回归的梯度下降
对于多元线性回归,梯度下降的更新公式具有特定的矩阵形式。
具体更新规则如下:
W_t+1 = W_t - 2η * H^T (y - H W_t)
让我们来解析这个公式:
- W_t:第
t次迭代时的参数向量。 - η:学习率,控制每次更新的步长。
- H:设计矩阵,包含所有观测的特征数据。
- y:观测值的真实向量。
- H W_t:使用当前参数
W_t对所有观测值做出的预测向量。 - (y - H W_t):当前预测的残差向量。

这个公式的意义在于,它同时更新模型中的所有回归系数(即整个 W 向量)。更新方向由设计矩阵 H 的转置与当前残差向量的乘积决定。

算法步骤总结
本节课中我们一起学习了梯度下降法在多元线性回归中的应用。
- 初始化:随机选择一组初始参数 W。
- 迭代更新:重复应用更新公式 W = W - 2η * H^T (y - H W),直到参数收敛(即变化非常小)或达到预设的迭代次数。
- 输出:最终得到的 W 即为模型学到的回归系数。

这种方法通过迭代避免了直接求解大型矩阵的逆,在处理特征维度非常高或数据量极大时可能更具计算优势。
机器学习:第2课:逐特征更新梯度下降

在本节课中,我们将深入探讨梯度下降算法,并聚焦于单个特征的权重更新过程。我们将推导其数学公式,并解释其背后的直观含义,帮助你理解为什么更新规则会呈现为当前的形式。
上一节我们介绍了梯度下降的整体框架,本节中我们来看看如何将其应用到单个特征的权重更新上。
单特征更新公式推导
与其直接使用矩阵形式,我们回到残差平方和的原始定义来推导,这样更简单明了。
残差平方和公式如下:
RSS(w) = Σ_{i=1}^{n} [ y_i - (w_0 * h_0(x_i) + w_1 * h_1(x_i) + ... + w_D * h_D(x_i) ) ]^2
梯度是一个向量,包含了对每个权重 w_j 的偏导数。我们只需关注其中一个元素,即 RSS 对 w_j 的偏导数,这就能给出第 j 个权重的更新规则。
对 w_j 求偏导的过程如下:
∂RSS/∂w_j = Σ_{i=1}^{n} [ -2 * h_j(x_i) * ( y_i - H(x_i)^T w ) ]
其中,H(x_i)^T w 是使用当前权重向量 w 对第 i 个观测值的预测值。
因此,第 j 个特征在梯度下降中的更新规则为:
w_j^{t+1} = w_j^{t} - η * ( ∂RSS/∂w_j )
代入偏导数公式,得到:
w_j^{t+1} = w_j^{t} + η * [ 2 * Σ_{i=1}^{n} h_j(x_i) * ( y_i - H(x_i)^T w^t ) ]
在实际算法中,常数因子2通常被吸收到学习率 η 中,因此核心更新项为:
w_j^{t+1} = w_j^{t} + η * Σ_{i=1}^{n} h_j(x_i) * ( y_i - ŷ_i^t )
其中 ŷ_i^t 是第 t 次迭代时的预测值。
更新规则的直观解释
现在,让我们通过一个例子来直观理解这个更新规则。假设 w_j 对应“卫生间数量”这个特征的系数。
以下是更新过程如何工作的逻辑:
-
情况:低估特征影响
- 如果当前模型低估了卫生间数量对房价的影响,意味着权重
w_j^t太小。 - 那么,对于许多观测值,真实房价
y_i将大于模型预测值ŷ_i^t,导致残差(y_i - ŷ_i^t)在整体上为正。 - 在更新公式中,我们将这些正的残差乘以对应的特征值
h_j(x_i)(即卫生间数量)并求和。 - 最终,更新项
η * Σ [...]会是一个正值,加到当前的w_j^t上。 - 结果:
w_j^{t+1} > w_j^t,我们增加了卫生间数量的权重,修正了之前的低估。
- 如果当前模型低估了卫生间数量对房价的影响,意味着权重
-
为何用特征值加权残差?
- 在求和项
Σ h_j(x_i) * (y_i - ŷ_i^t)中,每个观测值的残差都被其对应的特征值h_j(x_i)加权。 - 这是因为,拥有更多该特征(例如更多卫生间)的观测值,在评估该特征对误差的“责任”时应具有更大的发言权。一个卫生间很多的房子,其预测误差在调整卫生间权重时理应比一个卫生间很少的房子贡献更多的信息。
- 在求和项


本节课中我们一起学习了梯度下降算法中针对单个特征的权重更新过程。我们推导了其数学公式,并通过“卫生间数量”的例子,解释了更新规则如何根据预测误差(残差)和特征值本身来动态调整权重,使模型逐步逼近最优解。这种逐特征审视的方式,为理解梯度下降的工作原理提供了清晰的直觉。
机器学习(回归):第2课:梯度下降算法总结

在本节课中,我们将详细总结用于多元回归的完整梯度下降算法。我们将仔细梳理算法的每一个步骤,并解释其背后的核心概念。梯度下降是机器学习中最基础且应用最广泛的优化算法之一,理解其运作机制至关重要。
算法概述
梯度下降算法的目标是找到一组模型参数,使得损失函数(如残差平方和)的值最小化。其核心思想是沿着损失函数梯度的反方向,以一定的步长(学习率)迭代更新参数,直至收敛。
算法步骤详解
上一节我们推导了多元回归中损失函数的梯度。本节中,我们来看看如何利用这个梯度来构建完整的迭代优化算法。
以下是梯度下降算法的具体步骤:
- 初始化参数与计数器:首先,将所有模型参数初始化为零。当然,也可以随机初始化或采用其他更智能的策略。同时,将迭代计数器
t设置为 1。 - 检查收敛条件:在每次迭代开始前,检查算法是否已经收敛。我们设定的收敛条件是:损失函数
J(即残差平方和 RSS)的梯度向量的模长是否小于一个预设的极小容差值ε。如果梯度的模长大于ε,则继续迭代;否则,停止迭代。- 梯度模长的计算公式:
||∇J|| = sqrt( (∂J/∂w₀)² + (∂J/∂w₁)² + ... + (∂J/∂w_D)² )
其中,∂J/∂w_j是损失函数J对第j个参数的偏导数。
- 梯度模长的计算公式:
- 迭代更新参数:只要未满足收敛条件,就对模型中的每一个特征参数
w_j执行以下更新操作:- 计算偏导数:根据上一节推导的公式,计算损失函数
J对当前参数w_j的偏导数∂J/∂w_j。这个值既用于参数更新,也用于评估收敛性。- 偏导数公式:
∂J/∂w_j = -2 * Σ_{i=1}^{N} [ (y_i - ŷ_i) * x_{i,j} ]
其中,ŷ_i是当前参数下的模型预测值。
- 偏导数公式:
- 执行梯度步进:使用计算出的偏导数和预设的步长(学习率
η)来更新参数。- 参数更新公式:
w_j^{(t+1)} = w_j^{(t)} - η * (∂J/∂w_j)
- 参数更新公式:
- 计算偏导数:根据上一节推导的公式,计算损失函数
- 循环与终止:完成对所有参数的一轮更新后,将迭代计数器
t加 1。然后,跳回步骤 2 重新计算梯度模长并检查收敛条件。如此循环,直至梯度模长||∇J||小于容差ε,算法终止。
算法的重要性
虽然我们是在多元回归的背景下介绍梯度下降,但请务必理解,这个算法本身极其重要且通用。它是目前应用最广泛的机器学习优化算法之一。在后续课程中,无论是讨论分类问题,还是深入到深度学习领域,我们都会反复见到梯度下降及其变种的身影。正如本课标题所示,掌握梯度下降是构建机器学习知识体系的核心基石。
总结


本节课中,我们一起学习了多元回归背景下梯度下降算法的完整流程。我们明确了算法从参数初始化、收敛性判断,到迭代更新参数的每一个步骤,并给出了关键的数学公式。理解并熟练应用梯度下降,将为后续学习更复杂的机器学习模型打下坚实的基础。
机器学习:第2课:多元回归核心回顾 🧠
在本节课中,我们将系统回顾多元回归的核心概念。多元回归是应用最广泛的机器学习工具之一,与之配套的梯度下降算法也是最常用的优化算法。本节将总结多元回归模型的定义、拟合方法、系数解释及其预测应用。

多元回归模型概述 📊
上一节我们介绍了多元回归的基本思想。多元线性回归模型用于描述一个目标变量与多个特征变量之间的线性关系。其核心公式如下:
公式:
[
y = w_0 + w_1 x_1 + w_2 x_2 + \dots + w_d x_d + \epsilon
]
其中:
- ( y ) 是目标变量。
- ( x_1, x_2, \dots, x_d ) 是特征变量。
- ( w_0, w_1, \dots, w_d ) 是模型系数(参数)。
- ( \epsilon ) 是误差项。
该模型不仅适用于处理多个不同输入特征的情况,也能通过特征变换(如多项式项)来建模单输入的非线性关系,例如多项式回归或时间序列中的季节性建模。
模型拟合方法 ⚙️
本节中我们来看看两种主要的模型拟合方法:解析解和梯度下降。
1. 解析解(闭式解)
对于多元线性回归,存在一个直接的解析解,可通过最小二乘法求得。其核心是通过求解正规方程来得到最优系数。
公式:
[
\mathbf{w} = (\mathbf{X}^T \mathbf{X})^{-1} \mathbf{X}^T \mathbf{y}
]
其中:
- ( \mathbf{X} ) 是特征矩阵(包含一列1以对应截距 ( w_0 ))。
- ( \mathbf{y} ) 是目标变量向量。
- ( \mathbf{w} ) 是系数向量。
2. 梯度下降算法
当特征维度很高或数据量很大时,计算解析解可能计算量过大。梯度下降是一种迭代优化算法,通过不断沿成本函数梯度反方向更新参数来寻找最优解。
以下是梯度下降的参数更新规则:
代码(更新规则):
# 重复直到收敛
for j in range(num_iterations):
# 计算预测值
predictions = X.dot(w)
# 计算误差
errors = predictions - y
# 计算梯度(对每个系数w_j)
gradient = (1/m) * X.T.dot(errors)
# 更新系数
w = w - learning_rate * gradient
模型系数的解释 🔍
理解模型系数的含义对于解释模型至关重要。在多元回归中,系数 ( w_j ) 表示在保持其他所有特征不变的情况下,特征 ( x_j ) 每增加一个单位,目标变量 ( y ) 的预期变化量。
例如,在一个预测房价的模型中,如果 ( w_1 = 150 ),且 ( x_1 ) 代表房屋面积(平方米),则意味着在房屋其他条件不变的情况下,面积每增加一平方米,房价预计上涨150单位。
模型预测与应用 🎯
拟合模型后,核心应用是进行预测。使用学习到的系数 ( \mathbf{w} ),对于新的输入特征向量 ( \mathbf{x}_{\text{new}} ),预测值计算如下:
公式:
[
\hat{y} = w_0 + w_1 x_{\text{new},1} + w_2 x_{\text{new},2} + \dots + w_d x_{\text{new},d}
]


总结 📝
本节课中我们一起学习了多元回归的核心内容。我们回顾了多元线性回归模型的定义,它能够处理多特征输入及通过变换处理复杂模式。我们探讨了两种模型拟合方法:高效的解析解和适用于大规模数据的梯度下降算法。我们还学习了如何解释模型系数,并了解了如何使用拟合好的模型进行预测。多元回归是机器学习中强大而基础的工具,为理解更复杂的模型奠定了坚实的基础。
机器学习:第2课:评估性能简介 🎯

在本节课中,我们将要学习如何评估机器学习模型的性能。到目前为止,我们已经详细讨论了用于拟合模型的不同模型和算法,但我们还不知道如何评估所估计模型的性能。这当然对于分析我们手头方法的性能至关重要。如果我们能思考如何评估我们程序的性能,那么我们就可以利用这一点来帮助我们在不同复杂度的模型之间做出选择。
为何需要评估性能? 🤔
上一节我们介绍了多种模型和拟合算法,本节中我们来看看为什么以及如何评估它们的性能。评估性能是机器学习流程中的关键一步,它帮助我们理解模型在现实世界中的表现,并指导我们进行模型选择和改进。
评估性能的核心目标 🎯
评估模型性能主要服务于以下几个核心目标:
- 衡量模型准确性:判断模型预测结果与真实情况的接近程度。
- 比较不同模型:在多个候选模型中,选择性能最优的一个。
- 指导模型选择:帮助我们决定模型的复杂度,避免过拟合或欠拟合。
- 分析方法有效性:评估我们所使用的整个建模流程(包括算法和参数)是否有效。
如何进行性能评估? 📊
为了评估性能,我们需要一套系统的方法和指标。以下是评估过程中需要考虑的几个关键方面:
- 定义评估指标:首先需要确定用什么数学公式或标准来衡量性能,例如均方误差(MSE)或准确率(Accuracy)。
- 划分数据集:通常将数据分为训练集和测试集。模型在训练集上学习,在未见过的测试集上评估,以模拟真实应用场景。
- 计算性能指标:使用选定的评估指标,在测试集上计算模型预测的得分。
总结 📝

本节课中我们一起学习了评估机器学习模型性能的重要性及其核心目标。我们了解到,性能评估不仅是衡量模型好坏的标尺,更是比较不同模型、选择合适复杂度以及优化整个建模流程的基石。在接下来的课程中,我们将深入探讨具体的评估指标和方法。
机器学习(回归):第2课:损失函数详解

在本节课中,我们将要学习机器学习中的一个核心概念:损失函数。损失函数用于量化模型预测值与真实值之间的差异,是评估模型性能、指导模型训练的关键工具。上一节我们介绍了如何指定模型和拟合算法,本节中我们来看看如何衡量模型预测的“好坏”。

完成前面的模块后,我对自己很有信心。我可以指定一个模型,也可以指定一个拟合该模型的算法。通过这个过程,我得到一个拟合好的函数,并且知道如何使用这个函数进行预测。例如,我预测我的房子价值,然后去卖房赚钱,一切顺利。
然而,情况可能并非如此。我的预测可能不够准确。结果,我对房子的标价可能不准确,最终可能导致我亏钱。因此,我们需要思考一个衡量标准:当我们做出某个预测时,我们损失了多少。
以房屋估价为例,如果我们把房价标得太低,可能会收到较低的报价,这相对于做出更好的预测来说是一种损失。或者,如果把房价标得太高,可能没人来看房,收不到任何报价,或者看房人少导致买家出价很低。同样,由于对房屋价值做出了糟糕的预测,我陷入了更糟糕的财务状况。
问题在于,与做出完美预测相比,我损失了多少?当然,我们永远无法做出完美预测。世界运行的方式非常复杂,我们无法期望完美地建模,也无法完美处理观测过程中固有的噪声。但让我们想象一下,如果我们能完美预测价值,那么在这种情况下,我们的损失是零,因为我们做得完美,没有损失任何钱。
那么,如何形式化地描述我们损失了多少这个概念呢?在机器学习中,我们通过定义所谓的损失函数来实现。损失函数规定了当真实观测值是 y,而我们做出其他预测 ŷ 时所付出的代价。
更明确地说,我们将估计模型参数 ŵ,并用它们来形成预测。这里的符号 f_ŵ 等价于我们之前写的 f̂,但出于本模块稍后将看到的原因,这个符号非常方便。它表示我们在某个输入 x 处的预测观测值或预测值,而 y 是真实值。
损失函数 L 以某种方式衡量这两者之间的差异。
定义损失函数有多种方式,实际上有很多种。这里我将介绍几个例子。特别要说明的是,我将要介绍的这些例子假设高估和低估所产生的成本完全相同。也就是说,把房子标价高估1000美元与低估1000美元没有区别。在这些例子中,我们假设的是对称损失函数。
非常常见的选择包括绝对误差,它只关注真实值与预测值之差的绝对值。
另一个常见的选择是平方误差,它不是看绝对值,而是看那个差值的平方。这意味着,如果差值很大,相对于绝对误差,你会承担非常高的成本。
在本模块的学习过程中,记住乔治·博克斯的这句话很有用:“记住,所有模型都是错的。实际问题是,它们要错到什么程度才会变得无用?”
我们已经花了大量时间定义不同的模型,现在我们将拥有工具来评估这些方法的性能,思考它们在实践中是否对我们有用的问题。

核心概念与公式
以下是两种常见的对称损失函数定义:
1. 绝对误差损失函数
该函数计算预测值与真实值之差的绝对值。
L(y, ŷ) = |y - ŷ|
2. 平方误差损失函数
该函数计算预测值与真实值之差的平方。
L(y, ŷ) = (y - ŷ)²
总结

本节课中我们一起学习了损失函数的概念及其在机器学习中的重要性。我们了解到,损失函数 L(y, ŷ) 用于量化模型预测 ŷ 与真实值 y 之间的差异。我们介绍了两种基础的对称损失函数:绝对误差和平方误差,并理解了它们如何以不同方式惩罚预测误差。正如乔治·博克斯所言,模型总是不完美的,而损失函数正是我们衡量其“错误”程度、判断其是否“有用”的关键工具。在后续课程中,我们将看到如何利用损失函数来训练和优化我们的模型。
机器学习(回归):第2课:训练误差:评估训练集上的损失 📊

在本节课中,我们将学习如何评估模型在训练数据上的表现,即计算训练误差。我们将了解其定义、计算方法,并探讨其与模型复杂度之间的关系及其局限性。
训练误差的定义
上一节我们介绍了模型拟合的基本概念,本节中我们来看看如何量化模型在训练数据上的表现。首先,我们需要明确什么是训练数据。
训练数据通常是我们从所有可用数据中选取的一个子集。在图表中,蓝色圆圈代表被选入训练集的数据点,而灰色圆圈则代表未被包含的点。
我们使用这个训练数据集来拟合模型,即估计模型参数。例如,对于一组数据,我们可能选择用一个二次函数来拟合。为了找到最佳拟合,我们会最小化这些训练数据点上的残差平方和。
在获得估计的模型参数 Ŵ 后,我们希望评估该模型的训练误差。为此,我们首先需要定义一个损失函数,例如平方误差或绝对误差。
训练误差的定义是:在训练点上计算的平均损失。其数学公式如下:
训练误差 = (1 / n) * Σ L(y_i, ŷ_i)
其中:
- n 是训练集中的观测总数。
- Σ 表示对所有训练观测值求和。
- L(y_i, ŷ_i) 是第 i 个观测值的损失函数值(例如,平方误差)。
需要明确的是,模型参数 Ŵ 正是在这个训练集上通过最小化残差平方和(或其他目标函数)估计出来的。现在,我们又在同一个训练集上评估其误差。
以平方误差为例
为了更具体地理解,我们来看一个使用平方误差作为损失函数的例子。
在这种情况下,训练误差的公式变为:
训练误差 = (1 / n) * Σ (y_i - ŷ_i)²
这个公式计算的是所有训练房屋的实际销售价格与预测销售价格之差的平方的平均值。
我们可以看到,当损失函数为平方误差时,训练误差的形式恰好是残差平方和除以 n。这里需要注意一个惯例差异:有些人定义训练误差时包含 1/n(即平均损失),有些人则直接使用残差平方和。在本教程中,我们采用平均损失的定义。
此外,我们经常使用一个相关的指标:均方根误差。
RMSE = √(训练误差)
RMSE 是训练误差的平方根。考虑使用 RMSE 的原因是它的单位更直观。在我们的房价例子中,训练误差的单位是“美元²”,而 RMSE 的单位是“美元”,这更符合我们对误差的常规理解。
训练误差与模型复杂度
现在我们已经定义了训练误差,接下来可以观察训练误差如何随着模型复杂度的增加而变化。
我们从最简单的模型开始:常数模型(例如,用所有房价的平均值来预测)。这个模型非常简单,通常会产生较大的训练误差。
以下是随着模型复杂度增加,训练误差变化的典型趋势:
- 线性模型:当我们用一条直线(线性回归)拟合数据时,训练误差通常会比常数模型有所下降。
- 二次模型:使用二次函数拟合时,模型能更好地捕捉数据中的曲线关系,训练误差会进一步降低。
- 高次多项式模型:随着我们使用更高阶的多项式,模型拥有更多的灵活性,可以几乎完美地穿过每一个训练数据点,从而导致训练误差变得非常低,甚至接近于零。
总的来说,训练误差随着模型复杂度的增加而单调下降。原因很直观:模型是在训练数据上拟合的,模型越复杂,它“记住”或拟合训练数据点的能力就越强。因此,当我们在这些高复杂度模型上评估训练误差时,自然会得到非常低的值。

训练误差的局限性:过拟合问题
一个自然的问题是:训练误差是衡量模型预测性能的好指标吗?

上图展示了一个高阶多项式模型,它在训练数据上误差极低,完美地拟合了那些蓝色数据点。然而,如果我们用它来预测一个位于灰色区域的新房屋(具有特定平方英尺数),问题就出现了。
这个拟合函数预测,拥有大约 Xt 平方英尺的房屋,其价值反而比面积更小或更大的房屋要低(因为函数在此处有一个向下的“凹陷”)。我们真的相信这是一个真实的价值洼地吗?很可能不是。
这里的问题在于:训练误差在评估预测性能时过于乐观。这是因为模型参数 Ŵ 是为了最小化训练集上的误差(如残差平方和)而专门调整的。然后,我们又用同一个数据集来评估它的表现,这就像让一个学生用自己的复习笔记来出题并参加考试,然后得了高分一样——这并不能代表他面对全新试题时的真实能力。
因此,训练误差小并不一定意味着预测性能好,除非你的训练数据集能够完美代表未来可能遇到的所有情况。这种现象就是过拟合:模型过于复杂,以至于它不仅学到了数据中潜在的真实规律,还“记住”了训练数据中的随机噪声和特定细节,导致其在新数据上的泛化能力变差。
总结
本节课中我们一起学习了:
- 训练误差的定义:它是模型在训练数据集上的平均预测损失。
- 其计算公式为 平均损失,当使用平方误差时,它与残差平方和相关,并引出了单位更直观的 RMSE。
- 训练误差随模型复杂度增加而下降,因为更复杂的模型能更好地拟合训练数据。
- 训练误差的主要局限性:它是一个过于乐观的指标,低训练误差不能保证模型在新数据(测试数据)上有良好的预测性能,这引出了过拟合的核心问题。


认识到训练误差的局限性至关重要,它促使我们在下一节中引入更可靠的评估方法:测试误差。
机器学习(回归):第2课:泛化误差:我们真正想要的

在本节课中,我们将要学习一个比训练误差更重要的概念——泛化误差。我们将探讨为什么评估模型在未知数据上的表现至关重要,以及如何从理论上理解它。
概述:从训练误差到泛化误差
上一节我们介绍了训练误差,即模型在训练数据上的表现。然而,训练误差并不能完全反映模型在真实世界中的预测能力。本节中我们来看看一个更核心的评估指标:泛化误差。
训练误差仅衡量模型对已见数据的拟合程度。我们真正需要评估的,是模型对所有可能遇到的新数据的预测性能。这被称为泛化误差或真实误差。
具体来说,我们真正希望得到的是,模型在我们社区所有可能出现的房屋(而不仅仅是已售出的样本)上的平均损失估计。


定义泛化误差
为了计算对所有可能房屋的误差估计,我们需要根据每对“房屋特征”和“销售价格”在数据中出现的可能性对其进行加权。
这可以通过定义两个分布来实现:
- 房屋面积分布:描述我们社区中不同面积房屋出现的可能性。它类似于一个非常密集的直方图,显示了每个可能面积值对应的房屋数量。通常,极小或极大的房屋都较少见,呈现一种类似钟形曲线的分布。
- 给定面积下的房价分布:对于特定面积(例如2640平方英尺)的房屋,其销售价格也有一个分布范围(例如68万到95万美元),具体价值取决于房屋的其他品质。
因此,泛化误差的形式化定义为:我们根据训练数据估计出模型参数 W_hat,然后计算损失函数 L( f_W_hat(x), y ),最后对所有可能的 (x, y) 对求平均,但需按它们根据上述分布出现的可能性进行加权。
用公式表示如下:
泛化误差 = E_(x, y)~P_data [ L( f_W_hat(x), y ) ]
其中,P_data 代表真实世界中数据(特征x和标签y)的联合概率分布。
模型复杂度与泛化误差的关系
现在,让我们回到观察误差与模型复杂度的关系图,但这次我们量化泛化误差随复杂度的变化。
以下是不同复杂度模型下泛化误差的直观分析:
- 常数模型:泛化误差较高。它只在中间某个区域表现尚可,但整体上对数据分布的近似效果很差。
- 线性模型:泛化误差有所下降,表现优于常数模型,但在数据分布的边缘区域仍然不佳。
- 二次模型:泛化误差进一步降低。模型开始更好地捕捉数据的整体趋势,尽管在极端区域可能仍有改进空间。
- 高阶多项式模型:当我们观察训练误差时,它确实更低了。但现在考虑泛化误差,它实际上会开始上升。模型在训练数据点附近拟合得过于完美,但在其他广大区域(如图中所示)预测非常糟糕,导致整体泛化性能变差。
- 极高阶多项式模型:得到极其曲折的拟合线。除了在个别训练数据点附近,它在几乎所有区域的预测都极其糟糕,因此泛化误差会急剧升高。
泛化误差曲线与核心挑战
综合以上分析,我们可以描绘出泛化误差随模型复杂度变化的一般曲线:
泛化误差曲线通常呈U形。随着复杂度增加,误差最初下降,到达一个最优复杂度点后,误差开始重新上升。这是因为模型变得过于复杂,虽然能完美拟合训练数据(训练误差低),但丧失了推广到新数据的能力,即发生了过拟合。
然而,与训练误差不同,我们无法直接计算泛化误差。因为它的定义依赖于真实的、未知的数据分布 P_data(即世界运行的真实规律)。我们只能通过一些方法(如验证集、交叉验证)来估计它,而无法精确获得图中每个点。
总结


本节课中我们一起学习了泛化误差的概念。我们明白了评估模型不应只关注其在训练数据上的表现(训练误差),而更应关注其在所有可能新数据上的预期表现(泛化误差)。泛化误差通过考虑数据真实分布对预测损失进行加权平均来定义。随着模型复杂度增加,泛化误差会先减后增,揭示出偏差-方差权衡与过拟合现象的核心问题。理解这一点是构建实用、稳健机器学习模型的基础。
机器学习:第2课:测试误差:我们实际可以计算的

在本节课中,我们将学习如何评估机器学习模型的预测性能。我们将了解到,虽然我们无法直接计算模型在未知数据上的真实误差(泛化误差),但可以通过一种称为“测试误差”的指标来近似它。我们将探讨测试误差的计算方法、它与训练误差的区别,以及它如何随模型复杂度变化。
上一节我们讨论了训练误差及其局限性,它无法很好地反映模型在新数据上的表现。本节中我们来看看如何通过“测试误差”来更好地评估模型。
什么是测试误差?
我们无法计算泛化误差,但需要一个比训练误差更好的指标来衡量预测性能。测试误差允许我们近似泛化误差。
实现方法是:通过评估那些不在训练集中的数据点来近似误差。为此,我们必须预留一部分数据。
假设我们有一个包含所有彩色房屋的完整数据集。我们不将所有数据都用于训练,而是将其中一部分(图中灰色房屋)留出,形成一个测试集。

测试集中的房屋不包含在训练集中。训练集由剩余的彩色房屋组成。当我们拟合模型时,只使用训练数据集。然后,在评估该模型的性能时,我们查看这些测试房屋。我们希望测试集能作为世界上所有潜在数据的一个代表,至少能用来衡量给定模型的性能好坏。
如何计算测试误差?
测试误差是我们在测试数据集上计算的平均损失。其正式定义如下:
公式:
测试误差 = (1 / n_test) * Σ loss(y_i, f(x_i; ŵ))
其中:
n_test是测试集中的房屋数量。loss是损失函数(例如平方误差)。ŵ是模型参数。- 求和
Σ是针对所有测试集房屋进行的。
需要特别强调的是:估计参数 ŵ 是在训练数据集上拟合得到的。

尽管这个公式看起来与训练误差非常相似,但求和是在测试房屋上进行的,而我们评估的函数(模型)是在训练数据上拟合的。这些拟合函数中的参数从未见过测试数据。

测试误差计算示例
为了说明这一点,我们沿用之前的例子。我们考虑用一个二次函数来拟合数据,通过最小化训练点(蓝色圆圈)上的残差平方和来获得估计参数 ŵ。

然后,当我们计算测试误差时(这里仍以平方误差为例),我们是在测试点(所有这些不同的灰色圆圈)上计算这个误差。

公式:
测试误差 = (1 / n) * Σ (真实房价 - 预测房价)^2
求和针对测试数据集中的所有房屋。关键区别在于:这个函数是用蓝色圆圈拟合的,但我们在评估性能时,看的是这些灰色圆圈。
误差与模型复杂度的关系
现在,让我们总结一下误差作为模型复杂度函数的变化趋势。
我们发现,训练误差随着模型复杂度的增加而下降。

相比之下,泛化误差(或真实误差)在一段时间内下降,但当我们开始使用过于复杂、泛化能力差的模型时,泛化误差开始上升。
那么,我们的测试误差是怎样的呢?测试误差是泛化误差的一个有噪声的近似。因为如果我们的测试数据集包含了世界上我们可能看到的所有数据,并且比例与其出现的可能性成比例,那么测试误差就恰好等于泛化误差。但当然,我们的测试集只是一个有限的数据集,我们用它来近似泛化误差。因此,它将是这条曲线的一个有噪声的版本。



本节课中我们一起学习了测试误差的概念。我们了解到,测试误差是我们实际可以计算的指标,通过在预留的、模型未见过的测试集上评估模型性能而得。它是我们真正关心的泛化误差的一个近似。测试误差与训练误差的关键区别在于评估数据的不同:训练误差使用模型拟合时见过的数据,而测试误差使用模型未见过的数据。理解这一点对于正确评估和选择模型至关重要。
机器学习:第2课:定义过拟合 📈

在本节课中,我们将正式定义机器学习中的一个核心概念——过拟合。我们将通过清晰的图示和条件描述,帮助你理解什么是过拟合,以及如何识别它。
上一节我们讨论了模型复杂性与泛化能力的关系,本节中我们来看看如何正式定义“过拟合”。
过拟合是指,当你有一个模型(例如,一个具有参数 Ŵ 和一定复杂度的模型)时,如果满足以下两个条件,则该模型是过拟合的:
以下是判断模型是否过拟合的两个核心条件:
- 模型 Ŵ 的训练误差小于另一个模型 W‘ 的训练误差。
- 模型 Ŵ 的真实误差大于另一个模型 W‘ 的真实误差。
用公式可以表示为:
- 条件一:
训练误差(Ŵ) < 训练误差(W‘) - 条件二:
真实误差(Ŵ) > 真实误差(W‘)

这个概念可能看起来不那么直观。让我们结合这张图来解释,图中的点正好对应了上述两个条件。
图中存在一系列真实误差大于 W‘ 的模型。而过拟合的模型是那些训练误差特别小的模型。这些模型对训练数据集的拟合程度非常高,但泛化能力很差。而图中另一半空间的点,则是对训练数据拟合不好、同时泛化能力也差的模型。




本节课中我们一起学习了过拟合的正式定义。一个模型如果在训练集上表现优异(误差小),但在真实数据上表现不佳(误差大),并且存在另一个在两方面表现更均衡的模型,那么它就是过拟合的。理解这一定义是后续讨论如何避免和解决过拟合问题的基础。
机器学习:第2课:训练集与测试集分割

在本节课中,我们将学习如何将数据集分割为训练集和测试集,这是评估模型性能的关键步骤。我们将探讨分割的原则、权衡以及一些实用的经验法则。

为了评估模型的性能,我们确实需要从完整数据集中划分出一个测试数据集。这就引出了一个问题:应如何考虑将数据划分为训练数据与测试数据?
用图示来说,我应该在这个蓝色区域(即训练集)中放入多少个数据点,又应该在这个粉色区域(即测试集)中放入多少个数据点?
如果我在训练集中放入的点太少,那么我将无法很好地估计我的模型,因此模型的预测性能显然会很差。
另一方面,如果我在测试集中放入的点太少,那将是对泛化误差的一个糟糕近似,因为它无法充分代表我在现实世界中可能遇到的各种情况。
将数据分割为训练集和测试集并没有完美的公式,但如果你能确定如何操作,一个通用的经验法则是:你只需要在测试集中放入足够多的点来很好地近似泛化误差,而将剩余的所有点都放入训练数据中。因为你希望在训练数据集中有尽可能多的点来学习一个好的模型,尤其是在处理非常复杂的模型时。
但正如我们之前所说,你仍然需要在测试集中有足够的点来分析拟合模型的性能。
以上讨论假设你有足够的数据来进行这种分割,以便在训练集和测试集中都留有足够的点。但如果情况并非如此,本课程后续将讨论其他方法,例如交叉验证。

本节课中,我们一起学习了数据集分割的重要性。我们了解到,需要在训练集和测试集之间取得平衡:训练集需要足够的数据来学习有效的模型,而测试集也需要足够的数据来可靠地评估模型的泛化能力。当数据量不足时,可以考虑使用交叉验证等其他方法。
机器学习:第2课:不可约误差与偏差


在本节课中,我们将学习预测误差的三个主要来源:噪声、偏差和方差。我们将首先理解什么是不可约误差,然后深入探讨偏差的概念,并直观地理解它如何影响我们的模型预测。
概述
当我们构建预测模型时,预测值与真实值之间的误差并非凭空产生。它主要来源于三个方面:数据中固有的噪声、模型本身因过于简单而导致的偏差,以及模型对训练数据随机波动的敏感性所导致的方差。本节我们将重点讨论噪声和偏差,理解它们为何产生以及如何影响我们的预测。
噪声:不可约误差
上一节我们介绍了不同的误差衡量方式。本节中,我们来看看误差的来源。首先,让我们认识第一个误差来源——噪声。
数据本身具有固有的噪声。世界运行的方式是,在房屋面积(X)和房价(Y)之间,或者说在一般的X和Y之间,存在某种真实的关系。我们用 F_w_true 这个函数来表示这种由世界定义的任意关系。但这并非X和Y之间完美的描述。除了面积,还有许多其他因素影响房价,例如房屋的其他属性、购房者的个人感受、与房主的关系等。这些我们无法仅通过一个函数完美捕捉的因素,就是过程中的固有噪声,我们用 ε 来表示。
具体来说,对于任何一个观测值 Y_i,它都是真实关系与针对该房屋的特定噪声项 ε_i 之和:
Y_i = F_w_true(x_i) + ε_i
我们之前假设这个噪声的均值为零(否则其均值部分可以被并入F函数中)。但我们尚未讨论的是这个噪声的离散程度,即在任何给定的房屋面积下,基于这种观测中固有的噪声,我们可能看到的房价波动范围。这被称为噪声项 ε 的方差。
这是数据本身的一种属性。我们无法控制它,它与我们选择的模型或估计方法无关,是我们必须处理的问题。因此,这被称为不可约误差,因为我们无法通过选择更好的模型或估计方法来减少它。
偏差:模型的固有限制
既然噪声是我们无法控制的,那么我们可以控制的就是偏差和方差。接下来,让我们重点讨论偏差。
偏差本质上评估的是我们的模型平均而言拟合X和Y之间真实关系的能力。为了理解这一点,让我们思考数据是如何获得的。
我们观测到的数据点,只是已售出并被记录在案的N个房屋的一个随机快照。基于这些数据,我们拟合出一个函数。为了直观理解偏差,我们从最简单的模型——常数函数(例如,用所有房屋的平均房价来预测)开始思考。
如果我们观测到的是另一组N个已售房屋呢?那么我们就会得到一个不同的数据集,当我们去拟合模型时,就会得到一条不同的(水平)线。
为了更明确地说明这一点,请看示意图。在左侧数据集中,我倾向于绘制一些位于真实关系线之下的点(即数据中的房屋价格恰巧低于世界定义的典型值)。在右侧数据集中,我绘制了倾向于位于线上方的点。这是两个差异极大的数据集,但你会发现,拟合出的(水平)线却非常相似。这一点我们稍后会再次提到。
现在回到偏差的概念。我们所说的是,在所有可能出现的、大小为N的房屋销售数据集中,我们期望得到的拟合结果平均来看是什么样子。对于一个数据集,我们得到一条拟合线;对于另一个数据集,我们得到另一条拟合线。当然,存在一系列我们可能得到的拟合结果。对于所有这些可能的拟合,图中绿色的虚线代表了我们的平均拟合,即对所有拟合结果按其出现的可能性进行加权平均。
现在我们可以定义偏差了。偏差就是这个平均拟合与真实函数 F_true 之间的差异。在图中,这表现为灰色阴影区域,即真实函数与我们平均拟合线之间的差距。
直观地说,偏差衡量的是:我们的模型是否足够灵活,能够平均而言捕捉到房屋面积与房价之间的真实关系?我们看到,对于这个非常简单的、低复杂度的常数模型,它具有高偏差。它不够灵活,无法很好地近似真实关系。
由于这种差异,由于这种偏差,导致了我们预测中的误差。
总结
本节课我们一起学习了预测误差的两个重要来源。首先,我们认识了不可约误差(噪声),它源于数据生成过程本身固有的随机性,是我们无法通过改进模型来消除的。接着,我们深入探讨了偏差,它反映了模型由于过于简单(例如假设房价与面积无关)而无法捕捉数据真实关系的固有限制。高偏差的模型会导致系统性的预测误差。

理解这些概念是迈向构建更好模型的第一步。在接下来的章节中,我们将探讨误差的第三个来源——方差,并学习如何在偏差和方差之间进行权衡,这就是著名的偏差-方差权衡。
机器学习:第2课:方差与偏差-方差权衡

在本节课中,我们将学习机器学习模型评估中的两个核心概念:方差和偏差-方差权衡。理解这两者对于选择合适复杂度的模型至关重要。
方差的概念
上一节我们介绍了偏差,它衡量了模型预测的平均值与真实值之间的差距。本节中,我们来看看方差。
方差描述的是:对于不同的训练数据集,模型拟合出的具体结果之间差异有多大。换句话说,它衡量了模型预测的稳定性。
- 以一个简单的常数模型为例。即使数据点随机分布在真实关系线的上方或下方,模型拟合出的结果(一条水平线)变化并不大。这意味着该模型的预测在不同数据集上相当稳定。
- 当我们观察所有可能数据集的拟合结果时,会发现这些拟合线彼此非常相似。因此,这个低复杂度模型的方差很低。
总结来说,方差衡量的是模型拟合结果的波动程度。如果模型预测因训练数据的不同而产生剧烈变化,那么预测就会非常不稳定,这将成为预测误差的一个来源。
高复杂度模型的方差
为了更直观地理解,让我们观察高复杂度模型的情况。
- 再次观察同一个数据集,这次我们用一个高阶多项式来拟合,得到一条如示例所示的复杂曲线。
- 现在,保持数据集主体不变,仅轻微移动其中的两个数据点(例如图中标为粉色的点)。
- 尽管数据变动不大,但得到的拟合曲线却发生了戏剧性的变化。
这意味着,当我们考虑所有可能的数据集时,可能会得到一系列形状迥异、非常“疯狂”的曲线。虽然所有这些曲线的平均可能是一条相对平滑、合理的曲线(因为剧烈波动的部分在平均过程中被抵消了),但不同拟合曲线之间的差异(即方差)确实非常大。
因此,高复杂度模型具有高方差。


偏差-方差权衡
现在,我们可以将偏差和方差放在一起讨论,形成偏差-方差权衡的概念。
以下是偏差和方差随模型复杂度变化的趋势:
- 偏差:随着模型复杂度增加,模型能越来越精确地逼近X和Y之间的真实关系,因此偏差会减小。高复杂度模型具有低偏差。
- 方差:随着模型复杂度增加,模型对训练数据的变化变得极其敏感,因此方差会增大。高复杂度模型具有高方差。
一种总结这种权衡关系的方法是使用均方误差。均方误差可以近似分解为偏差的平方加上方差:
MSE ≈ Bias² + Variance
机器学习在很大程度上就是在处理这种偏差与方差之间的权衡。我们的目标是找到一个“最佳平衡点”,即模型复杂度的一个甜区。在这个甜区,偏差和方差共同贡献的预测总误差达到最小。
重要说明:与泛化误差的关系
然而,就像我们无法直接计算泛化误差一样,我们也无法精确计算偏差和方差,进而无法精确计算均方误差。
原因在于:
- 偏差的定义明确依赖于我们未知的“真实函数”。
- 方差和偏差的计算都需要对所有可能的数据集(从世界中抽取的、大小为N的所有样本)进行平均,而这在现实中是无法做到的。
尽管无法精确计算,但在本课程后续内容中,我们将学习如何在实践中优化这种偏差-方差的权衡,以构建更好的模型。
总结

本节课中,我们一起学习了:
- 方差:衡量模型预测对于不同训练数据的敏感度或稳定性。低复杂度模型方差低,高复杂度模型方差高。
- 偏差-方差权衡:模型复杂度存在一个内在的权衡。增加复杂度可以降低偏差,但会增大方差;降低复杂度可以减少方差,但会增加偏差。
- 目标:通过实践方法,寻找偏差与方差之间的最佳平衡点,以最小化模型的整体预测误差。
机器学习:第2课:误差与数据量的关系 📈

在本节课中,我们将探讨模型误差如何随着训练数据量的变化而变化。我们将重点关注在模型复杂度固定的前提下,真实误差与训练误差随数据点数量增加而呈现的不同趋势。
上一节我们介绍了偏差与方差的概念,本节中我们来看看当数据量变化时,它们如何影响我们的误差评估。
固定模型复杂度下的误差分析
首先需要明确,我们是在模型复杂度固定的条件下进行分析。这与之前观察误差随模型复杂度变化的情况不同。
真实误差(泛化误差)的趋势
让我们从观察真实误差(即泛化误差)开始。当训练数据点非常少时,我们拟合出的函数 ŵ 是对 x 和 y 之间真实关系的较差估计。因此,真实误差会相当高。
公式表示:
ŵ 无法从少量数据点中得到良好近似。
随着我们获得越来越多的数据,我们对模型的近似会越来越好,真实误差也随之下降。然而,这种下降存在一个极限。
这个极限就是模型的偏差加上数据中固有的噪声。因为即使我们拥有海量观测数据,并将模型拟合到极致,模型本身可能仍不够灵活,无法完全捕捉 x 和 y 之间的真实关系——这就是偏差的概念。此外,观测数据中的噪声也会贡献误差。
图示总结:
真实误差曲线从高点开始,随数据量增加而下降,最终趋于一个由 偏差 + 噪声 决定的平台。
训练误差的趋势
现在让我们看看训练误差。这个趋势可能看起来更令人惊讶。
训练误差的起点可能较低。但随着数据点越来越多,训练误差实际上会上升。这是因为我们保持模型复杂度固定:当数据点很少时,一个固定复杂度的模型可以相当好地拟合这些点。
代码示例(概念性描述):
# 当数据点少时,固定复杂度模型容易拟合(可能过拟合)
model.fit(few_data_points) # 训练误差低
# 当数据点多时,相同复杂度的模型无法完美拟合所有点
model.fit(many_data_points) # 训练误差升高
随着数据点不断增加,相同复杂度的模型无法期望完美拟合所有这些点。那么训练误差的极限是什么?
训练误差的极限与真实误差的极限完全相同。原因在于:当数据量趋于无穷时,训练集就包含了世界上所有可能的数据点。在此训练集上测量误差,其定义就等同于真实误差的定义。
因此,在数据量极大的极限情况下,两条曲线会收敛到同一点。这个收敛点同样由模型的偏差和数据固有的噪声决定。
核心结论:
在获取海量数据点的极限情况下,真实误差等于训练误差。
本课总结
在本节课中,我们一起学习了误差度量与训练数据量之间的关系。我们了解到:
- 在模型复杂度固定的前提下,真实误差随数据量增加而下降,并趋于由偏差和噪声决定的极限。
- 训练误差随数据量增加而上升,在数据量极大时与真实误差收敛于同一点。
- 无论我们拥有多少数据,由模型复杂度不足引起的偏差都是无法消除的。

至此,我们已经介绍了三种误差度量(训练误差、真实/泛化误差、测试误差)以及误差的三个来源(噪声、偏差、方差),并探讨了偏差与方差之间的权衡。在接下来的课程中,我们将以更形式化的方式深入探讨这些概念。
机器学习:第2课:正式定义三种误差来源 📊

在本节课中,我们将深入探讨机器学习模型预测误差的三个核心来源:噪声、偏差和方差。我们将以更正式、更技术性的方式定义这些概念,帮助你理解它们如何共同构成模型的总体预测误差。

概述
在前面的课程中,我们初步介绍了误差的三种来源。本节将提供一个更技术性的定义,使用数学形式化和统计理解来剖析这些概念。我们将看到,对于一个给定的目标输入点,其平均预测误差可以分解为三个明确的部分:噪声方差、偏差的平方和估计量的方差。
噪声方差 (σ²) 🎲
首先,我们来定义第一个误差项:噪声方差。
在现实世界中,我们假设特征 X(如房屋面积)和标签 Y(如房屋价值)之间存在一个真实但未知的关系,记作 f_w_true(x)。然而,我们的观测值 Y 并不仅仅由 X 决定,还受到其他无数未观测到或不可测量的因素影响。这些因素被统称为“噪声”。
我们通常将这种关系建模为:
Y = f_w_true(x) + ε
其中,ε 代表噪声项。我们假设噪声的期望值(均值)为零(E[ε] = 0),否则其非零部分可以被吸收到真实函数 f_w_true 中。噪声的方差(即其波动程度)被记为 σ²,也就是 Var(ε) = σ²。

核心概念:
- 公式:
Y = f_w_true(x) + ε,其中E[ε]=0,Var(ε)=σ² - 含义:
σ²代表了数据生成过程中固有的、不可消除的随机波动。

这个误差项被称为不可约误差,因为无论我们选择多么复杂的模型或先进的算法,都无法减少这部分由世界本身的不确定性带来的误差。
偏差的平方 (Bias²) 🎯
上一节我们介绍了无法控制的噪声,本节我们来看看模型本身的选择所带来的误差:偏差。
偏差衡量的是,我们平均拟合的函数与真实函数之间的差距。更正式地说,假设我们从真实的数据分布中随机抽取一个大小为 N 的训练集,并用它来训练我们的模型,得到一个具体的拟合函数 f_w_hat(x)。如果我们重复这个过程无数次(抽取无数个不同的训练集),就会得到无数个具体的拟合函数。
所有这些可能拟合函数的期望值(即平均函数),我们称之为平均拟合函数,记作 f_w_bar(x)。
核心概念:
- 公式:
Bias(x) = f_w_true(x) - f_w_bar(x) - 含义:在输入点
x处,偏差是真实函数值与所有可能模型平均预测值之间的差异。
偏差反映了模型系统性地偏离真实关系的能力。一个高偏差的模型(例如用直线去拟合曲线关系)可能过于简单,导致平均预测与真相相差甚远。在预测误差的分解中,我们使用的是偏差的平方 Bias(x)²。
方差 (Variance) 📈
现在,我们来看第三个误差来源:方差。它描述的是模型对于训练数据随机波动的敏感程度。
方差衡量的是,单个具体拟合函数 相对于 所有拟合函数的平均值(即 f_w_bar(x)) 的波动情况。换句话说,如果我们更换不同的训练数据集,模型的预测结果会发生多大的变化。
核心概念:
- 公式:
Variance(x) = E[ (f_w_hat(x) - f_w_bar(x))² ] - 含义:方差计算了在特定输入点
x处,模型预测值围绕其平均预测值的平均偏离程度(的平方)。这里的期望E是对所有可能的大小为N的训练集取的。
高方差意味着模型过于复杂,过度学习了训练数据中的噪声和随机细节(即“过拟合”)。因此,训练数据的微小变化会导致拟合出的函数发生巨大改变,使得预测不稳定。
误差分解公式 🧩
综合以上三个定义,对于一个给定的目标输入点 x_t,并使用平方误差作为损失函数时,模型的期望预测误差可以精确地分解为以下三项之和:
核心公式:
Expected Prediction Error(x_t) = σ² + Bias(x_t)² + Variance(x_t)
直观理解:
- σ² (噪声):这是数据的“天灾”,无法通过改进模型消除。
- Bias² (偏差):这是模型的“系统性错误”。如果平均预测就偏离真相,那么单个预测很难准确。
- Variance (方差):这是模型的“不稳定性”。即使平均预测很准,但具体到某次训练,结果可能因为数据采样噪声而上下波动,导致误差。
这个公式完美地解释了偏差-方差权衡:过于简单的模型偏差高、方差低;过于复杂的模型偏差低、方差高。我们的目标是在两者之间找到最佳平衡点,以最小化总体的期望预测误差。
总结
本节课中,我们一起学习了机器学习模型预测误差的三种正式技术定义:
- 噪声方差 (σ²):数据中固有的、不可约的随机误差。
- 偏差的平方 (Bias²):模型平均预测与真实值之间的系统性差距。
- 方差 (Variance):模型对于不同训练集的敏感性导致的预测波动。


理解这三者的构成与关系,是诊断模型问题、选择合适模型复杂度以及改进机器学习系统性能的基石。
机器学习(回归):第2课:正式推导三种误差来源的来源 🧮


在本节课中,我们将深入探讨机器学习回归模型中预测误差的三个来源:噪声方差(σ²)、偏差平方(Bias²) 和方差(Variance)。我们将通过严格的数学推导,解释为什么总预测误差可以分解为这三项之和。本教程旨在让初学者也能理解这一核心概念。
概述:预测误差的分解
我们首先回顾期望预测误差的定义,它是在所有可能训练集上平均的泛化误差。在特定输入点 Xt 并使用平方误差损失的假设下,我们将推导出期望预测误差的精确表达式:σ² + Bias² + Variance。
上一节我们介绍了三种误差来源的直观概念,本节中我们将通过正式推导来理解其数学本质。
期望预测误差的定义
我们从期望预测误差的正式定义开始。设训练数据集为 D_train,模型在 D_train 上训练得到的预测函数为 f_hat。对于固定的目标输入点 Xt,其对应的真实输出为 Yt。期望预测误差 EPE(Xt) 定义为:
EPE(Xt) = E_{D_train}[E_{Yt}[(Yt - f_hat(Xt))^2]]
这里,外层期望 E_{D_train} 是对所有可能训练集的平均,内层期望 E_{Yt} 是对在 Xt 处可能观测到的输出 Yt 的平均。我们假设真实关系为 Y = f(X) + ε,其中 ε 是均值为0、方差为 σ² 的噪声。
推导第一步:引入真实函数
为了分解误差,我们在平方误差项中同时加上和减去真实函数值 f(Xt):
EPE(Xt) = E_{D_train, Yt}[(Yt - f(Xt) + f(Xt) - f_hat(Xt))^2]
令 A = Yt - f(Xt), B = f(Xt) - f_hat(Xt)。根据期望的线性性质以及 E[(A+B)²] = E[A²] + 2E[AB] + E[B²],我们可以展开上式。
以下是展开后的各项分析:
- 第一项 E[A²]:此项为 E[(Yt - f(Xt))²]。由于 Yt - f(Xt) = ε,且噪声均值为0,方差为σ²,因此 E[ε²] = σ²。这一项代表了数据中固有的、不可约的噪声方差。
- 第二项 2E[AB]:此项为 2 * E[(Yt - f(Xt)) * (f(Xt) - f_hat(Xt))]。由于噪声 ε = Yt - f(Xt) 与模型预测 f_hat(Xt) 独立(噪声不依赖于模型),且 E[ε] = 0,因此该项等于 2 * E[ε] * E[f(Xt) - f_hat(Xt)] = 0。
- 第三项 E[B²]:此项为 E[(f(Xt) - f_hat(Xt))²]。它衡量了模型预测与真实函数之间的平均平方差异,我们称之为均方误差。
因此,我们得到:
EPE(Xt) = σ² + MSE(f_hat)
其中,MSE(f_hat) = E_{D_train}[(f(Xt) - f_hat(Xt))²]。
推导第二步:分解均方误差为偏差与方差
现在,我们需要分解 MSE(f_hat)。我们引入一个新量:在所有可能训练集上平均的模型预测,记作 f_bar(Xt) = E_{D_train}[f_hat(Xt)]。
同样,我们在 MSE 的表达式中同时加上和减去 f_bar(Xt):
MSE(f_hat) = E_{D_train}[(f(Xt) - f_bar(Xt) + f_bar(Xt) - f_hat(Xt))^2]
令 C = f(Xt) - f_bar(Xt), D = f_bar(Xt) - f_hat(Xt)。再次展开平方项:
MSE = E[C²] + 2E[CD] + E[D²]
以下是各项分析:
- 第一项 E[C²]:此项为 (f(Xt) - f_bar(Xt))²。注意,f(Xt) 和 f_bar(Xt) 都是固定值(不依赖于当前训练集 D_train),因此期望就是其本身。这衡量了真实函数与模型平均预测之间的差异,其平方正是偏差的平方:Bias² = (f(Xt) - f_bar(Xt))²。
- 第二项 2E[CD]:此项为 2 * (f(Xt) - f_bar(Xt)) * E_{D_train}[f_bar(Xt) - f_hat(Xt)]。因子 (f(Xt) - f_bar(Xt)) 是常数,可以提到期望外。而 E[f_bar(Xt) - f_hat(Xt)] = f_bar(Xt) - E[f_hat(Xt)] = f_bar(Xt) - f_bar(Xt) = 0。因此,整个第二项为 0。
- 第三项 E[D²]:此项为 E_{D_train}[(f_bar(Xt) - f_hat(Xt))²]。这衡量了单个模型预测 f_hat(Xt) 围绕其平均值 f_bar(Xt) 的波动程度,这正是方差的定义:Variance = E[(f_hat(Xt) - f_bar(Xt))²]。
因此,我们得到:
MSE(f_hat) = Bias² + Variance
最终结论:三种误差来源
将两步推导的结果结合,我们得到了著名的偏差-方差分解公式:
EPE(Xt) = σ² + Bias² + Variance
这个公式清晰地展示了在点 Xt 处的期望预测误差来源于三个部分:
- σ² (噪声方差):数据本身的随机噪声,无法通过改进模型消除。
- Bias² (偏差平方):模型平均预测与真实值之间的系统性差异,反映了模型本身的拟合能力。
- Variance (方差):模型对于不同训练数据的敏感度,反映了模型的稳定性。
总结


本节课中,我们一起学习了机器学习回归模型中预测误差的正式分解方法。我们从期望预测误差的定义出发,通过严谨的数学推导,证明了总误差可以分解为噪声方差、偏差平方和方差三项之和。理解这一分解有助于我们诊断模型问题:高偏差意味着模型欠拟合,高方差意味着模型过拟合,而噪声方差则是我们无法控制的固有不确定性。在后续课程中,我们将学习如何利用这一理论指导模型选择与优化。
机器学习:第2课:用于模型选择、拟合和评估的训练-验证-测试集分割


在本节课中,我们将要学习回归分析中两个至关重要的任务:选择模型复杂度和评估模型性能。通过讨论这两个任务,我们将引入一个核心概念——验证集,并学习如何通过分割数据集来避免评估偏差,从而获得对模型泛化能力的可靠估计。
选择模型复杂度与评估性能
上一节我们介绍了回归分析的基本概念,本节中我们来看看模型开发过程中的两个核心步骤。
在回归任务中,我们首先需要选择一个具体的模型复杂度。例如,在多项式回归中,我们需要确定多项式的阶数。其次,对于选定的模型,我们需要评估其性能。这两个步骤并非回归所独有,而是贯穿于机器学习的各个方面。
为了讨论方便,我们将模型复杂度选择问题形式化为选择一组调优参数,记为 λ。例如,λ 可以指定多项式回归的阶数。
一种天真的方法及其问题
首先,让我们讨论如何选择 λ。一种非常天真的方法是沿用之前介绍过的做法:将数据集分割为训练集和测试集。
以下是具体步骤:
- 对于每一个可能的 λ 值,在训练集上估计对应模型的参数。
- 将拟合好的模型在测试集上进行测试,计算测试误差。
- 在所有考虑的 λ 值中,选择在测试集上表现最好(即测试误差最小)的那个,记为 λ*。
现在,我们有了选定的模型(例如,确定了多项式阶数),接下来需要评估这个特定模型的性能。按照上述逻辑,我们会再次使用测试集,计算 λ* 模型的测试误差,并将其作为模型泛化误差的近似。
这个方法存在什么问题?它的评估结果会准确吗?
答案是否定的,这种方法会给出过于乐观的估计。这与我们之前讨论过的问题本质相同:数据被重复使用了。在选择模型复杂度 λ 时,我们已经利用了测试集来比较不同模型的性能,并选择了在测试集上表现最好的 λ。这相当于在测试集上“拟合”了调优参数 λ。因此,再用同一个测试集来评估最终模型的性能,其结果必然偏向于高估模型在全新数据上的表现,无法很好地泛化。
解决方案:引入验证集


那么,我们的解决方案是什么?我们可以创建两个独立的“测试”数据集。为了避免混淆,我们不把它们都称为测试集,而是将其中一个称为验证集。
具体做法是:将整个数据集分割成三个互斥的部分:
- 训练集
- 验证集
- 测试集
以下是使用这三个数据集的标准流程:
- 模型拟合:对于每一个考虑的模型复杂度 λ,我们总是在训练集上估计模型参数。
- 模型选择:对于每一个拟合好的模型,我们在验证集上评估其性能(计算验证误差)。我们选择在验证集上表现最好(验证误差最小)的模型复杂度,记为 λ*。
- 性能评估:最后,我们评估这个最终选定模型(参数在训练集上拟合,复杂度 λ* 由验证集选出)在测试集上的性能。此时得到的测试误差才是对模型泛化误差的合理近似,因为测试集在之前两个步骤中完全没有被使用过。
总结一下:
- 在训练集上拟合模型参数。
- 在验证集上评估不同模型并选择最优调优参数 λ*。
- 在测试集上评估最终模型的泛化性能。
数据集分割比例
一个自然的问题是:我们应该如何划分训练集、验证集和测试集的比例?这里没有一成不变的铁律,但有一些常见的经验分割比例。
以下是两种典型的分割方式:
- 80/10/10 分割:80% 数据用于训练,10% 用于验证,10% 用于测试。
- 50/25/25 分割:50% 数据用于训练,25% 用于验证,25% 用于测试。
选择哪种比例取决于一个关键前提:你有足够的数据。你需要确保训练集足够大以可靠地估计模型参数,验证集足够大以公平地比较不同模型的复杂度,测试集也足够大以提供对泛化误差的稳定估计。如果数据量不足,这种硬性的分割方式可能不再适用,我们将需要讨论其他方法(如交叉验证)来实现相同的目标。

本节课中我们一起学习了在机器学习中正确评估模型性能的关键方法。通过引入验证集,我们将数据集分为训练、验证、测试三部分,分别用于拟合模型、选择模型复杂度和最终性能评估,从而避免了因数据重复使用而产生的乐观偏差,获得了对模型泛化能力更可靠的估计。
机器学习:第2课:性能评估核心概念回顾 🧠

在本节课中,我们将回顾并总结机器学习性能评估的核心概念。这些概念不仅对回归任务至关重要,也是贯穿整个机器学习领域的基石。我们将学习损失函数、不同误差的定义、数据集的划分方法,以及如何选择模型复杂度。
损失函数与误差类型 📉
上一节我们介绍了模型评估的基本框架,本节中我们来看看其核心组成部分:损失函数与误差类型。
损失函数用于量化模型预测值与真实值之间的差异。我们讨论了多种损失函数的例子,例如平方误差损失。
平方误差损失公式:
L(y, ŷ) = (y - ŷ)²

在评估模型时,我们需要区分三种不同的误差概念:
- 训练误差:模型在训练数据集上计算出的平均损失。
- 泛化误差(真实误差):模型在整个数据分布(包括未见过的数据)上的期望损失。
- 测试误差:使用独立的测试数据集来近似估计的泛化误差。
为了同时完成模型参数拟合和泛化误差估计,我们需要将数据划分为训练集和测试集。
数据集划分与验证集 🧩
理解了误差类型后,我们需要一个系统的方法来管理数据,以进行可靠的评估。这涉及到数据集的划分。
以下是数据划分的核心步骤:
- 训练集:用于拟合模型参数。
- 测试集:在模型完全确定后,用于最终评估模型性能,近似泛化误差。测试集在训练过程中应保持“未见”状态。
然而,模型性能不仅取决于参数,还受模型复杂度(如多项式阶数)的影响。直接使用测试集来选择复杂度会导致对泛化误差的乐观估计。
为了解决这个问题,我们引入了验证集的概念。我们将数据分为三部分:
- 训练集:拟合模型参数。
- 验证集:用于选择模型复杂度、调整超参数。
- 测试集:用于最终性能报告。
这种方法确保了我们可以客观地选择模型,并在一个完全独立的数据集上评估其最终表现。
总结 📚
本节课中我们一起学习了机器学习性能评估的核心工作流程。
我们首先定义了损失函数,它是衡量预测好坏的量化工具。接着,我们区分了训练误差、泛化误差和测试误差这三种关键概念,并解释了为何需要将数据划分为训练集和测试集。

最后,我们探讨了模型复杂度选择这一关键步骤。通过引入验证集,我们构建了一个稳健的流程:使用训练集拟合参数,用验证集选择模型复杂度,最终在独立的测试集上评估模型性能。这套方法论是构建可靠机器学习模型的基础。
机器学习:第2课:多项式回归与过拟合症状 🧠

在本节课中,我们将学习多项式回归中过拟合的症状,并探讨如何通过观察模型系数的大小来识别过拟合。上一节我们介绍了高复杂度模型可能导致过拟合以及偏差-方差权衡的概念。本节中,我们来看看一个具体的定量指标,帮助我们判断模型是否过拟合。
回顾过拟合问题
在多项式回归的背景下,过拟合是一个常见问题。回忆一下,多项式回归模型的形式如下:

公式: y = w₀ + w₁x + w₂x² + ... + w_d x^d

如果我们用一个低阶多项式(例如二次多项式)拟合数据,可能会得到一条平滑的曲线,能够较好地捕捉数据的整体趋势。然而,当我们使用一个非常高阶的多项式时,模型会变得异常复杂,其拟合曲线可能会剧烈波动,穿过每一个训练数据点。
这种模型被称为高方差模型,我们称其为过拟合。因为它对训练数据的拟合过于“完美”,以至于捕捉到了数据中的噪声和随机波动,导致其在新数据上的泛化能力很差。
识别过拟合的定量指标
一个关键的问题是:是否存在某种定量指标,可以指示模型何时发生了过拟合?答案是肯定的。通过观察模型学习到的系数(权重),我们可以发现一个明显的规律。
以下是识别过拟合的关键观察:
当过拟合发生时,模型估计出的系数(w₁, w₂, ..., w_d)的绝对值往往会变得非常大。
为了理解这一点,我们可以思考:高阶多项式模型为了精确穿过每一个训练点,需要利用那些高次项(如 x^15, x^20)进行剧烈的调整。这些调整会体现在对应的高次项系数上,导致它们的值异常巨大。相反,一个泛化能力好的模型,其系数通常保持在相对合理、较小的范围内。
因此,系数的大小可以作为模型是否过拟合的一个警示信号。巨大的系数值往往意味着模型过于复杂,并可能对训练数据中的噪声进行了建模。
总结



本节课中我们一起学习了多项式回归中过拟合的症状。我们回顾了过拟合的概念,即模型在训练集上表现完美但在新数据上表现不佳。更重要的是,我们探讨了一个实用的定量识别方法:当过拟合发生时,模型的系数往往会爆炸性增长,变得非常大。这为我们后续引入正则化等技术来控制模型复杂度、防止过拟合奠定了基础。下一节,我们将学习一种名为“岭回归”的方法,它能够自动在偏差和方差之间进行权衡。
机器学习:第2课:过拟合演示 🧪

在本节课中,我们将通过一个具体的代码演示,直观地理解什么是过拟合。我们将生成一些数据,并拟合不同阶数的多项式模型,观察随着模型复杂度增加,会发生什么现象,特别是模型系数如何变化。
数据生成与可视化 📊
首先,我们需要导入必要的库,并生成用于演示的数据。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
我们创建30个观测点。对于每个x值,我们计算其正弦函数值作为真实趋势,然后添加一些随机噪声来模拟现实世界中带有噪声的观测数据。
np.random.seed(0)
n = 30
x = np.linspace(0, 2*np.pi, n)
y_true = np.sin(x)
y = y_true + np.random.normal(0, 0.3, n) # 添加噪声
data = pd.DataFrame({'X': x, 'y': y})
以下是生成数据的可视化结果。黑色圆点代表我们的观测值,它们大致遵循一个正弦曲线的趋势,但被噪声干扰。

多项式回归函数定义 ⚙️
上一节我们生成了数据,本节中我们来看看如何构建多项式回归模型。我们将定义几个辅助函数。
第一个函数用于创建多项式特征。它接收一个数据框和指定的多项式阶数 degree,然后生成 X 的1次方到 degree 次方的新列。
def polynomial_features(data, degree):
data = data.copy()
for deg in range(2, degree+1):
data[f'X^{deg}'] = data['X']**deg
return data
接下来是核心的回归函数。它使用线性回归来拟合多项式模型。目前,我们将L1和L2惩罚项都设置为零,这意味着我们使用的是普通最小二乘法。
from sklearn.linear_model import LinearRegression
def polynomial_regression(data, degree, l2_penalty=0, l1_penalty=0):
poly_data = polynomial_features(data, degree)
features = ['X'] + [f'X^{d}' for d in range(2, degree+1)]
model = LinearRegression()
model.fit(poly_data[features], data['y'])
return model, features
我们还需要函数来绘制拟合曲线,以及美观地打印多项式系数。
def plot_fit(model, features, data):
x_plot = np.linspace(data['X'].min(), data['X'].max(), 200)
X_plot = pd.DataFrame({'X': x_plot})
for f in features[1:]:
deg = int(f.split('^')[1])
X_plot[f] = X_plot['X']**deg
y_plot = model.predict(X_plot[features])
plt.scatter(data['X'], data['y'], color='black')
plt.plot(x_plot, y_plot, 'r-', linewidth=2)
plt.show()
def print_coefficients(model, features):
coeffs = model.coef_
intercept = model.intercept_
print(f"截距: {intercept:.4f}")
for feat, coef in zip(features, coeffs):
print(f"{feat}: {coef:.4f}")
拟合不同阶数的多项式 🔬
现在,让我们使用这些函数来拟合不同复杂度的模型,并观察结果。
拟合二阶多项式
首先,我们从简单的二阶多项式开始。
model_deg2, features_deg2 = polynomial_regression(data, degree=2)
print_coefficients(model_deg2, features_deg2)
plot_fit(model_deg2, features_deg2, data)
以下是二阶多项式的系数示例和拟合曲线。系数是相对较小的数字(例如0.5, -0.3),拟合曲线是一条平滑的抛物线,看起来能够合理地捕捉数据的整体趋势。

拟合四阶多项式
接下来,我们增加模型复杂度,拟合一个四阶多项式。
model_deg4, features_deg4 = polynomial_regression(data, degree=4)
print_coefficients(model_deg4, features_deg4)
plot_fit(model_deg4, features_deg4, data)
观察四阶模型,我们发现系数值开始变大(例如出现23.5, -15.2这样的值)。拟合曲线变得有些“波浪形”,但总体上仍然可以接受。
拟合十六阶多项式
最后,我们尝试拟合一个非常高阶的模型——十六阶多项式。请注意,我们只有30个数据点,却要估计17个参数(1个截距 + 16个系数)。
model_deg16, features_deg16 = polynomial_regression(data, degree=16)
print_coefficients(model_deg16, features_deg16)
plot_fit(model_deg16, features_deg16, data)
结果非常惊人。系数变得极其巨大(例如 2.583e6, -1.295e7)。拟合曲线极度扭曲和振荡,穿过了几乎所有数据点,但在数据点之间出现了不合理的剧烈波动。我们显然不会相信这是数据背后的真实规律。

核心结论与过渡 🎯
本节课中我们一起学习了过拟合的直观演示。我们从低阶多项式开始,逐步增加模型复杂度,并观察了模型系数和拟合曲线的变化。
通过这个演示,我们得到了一个关键结论:当过拟合发生时,模型的学习系数往往会变得异常巨大。模型试图用这些巨大的系数来“硬记”每一个数据点,包括其中的噪声,从而导致在未知数据上表现糟糕。
这个观察至关重要。它告诉我们,可以通过检查模型系数的大小来量化过拟合的程度。如果系数非常大,模型很可能过拟合了。这直接引出了我们下一课要学习的核心内容——正则化。
下一节我们将看到,如何通过给损失函数添加一个惩罚项,来限制系数的大小,从而防止过拟合。这种方法就是岭回归(Ridge Regression),它使用的正是 L2惩罚项。


总结:本节课我们通过代码演示,直观展示了过拟合现象。我们发现,随着多项式阶数增加,模型为了完美拟合训练数据(包括噪声),其系数会急剧膨胀,导致拟合曲线失去平滑性,泛化能力变差。控制系数大小是解决过拟合的一个关键思路。
机器学习:第2课:更一般的多元回归模型中的过拟合

在本节课中,我们将探讨过拟合问题,它不仅仅存在于多项式回归中,在包含大量输入特征的复杂多元回归模型中同样普遍存在。我们将分析过拟合如何与数据量及模型复杂度相关联,并理解为何在高维特征空间中避免过拟合尤为困难。
过拟合在复杂模型中的普遍性
上一节我们通过多项式回归演示了过拟合现象。然而,过拟合问题在更广泛的复杂模型中都可能出现,并非多项式回归所独有。
具体而言,当我们的模型包含大量输入特征时,同样会面临过拟合问题。例如,在房价预测数据中,如果我们拟合一个包含房屋面积、浴室数量、卧室数量、地块大小、建造年份等一长串可能特征的模型,这个高度灵活的模型就会遇到与多项式回归演示中相同的问题。

更一般地说,只要特征数量(用大写 D 表示)非常大,就可能出现过拟合。这些特征可以是原始输入的不同函数变换。当回归模型中包含了大量这些输入的函数时,模型就拥有了极大的灵活性来解释数据,从而容易变得过拟合。
数据量与模型复杂度的平衡
但是,模型复杂度增加导致的过拟合问题,实际上与我们拥有的数据量密切相关。接下来,我们将过拟合视为观测数据数量(n)以及输入特征数量(模型复杂度)的函数来讨论。
具体来说:
- 如果观测数据很少(n 很小),我们的模型会迅速对数据过拟合。因为我们只有少数几个数据点,随着模型复杂度(如多项式阶数)增加,模型可以轻易地穿过所有观测点,但在这些点之间,函数形态可能会变得非常怪异且不切实际。
- 另一方面,如果我们拥有海量的观测数据,即使模型真的非常复杂,也不会那么快出现过拟合。因为输入空间中被密集的观测数据所覆盖,函数在整个区域内基本上都被“固定”住了。在这个以房屋面积为输入的例子中,模型无法穿过每一个观测点,也就无法产生那些极其疯狂的、曲折的波动。
高维空间带来的挑战
另一方面,当我们仅有一个输入(例如房屋面积)时,为了避免过拟合,我们需要在该输入(面积)的取值范围内拥有密集的观测数据。也就是说,我们需要大量具有代表性的(面积,房价)配对样本。
实际上,要获得你可能见到的每一种可能面积的房屋的大量例子,这已经相当困难了。然而,当我增加模型中的输入特征数量时,这个问题会变得更加困难。
例如,考虑一个包含房屋面积和浴室数量的模型。为了提供具有代表性的样本并避免过拟合,我需要覆盖这两个输入所有可能的组合,这已经非常非常困难了。
现在,请想象一个包含房屋面积、浴室数量、卧室数量、地块大小、建造年份以及一长串特征的模型。如果你想覆盖所有这些特征所有可能出现的组合,这基本上是不可能完成的艰巨任务。因此,这是一个困难得多的问题,在这些情况下,你的模型更容易变得过拟合。
总结

本节课中,我们一起学习了过拟合在一般多元回归模型中的表现。我们认识到过拟合是模型复杂度和可用数据量之间不平衡的结果:数据不足时,复杂模型极易过拟合;而充足的数据可以在一定程度上约束复杂模型的行为。更重要的是,我们理解了随着特征维度(D)的增加,要获得能充分覆盖整个特征空间的代表性数据变得异常困难,这使得高维模型尤其容易受到过拟合的威胁。这为后续介绍正则化等应对过拟合的技术奠定了基础。
机器学习:第2课:平衡拟合与系数大小 ⚖️


在本节课中,我们将学习如何通过修改成本函数,来自动解决模型过拟合的问题。我们将引入一个平衡模型拟合优度与模型复杂度的新方法。
概述
上一节我们讨论了过拟合问题,即模型在训练数据上表现很好,但在新数据上表现不佳。本节中,我们来看看如何通过修改成本函数来避免过拟合。核心思想是,在衡量模型好坏时,不仅要看它对数据的拟合程度,还要考虑模型本身的复杂度,特别是回归系数的大小。
修改成本函数
我们之前衡量模型质量的指标,只依赖于预测房价与实际房价之间的差异,具体使用的是残差平方和。现在,我们将修改这个质量指标,使其同时考虑模型复杂度的度量,目的是偏向于更简单的模型。
定义这个修改后的成本函数时,我们需要在函数对数据的拟合程度与模型复杂度(或潜在过拟合程度)的度量之间取得平衡。那么,什么可以作为复杂度的指标呢?答案是:我们估计的系数的大小。
因此,我们要平衡的是模型对数据的拟合度与模型系数的大小。我们可以写出一个包含这两项的总成本,其中一项是我们新的拟合质量度量。
这里所说的“拟合度量”,数值越小表示对数据的拟合越好。另一方面,“系数大小度量”,如果数值小,则意味着系数的大小很小,我们不太可能处于一个严重过拟合的模型中。
显然,我们需要在这两个度量之间取得平衡。因为如果我只优化系数大小,我会将所有系数设为零,这当然不会过拟合,但也不能很好地拟合数据,这将是一个高偏差的解。另一方面,如果我只专注于优化拟合度量,那就是我们之前所做的,在面对复杂模型时容易导致过拟合。因此,我们需要在这两项之间进行权衡。
拟合度量:残差平方和
我们当前的拟合度量是残差平方和,公式如下:
RSS(w) = Σ (yi - ŷi)^2
其中,ŷi 是使用参数向量 w 的模型做出的预测值。有时我们也写作:
RSS(w) = Σ (yi - f(xi))^2
请记住,残差平方和越小,表明模型对训练数据的拟合越好。正如上一张幻灯片所说,对于拟合度量,数值小表示拟合好。
系数大小度量
现在我们需要一个系数大小的度量。什么汇总数字可以表示回归系数的大小呢?你可能会想直接对所有系数求和。
但这在很多时候并不是一个好的度量,因为你可能会遇到这样的情况:假设 w0 = 1527301,w1 = -1605253。如果模型中只有这两个系数,那么 w0 + w1 会是一个很小的数,尽管每个系数本身都很大。
你可能会说,我知道如何解决,我可以看绝对值。也许我会看:
|w0| + |w1| + ... + |wD|
这可以紧凑地写为 Σ |wj|,其中 j 从 0 到特征数量 D。这被定义为系数向量 w 的 L1 范数,记作 ||w||₁。
这是一个非常合理的选择,我们将在下一个模块中详细讨论。但现在,我们将考虑另一种度量:系数平方和。
即 w0² + w1² + ... + wD²,也就是 Σ wj²。这被定义为 L2 范数的平方,记作 ||w||₂²。这将是本模块的重点。
总成本函数
总结一下,我们的总成本是拟合度量与系数大小度量的和。我们说过,拟合度量是残差平方和,而本模块中系数大小的度量将是系数向量 w 的 L2 范数的平方。
因此,新的总成本函数可以表示为:
总成本(w) = RSS(w) + λ * ||w||₂²
其中,λ 是一个控制两项权重的超参数。
总结

本节课中,我们一起学习了如何通过修改成本函数来平衡模型的拟合优度与复杂度,从而对抗过拟合。我们引入了残差平方和作为拟合度量,并引入了系数向量的 L2 范数平方作为复杂度惩罚项。通过在这两者之间进行权衡,我们可以引导模型找到既不过于简单(高偏差)也不过于复杂(高方差)的解决方案。在接下来的课程中,我们将深入探讨基于这个新成本函数的具体优化方法。
机器学习:第2课:岭回归目标及其极端解

在本节课中,我们将学习岭回归的目标函数,并探讨当调整参数λ取极端值(0和无穷大)时,模型解的变化情况。理解这些极端情况有助于我们把握岭回归在模型拟合与复杂度控制之间的权衡机制。
岭回归的目标函数
上一节我们介绍了普通最小二乘法。本节中,我们来看看如何通过修改目标函数来控制模型复杂度。
岭回归的目标是寻找一个参数向量 W,使其最小化以下目标函数:
目标函数 = 残差平方和 + λ × ||W||₂²
其中:
- 残差平方和 衡量模型对数据的拟合程度。
- ||W||₂² 是参数向量 W 的L2范数的平方,用于衡量模型复杂度(系数的大小)。
- λ 是一个调整参数,用于平衡“拟合优度”和“模型复杂度”这两项。
我们得到的解记为 Ŵ,即我们估计的模型参数。
调整参数λ的极端情况
接下来,我们分析当调整参数λ取两个极端值时,岭回归的解会如何变化。
情况一:λ = 0
当λ被设置为0时,目标函数中的模型复杂度项完全消失。
目标函数简化为:最小化残差平方和
这与我们之前普通最小二乘法的目标完全一致。因此,此时的解 Ŵ 就是最小二乘解,我们将其记为 Ŵ^(LS)。
情况二:λ → ∞
当λ被设置为一个趋近于无穷大的值时,模型复杂度项在目标函数中占据绝对主导地位。
以下是分析过程:
- 对于任何 Ŵ ≠ 0 的解,其总代价为:(某个非零值 × ∞)+ 残差平方和 = ∞。
- 对于 Ŵ = 0 的解,其总代价为:0 × ∞ + 残差平方和(0) = 某个有限值。
因此,为了最小化总代价,最优解必然是让所有系数为零,即 Ŵ = 0。这相当于一个最简单的模型:y = ε(只有噪声项)。
小结与过渡
我们刚刚看到,λ控制着解在“完全拟合数据的最小二乘解”和“极度简化的零系数模型”之间移动。
在实际应用中,我们通常选择λ为一个介于0和无穷大之间的值。在这种情况下,我们估计出的系数向量 Ŵ 的L2范数将满足以下关系:
0 ≤ ||Ŵ||₂ ≤ ||Ŵ^(LS)||₂
这意味着岭回归的解的幅度(复杂度)将小于或等于最小二乘解,但大于等于零。我们正是通过选择恰当的λ值,在这两个极端之间进行折衷,以期获得泛化能力更好的模型。

最后需要指出,这种在目标函数中加入参数L2范数平方项以约束解的方法,被称为岭回归或L2正则化。在后续内容中,我们将更深入地探讨正则化的概念。
机器学习:第2课:岭回归如何平衡偏差和方差 📈

在本节课中,我们将学习岭回归如何通过一个称为 λ 的调优参数,在模型的偏差和方差之间进行权衡。我们将看到,调整 λ 的值可以控制模型的复杂度,从而帮助缓解过拟合问题。
上一节我们介绍了岭回归的基本概念,本节中我们来看看它在偏差-方差权衡中的具体作用。
当 λ 值非常大时,我们得到的解具有高偏差但低方差。一种理解方式是,当 λ 趋近于无穷大时,所有系数都会收缩至零。这显然是一个高偏差的模型,因为它忽略了数据中的所有关系。同时,它的方差极低,因为无论输入什么数据,模型预测结果始终相同。
另一方面,当 λ 值非常小时,我们得到的模型具有低偏差但高方差。考虑将 λ 设置为零的情况,此时岭回归退化为普通的最小二乘法,即最小化残差平方和(RSS)。对于高复杂度模型,这种方法通常会导致低偏差(对训练数据拟合得很好),但方差很高(对训练数据中的微小变化非常敏感)。
因此,λ 这个调优参数控制了模型的复杂度,并管理着这种偏差-方差的权衡关系。
接下来,让我们回到多项式回归的演示中,但这次使用岭回归,看看在改变 λ 的选择时,我们是否能改善过拟合问题。
我们将探索几个不同 λ 值下的岭回归解。
以下是不同 λ 值对应的模型表现示意图:




本节课中我们一起学习了岭回归的核心机制。我们了解到,通过调整正则化参数 λ,我们可以在模型的偏差(欠拟合)和方差(过拟合)之间找到一个平衡点。λ 值越大,模型越简单(高偏差,低方差);λ 值越小,模型越复杂(低偏差,高方差)。选择合适的 λ 是构建一个泛化能力良好模型的关键。
机器学习:第2课:岭回归演示 🧪

在本节课中,我们将学习岭回归(Ridge Regression)的核心概念,并通过一个多项式回归的演示,直观地理解如何通过调整正则化参数(λ)来平衡模型的拟合程度与复杂度。我们将看到,当λ值过小时,模型会过拟合;当λ值过大时,模型会欠拟合;而通过交叉验证技术,我们可以自动选择一个合适的λ值,以获得最佳的预测性能。
回顾最小二乘法
上一节我们介绍了多项式回归。现在,让我们快速回顾一下使用普通最小二乘法(OLS)进行拟合的情况。
我们有一组由S形函数生成的数据。当我们用2阶多项式拟合时,结果看起来相当合理。使用4阶多项式时,拟合曲线开始变得有些波动,估计的系数值也变大了。而当我们使用16阶多项式时,拟合曲线变得非常曲折,并且产生了巨大的系数值。

引入岭回归
本节中,我们来看看如何将普通多项式回归修改为岭回归。使用GraphLab Create库实现这一点非常简单,因为linear_regression函数自带一个L2惩罚项(正则化项)的参数。
在之前进行最小二乘估计时,我们将这个L2惩罚参数设置为零。这个参数正是我们之前讨论的,用于权衡拟合优度与模型复杂度的λ值。现在,为了实现岭回归,我们只需要为这个惩罚参数指定一个非零值。
以下是实现多项式岭回归函数的核心代码修改部分:
# 最小二乘法(λ=0)
model_ols = graphlab.linear_regression.create(features, target, l2_penalty=0)
# 岭回归(λ>0)
model_ridge = graphlab.linear_regression.create(features, target, l2_penalty=lambda_value)
在本课程的作业中,你将有机会自己动手实现这些方法。
探索不同λ值的影响
接下来,我们将用这个16阶多项式模型进行岭回归拟合,并观察不同λ值对结果的影响。
极小的λ值(λ = 1e-25)
首先,我们考虑一个非常小的λ值,即对系数向量的L2范数施加的惩罚非常轻微。
我们预计此时的拟合结果会与标准最小二乘法的情况非常相似。查看绘图结果证实了这一点:拟合曲线与之前OLS的拟合曲线几乎完全相同,系数也仍然是那些巨大的数值。这与我们的预期相符。
极大的λ值(λ = 100)
接着,我们考虑一个非常大的L2惩罚,这里设置λ为100。
在这种情况下,我们得到的系数变得非常小。拟合曲线变得非常平滑,甚至近乎一条直线,这显然过于简单,无法捕捉数据中先上升后下降的趋势,出现了欠拟合。
这验证了我们的理论:当λ极小时,解接近最小二乘解;当λ极大时,所有系数都趋向于零。
中间范围的λ值
现在,我们系统地观察λ值从1e-25逐步增加到100的过程中,拟合效果和系数的变化。
以下是不同λ值对应的系数大小和拟合曲线的变化趋势:
- λ = 1e-25: 系数极大,曲线极度曲折(过拟合)。
- λ = 1e-10: 系数值下降了约两个数量级,但仍很大。
- λ = 1e-6: 系数值降至百位量级,开始看起来更合理一些。
- λ = 1e-3: 拟合曲线看起来相当不错,尤其在数据密集的中间区域。
- λ = 100: 系数极小,曲线过于平滑(欠拟合)。
在边界区域,由于观测数据稀少,很难控制拟合行为,因此我们更应相信在X值范围内有大量观测数据的中间区域的拟合结果。
一个很自然的问题是:在这么多可能的λ值和对应的拟合模型中,我们应该选择哪一个来做出预测?
自动选择λ:留一法交叉验证
手动遍历大量λ值并凭经验判断显然效率低下。好消息是,存在自动选择λ值的方法,我们将在本模块后续内容中详细讨论。
其中一种方法叫做留一法交叉验证。这种方法通过近似最小化预测的平均均方误差,来为我们选择最优的λ值。
我们定义一个留一法交叉验证函数并将其应用于数据。目前你无需理解其具体实现,在本模块结束时,你将能够自己实现这个方法。它的核心思想是评估不同λ值下的预测误差,并选择误差最小的那个λ,而且它评估误差的方式非常特殊,既不是用训练集,也不是用简单的测试集或验证集。
应用该函数后,我们可以绘制出交叉验证误差随λ值变化的曲线。在本例中,曲线在某些区域相当平坦,这意味着在这些区域内拟合结果对λ的选择不敏感。但曲线存在一个明确的最低点,我们可以找到它。
以下是选择过程的核心步骤:
- 计算一系列λ值对应的留一法交叉验证误差。
- 选择误差最小的λ值。
- 使用该λ值重新拟合岭回归模型。
# 伪代码:选择最佳lambda
best_lambda = lambda_values[argmin(cross_validation_errors)]
model_best = graphlab.linear_regression.create(features, target, l2_penalty=best_lambda)
使用最佳λ值拟合后,我们得到了数量级非常合理(如1, 2, 5)的系数。其对应的拟合曲线在整个X范围的大部分区域内都呈现出良好的趋势。只有在边界处,由于缺乏数据约束,曲线表现仍有些不确定,但考虑到我们使用的是16阶多项式且系数已被收缩,这在意料之中。

总结

本节课中,我们一起学习了岭回归的实战应用。我们通过演示看到:
- λ的作用: λ控制着正则化的强度,过小导致过拟合,过大导致欠拟合。
- 自动调参: 留一法交叉验证是一种有效的自动选择最优λ值的方法,它帮助我们在偏差与方差之间取得平衡,从而获得泛化能力更佳的模型。
- 实践结果: 通过交叉验证选出的λ,我们成功用一个高阶多项式模型得到了平滑、合理且预测性能良好的拟合结果,避免了过拟合的陷阱。
机器学习:第2课:岭回归系数路径 📈

在本节课中,我们将学习岭回归中一个重要的可视化工具——系数路径。我们将看到,随着正则化参数 λ 的变化,模型系数是如何连续变化的,并理解这背后的含义。
上一节我们介绍了岭回归如何通过惩罚项来约束模型系数的大小。本节中,我们来看看当 λ 从 0 变化到无穷大时,这些系数具体是如何演变的。
系数路径的概念
系数路径图描绘了当 λ 从 0 逐渐增加到无穷大时,岭回归模型中每一个系数值的变化轨迹。
具体来说,我们之前分析过:
- 当 λ = 0 时,我们得到普通最小二乘解。
- 当 λ → ∞ 时,所有系数会趋近于 0。
- 在两者之间,我们会得到一系列不同的系数解。
房价预测案例的可视化
我们通过一个房价预测的例子来实验性地探索这一点。该模型使用了八个特征:
- 卧室数量
- 浴室数量
- 居住面积(平方英尺)
- 地块面积(平方英尺)
- 楼层数
- 建造年份
- 翻新年份
- 是否临水
为了绘制系数路径,我们首先对特征进行了归一化处理,使每个特征都具有单位范数。这样,所有系数的大小就大致处于同一数量级,便于在图中进行比较。
以下是绘制系数路径的步骤说明:
- 初始化:从 λ = 0 开始,计算对应的最小二乘解,得到每个特征的初始系数值。
- 迭代增加 λ:逐步增大 λ 的值。
- 求解新系数:对于每一个新的 λ 值,重新求解岭回归优化问题,得到一组新的系数。
- 绘制路径:将每个特征对应的系数值,按照 λ 增大的顺序连接起来,形成一条条曲线。
在生成的系数路径图中,我们可以看到:
- 最左侧(λ = 0)的每个点,代表最小二乘解
W_hat_least_squares。 - 随着 λ 向右(增大)移动,所有系数曲线都逐渐向 0 趋近。
- 图中存在一个特定的 λ* 值(对应某个垂直切片),它可能代表模型在偏差与方差之间取得最佳平衡的点,我们将在后续课程中讨论如何选择这个最优的 λ。
核心要点总结

本节课中,我们一起学习了岭回归的系数路径。
- 系数路径图直观展示了正则化强度 λ 如何影响每个特征的权重。
- 当 λ 为 0 时,模型退化为无正则化的线性回归。
- 当 λ 增大时,所有系数都被“压缩”并向 0 收缩。
- 理解系数路径有助于我们把握模型复杂度与正则化之间的关系,并为后续选择最优的 λ 值奠定基础。
机器学习:第2课:计算岭回归目标的梯度 🧮

在本节课中,我们将学习如何计算岭回归目标的梯度。岭回归通过在普通最小二乘法的目标函数中添加一个模型复杂度惩罚项(L2正则化)来防止过拟合。我们将首先回顾如何用矩阵形式表示岭回归的目标函数,然后详细推导其梯度,为后续寻找最优解(无论是通过闭式解还是梯度下降法)奠定基础。


上一节我们介绍了岭回归的目标函数,它由残差平方和与模型复杂度惩罚项两部分组成。本节中,我们来看看如何将这个目标函数用矩阵形式表示,并计算其梯度。
用矩阵形式表示目标函数
首先,我们假设已经给定了一个用于岭回归的正则化参数 λ 值。我们的目标是讨论如何从算法上拟合这个模型。
与之前多次操作类似,我们首先将目标函数用矩阵符号重写。假设我们有 N 个观测值,我们希望为所有 N 个观测值联合写出目标函数。
以下是残差平方和项的矩阵表示回顾。对于我们的模型,我们将所有 N 个观测值及其特征堆叠在一个大的绿色矩阵 H 中。该矩阵乘以我们的回归系数向量 w,然后加上每个观测值的加性噪声 ε。因此,我们将其矩阵形式写为:
y = Hw + ε
当我们构建残差平方和时,我们证明了它等价于以下形式:
(y - Hw)^T (y - Hw)
这就是我们残差平方和项的矩阵表示。
现在,我们需要为添加到原始目标函数中以得到岭回归目标的模型复杂度惩罚项,构建一个类似的矩阵表示。
模型复杂度惩罚项的矩阵表示


具体来说,我们希望用向量符号表示 ||w||₂²(即 w 的 L2 范数的平方)。我们说过,向量 w 的 L2 范数平方等于 w₀² + w₁² + w₂² + ... + w_d²。
这等价于取我们的 w 向量,将其转置(即写成行向量),然后乘以 w 向量本身。因为如果我们考虑进行这个乘法运算,我们将得到 w₀ × w₀ + w₁ × w₁ + w₂ × w₂,等等,这完全等价。因此,我们可以将其写为:
w^T w
这就是我们模型复杂度项的向量表示。
完整的岭回归目标函数
将两部分结合起来,对于 N 个观测值,岭回归的总成本可以写成如下形式:
J(w) = (y - Hw)^T (y - Hw) + λ w^T w
现在,我们有了这个目标函数,就可以像过去一样开始操作:计算梯度。我们可以考虑将梯度设为零以获得闭式解,或者执行梯度下降算法。接下来我们将逐步讲解这两种方法。
第一步是计算这个目标函数的梯度。
计算梯度
这里,我直接写出了上一张幻灯片的内容,但现在前面加上了梯度符号。正如我们之前所见,梯度在求和上是可分配的。因此,我们有第一项的梯度加上模型复杂度项的梯度。第一项是我们的拟合度量,即残差平方和项。
我们知道残差平方和的梯度具有以下形式:
∇[ (y - Hw)^T (y - Hw) ] = -2 H^T (y - Hw)
但问题是,这个模型复杂度项的梯度是什么?
我们看到,这个模型复杂度项的梯度是 2w。为什么是 2w 呢?与其在这里推导,我将其留作一个小的挑战。通过分别对每个 w 分量求偏导来推导是相当简单的:只需将 w^T w 写成 w₀² + w₁² + ... + w_d²,然后对其中一个 w 求导。
现在,我要做的是类比一维情况。如果 w 不是向量而是一个标量,那么 w^T w 就类似于 w²。而 w² 的导数是什么?是 2w。所以,这里是通过类比来证明。
因此,模型复杂度惩罚项 λ w^T w 的梯度是 2λw。
完整的梯度表达式
将两部分结合起来,岭回归目标函数 J(w) 的完整梯度为:
∇J(w) = -2 H^T (y - Hw) + 2λw
我们可以将其重写为:
∇J(w) = -2 H^T (y - Hw) + 2λw
这个表达式为我们提供了目标函数在任意点 w 的下降方向。在下一部分,我们可以将其设为零来求解最优的 w(闭式解),或者将其代入梯度下降的迭代更新公式中。

本节课中我们一起学习了如何用矩阵形式表示岭回归的目标函数,并详细推导了其梯度。我们回顾了残差平方和的矩阵表示,引入了模型复杂度惩罚项 λ w^T w 的向量表示,并通过类比一维情况,得出了其梯度为 2λw。最终,我们得到了完整的岭回归梯度表达式 ∇J(w) = -2 H^T (y - Hw) + 2λw,这是后续进行模型优化的关键一步。
机器学习:第2课:方法1:闭式解 🧮

在本节课中,我们将学习求解岭回归问题的第一种方法:闭式解。我们将通过设置梯度为零并求解权重向量 W 来得到解析解。首先,我们需要回顾一些线性代数的基础知识,特别是单位矩阵和矩阵逆的概念。
线性代数回顾:单位矩阵与矩阵逆
上一节我们介绍了岭回归的目标函数。在推导其闭式解之前,让我们先回顾一些关键的线性代数概念。
单位矩阵是数字“1”的矩阵类比。它可以定义在任何维度上。对于一个标量,单位就是1。对于一个矩阵,单位矩阵是一个方阵,其主对角线上的元素均为1,其余元素均为0。
以下是一些关于单位矩阵和矩阵逆的重要性质:
- 性质1:任何向量 V 乘以与其维度匹配的单位矩阵 I,结果仍是该向量本身。
- 公式: I * V = V
- 性质2:任何矩阵 A 乘以与其行数匹配的单位矩阵 I,结果仍是该矩阵本身。
- 公式: I * A = A
- 性质3:矩阵 A 的逆矩阵 A⁻¹ 满足以下关系(前提是 A 是可逆的方阵)。
- 公式: A⁻¹ * A = I 且 A * A⁻¹ = I
- 这类似于标量除法:a * (1/a) = 1。
理解这些性质将帮助我们简化后续的推导过程。
推导岭回归的闭式解
现在,我们回到岭回归的目标。我们的目标是找到使总成本函数 J(W) 最小的权重 W。为此,我们计算其梯度并令其等于零。
首先,我们利用单位矩阵的性质,将梯度表达式中的 W 改写为 I * W。这种写法是等价的,但能为后续的因式分解提供便利。
梯度表达式为:
∇J(W) = -2Hᵀy + 2HᵀH W + 2λ W
将其中的 W 替换为 I W 后,我们得到:
∇J(W) = -2Hᵀy + 2HᵀH W + 2λ I W
接下来,我们设置梯度等于零以求解最优的 Ŵ:
- 将等式两边同时除以2以简化:
-Hᵀy + HᵀH Ŵ + λ I Ŵ = 0 - 将包含 Hᵀy 的项移到等式右边:
HᵀH Ŵ + λ I Ŵ = Hᵀy - 注意到 Ŵ 在两个项中都出现,我们可以将其因式分解出来。这正是之前引入单位矩阵 I 的关键步骤:
(HᵀH + λ I) Ŵ = Hᵀy - 最后,为了解出 Ŵ,我们在等式两边同时左乘矩阵 (HᵀH + λ I) 的逆矩阵:
Ŵ = (HᵀH + λ I)⁻¹ Hᵀy
至此,我们得到了岭回归问题的闭式解。我们将其记为 Ŵ_Ridge,以强调它是针对特定正则化参数 λ 的岭回归解。
总结

本节课中,我们一起学习了求解岭回归问题的第一种方法——闭式解法。我们首先回顾了单位矩阵和矩阵逆的核心线性代数知识。然后,通过设置成本函数梯度为零,并巧妙地利用矩阵运算进行推导,最终得到了权重向量的解析解公式:Ŵ_Ridge = (HᵀH + λ I)⁻¹ Hᵀy。这个公式为我们提供了一种直接计算最优参数的方法。
机器学习:回归:第2课:岭回归的闭式解讨论 🧮

在本节课中,我们将深入探讨岭回归的闭式解。我们将分析其数学形式,理解正则化参数 λ 如何影响解,并将其与普通最小二乘法的解进行比较。我们还将讨论该解的计算特性及其在特征数量众多时的意义。
上一节我们介绍了岭回归的目标函数。本节中,我们来看看其闭式解 W_hat_Ridge 的具体形式及其性质。
W_hat_Ridge 的闭式解由以下公式给出:
W_hat_Ridge = (H^T * H + λ * I)^(-1) * H^T * Y
其中,H 是设计矩阵,Y 是目标值向量,λ 是正则化参数,I 是单位矩阵。
正则化参数 λ 的影响
现在,我们来探讨正则化参数 λ 取不同值时解的变化。
以下是两种极端情况的分析:
- 当
λ = 0时:公式简化为(H^T * H)^(-1) * H^T * Y。这正是我们熟悉的普通最小二乘法(OLS) 的解W_hat_least_squares。这验证了岭回归是普通最小二乘法的一个推广。 - 当
λ → ∞时:公式中的(H^T * H + λ * I)^(-1)项趋近于零矩阵,因为相当于除以无穷大(矩阵求逆是除法概念的类比)。因此,解W_hat_Ridge趋近于零向量。这意味着极强的正则化会迫使所有权重收缩至零。
通过这个闭式解,我们现在可以精确地计算 λ 在 0 到 ∞ 之间任意值时的解。
与最小二乘解的比较
让我们回顾一下之前关于最小二乘解 W_hat_least_squares 的讨论。
H^T * H 矩阵的可逆性通常要求观测数量 n 大于特征数量 d(更准确地说,是线性无关的观测数量大于特征数量)。其求逆的计算复杂度是 O(d^3),即与特征数量的立方成正比。
现在,考虑岭回归的解 W_hat_Ridge。其核心矩阵变为 H^T * H + λ * I。
当 λ > 0 时,即使观测数量少于特征数量(n < d),这个新矩阵也总是可逆的。这一点至关重要。
正则化的作用与计算考量
这引出了岭回归被称为正则化技术的原因。添加 λ * I 项使得 H^T * H 矩阵变得更“规则”(更稳定),从而保证了在各种情况下(包括特征很多的情况)都能求逆。正是这种“规则化”效应,使其得名“岭”回归。
然而,尽管保证了可逆性,求逆的计算复杂度仍然是 O(d^3)。在岭回归的典型应用场景中,我们往往处理具有大量特征(d 很大)的复杂模型。因此,直接计算这个闭式解在计算上可能非常昂贵,甚至不可行。

本节课中,我们一起学习了岭回归的闭式解。我们看到了正则化参数 λ 如何平滑地在最小二乘解和零解之间进行插值,并理解了 λ > 0 如何确保解始终存在,即使特征多于样本。最后,我们指出了直接计算闭式解在高维情况下的计算挑战,这为后续介绍更高效的优化方法(如梯度下降)做了铺垫。
机器学习:第2课:方法2:梯度下降

在本节课中,我们将学习如何使用梯度下降算法来求解岭回归问题。我们将看到,相比于可能计算量巨大的闭式解,梯度下降提供了一种更灵活、更易于实现的迭代求解方法,并且只需对标准最小二乘的梯度下降代码进行微小的修改。
岭回归的梯度下降更新规则
上一节我们介绍了岭回归的目标函数,它由残差平方和与模型复杂度惩罚项组成。本节中,我们来看看如何通过梯度下降来优化这个目标函数。
我们关注对第 j 个特征权重 W_j 的逐元素更新。总成本函数的梯度(作为提醒)如下所示。
更新规则是:我们取第 j 个特征的上一个权重 W_j^T,减去学习率 η(步长)乘以梯度指示的更新量,从而得到新的权重。
这个梯度由两部分组成:
- 第一部分来自残差平方和项,这与我们之前的标准最小二乘梯度相同。
- 第二部分是新增的项,它来自惩罚项
λ * ||w||^2对W_j的偏导数,即2λW_j。
我们发现 W_j^T 在两个地方出现,因此可以合并并简化这个表达式,使其更具可解释性。
简化后的更新规则表明,更新首先将 W_j^T 乘以 (1 - 2ηλ)。我们知道 η > 0 且 λ ≥ 0,因此 2ηλ 是一个正数。为了保证 (1 - 2ηλ) 是正数(从而起到收缩作用而非反向放大),我们要求 2ηλ < 1。
所以,(1 - 2ηλ) 是一个介于 0 和 1 之间的正数。这意味着在每次迭代中,我们首先将上一个系数值按这个比例进行收缩。
然后,我们再加上来自残差平方和项的更新量(与标准最小二乘相同)。我们可以将此称为 RSS更新项。
因此,岭回归的权重更新公式可以清晰地写为:
W_j^{new} = (1 - 2ηλ) * W_j^{old} + η * [RSS对W_j的梯度]
可视化更新过程:收缩与拟合
为了理解这个过程,让我们画一个简图。假设横轴是迭代次数,纵轴是系数 W_j 的大小。
在某个迭代 T,我们有一个系数值 W_j^T。岭回归引入了一个中间步骤:
- 收缩步骤:首先,我们将
W_j^T乘以(1 - 2ηλ),得到一个收缩后的系数值。这体现了模型复杂度惩罚项的作用:我们希望系数更小以避免过拟合。 - 拟合步骤:然后,我们考虑模型对数据的拟合情况,即加上 RSS 梯度项(可能是正或负)来调整这个收缩后的系数,最终得到
W_j^{T+1}。
相比之下,标准最小二乘的梯度下降(红色路径)没有这个收缩步骤。它直接从 W_j^T 出发,加上相同的 RSS 更新项,得到 W_j^{T+1}。
关键区别在于:岭回归在每次迭代中都“先收缩,再根据数据拟合调整”;而标准最小二乘“只根据数据拟合调整”。正是这个持续的收缩倾向,帮助岭回归控制了系数大小,从而缓解过拟合。
算法对比与代码实现
以下是标准最小二乘梯度下降算法的伪代码总结:
初始化权重向量 w
while 未收敛:
for j in 所有特征维度:
计算残差平方和对 w_j 的偏导数 (grad_rss)
w_j = w_j - η * grad_rss # 更新权重
现在,我们看看如何修改这段代码来实现岭回归。唯一的改变就在权重更新的那一行。
以下是岭回归梯度下降的伪代码:
初始化权重向量 w
while 未收敛:
for j in 所有特征维度:
计算残差平方和对 w_j 的偏导数 (grad_rss)
w_j = (1 - 2*η*λ) * w_j - η * grad_rss # 更新权重(注意符号合并)
注意,修改非常简单:在应用 RSS 梯度更新之前,先将旧的 w_j 乘以收缩因子 (1 - 2ηλ)。这是一个微不足道但至关重要的修改,使得给定一个 λ 值后,实现岭回归变得非常容易。
总结
本节课中,我们一起学习了:
- 岭回归的梯度下降更新规则:其核心是在标准最小二乘更新前,增加了一个系数收缩步骤
(1 - 2ηλ)。 - 更新的直观理解:收缩步骤对应于模型复杂度惩罚,它持续地将系数向零方向压缩;而 RSS 梯度项则致力于提高数据拟合度。两者在每次迭代中平衡。
- 算法实现:实现岭回归的梯度下降只需对标准最小二乘梯度下降代码进行一行修改,即在更新权重时乘以收缩因子,非常简单。

通过这种方法,我们可以高效地求解岭回归模型,即使在特征维度很高、闭式解计算困难的情况下也是如此。
机器学习:第2课:通过交叉验证选择调优参数 🎯


在本节课中,我们将学习一个关键问题:当数据量有限时,如何选择岭回归中的调优参数 λ。我们将重点介绍一种比简单的训练-验证-测试集划分更智能的方法——交叉验证。
上一节我们介绍了使用验证集来选择控制模型复杂度的调优参数。本节中,我们来看看当数据量不足以进行有效的三部分划分时,应该怎么办。
问题背景:数据量不足的挑战
我们假设从一个较小的数据集开始。与往常一样,我们需要预留一部分数据作为测试集,这部分数据在模型训练和验证过程中绝对不能使用。这样一来,可用于训练和模型验证的数据集就更小了。
那么,我们该如何进行呢?我们需要一种比简单地划分出一个验证集更聪明的方法。
简单验证集方法的局限性
让我们回顾一下简单的方法:在划分出测试集后,用剩余的数据定义一个验证集。问题是,当数据总量很小时,这个验证集必然只包含少量观测样本。这足以比较不同模型复杂度并评估哪个最佳吗?答案显然是否定的。一个小的验证集不能很好地代表我们可能遇到的数据分布。
更好的解决方案:交叉验证
既然我们只有这些数据,有什么更好的办法吗?我们是否必须用最后一部分观测数据来定义验证集?不,我可以用前几个观测值、下一组观测值或数据集中的任何随机子集。那么,应该使用哪个子集作为我的验证集呢?
关键的见解是:使用所有数据子集。因为这样做,你可以考虑在这些验证集上平均你的性能表现,从而避免对某个特定验证集选择的敏感性。一个只包含少量观测值的特定验证集可能会因为偶然性给出奇怪的结果,无法很好地评估不同模型复杂度之间的比较。
以下是交叉验证的核心思想:
- 将数据划分为K份:将训练数据(测试集已预留)随机、均匀地划分为K个部分(或“折”)。
- 迭代训练与验证:进行K次迭代。在每次迭代
i中:- 将第
i份数据作为验证集。 - 使用剩余的 K-1 份数据来训练模型。
- 在验证集上评估训练好的模型的性能(例如,计算误差)。
- 将第
- 汇总结果:计算K次验证误差的平均值,作为对特定 λ 值下模型性能的估计。
- 选择最佳参数:对多个候选的 λ 值重复上述过程,选择那个在交叉验证中平均验证误差最小的 λ。
- 最终评估:使用选定的最佳 λ,在整个训练集上重新训练最终模型,并在预留的测试集上进行最终性能评估。
这种方法的核心优势在于,它最大限度地利用了有限的数据进行模型选择和评估,减少了因单次数据划分带来的随机性影响。
总结


本节课中,我们一起学习了在数据量有限的情况下,如何通过交叉验证技术来选择岭回归(或其他模型)的调优参数 λ。我们认识到简单划分验证集的局限性,并掌握了交叉验证通过多次划分、训练和验证来更稳健地评估模型性能的基本流程。这是机器学习实践中一项非常重要且实用的技术。
机器学习:第2课:K折交叉验证 📊

在本节课中,我们将学习一种非常重要的机器学习技术——K折交叉验证。这种方法能帮助我们更有效地利用有限的数据来评估模型性能,并选择最佳的超参数(例如正则化强度λ)。我们将详细介绍其原理、步骤以及如何选择K值。
上一节我们讨论了将数据简单划分为训练集和验证集的方法。然而,这种方法可能无法充分利用所有数据,并且验证集的评估结果可能不稳定。本节中,我们来看看如何通过K折交叉验证来解决这些问题。
K折交叉验证的核心思想是:将全部数据集循环用作验证集,从而让每一份数据都参与到模型评估中。以下是其具体步骤。
数据预处理:划分K个块
首先,这是一个预处理步骤。我们将总数为 n 的观测数据,随机划分为 K 个不同的数据块。
- 每个数据块包含
n/K个观测值。 - 关键点在于,每个数据块中的观测值是随机分配的。
- 在整个算法过程中,我们将使用完全相同的划分方式,即每个观测值所属的块是固定的。
核心算法:循环验证与评估
接下来,对于每一个我们考虑的超参数值(例如λ),我们将执行以下循环过程。为简化说明,我们假设当前正在评估一个特定的λ值。
我们将循环遍历这K个数据块。在每一次循环中,我们将其中一个块视为验证集,并使用所有剩余的数据来拟合模型。
以下是针对一个特定λ值的详细步骤:
- 第一次迭代:将第一个数据块作为验证集。使用剩余的所有数据拟合模型,得到模型参数
W_hat_λ。然后,用该模型在第一个验证集上评估性能,计算出一个误差值,记为error_1(即针对此λ值,在第一个数据块上的误差)。 - 后续迭代:移动到下一个数据块,将其作为新的验证集。再次使用所有剩余数据拟合模型,并在第二个验证集上计算误差
error_2。 - 循环完成:重复此过程,直到每个数据块都轮流充当过一次验证集。最终,我们得到了此λ值在K个不同数据块上的K个误差值。
完成对所有K个块的循环后,我们计算此λ值的交叉验证误差。它非常简单,就是所有K个块上误差的平均值:
CV_Error(λ) = (error_1 + error_2 + ... + error_K) / K
现在可以清楚地看到,我们对特定λ值的误差度量,是通过对所有不同数据块上的验证集误差取平均得到的,从而利用了全部数据的信息。
选择最佳超参数
上述过程是针对一个λ值进行的。我们需要对考虑的所有λ值重复这一整个流程。
最终,我们选择那个能够最小化交叉验证误差的λ值作为最佳超参数。
如何选择K值?🤔
在运行K折交叉验证算法时,一个自然的问题是:K应该取多少?
理论上,当取 K = n(即数据总量)时,对模型泛化误差的近似是最好的。这意味着每个数据块只包含一个观测值,这种方法称为留一法交叉验证。
- 优点:能提供对泛化误差的最佳估计。
- 缺点:计算量非常大。因为对于每个λ值,我们都需要进行n次模型拟合。当n较大或模型本身拟合较复杂时,这会非常耗时。
因此,实践中人们通常使用 K = 5 或 K = 10,即五折或十折交叉验证。这在计算效率和估计准确性之间取得了良好的平衡。
本节课中我们一起学习了K折交叉验证算法。这是一个用于选择模型超参数(如正则化参数λ)的极其重要的算法。
尽管我们之前讨论了划分训练集、验证集和测试集的方法,但通常我们面临的情况是数据不足以进行如此清晰的划分,或者不确定划分后是否能准确估计泛化误差。因此,标准的做法是:保留一部分数据作为最终的测试集,然后使用留一法、五折或十折交叉验证等方法在剩余数据上选择超参数λ。

选择这些超参数以筛选出最佳模型,是机器学习工作流程中至关重要的一步,它直接关系到模型最终用于预测或完成各项任务的性能。
机器学习:第2课:如何处理截距

在本节课中,我们将要学习一个在岭回归中容易被忽略但相当重要的问题:如何处理模型中的截距项。我们将探讨为什么在惩罚项中包含截距可能不合理,并介绍两种处理此问题的实用方法。

上一节我们介绍了岭回归和交叉验证,但在讨论岭回归目标函数时,我们暂时搁置了一个重要议题。

回顾带截距的模型
首先,让我们回顾一下多元线性回归模型。模型通常表示为:
公式: y = w0 + w1*x1 + w2*x2 + ... + wd*xd
其中,w0 代表模型的截距。在特征矩阵 H 的表示中,与 w0 相乘的第一列特征通常被设置为常数 1,以便 w0 对每个观测值都起作用。
代码表示(构造设计矩阵 H):
# 假设已有特征矩阵 X (n x d)
import numpy as np
n = X.shape[0]
# 在 X 前添加一列全为1的向量,对应截距 w0
H = np.column_stack([np.ones(n), X])
因此,当模型中包含截距项时,我们的设计矩阵 H 具有一个特殊的结构。
岭回归目标函数中的截距问题
现在,让我们回到标准的岭回归目标函数:
公式: RSS(w) + λ * ||w||₂²
这里,||w||₂² 是权重向量 w 的 L2 范数平方,它包含了截距 w0。这意味着惩罚项也在鼓励 w0 变小。
但这里存在一个疑问:无论我们向模型中添加多少特征,我们真的希望截距项也变小吗?直觉上,惩罚截距项可能并不合理,因为截距的大小通常与模型的灵活性无关。
因此,我们需要思考如何解决这个问题。
方法一:不惩罚截距项
第一种解决方案是将截距 w0 从惩罚项中排除。我们可以修改目标函数,使其只惩罚 w0 之外的其他权重。
修改后的目标函数公式:
RSS(w0, w_rest) + λ * ||w_rest||₂²
其中,w_rest = [w1, w2, ..., wd]。
那么,在实践中如何实现呢?这会影响我们之前推导的闭式解和梯度下降算法。
对于闭式解,我们需要修改正则化矩阵。我们定义一个修改的单位矩阵 I_mod,其左上角(对应 w0 的位置)为 0,其余对角元素为 1。
代码表示(修改正则化矩阵):
d = X.shape[1] # 特征数量(不包括截距)
I_mod = np.eye(d+1) # 创建单位矩阵,尺寸为 (d+1) x (d+1)
I_mod[0, 0] = 0 # 将第一个对角元素(对应w0)设为0
# 岭回归闭式解变为:w = np.linalg.inv(H.T @ H + lambda * I_mod) @ H.T @ y
对于梯度下降算法,修改非常简单:在更新 w0 时,不使用收缩(即不使用正则化项),而更新其他权重时则应用岭回归的更新规则。
梯度下降更新规则伪代码:
对于每一次迭代:
# 更新截距 w0(使用普通最小二乘的梯度,无惩罚)
w0_new = w0_old - learning_rate * gradient_of_RSS_wrt_w0
# 更新其他权重 w_j(使用岭回归的梯度,包含惩罚)
对于 j 在 [1, d] 中:
w_j_new = w_j_old - learning_rate * (gradient_of_RSS_wrt_wj + 2*λ*w_j_old)
这样,我们就能在算法上轻松实现不惩罚截距项。
方法二:数据中心化
另一种完全合理的解决方案是对数据进行预处理,具体来说,是进行中心化。

其核心思想是:如果我们将目标变量 y 和特征 x 都中心化(即减去各自的均值),使得数据围绕零点分布,那么拟合出的截距 w0 自然会接近于零。在这种情况下,即使惩罚项包含了 w0,其影响也会大大减弱。
操作步骤如下:
- 第一步:计算
y的均值y_mean,并将所有y观测值转换为y_centered = y - y_mean。同样地,对每个特征xj计算均值并中心化。 - 第二步:对中心化后的数据
(y_centered, X_centered)运行标准的岭回归,无需再对截距做特殊处理。因为此时模型拟合的截距预期很小,惩罚它不再是一个大问题。
代码表示(数据预处理):
# 1. 中心化目标变量 y
y_mean = np.mean(y)
y_centered = y - y_mean
# 2. 中心化特征 X(对每一列)
X_mean = np.mean(X, axis=0)
X_centered = X - X_mean
# 3. 在中心化后的数据上运行标准岭回归(无需修改惩罚项)
# 注意:此时模型拟合的 w0 将代表中心化后的“截距”
这种方法通过数据变换巧妙地解决了问题,无需修改算法本身。
总结
本节课中,我们一起学习了如何处理岭回归中的截距项问题。我们认识到,不加区分地惩罚截距可能缺乏直观意义。为此,我们介绍了两种主要策略:
- 算法修改:明确地将截距
w0排除在岭回归的 L2 惩罚项之外,无论是通过修改闭式解中的正则化矩阵,还是在梯度下降中为w0设置特殊的更新规则。 - 数据预处理:通过对目标变量和特征进行中心化,使数据围绕零点分布,从而让截距自然趋近于零,这样即使惩罚截距,其影响也微乎其微。

这两种方法都是有效且常用的,你可以根据具体场景和编程便利性选择适合的一种。理解这一点有助于你更正确地应用岭回归,并解释其结果。
机器学习:第2课:岭回归核心概念回顾 🧠

在本节课中,我们将系统性地回顾岭回归的核心概念。岭回归是标准线性回归的一种正则化形式,它提供了一种直观且算法上直接的方法来处理大量特征。我们将探讨其动机、目标函数、拟合方法以及如何选择关键参数。
岭回归的动机与目标 🎯
上一节我们介绍了标准线性回归可能面临的过拟合问题。本节中,我们来看看岭回归如何通过惩罚系数的大小来解决这个问题。
过拟合模型往往具有非常大的系数。岭回归通过在其目标函数中引入一个惩罚项来限制系数的大小,从而在模型拟合与系数幅度之间进行权衡。其目标函数如下:
公式:
目标 = 最小化 [ RSS(w) + λ * Σ(wi²) ]
其中:
RSS(w)是残差平方和,衡量模型对数据的拟合程度。λ * Σ(wi²)是惩罚项(L2正则化),λ是控制惩罚力度的超参数。wi是模型系数(不包括截距项)。
这个公式清晰地表明,岭回归的目标是找到一个平衡点:既要让预测误差(RSS)小,又要让所有系数的平方和不过大。
模型拟合方法 ⚙️
理解了目标函数后,我们来看看如何实际求解岭回归模型。主要有两种方法。

以下是两种核心的拟合方法:
-
闭式解:对于岭回归,我们可以直接通过矩阵运算得到最优系数的解析解。公式为:
公式:w* = (XᵀX + λI)⁻¹ Xᵀy
其中I是单位矩阵。当特征数量非常多或XᵀX不可逆时,这个公式依然有效。 -
梯度下降:这是一种迭代优化算法。我们通过计算目标函数的梯度(导数),并沿梯度反方向逐步更新系数
w,直至收敛到最小值。这种方法适用于大规模数据集或在线学习场景。
选择正则化参数 λ 🔍
模型拟合依赖于参数 λ 的选择。λ 控制着正则化的强度:λ=0 时退化为普通线性回归;λ 很大时,所有系数会被严重压缩趋近于零。
为了选择最优的 λ,我们使用交叉验证方法。这个方法不仅适用于岭回归,也广泛适用于其他机器学习模型。
以下是交叉验证的基本步骤:
- 将训练数据分成若干份(例如5份)。
- 依次将其中一份作为验证集,其余作为训练集。
- 对于每个待选的
λ值,用训练集拟合模型,并在验证集上评估性能(如计算误差)。 - 对所有分割的结果取平均,得到每个
λ对应的平均性能。 - 选择平均性能最好(如验证误差最小)的那个
λ值作为最终参数。
处理截距项 📐
最后,我们讨论一个重要的细节:如何处理截距项(偏置项)。
在岭回归中,我们通常只对特征对应的系数 w 进行惩罚,而不惩罚截距项 w0。这是因为截距项代表目标变量的全局均值偏移,惩罚它可能使模型产生不必要的偏差。实际操作中,通常在计算惩罚项 Σ(wi²) 前,先将数据中心化(使每个特征均值为0),这样拟合出的模型自然就包含了正确的截距信息。
总结 📝

本节课中我们一起学习了岭回归的完整框架。我们从其动机开始——通过惩罚大系数来防止过拟合。然后,我们定义了岭回归的目标函数,它平衡了拟合优度与模型复杂度。接着,我们探讨了两种拟合方法:闭式解和梯度下降。为了找到最佳的正则化强度,我们介绍了交叉验证这一通用且强大的模型选择工具。最后,我们明确了截距项通常不被纳入正则化惩罚范围的处理方式。岭回归为我们提供了一种系统性的方法,来自动进行偏差-方差权衡,是处理高维数据的有力工具。
机器学习:第2课:特征选择任务 🎯

在本节课中,我们将要学习如何从一组特征中选择一部分来构建我们的模型。我们将首先介绍一种显式搜索所有可能模型的方法,然后描述一种类似于岭回归思想的、使用正则化回归进行隐式特征选择的方法。
为什么需要特征选择? 🤔
上一节我们介绍了特征选择的概念,本节中我们来看看为什么我们需要进行特征选择。主要有两个原因:效率和可解释性。
效率原因
假设一个问题有1000亿个特征。每次进行预测时,都需要计算特征向量与所有权重的乘积,这在计算上非常密集。相比之下,如果我们的权重是稀疏的(即许多权重为零),那么预测过程会高效得多,因为我们只需要对非零权重的特征进行求和。
可解释性原因
更常见的原因是为了可解释性。我们希望通过理解哪些特征与预测任务相关,来更好地解释模型。例如,在房价预测应用中,我们可能有许多特征,但并非所有特征都与房价评估真正相关。我们可能希望选择一个真正有代表性的特征子集。

另一个例子是“读心术”任务,我们希望通过大脑扫描图像预测情绪。我们可能希望找到与预测任务相关的大脑区域的小子集,这同样是为了可解释性。
显式特征选择方法 🔍
在了解了特征选择的重要性之后,本节中我们来看看如何进行特征选择。一种直接的方法是显式地搜索所有可能的特征组合。
搜索所有子集
最直接的方法是尝试所有可能的特征子集。对于一个有 D 个特征的问题,总共有 2^D 个子集。以下是评估每个子集的基本步骤:
- 对于每个特征子集
S(S是{1, 2, ..., D}的一个子集)。 - 仅使用子集
S中的特征来训练一个模型(例如线性回归模型)。 - 在验证集上评估该模型的性能(例如计算误差)。
- 选择在验证集上性能最好的那个特征子集。
这种方法可以保证找到最优的特征子集,但计算成本极高。当 D 很大时(例如 D=100,则有 2^100 个子集),这在计算上是不可行的。
隐式特征选择方法:正则化 🛡️
由于显式搜索所有子集的方法计算量过大,本节中我们介绍一种更实用的隐式特征选择方法:正则化。这种方法通过修改损失函数,鼓励模型使用更少的特征。
L2正则化(岭回归)
我们之前讨论的岭回归使用了L2正则化。它在损失函数中增加了所有权重平方和的惩罚项。其公式如下:
损失函数 = 误差平方和 + λ * Σ(权重_j²)
L2正则化会使权重变小,但通常不会将任何权重精确地设为零。因此,它实现了“收缩”效果,而非严格的特征选择。
L1正则化(Lasso回归)
为了实现特征选择,我们可以使用L1正则化,也称为Lasso回归。它在损失函数中增加的是权重的绝对值之和作为惩罚项。其公式如下:
损失函数 = 误差平方和 + λ * Σ|权重_j|
L1正则化的关键特性是,它倾向于产生稀疏解,即许多权重会被精确地设为零。那些权重为零的特征就被模型“选择”排除在外了。参数 λ 控制着正则化的强度:λ 越大,被置零的权重就越多,模型使用的特征就越少。
通过调整 λ,我们可以在模型的复杂度和稀疏性之间进行权衡,从而隐式地完成特征选择。
总结 📝


本节课中我们一起学习了特征选择的任务和方法。
- 我们首先讨论了进行特征选择的两个主要原因:提升计算效率和增强模型可解释性。
- 接着,我们介绍了一种显式方法,即搜索所有可能的特征子集,虽然它能找到最优解,但计算成本过高,不适用于特征数量多的情况。
- 最后,我们重点介绍了一种隐式方法,即通过正则化进行特征选择。特别是L1正则化(Lasso回归),它通过在损失函数中添加权重绝对值之和的惩罚项,能够自动将不重要的特征权重设为零,从而实现高效的特征选择。这种方法通过在模型训练中融入选择过程,避免了组合爆炸问题,是一种更实用的解决方案。
机器学习:第2课:特征选择之所有子集法

在本节课中,我们将学习一种特征选择方法——所有子集法。该方法通过评估包含不同特征组合的模型性能,来帮助我们为预测任务选择最合适的特征集。

特征选择任务
上一节我们讨论了特征选择的重要性。本节中,我们来看看如何具体执行特征选择任务。一个直观的方法是:搜索所有可能的特征组合,并评估每个组合对应模型的性能。这正是“所有子集”算法所做的事情。
所有子集算法详解
所有子集算法从一个不包含任何特征的模型开始。
初始模型:无特征
首先,考虑一个没有任何特征的模型。这意味着模型假设观测值仅仅是噪声。我们可以在训练数据上评估这个模型的性能,并得到一个训练误差值。
搜索单特征模型
接下来,算法会搜索所有仅包含一个特征的模型。例如,我们首先评估仅以“卧室数量”为特征的模型,并计算其训练误差。然后,我们依次评估仅以“浴室数量”、“居住面积”、“地块面积”等单个特征为输入的模型。完成对所有单特征模型的评估后,我们找出其中训练误差最小的模型。在这个例子中,表现最好的单特征模型是包含“居住面积”的模型。
以下是评估单特征模型的伪代码表示:
for feature in all_features:
model = train_model(training_data, [feature])
error = compute_training_error(model, training_data)
record_error(feature, error)
best_single_feature = feature_with_minimum_error
搜索双特征及更多特征的模型
然后,算法会继续搜索所有包含两个特征的模型组合。我们评估所有可能的双特征组合,并找出训练误差最小的那个。例如,最佳的双特征模型可能包含“卧室数量”和“浴室数量”。
需要强调的是,最佳的双特征模型不一定包含最佳单特征模型中的特征。例如,最佳单特征模型使用“居住面积”,而最佳双特征模型可能使用“卧室数量”和“浴室数量”。因此,大小为 k 的最佳模型不一定包含大小为 k-1 的最佳模型中的特征。
算法会以此类推,继续搜索所有包含三个、四个、五个……直至包含所有 D 个特征的模型。
选择最终模型
完成所有搜索后,我们会得到一条曲线,它连接了每个特征数量 k 下对应的最佳模型(即训练误差最小的模型)的性能点。
那么,我们应该选择哪个特征数量的最佳模型用于最终预测呢?根据课程知识,我们不能简单地选择训练误差最低的模型,因为随着模型复杂度(特征数量)增加,训练误差通常会持续下降,这从我们绘制的曲线中也可以看出。
因此,我们需要使用其他方法来在复杂度不同的模型间做出选择,这与本课程之前讨论过的模型选择原则一致。
以下是几种常见的选择方法:
- 验证集评估:如果有足够的数据,可以在独立的验证集上评估各个模型的性能,选择验证误差最小的模型。
- 交叉验证:使用交叉验证来更稳健地估计模型的泛化误差。
- 信息准则:使用如BIC(贝叶斯信息准则)等包含模型复杂度惩罚项的指标进行选择。
在本课程中,我们将重点关注基于验证集误差进行模型选择的方法。
总结


本节课中,我们一起学习了“所有子集”特征选择算法。该算法系统地评估了从零特征到全部特征的所有可能组合,并找出了每个特征数量下的最佳模型。最后,我们讨论了如何通过验证集误差、交叉验证或信息准则等方法,从这些最佳模型中选择出泛化能力最强的最终模型,避免因过度追求低训练误差而导致过拟合。
机器学习:第2课:所有子集算法的复杂度分析

在本节课中,我们将探讨“所有子集”算法在特征选择中的应用,并重点分析其计算复杂度。我们将了解为何随着特征数量的增加,该算法会变得不可行。
算法回顾与复杂度问题
上一节我们介绍了“所有子集”算法,它通过评估所有可能的特征组合来寻找最佳模型。本节中,我们来看看运行该算法需要评估多少个模型,即其计算复杂度。
该算法评估了从“仅噪声”模型(无任何特征)到包含所有特征的完整模型之间的每一个可能模型。为了量化模型总数,我们可以为每个被评估的模型分配一个特征向量。
特征向量的表示方法
以下是特征向量的定义方式:
- 我们为每个特征(从特征0到特征D)分配一个位置。
- 如果某个特征被包含在模型中,其对应位置的值设为 1。
- 如果某个特征未被包含在模型中,其对应位置的值设为 0。
因此,每个模型都对应一个长度为 D+1 的二进制向量。例如:
- “仅噪声”模型对应的向量为:
[0, 0, ..., 0] - 仅包含第一个特征的模型对应的向量为:
[1, 0, ..., 0]
计算模型总数
我们需要遍历所有可能的二进制特征向量。每个特征位置有两种选择(0或1)。由于有 D+1 个特征位置,因此需要评估的模型总数为:
公式: 2^(D+1)
这意味着模型数量随特征数量 D 呈指数级增长。
复杂度实例分析
以下是针对不同特征数量 D 的计算结果:
- D = 8:需评估
2^9 = 512个模型。这个数量或许可以接受。 - D = 30:需评估
2^31 ≈ 21.4亿个模型。数量变得非常庞大。 - D = 1000:需评估
2^1001 ≈ 1.07 * 10^301个模型。这个数字已经大到无法实际计算。 - D = 1000亿:需评估的模型数量是一个无法想象的天文数字。
结论

本节课中我们一起学习了“所有子集”算法的复杂度分析。我们可以看到,模型总数是特征数量的指数函数 2^(D+1)。对于现代应用中常见的成百上千甚至更多的特征,评估所有可能的子集在计算上是完全不可行的。因此,我们需要寻找更高效的特征选择方法。
机器学习:第2课:贪心算法


在本节课中,我们将学习一种在特征数量过多、无法穷举所有子集时,用于特征选择的次优但可行的算法——贪心算法。我们将详细介绍其工作原理、步骤、优缺点,并讨论如何确定停止添加特征的时机。
上一节我们介绍了穷举所有特征子集的方法,本节中我们来看看当特征数量庞大时,一种更实用的替代方案。
算法概述
贪心算法是一种迭代式的方法。它从一个初始特征集(通常是空集)开始,在每一步中,它都“贪婪地”选择当前能最大程度提升模型性能的单个特征加入模型,并重复此过程。
前向逐步选择算法
一种简单的贪心算法称为前向逐步选择算法。以下是其具体步骤:
首先,从一个初始特征集开始。通常从空集开始,也可以从已知必须包含的特征(例如常数项特征 h0)开始。
然后,执行以下迭代过程:
- 用当前的特征集拟合模型,得到回归系数的估计值。
- 搜索所有可能被加入的特征,选择一个能最大程度改善模型拟合效果的特征。衡量标准可以是训练误差,即选择那个能最大程度降低训练误差的特征。
- 将该特征纳入模型。
- 重复此过程:在已包含若干特征的模型基础上,继续搜索剩余特征,选择下一个能最大程度降低训练误差的特征。
算法流程可视化
为了理解贪心搜索与全子集搜索的差异,我们可以进行可视化对比。
在第一步,我们从空模型开始,这与全子集搜索的起点相同,对应的训练误差也相同。
接着,我们搜索所有特征,选择那个最能降低训练误差的特征。在只有一个特征的情况下,贪心算法找到的最佳特征与全子集搜索找到的最佳单特征模型结果相同。例如,在房价预测中,两者可能都会选择“房屋面积”作为第一个最佳特征。
但从第二步开始,情况可能开始分化。在贪心算法中,我们被强制保留已选的“房屋面积”特征,然后贪婪地搜索下一个最佳特征。此时,第二个被加入的特征可能是“翻新年份”。
然而,全子集搜索找到的最佳双特征模型可能是“卧室数量”和“卫生间数量”。这就是差异所在:一旦贪心算法固定了第一个特征,其后续选择可能无法达到全局最优的组合。
我们继续这个流程。在已有“房屋面积”和“翻新年份”后,下一个加入的特征可能是“是否临水”。这个过程会持续进行。
贪心算法与全子集搜索的解在何时会再次重合?显然,当模型包含所有特征时,两者必然相同,因为此时只有一个可能的模型。
关于这个贪心过程,有几点需要说明:
- 训练误差单调不增:从一次迭代到下一次迭代,训练误差永远不会增加。原因是,即使新加入的特征是无效的,我们总可以将其权重设为零,从而得到与之前完全相同的模型,训练误差保持不变。
- 最终收敛:最终,当使用所有特征时,训练误差会与全子集搜索的结果相同(也可能在此之前某个点相同)。
何时停止算法?
一个关键问题是:我们何时停止这个贪心过程?
- 当训练误差足够低时停止? 不。因为随着模型复杂度(特征数)增加,训练误差总会下降,这会导致我们选择过于复杂的模型。
- 当测试误差足够低时停止? 不。记住,在搜索模型复杂度或选择任何调优参数时,我们绝不能触碰测试数据。


正确的做法是使用验证集或交叉验证来选择停止贪心程序的时机。我们在验证集上评估每一步得到的模型性能,选择在验证集上表现最好的那个模型复杂度(即特征数量)。
总结

本节课中我们一起学习了贪心算法,特别是前向逐步选择法,作为一种高效的特征选择手段。我们了解了它通过迭代地添加当前最优特征来工作,虽然无法保证找到全局最优特征子集,但计算上可行。最重要的是,我们明确了必须依赖验证集或交叉验证,而不是训练误差或测试误差,来决定何时停止添加特征,以防止过拟合并选择泛化能力最佳的模型。
机器学习:第2课:贪心前向逐步算法复杂度分析

在本节课中,我们将要学习贪心前向逐步算法的计算复杂度,并将其与全子集选择法进行对比。我们还将探讨该算法的变体及其在特征选择中的应用。
算法复杂度分析
上一节我们介绍了贪心前向逐步算法的基本流程,本节中我们来看看它的计算复杂度。
假设我们总共有 D 个特征。在算法的第一步,我们需要评估 D 个模型(即考虑添加每一个特征)。在第二步,我们评估 D-1 个模型(考虑添加剩余的特征)。第三步评估 D-2 个模型,依此类推。
算法需要执行多少步?这取决于我们何时选择停止。但最多的情况下,我们会执行 D 步,直到构建出包含所有特征的完整模型。
因此,该算法的复杂度是 O(D²)。这是因为最多有 D 步,每一步大约需要评估 D 个模型。
当 D 较大时,O(D²) 的计算量远小于全子集选择法的 O(2ᴰ)。这使得贪心前向逐步算法在计算上显著更高效、更可行。
贪心算法的其他变体
上述算法只是众多可能的贪心特征选择策略之一。以下是其他一些常见的变体:
- 后向逐步选择:与“前向”过程相反,该算法从包含所有特征的完整模型开始,在每次迭代中,选择删除一个对模型性能影响最小的特征。
- 前向后向混合选择:这是一种结合了添加和删除操作的策略。在“前向”过程中添加特征后,算法可能会周期性地“回看”,评估并删除那些因添加了新特征而变得不再重要的旧特征。例如,在预测房价时,一旦模型添加了“卧室数量”和“浴室数量”这两个特征,“房屋面积”这个特征可能就不再那么重要,因为前两者可以作为面积的一个近似代理。
除了上述策略,研究人员还提出了许多其他算法变体。这些变体在何时添加或删除特征的标准(度量指标)以及如何搜索特征组合的方式上有所不同。特征选择是一个非常重要且历史悠久的问题,因此诞生了多种多样的解决方案。
总结

本节课中我们一起学习了贪心前向逐步算法的计算复杂度。我们了解到其复杂度为 O(D²),远低于全子集选择法的 O(2ᴰ),从而在特征数量较多时具有显著的计算优势。我们还简要介绍了该算法的其他变体,如后向选择和混合选择,说明了特征选择方法的多样性。
机器学习:第2课:使用正则化进行特征选择

在本节课中,我们将探讨特征选择的第三种方法:使用正则化回归来隐式地执行特征选择。我们将重点介绍一种名为Lasso的算法,该算法在机器学习、统计学和工程学领域产生了深远的影响。
概述
上一节我们介绍了特征选择的基本概念和两种传统方法(子集搜索与贪心算法)。本节中,我们将探索一种不同的思路:通过修改正则化惩罚项,使模型在训练过程中自动将某些特征的系数精确地收缩至零,从而实现特征选择。这种方法的核心是Lasso回归。

回顾岭回归
首先,让我们回顾一下岭回归中的正则化思想。岭回归的目标是在模型对训练数据的拟合优度与模型系数的幅度之间进行权衡。我们引入了一个调优参数 λ 来平衡这两个相互竞争的目标。
其目标函数可以表示为:
公式:
最小化:RSS(w) + λ * ||w||₂²
其中:
RSS(w)是残差平方和,衡量模型拟合度。||w||₂²是系数向量的 L2范数的平方,即所有特征权重的平方和:w₁² + w₂² + ... + w_d²。λ是控制惩罚强度的参数。
岭回归的惩罚项会促使系数变小。但需要强调的是,它只是让系数趋近于零,而不会精确地等于零。从系数路径图可以看出,随着 λ 增大,系数不断缩小并无限接近零,但对于任何有限的 λ 值,系数都不会真正变为零。
稀疏性与精确零值的重要性
为什么系数精确等于零如此重要?这关乎我们之前讨论的稀疏性概念。
以下是系数为零的两个关键好处:
- 预测效率:如果某个特征的系数为零,在进行预测时,我们可以完全忽略该特征,从而减少计算量。
- 模型可解释性:系数为零意味着该特征未被模型使用。这本身就完成了一次特征选择:我们识别出了对预测没有贡献的特征。
因此,我们面临一个问题:能否利用正则化来实现这种能产生精确零系数的特征选择?
与传统方法(在离散的特征子集空间中搜索)不同,我们希望能从一个包含所有特征的完整模型出发,通过某种方式,将一部分不重要的特征的系数精确地收缩至零,而保留其他特征的系数。非零系数所对应的特征,即为我们选中的特征。
引入Lasso回归
为了达到上述目的,我们需要改变正则化惩罚项。Lasso回归应运而生。与岭回归使用L2范数不同,Lasso回归使用系数的 L1范数 作为惩罚项。
Lasso回归的目标函数是:
公式:
最小化:RSS(w) + λ * ||w||₁
其中,||w||₁ 是系数向量的 L1范数,即所有特征权重的绝对值之和:|w₁| + |w₂| + ... + |w_d|。
将惩罚项从L2范数平方改为L1范数,这个看似微小的变化,却带来了一个关键特性:它倾向于产生稀疏的系数向量,即许多系数会精确地等于零。
Lasso如何实现特征选择
为什么L1惩罚能产生零系数?我们可以从几何角度直观理解。
- 岭回归 (L2):其约束区域是一个“圆滑”的球形。最优解(损失函数等高线与约束区域的切点)很难恰好落在坐标轴上,因此系数通常非零。
- Lasso回归 (L1):其约束区域是一个有“尖角”的菱形。这些尖角恰好位于坐标轴上。当损失函数等高线与这些尖角相切时,最优解就会落在坐标轴上,使得一个或多个系数恰好为零。
随着调整参数 λ 增大,惩罚力度增强,会有越来越多的系数被“压缩”至零。通过选择不同的 λ 值,我们可以得到具有不同稀疏度(即不同数量非零特征)的模型。这样,Lasso就自动地为我们完成了一套从全模型到极简模型的特征选择路径。
总结

本节课中,我们一起学习了如何使用正则化方法进行特征选择。我们从岭回归的局限性(系数收缩但非零)出发,引出了对稀疏模型的需求。进而,我们介绍了Lasso回归,它通过将惩罚项改为系数的L1范数,能够将不重要特征的系数精确地收缩至零,从而同时实现了模型正则化与特征选择。这种方法避免了在离散特征子集上进行穷举搜索,提供了一条连续且自动的特征选择路径。
机器学习:第2课:对岭回归系数进行阈值处理

在本节课中,我们将探讨一种看似直观的特征选择方法:对岭回归模型的系数进行阈值处理。我们将分析其背后的逻辑,并通过一个具体的例子来揭示这种方法存在的根本问题。
上一节我们介绍了岭回归及其在防止过拟合方面的作用。本节中我们来看看,能否通过简单地“舍弃”小系数来实现特征选择。
概述:阈值处理的想法
岭回归的解决方案可能会产生许多系数值很小的特征。一个自然的想法是:我们可以设定一个阈值,将所有系数绝对值低于该阈值的特征权重直接设为零,从而将它们从模型中移除。我们称这种方法为“阈值处理”。
以下是阈值处理的基本步骤:
- 训练一个岭回归模型。
- 检查所有特征的权重系数。
- 设定一个阈值(例如 0.01)。
- 将所有系数绝对值小于该阈值的特征权重设为零。
- 仅保留系数绝对值大于阈值的特征。
一个具体的例子
为了更清楚地说明,让我们看一个图示。假设在房价预测应用中,我们有一系列特征及其对应的岭回归权重系数。

图中,每个条形代表一个特征的权重系数大小。我们选择了一个阈值(图中的黑色虚线)。任何系数绝对值超过此阈值的特征(图中品红色部分)将被保留在模型中;而低于此阈值的特征(图中其他颜色部分)则被剔除。
这看起来似乎是一种合理的方法。但让我们深入分析,特别是观察两个高度相关的特征。
问题所在:相关特征的影响
如果我们查看特征列表,会发现“卫生间数量”和“淋浴间数量”这两个特征(图中绿色高亮部分)通常高度相关。因为大多数卫生间都配有淋浴设施,随着淋浴间数量增加,卫生间数量也往往会增加。
然而,在我们的阈值处理结果中,模型完全没有包含任何与卫生间或淋浴间相关的特征。这似乎不合逻辑,因为房屋的卫生间数量理应是评估其价值时的一个重要特征。
那么,问题出在哪里?
为了简化分析,我们假设“淋浴间数量”与“卫生间数量”完全相等。如果最初在构建完整模型时没有包含“淋浴间数量”这个特征,那么岭回归算法就会将原本分配给“淋浴间数量”的权重全部加到“卫生间数量”上。
因为这是一个线性模型,其预测是各特征权重与取值的乘积之和。如果“卫生间数量”等于“淋浴间数量”,那么“权重1 * 卫生间数量 + 权重2 * 淋浴间数量”就等价于“(权重1 + 权重2)* 卫生间数量”。
因此,如果没有这个冗余的“淋浴间数量”特征,仅对“卫生间数量”进行阈值处理时,其系数很可能超过阈值并被保留在模型中。
根本原因:岭回归的惩罚项
这里揭示的问题并非特例,而是一个普遍现象:当存在一组高度相关(统计上称为强相关性)的特征时,岭回归倾向于给所有这些特征分配一系列较小的权重,而不是给其中一个特征分配一个较大的权重。
原因在于岭回归的成本函数。岭回归的目标是最小化以下公式:
总成本 = 预测误差 + λ * Σ(权重_i²)
其中,Σ(权重_i²) 是 L2 惩罚项。如果将一个很大的权重集中在一个特征上,会显著增大这个惩罚项。然而,将权重分散到多个冗余特征上,模型的拟合效果(预测误差部分)几乎相同,但惩罚项的总和却可能更小。
因此,对于一组冗余特征,岭回归给出的解决方案是一系列小权重。此时如果进行简单的阈值处理,我们就会错误地丢弃所有这些实际上与预测任务相关的特征。
希望通过这个图示和解释,能够清楚地表明:简单地采用岭回归并对小系数进行阈值处理,并不能解决我们的特征选择问题。
总结与过渡
本节课中我们一起学习了为何对岭回归系数进行阈值处理是一种有缺陷的特征选择方法。其核心问题在于,岭回归的 L2 惩罚项会促使模型将权重分散到相关特征上,导致每个特征的系数都变小,从而在阈值处理时被误删。




于是,我们面临一个新的问题:能否使用正则化方法直接优化模型的稀疏性(即让大部分系数直接为零)? 这将引导我们探索下一节的主题:Lasso回归及其背后的L1正则化。
机器学习:第2课:Lasso目标及其系数路径 📊

在本节课中,我们将学习Lasso回归的目标函数,并理解其如何通过L1正则化产生稀疏解。我们将对比Lasso与之前介绍的岭回归,并通过系数路径图直观地展示其特性。

上一节我们介绍了岭回归及其L2正则化。本节中,我们来看看另一种正则化方法——Lasso回归。

如果我们将衡量系数大小的方式从岭回归的L2范数(平方和)替换为L1范数,即简单地对每个系数的绝对值求和,会发生什么?我们在上一个模块讨论岭回归时,曾将其描述为一种合理的系数大小度量方式。
这个修改的结果是,它会导向稀疏解。我们将在本模块的剩余部分探讨其原因。这个目标函数被称为Lasso回归或L1正则化回归。
其目标函数公式如下:
最小化 [ RSS(w) + λ * ||w||_1 ]
其中,||w||_1 = |w_1| + |w_2| + ... + |w_D| 是系数的L1范数。
与岭回归类似,Lasso也由一个调优参数λ控制。λ决定了我们在多大程度上倾向于解的稀疏性,而不是对训练数据的拟合程度。
需要明确的是,在进行特征选择任务时,我们是在一个连续的空间(λ值的空间)中进行搜索。λ控制着解的稀疏性。这与“所有子集”或“贪婪”方法形成对比,那些方法是在一组离散的可能解中搜索。因此,Lasso是一种根本不同的特征选择方法。
接下来,我们讨论当λ变化时,解会发生什么变化。再次强调,λ是一个平衡拟合度与稀疏性的调优参数。
以下是λ取不同值时的情况:
- λ = 0:此时惩罚项完全消失,目标函数简化为最小化残差平方和(RSS),即我们之前的最小二乘目标。因此,Lasso的解
ŵ_lasso将完全等于最小二乘解ŵ_least_squares。这就是无正则化的解。 - λ = ∞:此时我们完全倾向于系数大小的惩罚,完全忽略残差平方和的拟合。那么,什么值能使L1范数最小呢?与岭回归类似,当λ趋近于无穷大时,我们会得到
ŵ_lasso等于零向量。 - 0 < λ < ∞:在这种情况下,Lasso解的L1范数将小于或等于最小二乘解的L1范数,并且大于等于零(标量零)。
到目前为止,尚不清楚为什么L1范数会导致稀疏性。我们稍后会解释。但首先让我们直观地探索一下。一种方法是观察系数路径。
我们先回顾一下岭回归的系数路径。我们看到,即使λ值很大,所有特征也仍然在模型中,只是系数值很小。对于大的λ值,所有 ŵ_j 都大于0,但都很小。
相比之下,观察Lasso的系数路径,我们会看到一个非常不同的模式。我们发现,在调优参数λ达到某些临界值时,某些特征会“跳出”模型。
例如,在下图中:
- 地块面积(square feet of the lot size)在此处从模型中消失。
- 卧室数量(number of bedrooms)几乎与楼层数(number of floors)和浴室数量(number of bathrooms)同时消失。
- 接着是房屋建造年份(year the house was built)。
对于像图中这个位置的λ值,我们模型中包含的是一个稀疏的特征集合。只有被圈出的特征是模型中包含的,所有其他特征的系数都已精确地降至零。
我们还观察到,当λ非常大时(如前一张图中所示的大值),模型中唯一剩下的特征是居住面积(square feet living)。请注意,即使其他特征都不在模型中,居住面积仍然具有非常大的权重。只有当λ值变得极大时,居住面积的系数最终才会被压缩至零。
回到岭回归的解,我们会发现居住面积的权重要小得多,因为权重被分配给了模型中的许多其他特征,因此居住面积的个体影响不那么明显。

本节课中,我们一起学习了Lasso回归的目标函数及其核心特性。我们了解到,Lasso通过引入系数的L1范数作为惩罚项,能够在优化过程中自动将某些不重要的特征系数精确地压缩为零,从而实现特征选择和稀疏解。通过系数路径图,我们直观地对比了Lasso与岭回归的差异:岭回归倾向于保留所有特征但缩小其系数,而Lasso则倾向于产生一个只包含部分特征的更简洁模型。
机器学习:第2课:可视化岭回归成本


在本节课中,我们将学习如何通过几何视角来理解岭回归的解。我们将从二维特征空间入手,通过绘制成本函数的等高线图,直观地展示岭回归如何平衡数据拟合(残差平方和)与模型复杂度(L2范数惩罚项)。理解这种几何解释,有助于我们为后续理解Lasso回归的稀疏性打下基础。

岭回归目标的几何解释
为了进行可视化,我们考虑一个简化的场景:模型只有两个特征,即 w0 和 w1。我们的目标是理解岭回归的解在参数空间中的位置。
岭回归的目标函数可以写为:
目标函数 = 残差平方和(RSS) + λ * (w0² + w1²)
其中,λ 是控制惩罚强度的超参数。
接下来,我们将分别分析这个目标函数中的两个组成部分。
残差平方和的等高线
首先,我们关注目标函数的第一部分:残差平方和(RSS)。在二维特征空间中,RSS作为 w0 和 w1 的函数,其等高线图具有特定的形状。
当我们固定RSS等于某个常数 C 时,方程 RSS(w0, w1) = C 定义了一个椭圆。这是因为方程中 w0 和 w1 都以平方项形式出现,并且包含它们的交叉项。
以下是RSS等高线图的关键点:
- 图中的每一个椭圆都代表一组
(w0, w1)参数,它们都产生相同的RSS值。 - 越靠近中心的椭圆,其RSS值越小。
- 所有椭圆同心,并且中心点对应着RSS的全局最小值。
如果我们的目标仅仅是最小化RSS,那么最优解就是这个椭圆的中心点。这个点正是最小二乘解,我们将其标记为 ŵ_least_squares。
L2惩罚项的等高线
现在,我们来看目标函数的第二部分:L2范数惩罚项 w0² + w1²。这个项的几何形状更为简单。
当我们固定惩罚项等于某个常数 C 时,方程 w0² + w1² = C 定义了一个圆。这个圆以坐标原点 (0, 0) 为圆心。
以下是L2惩罚项等高线图的关键点:
- 图中的每一个圆都代表一组
(w0, w1)参数,它们具有相同的L2范数值。 - 越靠近原点的圆,其L2范数值越小。
- 如果我们的目标仅仅是最小化L2范数,那么最优解就是原点
(0, 0)。这对应着岭回归中惩罚强度λ趋于无穷大的极端情况。
岭回归解的平衡点
上一节我们分别查看了RSS和L2惩罚项的几何形状。在岭回归中,我们需要同时最小化这两者之和。最终的解将是这两个竞争目标之间的一个平衡点。
从几何上看,岭回归的最优解 ŵ_ridge 必须同时满足两个条件:
- 它需要位于某个RSS的椭圆等高线上。
- 它也需要位于某个L2惩罚项的圆形等高线上。
实际上,ŵ_ridge 就是使得RSS椭圆与L2圆恰好相切的那个点。随着惩罚强度λ的变化,这个切点的位置会沿着RSS椭圆的边界移动:
- 当 λ = 0 时,相当于没有惩罚,解就是最小二乘解
ŵ_least_squares。 - 当 λ 增大时,圆形等高线“收缩”,迫使解向原点
(0, 0)移动,参数值被“压缩”得更小。 - 当 λ → ∞ 时,解被压缩至原点
(0, 0)。
这种可视化清晰地展示了岭回归如何通过引入L2惩罚,将参数估计值从最小二乘解“拉向”原点,从而在偏差和方差之间取得平衡,提高模型的泛化能力。
总结


本节课中,我们一起学习了岭回归的几何解释。我们通过绘制残差平方和(椭圆)与L2惩罚项(圆)的等高线图,直观地看到了岭回归的解是如何作为这两个竞争目标之间的平衡点而出现的。解是RSS椭圆与L2圆的切点,其具体位置由惩罚系数λ控制。这种几何视角为我们理解正则化的作用机制提供了清晰的图像,并为下一课理解Lasso回归产生稀疏解的几何原因奠定了基础。
机器学习:第2课:可视化岭回归解

在本节课中,我们将学习如何通过可视化来理解岭回归的解。我们将看到,岭回归的解是如何在最小化残差平方和与最小化模型系数大小之间取得平衡的。
岭回归解的平衡
上一节我们介绍了岭回归的目标函数。本节中我们来看看这个解在几何上的直观表现。
对于任何一个特定的 lambda 值,我们都会在残差平方和与系数的 L2 范数之间取得某种平衡。
因此,我接下来要做的是,在这个演示中,将这两个等高线图叠加在一起。具体来说,我将叠加残差平方和 RSS(w) 与 λ * ||w||₂² 的等高线图。其中,残差平方和的等高线是围绕最小二乘解的一系列椭圆,而 L2 范数的等高线是围绕零点的一系列圆。λ 是一个权重参数,决定了惩罚项在总成本中的比重。
随 Lambda 变化的动态过程
以下是这个动态过程的核心:我将展示一个随着 lambda 值增加而变化的动画。
- 动画内容:随着 lambda 增加,观察解的变化。
- 初始状态:当 lambda 等于 0 时,我们的解就是最小二乘解。
- 最终状态:随着 lambda 趋近于无穷大,系数会收缩至 0。
- 动画目的:可视化系数收缩的路径。
让我们观看这个动画。动画中的 “X” 标记了对于特定 lambda 值的最优解。随着 lambda 变化,这个 “X” 会移动。
动画开始于最小二乘解。随着 lambda 增加,我们可以看到系数 w0 和 w1 的幅度越来越小,逐渐向零点收缩。这个过程直观地展示了岭回归的“收缩”效应。
特定 Lambda 值的解
现在,让我们讨论对于一个给定的 lambda 值,解的具体形态。
对于一个特定的 lambda 值,我们在残差平方和与系数幅度之间取得某种平衡。lambda 自动地在两者之间进行权衡。
具体到这张图中,这就是我们的解。它对应一个特定的残差平方和(图中等高线上的数字 5215 即表示此值),以及一个特定的 L2 范数值(4.75)。这个 lambda 值选择了这个特定的权衡点。我们可以看到,解的位置介于最小二乘解(大约在图中椭圆中心)和零点之间。
如果我们选择了一个不同的 lambda 值,例如一个更大的 lambda,我们将得到一个不同的解。在更大的 lambda 下,解会更倾向于更小的 L2 范数,但会接受更大的残差平方和。
理解最优性
当我绘制这些等高线时,我想表达的是:沿着这个椭圆上的任何其他点,都具有完全相同的残差平方和,但具有更大的系数 L2 范数;而沿着这个圆上的任何其他点,都具有完全相同的系数 L2 范数,但具有更大的残差平方和。因此,图中 “X” 标记的点,正是对于这个 lambda 值的最优权衡点。

本节课中我们一起学习了如何通过可视化等高线图来理解岭回归。我们看到了解如何随着正则化强度 lambda 的变化,在拟合数据(最小化残差)和约束模型复杂度(缩小系数)之间平滑地移动。这种几何视角有助于我们直观把握岭回归的工作原理。
机器学习:回归:第2课:可视化Lasso成本函数与解 🎯


在本节课中,我们将学习Lasso回归的成本函数及其几何解释。我们将通过可视化方法,理解Lasso如何通过L1正则化产生稀疏解,即某些系数恰好为零的解。

上一节我们介绍了岭回归(Ridge)的几何解释,本节中我们来看看Lasso回归的目标函数。
Lasso的目标函数由两部分组成:残差平方和(RSS)加上一个L1正则化项。其公式如下:
成本函数 = RSS + λ * ||w||₁
其中,||w||₁ 表示权重向量的L1范数,即各权重绝对值之和。
残差平方和(RSS)的等高线
首先,我们关注目标函数的第一项——残差平方和(RSS)。对于Lasso目标函数,RSS项与我们在岭回归中讨论的完全相同。
因此,在可视化Lasso目标函数中RSS的等高线时,它与岭回归中的形状完全一致。RSS的等高线是一组椭圆,其中心点是最小二乘解。
L1正则化项的等高线
现在,让我们关注与岭回归不同的部分——L1正则化项。我们不再使用L2范数,而是使用L1范数。
如果我们考虑方程 |w₀| + |w₁| = 常数,这个方程定义了L1范数的一个等高线。这个形状看起来像什么?
它定义了一个菱形(或钻石形)。沿着这个菱形边界上的每一个点,都具有完全相同的L1范数值。
以下是不同L1范数常数对应的菱形:
- 当
|w₀| + |w₁| = 常数1时,得到一个较小的菱形。 - 当
|w₀| + |w₁| = 常数2(大于常数1)时,得到一个较大的菱形。
如果我们的目标仅仅是最小化L1范数本身,那么最优解就是让所有权重趋近于零,即 min over w of ||w||₁ 的解是 w = 0。
这个菱形的可视化对于理解Lasso至关重要,我们稍后会再次回到这个概念。
组合目标函数与解的路径
接下来,我们将展示一个动态过程,就像之前对岭回归所做的那样,但这次是针对Lasso。这个动态图展示了我们将两个等高线图相加的过程:椭圆形的RSS等高线加上经过λ加权的菱形L1等高线。
然后,我们求解这个组合函数的最小值,这个最小值点(标记为 x)就是对应特定λ值的最优解 ŵ。
我们将观察这个解如何随着λ值的增加而变化:
- 当
λ = 0时,我们得到的就是普通最小二乘解,这与岭回归的起点相同。 - 随着λ逐渐增大,解的变化路径将与岭回归非常不同。虽然最终解都会趋向于零,但让我们看看具体路径是怎样的。
播放动态图...
我们观察到,解最终到达了 w₀ 恰好等于零的点。让我们再看一遍这个过程:
- 解
x沿着路径移动并收缩。 - 在某个时刻,它碰到了y轴(即
w₀ = 0的轴)。 - 此后,解沿着y轴向下移动。
这意味着,首先发生的是 w₀ 系数恰好变为零。然后,第二个特征 H₁ 的权重 w₁ 会随着惩罚项λ的继续增加而不断减小,解将沿着y轴持续向下移动。
随着λ权重增大,组合后的等高线会变得越来越像定义L1范数的菱形。
为什么Lasso会产生稀疏解?
现在,让我们可视化Lasso在某个特定λ值下的解,这将为我们提供超越动态图的几何直觉,以理解为什么Lasso解是稀疏的。
动态图已经显示,对于某些λ值,我们会得到恰好为零的系数。现在,我们只看一个λ值下的情况。
这里的 x 就是我们的解。
关键点在于,由于我们添加的L1惩罚项具有菱形形状,解有很高的概率碰到这个菱形的角上。而在这些角上,我们就会得到稀疏解(即某些系数为零)。
可以这样形象地理解:菱形的角(在高维空间中是多面体的顶点)非常“尖”,它们会“刺中”RSS的椭圆等高线。这导致了最优解经常落在坐标轴上,使得某些系数为零。
需要提及的是,这个可视化仅仅是二维的。在更高维度中,L1范数的等高线形状被称为菱面体,它们同样是带有尖锐顶点的物体。因此,在高维空间中,对于任何λ值,解都更有可能落在L1惩罚项的某个顶点(角)上,从而产生稀疏性。

本节课中我们一起学习了Lasso回归成本函数的几何解释。我们看到了L1正则化项的菱形等高线如何与残差平方和的椭圆等高线相互作用,并理解了这种相互作用如何导致最优解经常位于坐标轴上,从而产生系数恰好为零的稀疏模型。这是Lasso回归用于特征选择的核心原理。
机器学习:第2课:Lasso回归演示 🎯

在本节课中,我们将通过一个多项式回归的示例,直观地展示Lasso回归如何通过L1惩罚项实现稀疏解。我们将观察随着正则化参数λ的变化,模型系数如何被压缩至零,以及这如何影响模型的拟合效果。
稀疏性实践
上一节我们介绍了Lasso回归的理论基础,本节中我们来看看它在实际数据上的表现。我们将回到多项式回归的示例,但这次我们将应用Lasso回归,并观察不同λ值下的结果。
以下是我们的演示设置:我们将使用一个16阶的多项式回归模型,并调整L1惩罚项的强度。

代码实现与参数探索
我们修改了多项式回归函数,以使用支持L1惩罚项的线性回归模型。在代码中,我们将L2惩罚项设置为零,并专注于调整L1惩罚项。我们使用FISTA求解器来优化Lasso目标函数。
# 示例:多项式Lasso回归函数
def polynomial_lasso_regression(data, deg, l1_penalty):
# 构建多项式特征
# 应用带L1惩罚的线性回归
# 返回模型和系数
现在,我们将探索一系列λ值,从 1e-4 到 10。我们从16阶多项式开始,这个模型在未正则化的最小二乘法中会产生非常复杂的拟合。
观察系数稀疏性
随着λ值的变化,我们可以观察到模型系数的变化。
以下是不同λ值下非零系数的数量变化:
- λ非常小(如1e-4):所有17个系数(16个特征加1个截距项)均为非零。此时模型近似于最小二乘解。
- λ增大(如0.01):非零系数数量减少至14个。
- λ继续增大(如0.1):非零系数数量进一步减少至5个。
- λ很大(如10):仅剩2个系数为非零。
这个结果清晰地展示了Lasso如何通过增加L1惩罚项的强度来产生稀疏解,即自动将不重要的特征系数精确地设为零。
对比模型拟合效果
接下来,我们看看这些不同稀疏度的模型对应的拟合曲线。
以下是不同λ值对应的拟合图像描述:
- λ值很小时:拟合曲线虽然比未正则化的最小二乘解平滑一些,但仍然相当曲折。即使没有系数为零,Lasso的收缩效应也提供了一定的正则化。
- λ值适中时:拟合曲线变得平滑,类似于我们在岭回归中找到的最优解。模型在保持关键特征的同时,避免了过拟合。
- λ值很大时:拟合曲线过于平滑,由于大部分特征被剔除,模型变得过于简单,导致欠拟合。
与岭回归简单地收缩所有系数不同,Lasso通过将部分系数设为零,实现了特征选择,从而得到了一个更易于解释的模型。

总结

本节课中我们一起学习了Lasso回归在实际中的应用。我们通过一个多项式回归的演示,观察到L1惩罚项如何随着λ的增大,将越来越多的模型系数压缩至零,从而实现稀疏解和自动特征选择。与岭回归的系数收缩不同,Lasso能够产生更简洁、更具解释性的模型。为了选择最优的λ值,我们可以像在岭回归中一样,使用留一法交叉验证等技术。
机器学习:回归:第2课:Lasso目标函数的独特性与优化 🎯

在本节课中,我们将学习Lasso回归目标函数的独特性,并探讨如何优化这个目标函数以找到特定λ值下的解。λ是一个调节参数,用于控制目标函数中L1惩罚项的权重。

从目标函数到优化方法
上一节我们介绍了Lasso目标函数及其导致稀疏解的直观原因。本节中,我们来看看如何优化这个目标函数,并实际求解特定λ值下的Lasso解。


在回归的机器学习工作流程中,我们目前关注的是代表机器学习算法的灰色方框。首先,让我们回顾一下之前处理最小二乘法和岭回归目标函数时的方法。我们计算了总成本的梯度,然后要么通过令梯度为零来寻找闭式解,要么在称为梯度下降的迭代过程中使用梯度。
Lasso目标函数的梯度挑战
以下是我们的Lasso目标函数,让我们考虑计算其梯度。我们知道如何计算残差平方和项的梯度,但接下来会遇到这个L1目标项。这里存在一些问题。具体来说,绝对值的导数是什么?因为记住,我们的L1目标是W_j从j=0到D的绝对值之和。
因此,我们需要计算W_j绝对值的导数。当我思考这个绝对值函数时,即W_j的绝对值。那么,这里的导数是什么?在这条线的任何一点,导数都是-1,因为这条线的斜率是-1。而在这个半平面的任何地方,导数是+1,因为斜率是+1。然后我到达这个关键的零点,那里的导数是什么?实际上,该点不存在导数。
次梯度的引入
因此,与其考虑由这些导数定义的梯度,我们可以讨论一种称为次梯度的概念。我们将在更高级的可选视频中讨论次梯度的概念,但只需知道它们存在,并且对于推导我们将要讨论的Lasso目标函数算法至关重要。如果你有兴趣了解更多,请关注我们的可选高级视频。
但即使你能计算这个我们所说的绝对值函数不存在的导数,我们的Lasso目标函数仍然没有闭式解。因此,我们无法采用闭式解选项。不过,我们可以使用梯度下降算法,但再次强调,不是使用梯度,而是使用次梯度。
总结


本节课中,我们一起学习了Lasso回归目标函数在优化时面临的独特挑战。由于L1惩罚项包含绝对值函数,其在零点不可导,因此无法像最小二乘法或岭回归那样直接计算梯度并求闭式解。这引入了次梯度的概念,它是优化Lasso目标函数的关键工具。虽然我们无法获得闭式解,但可以通过基于次梯度的迭代算法(如次梯度下降)来求解Lasso问题。
机器学习:第2课:坐标下降法


在本节课中,我们将学习一种重要的优化算法——坐标下降法。我们将首先介绍坐标下降法的基本概念和流程,然后详细说明如何将其应用于求解Lasso回归的目标函数。

概述
上一节我们讨论了梯度下降和次梯度下降。本节中,我们将介绍一种替代的优化方法:坐标下降法。这种方法的核心思想是,通过固定其他所有变量,每次只优化一个变量,从而将一个复杂的多变量优化问题转化为一系列简单的一维优化问题。
坐标下降法算法
我们的目标是最小化某个函数 G(w),其中 w 是一个包含多个变量(w₀, w₁, ..., w_D)的向量。直接优化所有变量可能很困难,但固定其他变量,仅优化一个变量则相对简单。
以下是坐标下降法的基本步骤:
- 初始化:初始化权重向量 ŵ,例如可以全部设为0,或采用其他更智能的初始化方法。
- 迭代优化:当算法未收敛时,重复以下步骤:
- 从所有坐标(0, 1, ..., D)中选择一个坐标 j。
- 固定其他所有坐标的值(即使用前一次迭代得到的 ŵ₀, ..., ŵ_{j-1}, ŵ_{j+1}, ..., ŵ_D),仅针对第 j 个坐标进行优化。具体来说,我们寻找一个值 ω,使得函数 G 最小:
ŵ_j = argmin_ω G(ŵ₀, ..., ŵ_{j-1}, ω, ŵ_{j+1}, ..., ŵ_D) - 将找到的最优 ω 值赋给 ŵ_j。
- 收敛判断:持续循环,直到满足收敛条件。
算法图解
为了更直观地理解,我们以二维空间(w₀, w₁)为例:
- 首先,选择优化 w₁ 坐标,同时固定 w₀ 的值。这相当于在 w₀ 固定的垂直线上寻找函数 G 的最小值点。
- 找到该点后,接下来选择优化 w₀ 坐标,同时固定 w₁ 为刚更新的值。这相当于在 w₁ 固定的水平线上寻找最小值点。
- 如此交替进行,优化路径会呈现一系列沿坐标轴方向的移动,最终逼近全局最优点。
坐标选择策略
关于如何选择下一个要优化的坐标,有几种常见策略:
- 循环坐标下降:按固定顺序(如 0, 1, 2, ..., D)循环遍历所有坐标。
- 随机坐标下降:在每次迭代中随机选择一个坐标进行优化。
坐标下降法的特点
与梯度下降法相比,坐标下降法有几个重要的特点:
- 无需步长参数:在坐标下降法中,我们直接求解每个一维子问题的最优解,因此不需要像梯度下降法那样手动设置或调整学习率(步长)。这简化了算法的使用。
- 收敛性保证:对于某些类型的函数,可以证明坐标下降法能够收敛。例如,当目标函数是强凸函数时,算法保证收敛。更重要的是,对于我们将要应用的Lasso回归问题,坐标下降法也被证明是收敛的(尽管本课程不展开证明)。
- 广泛应用:坐标下降法是一种非常实用的优化算法,适用于许多机器学习问题。
总结


本节课我们一起学习了坐标下降法。我们了解了其核心思想:通过固定其他变量,轮流优化单个变量,将复杂问题分解。我们介绍了算法的具体步骤,并通过二维示例图解了其工作原理。我们还讨论了坐标选择策略,并指出了坐标下降法无需步长参数以及对Lasso等问题具有收敛保证的优点。接下来,我们将具体探讨如何应用坐标下降法来求解Lasso回归的目标函数。
机器学习:第2课:特征归一化

在本节课中,我们将要学习一个在机器学习中非常实用且重要的概念——特征归一化。它不仅能简化某些算法(如Lasso回归的坐标上升法)的推导和实现,还能提升模型性能,确保不同尺度的特征能被公平对待。


概述:什么是特征归一化?
上一节我们介绍了Lasso回归等模型。本节中我们来看看如何通过特征归一化来简化问题并提升实践效果。
特征归一化指的是对数据集的列(即特征)进行缩放处理,使其落入一个相近的数值范围。例如,在房价预测中,“房屋面积”的数值可能高达数千,而“卧室数量”通常只是个位数。这种量级差异会影响许多机器学习算法的表现。
核心操作是:我们必须对训练数据的每一列(特征)进行归一化,并且将完全相同的缩放操作应用到测试数据上。
如何对特征进行归一化?
以下是特征归一化的标准步骤。其核心思想是计算每个特征的“尺度”或“范数”,然后用该特征的所有值除以这个尺度。
-
计算归一化因子(尺度):对于训练数据集中的第
j个特征(即第j列),我们计算其归一化因子Z_j。一个常见的方法是计算该特征所有值的平方和的平方根(即L2范数)。公式:
Z_j = sqrt( sum_{i=1}^{n} (x_{i,j})^2 )其中,
x_{i,j}表示第i个训练样本的第j个特征值,n是训练样本的总数。 -
归一化训练数据:用训练数据中该特征的每一个值除以计算得到的
Z_j。公式:
x_{i,j}^{(normalized)} = x_{i,j} / Z_j对所有训练样本
i和特征j执行此操作。 -
归一化测试数据(关键步骤):当需要对新的测试数据进行预测时,必须使用从训练数据计算得到的同一个
Z_j来对测试数据的相应特征进行归一化。公式:
x_{test, j}^{(normalized)} = x_{test, j} / Z_j这里使用的
Z_j与步骤1中计算出的值完全相同。
为什么必须对训练集和测试集使用相同的归一化因子?
这是一个至关重要的实践要点。如果我们用一套标准(例如,将面积从平方英尺转换为平方米)处理了训练数据,但测试数据却仍保持原始单位(平方英尺),那么模型在测试集上的预测将完全错误。模型从归一化后的数据中学到的规律,无法直接应用到未以同样方式处理的测试数据上。
简而言之:必须保证训练阶段和测试/预测阶段的数据预处理管道完全一致。
归一化带来的好处
- 算法简化:如课程开头所述,特征归一化后,Lasso回归的坐标上升法等算法的数学表达和实现会变得更加简洁清晰。
- 公平比较:将所有特征缩放到相近的范围,可以防止某些数值大的特征仅仅因为其尺度大而在模型中占据主导地位。
- 提升性能:对于依赖距离计算(如K近邻、支持向量机)或梯度下降的算法,归一化能显著加快收敛速度并提高模型精度。
总结

本节课中我们一起学习了特征归一化。我们明确了其定义:对数据特征的列进行缩放处理。我们掌握了其方法:基于训练集计算归一化因子,并统一应用于训练集和测试集。我们理解了其重要性:确保数据尺度一致,避免模型偏差,并简化算法实现。记住,在将任何预处理技术应用于测试数据时,都必须严格复用从训练数据中得出的参数,这是构建可靠机器学习工作流的基本原则。
机器学习:第2课:最小二乘回归的坐标下降法(归一化特征)📊



在本节课中,我们将要学习一种用于最小二乘回归的优化算法——坐标下降法。我们将从归一化特征这一重要概念出发,逐步推导出算法的核心更新公式,并解释其背后的直观含义。
概述
上一节我们介绍了归一化特征的概念。本节中,我们来看看如何利用归一化特征,为最小二乘回归问题推导出坐标下降算法。坐标下降法的核心思想是:在优化多变量目标函数时,每次只优化一个变量,而固定其他所有变量,并循环迭代这一过程。
坐标下降法推导
我们的目标是最小化残差平方和(RSS)。在坐标下降法中,当我们针对特定变量 Wj 进行优化时,会固定所有其他变量 W_{-j}(即除 Wj 外的所有权重),然后求解使目标函数最小的 Wj 值。这本质上是一个一维优化问题。
以下是我们的最小二乘目标函数:
最小化:RSS(W) = Σ_{i=1}^{n} (y_i - Σ_{k=1}^{p} w_k * \bar{h}_k(x_i))^2
其中,\bar{h}_k(x_i) 表示第 k 个归一化特征。
为了求解最优的 Wj,我们对 RSS 关于 Wj 求偏导数,并令其等于零。
RSS 关于 Wj 的偏导数推导如下(注意,所有特征均已归一化):
∂RSS/∂w_j = -2 * Σ_{i=1}^{n} \bar{h}_j(x_i) * [ y_i - Σ_{k≠j} w_k * \bar{h}_k(x_i) ] + 2 * w_j * Σ_{i=1}^{n} \bar{h}_j(x_i)^2
现在,我们定义两个关键量来简化这个表达式。
首先,根据归一化特征的定义,每个归一化特征的平方和等于1:
Σ_{i=1}^{n} \bar{h}_j(x_i)^2 = 1
其次,我们定义 ρ_j,它衡量了第 j 个特征与当前模型残差(在排除第 j 个特征的情况下计算)之间的相关性:
ρ_j = Σ_{i=1}^{n} \bar{h}_j(x_i) * [ y_i - Σ_{k≠j} w_k * \bar{h}_k(x_i) ]
其中,Σ_{k≠j} w_k * \bar{h}_k(x_i) 是在模型中排除第 j 个特征时对第 i 个观测值的预测值。
将这两个定义代入偏导数公式,我们得到:
∂RSS/∂w_j = -2 * ρ_j + 2 * w_j
令偏导数等于零以求解最优的 w_j(记作 ŵ_j):
-2 * ρ_j + 2 * ŵ_j = 0
由此,我们得到坐标下降法的核心更新规则:
ŵ_j = ρ_j
算法步骤与直观理解
基于上述推导,我们可以总结出最小二乘回归的坐标下降算法。
以下是算法的主要步骤:
- 初始化权重:将所有回归权重 w 初始化为0(或其他初始值)。
- 循环迭代:重复以下步骤直至收敛。
- 遍历特征:对于每一个特征 j = 1, 2, ..., p,执行以下操作:
- 根据当前所有权重(w_{-j})计算残差,即 y_i - Σ_{k≠j} w_k * \bar{h}_k(x_i)。
- 计算相关性度量 ρ_j,即第 j 个归一化特征与上述残差的点积。
- 将权重 w_j 更新为 ρ_j。
现在,我们来理解 ρ_j 的直观含义。ρ_j 度量了第 j 个特征与当前模型残差(在排除该特征时计算)的相关性。
- 如果 ρ_j 的绝对值很大(正或负),意味着该特征与当前模型未能解释的误差高度相关。因此,将该特征以相应的权重(ŵ_j = ρ_j)加入模型,可以有效地减少这些残差,从而显著改进预测。
- 如果 ρ_j 接近于零,则意味着该特征与当前残差不相关,或者当前模型的预测已经很好(残差本身很小)。因此,在模型中加入该特征不会带来多大改善,其权重也会被设得很小。
总结

本节课中我们一起学习了针对归一化特征的最小二乘回归坐标下降法。我们首先回顾了归一化特征,然后通过固定其他变量、对单一变量求导并令其为零的方法,推导出了核心更新公式 ŵ_j = ρ_j。最后,我们解释了 ρ_j 作为特征与残差相关性的直观意义,并概述了算法的迭代步骤。这个简单而有效的算法为理解后续更复杂的正则化回归(如Lasso)的坐标下降法奠定了重要基础。
机器学习:第2课:Lasso的坐标下降法(归一化特征)📉

在本节课中,我们将学习Lasso回归的坐标下降算法,特别是当特征经过归一化处理时的情况。我们将看到Lasso如何通过一个称为“软阈值”的操作,在优化过程中自动进行特征选择,从而产生稀疏的模型解。
上一节我们介绍了普通最小二乘回归的坐标下降算法。本节中,我们来看看在Lasso回归中,这个算法是如何变化的。
我们继续讨论归一化特征的情况。回顾一下,在无正则化的最小二乘回归的坐标下降算法中,关键步骤是将权重系数 W_hat_j 设置为 ρ_j,即特征 j 与排除该特征后模型预测残差之间的相关性。
在Lasso的情况下,我们如何设置 W_hat_j 将取决于我们的调优参数 λ 以及它与相关性项 ρ_j 的关系。具体来说:
以下是Lasso坐标下降法中更新权重 W_hat_j 的规则:
- 情况一:相关性较弱
如果ρ_j的值较小,即处于[-λ/2, λ/2]这个区间内(“小”的程度由λ决定),那么我们将直接把W_hat_j设置为零。
公式表示为:if |ρ_j| <= λ/2: W_hat_j = 0
这里我们直接看到了Lasso解稀疏性的体现。


-
情况二:相关性较强(正相关)
如果ρ_j非常大(正相关很强),我们将把这个特征包含在模型中。但与最小二乘解相比,我们会减小其权重。
公式表示为:if ρ_j > λ/2: W_hat_j = ρ_j - λ/2 -
情况三:相关性较强(负相关)
如果ρ_j非常小(负相关很强),我们同样会包含该特征,并调整其权重。
公式表示为:if ρ_j < -λ/2: W_hat_j = ρ_j + λ/2
让我们通过可视化来理解我们如何设置 W_hat_j 的这个函数。
这个在Lasso更新中执行的操作被称为软阈值。为了可视化它,我们绘制 ρ_j(我们讨论的相关性)与 W_hat_j(我们设置的系数)的关系图。
在最小二乘解中,我们设 W_hat_j = ρ_j。对于最小二乘法(可以看作是令 λ = 0 的Lasso特例),我们得到一条 y = x 的绿色直线。这条线代表了作为 ρ_j 的函数,我们如何为最小二乘法设置 W_hat_j。
相比之下,图中显示的这条蓝色折线是针对Lasso的。我们看到,在 [-λ/2, λ/2] 这个区间内,如果相关性在这个范围内,意味着特征 j 与残差之间没有太强的关系,我们将完全剔除该特征,将其权重精确设置为零。但是,如果相关性在这个范围之外,我们仍然会在模型中包含该特征,但相对于最小二乘解,我们会将该特征的权重收缩 λ/2 的量。
这就是它被称为“软阈值”的原因:我们在所有地方收缩解,但在 [-λ/2, λ/2] 区间内严格将其驱动为零。
我想用红色对比一下岭回归的解。可以证明(此处不展开),岭回归的解会收缩系数,但永远不会严格收缩到零。这是 W_hat_Ridge 的线。而蓝色的是 W_hat_Lasso 的线。
这样,我们就得到了最小二乘法、岭回归和Lasso之间差异的清晰可视化。


本节课中,我们一起学习了Lasso回归的坐标下降算法。核心在于,通过引入 λ 参数和软阈值操作,算法能够根据特征与残差的相关性 ρ_j 自动决定是否将特征权重设为零。当 |ρ_j| <= λ/2 时,权重归零,实现特征选择;当相关性较强时,权重被收缩为 ρ_j ± λ/2。这与始终收缩但永不置零的岭回归,以及完全不收缩的最小二乘法形成了鲜明对比,直观地展示了Lasso能产生稀疏模型的原因。
机器学习:回归:第2课:评估收敛性与其他Lasso求解器

在本节课中,我们将学习如何评估坐标下降算法的收敛性,并简要介绍除坐标下降法之外的其他Lasso求解器。我们将了解判断算法何时停止的实用方法,并概览解决Lasso问题的不同技术路径。
评估收敛性
上一节我们介绍了用于Lasso的坐标下降算法。在算法中,我们有一个“while not converged”的循环,那么如何评估算法是否收敛呢?
在梯度下降法中,我们通过检查梯度向量的大小来判断,当其模长小于某个容差ε时便停止迭代。然而,在坐标下降法中,我们并不直接计算梯度,因此需要采用其他方法。
我们知道,对于凸目标函数,算法在向最优解移动时,所采取的步长会变得越来越小。至少在强凸函数中,我们可以确信算法会收敛到最优解。
因此,一种可行的方法是:测量我们在所有坐标上完成一个完整循环后,所采取步骤的大小。必须强调的是,我们需要在遍历完所有0到D的坐标后,再判断是否停止。因为有可能某些坐标的更新步长很小,但后续坐标的更新步长仍然很大。
以下是判断收敛的准则:
- 如果在一次完整遍历所有坐标的循环中,所采取的最大更新步长小于预设的容差ε,那么就可以判定算法已经收敛。
其他Lasso求解器

我们刚刚详细探讨了坐标下降法。需要指出的是,坐标下降法只是求解Lasso目标的众多可能方法之一。
经典上,Lasso问题使用最小角回归与收缩算法求解。该算法在2008年之前非常流行。

大约在2008年,一种更早的算法被重新发现并推广开来,这就是我们正在学习的、用于Lasso的坐标下降法。
近年来,在开发高效、并行化和分布式的Lasso求解器方面涌现了大量研究。这些方法包括:
- 坐标下降法的并行版本。
- 其他并行学习方法,如并行随机梯度下降。
- 一种同样相当流行的分布式与平均方法。
其中,专门针对Lasso最流行的方法之一叫做交替方向乘子法。这种方法在Lasso使用者社区中非常受欢迎。
总结

本节课中,我们一起学习了如何为坐标下降算法设定收敛准则,即通过检查一次完整坐标循环中的最大更新步长是否小于阈值。此外,我们还简要回顾了Lasso求解器的发展历程,从经典的最小角回归,到如今广泛使用的坐标下降法,再到当前研究热点中的并行与分布式方法,特别是交替方向乘子法。
机器学习:第2课:Lasso坐标下降法(未归一化特征)

在本节课中,我们将学习如何将Lasso回归的坐标下降算法应用于未归一化的特征。我们将看到,算法核心逻辑不变,但需要引入一个额外的归一化因子 Zj 来调整计算过程。
上一节我们介绍了特征归一化情况下的坐标下降法。本节中我们来看看当特征未归一化时,算法需要做出哪些调整。
算法概述
未归一化特征的坐标下降算法是更通用的形式。它当然也适用于归一化后的特征。我们先回顾一下特征归一化时的算法步骤。
以下是归一化特征下的坐标下降算法核心步骤:
- 初始化权重
w。 - 循环直至收敛:
- 对于每个特征
j:- 计算
ρj。 - 根据软阈值规则更新权重
ŵj。
- 计算
- 对于每个特征
针对未归一化特征的调整
相对于归一化特征的算法,唯一的改动体现在几个关键位置,这些位置在下图中以绿色框高亮显示。

主要的调整有以下三点:
1. 预计算归一化因子 Zj
首先,我们需要为每个特征 j 预计算一个项 Zj。这个 Zj 实质上等同于我们对特征进行归一化时所用的归一化常数。
公式:
Zj = Σ(x_ij²),对所有观测样本 i 求和。
即使不进行归一化,也必须计算这个归一化因子,因为后续步骤会用到它。
2. 计算 ρj 时使用未归一化特征
在计算 ρj 时,我们使用的是原始的、未归一化的特征值 x_ij。
公式:
ρj = Σ( x_ij * (yi - ŷ_i^(j)) ),其中 ŷ_i^(j) 是使用当前所有权重(但特征 j 的贡献被暂时移除)对第 i 个观测值的预测。
3. 应用包含 Zj 的软阈值规则
最后,在根据软阈值规则设置新的权重 ŵj 时,规则有所变化。我们不再直接比较 ρj 与 λ/2,而是需要将相关项除以归一化因子 Zj。
更新规则(代码描述):
if ρj < -λ/2:
ŵj = (ρj + λ/2) / Zj
elif ρj > λ/2:
ŵj = (ρj - λ/2) / Zj
else:
ŵj = 0
算法流程总结
综上所述,未归一化特征的Lasso坐标下降算法流程如下:
- 预计算:为每个特征
j计算Zj = Σ(x_ij²)。 - 初始化:初始化权重向量
w(例如,全零向量)。 - 迭代优化:循环直至权重收敛或达到最大迭代次数。
- 对于每个特征
j(按顺序或随机):- 计算当前模型对每个样本
i的预测ŷ_i(使用所有特征,包括当前的wj)。 - 计算残差
ri = yi - ŷ_i。 - 计算
ρj = Σ( x_ij * ri ) + Zj * wj。(此公式等价于移除特征j贡献后的计算,但更高效) - 根据上述包含
Zj的软阈值规则更新权重ŵj。
- 计算当前模型对每个样本
- 对于每个特征
核心要点
本节课中我们一起学习了Lasso坐标下降法在未归一化特征下的应用。关键点在于:
- 算法本质不变,仍是通过循环更新每个权重来最小化目标函数。
- 主要区别是引入了特征
j的平方和Zj作为归一化因子。 - 在计算相关性
ρj和更新权重ŵj时,都需要考虑这个Zj因子。 - 虽然对未归一化特征实现该算法是直接的,但使用归一化特征能提供更清晰、更直观的算法解释和实现过程。


机器学习:第2课:推导Lasso坐标下降更新

在本节中,我们将深入探讨Lasso回归的坐标下降算法更新规则的推导过程。我们将看到,与普通最小二乘法不同,Lasso的目标函数包含不可微的L1惩罚项,这要求我们引入次梯度的概念来求解。通过本次推导,我们将清晰地理解Lasso解中软阈值形式的来源。


上一节我们介绍了Lasso坐标下降算法的基本形式,本节中我们将详细推导其更新规则。我们使用未标准化的特征进行推导,这是最一般的情况,标准化特征的推导可直接由此得出。
首先,我们回顾Lasso的目标函数,并针对单一坐标 ( w_j ) 进行优化。目标函数包含残差平方和项与L1惩罚项。
残差平方和项的偏导
我们从残差平方和项对 ( w_j ) 的偏导数开始。这与最小二乘法的推导类似,但针对未标准化特征。
我们定义两个关键量:
- ( \rho_j = \sum_{i=1}^n h_j(x_i) \left[ y_i - \sum_{k \neq j} w_k h_k(x_i) \right] )
- ( Z_j = \sum_{i=1}^n h_j(x_i)^2 )
经过推导,残差平方和项对 ( w_j ) 的偏导数为:
[
\frac{\partial}{\partial w_j} \text{RSS} = -2\rho_j + 2 w_j Z_j
]
L1惩罚项的次梯度
接下来处理L1惩罚项 ( \lambda |w_j| )。绝对值函数在 ( w_j = 0 ) 处不可微,因此我们需要使用次梯度。
对于函数 ( g(x) = |x| ),其次梯度 ( \partial g(x) ) 是一个集合:
- 当 ( x > 0 ) 时,( \partial g(x) = {1} )
- 当 ( x < 0 ) 时,( \partial g(x) = {-1} )
- 当 ( x = 0 ) 时,( \partial g(x) = [-1, 1] )
因此,L1惩罚项 ( \lambda |w_j| ) 的次梯度为:
- 当 ( w_j > 0 ) 时,( \lambda \cdot {1} )
- 当 ( w_j < 0 ) 时,( \lambda \cdot {-1} )
- 当 ( w_j = 0 ) 时,( \lambda \cdot [-1, 1] )
合并得到完整目标的次梯度
现在,我们将残差平方和项的偏导与L1惩罚项的次梯度相加,得到整个Lasso目标函数关于 ( w_j ) 的次梯度 ( \partial_{w_j} \text{Cost} ):
[
\partial_{w_j} \text{Cost} = (-2\rho_j + 2 w_j Z_j) + \lambda \cdot \partial |w_j|
]
根据 ( w_j ) 的符号,具体写出三种情况:
- 若 ( w_j > 0 ),则 ( \partial_{w_j} \text{Cost} = -2\rho_j + 2 w_j Z_j + \lambda )
- 若 ( w_j < 0 ),则 ( \partial_{w_j} \text{Cost} = -2\rho_j + 2 w_j Z_j - \lambda )
- 若 ( w_j = 0 ),则 ( \partial_{w_j} \text{Cost} = [-2\rho_j - \lambda, -2\rho_j + \lambda] )
求解最优更新规则
为了找到最优的 ( \hat{w}_j ),我们令次梯度包含零。这需要对上述三种情况分别求解。
以下是求解后得到的最优更新规则 ( \hat{w}_j^{\text{Lasso}} ):
-
如果 ( \rho_j < -\frac{\lambda}{2} ),则:
[
\hat{w}_j = \frac{\rho_j + \frac{\lambda}{2}}{Z_j}
]
(此时解 ( \hat{w}_j < 0 )) -
如果 ( \rho_j > \frac{\lambda}{2} ),则:
[
\hat{w}_j = \frac{\rho_j - \frac{\lambda}{2}}{Z_j}
]
(此时解 ( \hat{w}_j > 0 )) -
如果 ( -\frac{\lambda}{2} \le \rho_j \le \frac{\lambda}{2} ),则:
[
\hat{w}_j = 0
]


理解软阈值规则
这个更新规则体现了软阈值操作。我们可以将其与最小二乘解 ( \hat{w}_j^{\text{LS}} = \frac{\rho_j}{Z_j} ) 进行比较。
- 当 ( |\rho_j| ) 很大(即特征 ( j ) 与残差的相关性很强)时,Lasso解是在最小二乘解的基础上向零收缩了 ( \frac{\lambda}{2Z_j} )。
- 当 ( |\rho_j| ) 较小(低于阈值 ( \frac{\lambda}{2} ))时,Lasso解被直接置为零,这便产生了模型的稀疏性。
参数 ( Z_j )(特征 ( j ) 的平方和)起到了缩放作用。特征尺度越大(( Z_j ) 越大),阈值区间 ( [-\frac{\lambda}{2}, \frac{\lambda}{2}] ) 在 ( \rho_j ) 尺度上看起来越宽,但收缩量 ( \frac{\lambda}{2Z_j} ) 越小。


本节课中我们一起学习了Lasso坐标下降更新规则的完整推导。核心在于使用次梯度处理L1惩罚项的不可微性,并通过对三种情况的分析,最终得到了具有软阈值形式的更新公式。该公式清晰地解释了Lasso如何通过将较小系数置零来产生稀疏解,以及系数收缩的机制。理解这个推导有助于我们更深入地掌握Lasso回归的内在原理。
机器学习:第2课:选择惩罚强度与Lasso的其他实际问题


在本节课中,我们将学习如何为Lasso回归选择合适的惩罚强度参数λ,并探讨Lasso在实际应用中的几个重要问题,包括如何降低其估计偏差,以及它在处理强相关特征时的局限性。
选择惩罚强度参数λ
上一节我们介绍了使用坐标下降法求解特定λ值下的Lasso目标函数。本节中我们来看看如何选择合适的λ值。
选择λ值的方法与岭回归完全相同。以下是两种主要方法:
- 验证集法:如果数据量充足,可以预留一个验证集,通过比较不同λ值下模型在验证集上的表现来选择最优的λ。
- 交叉验证法:如果数据量有限,则可以使用交叉验证的方法来选择λ。
这些方法旨在选择能提供最佳预测精度的λ值。但需要指出的是,为了追求最佳预测精度,这些方法往往会选择一个比“最优模型选择”所需的λ值稍小的值。这是因为在有限的数据集上,包含少量不相关特征的模型,其预测效果有时可能比真正的、最稀疏的模型更好。关于如何为模型选择目的更精确地选择λ,可以参考Kevin Murphy的《Machine Learning: A Probabilistic Perspective》等教材进行深入探讨。

Lasso的实用问题与解决方案

在选择了λ并得到Lasso模型后,我们还需要了解其在实际应用中的一些特性。本节将讨论两个关键问题及其应对策略。
问题一:偏差与去偏
正如我们在本模块中多次看到的,Lasso通过将系数向零收缩来增加解的偏差,以换取更低的方差,这是一种自动的偏差-方差权衡。但有时我们仍希望得到一个低偏差的解。
我们可以通过以下方式降低Lasso解的偏差,这种方法称为Lasso去偏:
- 运行Lasso求解器,得到一组被选中的特征(即权重不为零的特征)。
- 仅使用这组被选中的特征构成一个简化模型。
- 在这个简化模型上运行标准的最小二乘回归。
这样,那些被判定为相关的特征,其权重将不会像原始Lasso解那样被收缩,而是会得到与仅在该简化模型上做最小二乘估计时相近的、无偏的权重。整个过程的核心在于,Lasso帮助我们完成了特征选择,然后我们在选出的模型上进行无偏估计。
下图展示了去偏带来的好处:

- 第一行(True):展示了真实数据生成所用的系数,共有4096个特征,但只有160个具有非零系数,是一个非常稀疏的设置。
- 第二行(L1):Lasso回归的结果,它发现了1024个非零权重的特征,均方误差为0.0072。
- 第三行(Debiased):对Lasso选出的1024个特征进行最小二乘回归(去偏)后的结果,其均方误差显著降低。
- 第四行(LS):作为对比,如果在全部4096个特征上直接进行最小二乘回归,会得到一个非常差的估计和巨大的均方误差。
这个例子说明了结合使用Lasso进行特征选择,再对选中特征进行去偏的重要性。
问题二:强相关特征与弹性网络
Lasso的另一个问题是,当存在一组强相关特征时,它倾向于近乎随机地从中选择一个,而排除其他。这意味着数据的微小变动可能导致被选入的变量完全不同。例如,在房价预测中,“房屋面积”和“地块大小”可能高度相关,Lasso可能会在它们之间任意选择。但在许多情况下,我们可能希望将整个相关特征组都纳入模型。
此外,经验表明,在许多情况下,岭回归的预测性能实际上优于Lasso。
为了应对这些问题,出现了Lasso的变体,称为弹性网络。它融合了岭回归和Lasso的目标,同时包含L1惩罚项和L2惩罚项。其目标函数可以表示为:
最小化:RSS(w) + λ₁ * ||w||₁ + λ₂ * ||w||₂²
其中,||w||₁ 是L1范数(用于特征选择),||w||₂² 是L2范数的平方(用于处理共线性)。弹性网络旨在同时获得稀疏性和对相关特征组的稳定选择。关于弹性网络如何解决原始Lasso目标函数问题的更多讨论,可以参考相关论文。
总结

本节课中我们一起学习了为Lasso回归选择惩罚参数λ的实用方法,主要包括验证集法和交叉验证法。我们还探讨了Lasso的两个实际问题:首先,其解存在偏差,我们可以通过“去偏”步骤,即在Lasso选出的特征上运行最小二乘回归来降低偏差;其次,Lasso在处理强相关特征时可能不稳定,而弹性网络通过结合L1和L2惩罚项,为解决这一问题提供了方案。
机器学习:第2课:特征选择与Lasso回归回顾 🎯

在本节课中,我们将回顾机器学习回归模块中关于特征选择的核心内容。我们将总结已学习的关键概念,包括特征选择的任务、搜索方法、Lasso正则化回归及其重要性,并讨论在解释所选特征时需要注意的问题。
模块内容总结 📚

上一节我们介绍了特征选择的基本任务及其挑战。本节中,我们来回顾本模块涵盖的核心知识点。
本模块深入探讨了特征选择任务。我们描述了搜索所有可能特征子集以构建最佳模型的方法。
我们讨论了该方法在计算上面临的挑战,随后转向贪心算法的思考,并介绍了用于处理特征选择任务的Lasso正则化回归方法。
本模块覆盖了机器学习中许多非常重要的概念。
Lasso回归的影响与注意事项 ⚠️
尽管Lasso正则化回归方法非常简单,但它极大地改变了机器学习、统计学和工程学领域。
该方法在多种不同的应用领域中都显示了其实用性。
但需要提及一个非常重要的问题,我们在之前也有所暗示。对于特征选择,不仅仅是Lasso,在一般情况下思考特征选择时,必须非常小心地解释你所选择的特征。
以下是需要注意的原因:

- 特征选择范围的局限性:所选特征始终只是在你最初提供的可能特征集合的背景下进行的。
- 特征相关性的敏感性:所选特征集对特征之间的相关性非常敏感。在这些情况下,数据的微小变化可能导致包含不同的特征。因此,声称某个特征重要而另一个不重要时,必须谨慎对待此类陈述。
- 算法依赖性:所选特征集还取决于你使用的算法。特别是在讨论前向逐步选择等贪心算法时,我们清楚地看到了这一点。

不过需要指出,在非常特定的条件下,Lasso有一些很好的理论保证。
本模块掌握的技能清单 ✅
在完成本模块后,你现在可以执行以下一长串任务:
- 离散模型空间搜索:思考在可能的模型离散集合上进行搜索,以进行特征选择,可以使用全子集法或贪心算法。
- 正则化回归公式化:构建Lasso正则化回归方法,以隐式地进行特征选择,在一个连续空间(即调优参数λ)上进行搜索。
- 目标函数与几何解释:我们讨论了目标函数的构建,以及为什么Lasso目标函数会导致稀疏性的几何解释。
- 坐标下降算法:我们讨论了使用坐标下降作为求解Lasso的算法。坐标下降法本身是一个适用范围远超出Lasso的算法,这也是我们从本模块中获得的一个重要概念。
- 高级概念(可选):如果你观看了可选视频,我们还讨论了一些与次梯度相关的技术性概念。
最后,为了总结本模块,我们讨论了与Lasso相关的一些挑战,以及该方法可能产生的影响,因为它确实是一个非常重要的工具。正如我所提到的,它在许多不同领域都显示了巨大的潜力。
总结 🏁

本节课中,我们一起回顾了机器学习回归模块关于特征选择的核心内容。我们总结了特征选择的多种方法、Lasso正则化回归的原理与巨大影响,并重点强调了在解释所选特征时需要保持谨慎。此外,我们还列出了通过本模块学习所掌握的一系列重要技能和算法。理解这些概念对于构建有效且可靠的机器学习模型至关重要。
机器学习:第2课:非参数回归与局部拟合 🧩

在本节课中,我们将要学习一种全新的建模思路——非参数回归方法。我们将重点介绍 K近邻(K-Nearest Neighbors) 与 核回归(Kernel Regression)。与之前学习的参数化模型不同,这些方法不预先设定固定的函数形式,而是让模型的复杂度随着数据量的增加而增长,从而获得极大的灵活性。它们的实现非常简单,并且在拥有足够数据时,效果往往出人意料地好。
全局拟合 vs. 局部拟合 🌍
上一节我们介绍了基于特定特征集的参数化模型,其灵活性是固定的。本节中我们来看看一种不同的思路:局部拟合。
为了理解这个概念,让我们想象一个关于房屋面积(平方英尺)与售价的数据集。假设对于小户型房屋,面积与价格呈线性关系;对于中等户型,面积增加对价格的影响变小;而对于豪宅,面积增加可能导致价格大幅上升。
在之前介绍的模型中,我们尝试用一个函数(如常数、直线、二次或三次曲线)来拟合整个输入空间(所有面积范围)的数据。例如:
- 一个常数拟合可能是一条水平线。
- 一个线性拟合可能是一条斜线。
- 一个三次曲线拟合可能看起来更贴合数据点。

然而,这种全局拟合的问题在于,它试图用同一个函数形式描述所有区域的关系。这可能导致在某些区域(如小户型区)模型过于复杂,而在另一些区域又不够灵活。

这促使我们思考:能否在不同的输入区域局部地拟合函数?或者说,我们能否拥有比全局拟合模型更灵活的、针对局部数据的描述能力?这就是局部拟合的核心思想。
K近邻回归(K-NN Regression)📏
我们希望灵活地定义函数 f(x)(即面积与房价的关系),使其能捕捉这种局部结构,但又不想手动设定所谓的“结构断点”。以下是一种在拥有大量数据时非常有效的简单方法。
核心思想:要预测一个新数据点 x 的输出值,我们只需找到训练数据中与 x 最接近的 K 个点,然后用这 K 个点的输出值的(加权)平均作为预测值。
算法步骤:
- 确定邻居数量
K:选择一个正整数K。 - 计算距离:对于待预测点
x,计算它与训练集中所有点的距离(通常使用欧氏距离)。 - 找到K个最近邻:找出距离最近的
K个训练样本。 - 进行预测:将这
K个邻居的输出值(房价)取平均,作为x的预测值。
公式表示:
预测值 ŷ 的计算公式为:
ŷ = (1/K) * Σ(y_i),其中求和针对 x 的 K 个最近邻。
代码描述(伪代码):
def knn_predict(x, training_data, K):
# 计算x与所有训练点的距离
distances = [distance(x, train_x) for train_x in training_data.x]
# 获取K个最近邻的索引
nearest_indices = argsort(distances)[:K]
# 获取这些邻居的输出值
neighbor_values = training_data.y[nearest_indices]
# 返回平均值作为预测
return mean(neighbor_values)
特点:
- 简单直观:没有复杂的模型参数,只有邻居数量
K需要选择。 - 极度灵活:模型形状完全由数据驱动,可以拟合非常复杂的模式。
- 数据依赖性:模型“记住”了训练数据,预测时需要计算与所有训练点的距离。
核回归(Kernel Regression)🕯️
K近邻回归有一个特点:它对 K 个最近邻一视同仁,而完全忽略更远的点。核回归对此进行了平滑的改进。
核心思想:所有训练点都对待预测点 x 的预测有贡献,但贡献的权重根据该点与 x 的距离而定。距离越近,权重越大;距离越远,权重越小,直至可以忽略。
关键组件——核函数 K(z):
核函数是一个用来分配权重的函数,它描述了距离与权重之间的关系。常见的核函数有高斯核(钟形曲线)、Epanechnikov核等。核函数通常满足:距离 z=0 时权重最大,随着 |z| 增大,权重平滑地衰减至0。
公式表示:
预测值 ŷ 的计算公式为加权平均:
ŷ = Σ [ w_i * y_i ] / Σ w_i
其中,权重 w_i = K( (x - x_i) / h ),h 是一个称为带宽(bandwidth) 的参数,控制着权重衰减的速度(即影响的局部范围)。
代码描述(伪代码):
def kernel_predict(x, training_data, bandwidth, kernel_func):
weights = []
values = []
for train_x, train_y in training_data:
# 计算标准化距离
z = (x - train_x) / bandwidth
# 计算权重
weight = kernel_func(z)
weights.append(weight)
values.append(train_y)
# 计算加权平均作为预测
prediction = sum(w*v for w, v in zip(weights, values)) / sum(weights)
return prediction
特点:
- 更平滑的预测:预测输出是所有权重贡献的平滑组合,结果通常比K-NN更连续、光滑。
- 带宽
h是关键:h控制模型的平滑程度。h太大,模型过于平滑(欠拟合);h太小,模型会对噪声过于敏感(过拟合)。
总结 📚
本节课中我们一起学习了非参数回归的核心思想与方法。
- 思路转变:我们从全局拟合(用单一函数描述全体数据)转向了局部拟合(在不同数据区域自适应地描述关系)。
- K近邻回归:通过查找最近邻的
K个点并取平均进行预测。公式:ŷ = mean(y_neighbors)。其实现简单,灵活性高。 - 核回归:通过核函数为所有数据点分配距离权重,进行加权平均预测。公式:
ŷ = Σ [K((x-x_i)/h) * y_i] / Σ K((x-x_i)/h)。它提供了比K-NN更平滑的预测曲线。

这两种方法都极度依赖数据,需要足够多的数据点才能对局部区域做出可靠估计。它们的强大之处在于,无需预先假设数据的全局函数形式,模型的复杂度能随着数据量的增加而自然增长,从而在许多复杂现实问题上表现出色。
机器学习:第2课:最近邻回归方法 🏠


在本节课中,我们将要学习一种非常直观且基础的回归方法——最近邻回归。我们将从核心思想开始,逐步形式化其算法,并探讨其在多维空间中的应用。
概述
最近邻回归是一种简单直接的预测方法。其核心思想是:当需要预测一个新数据点的值时,只需在已有数据中找到与它最相似(即“最近”)的那个观测点,并将该观测点的值直接作为预测值。
最近邻回归的核心思想
上一节我们概述了基本概念,本节中我们来看看其具体的工作方式。
假设我们有一些数据点,如上图中的蓝色圆圈所示。当你想预测输入空间中任意一点(例如,你的房子的面积)对应的输出值时,你只需找到数据集中与你的房子最接近的那个观测点(即“最近邻”),并将其输出值直接作为你的房子的预测值。
这可能是你能想到的最简单的模型。图中的绿色拟合线展示了这种方法的预测结果,小箭头指示了每个查询点对应的最近邻观测点。这导致了一种“局部拟合”的效果,每个局部拟合区域都围绕着一个观测点,其范围大小取决于其他观测点的位置。
这种方法被称为 1-最近邻回归。这实际上也是人们自然而然的做法。例如,一位房地产经纪人评估你的房子价值时,他会查看所有已售出的房子,并问:“哪套房子与你的房子最相似?它卖了多少钱?”这位经纪人隐式地就是在执行最近邻回归:寻找与你房子最相似的“最近邻”,并将其售价作为对你房子价值的评估。

形式化最近邻方法

理解了直观思想后,现在我们来形式化定义这个算法。
我们有一个数据集。在房价应用中,它是成对的房屋属性和对应价值(售价)的集合。我们将其表示为 (X, y),共有 N 个观测点。这是我们假设拥有的数据。
同时,我们有一个查询房屋 X_q,它不在我们的训练数据中,是我们感兴趣并想预测其价值的房子。
最近邻方法的第一步是:在数据集中找到与查询房屋最接近的其他房屋。
具体来说,我们定义 最近邻 X_nn 为那个能最小化其与查询点 X_q 之间距离的观测点 X_i。用公式表示如下:
X_nn = argmin_i distance(X_i, X_q)
在之前的图示中,X_nn 就是那个粉色的大房子。
然后,我们简单地预测查询房屋(图中的绿色大房子)的价值,恰好等于这个最近邻房屋(粉色大房子)的售价。
预测值 = y_nn (其中 y_nn 是 X_nn 对应的真实输出值)
这是一个非常直接的算法。关键点在于 距离度量,它衡量了查询房屋与数据集中任何其他房屋的相似程度。这个度量定义了数据集中“最接近的房屋”的概念,是算法性能的核心,决定了哪个房子会被认为与你的房子最相似。我们稍后会详细讨论距离度量。
高维空间中的最近邻
到目前为止,我们假设只有一个输入特征(如房屋面积)。在那种情况下,我们需要定义这些“过渡点”,在这些点上,最近邻从一个观测点切换到另一个,从而改变整个输入空间上的预测值。
那么,我们如何在高维空间中思考这个问题呢?我们可以借助 Voronoi 图(或 Voronoi 镶嵌)来可视化。上图展示了一个二维空间中的 Voronoi 镶嵌,但这个概念可以推广到更高维度。
以下是其工作原理:
我们将输入空间划分为多个区域。在二维情况下,这些区域就是二维平面上的多边形。每个区域由一个观测点定义。区域的定义是:对于该区域内的任何其他点 X,它到其所属观测点 X_i 的距离,小于到数据集中任何其他观测点 X_j 的距离。
用公式表示,对于区域内的点 X,满足:
distance(X, X_i) < distance(X, X_j),对于所有 j ≠ i。
这意味着,如果 X 是我们的查询点 X_q,那么当我们预测 X_q 的值时,我们只需查看该区域内观测点 X_i 对应的值 y_i。
Voronoi 图看起来可能很复杂,但我们实际上并不需要显式地构建所有这些区域。我们只需要能够计算输入空间中任意两点之间的距离,并确定哪个观测点是最接近的即可。
总结

本节课中我们一起学习了最近邻回归方法。我们从其“寻找最相似数据点并直接借用其值”的直观思想开始,然后将其形式化为一个具体的算法,涉及寻找最近邻和距离度量。最后,我们探讨了如何通过 Voronoi 图的概念,将这种方法理解并扩展到高维输入空间。这是一种简单而强大的基线方法,体现了机器学习中“相似输入产生相似输出”的基本假设。
机器学习:第2课:距离度量 📏

在本节课中,我们将要学习最近邻算法中的一个核心概念:距离度量。我们将探讨如何定义和计算两个数据点之间的距离,尤其是在多维空间中,并了解不同的距离度量方式如何影响模型的预测结果。
距离的定义
在最近邻算法中,我们需要一个方法来衡量数据点之间的“相似性”或“距离”。在一维空间中,这非常简单。对于连续空间,我们通常使用欧几里得距离。具体来说,给定一个输入点 X 和一个查询点 Xq,我们计算这两个数字之间的绝对差值。例如,这可以代表两栋房屋的平方英尺面积,我们只需计算它们差值的绝对值。
公式:距离 = |X - Xq|
多维空间的距离度量
当我们处理更高维度的数据时,有许多有趣的距离度量方法可以考虑。接下来,我们将介绍一种在实践中非常实用的方法:加权欧几里得距离。这种方法的核心思想是,为不同的维度分配不同的权重,但除此之外,其计算方式与标准欧几里得距离类似。
为了理解其动机,让我们回到房屋预测的例子。假设我们有一组描述房屋属性的输入特征,例如卧室数量、浴室数量和房屋面积。当我们思考“哪栋房子与我的房子最相似”时,某些特征可能比其他特征更重要。例如,卧室数量、浴室数量和房屋面积在评估相似性时,可能比房屋的翻新年份更为相关。
为了考虑这一点,我们可以定义一个缩放欧几里得距离。我们计算输入向量 Xj(训练数据点)和查询向量 Xq 之间的距离。具体做法是,对每个维度计算差值的平方,然后乘以一个缩放系数,最后对所有维度的结果求和并取平方根。
公式:距离 = sqrt( Σ [ a_d * (Xj_d - Xq_d)^2 ] )
其中,a_d 是第 d 个维度的缩放系数,它捕捉了该维度在计算相似性时的相对重要性。如果所有权重 a_d 都等于1,那么这个公式就简化为标准的欧几里得距离。
不同距离度量的影响
不同的距离度量方式会直接影响最近邻模型的预测结果。为了直观地理解这一点,我们可以观察不同距离度量下数据区域的划分情况。
以下是两种不同距离度量的可视化效果:
- 标准欧几里得距离:在右侧的图中,不同颜色代表不同区域的预测值。每个区域内的所有点都具有相同的最近邻,因此预测值也相同,形成了颜色恒定的区域。
- 曼哈顿距离:在左侧的图中,区域划分的方式有所不同。曼哈顿距离的计算方式类似于在纽约街道上开车,它测量的是沿坐标轴方向的距离总和,即X方向的距离加上Y方向的距离。这与标准的欧几里得距离不同。
公式(曼哈顿距离):距离 = |Xj_x - Xq_x| + |Xj_y - Xq_y|
由于距离的定义方式不同,数据空间的区域划分也会随之改变,从而影响模型的预测边界和结果。
总结

本节课中,我们一起学习了距离度量的概念及其在最近邻算法中的重要性。我们从一维空间中的简单绝对距离开始,扩展到多维空间中的加权欧几里得距离,理解了如何通过为不同特征分配权重来捕捉其在相似性判断中的重要性。最后,我们通过可视化对比了标准欧几里得距离和曼哈顿距离如何导致不同的预测区域划分。选择合适的距离度量是构建有效最近邻模型的关键一步。
机器学习:第2课:最近邻算法

在本节课中,我们将学习最近邻算法的具体实现方法。我们将了解如何通过指定查询点、数据集和距离度量来执行最近邻搜索,并观察该算法在不同数据分布下的表现。
上一节我们直观地讨论了最近邻算法的工作原理。本节中,我们来看看如何在实践中具体实现最近邻算法。
为了执行最近邻搜索,我们需要完成以下步骤:
- 指定一个查询输入,例如我们想要评估其价值的房屋。
- 提供我们的数据,即训练用的房屋集合。
- 指定一个距离度量,用于衡量房屋之间的相似性。
最近邻搜索的输出将是与查询点最相似的房屋。我们可以使用该房屋对应的价值,作为我们对查询房屋的预测值。
更具体地说,一最近邻算法的伪代码如下:
初始化 distance_to_nearest_neighbor = 无穷大
初始化 closest_house = 空集
对于数据集中的每一个房屋:
计算 查询房屋 到 当前房屋 的距离
如果 该距离 < distance_to_nearest_neighbor:
设置 closest_house = 当前房屋
设置 distance_to_nearest_neighbor = 该距离
返回 closest_house
算法首先将“到最近邻的距离”初始化为无穷大,将“最近邻房屋”初始化为空。然后,它遍历数据集中的每一个房屋,计算其与查询房屋的距离。如果该距离小于当前记录的最小距离,则更新最近邻房屋和最小距离值。遍历结束后,返回最相似的房屋,其对应的价值即为预测值。
现在,让我们看看这个算法在实际数据上的表现。
下图展示了一组从一个具有曲线形状的真实函数中抽取的观测数据。蓝线代表用于生成这些数据的真实函数,而绿线代表我们的一最近邻拟合结果。

可以看到,在输入空间(X轴)数据密集的区域,拟合效果相当好。我们在整个输入空间获得了大量观测值。
然而,如果我们在输入空间的某个区域移除一些观测数据,情况就开始变得不那么理想。

最近邻算法很难在没有任何观测值或观测值非常稀少的输入空间区域进行有效插值。
同样地,如果我们观察一个噪声更大的数据集,会发现最近邻拟合也变得非常不稳定。

这看起来就像我们之前讨论过拟合模型时展示的图表类型。由此可见,一最近邻算法对数据中的噪声也非常敏感。


本节课中,我们一起学习了最近邻算法的具体实现步骤,并通过图示观察了其表现。我们了解到,该算法在数据密集区域表现良好,但在数据稀疏或噪声较大的情况下,其拟合结果可能不稳定或出现过拟合现象。
机器学习:第2课:K-最近邻回归

在本节课中,我们将要学习一种名为 K-最近邻 的回归方法。它是我们上一节介绍的“1-最近邻”回归的一个简单而强大的扩展。我们将了解其核心思想、工作原理以及如何在实际中实现它。
从1-最近邻到K-最近邻
上一节我们介绍了1-最近邻回归,它通过寻找与查询点最相似的一个数据点来进行预测。然而,这种方法可能不够稳定,因为单个数据点的值可能受到特殊因素(例如,房屋在特定时间以异常价格售出)的影响。
为了获得更可靠的估计,我们可以借鉴房地产评估师的常用方法:他们不会只看一套“可比房屋”,而是会收集一组相似的房屋(即“可比销售”或“comps”),并基于这组房屋的价值来评估目标房屋。K-最近邻回归正是基于这一思想。
K-最近邻的核心概念
K-最近邻方法接收与之前相同的数据集和一个查询点。它的目标是找到数据集中与查询点最相似的 K 个观测值。
具体来说,我们定义一组 K个最近邻:x_nearest_neighbor_1, x_nearest_neighbor_2, ..., x_nearest_neighbor_K。我们假设这些邻居已按与查询点的相似度(距离)排序,因此 x_nearest_neighbor_K 是这组中最不相似(距离最远)的一个。
这组最近邻的定义是:对于数据集中 任何不在 这组最近邻中的观测点 x_i,其与查询点 x_q 的距离,都 大于或等于 第K个最近邻 x_nearest_neighbor_K 与 x_q 的距离。这意味着所有其他数据点都比我们选出的第K个邻居更远。
如何进行预测?
在1-最近邻回归中,预测值就是最近邻对应的输出值 y。但现在我们有了K个最近邻,每个都有其输出值 y_nearest_neighbor_j。
K-最近邻回归的预测方法是:取这K个邻居输出值的 平均值。
我们可以用以下公式表示:
预测值 = (1/K) * Σ (y_nearest_neighbor_j),其中求和下标 j 从 1 到 K。
或者写成代码形式:
prediction = sum(y_nearest_neighbors) / K
这种方法通过平均多个相似点的值,平滑了单个数据点可能存在的噪声或异常,从而得到更稳健的预测。
K-最近邻搜索算法实现
了解了核心思想后,本节我们来看看如何在实践中实现K-最近邻搜索。其设置与1-最近邻类似,但目标变为输出K个最相似的房屋。
以下是K-最近邻搜索算法的关键步骤概述。算法的核心在于,在遍历数据的过程中,始终维护一个 有序的、包含当前K个最近邻的队列。
以下是算法步骤的详细说明:
-
初始化:创建一个列表
distance_to_K_nearest_neighbors,用于存储当前K个最近邻的距离。开始时,我们可以将数据集中的前K个房屋作为初始的K个最近邻,并计算它们与查询房屋的距离,然后对这个距离列表进行排序。同时,对应的房屋列表也按此顺序排列。 -
遍历剩余数据:接着,我们遍历数据集中从第K+1个到第N个的所有房屋。
- 对于每一个新房屋,计算其与查询房屋的距离。
- 如果这个距离 小于 当前K个最近邻中 最远那个邻居的距离(即列表中的最大值),则说明这个新房屋应该进入我们的最近邻集合。
-
插入新邻居:
- 由于新房屋的距离比当前第K个邻居小,我们需要找到它在有序距离列表中的正确位置
J。位置J满足:所有索引小于J的邻居都比这个新房屋更近,而新房屋比索引J及之后的所有当前邻居都更近。 - 找到位置
J后,我们需要更新列表。这分为两步:- 首先,将房屋列表从索引
J到K-1的元素向后移动一位,从而“挤掉”原先的第K个房屋(即最不相似的那个)。 - 同样,对距离列表进行完全相同的移位操作。
- 首先,将房屋列表从索引
- 最后,将新房屋插入到房屋列表的
J位置,将其距离插入到距离列表的J位置。
- 由于新房屋的距离比当前第K个邻居小,我们需要找到它在有序距离列表中的正确位置
-
完成与预测:遍历完所有数据后,我们便得到了与查询房屋最相似的K个房屋的集合。要预测查询房屋的值,我们只需计算这K个邻居对应房价的平均值,如上一节所述。
课程总结

本节课中我们一起学习了 K-最近邻回归。我们了解到,它是1-最近邻的自然扩展,通过考虑多个(K个)相似数据点并取其输出值的平均值来进行预测,这种方法能有效减少单个数据噪声带来的影响,使预测更加稳定。我们还详细探讨了在大量数据中高效查找K个最近邻的算法实现,其关键在于动态维护一个有序的最近邻队列。K-最近邻是一个简单直观却非常强大的基础机器学习算法。
机器学习:第2课:K-最近邻的实际应用 🧠

在本节课中,我们将学习K-最近邻(K-NN)算法在实际应用中的表现。我们将通过一个具体的数据集,对比K-NN与1-最近邻(1-NN)的拟合效果,并探讨K-NN算法的优点及其存在的边界效应和不连续性问题。
K-最近邻的拟合效果
上一节我们介绍了1-最近邻算法及其可能产生的噪声拟合。本节中我们来看看当使用K-最近邻(K>1)时,拟合效果如何改善。

图中展示的是对同一个数据集应用K-最近邻算法的结果。我们可以看到,与之前1-最近邻产生的噪声拟合相比,现在的拟合曲线看起来合理得多。
在图中黄色的方框内,我们展示了针对一个特定目标点 x₀ 的所有最近邻。一条红线从我们的查询点(目标点)向上延伸至黄色方框。在这个黄色方框中,所有最近邻的观测点都被高亮显示为红色圆圈(而非其他点的灰色圆圈)。
如果我们考虑对这些点的值进行平均,结果就是绿色曲线在目标点 x₀ 处的值。我们可以对输入空间中的每一个值重复这个过程,最终得到整条绿色的拟合曲线。
因此,我们看到这个拟合结果比之前展示的噪声很大的1-最近邻拟合要合理得多。
边界效应
然而,我们需要指出一个现象:我们得到了这些边界效应。如果输入空间的任何区域数据有限,也会出现同样的情况。
特别是在边界处,我们得到这些恒定拟合值的原因是:对于所有这些不同的输入点,我们的最近邻集合是完全相同的一组点。因为如果我处于边界的最边缘,我的所有最近邻都是在我右侧或左侧的K个点(取决于位于哪个边界)。然后,如果我向右移动一个点,我仍然拥有几乎相同的最近邻集合(显然,除了查询点本身发生变化)。因此,在边界上的每一个点,你使用的基本上是同一组值来计算平均值。
但总体而言,我们看到K-最近邻能够比1-最近邻更好地处理数据中的一些噪声。


不连续性问题
除了边界问题,K-最近邻拟合还存在另一个相当重要的问题:不连续性。


如果你仔细观察这条绿线,会发现它在不同值之间有一系列的跳跃。产生这些跳跃的原因是:当你从一个输入点移动到下一个输入点时,一个最近邻点要么完全进入窗口,要么完全退出窗口。这种效应导致最近邻集合突然发生变化,进而引起预测值的跳跃。
对预测准确性的整体影响可能并不显著,但我们不喜欢这类不连续拟合有几个原因:
- 视觉上可能不太美观。
- 从应用角度考虑,这不符合常理。
以下是具体说明:
以我们的房屋估价应用为例。这意味着,如果我们从一栋2640平方英尺的房子,换到一栋2641平方英尺的房子,在你看来,这对评估价值可能不会有太大差别。但如果这两个点之间存在不连续性,就意味着预测值会发生跳跃。我的房子有一个预测值,我仅仅增加一平方英尺,预测值就可能出现显著的增长或下降。
在房屋估价这类应用中,这是非常不合理的。更普遍地说,我们通常不相信这类具有跳跃性的拟合模型。


总结


本节课中,我们一起学习了K-最近邻算法的实际应用。我们看到了通过平均多个最近邻点的值,K-NN能够有效减少1-NN带来的噪声,产生更平滑、更合理的拟合。然而,我们也分析了K-NN算法的两个主要局限性:在数据边界处产生的边界效应,以及由于最近邻集合突变导致的预测曲线不连续性。理解这些优缺点对于在实际问题中正确选择和使用K-最近邻算法至关重要。
机器学习:第2课:加权K-最近邻

在本节课中,我们将要学习一种改进的K-最近邻算法,称为加权K-最近邻。这种方法通过调整不同邻居的权重,使预测结果更加平滑和稳定。
上一节我们介绍了基本的K-最近邻算法,本节中我们来看看如何通过引入权重来优化其预测性能。
加权K-最近邻的核心思想
加权K-最近邻的核心思想是:根据邻居与查询点(目标点)的距离远近,赋予不同的权重。距离查询点较近的邻居对预测的影响更大,而距离较远的邻居影响则被削弱。
这样做的好处是,当我们从一个查询点切换到另一个查询点时,即使最近邻集合中的成员发生变化,由于较远的邻居已被赋予较低的权重,其对最终预测值的“跳入”或“跳出”影响就不会那么显著。
如何定义权重
在加权K-最近邻中,我们对每个最近邻观测值赋予一个权重。这个权重通常表示为 C_{Q, j},其中 Q 代表查询点,j 代表第 j 个最近邻。
权重的定义原则很简单:
- 如果查询点与某个邻居的距离很大,我们希望赋予它的权重常数非常小,以削弱该观测值的影响。
- 反之,如果距离很小(即房屋非常相似),我们希望赋予它的权重较大。
以下是定义权重的一种简单方法:
权重 = 1 / 距离
用公式表示即:
C_{Q, j} = 1 / distance(X_j, X_Q)
这个公式实现了我们的目标:距离越大,权重越小;距离越小,权重越大。
更通用的方法:核函数
更一般地,我们可以使用核函数来定义这些权重。核函数是距离的函数,它描述了权重如何随着查询点与数据点之间距离的增加而衰减。
在本课程中,我们主要关注最简单的各向同性核,这类核函数仅依赖于点与查询点 X_Q 之间的距离。
以下是几种常用的核函数示例:
- 高斯核:权重随距离呈指数衰减,永远不会精确变为零。
- 公式:K_λ(d) = exp(-d² / λ)
- 参数 λ 控制衰减速度。
- Epanechnikov核:在距离超过一定范围(如 [-λ, λ])后,权重精确变为零。
- 三次核:同样,在边界外权重精确为零。
这些核函数都有一个共同参数 λ,它决定了权重随距离衰减的快慢。
从单变量到多变量空间

我们之前的描述假设只考虑一个输入特征(如房屋面积),距离计算使用简单的绝对值差(即一维欧几里得距离)。
然而,加权K-最近邻可以轻松扩展到具有多个特征的高维空间。方法完全一致:
- 根据你定义的方式(通常是欧几里得距离)计算多变量空间中查询点与每个数据点之间的距离。
- 将这个距离值代入你选择的核函数中,计算出对应的权重。
总结


本节课中我们一起学习了加权K-最近邻算法。我们了解到,通过根据距离为K个最近邻分配不同的权重,可以使得预测模型对邻居集合的变化不那么敏感,从而产生更平滑的预测结果。我们介绍了权重的核心思想,探讨了使用1/距离的简单加权方法,并引入了更通用的核函数(如高斯核)来定义权重衰减。最后,我们明确了这些概念可以自然地推广到多特征的高维数据空间中。
机器学习:第2课:从加权K-NN到核回归 📈


在本节课中,我们将学习一种与加权K近邻(K-NN)密切相关但略有不同的方法——核回归。我们将探讨其核心思想、工作原理,以及如何选择关键参数来获得良好的预测效果。
上一节我们介绍了加权K-NN,它通过距离为K个最近邻分配权重。本节中,我们来看看核回归如何将这一思想推广到整个训练集。
核回归的核心思想是:为训练集中的每一个观测值都分配一个权重,而不仅仅是K个邻居。预测值是通过对所有观测值的加权平均计算得出的。
以下是核回归的预测公式:
公式:
ŷ(x_q) = Σ_i [ C_qi * y_i ]
其中:
ŷ(x_q)是在查询点x_q处的预测值。y_i是第i个训练观测的真实值。C_qi是赋予第i个观测的权重,它由核函数和带宽参数决定。权重C_qi通常需要归一化,使得所有权重之和为1。
在统计学中,这种方法常被称为Nadaraya-Watson核加权平均。
为了理解核回归的实际效果,让我们看一个例子。图中黄色的曲线区域代表我们选择的一个核函数(本例中是Epanechnikov核)。红色高亮的观测点,是针对目标点 x0 被赋予显著权重的点。

需要强调的是,这里我们没有像在K-NN中那样固定邻居数量(K)。相反,我们选择了一个具有特定带宽(即之前讨论的λ参数)的核函数。这个带宽定义了一个区域,只有落在这个区域内的观测值才会被纳入加权计算。像Epanechnikov这样的核具有有界支撑,这意味着权重只在某个区域内非零,区域外的观测点权重完全为零(被丢弃)。这与例如高斯核(权重处处非零)形成对比。

核回归的拟合过程是:在输入空间的每一个目标点 x0 处,我们都用这个核函数为所有观测值分配权重,然后计算加权平均值作为该点的预测值。对输入空间中的所有点重复此过程,就得到了图中绿色的预测曲线。
因此,核回归的结果与加权K-NN的拟合看起来差异不大。主要区别在于:这里我们不是指定K值,而是通过核函数的带宽参数来指定一个加权区域。可以看到,核回归(以及加权K-NN)的拟合结果比标准K-NN的拟合要平滑得多。
进行核回归时,有两个重要问题:
- 使用哪种核函数?
- 对于给定的核函数,应该选择多大的带宽?
通常,带宽的选择比核函数本身的选择重要得多。为了说明这一点,让我们看看Epanechnikov核在不同带宽下的表现。
以下是不同带宽对拟合效果的影响:
- 带宽过小(λ太小):拟合曲线会剧烈波动,对数据过拟合,方差高,偏差低。
- 带宽适中(λ合理):拟合曲线看起来比较合理,能捕捉趋势又不过度波动。
- 带宽过大(λ太大):拟合曲线会变得过度平滑,无法很好地反映数据的细节,偏差高,方差低。
这体现了经典的偏差-方差权衡。带宽参数λ控制着我们对观测数据的拟合程度。λ小则拟合紧密(低偏差,高方差);λ大则拟合平滑(高偏差,低方差)。图中蓝色曲线代表真实的潜在函数。
为了说明我们对核函数的选择相对不敏感,我们将中间图中的Epanechnikov核换成方窗核。方窗核在其定义的窗口内赋予固定权重,窗口外权重为零,这看起来非常像标准K-NN(但固定的是区域大小而非邻居数量K)。尽管方窗核由于“非入即出”的特性会产生不连续性,但其整体拟合曲线与Epanechnikov核的结果非常相似。这正说明了带宽的选择比核函数类型的选择影响更大。
这引出了下一个关键问题:我们如何选择这个至关重要的带宽参数λ?对于K近邻法,等价的问题是如何选择邻居数量K。
在K-NN中,我们同样看到了偏差-方差权衡:当K=1时,拟合曲线疯狂地过拟合;当K取一个较大的合理值时,拟合结果则更稳定、表现更好。
那么,我们如何为这些方法选择调优参数(λ或K)呢?答案与之前讨论过的一样:交叉验证,或者在数据充足时使用验证集。通过评估模型在未见数据上的表现,我们可以选择出使预测误差最小的参数值。


本节课中我们一起学习了核回归方法。我们从回顾加权K-NN出发,了解了核回归通过为所有训练样本赋权来进行预测的核心思想。我们重点讨论了带宽参数的关键作用及其背后的偏差-方差权衡原理,并认识到带宽的选择比核函数类型的选择更为重要。最后,我们指出交叉验证是选择此类模型超参数(如带宽λ或邻居数K)的标准且有效的方法。
机器学习:第2课:全局拟合与局部拟合

在本节课中,我们将学习参数化模型与核回归方法在拟合数据时的核心区别:全局拟合与局部拟合。我们将从最简单的常数拟合开始,逐步理解核回归如何实现局部加权平均,并简要探讨其扩展形式——局部加权线性回归。
全局拟合:常数模型
上一节我们介绍了K近邻与核回归的基本概念。本节中,我们首先来看一种最简单的拟合方式:用常数函数拟合数据。
这被称为计算全局平均值。具体做法是,取所有观测值,将它们相加,然后除以观测值的总数。
用公式表示,即:
全局平均值 = (观测值1 + 观测值2 + ... + 观测值N) / N
这个公式也可以写成加权和的形式,其中每个数据点的权重完全相同,然后除以所有权重的总和。当我们以这种形式来看待全局平均值时,它就开始与核回归的思想非常相似了。
从全局到局部:核回归的思想
以下是核回归与全局平均的关键对比:
- 全局平均(常数模型):这类似于使用一个箱型核函数,该核函数为所有观测点分配完全相同的权重,并且使用一个极大的带宽参数。结果是,对于输入空间中的每一个点,拟合时都包含了所有其他观测点。
- 标准核回归(局部常数拟合):现在我们来看更标准的核回归公式。它与全局平均公式形式一致,但权重由核函数决定。核函数的作用通常是设定一个硬性界限,只考虑目标点
x0附近一个窗口内的观测值。
最简单的例子是局部箱型核,它为目标点 x0 附近的所有观测点分配相等的权重。这样,我们在 x0 处得到一个常数拟合值。然后,我们在下一个目标点进行同样的操作,得到另一个常数拟合值,依此类推。
需要明确的是,最终的输出并不是一个阶梯函数,也不是这些常数块的集合。我们是在每一个独立的点上分别进行一次局部常数拟合,所有这些拟合点的连线就构成了图中绿色的拟合曲线。
如果使用另一个核函数,例如爱普尼科夫核,权重会在固定区域内衰减。它仍然是在进行常数拟合,但它通过降低远离目标点的观测值的权重,提高靠近目标点的观测值的权重来确定这条水平线的高度。这本质上是一个加权的平均,并且由于只考虑了定义窗口内的观测值,所以它是局部的。我们在输入空间的每一个点上进行这种局部加权平均,从而描绘出绿色的曲线。
局部拟合的扩展:从常数到多项式
到目前为止,我们所描述的核回归方法,其动机可以理解为在输入空间的每一个点上局部地拟合一个常数函数。这被称为局部加权平均。
然而,我们不一定非要在每个点拟合一个常数。同理,我们也可以在局部拟合一条直线或一个多项式。这就引出了局部加权线性回归的概念。
本模块不会深入探讨局部加权线性回归的细节,但其思想与局部常数拟合类似,只是将常数替换为直线或多项式。这里,我们提供一些关于如何在不同阶数多项式之间进行选择的经验法则:
- 局部线性拟合 vs 局部常数拟合:使用局部直线而非局部常数,有助于缓解我们之前讨论过的边界效应问题,即边界处存在的较大偏差。可以严格证明,局部线性拟合能有效减少这种偏差。
- 局部二次拟合:局部二次拟合有助于减少在输入空间内部曲率变化点处产生的偏差。例如,在我们一直试图拟合的蓝色曲线中,曲率变化点处存在欠拟合真实曲率的情况。局部二次拟合能更好地捕捉这种曲率。
- 权衡:但局部二次拟合通常会导致方差增大,这可能是一个缺点。
因此,一个基本的通用建议是:使用标准的局部线性回归,即在输入空间的每个点拟合一条直线。
总结


本节课中,我们一起学习了机器学习中两种核心的拟合策略。我们首先回顾了参数化模型的全局拟合思想,并以最简单的常数模型为例。然后,我们深入探讨了核回归所代表的局部拟合思想,看到它如何通过在每一个输入点进行局部加权平均来实现灵活的拟合。最后,我们了解到这种思想可以从局部常数扩展到局部线性甚至多项式拟合,并了解了不同选择在偏差与方差之间的权衡。理解全局与局部的区别,是掌握多种回归方法的关键。
机器学习(回归):第2课:非参数方法与最近邻回归的性能分析 🧠


在本节课中,我们将要学习非参数方法的核心概念,并深入探讨最近邻回归在数据量增加时的性能表现。我们将分析其在无噪声和有噪声数据下的极限行为,理解其与参数化方法的根本区别。
非参数方法简介
上一节我们介绍了最近邻和核回归,本节中我们来看看它们所属的类别——非参数方法。


非参数方法的目标是在定义函数 f(x) 时保持高度灵活性,其核心是尽可能少地做出假设。定义非参数方法的一个关键特性是:模型的复杂度可以随着数据点的增加而增长。我们已经在最近邻和核回归中看到了这一点,其拟合结果直接依赖于观测数据的数量。
除了最近邻和核回归,非参数方法还包括样条、决策树(将在分类课程中讨论)以及我们已讨论过的回归模型的局部加权版本等。非参数方法的核心理念就是让模型复杂度随观测数据量一同增长。
无噪声数据下的最近邻回归
现在,让我们来探讨当数据量不断增加时,最近邻回归的极限行为。首先,我们假设获得的数据是完全无噪声的,即每个观测点都精确地落在真实函数上。
在这种情况下,1-最近邻回归的均方误差(MSE)会随着数据量的增加而趋近于零。回顾一下,均方误差是偏差平方与方差之和(MSE = Bias² + Variance)。MSE趋近于零意味着偏差和方差都趋近于零。
为了直观地理解这一点,请看下面的动态演示。蓝线代表真实曲线,绿线是基于恰好落在真实函数(蓝线)上的一组观测点得到的当前1-最近邻拟合结果。
随着我们获得越来越多的数据,拟合曲线越来越接近真实函数。可以相信,在输入空间中获得无限多个观测点的极限情况下,最近邻拟合将完全覆盖在真实函数之上。这对于我们可能获得的所有无限观测数据集都是成立的。
相比之下,如果我们使用标准的二次拟合(即之前讨论的标准最小二乘拟合),无论获得多少数据,总会存在一些偏差。我们可以看到,尤其是在曲线的弯曲点,即使获得大量观测数据,绿色拟合线也永远不会与真实的蓝色曲线完全匹配。这是因为真实的蓝色曲线实际上是正弦函数的一部分,而二次拟合永远无法精确描述正弦函数。
这就是我们之前讨论的模型固有偏差。即使消除了噪声,随着数据量无限增加,我们的真实误差也永远不会精确地变为零——除非数据恰好是由我们用于拟合的模型生成的,但这在大多数情况下并不成立。
有噪声数据下的最近邻回归
现在我们来讨论更常见的有噪声情况。在大多数实际应用中,我们面对的都是有噪声的数据。
在这种情况下,可以证明:只有当最近邻回归中的邻居数量K也随着观测数据量的增加而增加时,其均方误差才会趋近于零。试想,如果你获得了海量数据但保持K固定,你只会关注输入空间中一个非常局部的区域,并且会引入大量噪声。但如果允许K增长,它就能平滑掉由每个观测点引入的噪声。

让我们通过可视化来理解这一点。下图展示了本模块中一直使用的同一个真实函数,但观测点(灰色点)是有噪声的,它们不再精确地位于蓝色曲线上,因此形成了一片点云。

我们可以看到,1-最近邻拟合结果非常嘈杂,表现出剧烈的波动,正如我们之前讨论的,1-最近邻对数据中的噪声非常敏感。
相反,如果我们观察一个较大的K值(例如K=200的200-最近邻拟合),结果看起来要好得多。可以想象,随着观测数据越来越多,如果你允许K增长,就可以平滑掉每个观测点引入的噪声,从而使均方误差趋近于零。
再次对比,如果我们观察标准最小二乘回归(本例中是二次拟合),我们将始终存在偏差。引入噪声并不会改变这一点,甚至可能使情况变得更糟。
总结
本节课中我们一起学习了非参数方法的核心思想,并重点分析了最近邻回归的性能。我们了解到:
- 非参数方法(如最近邻、核回归)的模型复杂度会随数据量增长,从而提供了极大的灵活性。
- 在无噪声数据下,1-最近邻回归的拟合结果会随着数据量无限增加而收敛到真实函数,其均方误差趋近于零。
- 在有噪声数据下,为了达到同样的效果,必须让最近邻的数目K也随数据量一同增加,以平滑噪声的影响。
- 相比之下,参数化方法(如固定次数的多项式回归)存在固有偏差,即使数据量无限增加,其误差也不会降至零(除非模型设定完全正确)。


理解这些理论特性,有助于我们在实践中根据数据的噪声水平和可获得的数据量,在模型的灵活性与稳定性之间做出明智的权衡。
机器学习:回归:第2课:高维问题:数据稀疏性与计算复杂度 🧮

在本节课中,我们将探讨最近邻回归方法在高维输入空间下遇到的挑战。我们将分析数据稀疏性如何影响模型性能,并讨论朴素最近邻搜索算法的计算复杂度问题。
上一节我们介绍了在拥有海量观测数据时,最近邻回归的表现非常出色。然而,当我们开始增加输入空间的维度,或者观测数据本身有限时,情况就不那么乐观了。
最近邻回归的性能,正如我们之前讨论过的,对数据覆盖输入空间的程度非常敏感。回想一下我们早期的图表,当我们从输入空间的某个区域移除观测数据时,一最近邻拟合的结果会变得很差。
现在想象一下,你面对的是一个维度极高、极其庞大的空间。为了让观测数据覆盖这个空间中的所有点,你需要与空间维度呈指数级增长的观测数据量,才能获得良好的最近邻回归性能。而在这些高维空间中,获取如此大量的观测数据通常非常困难。
因此,在数据量相对于输入空间维度有限的情况下,我们在本课程其余部分讨论的参数化模型就变得至关重要。
另一个需要讨论的重要问题是最近邻搜索的复杂度。我们目前讨论的朴素算法,即在整个数据集上进行暴力搜索,计算量可能相当大。
以下是计算复杂度的具体分析:
- 单点查询:对于一个查询点
Xq,进行一次最近邻搜索,你必须扫描数据中的每一个观测值,并计算到每个观测值的距离。这相当于从查询房屋出发,计算它与数据集中每一栋其他房屋的相似度,以找到最近邻。其复杂度与观测值数量n呈线性关系,即 O(n)。 - K近邻查询:如果我们采用K近邻方法,需要维护一个K个最近邻的列表。如果使用我们讨论过的排序队列方法,可以在 O(n log K) 的复杂度内完成搜索。
无论是单最近邻还是K近邻,其复杂度都与观测值数量 n 呈线性关系。但是,如果 n 非常巨大(这正是我们说K近邻方法表现优异的情况),计算就会变得非常密集。特别是当你需要对输入空间中的许多点进行预测(即执行多次查询)时,这个过程会变得计算量极大。
因此,我们将在后续的专业课程“聚类与检索”中,讨论更高效的最近邻搜索方法。

总结:本节课我们一起学习了最近邻回归在高维空间下面临的两大核心挑战。首先,数据稀疏性问题要求指数级增长的观测数据才能有效覆盖高维空间,这使得参数化模型在数据有限时更具优势。其次,朴素最近邻搜索算法的计算复杂度与数据量呈线性关系,在大规模数据或多查询场景下计算成本高昂,这引出了对更高效搜索算法的需求。
机器学习:第2课:用于分类的K-NN

在本节课中,我们将学习如何将K最近邻(K-NN)算法应用于分类问题。我们将以垃圾邮件过滤为例,介绍其核心思想、具体步骤以及实现方式。
概述

上一节我们介绍了K-NN在回归问题中的应用。本节中我们来看看如何将这一方法用于分类任务。分类与回归的核心区别在于,我们的预测目标是离散的类别标签,而不是连续的数值。我们将通过一个直观的例子——垃圾邮件分类——来理解这个过程。
分类任务与K-NN
我们的任务是构建一个垃圾邮件过滤器。输入是一封电子邮件,输出是一个类别标签:垃圾邮件或非垃圾邮件。这个决策将基于邮件的文本内容、发件人信息、IP地址等特征。
K-NN分类的直观想法是:将所有已标记为“垃圾邮件”或“非垃圾邮件”的邮件样本放置在一个特征空间中。在这个空间里,邮件之间的距离代表了它们在特征(如文本相似度)上的差异。
当我们收到一封新的查询邮件时,我们就在这个特征空间中找到它的K个最近邻(即最相似的K封已知邮件)。然后,我们通过这K个邻居的类别进行多数投票,来决定新邮件的类别。
K-NN分类步骤
以下是使用K-NN进行分类的具体步骤:
- 数据准备与表示:将每封邮件转化为特征向量。例如,可以使用词袋模型来表示文本。
- 距离计算:为查询邮件计算它与训练数据集中所有邮件的距离。常用的距离度量是欧几里得距离。
公式:distance(x, y) = sqrt( sum( (x_i - y_i)^2 ) ) - 寻找邻居:根据计算出的距离,找出距离查询邮件最近的K个训练样本。
- 多数投票:统计这K个邻居中属于每个类别的数量。将查询邮件分配给数量最多的那个类别。
代码逻辑:# 假设 neighbors_labels 是K个邻居的标签列表 predicted_label = max(set(neighbors_labels), key=neighbors_labels.count)
一个具体例子
假设我们有一封待分类的灰色邮件。在特征空间中,我们找到它的5个最近邻(K=5)。其中4个邻居被标记为“垃圾邮件”,1个被标记为“非垃圾邮件”。
通过多数投票,我们预测这封查询邮件为垃圾邮件。这个方法非常直观且易于理解。
总结

本节课中我们一起学习了K最近邻算法在分类问题上的应用。核心思想是“物以类聚”——通过查找特征空间中最近的已知样本,并用它们的类别标签进行多数投票,来预测新样本的类别。我们以垃圾邮件分类为例,介绍了从数据表示、距离计算到多数投票的完整流程。下一节,我们将深入探讨更专门的分类算法。
机器学习:第2课:简要回顾 🧠

在本节课中,我们将对最近邻与核回归方法进行总结,回顾其核心概念、应用与挑战。
概述

本节将总结最近邻与核回归方法。这些方法直观易懂,实现简单,且在众多应用中表现出色。我们将回顾其核心操作、参数选择、理论性质、实践挑战,以及如何将其应用于分类问题。
核心方法回顾
上一节我们介绍了最近邻与核回归的基本思想。本节中,我们来看看这些方法的具体要点。
以下是本模块讨论的核心内容:
- 最近邻回归:我们学习了如何执行1-最近邻或 k-最近邻回归。其核心思想是,对于一个查询点,找到训练集中与其最接近的k个邻居,并用这些邻居目标值的(加权)平均值作为预测。对于k-最近邻回归,预测公式可表示为:
ŷ = (1/k) * Σ(y_i),其中求和针对k个最近邻。 - 核回归:我们探讨了为k个最近邻赋予不同权重的思想,这引出了核回归的概念。核回归使用一个核函数(如高斯核)来根据距离远近为所有数据点分配权重,距离越近权重越高。其预测公式通常为:
ŷ = Σ( K( (x - x_i) / h ) * y_i ) / Σ( K( (x - x_i) / h ) ),其中K是核函数,h是带宽参数。 - 参数选择:对于核回归,存在一个关键的带宽参数选择,这类似于k-最近邻中的K值。我们提到,可以使用交叉验证方法来选择这些参数,以在验证集上获得最佳性能。
- 性质与挑战:我们讨论了k-最近邻与核回归的一些理论和实践方面。当拥有海量数据时,k-最近邻具有非常良好的理论性质。然而,我们也会遇到一些计算上的挑战,以及在数据量不足或输入空间维度极高时面临的困难。
方法拓展:分类问题
最后,我们讨论了如何将k-最近邻方法应用于分类问题。其基本思路与回归类似,但对于一个查询点,我们将其k个最近邻中最常见的类别作为预测类别。
我们将在下一门专门讲解分类的课程中更深入地探讨分类问题。
总结
本节课中,我们一起学习了最近邻与核回归方法。我们回顾了它们的实现方式、参数选择策略、优缺点以及向分类问题的拓展。这些方法以其简单性和广泛适用性,构成了机器学习工具箱中的重要组成部分。
机器学习:第2课:回归课程总结与回顾 🎯

在本节课中,我们将回顾华盛顿大学《机器学习(回归)》课程的核心内容。我们将总结从简单回归到多元回归的关键概念,并展望后续学习方向。

简单回归 📈
上一节我们介绍了机器学习的基础,本节中我们来看看简单回归。简单回归假设我们只有一个输入变量,并拟合一条直线来描述输入与输出之间的关系。
简单回归模型可以表示为:
y = w0 + w1 * x + ε


其中:
- y 是输出变量
- x 是输入变量
- w0 是截距
- w1 是斜率
- ε 是误差项
为了评估不同直线的拟合效果,我们定义了残差平方和(RSS):
RSS = Σ (yi - (w0 + w1 * xi))^2
以下是选择最佳拟合线的步骤:
- 定义目标函数:基于斜率
w1和截距w0的 RSS。 - 使用梯度下降算法最小化 RSS。
- 梯度下降是一种迭代算法,沿负梯度方向移动,对于凸函数能收敛到最优解。
多元回归 🔄
在掌握了简单回归后,我们将其扩展到更复杂的情况。多元回归允许我们使用多个特征来拟合输入与输出之间更复杂的关系。
多元回归模型可以表示为:
y = w0 + w1 * h1(x) + w2 * h2(x) + ... + wk * hk(x) + ε
其中 h1(x), h2(x), ..., hk(x) 是特征函数,它们可以是:
- 多项式项(如
x^2) - 季节性指标
- 其他输入变量的函数(如在房价预测中使用的面积、卧室数量等)
对于多元回归,我们同样使用残差平方和(RSS)作为成本函数,并计算其梯度以进行优化。
参数估计方法 ⚙️
在定义了成本函数后,我们需要找到最优参数。有两种主要方法:
1. 闭式解

当特征矩阵 H 满足条件时,我们可以直接计算最优权重:

ŵ = (H^T * H)^(-1) * H^T * y
优点:直接给出精确解。
缺点:
- 计算复杂度高(与特征数量的立方成正比)。
- 矩阵
H^T * H可能不可逆。
2. 岭回归
为了解决矩阵不可逆的问题,我们引入了岭回归。它对闭式解进行了简单修改,确保矩阵始终可逆:
ŵ = (H^T * H + λI)^(-1) * H^T * y
其中 λ 是正则化参数,I 是单位矩阵。
3. 梯度下降
对于计算成本高昂或矩阵不可逆的情况,梯度下降提供了一种迭代解决方案:
重复直到收敛:
w := w - η * ∇RSS(w)
其中:
- η 是学习率(步长),控制收敛速度。
- ∇RSS(w) 是残差平方和在当前权重
w处的梯度。
梯度下降是一种通用优化算法,将在后续课程中再次出现。
总结 📝
本节课中我们一起学习了回归分析的核心内容。我们从简单回归开始,学习了如何用一条直线拟合数据,并使用梯度下降最小化残差平方和。接着,我们扩展到多元回归,探讨了如何利用多个特征构建更复杂的模型。最后,我们比较了参数估计的几种方法:闭式解、岭回归和梯度下降,理解了它们各自的适用场景与优缺点。


这些关于模型定义、成本函数和优化算法的概念,为理解更广泛的机器学习模型奠定了坚实基础。
机器学习:第2课:性能评估与岭回归

在本节课中,我们将学习如何评估机器学习模型的性能,并介绍一种名为岭回归的技术,它通过控制模型复杂度来防止过拟合,从而提升预测能力。
性能评估:损失与误差
在第一和第二模块中,我们介绍了如何拟合不同的模型。在第二模块中,我们描述了如何拟合非常复杂的模型。但直到第三模块,我们仍不清楚如何评估拟合的模型是否能在预测任务中表现良好。
因此,第三模块的重点是评估拟合模型的性能,并思考如何在不同的模型之间进行选择以获得良好的预测性能。
为了衡量拟合效果,我们引入的第一个概念是损失。这是一种衡量性能的负面指标,我们希望在做不完美的预测时,损失尽可能小。我们讨论了两种常用的损失度量:绝对误差和平方误差。
基于损失函数,我们定义了三种不同的误差度量:
- 训练误差:我们指出,这不是评估模型预测性能的好方法。
- 泛化误差(或真实误差):这是我们真正想要的,它衡量模型对所有可能观测值的预测能力。
- 测试误差:由于无法计算真实误差,我们定义了测试误差。它使用训练集之外的数据子集(测试集),评估在训练数据上拟合的模型对这些“保留”点的预测效果。
测试误差是泛化误差的一个有噪声的近似值。


模型复杂度与误差的关系
对于上述三种误差度量,我们讨论了它们如何随模型复杂度变化:
- 训练误差 随着模型复杂度增加而下降。
- 泛化误差(或真实误差) 在达到某个点后趋于上升。
当模型在训练数据上表现很好,但无法很好地推广到未见过的数据时,我们就说模型过拟合了。虽然我们在回归的背景下讨论,但训练误差、测试误差、泛化误差及其与模型复杂度的关系是一个更普遍的概念,将在后续课程中再次出现。
预测误差的来源
我们分析了构成预测误差的三个不同来源:
- 数据固有噪声(不可约误差):我们无法控制,与模型或估计过程无关。
- 偏差:衡量模型在所有可能训练数据集上的平均拟合能力,描述模型捕捉真实关系的能力。
- 方差:描述拟合函数在不同训练数据集(大小均为
n)之间的波动程度。
数据噪声、模型无法充分描述真实关系(高偏差)以及模型对训练数据的敏感性(高方差)都是预测误差的来源。为了获得良好的预测性能,我们希望偏差和方差都低。
然而,存在偏差-方差权衡:随着模型复杂度增加,偏差下降,但方差上升。因此,存在一个最佳平衡点,能实现最低的均方误差,这正是我们寻求的目标。可以说,机器学习在很大程度上就是在探索这种偏差-方差的权衡。
模型选择与性能评估
为了选择模型并评估其性能,我们需要引入验证集。具体流程如下:
- 在训练集上拟合模型。
- 在验证集上评估不同模型或调整参数,进行模型选择。
- 在从未使用过的测试集上最终测试模型性能。
如果数据不足以划分出验证集,可以采用交叉验证作为替代方法。
岭回归:控制过拟合
在第四模块中,我们讨论了岭回归。随着模型变得越来越复杂,可能会发生过拟合。过拟合的一个典型症状是估计系数的幅度急剧增大。

岭回归通过在目标函数中引入一个惩罚项,来权衡模型对训练数据的拟合程度与系数幅度的大小。通过平衡这两项,我们实际上在进行偏差-方差的权衡。

岭回归的目标函数是:
最小化:残差平方和 + λ * (系数的L2范数)
其中,λ 是惩罚强度参数。我们讨论了随着 λ 变化,岭回归解的系数路径如何变化。随着惩罚参数 λ 增大,系数的幅度会变得越来越小。
与标准最小二乘法类似,我们通过计算梯度并设为零,得到了岭回归的闭式解:
w_ridge = (X^T X + λI)^(-1) X^T y
这个解与之前的标准解类似,但多了一个 λI 项。这个附加项使得即使在特征数量 p 大于观测数量 n 时,我们也能得到一个解,并且能得到一个更“稳定”的解,因此它被称为一种正则化回归技术。其计算复杂度与最小二乘法相同,都是 O(p^3)。
我们还讨论了岭回归的梯度下降实现方法。
岭回归解的关键由 λ 这个惩罚强度参数决定。为了选择这个调整参数,我们讨论了在数据不足时,使用交叉验证程序来代替划分独立验证集的方法。
总结
在本节课中,我们一起学习了:


- 如何通过损失函数和训练/测试/泛化误差来评估模型性能。
- 模型复杂度如何影响不同误差,以及过拟合的概念。
- 预测误差的三个来源:噪声、偏差和方差,以及它们之间的权衡关系。
- 如何使用训练集、验证集和测试集(或交叉验证)来选择和评估模型。
- 岭回归如何通过惩罚系数幅度(L2正则化)来控制模型复杂度、防止过拟合,并在高维情况下提供稳定解。
机器学习(回归):第2课:特征选择、Lasso与最近邻回归 🧠

在本节课中,我们将学习回归模型中的三个核心主题:特征选择、Lasso回归以及最近邻与核回归。我们将探讨如何从众多特征中筛选出最重要的子集,如何使用L1正则化实现稀疏解,以及如何利用数据本身的相似性进行非参数预测。
概述 📋
第五模块的核心内容是特征选择。我们讨论这一主题的动机在于,现实数据(例如房屋属性)往往包含大量特征。为了提高模型的可解释性和预测效率,我们需要从中选择一个稀疏的特征子集来构建模型。
特征选择方法 🔍

为了执行特征选择,我们首先介绍了一类显式搜索不同特征数量模型的方法。

以下是两种主要的搜索策略:
- 全子集选择:这是一种穷举方法,会评估所有可能的特征组合。虽然能找到最优子集,但计算成本极高。
- 前向选择:这是一种贪婪算法。它从一个空模型开始,每次迭代添加一个对模型改进最大的特征。这种方法效率更高,但可能无法得到全局最优解。
Lasso回归:隐式特征选择 ⚙️
上一节我们介绍了显式搜索方法,本节我们来看看如何利用Lasso回归隐式地完成特征选择。
Lasso的目标函数与岭回归相似,但关键区别在于它使用系数的L1范数作为惩罚项,而非L2范数。正是这一改动导致了稀疏解的产生。
其目标函数公式为:
minimize (RSS + λ * Σ|w_j|)
如果我们观察Lasso的系数路径,会发现对于任意给定的正则化参数λ,解通常是稀疏的。随着λ增大,越来越多的系数会变为零。这与岭回归形成鲜明对比:在岭回归中,系数只会不断缩小但很少会精确为零。Lasso的这种特性直接实现了特征选择。
为了优化Lasso目标函数,我们介绍了一种坐标下降算法。该算法通过迭代求解一系列一维优化问题来更新每个特征的系数。
具体来说,对于Lasso,我们最终会根据一种称为软阈值的规则来设置系数。我们定义了一个与特征相关性有关的系数。当这个相关性系数处于某个特定范围内时,对应的模型系数将被精确地设为零;而在这个范围之外时,估计的系数值会相对于最小二乘解进行收缩。
Lasso能够产生稀疏解,这一特性在众多应用领域中都显示出巨大价值。
最近邻与核回归 🌐
在最后一个模块中,我们讨论了一组称为最近邻回归和核回归的非参数技术。
1-最近邻是一个极其简单的过程:要预测一个目标值(如房屋价格),你只需在数据集中找到最相似的样本(房屋),并将其值作为预测值。尽管简单,但在拥有大量数据时,这种方法往往表现优异。
为了使方法更稳健,我们将其推广到K-最近邻回归。我们不是只看最近的一个点,而是查看K个最近邻点,然后取它们的平均值作为预测。
更进一步,我们可以根据这些近邻点与查询点的相似度对它们进行加权,然后计算加权平均值作为最终预测。这直接引出了核回归的思想。
在核回归中,我们不再仅仅加权K个近邻点,而是为数据集中的每一个观测值分配一个权重。不过,我们使用的许多核函数会使距离查询点较远的观测值权重为零,而在一定范围内的权重则随着距离衰减。
这导致了局部拟合的思想。我们讨论了核回归等价于进行这些局部常数拟合,这与我们之前学习的形成全局拟合的参数化模型形成了对比。
下图展示了本模块中介绍的核回归可视化结果。我们可以看到它如何产生非常平滑的拟合曲线。这些拟合能够自适应数据的复杂度,并且随着数据量的增加,其复杂度也可以相应提升。

总结 🎯

本节课我们一起学习了回归中的三个重要概念。我们了解了进行特征选择的动机和方法,包括显式的全子集/前向选择,以及通过Lasso回归实现隐式特征选择的原理。最后,我们探索了最近邻和核回归这两种非参数方法,它们通过局部加权平均的方式进行预测,能够灵活地适应数据的复杂结构。
机器学习:回归:第2课:课程内容总结与展望 🧭

在本节课中,我们将总结本课程已涵盖的核心内容,并简要介绍一些因时间限制而未深入探讨的重要主题。这有助于你建立完整的知识框架,并了解回归分析在更广阔机器学习领域中的位置。

课程内容回顾 📚
上一节我们介绍了多种回归模型,本节中我们来系统回顾一下本课程所涵盖的广泛主题。
我们讨论了一系列模型,包括从简单回归到多元回归的不同线性回归模型。我们还探讨了岭回归、Lasso回归、最近邻回归以及核回归。

此外,我们介绍了一些非常重要的优化算法,例如梯度下降法和坐标下降法。这实质上涉及了“什么是优化”以及“如何进行优化”的核心概念。
然后,我们讨论了那些适用范围远超回归分析本身的重要概念。这些概念包括:
- 损失函数
- 偏差-方差权衡这一核心概念
- 交叉验证
- 稀疏性
- 过拟合
- 特征选择
- 模型选择
这些思想将在本专业系列课程的大部分内容中反复出现。
未涵盖的重要主题 🔮
我们花了大量时间学习本模块的方法并总结所学,现在我想花点时间谈谈本课程未涵盖的内容。实际上,有一些重要主题我们因时间关系未能深入讲解,我在此特别指出。
以下是本课程未涵盖的几个关键方向:
- 多元输出回归:本课程只关注单变量输出(例如房屋价值或售价)。当然,你也可以处理多元输出。当这些输出维度相互关联时,你需要采用更复杂的方法。相反,如果你假设每个输出彼此独立,那么你可以对每个维度独立应用我们描述过的方法。
- 最大似然估计:我们尚未涵盖这个概念,它将在分类课程中详细介绍。但我想指出,在回归的背景下,如果你听说过最大似然估计,并且假设你的模型具有所谓的正态或高斯误差(即我们讨论过的公式 y = Wx + ε 中的 ε 项),那么最大似然估计的结果完全等同于我们在本课程中讨论的最小化残差平方和目标。我们将在分类课程中进一步学习最大似然估计。
- 统计推断:本课程完全没有讨论统计推断,这让我作为一名统计学家感到非常遗憾。我们只专注于所谓的点估计思想,即直接返回一个估计系数 Ŵ。但我们没有讨论任何关于这些估计系数或预测的不确定性度量。数据本身存在噪声,因此我们可以考虑对预测或估计系数进行不确定性度量。这被称为推断,是一个非常重要但我们未涉及的主题。
- 广义线性模型:我们实际上将在分类课程中看到一个广义线性模型的例子。广义线性模型允许你在输出受到特定限制时进行回归建模,例如输出总是正值、有界、或是离散值(如分类课程中将讨论的是/否响应)。如果我们假设误差是高斯分布的(如最大似然估计或本课程所讨论的,具有零均值,观测值等可能地高于或低于真实函数,并且实际上在偏离真实函数的程度上无界),那么当我们预测的值具有此类约束或特定结构时,目前讨论的回归模型就不适用了。广义线性模型使我们能够高效处理某些类型的输出结构。
- 回归树:本课程未描述的另一个强大工具是回归树。这是因为我们将在分类课程中介绍它。实际上,这些方法更普遍地被称为CART(分类与回归树)。无论我们处理分类还是回归,你构建的树结构是相同的。我们将在分类的背景下重点描述这些结构,因为在那样的语境下更容易理解。但我想强调,我们在下一课程中将学习的这些相同工具也可用于回归。
- 其他方法:当然,本课程未描述的方法还有很多很多。回归在统计学中有着极其悠久的历史,因此有许多潜在值得关注的内容。但在本课程中,我们真正专注于对现代机器学习回归应用有用的核心概念。
总结 ✨

本节课中我们一起学习了本回归课程的知识体系总结。我们回顾了已涵盖的核心模型、优化算法及通用概念,如偏差-方差权衡。同时,我们也展望了多元输出回归、统计推断、广义线性模型和回归树等重要但未深入的主题,为你勾勒出回归分析更广阔的图景。这些未涵盖的主题将在后续课程,特别是分类课程中得到延续和深化。
机器学习(回归):第2课:课程总结与展望

在本节课中,我们将对回归课程的核心内容进行总结,并展望机器学习专项课程后续的学习方向。
你们在回归课程中付出了巨大努力,学习了许多至关重要的概念。不仅学习了回归模型,还掌握了如何使用、实现以及在实践中部署它们。掌握了这些方法后,你们可以着手解决许多重要的实际问题。
此外,我们学习的一些概念是整个机器学习专项课程的基础,是核心的机器学习思想。
回归技术广泛应用于众多领域。卡洛斯度假归来,看起来神采奕奕,在下一门课程中你们会更多地见到他。
以下是回归的一些典型应用场景:
- 从预测产品的销售量,到预测股票市场走势。
你们在此学到的技术,将帮助你们构建真正能在现实世界产生影响的智能应用。
我们希望能在整个专项课程中继续见到你们。我们将一起学习分类器、推荐系统、文档检索,直至使用深度学习构建出色的推荐系统。
期待不久后与你们再见。

本节课中,我们一起回顾了回归课程的主要成果,了解了回归在预测等领域的广泛应用,并展望了机器学习专项课程后续将涵盖的分类、推荐系统及深度学习等激动人心的内容。
机器学习(分类,聚类和检索):第3课:欢迎与课程概述

在本节课中,我们将学习分类的基础知识,这是机器学习专项课程的第三门课。我们将从基础概念出发,深入理解核心算法,并最终能够构建现实世界中的分类器。
我是卡洛斯·古丁,我们将一起探索分类的方方面面。这个过程将充满挑战,但也非常有趣。通过努力,你将掌握构建实用分类器所需的核心技术。

这门课程是我们六门机器学习专项课程中的第三门。在第一门课程中,我们概述了机器学习的基础,将算法视为输入输出的黑箱。从第二门课程开始,我们深入理解每个算法的原理,并尝试自己从头实现它们。
上一节我们回顾了整个专项课程的脉络,本节中我们来看看本课程的具体定位。第一门关于回归的课程非常精彩,由艾米丽主讲。现在由我主讲这门关于分类的课程。此后,还将有关于聚类、推荐系统的课程,以及最终的顶点项目。在顶点项目中,你将运用深度学习和文本分析技术,构建一种全新的产品推荐系统,并将其部署为实时服务。
以下是本课程在专项课程中的位置图示:




本节课中我们一起学习了课程的欢迎介绍和整体安排,明确了分类课程在机器学习知识体系中的位置以及后续的学习路径。
机器学习(分类,聚类和检索):第1课:课程概述 🎯


在本节课中,我们将要学习机器学习的一个核心领域——分类。分类是机器学习中最基础、应用最广泛的技术之一。理解分类器,将帮助你掌握机器学习的核心思想,并且本课程所教授的技术是业界成功应用机器学习的关键。
什么是分类?🤔
上一节我们介绍了课程的整体目标,本节中我们来看看分类的具体定义。机器学习通常涉及输入数据,这些数据通过某种机器学习算法进行处理,最终从数据中输出我们视为某种“智能”的结果。
在本课程中,我们的目标是构建分类器。分类器接收输入 X(即数据的特征),并输出一个预测结果 Y。这个预测结果是一个离散的类别、分类或标签。
分类器的目标是学习一个从输入 X 到输出 Y(即类别)的映射关系。用公式可以表示为:


Y = f(X)
其中,f 代表我们学习的分类模型。
分类实例:情感分析 💬
在第一门课程中,我们讨论过一个情感分类器的例子。给定一个输入句子 X,例如“西雅图毫无疑问最好的寿司”,我们将其输入情感分类器。分类器会输出一个预测结果 Y,判断该句子是积极的(“yeah”)还是消极的(“nay”)。这种预测可以以多种方式被广泛应用。
超越二分类:多类别分类 📊
一般来说,分类就是接收输入 X,通过某个模型来预测 Y。这可能是二分类(例如正面或负面),也可能是多类别分类。
例如,假设我有一个网页,需要确定应该展示什么广告。为此,我需要自动判断该网页的内容属于哪个类别。目标是获取网页文本,并将其自动分类为教育类网站(展示教育类广告)、金融类文章(展示金融类广告)或科技类内容等等。因此,分类不仅仅是二元的“是或否”,它可以是多个类别中的一个。
以下是多类别分类的一些常见应用场景:
- 垃圾邮件过滤:这是最常见的分类器之一。每当新邮件到达时,垃圾邮件过滤器会基于邮件文本、发件人、IP地址等信息,预测该邮件是垃圾邮件(应被忽略)还是非垃圾邮件。
- 图像识别:给定一张图片(例如我的狗的图像像素),我们希望从一组类别中做出预测。例如,在著名的ImageNet数据集中有1000个不同类别,我们可能想预测它是否是拉布拉多犬、金毛猎犬等。
- 个性化医疗:这是一个令人兴奋的领域。传统的医疗基于相同的症状对所有人做出相同的诊断。个性化医疗将考虑我们的DNA序列(因为基因不同)和生活方式,来预测我们可能患有的疾病以及对我们最有效的治疗方案。这是一个现实世界中的分类示例。
- 脑成像与“读心术”:一个有趣且惊人的例子是我的同事Tom Mitchell的工作。通过扫描你在阅读单词时的大脑图像(fMRI),分类器可以预测你正在阅读的是哪个词(例如“锤子”或“房子”)。更惊人的是,他们可以在一个人阅读单词的脑图像上训练分类器,然后用它来预测另一个人观看图片(例如锤子的图片)时的脑活动。这是一个非常酷的分类应用。
总结 📝

本节课中我们一起学习了机器学习中分类的基本概念。我们了解到,分类器旨在学习从输入特征 X 到输出类别 Y 的映射。我们探讨了从简单的二分类(如情感分析)到复杂的多类别分类(如网页分类、图像识别)的各种实例。此外,我们还看到了分类在垃圾邮件过滤、个性化医疗乃至脑科学研究等广泛领域中的强大应用。掌握分类是理解机器学习世界的关键一步。
机器学习(分类,聚类和检索):第3课:分类的影响 🚀


在本节课中,我们将探讨分类器如何深刻地改变世界,并理解其在众多技术应用中的核心地位。我们将看到,分类技术不仅是处理电子邮件或网络搜索的基础,也是构建更广泛机器学习模型的关键。
分类器已经真正地改变了世界。
人们可能对分类器习以为常,但它们是我们所享受的每一项技术的核心。无论是我们讨论过的处理电子邮件的垃圾邮件过滤器、在网页搜索时返回特定答案集的过程、向你展示的广告、推荐的产品,还是我们对某人医疗状况的分类等等,分类器都无处不在。
我们每天都能看到这一切在世界各地发生。关于分类器的一个有趣之处在于,构建分类器所需的基本技术与构建各种其他机器学习模型所需的技术非常相似。
因此,如果你能深入理解分类器,你将基本上能够进行所有类型的机器学习,即所谓的监督学习。而这正是当今大多数机器学习实际应用的核心。


本节课中我们一起学习了分类器在现实世界中的广泛影响及其核心地位。我们了解到,掌握分类技术是深入理解监督学习乃至更广泛机器学习应用的关键基础。
机器学习(分类,聚类和检索):第3-4课:课程概览 🧭

在本节课中,我们将要学习这门课程的核心理念、教学方式以及涵盖的核心内容。这是一门高度注重实践的课程,旨在通过案例研究、可视化工具和动手实现,帮助你掌握当今世界真正实用且有影响力的分类技术。
课程核心理念与结构

上一节我们介绍了课程的整体定位,本节中我们来看看课程的具体教学方法和模块设计。本课程将始终围绕一个核心哲学展开:使用案例研究来驱动所有教学内容。你将在整个课程中看到这一点的体现。
此外,每个教学模块都将围绕以下六个方面构建:
以下是每个模块包含的六个核心要素:
- 核心概念:讲解超越特定模块技术的通用概念。
- 可视化辅助:为课程的每个方面创建了新的可视化图表,以帮助你深入理解底层思想。
- 实际算法:详细讨论能在实践中构建分类器的具体算法。
- 实践实现:你将从头开始实现所有讨论的算法,并能将其应用于现实世界。
- 可选高级主题:每个模块都包含标记为可选的高级内容,供有兴趣深入学习者探索。
- 聚焦实用技术:课程内容经过精心筛选,专注于那些在当今世界真正产生实际影响的技术。
核心技术与算法
在了解了课程结构后,我们来看看本课程将深入讲解哪些具体的技术和算法。我们不会涵盖分类的所有内容,但会深入讲解足以让你真正理解并能应用的技术。
我们将重点放在能产生最大影响的模型上:
- 线性分类器
- 逻辑回归
- 决策树
- 集成方法

如果你能理解这些模型,你将能够创建在各种现实世界问题中取得惊人准确度的分类器。
我们将讨论基础算法,并且你将实现它们并熟练掌握:
- 梯度下降:我们在回归课程中也讨论过。
- 随机梯度下降:对于将梯度方法扩展到大规模分类问题非常有用。
- 递归梯度算法:对于学习决策树非常有用。
- 提升法:一种用于学习分类器集成的卓越技术。
超越本课程的机器学习概念
除了具体的技术和算法,本课程还将讨论一些核心的机器学习概念。这些概念的应用范围远不止于本课程或分类问题本身。
我们将探讨以下关键概念:
- 如何避免过拟合。
- 如何处理缺失数据。
- 精确率与召回率。
- 在线学习。

本节课中我们一起学习了本课程的概览。我们了解到这是一门注重实践、以案例驱动的课程,涵盖了从核心概念、可视化、算法实现到高级主题的完整学习路径。课程聚焦于线性分类器、逻辑回归、决策树和集成方法等实用技术,并将深入讲解梯度下降、随机梯度下降等关键算法。此外,我们还将学习过拟合、缺失数据处理等具有广泛适用性的核心机器学习概念。这门课程内容充实,旨在让你通过动手实践成为真正的专家。
机器学习(分类,聚类和检索):第3-4课:课程前半部分大纲


在本节课中,我们将要学习华盛顿大学《机器学习(分类,聚类和检索)》课程前半部分的核心内容。我们将深入探讨线性分类器、逻辑回归、决策树等关键模型,并了解如何学习模型参数、处理过拟合问题以及应用奥卡姆剃刀原理来简化模型。
🧠 模块一:深入理解线性分类器与逻辑回归
在上一节概述之后,本节中我们来看看课程的第一个核心模块。我们将从线性分类器开始,并扩展到逻辑回归。
线性分类器是分类任务的基础。例如,在情感分析中,我们可能关心“awesome”和“awful”两个词在评论中出现的次数。一个线性分类器可能会为每个“awesome”赋予+1的权重,为每个“awful”赋予-1.5的权重。对于一个具体的评论,我们计算其得分:得分 = (1 * awesome次数) + (-1.5 * awful次数)。如果得分大于0,则分类为正面;否则为负面。决策边界是一条直线。
逻辑回归在此基础上更进一步,它不仅能预测类别(+1或-1),还能为每个预测分配一个概率。例如,得分很高的点被预测为正面的概率接近1(亮绿色),得分很低的点被预测为负面的概率接近1(亮紫色),而得分在0附近的点则概率接近0.5(白色区域),表示模型不确定。这使得分类器的应用更加灵活。
🔍 模块二:从数据中学习模型参数
上一节我们介绍了线性分类器和逻辑回归的基本思想,本节中我们来看看如何从数据中自动学习这些模型的参数(即权重系数)。
我们定义了似然的概念,用于衡量一个分类器(由一组参数定义的一条线)对数据的拟合好坏。不同的参数值对应不同的分类器。我们的目标是找到使似然最大化的那组参数。为此,我们将使用梯度上升算法,这与我们在之前线性回归课程中使用的梯度下降思想类似,但目标是最大化而非最小化。
⚠️ 模块三:分类中的过拟合与正则化
过拟合在分类中是一个非常重要的问题。当我们绘制模型复杂度与分类错误率的关系图时,可以看到:随着模型变得复杂,训练误差会不断降低直至接近零,但真实误差(测试误差)会先下降后上升,这表明模型开始记忆噪声而非学习规律。
在分类中,过拟合表现为决策边界变得异常复杂。例如,决策边界可能从一条简单的直线,变成一个稍微弯曲的曲线来更好地拟合数据,最终变成一个极其扭曲、几乎包裹住每个数据点的复杂形状。这种边界虽然完美拟合了训练数据,但泛化能力很差。
为了解决这个问题,我们将引入正则化技术。这与在线性回归中应用正则化的思路非常相似,通过给模型复杂度增加惩罚项,来鼓励更简单、更平滑的决策边界,从而防止过拟合。
🌳 模块四:决策树分类器
在第三个模块处理了线性模型的过拟合问题后,本节我们将探索一种全新的分类器:决策树。决策树在实践中非常有用,它们结构简单、易于理解,并且能够很好地拟合数据,提供非线性的决策边界。
以下是一个预测银行贷款风险的决策树示例:
- 首先检查信用历史。
- 如果信用历史“良好”,则贷款“安全”。
- 如果信用历史“一般”,则进一步检查贷款期限。
- 如果是“短期”贷款,则贷款“有风险”。
- 如果是“长期”贷款,则贷款“安全”。
- 如果信用历史“差”,则进一步检查收入水平。
- 如果收入“高”,且是“长期”贷款,则贷款“安全”。
- 如果收入“低”,则贷款“有风险”。
决策树能够捕捉数据中复杂但可解释的规则。
✂️ 模块五:决策树的过拟合与奥卡姆剃刀
上一节我们看到了决策树的强大能力,本节中我们来看看决策树同样面临严重的过拟合问题。


随着决策树变得更深、更复杂,其决策边界会变得极其繁琐,从而严重过拟合训练数据。我们需要对此进行处理。
我们将应用一个基本原则:奥卡姆剃刀原理。该原理主张“如无必要,勿增实体”,即最简单的解释往往是最好的。这一思想可以追溯到毕达哥拉斯和亚里士多德,并在13世纪由奥卡姆的威廉明确提出。
在决策树中,这意味着我们需要将那些非常复杂、深层的树进行简化(例如通过剪枝),找到在保持良好性能的同时更简单、更不易过拟合的树模型。


本节课中我们一起学习了课程前半部分的大纲,涵盖了从线性模型到决策树的核心分类方法,并重点探讨了模型学习、过拟合及其解决方案。这些内容为后续深入学习更高级的机器学习主题奠定了坚实的基础。
机器学习(分类,聚类和检索):第3-4课:课程后半部分大纲

在本节课中,我们将要学习机器学习课程后半部分的核心内容。我们将探讨如何处理缺失数据、如何组合简单分类器以构建强大的预测模型、如何评估模型性能以及如何将算法扩展到海量数据集。这些主题都是机器学习实践中的关键环节。
缺失数据处理 🧩
上一节我们介绍了课程的整体结构,本节中我们来看看如何处理数据中常见的问题——缺失值。


在数据科学实践中,我们经常会遇到数据缺失的情况。例如,在一个数据集中,某些条目的信息可能未被记录,比如下图中第二行关于贷款年限的数据就是一个问号,我们不知道这笔贷款是三年期还是五年期。

当数据缺失时,我们需要采取方法来解决。我们将讨论多种极其实用的处理方法,包括对决策树算法的修改。修改后的决策树在学习时可以考虑缺失数据,其决策过程不仅依赖于已观测到的值(例如信用评级为优秀、良好或差),还能处理信用评级未被观测到的情况。这些技术在实践中非常有用且应用广泛。
集成学习与提升法 🚀
在掌握了处理缺失数据的方法后,我们将进入一个令人惊叹的模块:集成学习。
第七模块将探讨一个由Kearns和Valiant在1988年提出的基础性问题(Valiant是图灵奖得主)。这个问题是:能否以某种方式组合简单的分类器,从而获得一个复杂分类器的性能?几年后,Schapire从理论上正面回答了这个问题,他提出了一种名为“提升法”的卓越算法,该算法在实践中产生了巨大影响。
事实上,在Kaggle等在线机器学习竞赛中,超过一半的获胜方案都使用了提升法。提升法是一种真正改变了世界的简单技术,我们将学习其基本原理,并能够自己实现它。
我们将讨论一种称为AdaBoost的提升算法。在这种算法中,你可以组合多个分类器的输出。例如,一个决策树可能预测某笔贷款是安全的(标记为+1),而另一个决策树可能预测它是高风险的(标记为-1)。通过让许多分类器进行“投票”,我们构建了一个“集成”模型。
以下是构建集成模型的核心思想:
- 我们学习如何组合这些分类器的投票结果,以获得最佳的预测。
- 通过使用提升算法学习这些组合权重,我们能够从非常简单的分类器出发,最终形成非常复杂的决策边界。
- 这正是赢得大多数Kaggle竞赛的技术。
精确率与召回率 📊
在学习了如何构建强大模型之后,我们需要退一步,审视机器学习中的基础评估概念:精确率与召回率。
让我用一个例子来说明。假设我拥有一家餐厅,并希望将顾客数量增加30%。为此,我计划开展一场营销活动。我希望这是一场真实、友好的营销活动,因此我打算利用餐厅的评论,找出那些精彩的句子,并将其展示在网站上。
在这种场景下,传统的“准确率”并不是一个好的评估指标。我们真正关心的是“精确率”和“召回率”。
- 精确率关注的是:如果我从评论中挑选出一些句子展示在网站上,那么我展示出一个真正负面句子的可能性有多大?因为如果我展示了一个像“寿司糟透了”这样的差评,那对我的网站将非常不利。因此,精确率确保我只展示正面的句子。
- 召回率关注的是:我能否找出人们所说的所有精彩的正面评价?如果一个分类器同时具有良好的精确率和召回率,那就意味着我找到了所有精彩的句子,并且只展示了关于我餐厅的精彩句子。
我们将非常详细地讨论这两个指标,因为如果你在实践中构建分类器,很可能会用到精确率和召回率。这基本上是所有公司在构建分类器时使用的核心评估指标。
可扩展性与随机梯度下降法 ⚡
在最后的模块中,我们将解决一个可扩展性问题:如何将算法扩展到真正海量的数据集?
正如你所见,网络上的网页数量正在急剧增长,目前约有48亿个网页。每天大约有5亿条推文。以YouTube为例,每天有50亿次的视频观看量。外界存在着海量数据,而传统的梯度类方法在处理大规模数据时往往不能很好地扩展。
因此,我们将介绍一种名为“随机梯度下降”的技术。与标准梯度下降相比,它能以更快的速度收敛到解。这只是对梯度下降的一个非常小的修改,却能带来惊人的性能提升。
在一个简单的情感分析例子中,我们在相同数据集上看到了超过100倍的性能提升。然而,随机梯度下降是一种非常“挑剔”的技术,需要正确处理才能使其工作。我们将讨论这项技术,解释其工作原理,同时也会解释为了使其良好工作所必须解决的实际问题。
总结

本节课中,我们一起学习了机器学习课程后半部分的核心大纲。我们探讨了处理缺失数据的实用方法,学习了如何通过集成学习和提升法组合弱分类器来构建强大的预测模型。我们还深入了解了评估分类器性能的关键指标——精确率与召回率。最后,我们介绍了如何利用随机梯度下降法将机器学习算法高效地扩展到海量数据集。这些内容涵盖了机器学习从理论到实践、从基础到前沿的多个关键方面。
机器学习(分类,聚类和检索):第0章:课程预备知识 📚

在本节课中,我们将要学习本课程开始前需要具备的背景知识、技能和工具。了解这些前提条件将帮助你更好地跟上课程进度,并顺利完成实践任务。
课程背景与先修知识
我们并非从零开始这门课程,而是假定所有学员都具备一些背景知识。
具体来说,我们假定你已经完成了本专项课程的前两门课程。这非常重要。从第一门课程中,你获得了关于机器学习可能性的广泛视野。如果你已经具备这种视野,那很好;但回顾这些内容将非常有帮助,同时也能提升你的编程技能、数据处理能力等。
在第二门课程中,我们同样假定你已经学习了相关内容,例如了解机器学习算法的基础概念、梯度下降、过拟合、验证集与交叉验证、偏差-方差权衡以及正则化等。我们假定你记得这些主题。如果你忘记了,请返回复习。如果你没有完成该课程,但已经掌握了这些技术,也可以直接开始本课程。我们将在整个课程中默认你已掌握这些知识。

数学与编程基础
与其他课程一样,我们假定你具备一些基础背景知识。
你需要在课程中计算一些导数。你应该知道什么是向量,因为我会使用这些概念。同时,你还需要了解一些基本函数,包括指数函数和对数函数。如果你需要复习这些基础知识,现在是一个好时机。
实践课程与编程要求
这是一门实践性课程。每个模块你都将使用真实世界的数据进行编程,并获得真实世界的结果。你应该对此有所预期。
但这并不意味着编程会很困难。我们建立了一个基础设施,使编程变得简单,特别是如果你会使用Python。如果你不会Python,可以像在前几门课程中那样快速学习。或者,你也可以使用任何你喜欢的语言来实现,我们不强制要求使用特定语言。但使用Python会方便很多。
工具与库的使用
与本专项的第一门课程不同,我们将大量使用GraphLab Create,因为它是一个很好的入门“黑箱”工具。然而,在本课程中,我们不会过度依赖GraphLab Create。
我们建议你使用SFrame,这是一个由Dato创建的开源数据操作库。但如果你更喜欢,也可以使用其他库,比如Python中的Pandas。在一些作业中,你会使用预先实现的算法,以便在自行实现之前理解其行为。对于这部分,我们建议使用GraphLab Create,但你也可以选择其他库,如Scikit-learn。这取决于你。
使用Python会更简单,我们会提供一些使用SFrame和其他工具的起始代码。当然,你也可以使用自己的工具。但本课程的最终目标是让你从头开始实现自己的机器学习算法,这是你需要准备好的。
硬件与软件要求
你需要一台性能尚可的计算机,笔记本电脑即可。64位机器会带来很大不同。
你需要能够访问互联网,以下载数据集、观看视频等。你需要有能力在你的机器上安装Python(以及GraphLab Create,如果你选择使用它),并存储几GB的数据。
就像在前几门课程中一样,我们也会为那些没有自己机器的学员提供一些在线资源,我们会在阅读材料中讨论这一点。
总结


本节课中,我们一起学习了开始本课程所需的预备知识。我们回顾了假定的先修课程内容、必要的数学与编程基础、课程的实践性质与编程要求、推荐的工具与库,以及所需的硬件与软件环境。确保你已准备好这些条件,将有助于你顺利开启机器学习算法实现的旅程。
机器学习(分类,聚类和检索):第1课:让我们开始吧 🚀

在本节课中,我们将开启机器学习课程的学习之旅。课程内容充实,充满乐趣,你将能够向潜在雇主或朋友展示令人惊叹的学习成果,并深入探讨算法原理。
课程概述
课程将涵盖分类、聚类和检索等核心机器学习主题。你将通过实践掌握关键概念,并能够深入讨论算法,这会使你在相关领域脱颖而出。
准备与后续信息
为了帮助你更好地准备并获取课程更新,建议你关注我的Twitter账号 @Garon。在那里,我会分享课程的最新动态、内部笔记以及未来课程的相关信息。
总结


本节课我们一起开启了机器学习的学习旅程,了解了课程的大致内容和获取后续信息的渠道。准备好迎接一段充满乐趣和收获的学习过程吧。
机器学习(分类,聚类和检索):第3课:线性分类器:一个激励性的例子 🍣

在本节课中,我们将开始学习分类课程的第一个模块。我们将讨论线性分类器,这是最常用的分类器之一。特别是,我们将重点介绍逻辑回归,它是最常用且最有用的线性分类器之一。这里学到的概念将延伸到线性分类器之外的许多其他分类方法。你将学习基本概念,以及用于优化模型参数以拟合训练数据的底层算法。

一个激励性的例子:餐厅评论系统 🍜

我们将从一个激励性的例子开始,这也是本专项课程第一门课中使用的例子:一个新的餐厅评论系统。
假设我有一个特殊的日子即将到来,我想出去吃一顿美味的日本料理。我想找一家能吃到绝佳寿司的餐厅。西雅图有很多评价很高的日本餐厅,我该如何选择呢?
餐厅有很多方面可以使其变得出色。我最关心的是美味的食物和良好的氛围。如果我查看一条餐厅评论,它会谈论餐厅的不同方面。例如,一条具体的评论可能有一句话写道:“在那里的体验非常出色。” 这告诉我什么?这句话对去这家餐厅的体验持积极态度。
接下来可能还有一句话写道:“我妻子尝试了拉面,味道相当一般。” 这意味着什么?那里的拉面很一般,我不想吃。但我去餐厅不是为了吃拉面,所以我不关心评论中的这句话。
另一方面,同一家餐厅的评论可能说:“那里的寿司很美味,是西雅图最好的寿司。” 这句话对寿司的评价很高,而寿司是我选择餐厅时最关心的方面。

因此,每条评论的不同句子都涉及不同的方面。我希望捕捉每个句子的情感,以便了解它对我最关心的寿司方面是否持积极态度。所以,对于每个句子,我将把它输入一个分类器,该分类器将判断这是积极情感还是消极情感,这就是我们的任务。
机器学习(分类,聚类和检索):第3课:线性分类器的直观理解 🧠


在本节课中,我们将学习线性分类器的基本工作原理。我们将从一个直观的例子开始,理解线性分类器如何利用词语的权重来预测文本的情感倾向,并概述训练这样一个分类器的整体流程。
线性分类器回顾 📖
上一节我们介绍了分类问题的基本概念,本节中我们来看看线性分类器的直观理解。
线性分类器接收一个输入量 X。在我们的例子中,X 是来自评论的句子。分类器模型会处理这个输入,并做出一个预测 ŷ。ŷ 的值表示这是一个正面评论(ŷ = +1)还是一个负面评论(ŷ = -1)。这就是我们试图解决的问题。
线性分类器还会多做一步:它为每个单词关联一个权重或系数。这个系数表明了该单词对情感的正面或负面影响程度。
以下是单词及其假设系数的例子:
- good 的系数可能是 1.0
- great 的系数可能是 1.5
- awesome 的系数可能是 2.7
- bad 的系数可能是 -1.0
- terrible 的系数可能是 -2.1
- awful 的系数可能是 -3.3
- 一些与评论情感无关的单词,其系数可能为 0
如何使用系数进行预测? 🔍
现在,让我们看看如何利用这些系数来预测一个句子是正面还是负面的。
我们以这个句子为例:“The sushi was great, the food was awesome, but the service was terrible.”
以下是计算该句子得分 score 的步骤:
- 查看句子中每个重要单词的系数。
- “great” 的系数是 1.5。
- “awesome” 的系数是 2.7。
- “terrible” 的系数是 -2.1。
- 将这些系数相加,得到句子的总得分:1.5 + 2.7 - 2.1 = 2.1。
这个总得分 2.1 大于 0。因此,我们预测这个句子的情感 ŷ 为 +1,即这是一个正面评论。
这被称为线性分类器,因为其输出是输入的加权和。用公式可以表示为:
score = Σ (word_coefficient_i)
ŷ = +1 if score > 0, else ŷ = -1

训练线性分类器 🏋️
更一般地说,一个简单的线性分类器接收与每个单词关联的系数作为输入,然后为输入句子计算一个得分。如果得分大于0,则预测输出 ŷ 为 +1;如果得分小于0,则预测 ŷ 为 -1。
我们需要从数据中训练出这个线性分类器的权重。以下是训练流程:
- 准备数据:给定一些包含已标注(+1 或 -1)评论句子的输入训练数据。
- 划分数据集:将这些数据划分为训练集和验证集。
- 训练模型:将训练集输入到某个学习算法中。该算法将学习与每个单词关联的权重(例如,good 对应 1.0,awesome 对应 1.7 等)。
- 评估模型:在学习到这个分类器之后,我们回到验证集上评估其准确性。
我们本节课的目标就是深入探索这个“学习”过程,理解如何从数据中学习分类器,并更深入地理解线性分类器(特别是在逻辑回归的背景下)的真正含义。
总结 ✨

本节课中我们一起学习了线性分类器的直观工作原理。我们了解到,线性分类器通过为每个特征(如单词)分配权重,并计算输入的加权和来做出决策。如果加权和为正,则预测为正类(+1);为负则预测为负类(-1)。我们还概述了从标注数据中训练这些权重的标准流程,包括数据准备、模型训练和验证评估。
机器学习(分类,聚类和检索):第3课:决策边界

在本节课中,我们将深入探讨线性分类器的一个重要概念——决策边界。决策边界是区分模型预测为正类(Positive)和负类(Negative)的分界线。理解它有助于我们直观地把握分类器是如何根据特征做出判断的。

决策边界的概念
为了更深入地理解线性分类器,我们先来回顾一下决策边界的概念。决策边界是正类预测和负类预测之间的分界线。

一个简单的例子
现在,假设我们处理完数据并训练了一个线性分类器。在这个模型中,除了两个词之外,所有词的权重都为零。具体来说,单词“awesome”的权重为 1.0,单词“awful”的权重为 -1.5。
这意味着,任何句子的得分(Score)计算公式为:
得分 = 1.0 * (单词“awesome”的出现次数) - 1.5 * (单词“awful”的出现次数)
我们可以将每个句子根据其包含的“awesome”和“awful”的数量绘制在一个二维图上。例如,对于句子“寿司很棒,食物很棒,但服务很糟糕”,它包含2个“awesome”和1个“awful”,因此我们将其绘制在坐标点 (2, 1) 上。
我们的训练数据或预测集中的其他句子可能包含不同的组合,比如 (3, 0) 或 (1, 2) 等,最终我们会得到一系列数据点。

绘制决策边界
我们训练的带有系数 1.0 和 -1.5 的分类器,其决策边界对应于一条直线,该直线满足方程:
1.0 * (awesome的数量) - 1.5 * (awful的数量) = 0
在这条直线以下的所有点,其得分都大于0。对于这些点,模型将预测为正类(+1)。例如,点 (3, 0) 的得分为 1.0*3 - 1.5*0 = 3,大于0,因此被分类为正类。
在这条直线以上的所有点,其得分都小于0。对于这些点,模型将预测为负类(-1)。你可以自行验证其他点。
因此,这条直线就是决策边界:线下为正,线上为负。这正是“线性”分类器的含义——它使用一条直线(或更高维度的平面)作为决策边界。




从二维到高维
以上我们看到了只有两个特征(或系数)时,决策边界是二维平面上的一条直线。
在更一般的情况下,我们可能拥有更多特征。以下是不同维度下的决策边界形态:
- 三个特征:如果恰好有三个特征具有非零系数,那么决策边界将是一个在三维空间中分隔正负样本的平面。
- 更多特征:如果拥有超过三个非零系数,我们就进入了高维空间。在高维空间中,这个分隔边界被称为超平面。它本质上是一个更高维度的“平面”,用于分隔正负样本。(顺便一提,这有点像科幻小说里的概念。)
- 复杂特征:如果我们使用更复杂的特征或形状,决策边界在低维空间中的投影可能看起来是弯曲的或不规则的复杂线条,而不仅仅是简单的直线或平面。

总结

本节课中,我们一起学习了决策边界的概念。我们通过一个具体的例子,看到了线性分类器如何利用特征的线性组合(公式 得分 = w1*x1 + w2*x2 + ...)在特征空间中定义一条直线(或平面、超平面)来区分正负样本。理解决策边界是理解线性模型工作原理的关键一步。
机器学习(分类,聚类和检索):第3课:线性分类器模型 🧠


在本节课中,我们将深入学习线性分类器模型,理解其如何捕捉数据特征并进行分类预测。我们将从情感分析的例子出发,逐步构建模型,并介绍相关的数学表示。


上一节我们通过情感分析的例子建立了线性分类器的直观理解。本节中,我们将更深入地探讨线性分类器模型究竟捕捉了什么。
具体来说,我们将处理一个数据集,从中提取特征 X,就像在回归课程中所做的那样。然后,我们将这些特征输入到用于分类的机器学习模型中,模型将输出预测值 ŷ。
该模型依赖于一些参数 Ŵ,这些参数将从数据中学习得到。
现在,让我们回到之前那个只有两个非零系数特征(“awesome”和“awful”)的例子。假设我们增加第三个具有非零系数的特征,例如“great”。在这种情况下,每个数据点都关联着这个三维空间中的一个坐标。例如,某个数据点可能有5个“awesome”、3个“awful”和2个“great”。
线性分类器模型的目标是构建一个超平面,试图将正例和负例分开。这个超平面与一个评分函数相关联,该评分函数是这些特征的加权组合。
对于一个数据点 X_i,其评分 score(X_i) 定义为:
score(X_i) = w0 + w1 * (awesome的数量) + w2 * (awful的数量) + w3 * (great的数量)
对于上述例子,即:
score(X_i) = w0 + 5*w1 + 3*w2 + 2*w3
根据系数 w 的不同,这个评分可能是正数或负数。由于这是一个正例训练样本,我们希望选择能使该评分为正的 w 值。
在建立了分类问题及其任务框架后,让我们快速回顾一下本课程将使用的符号表示法。本课程使用的符号与回归课程(专项课程的第二门课)一致。
我们有一个输出 y,即我们要预测的目标。在回归中它是实数值,但在我们的分类场景中是类别。我们有一组具有 d 维的输入 x,即 x1, x2, ..., xd。因此,x 实际上是一个 d 维向量。在二元分类(我们今天讨论的起点)中,我们要预测的输出 y 是 -1 或 +1。
x_j表示第j个输入(一个标量值)。h_j(x)表示第j个特征。x_i非常重要,它表示第i个数据点。x_i(j)表示第i个数据点的第j个输入。
符号有点多,但这与我们在回归课程中所做的完全相同。
借助这些符号,我们可以回过头来定义我们简单的超平面模型。在这个模型中,我们的预测 ŷ 是特定输入 X 的评分 score(X) 的符号。
符号函数 sign 定义如下:如果评分大于0,则预测 +1;如果评分小于0,则预测 -1;在等于0时,可以任意选择预测 -1 或 +1。我的处理方式是,如果等于0,我预测 +1。
输入 X_i 的评分是:
score(X_i) = w0 + w1 * x_i(1) + w2 * x_i(2) + ... + w_d * x_i(d)
这里的特征输入中,第一项 x_i(1) 通常是常数特征1(就像回归中一样)。x_i(1) 可以是“awesome”的数量,x_i(2) 可以是“awful”的数量,而最后一项 x_i(d) 可以是“ramen”这个词出现的次数(对我来说这可能与负面评价相关,但也可能无关紧要,具体取决于你赋予它的系数)。
我们的目标是优化这个评分函数。为了书写简便,我将使用 W^T * X_i 作为简写,这样我就不必总是写出 w0 + w1*x1 + w2*x2 + ... 了。这个转置记号与我们在回归课程中讨论的相同。


本节课中,我们一起学习了线性分类器模型的核心概念。我们从直观例子出发,定义了数据点、特征空间和分离超平面。我们引入了评分函数 score(X) = W^T * X,它通过特征的加权和计算每个数据点的得分。预测 ŷ 则由该得分的符号 sign(score(X)) 决定,从而完成分类任务。我们还统一了与回归课程一致的数学符号表示法,为后续的模型训练和优化奠定了基础。
机器学习(分类,聚类和检索):第3-4课:系数值对决策边界的影响 📊

在本节课中,我们将探讨在分类模型中,学习到的系数值如何直接影响决策边界的位置和形态。我们将通过一个具体的例子,展示系数 w0 和 w2 的变化如何改变决策边界,从而影响模型的预测结果。
上一节我们介绍了分类模型中的评分函数和决策边界。本节中,我们来看看系数 w0 和 w2 的具体数值变化会如何影响这条边界。
首先,回顾我们之前定义的评分函数。在示例中,评分由以下公式定义:
score = 1.0 * awesome - 1.5 * awful
这意味着系数 w1 = 1.0,w2 = -1.5,而 w0 = 0(虽然未显式写出,但等同于 w0 = 0)。
基于此,我们得到了决策边界:位于这条线上方的点评分小于0,下方的点评分大于0。这使得模型在边界一侧预测为正类(例如正面评价),另一侧预测为负类(例如负面评价)。
现在,假设我们学习到的系数 w0 不是0,而是 1.0。这意味着我们的评分函数增加了一个常数项:
score = 1.0 + 1.0 * awesome - 1.5 * awful
这个变化对决策边界有何影响?边界线会整体向上平移。
以下是具体影响:
- 观察左下角靠近
(0, 0)的数据点。在w0 = 0时,它被预测为负面评价(橙色)。 - 当
w0变为1.0后,该点现在被预测为正面评价(蓝色),即从橙色变为蓝色。
另一方面,如果我们改变系数 w2(对应“awful”一词),将其从 -1.5 增加到 -3.0(意味着“awful”一词的负面影响更强),评分函数变为:
score = 1.0 + 1.0 * awesome - 3.0 * awful
这个变化对决策边界有何影响?边界线会向下倾斜。
以下是具体影响:
- 观察一个原本在正类预测区域(蓝色)的数据点,它包含4个“awesome”和2个“awful”。
- 当
w2变为-3.0后,由于“awful”的权重加倍,4个“awesome”已无法抵消2个“awful”的负面影响。 - 该点因此被划到决策边界的另一侧,预测结果从正类(蓝色)变为负类(橙色)。

本节课中我们一起学习了系数值对决策边界的影响。我们看到,截距项 w0 的变化会导致决策边界平行移动,而特征系数(如 w2)的变化则会改变边界的倾斜角度。理解这种关系对于解释模型行为和调试模型至关重要。
机器学习(分类,聚类和检索):第3-4课:使用输入的特征

在本节课中,我们将学习如何在分类模型中引入和使用特征。我们将从基础的评分公式开始,逐步理解特征如何被提取、加权,并最终用于预测文档的情感倾向(正面或负面)。
特征与评分公式
到目前为止,我们使用的符号没有关联特征。与回归课程类似,我们将从一开始就重点介绍特征的引入。
我们将定义一系列从数据中提取的特征函数,记作 H₁ 到 H_D。同时,我们将常数函数编码为 H₀。
具体而言,一个数据点的预测评分(score)计算公式如下:
score = w₀H₀ + w₁H₁ + w₂H₂ + … + w_DH_D
其中,w_j 是与特征 H_j 对应的系数(权重)。
特征示例
- H₀:可以是一个常数(例如,截距项)。
- H₁:可以是文档中“awesome”(很棒)这个词出现的次数。
- H₂:可以是文档中“awful”(糟糕)这个词出现的次数。
- 更复杂的特征:可以是某些转换,例如“awesome”出现次数的对数乘以“awful”的出现次数。更实际的特征可以是TF-IDF值,它能帮助我们强调那些更具区分度或更重要的词语。我们在第一门课程中学习过TF-IDF,并将在后续课程中再次探讨。
模型的向量化表示与决策规则
为了简化表示,我们使用向量化的记法。将所有权重 w_j 组成的向量记为 w,将所有特征 H_j(x) 组成的向量记为 h(x),那么评分可以简洁地表示为两者的点积:
score = wᵀ h(x)
这里,wᵀ h(x) 就表示针对特定数据点 x 的评分。
基于这个评分,我们制定一个简单的决策规则:
- 如果 score > 0,我们预测该文档为正面评价(ŷ = +1)。
- 如果 score < 0,我们预测该文档为负面评价(ŷ = -1)。


模型工作流程详解
现在,让我们更详细地介绍整个模型的工作流程。这个过程可以清晰地分为几个步骤:
以下是模型从输入到预测的完整步骤:
- 特征提取:首先,将输入的原始数据 x(例如一段评论文本)送入特征生成函数。这个函数会执行诸如统计“awesome”一词出现的次数,或计算整个文档的TF-IDF向量等操作。
- 线性组合:接着,将生成的特征向量 h(x) 输入到机器学习模型的核心部分。模型会将每个特征 H_j(x) 与其对应的已学习权重 w_j 相乘,并将所有乘积求和,得到一个单一的评分(score)值。
- 决策输出:最后,将这个评分值通过符号函数(sign function)处理。根据结果是正还是负,模型输出最终的预测标签 ŷ,即 +1(正面评价)或 -1(负面评价)。
本节总结

本节课中,我们一起学习了如何为分类模型引入特征。我们定义了从数据中提取特征的函数,并建立了基于特征加权求和的评分公式 score = wᵀ h(x)。我们明确了利用该评分的决策规则,并梳理了模型从原始输入到最终预测的完整工作流程:输入数据 → 特征提取 → 线性加权评分 → 符号函数决策 → 输出预测。理解这个流程是构建更复杂分类器的基础。
机器学习(分类,聚类和检索):第3-4课:预测类别概率

在本节课中,我们将深入探讨逻辑回归的一个核心概念:预测类别概率。我们将学习如何不仅预测类别标签(如+1或-1),还能输出一个概率值,用以表示我们对预测结果的置信程度。
概述
到目前为止,我们讨论的内容主要是对专业课程第一门课知识的回顾。从此刻起,我们将更深入地探讨与逻辑回归相关的基本概念。在逻辑回归中,我们不仅仅预测+1或-1,我们预测的是一个概率——例如,这条评论是积极的可能性有多大,是消极的可能性有多大。这些概率极其有用,因为它们能指示我们对所做预测的把握程度。
从分数到概率
上一节我们介绍了如何获取分数并通过符号函数来决定一条评论是积极的(+1)还是消极的(-1)。然而,并非所有评论都具有相同的确定性。
例如,有一条评论说:“这家店的寿司太棒了。”这是一个明确的+1,我们对此非常有把握。另一条评论说:“寿司不错,服务一般。”我们不太确定这条评论的倾向,它可能是+1,也可能是-1。如果评论者为人友善,他们可能不愿写负面评价,即使内心认为是负面的,也可能写出这样的评论。
那么,如何捕捉第一种情况我们确信预测为+1,而第二种情况我们不确定是+1还是-1的事实呢?对于右边的情况,我们可能会说:预测的类别标签是+1,但概率只有0.5。
核心概念:逻辑函数

为了将分数(一个实数)转换为一个介于0和1之间的概率值,我们使用逻辑函数(或称Sigmoid函数)。这个函数能将任何实数映射到(0, 1)区间。
其公式如下:
P(y=+1 | x) = σ(score) = 1 / (1 + e^{-score})
其中,score = w^T * x + b(即特征的加权和加上偏置项),e是自然常数。
以下是该函数的代码描述:
import math
def logistic_function(score):
"""
将分数转换为概率。
参数:
score: 线性模型的输出值(实数)。
返回:
一个介于0和1之间的概率值。
"""
return 1 / (1 + math.exp(-score))
逻辑函数的输出可以解释为给定特征x时,目标y为+1类的概率。相应地,预测为-1类的概率就是1 - P(y=+1 | x)。
概率的解释与应用
通过引入概率预测,我们的模型输出变得更加丰富和实用。
以下是概率的几个关键用途:
- 衡量预测置信度:概率值越接近1或0,表示模型对预测为正类或负类越有信心;概率值接近0.5则表示模型不确定性很高。
- 制定差异化决策:在实际应用中,我们可以根据概率设定不同的行动阈值。例如,对于高置信度的正面评论可以优先展示,而对于概率接近0.5的评论则可以交给人工审核。
- 作为其他模型的输入:这些概率值可以作为更复杂集成模型或下游任务的特征。
总结

本节课中,我们一起学习了逻辑回归中预测类别概率的核心思想。我们了解到,通过使用逻辑函数,可以将线性模型输出的分数转换为一个具有明确概率解释的值。这使我们不仅能做出分类决策,还能评估每个决策的置信水平,为更精细和实用的机器学习应用奠定了基础。
机器学习:第3-4课:概率基础知识回顾

在本节课中,我们将学习概率论的基础知识。概率是衡量我们对预测结果确信程度的核心概念,在分类、聚类和检索等机器学习任务中至关重要。本节将快速回顾概率的基本定义、解释和性质,为后续学习打下基础。
概率的解释
上一节我们提到了概率的重要性,本节中我们来看看如何具体解释一个概率值。
概率可以表示事件发生的长期频率。例如,如果我说“评论为正面”的概率是0.7,这意味着在大量评论数据中,平均有70%的评论是正面的,其余30%是负面的。数据集是对真实评论世界的一个有限样本观察,因此比例可能不会精确等于70%,但会大致接近。
概率也可以表示我们对某件事的确信程度或信念强度。我们使用符号 P(y = +1) 来表示输出 y 为正面(+1)的概率。这个概率值在0到1之间。
- 如果
P(y = +1) = 1,表示我们绝对确信所有评论都是正面的。 - 如果
P(y = +1) = 0,表示我们绝对确信所有评论都不是正面的(即全是负面的)。 - 如果
P(y = +1) = 0.5,表示我们完全不确定评论的倾向,认为正面和负面的可能性各占一半。
概率的基本性质
理解了概率的含义后,我们来看看概率必须遵守的几个基本数学性质。
以下是概率的两个核心性质:
- 非负性与有界性:任何事件的概率都介于0和1之间(包含0和1)。不存在负概率或大于1的概率。
- 公式表示为:
0 ≤ P(事件) ≤ 1
- 公式表示为:
- 归一性:所有可能互斥事件(即不会同时发生的事件)的概率之和必须等于1。
在二元分类(如正面/负面评论)的例子中,只有两种互斥的可能结果。因此,正面概率和负面概率之和为1。
公式表示为:P(y = +1) + P(y = -1) = 1
扩展到多类别情况
上一节我们以二元分类为例,本节中我们来看看当输出有多个类别时,概率的性质如何扩展。
考虑一个图像分类问题,图像可能属于“狗”、“猫”或“鸟”三类,且仅此三类。此时,每个类别的概率仍然在0到1之间。
此外,所有可能类别的概率之和必须为1。因为图像必定属于这三类中的某一类。
公式表示为:P(y=狗) + P(y=猫) + P(y=鸟) = 1
如果存在更多类别,则需要将所有类别的概率相加,总和仍为1。

本节课中我们一起学习了概率的基础知识。我们了解了概率的两种解释(频率与信念),掌握了概率必须满足的非负性、有界性和归一性,并看到了这些性质如何从二元分类推广到多类别分类。这些概念是理解后续机器学习算法中不确定性度量的基石。
机器学习(分类,聚类和检索):第3-4课:条件概率基础知识回顾

在本节课中,我们将学习条件概率这一核心概念。条件概率是理解许多机器学习算法的基础,尤其是在处理分类问题时。我们将通过简单的例子来阐述其定义、性质及其在机器学习中的应用。
条件概率的定义
上一节我们介绍了概率的基本概念,本节中我们来看看条件概率。条件概率描述了在某个特定条件或事件发生的情况下,另一个事件发生的可能性。
例如,考虑这样一个陈述:“一篇包含三个‘awesome’和一个‘awful’的评论是正面评论的概率为0.9”。这意味着,在所有满足“包含三个‘awesome’和一个‘awful’”这个条件的评论中,我们预计平均有90%是正面评论。
我们可以通过数据来理解这一点。假设我们有一个数据集,我们只关注那些满足“包含三个‘awesome’和一个‘awful’”条件的行。在这些行中,我们预计大约90%的评论标签是正面的(+1)。这很直观,因为有三个正面词和一个负面词,评论很可能是正面的。
条件概率的符号表示
在机器学习中,我们经常关心在给定输入特征 X 的情况下,输出类别 y 的概率。我们用以下符号表示:
P(y = +1 | X = x_i)
其中:
P表示概率。y = +1是我们关心的输出事件(例如,评论是正面的)。|表示“在...条件下”或“给定”。X = x_i是给定的条件(例如,输入句子是“所有的寿司都很美味”)。
这个表达式读作:“在输入为 x_i 的条件下,输出 y 为 +1 的概率”。
条件概率的解释
条件概率的值反映了我们对特定条件下事件发生的信念强度。
- 如果
P(y = +1 | X = x_i) = 1,那么我们绝对确信在给定输入x_i时,输出是正面的。 - 如果
P(y = +1 | X = x_i) = 0,那么我们绝对确信在给定输入x_i时,输出是负面的。 - 如果
P(y = +1 | X = x_i) = 0.5,那么我们完全不确定,认为正面和负面的可能性各占一半。
对于二元分类(两个类别),一个重要的关系是:
P(y = +1 | X = x_i) + P(y = -1 | X = x_i) = 1
这意味着,在给定相同输入的条件下,输出为正面和负面的概率之和必须为1。
条件概率的重要性质
以下是条件概率的几个关键性质,对于理解后续内容至关重要。
首先,条件概率的值始终在0和1之间:
0 ≤ P(y | X) ≤ 1
其次,对于所有可能的输出类别 y,在给定同一个输入 X 的条件下,它们的概率之和为1。这在二元和多类别情况下都成立。
-
二元情况(两个类别):
P(y = +1 | X) + P(y = -1 | X) = 1 -
多类别情况(例如,图像分类为狗、猫、鸟):
P(y = 狗 | X) + P(y = 猫 | X) + P(y = 鸟 | X) = 1
重要提示:这个求和性质是针对输出变量 y 的所有可能取值,并且是在同一个输入条件 X 下。如果我们对不同的输入 X 求和,其结果不一定等于1。例如,对所有数据点求和 Σ P(y = +1 | X_i) 的结果可以是任意值,没有总和为1的限制。
总结

本节课中我们一起学习了条件概率的基础知识。我们明确了条件概率 P(y | X) 表示在已知输入特征 X 的情况下,预测输出为 y 的可能性。我们了解了它的取值范围在0到1之间,并且对于给定的同一个输入 X,所有可能输出类别的条件概率之和为1。掌握这些性质,是我们后续构建和理解逻辑回归、朴素贝叶斯等分类模型的重要基石。
机器学习(分类,聚类和检索):第3-4课:在分类中使用概率

在本节课中,我们将学习概率如何应用于分类问题。我们将探讨如何利用概率来评估分类模型对预测结果的置信度,并理解其在实践中的重要性。
概率在分类中的应用
上一节我们回顾了概率的基础知识,本节中我们来看看它如何在分类问题中发挥作用。
假设我们有两个句子。第一个句子是“definitely positive, the solution and everything were awesome”。第二个句子是“I was not sure the sushi was good, the service was okay”。
对于第一个句子,我们可以说它是正面评论的概率非常高。具体而言,给定该句子,其标签 y 为 +1(正面)的概率 P(y=+1 | 句子) 为 0.99。
对于第二个句子,给定句子“the sushi was good, the service was okay”,其标签 y 为 +1 的概率 P(y=+1 | x) 仅为 0.55。
通常,许多分类器会输出这种置信度或概率,即给定输入 x 时输出标签 y 的概率 P(y | x)。这在实践中非常有用。
概率分类器的工作流程
让我们通过一个例子来理解这意味着什么。
假设我们有一个包含 n 个数据点的输入数据集。每个数据点有输入特征(例如“awesome”一词出现的次数)和标签 y。我们使用这个数据集来训练一个分类器。
分类器的输出是概率预测,我们称之为 P_hat。这是我们对预测概率的估计,它取决于我们模型的参数 W_hat 或系数 w_hat。
因此,P_hat 将用于预测 y_hat,即预测的类别。在我们的例子中,y_hat 代表句子的情感倾向。
如何进行预测
我们将学习如何从数据中估计 P_hat,并用它来预测最可能的类别。
具体操作如下:给定一个输入句子,我计算 P(y=+1 | 句子),即给定该句子,其标签为正面(+1)的概率。
如果这个概率大于 0.5,我们就说预测的 y_hat 是 +1,这是一个正面句子。
如果这个概率小于 0.5,我们就说预测的 y_hat 是 -1,这是一个负面句子。
概率输出的优势
然而,P_hat 不仅仅给出 +1 或 -1 的预测。它为我们提供了更具解释性的输出。
P_hat 会告诉我们,我们对这个评论是正面评价的把握有多大。例如,一个概率为 0.99 的预测比一个概率为 0.55 的预测要确定得多。
总结

本节课中,我们一起学习了概率在分类问题中的应用。我们了解到,分类器可以输出给定输入时属于某个类别的概率 P(y | x),而不仅仅是硬性的类别标签。我们通过设定一个阈值(如 0.5)来做出最终的类别决策(y_hat)。这种基于概率的方法不仅提供了预测结果,还给出了模型对该预测的置信度,使模型的输出更具信息量和实用性。
机器学习(分类,聚类和检索):第3-4课:使用广义线性模型预测类别概率 📊


在本节课中,我们将深入探讨如何利用线性分类器(或称线性模型)来预测一个句子是正面或负面的概率。我们将学习如何将线性模型输出的分数(范围从负无穷到正无穷)转换为一个介于0到1之间的概率值。
上一节我们介绍了线性分类器的决策边界和分数计算。本节中,我们来看看如何将这些分数解释为具体的概率。
现在,我们接收一些输入数据 x,计算其特征 h,并输出预测概率 P̂,即标签为正或负的概率。
回顾决策边界的例子,我们为每个数据点计算了分数:wᵀh(x) 或 w₀h₀ + w₁h₁ + w₂h₂ + w₃h₃ + ...。决策边界以下的数据点分数大于0,以上的分数小于0。但我们不知道这些分数具体有多大或多小,它们可能分布在负无穷到正无穷之间。我们的任务就是将这些分数与输出为+1(正面)的概率联系起来。
实际上,分数 wᵀh 的范围是负无穷到正无穷。如果分数为正(>0),我们输出+1;如果为负(<0),则输出-1。现在,我们希望表达的是:如果分数非常大(趋近于正无穷),那么我们非常确信预测值 ŷ 是+1,因此应输出概率 P(y=+1 | x) = 1。反之,如果分数非常小(趋近于负无穷),我们非常确信 ŷ 是-1,则应输出概率 P(y=+1 | x) = 0。如果分数恰好为0,即位于决策边界上,我们对预测 ŷ 为+1或-1没有倾向性,因此可以解释为概率 P(y=+1 | x) = 0.5,即五五开。


所以,我们的目标就是从分数中预测出这些概率。
以下是我们的核心挑战:分数范围是负无穷到正无穷,而概率范围是0到1。如何将两者联系起来?
现在我们将看到一种“魔法”,它能将负无穷到正无穷的范围“粘合”或“链接”到0到1的范围。这被称为链接函数。它的作用是将分数通过一个函数 g 进行转换,将这个巨大的数轴“挤压”到区间[0, 1]内,并用它来预测 y=+1 的概率。
当你取一个线性模型 wᵀh(其输出范围是负无穷到正无穷),并通过一个链接函数将其挤压到[0, 1]区间时,你构建的就是所谓的广义线性模型。所以,如果有人今天在街上拦住你问“什么是广义线性模型?”,你可以轻松回答:它就像一个回归模型,但通过一个链接函数将其输出映射到了0到1之间。
这听起来有点抽象,我们将在逻辑回归的背景下具体讨论,因为它使用了一种特定类型的链接函数。虽然广义线性模型不仅限于将输出映射到0和1之间(还有其他类型),但就我们的分类目的而言,可以这样理解。
因此,在此背景下,我们的目标变为:获取训练数据,通过特征提取得到特征向量 h(例如TF-IDF或“awesome”等词的计数),然后构建线性模型 wᵀh,再通过链接函数将其挤压到[0,1]区间,最后用这个值来预测给定输入句子后,其情感为正面(积极)的概率。

本节课中,我们一起学习了如何将线性分类器的分数输出转化为概率预测。我们引入了链接函数的概念,它负责将分数从(-∞, +∞)映射到概率区间[0, 1]。这种通过链接函数扩展线性模型以处理概率预测的框架,就是广义线性模型的核心思想。下一节,我们将具体探讨逻辑回归中使用的链接函数——逻辑函数(或Sigmoid函数)。
机器学习(分类,聚类和检索):第3-4课:Sigmoid或Logistic链接函数

在本节课中,我们将学习如何将线性模型的得分“压缩”到0到1的区间内,以预测概率。我们将重点介绍逻辑回归中使用的特定链接函数——Sigmoid函数或Logistic函数。

上一节我们介绍了将得分映射到概率区间的抽象概念,本节中我们来看看逻辑回归中具体使用的函数。
Sigmoid函数定义
对于逻辑回归,我们使用的链接函数称为Logistic函数,有时也称为Sigmoid函数或Logit函数。
这是一个以得分为输入的函数,其数学表达式如下:
公式: σ(score) = 1 / (1 + e^(-score))
其中,e是自然常数。这个函数可能看起来有些复杂,但它极其有用,能够完美地将得分从负无穷到正无穷的区间映射到0到1之间。
函数特性分析
以下是Sigmoid函数在几个关键点上的行为分析,这有助于我们理解其工作原理。
-
当得分为0时:
- 计算过程:
σ(0) = 1 / (1 + e^0) = 1 / (1 + 1) = 0.5 - 结果解释:当线性模型的得分为0时,预测概率恰好为0.5,这符合我们的直觉。
- 计算过程:
-
当得分为正无穷时:
- 计算过程:
σ(+∞) = 1 / (1 + e^(-∞)) = 1 / (1 + 0) = 1 - 结果解释:当得分趋近于正无穷大时,预测概率趋近于1,表示模型对该类别有极高的置信度。
- 计算过程:
-
当得分为负无穷时:
- 计算过程:
σ(-∞) = 1 / (1 + e^(+∞)) = 1 / (1 + ∞) ≈ 0 - 结果解释:当得分趋近于负无穷大时,预测概率趋近于0,表示模型认为该类别极不可能。
- 计算过程:
函数曲线与中间值
理解函数在极端值处的行为后,我们再来看看中间值的情况。Sigmoid函数是一条平滑的S形曲线。
例如:
- 当得分为+2时,函数输出约为0.88。
- 当得分为-2时,函数输出约为0.12。
该函数关于点(0, 0.5)对称,其输出值始终在0和1之间。因此,它完美地实现了将任意实数得分映射到(0,1)概率区间的目标。


本节课中我们一起学习了逻辑回归的核心——Sigmoid链接函数。我们了解了它的数学定义,分析了它在关键点(0、正无穷、负无穷)的输出特性,并认识到它是一条平滑的S形曲线,能够将线性模型的得分有效地转化为概率预测。
机器学习(分类,聚类和检索):第3-4课:Logistic回归模型 🧮

在本节课中,我们将要学习Logistic回归模型。这是一种用于分类任务的强大工具,它能够将输入特征映射为一个概率值,从而预测样本属于某个类别的可能性。我们将详细探讨其数学形式、工作原理以及如何通过模型进行预测。
模型描述
上一节我们介绍了分类问题与线性模型的基础。本节中,我们来看看Logistic回归模型的具体形式。
Logistic回归模型接收一个分数作为输入。这个分数的范围从负无穷到正无穷,其具体形式是特征向量的线性组合,即 WᵀH(X)。模型将这个分数通过一个称为Sigmoid的函数进行处理,以估计在给定输入 Xᵢ 和参数 W 的条件下,标签 y 等于 +1 的概率。
更明确地说,这个概率等于:
P(y = +1 | Xᵢ, W) = 1 / (1 + e^(-score(Xᵢ)))
这等同于:
P(y = +1 | Xᵢ, W) = 1 / (1 + e^(-WᵀH(Xᵢ)))
为了更清晰地展示,我们可以将 WᵀH(Xᵢ) 展开写出来:
P(y = +1 | Xᵢ, W) = 1 / (1 + e^(- (w₀h₀(Xᵢ) + w₁h₁(Xᵢ) + ... + w_D h_D(Xᵢ))))
这就是Logistic回归模型的样子。它根据输入 X 和参数 W,预测输出为正类(例如正面情感)的概率。
模型理解
现在,让我们花点时间更好地理解Logistic回归模型。
模型的输入是一个句子 X(或任何其他输入)的分数。模型的输出是在给定输入 X 和参数 W 的条件下,标签为 +1 的概率,即 1 / (1 + e^(-WᵀH(X)))。
为了更好地可视化,我们可以观察Sigmoid函数的特性。如果分数为0,那么对应的概率是0.5。这意味着模型对正类和负类的判断是模糊的。
以下是关于模型预测行为的关键观察:
- 当分数小于0时(即位于0的左侧),模型预测 y_hat 为 -1。
- 当分数大于0时(即位于0的右侧),模型预测 y_hat 为 +1。
让我们通过几个例子来具体看看:
- 如果分数为 -2,代入公式计算,得到概率约为 0.12。由于概率小于0.5,模型预测为负类(y_hat = -1)。
- 如果分数为 +2,计算得到概率约为 0.88。由于概率大于0.5,模型预测为正类(y_hat = +1)。
- 如果分数为 +4,计算得到概率约为 0.98。此时模型不仅预测为正类,而且对此预测的“信心”或“确定性”更高。
值得注意的是,对于分数为 -2 和 +2 的情况,其概率值(0.12 和 0.88)相加等于1。这并非巧合,因为 P(y = +1) 和 P(y = -1) 之和必须为1,而Sigmoid函数恰好具有这种对称性。
总结

本节课中,我们一起学习了Logistic回归模型。我们首先描述了模型的核心公式,它通过Sigmoid函数将线性分数转换为概率。接着,我们深入探讨了模型的行为:分数为0时预测不确定(概率0.5),分数为负时预测为负类,分数为正时预测为正类,并且分数的绝对值越大,模型对预测结果的信心就越强。这个模型具备了我们在分类任务中所期望的特性:输出是易于解释的概率,并且决策边界清晰。
机器学习(分类,聚类和检索):第3课:系数值对预测概率的影响 📊

在本节课中,我们将深入探讨逻辑回归模型中系数(权重)如何影响模型的决策边界和预测概率。我们将通过具体的例子和图示,直观地理解系数 w0 和特征权重 w1、w2 的变化如何改变模型的预测行为。
决策边界与概率回顾
上一节我们介绍了逻辑回归模型如何通过决策边界进行分类。本节中,我们来看看边界附近的点与远离边界的点,其预测概率有何不同。
考虑一个简单的决策边界方程:1.0 × (awesome数量) - 1.5 × (awful数量) = 0。在这条线上方的点,其得分 score(Xi) > 0,被预测为正类;线下方的点,其得分 score(Xi) < 0,被预测为负类。
然而,逻辑回归输出的不是硬分类,而是概率。让我们通过几个具体数据点来观察。
以下是三个不同位置的数据点及其对应的预测概率:
- 靠近边界的点:例如,一个评论有4个“awesome”和2个“awful”。其得分为
4 - 1.5 × 2 = 1。通过sigmoid函数计算,预测其为正面评论的概率P(y=+1|X) ≈ 0.73。这个概率大于0.5,但并非远大于0.5,反映了模型对该点分类的不确定性。 - 远离边界的点(正侧):例如,一个评论有3个“awesome”和0个“awful”。其得分为
3 - 1.5 × 0 = 3。预测概率P(y=+1|X) ≈ 0.95。这个概率远高于边界附近的点,表明模型对这个预测非常有信心。 - 远离边界的点(负侧):例如,一个评论有1个“awesome”和3个“awful”。其得分为
1 - 1.5 × 3 = -3.5。预测概率P(y=+1|X) ≈ 0.03。这个概率极低,表明模型非常确信这是一个负面评论。
系数如何影响预测
现在,让我们更系统地探讨从数据中学到的系数(包括常数项 w0 和特征权重 w1, w2)如何影响决策边界和预测的置信度。
我们以一个仅包含两个特征(“awesome”数量 和 “awful”数量)的简单模型为例。
情况一:常数项 w0 = 0
当常数项 w0 为0时,模型的决策由特征权重决定。预测概率公式为:
P(y=+1 | X, W) = sigmoid( w1 * (#awesome) + w2 * (#awful) )
假设 w1 = 1, w2 = -1。那么:
- 当
#awesome与#awful数量相等时,得分score(X) = 0,预测概率为0.5。 - 当
#awesome比#awful多一个时,得分score(X) = 1,预测概率跃升至约0.73。
情况二:改变常数项 w0
如果将常数项 w0 改为 -2,而保持特征权重不变,决策边界会向右平移。
这意味着,现在需要 #awesome 比 #awful 多两个,才能使预测概率达到 0.5。常数项 w0 的作用是整体偏移决策边界,相当于模型对正类有一个先验的“偏见”或“阈值”。
情况三:增大特征权重的幅度
如果保持 w0 = 0,但增大特征权重 w1 和 w2 的绝对值(例如,w1 = 5, w2 = -5),sigmoid曲线的形状会变得更陡峭。
此时:
- 当
#awesome与#awful数量相等时,得分仍为0,预测概率仍是0.5。 - 但是,只要
#awesome比#awful多一个,得分score(X) = 5,预测概率会急剧增加到接近1。
系数幅度越大,模型从“不确定”(概率0.5)到“非常确定”(概率接近0或1)的变化就越快、越陡峭。
逻辑回归学习问题总结
本节课中我们一起学习了逻辑回归模型系数的核心作用。


我们看到了逻辑回归的学习问题:给定带有特征和标签的训练数据,我们的模型定义正类的预测概率为 P(y=+1|X, W) = sigmoid( W^T * X )。我们的目标是找到一个最优的权重向量 W_hat,使得这个概率模型能够最好地拟合观测到的数据。
具体来说:
- 常数项
w0:平移决策边界,改变模型做出正类预测所需的“基础门槛”。 - 特征权重
w1, w2, ...:决定了每个特征对最终得分(及概率)的贡献方向和强度。权重的符号影响贡献方向(正或负),绝对值大小影响贡献的强度以及模型做出确信预测的速度。

下一节,我们将讨论如何从数据中拟合出这个最优权重 W 的算法基础。
机器学习(分类,聚类和检索):第3-4课:Logistic回归模型学习概述 🧠

在本节课中,我们将要学习Logistic回归模型的学习过程。我们已经详细了解了Logistic回归模型本身,现在让我们快速概述一下对于这个模型而言,“学习”意味着什么。尽管在下一个模块中,我们将深入探讨学习算法的细节,但本节内容是为下一个模块所做的一个简要介绍和铺垫。

学习流程概览
上一节我们介绍了Logistic回归模型,本节中我们来看看如何让模型从数据中学习。
我们将从一组数据开始,这组数据包含输入 x 和输出(+1 或 -1)。正如之前所说,我们会将数据分为训练集和验证集。然后,我们将对训练集运行一个学习算法,该算法将输出参数估计值 W。
这些估计出的 W 将被代入模型中,用于估计一个输入句子是正面或负面的概率。
当然,我们可以使用学习到的模型,在验证集上评估其性能,计算质量指标和错误率。
定义质量指标:似然函数
为了找到最佳的分类器,我们需要定义一个质量指标。在本例中,这个质量指标被称为似然函数。
对于一个可能的参数集 W(例如,包含系数 w0、w1 和 w2),我们可以根据似然函数 L(w) 对其进行评分,以判断其好坏。
以下是几个参数集及其对应似然值的例子:
- 例如,对于参数
w0=0,w1=1,w2=-1.5,其似然值可能非常小,为10^-6。 - 对于另一组参数
w0=1,w1=1,w2=-1.5,似然函数值稍好一些,为10^-5。 - 而对于最佳的那条线,其参数可能是
w0=1,w1=0.5,w2=-1.5,此时我们得到最佳的似然值10^-4。
因此,我们需要一种方法来搜索可能的 W 值,以找到那条最佳的线(即最大似然值对应的参数)。
寻找最佳参数:梯度上升法
正如我们将在下一个模块中看到的,我们将使用梯度上升算法来寻找具有最高似然值(即最佳质量)的参数集 W。


总结


本节课中我们一起学习了Logistic回归模型学习过程的概述。我们了解到,学习过程始于将数据分为训练集和验证集,并通过算法从训练集中估计模型参数 W。我们引入了似然函数作为评估参数好坏的质量指标,并指出目标是找到使似然函数最大化的参数。最后,我们预告了下一个模块将使用梯度上升算法来实现这一目标。
机器学习(分类,聚类和检索):第3课:编码分类输入 📝

在本节课中,我们将要学习如何处理逻辑回归模型中的分类输入变量。我们已经了解了逻辑回归模型,并探讨了如何通过学习找到模型的最佳参数。然而,之前我们是以一种抽象的方式讨论特征的,例如“好评数量”、“差评数量”等。当我们的输入是所谓的分类变量时,我们需要更深入地思考如何表示它们。

分类变量与数值变量的区别
上一节我们介绍了逻辑回归模型的基本形式,本节中我们来看看如何处理不同类型的输入数据。如果输入 x 是数值,例如好评数量、年龄或薪水,将其乘以一个特定的系数是很自然的。例如,在评分函数中,1.5 * 好评数量 或 17 * 薪水 作为数值是有意义的。
然而,对于分类输入,如性别(男/女)、出生国家或邮政编码(在美国称为ZIP码),情况则不同。虽然邮政编码由数字组成(例如10005或98195),你可以想象将其乘以一个系数,但它们的行为并不像连续的数值。例如,98195并不比10005“大9倍”,它只是代表国家的一个不同地区。
因此,即使输入是数字,如果它们不代表连续尺度,而是像本例中一样代表类别或位置的指示符,我们仍然需要以有趣的方式对它们进行编码,以便能够与系数相乘。
编码方法:独热编码
那么,我们如何将像 1.5 或 -2.7 这样的系数与分类变量相乘呢?为此,我们需要使用一种称为编码的技术。编码接收一个分类输入(例如出生国家),并尝试使用某种数值来表示它,这些数值可以自然地与系数相乘。
以下是处理分类变量的一种核心方法:
一种编码方法是使用独热编码。在这种方法中,为每个可能的类别创建一个特征。例如,对于出生国家,可能有196个可能的类别。那么,你会为阿根廷创建一个特征,为巴西创建一个特征,依此类推,直到为津巴布韦创建第196个特征。
具体来说,如果某人出生在巴西,那么“阿根廷”特征的值是0,“巴西”特征的值是1,所有其他特征的值都是0。因此,在任何时候,只有一个特征的值是1,其他都是0。这就是“独热”的含义(源自电气工程,表示一个“开启”或“激活”的编码)。同样,如果某人出生在津巴布韦,我们会得到一串0,只有在代表津巴布韦出生的第196个特征上值为1。
另一种编码:词袋模型
在本模块中,我们实际上已经探索了另一种针对文本数据的编码方法,我们在第一门课程中讨论过,即词袋模型编码。一条评论由文本定义,文本可能包含成千上万个不同的单词。
以下是词袋模型的工作原理:
词袋模型接收文本,然后将其转换为计数。例如,我可能将特征 H1 与“好评”一词的出现次数关联,H2 与“差评”一词的出现次数关联,依此类推,直到第10,000个特征 H10000,可能与“寿司”一词的出现次数关联。一个特定的数据点可能有2个“好评”、0个“差评”、许多其他词的0次出现,以及3个“寿司”。因此,它变成了一个非常稀疏的10,000维向量。
编码的核心思想与应用
在上述两种情况下,我们都将一个分类特征(分类输入)转化为一组特征,每个特征对应一个可能的类别,其值要么是单一的“开启”值(1),要么是一个计数。我们可以直接将这种编码输入到我们目前讨论的逻辑回归模型中。
这种类型的编码在实践中至关重要,你应该熟悉它们。它们是将非数值信息转化为模型可以处理的数值形式的基础。


本节课中我们一起学习了如何处理逻辑回归中的分类输入。我们探讨了分类变量与数值变量的关键区别,并介绍了两种核心的编码方法:独热编码 用于一般的类别变量,以及词袋模型 用于文本数据。通过将分类数据转换为数值特征,我们能够将它们有效地整合到逻辑回归等机器学习模型中。
机器学习(分类,聚类和检索):3-4:一对多多类分类


在本节课中,我们将要学习多类分类问题,并重点介绍一种简单但极其有效的方法——一对多方法。
概述
多类分类是指预测任务中存在两个以上类别的情况。例如,给定一张图片,我们需要判断其中的物体是拉布拉多犬、金毛寻回犬、桌子还是相机。我们将学习如何使用多个二元分类器来解决这类问题。
一对多方法原理
上一节我们介绍了二元分类,本节中我们来看看如何将其扩展到多类场景。一对多方法的核心思想是为每个类别训练一个独立的二元分类器。
假设我们有 C 个类别(例如,三角形、心形、甜甜圈)。对于每个类别 c,我们训练一个分类器,其任务是区分“属于类别 c”和“不属于类别 c”(即所有其他类别)。
对于类别 c,我们学习一个模型,其输出是给定输入 x 时,y 属于该类别的概率估计:
P_hat_c(y = +1 | x, w_c)
请注意,每个类别 c 都有自己独立的参数 w_c。
训练与预测流程
以下是使用一对多方法进行多类分类的具体步骤。
首先,我们需要为每个类别训练一个二元分类器。
- 为每个类别训练分类器:对于总共
C个类别中的每一个,将其所有样本标记为正例(y=+1),将所有其他类别的样本标记为负例(y=-1),然后训练一个标准的二元分类器(如逻辑回归)。 - 获得概率估计:训练完成后,每个分类器
c都能对新的输入x输出一个概率值P_hat_c,表示x属于类别c的置信度。

接下来,在预测阶段,我们使用所有训练好的分类器对新样本进行判断。
- 初始化:设置最大概率
max_p = 0,预测类别y_hat为None。 - 遍历所有类别:对于每个类别
c,计算其分类器给出的概率p_c = P_hat_c(y=+1 | x, w_c)。 - 比较与更新:如果
p_c > max_p,则更新max_p = p_c,并将y_hat设置为当前类别c。 - 输出结果:遍历完所有类别后,输出最终确定的
y_hat作为预测类别。
用伪代码表示,预测过程如下:
max_p = 0
y_hat = None
for c in range(C):
p_c = P_hat_c(y=+1 | x, w_c) # 第c个分类器的预测概率
if p_c > max_p:
max_p = p_c
y_hat = c
return y_hat
总结

本节课中我们一起学习了多类分类问题的一对多解决方法。该方法通过为每个类别训练一个“一对其他”的二元分类器,将复杂的多类问题分解为多个简单的二元问题。在预测时,综合所有分类器的结果,选择概率最高的类别作为最终输出。这种方法概念清晰、实现简单,是处理多类分类任务的基础且强大的工具。
机器学习(分类,聚类和检索):第3-4课:Logistic回归分类器回顾

在本节课中,我们将回顾Logistic回归分类器的核心概念。我们将深入探讨线性分类器的表示方法、Logistic回归模型如何将分数转换为概率,以及如何将其扩展到多类别和分类数据场景。通过本次回顾,你将能够清晰地理解分类器的工作原理。
我们已经完成了第一个模块的学习,并且比第一门课程更深入地探讨了线性分类器的表示方法。事实上,我们有机会深入其中,真正理解这些模型是如何构建的,包括与之相关的线性基础参数,以及如何将其扩展到其他场景。
现在,我们能够将学习循环——从训练数据到创建特征 h(x),再到这个模型——应用到Logistic回归模型中,并定义一个学习算法。我们之前已经大致讨论过这个算法,但将在下一个模块中更详细地探讨如何得出权重 w,并利用它进行预测。

因此,现在你可以运用所学的所有知识,来讨论线性分类器的形态、Logistic回归模型是什么,以及它如何与一般的分数函数(如回归)相关联,但通过将其压缩到区间 [0, 1] 来预测概率。你还可以理解它如何受参数影响,如何扩展到多类别设置,以及如何处理分类数据。我们已经完成了大量工作,现在已准备好深入思考分类器。
核心概念回顾
以下是Logistic回归分类器的几个核心组成部分:
-
线性分类器:其决策边界由线性函数定义。对于一个特征向量
x和权重向量w,分数函数为score(x) = w · x + b,其中b是偏置项。 -
Logistic回归模型:该模型将线性分数通过Sigmoid函数转换为概率。公式为
P(y=1 | x) = σ(w · x + b) = 1 / (1 + exp(-(w · x + b)))。这确保了输出在0和1之间,代表属于正类的概率。 -
扩展到多类别:对于多类别分类问题,可以使用Softmax函数。对于
K个类别,给定分数向量s(其中s_k = w_k · x + b_k),类别k的概率为P(y=k | x) = exp(s_k) / Σ_{j=1}^{K} exp(s_j)。 -
处理分类数据:对于非数值的分类特征(如颜色、城市),通常使用独热编码将其转换为二进制特征向量,以便模型能够处理。
总结

本节课中我们一起回顾了Logistic回归分类器的关键内容。我们明确了线性分类器的表示,理解了Logistic回归如何通过Sigmoid函数将线性分数映射为概率,并探讨了模型向多类别分类的扩展方法以及分类数据的处理方式。这些知识为我们接下来深入学习分类器的训练算法奠定了坚实的基础。
机器学习(分类,聚类和检索):第3课:学习Logistic回归的参数

在本节课中,我们将深入探讨如何从数据中学习Logistic回归分类器的参数。我们将从快速回顾开始,确保大家对模型有共同的理解,然后详细讲解参数学习的过程。
概述
我们已经了解了Logistic回归分类器的表示形式、参数的影响以及如何将其用于分类和多类别分类。这是讨论线性分类器和完成后续分类课程的基础。现在,我们的目标是学习如何从数据中自动找到最优的参数。
模型回顾
回想一下我们的任务:例如,我们有一些餐厅评论,我们希望判断评论是正面还是负面。给定一条评论文本 x,我们希望模型能输出该评论为正面(y=1)的概率 P(y=1 | x)。
我们讨论过线性分类器,它为每个输入特征(在我们的例子中是单词,如“好”、“棒极了”等)关联一个权重或系数。正面词汇通常有正系数,负面词汇有负系数。
模型的核心是一个评分函数,它是输入句子中出现的单词与其对应系数的加权组合:
score = w^T * h(x)
其中 w 是权重向量,h(x) 是输入 x 的特征表示(例如,词袋向量)。这个分数可以从负无穷到正无穷。
为了将这个分数转化为一个介于0和1之间的概率,我们使用Logistic函数(或Sigmoid函数)进行“挤压”。在Logistic回归模型中,给定评论文本 x,其为正面评论的概率定义为:
P(y=1 | x) = 1 / (1 + exp(-w^T * h(x)))
这个公式是我们模型的核心。
学习目标
我们的目标是学习最优的权重系数向量 w。我们希望学到的 w 能够使得模型对训练数据中的正面评论给出高概率,对负面评论给出低概率。
那么,如何从数据中学习这些参数呢?以下是学习过程的关键步骤。
学习参数的方法
为了学习参数 w,我们需要一个衡量模型预测好坏的标准,即一个目标函数(或损失函数)。然后,我们通过优化这个函数来找到最佳的 w。
1. 定义目标函数:最大似然估计
一个自然的方法是使用最大似然估计。我们希望找到一组参数 w,使得模型对观测到的训练数据的“可能性”最大。换句话说,我们希望模型预测的概率分布与真实标签尽可能一致。
对于单个数据点 (x_i, y_i),其似然可以表示为:
L_i(w) = P(y_i | x_i)^y_i * (1 - P(y_i | x_i))^(1-y_i)
当 y_i=1(正面)时,我们希望 P(y=1|x_i) 大;当 y_i=0(负面)时,我们希望 P(y=1|x_i) 小(即 1-P(y=1|x_i) 大)。
对于整个训练集,总似然是所有数据点似然的乘积。通常,我们最大化对数似然,因为乘积取对数后变为求和,更易于数学处理:
log L(w) = Σ [y_i * log(P(y_i|x_i)) + (1-y_i) * log(1 - P(y_i|x_i))]
2. 优化目标函数
我们的目标是找到使对数似然函数 log L(w) 最大的 w。由于最大化对数似然等价于最小化负对数似然,我们通常将问题转化为最小化一个损失函数,称为对数损失或交叉熵损失:
Loss(w) = - Σ [y_i * log(P(y_i|x_i)) + (1-y_i) * log(1 - P(y_i|x_i))]
这个函数是凸函数,意味着它有一个全局最小值。我们可以使用梯度下降法来找到使损失最小的 w。
3. 使用梯度下降
梯度下降是一个迭代优化算法。它从 w 的一个初始猜测开始,然后反复朝着使损失函数下降最快的方向(负梯度方向)更新 w。
权重更新公式为:
w_new = w_old - η * ∇Loss(w_old)
其中 η 是学习率,控制每次更新的步长;∇Loss(w) 是损失函数关于 w 的梯度。
对于Logistic回归,梯度的计算有简洁的形式,它与预测误差 (y_i - P(y_i|x_i)) 和输入特征 h(x_i) 有关。这使得梯度下降的实现非常高效。
总结
在本节课中,我们一起学习了如何为Logistic回归分类器学习参数。
我们首先回顾了模型:它使用线性加权和计算分数,并通过Sigmoid函数将分数转化为概率。
然后,我们深入探讨了学习过程的核心:使用最大似然估计原理来定义目标。我们通过最大化训练数据的(对数)似然,或者等价地,最小化对数损失(交叉熵损失)来寻找最佳参数。
最后,我们介绍了如何使用梯度下降法来优化这个损失函数,从而迭代地更新权重系数 w,直到找到最优解。

通过这个过程,我们可以从标记好的数据中自动学习到一个能够有效区分正面和负面评论的Logistic回归模型。这为构建实用的文本分类器奠定了坚实的基础。在接下来的课程中,我们将看到如何评估和提升这些模型的性能。
机器学习(分类,聚类和检索):第3课:最大似然估计的直观理解


在本节课中,我们将学习如何为逻辑回归模型定义质量度量,即似然函数。我们将理解其直观含义,并了解如何通过最大化似然函数来找到最佳的模型参数。
为了从数据中学习系数 W,我们必须定义某种质量度量,使得系数能给出最高的质量,这就是 W 应该达到的目标。回顾我们的学习循环,给定一些训练数据(这些数据可能来自未来的生成或提取系统),我们将其输入到模型 h(x) 中。
在我们的逻辑回归模型中,现在我们将讨论质量度量。这个度量将输入到机器学习算法中,算法最终输出 W。具体来说,我们会得到一些训练数据作为输入,数据类似于我展示的这个例子。例如,每条数据可能有两个特征:“awesome”的数量和“awful”的数量,以及输出标签或情感,可能是+1(正面)或-1(负面)。
假设我们有 N 个数据点。我们将使用某种学习算法来优化质量度量,从而得到 W。那么,质量度量是什么样的呢?让我们直接深入探讨,尝试理解我们在上一模块中提到的似然函数到底是什么。
为了直观理解,让我们将数据集分成两部分:右边是具有正面情感的数据点,左边是具有负面情感的数据点。在这个例子中,我们有两个表格,分别对应负面和正面情感。
我们希望一个好的 W 能满足什么条件呢?对于所有正面情感的数据点,在理想情况下,我们希望模型预测其为正面的概率尽可能接近 1。对于所有负面情感的数据点,我们希望模型预测其为正面的概率尽可能接近 0(即它必须是负面的)。我们的目标是找到一个 W,使其尽可能实现这一点。
换句话说,对于所有的负面和正面例子,可能不存在一个 W 能对所有数据点都精确地实现概率为0或1。因此,似然函数这种质量度量试图在整体上找出一个平均最优解。它衡量的是在所有数据点上,系数 W 的质量,其目标是让极端情况(概率接近0或1)尽可能发生。
有了似然函数,我就可以评估多个分类器(或决策边界)。例如,对于图中这条绿色的线,似然函数可能有一个特定的值,比如 10^-6。对于另一条线(其中 w0 从0变为1,但 w1 和 w2 系数保持不变),似然值可能略高,为 10^-5.8。但对于最佳的线(例如,设 w0=1, w1=0.5, w2=-1.5),似然值是最大的,在这个例子中是 10^-4。
你看到了这些数字,它们看起来有点奇怪,都是 10 的负多少次方。这就是似然值通常的样子,它们是非常小的正数(小于1)。但值越大(越接近1),模型就越好。
那么问题来了:我们如何找到最好的 W,即最好的分类器呢?答案是,我们寻找能使我们将要讨论的这个似然函数 L(W) 最大化的 W。然后,我们将使用梯度上升方法来找到 W。
你应该还记得回归课程中关于梯度下降的讨论(无论是美好的还是痛苦的回忆),我们探索了使用梯度来寻找最佳参数以优化质量度量的思想。在本案例中,我们将再次经历这个过程,不过这次是最大化(梯度上升)而非最小化(梯度下降)。


本节课中,我们一起学习了最大似然估计的直观思想。我们了解到,似然函数 L(W) 衡量了在给定参数 W 下,观察到当前训练数据的概率。我们的目标是找到一组参数 W,使得这个概率(似然)最大化。这相当于寻找一个模型,使其预测结果与真实标签尽可能一致。接下来,我们将具体定义这个似然函数的数学形式,并学习如何使用梯度上升法来优化它。
机器学习(分类,聚类和检索):第3-4课:数据似然

在本节课中,我们将要学习一个在机器学习中至关重要的概念——数据似然。我们将探讨如何通过优化这个指标来找到最佳的模型参数,从而让我们的分类器(例如逻辑回归)做出最准确的预测。
在深入探讨梯度下降等优化方法之前,我们需要明确我们试图优化的质量指标是什么。这个质量指标被称为数据似然。
为了更好地理解数据似然,让我们从一些简单的例子开始,尝试理解参数 W 的目标是什么,也就是我们在学习问题中试图完成的任务。
假设我们有一个数据点,它包含两个“awesome”词和一个“awful”词。我们称这个输入为 X1。其对应的输出 Y1 是正面的情感(+1),表示这是一条正面评价。
如果我们的分类器性能很好,即参数 W 设置得当,那么对于这个特定的输入,模型的预测输出 Ŷ1 也应该等于 +1。换句话说,预测值 Ŷ 与真实标签 Y 一致。
那么,在使用逻辑回归时,我们如何让 Ŷ 与真实标签 Y 一致呢?我们将尝试找到一个参数 W,使得在输入为 X1、参数为 W 的条件下,Y 等于 +1 的概率尽可能大。也就是说,我们希望最大化这个概率:P(Y = +1 | X1, W)。
但以上是针对一个正面例子。我们不仅要最大化正面例子中 Y=+1 的概率。
现在,让我们看另一个例子。称这个例子为 X2,它包含零个“awesome”词和两个“awful”词,这必然是一条负面评价。因此,其情感标签 Y2 是 -1。
如果我们的分类器性能很好,即 W 设置得当,那么在这种情况下,我们应该预测 Ŷ2 等于 -1,以与真实标签一致。因此,在这种情况下,我们不是最大化 Y=+1 的概率,而是最大化在输入为 X2、参数为 W 的条件下,Y 等于 -1 的概率:P(Y = -1 | X2, W)。
总结一下:
- 当输入是 X1(正面例子)时,我们想要最大化 P(Y = +1 | X1, W)。
- 当输入是 X2(负面例子)时,我们想要最大化 P(Y = -1 | X2, W)。
这正是数据似然试图实现的目标。但让我们更深入地理解一下。
实际上,我们通常不止有两个训练样本,而是拥有一个包含大量样本的数据集。那么,我们具体要做什么呢?
让我们逐一审视数据集中的例子:
- 对于第一个例子(正面),我们希望最大化 P(Y = +1 | X1, W)。
- 对于第二个例子(负面),我们希望最大化 P(Y = -1 | X2, W)。
- 对于第三个例子(负面),我们希望最大化 P(Y = -1 | X3, W)。
- 对于第四个例子(正面),我们希望最大化 P(Y = +1 | X4, W)。
以此类推。换句话说:
- 对于所有正面例子,我们试图使 P(Y = +1 | X, W) 尽可能大。
- 对于所有负面例子,我们试图使 P(Y = -1 | X, W) 尽可能大。
这非常直观自然。我们希望为数据集中的每一个样本都做到这一点。
现在的问题是:我们如何将这些针对单个样本的目标组合成一个单一的质量指标?你可以想象有多种组合方式,比如求平均值等。
在所谓的最大似然估计或最大化似然的方法中,通常的组合方式是将这些概率相乘。
所以,似然函数 L(W) 可以写成:
L(W) = P(Y1 | X1, W) × P(Y2 | X2, W) × P(Y3 | X3, W) × ...
(注:对于了解概率论的读者,相乘的原因是我们假设每个数据样本是相互独立的。但不必过于担心这一点,只需理解为相乘即可。)
让我们更明确地表达这一点。对于数据集中的每个数据点,我们都在尝试最大化其对应的特定概率。因此,似然函数,即我们想要优化的目标,就是所有这些概率的乘积。
为了简化冗长的表示法,我们使用以下符号:
- 用 P(y_i | x_i, W) 表示第 i 个样本在其真实标签 y_i(+1 或 -1)下的概率。
- 使用连乘符号 Π 来表示所有样本概率的乘积。
因此,似然函数 L(W) 的正式定义为:
L(W) = Π_{i=1}^{N} P(y_i | x_i, W)
其中:
- N 是数据点的总数。
- y_i 是第 i 个数据点的真实标签(+1 或 -1)。
- x_i 是第 i 个数据点的输入特征(例如,句子中“awesome”和“awful”的词频)。
- W 是我们的模型参数。
我们的最终目标就是:选择一组参数 W,使得这个似然函数 L(W) 的值尽可能大。
通过最大化数据似然,我们实际上是在寻找一组参数,使得模型预测出的概率分布与观测到的真实数据(标签)最为吻合。这是训练许多概率模型(包括逻辑回归)的核心思想。

在本节课中,我们一起学习了数据似然的概念。我们了解到,为了训练一个好的分类器,我们需要找到模型参数 W,以最大化所有训练样本的预测概率的乘积,即似然函数 L(W)。这个函数量化了我们的模型参数与观测数据之间的匹配程度。在接下来的课程中,我们将探讨如何通过优化算法(如梯度下降)来实际找到这个最大化似然函数的 W。
机器学习(分类,聚类和检索):第3-4课:使用梯度上升法找到最佳线性分类器

在本节课中,我们将学习如何使用梯度上升算法来最大化逻辑回归模型的似然函数,从而找到最佳的分类器参数。我们将从数学原理入手,最终得到一个极其简单且直观的算法实现。
上一节我们介绍了用于评估模型质量的似然函数。本节中,我们来看看如何通过梯度上升算法来最大化这个函数,从而找到最优的模型参数 W。
梯度上升算法概述
梯度上升是一种优化算法,用于寻找使目标函数(此处为似然函数)值最大的参数。其核心思想是:从参数的某个初始猜测值开始,反复朝着函数值增长最快的方向(即梯度方向)迈出一小步,直至收敛到最大值点。

想象我们站在一个参数构成的山坡上,似然函数值就是海拔。我们的目标是爬到山顶(最大值)。梯度方向就是最陡的上山方向。
算法原理与步骤
以下是梯度上升算法的具体步骤:
- 初始化参数:为参数向量 W(例如
w0, w1, w2)选择一组初始值。这可以是随机值或全零。 - 计算梯度:计算当前参数下,似然函数 L(W) 关于每个参数的梯度(偏导数)。梯度向量
∇L(W)指向函数值增长最快的方向。 - 更新参数:沿着梯度方向,以一定的步长(学习率
η)更新参数。更新公式为:
W_new = W_old + η * ∇L(W_old)
这里的+号是因为我们在做“上升”(最大化)。如果是梯度下降(最小化),则使用-号。 - 迭代:重复步骤2和步骤3,直到参数的变化非常小,或达到预设的迭代次数。
逻辑回归的梯度计算
对于逻辑回归模型,其条件概率公式为:
P(y_i | x_i, W) = σ(y_i * (W^T x_i))
其中 σ(z) = 1 / (1 + exp(-z)) 是sigmoid函数,y_i ∈ {-1, +1}。
对数似然函数(通常更易于优化)为:
log L(W) = Σ_i log( σ(y_i * (W^T x_i)) )
其对参数 W 的梯度经过推导后,形式非常简洁:
∇ log L(W) = Σ_i [1 - σ(y_i * (W^T x_i))] * y_i * x_i
这个公式有直观的解释:对于每个数据点 i,如果模型预测的概率 σ(...) 很低(即预测错误),那么 [1 - σ(...)] 项就很大,梯度更新会朝着 y_i * x_i 的方向显著调整参数 W,以修正这个错误。
算法实现伪代码
基于上述推导,学习逻辑回归分类器的梯度上升算法变得非常简单:
初始化 W = [0, 0, ..., 0]
设置学习率 η (例如 0.01)
设置最大迭代次数 T
for t in 1 到 T:
初始化梯度向量 grad = [0, 0, ..., 0]
for 每个训练样本 (x_i, y_i):
计算 score = W^T * x_i
计算 prob = σ(y_i * score) # 预测当前样本正确的概率
grad += (1 - prob) * y_i * x_i # 累加梯度
W = W + η * grad # 更新参数
返回 W
总结

本节课中我们一起学习了梯度上升算法的核心思想及其在逻辑回归中的应用。我们从最大化似然函数的目标出发,推导出了参数更新的梯度公式。最终,我们得到了一个清晰、直观且易于实现的算法:它遍历数据,根据模型当前的预测误差来调整参数,逐步逼近最优分类器。尽管背后的数学推导可能略显复杂,但最终的算法实现仅需寥寥数行代码,这正是机器学习强大魅力的体现。
机器学习(分类,聚类和检索):第3-4课:梯度上升法回顾 🧗

在本节课中,我们将快速回顾梯度上升法的核心概念。梯度上升法是一种用于寻找函数最大值的优化算法,在机器学习中常用于最大化似然函数。我们将从直观的山地爬升比喻开始,逐步理解其数学原理和算法步骤。


山地爬升的直观理解 🏔️
上一节我们介绍了优化问题的背景,本节中我们来看看梯度上升法的直观解释。
你可以将梯度上升法视为一种“爬山”算法。观察左侧的图片,假设我们只有一个参数 W。想象从某个起点(例如第 T 次迭代的参数 W_T)开始,然后沿着山坡向上移动一小步,到达下一个参数 W_{T+1}。
移动的距离与以下项有关:
W_{T+1} = W_T + \eta \cdot \frac{dL}{dW} \bigg|_{W=W_T}
其中,\frac{dL}{dW} 是似然函数 L 关于参数 W 的导数在当前点 W_T 处的值。\eta 是一个额外的系数,我们称之为步长。在本模块稍后部分,我们将讨论如何选择步长及其影响。现在,假设步长是给定的。
你不断向上移动,最终会到达山顶,即最优解,我们暂时称之为 W*。我们的目标就是到达这个山顶。
收敛条件与停止准则 🎯
现在我们已经从抽象层面理解了爬山过程,即到达山顶 W*。接下来,我们可以讨论在迭代算法中如何知道何时停止,也就是何时收敛。
你可能记得,对于凸函数(我们今天处理的就是凸函数),在最优点处,似然函数关于 W 的导数将等于0,因为曲线在那里变得平坦。
\frac{dL}{dW} = 0
然而,我们永远无法精确地达到导数为0的点。因此,我们会在导数足够小时停止迭代。具体来说,当在当前参数 W_T 处计算的导数的绝对值小于某个容差参数 \epsilon 时,我们就停止。
\left| \frac{dL}{dW} \bigg|_{W=W_T} \right| < \epsilon
你可以将 \epsilon 设置为一个小数,例如 0.001,具体取决于问题。你将在作业中探索其影响。这样,虽然无法精确到达山顶,但可以非常接近,得到的解记为 Ŵ。
从一维到多维:梯度的概念 📈
以上讨论的是一维空间。但在实际中,我们通常处理高维空间,因为我们可能需要拟合成千上万个系数。
因此,我们不再计算一维导数,而是需要计算所谓的梯度。梯度是所有偏导数组成的向量:
\nabla L(W) = \left[ \frac{\partial L}{\partial w_0}, \frac{\partial L}{\partial w_1}, ..., \frac{\partial L}{\partial w_D} \right]^T
这是一个 D+1 维的向量(假设有 D 个特征)。在图中,从某点出发,梯度方向可能如箭头所示。我们的目标就是沿着这个梯度方向一直向上,直到山顶。
更形象地说,我们从某个初始点(选择初始点有多种启发式方法)开始,例如图中左侧的点。然后我们沿着梯度方向移动。右侧的图展示了所谓的等高线图,它对应着似然函数的不同水平集。
从左侧的点开始,相当于在三维图中从山脚出发。我们沿着梯度方向一步步移动,直到到达最优点 W*,这对应于爬到了山顶。
梯度上升算法总结 📝
以下是梯度上升算法的完整描述:
- 初始化:从某个初始点 W_0 开始。例如,可以设 W_0 = 0 或随机初始化。
- 迭代更新:重复以下步骤,直到梯度的模长足够小。
W_{t+1} = W_t + \eta \cdot \nabla L(W_t)
其中,\eta 是步长。 - 收敛判断:当梯度向量的模长 ||\nabla L(W_t)|| 小于预设的容差 \epsilon 时,算法停止。
这就是将我们带向最优解的算法,其过程在图中得到了示例。

本节课中我们一起学习了梯度上升法的核心思想:通过沿着函数梯度(最陡上升方向)迭代更新参数,以最大化目标函数(如似然函数)。我们回顾了其山地爬升的直观比喻、收敛的判定条件,以及从一维导数到多维梯度的扩展,并总结了完整的算法步骤。理解这些基础是后续应用梯度上升法解决逻辑回归等分类问题的关键。
机器学习(分类,聚类和检索):第3-4课:Logistic回归的学习算法 🧠

在本节课中,我们将要学习Logistic回归模型的学习算法。我们将回顾梯度下降法,并推导出Logistic回归的梯度上升更新规则。这个算法非常简洁,只需几行代码即可实现。
上一节我们介绍了最大似然估计和相关的数学推导。本节中我们来看看如何将这些理论转化为一个具体、可执行的学习算法。
梯度上升算法
Logistic回归的学习算法是梯度上升。其核心是计算对数似然函数关于每个参数 ( W_j ) 的导数。这个导数公式非常简单。
以下是导数公式的组成部分:
- 求和:对所有数据点求和。每个数据点对导数的贡献不同,有些会使 ( W_j ) 增大,有些则使其减小。
- 差值项:计算真实标签与模型预测之间的差值。具体是“指示函数”与“模型预测为正例的概率”之差。
- 指示函数:如果数据点 ( Y_i ) 的真实标签是正例(+1),则输出1;如果是负例,则输出0。
- 模型预测:模型认为数据点 ( X_i ) 属于正例的概率 ( P(Y=1|X) )。
- 特征权重:将上述差值乘以对应特征 ( X_j ) 的值。这意味着,如果某个特征值很大(例如“awesome”一词出现20次),它对参数更新的影响就更大;如果特征值为0,则对该参数的更新没有贡献。
因此,关于参数 ( W_j ) 的导数公式为:
[
\frac{\partial \ell}{\partial W_j} = \sum_{i=1}^{N} ( \mathbf{1}[Y_i = +1] - P(Y=1|X_i) ) \cdot X_{ij}
]
其中,( \mathbf{1}[Y_i = +1] ) 是指示函数,( P(Y=1|X_i) ) 是模型的预测概率,( X_{ij} ) 是第 ( i ) 个样本的第 ( j ) 个特征值。
得到导数后,梯度上升的更新规则就是按照这个导数的方向调整参数:
[
W_j \leftarrow W_j + \eta \cdot \frac{\partial \ell}{\partial W_j}
]
其中 ( \eta ) 是学习率,控制每次更新的步长。
算法实现
这个算法的实现极其简单。以下是其核心步骤的伪代码描述:
初始化权重 W
for 迭代次数 in range(总迭代次数):
计算梯度 = 0
for 每个数据点 i in 所有数据点:
计算预测概率 P_i = 1 / (1 + exp(-W·X_i))
计算误差 = (真实标签 Y_i) - P_i
梯度 += 误差 * 特征向量 X_i
W = W + 学习率 * 梯度
可以看到,尽管背后的数学推导可能较为复杂,但最终的学习算法只需要几行循环和计算即可实现。

本节课中我们一起学习了Logistic回归的梯度上升学习算法。我们回顾了梯度下降的概念,推导出了关键的导数公式,并看到了如何将其转化为一个简洁的迭代更新过程。这个算法高效而强大,是许多分类任务的基础。
机器学习:3-4:计算Logistic回归导数的示例

在本节课中,我们将通过一个具体的手算示例,演示如何计算Logistic回归模型中某个参数的梯度(导数)。我们将使用当前模型参数,对几个数据点进行预测,并汇总每个数据点对目标函数导数的贡献,最终应用梯度上升更新规则来调整参数。
模型与当前参数
假设在迭代步骤 T,我们的Logistic回归模型拥有以下参数:
- W0 = 0
- W1 = 1
- W2 = -2
这些参数构成了我们当前的参数估计 W^T。
我们的目标是计算似然函数关于参数 W1 的偏导数。参数 W1 将与第一个特征 h1(x) 相乘,在这个例子中,h1(x) 代表“好评”的数量。
计算数据点的导数贡献
根据梯度公式,每个数据点对导数的贡献为:
贡献 = h1(x_i) * [指示函数(y_i=+1) - P(y_i=+1 | x_i, W)]
其中:
- h1(x_i) 是第 i 个数据点的“好评”数量。
- 指示函数(y_i=+1) 在数据点真实标签为 +1 时等于 1,否则为 0。
- P(y_i=+1 | x_i, W) 是模型预测该数据点标签为 +1 的概率。
现在,我们逐一计算四个数据点对导数 ∂L/∂W1 的贡献。
以下是四个数据点的详细计算过程:
数据点 1:特征为 (好评=2, 差评=1),真实标签为 +1。
- 模型预测为正例的概率:P(+1) = 0.5
- 贡献计算:
2 * (1 - 0.5) = 1
数据点 2:特征为 (好评=0, 差评=2),真实标签为 -1。
- 模型预测为正例的概率:P(+1) = 0.02
- 贡献计算:
0 * (0 - 0.02) = 0 - 模型对这个负例的预测概率极低(0.02),判断非常准确。
数据点 3:特征为 (好评=3, 差评=3),真实标签为 -1。
- 模型预测为正例的概率:P(+1) = 0.05
- 贡献计算:
3 * (0 - 0.05) = -0.15 - 模型认为该点很可能是负例(概率0.95),贡献为负值。
数据点 4:特征为 (好评=4, 差评=1),真实标签为 +1。
- 模型预测为正例的概率:P(+1) = 0.88
- 贡献计算:
4 * (1 - 0.88) = 0.48
汇总梯度并更新参数
上一节我们计算了每个数据点对梯度的贡献,现在将它们汇总,得到关于 W1 的总梯度。
总梯度是各个数据点贡献之和:
∂L/∂W1 = 1 + 0 + (-0.15) + 0.48 = 1.33
得到梯度后,我们可以应用梯度上升更新规则来调整参数 W1。更新公式为:
W1^{t+1} = W1^{t} + η * (∂L/∂W1)
假设学习率 η 设置为 0.1。将当前值 W1^t = 1 和计算出的梯度 1.33 代入公式:
W1^{t+1} = 1 + 0.1 * 1.33 = 1.133
因此,在下次迭代中,参数 W1 将从 1 更新为 1.133。这个更新使 W1 略微增大,朝着最大化似然函数的方向前进。
总结

本节课中,我们一起完成了一个Logistic回归梯度计算的完整示例。我们首先明确了当前模型参数,然后根据梯度公式,逐步计算了每个训练数据点对目标函数(似然函数)关于特定参数 W1 的导数贡献。最后,我们汇总所有贡献得到总梯度,并应用梯度上升更新规则,使用学习率 η 对参数 W1 进行了更新。这个过程直观展示了梯度下降/上升法如何利用每个数据点的预测误差来迭代优化模型参数。
机器学习(分类,聚类和检索):3-4:解释Logistic回归的导数

在本节课中,我们将深入探讨Logistic回归中导数的含义。我们将通过分析不同情况下的导数贡献,来理解梯度如何指导模型参数更新,从而让模型学习得更准确。
上一节我们通过一个数值例子看到了导数是如何计算的。本节中我们来看看这些导数的实际意义。
理解单个数据点的贡献
假设我们正在更新某个特定参数 WJ,并且有一个特定的数据点 X。我们关注这个数据点对总导数的贡献。为了简化分析,我们假设该数据点的特征 HJ(X) 值为1,这样我们可以专注于分析预测概率与实际标签之间的差异。
我们将这个贡献称为 ΔI。其计算公式为:
ΔI = (Indicator[YI = +1] - P(Y = +1 | XI, W)) * HJ(XI)
由于我们设 HJ(XI) = 1,因此贡献简化为:
ΔI = Indicator[YI = +1] - P(Y = +1 | XI, W)
接下来,我们分析几种不同情况。
情况分析
以下是几种典型场景,帮助我们理解 ΔI 如何影响参数更新。
情况一:正确预测正例
- 场景:数据点标签 YI 为正(+1),且模型以很高的概率(接近1)预测其为正。
- 贡献分析:此时 ΔI ≈ 1 - 1 = 0。
- 含义:贡献接近0。这意味着从参数 WJ 的角度看,这个被正确分类的数据点“建议”不需要进行任何更改。模型已经做对了。
情况二:错误预测正例
- 场景:数据点标签 YI 为正(+1),但模型以很低的概率(接近0)预测其为正,即完全预测错误。
- 贡献分析:此时 ΔI ≈ 1 - 0 = 1。
- 含义:贡献是一个较大的正数。这个被错误分类的正例“希望”我们增加参数 WJ 的值。因为增加 WJ 会提高得分 Score,从而在下一步迭代中增加模型预测该数据点为正例的概率 P(Y = +1 | XI, W)。梯度下降正是在朝这个正确的方向推动参数。
情况三:正确预测负例
- 场景:数据点标签 YI 为负(例如,-1 或 0),且模型以很低的概率预测其为正(即,以高概率预测其为负)。
- 贡献分析:此时指示函数 Indicator[YI = +1] = 0,预测概率 P(Y = +1 | XI, W) ≈ 0,因此 ΔI ≈ 0 - 0 = 0。
- 含义:贡献同样接近0。被正确分类的负例也“建议”参数 WJ 无需改变。
情况四:错误预测负例
- 场景:数据点标签 YI 为负,但模型以很高的概率(接近1)预测其为正。
- 贡献分析:此时 ΔI ≈ 0 - 1 = -1。
- 含义:贡献是一个较大的负数。这个被错误分类的负例“希望”我们减小参数 WJ 的值。减小 WJ 会降低得分,从而降低模型预测该数据点为正例的概率,同时增加其预测为负例的概率。
核心机制总结
本节课中我们一起学习了Logistic回归梯度的直观解释。通过分析单个数据点在各种情况下的贡献(ΔI),我们揭示了梯度下降法更新参数的内在逻辑:
- 对于正例,如果预测错误(概率低),梯度会推动相关参数增大,以提高其被预测为正的概率。
- 对于负例,如果预测错误(概率高),梯度会推动相关参数减小,以降低其被预测为正的概率。
- 对于预测正确的样本,其梯度贡献接近零,对参数更新的影响很小。

这正是我们期望得分函数学习到的模式:让正例的得分更高,负例的得分更低。梯度计算为这种学习过程提供了精确的数学指导。
机器学习(分类,聚类和检索):第3-4课:Logistic回归梯度上升法总结 🎯

在本节课中,我们将学习Logistic回归的完整梯度上升算法。我们将从算法概述开始,逐步拆解其核心步骤,并解释每一步的计算细节。最后,我们将对整个算法进行总结。
算法概述
上一节我们介绍了Logistic回归的似然函数及其梯度。本节中,我们来看看如何利用梯度上升法来找到使似然函数最大化的最优参数。
梯度上升法的核心思想是:从一个初始参数点(例如 w0)开始,沿着似然函数梯度的方向(即函数增长最快的方向)迭代更新参数,直到达到最优解 w hat。当梯度的范数小于我们设定的容差参数 epsilon 时,算法停止迭代,这与回归问题中的处理方式类似。
迭代更新过程
在每次迭代中,算法会逐个特征(或系数)进行计算和更新。以下是每次迭代的核心步骤:
-
计算偏导数:对于第 j 个系数 Wj,计算当前迭代 t 下似然函数 L 关于该系数的偏导数。
- 公式表示为:∂L(t) / ∂Wj
-
更新系数:使用计算得到的偏导数和预设的步长(学习率)来更新系数。
- 更新公式为:Wj(t+1) = Wj(t) + η * (∂L(t) / ∂Wj)
- 其中 η 是步长。
核心计算:预测概率
在上述偏导数的计算中,核心的计算部分是评估在给定当前参数 W(t) 下,数据点 Xi 被预测为正类(+1)的概率。
这个概率的计算正是Logistic回归模型本身:
P(yi = +1 | Xi, W(t)) = 1 / (1 + e(-W(t)T * Xi))
得到这个预测概率后,将其与数据点的真实标签(若为正例则为1,否则为0)进行比较,再乘以对应的特征值 Xij,并对所有数据点求和,就得到了偏导数的值。
算法总结
本节课中我们一起学习了Logistic回归的梯度上升算法。这是一个极其简单、极其有用且非常强大的算法。

其流程可以概括为:从初始参数出发,在每次迭代中,计算似然函数关于每个系数的梯度,然后沿梯度方向更新参数。这个过程的核心是使用Logistic函数计算预测概率。当参数更新变化很小(梯度范数小于容差)时,算法收敛,我们便得到了模型的最优参数估计。
机器学习:3-4:选择梯度下降的步长

在本节课中,我们将学习如何为梯度下降算法选择步长参数(η)。这是一个需要仔细调整的关键步骤,我们将介绍几种实用的启发式方法。
概述
到目前为止,我们在讨论梯度下降(或上升)时,都假设步长参数 η 是给定的。本节我们将探讨如何选择这个参数。需要提前说明的是,这通常很困难,需要大量的调优。我们将介绍几种启发式方法来应对这个挑战。
构建学习曲线
选择步长时,最重要的一件事是构建所谓的“学习曲线”。下图展示了一个例子:

在X轴上,我们标出了迭代次数(在梯度下降算法中我们称之为 t),例如第1次迭代、第2次迭代等。对于每次迭代(或者每10次迭代),我们计算在整个数据集上的对数似然值。其公式如下:
L(w_t) = log( ∏_{i=1}^{n} P(y_i | x_i, w_t) )
这个值衡量了在第 t 次迭代时,当前参数估计的质量。我们可以在每次参数更新后测量这个质量指标。从图中可以看到,质量指标以一种相当平滑的方式变得越来越大,这是理想的情况。我们从大约 -37000 的较低值开始(记住这些值是负数),随着迭代次数的增加,它会不断上升。这条曲线对应一个特定的步长值:η = 10^{-5}。这是一个相对较小的步长,我们得到了这条看起来相当不错的上升曲线。
如何确定步长
我们通常的做法是尝试一系列不同的 η 值,并试图找到一个好的值。为了理解步长过小或过大会发生什么,让我们观察不同的学习曲线。通过观察这些行为,你可以对数据中可能出现的模式有所了解,并据此选择一个好的参数。
对于 η = 10^{-5},我们称之为“偏小”,因为曲线在50次迭代后仍在上升。这意味着我们可能需要执行超过50次迭代。这也引出了另一个观察点:我们何时停止?什么是停止准则?在这里,曲线仍在上升,所以我们应该继续迭代。
步长过小的情况
现在,让我们观察两条曲线。顶部蓝色曲线是我们刚刚观察过的 η = 10^{-5} 的情况。绿色曲线对应更小的步长 η = 10^{-6}。
我们观察到两条都是平滑的曲线,但 η = 10^{-5} 的曲线上升更快,并且达到了更高的似然值。η = 10^{-6} 的曲线仍在上升,只是步长非常小。可以想象,它正在以非常、非常小的步幅爬山,最终会到达山顶,但需要很长时间。通过尝试两个参数并绘图,你可以看到 η = 10^{-5} 可能是比 η = 10^{-6} 更好的参数。
尝试稍大的步长
既然 η = 10^{-5} 看起来不错,也许可以尝试稍大一点的步长。更大的步长意味着向山顶迈出更大的步伐。
这里我们比较 η = 10^{-5} 和 η = 1.5 × 10^{-5}(即大了50%)的情况。观察到的行为非常有趣,在实践中也经常看到。
在早期阶段,较大的步长会导致一些振荡。但一旦开始接近山顶,你会发现到了后期,较大的参数值往往能取得更快的进展。这条橙色曲线在后期进展更平滑、更快,并且开始达到更高的似然值(质量更高)。这很有趣:如果你的参数稍大(但不是太大),可能在开始时看到一些振荡,但之后往往会趋于平稳并表现良好。
尝试更大的步长
那么你可能会说,η = 1.5 × 10^{-5} 看起来不错,让我们尝试再大一点。

上图展示了当步长变得过大时会发生的情况。红色曲线对应 η = 10^{-4},这是一个更大的步长。你可以看到,曲线出现了剧烈的振荡和不稳定,似然值没有持续增长,反而上下波动。这表明步长过大,导致算法在最优解附近“跳跃”而无法收敛。这是一个需要避免的情况。
总结

本节课中,我们一起学习了如何为梯度下降选择步长参数 η。关键方法是构建并观察学习曲线,通过比较不同 η 值下的曲线行为来做出选择。步长过小(如 η = 10^{-6})会导致收敛缓慢;步长适中(如 η = 10^{-5} 到 η = 1.5 × 10^{-5})通常能稳定地提升目标函数;而步长过大(如 η = 10^{-4})则会引起振荡和不收敛。实践中,需要通过反复试验和调整来找到适合特定数据集和模型的“最佳”步长。
机器学习:3-4:对过大步长要小心 ⚠️

在本节课中,我们将探讨梯度下降算法中步长(学习率)选择的重要性。我们将通过对比不同步长下的收敛情况,理解为什么过大的步长会导致问题,并学习如何选择合适的步长范围。
上一节我们介绍了步长(学习率)对梯度下降收敛速度的影响。本节中,我们来看看当步长设置得过大时会发生什么。
首先,我们回顾一下之前的实验结果。我们有一条蓝色曲线,其步长(Eta)为 10^-5。然后有一条青色曲线,其步长比蓝色曲线大50%,即 1.5 * 10^-5。
现在,我们尝试一个更大的参数。红色曲线对应的步长为 2.5 * 10^-5,这是蓝色曲线步长的2.5倍。我们观察到,在迭代初期出现了更大的振荡,并且这种振荡阶段持续了很长时间。虽然振荡在后期有所减小,但算法并未完全收敛。在似然函数 L(W) 的值上,红色曲线与最优值之间存在显著差距。因此,2.5 * 10^-5 这个步长太大了。
为了更好地理解振荡产生的原因,让我们进行一个直观的比喻。
如果使用蓝色曲线对应的、非常平滑的步长,我们会从一个起点出发,沿着一条平滑的曲线,通过一系列小步长逐渐接近目标参数 W_hat。
然而,如果选择的步长过大,情况就不同了。假设我们用绿色来表示这个过大的步长。我们从起点开始,计算梯度方向,这个方向在初期看起来是正确的。但由于步长太大,我们一步就跨到了一个很远的地方。然后,我们在新的位置重新计算梯度,方向可能指向另一边,再次因为步长过大而跨到另一个遥远的位置。如此反复,我们就会在目标值附近来回振荡。
在红色曲线(2.5 * 10^-5)的例子中,我们看到振荡是逐渐减小的。这意味着最终它可能会越来越接近 W_hat,但我们必须非常小心。
现在,让我们看看当步长设置得更大时会发生什么。

这里我们尝试了一个更大的步长参数:Eta = 10^-4。请注意,之前的步长数量级是 10^-5,而这个是 10^-4,比最初的蓝色曲线步长大10倍。

我们观察到的第一件事是剧烈的振荡。这个参数显然太大了,迭代路径看起来杂乱无章,完全没有收敛的迹象。并且,其达到的似然函数值远低于其他参数设置下的结果。
从另一个角度看,我们之前认为红色参数(2.5 * 10^-5)已经太大了,它与蓝色参数(10^-5)之间有巨大差距。但为了展示这个疯狂振荡的紫色曲线,我们不得不把坐标轴尺度调得更大,相比之下,红色和蓝色曲线之间的差距看起来就很小了。这进一步证明 10^-4 这个步长是过大的。
以下是我们的发现总结:
我们了解到:
10^-6太小,收敛过慢。10^-4太大,导致剧烈振荡且不收敛。
现在,我们有了“太大”和“太小”之间的一个范围。我们下一步可以在这个范围内进行搜索,以找到最佳的步长。

本节课中我们一起学习了步长(学习率)对梯度下降算法收敛性的关键影响。过小的步长导致收敛缓慢,而过大的步长则会引起振荡,甚至阻碍收敛。一个合适的步长应能平衡收敛速度和稳定性,确保算法平滑、稳定地逼近最优解。在实践中,我们通常需要通过实验,在“太大”和“太小”之间找到一个合适的值。
机器学习(分类,聚类和检索):第3-4课:选择步长的经验法则 🎯

在本节课中,我们将学习如何为梯度下降算法选择合适的学习率(步长)。学习率是决定模型收敛速度和效果的关键参数。我们将介绍一个实用的经验法则,并探讨固定步长与递减步长的区别。
选择步长的经验法则
上一节我们介绍了梯度下降的基本概念。本节中,我们来看看如何选择一个有效的学习率。
理论上存在一些指导原则,但在实践中往往难以直接应用。以下是一个最实用的方法。
以下是选择学习率的具体步骤:
- 尝试多个指数间隔的值:首先尝试一系列以指数间隔分布的学习率值,例如从
10^-4到10^-6。 - 绘制学习曲线:针对每个尝试的学习率,绘制目标函数值(如训练似然)随迭代次数变化的曲线图。
- 识别边界:通过曲线图,找出导致学习过程“太慢”(曲线下降极其缓慢)的过小值,以及导致“振荡甚至发散”(曲线剧烈波动或不降反升)的过大值。
- 在边界内进一步搜索:在找到的过大值和过小值所确定的范围内,再次尝试一系列指数间隔的学习率值。
- 选择最佳值:最终,选择那个能带来最佳训练似然(即目标函数值最小或收敛最稳定)的学习率。
这是一个简单的启发式方法,但如果你需要从头实现梯度下降,这基本上是必须进行的步骤。
进阶话题:递减步长
到目前为止,我们讨论的都是固定步长,即每次迭代都使用相同的值,例如始终使用 10^-5。这是一个进阶步骤。
理论上,并且实践中也常常如此,使用随着迭代进行而递减的步长是有益的。在开始时,我们距离最优解较远,可以迈出较大的步伐;而在接近最优解时,则需要非常小的步伐来精确调整,最终收敛到最优解 W_hat。
那么,递减步长的公式是什么样的呢?定义方式有多种,这里给出一个在实践中通常效果良好的实用例子。
你选择一个依赖于迭代次数 t 的步长,记为 η_t。其定义方式如下:
η_t = η_0 / t
其中,η_0 是一个常数,你可以使用前面描述的经验法则来调试和确定其合适的值范围(找到其最小有效值和最大有效值)。然后,在每次迭代时,将 η_0 除以当前的迭代次数 t。
这意味着:
- 第1次迭代:使用
η_0 - 第2次迭代:使用
η_0 / 2 - 第3次迭代:使用
η_0 / 3 - 以此类推...
通过这种方式,步长会变得越来越小。对于本模块将要讨论的应用场景,固定步长已经足够。但在更高级的设置中,你可能会考虑使用这种递减步长策略。

本节课中我们一起学习了如何为梯度下降选择学习率。我们掌握了一个通过尝试指数间隔值并观察学习曲线来寻找合适固定步长的实用经验法则。此外,我们还了解了递减步长这一进阶概念,它通过随时间减小步长来帮助模型在后期更精细地收敛。对于初学者,掌握固定步长的选择方法已足够应对大部分基础问题。
机器学习(分类,聚类和检索):第3-4课:非常可选:推导Logistic回归梯度的对数技巧 📝

在本节课中,我们将学习如何推导逻辑回归似然函数的梯度。这是一个数学性较强的主题,但理解其推导过程能帮助我们更深入地掌握逻辑回归的工作原理。我们将从回顾对数似然函数开始,逐步推导出梯度公式。
上一节我们介绍了逻辑回归的梯度上升算法及其实现。本节中,我们将深入探讨如何计算似然函数的梯度,即其导数。
对数似然函数 📈

我们的目标是找到系数 W,以最大化似然函数。该函数是数据点概率的乘积:P(y_i | x_i, W)。然而,对似然函数取自然对数(记作 LL(W))可以大大简化后续的数学运算。
对数函数 ln(z) 具有以下重要性质:
- 它是一个单调递增函数。
- 它将乘法转换为加法:
ln(a * b) = ln(a) + ln(b)。 - 它将除法转换为减法:
ln(a / b) = ln(a) - ln(b)。
由于对数函数是单调的,最大化原始似然函数 L(W) 与最大化其对数值 LL(W) 会得到完全相同的解 W。因此,使用对数似然函数不会改变最优结果,但能使计算过程更简单。
以下是使用对数简化计算的关键步骤:
- 从乘积到求和:原始似然函数是多个概率的乘积。取对数后,乘积项转换为求和项,这更易于进行微分等操作。
- 保持最优解不变:因为
ln(x)是单调函数,所以argmax_w L(W) = argmax_w ln(L(W))。
梯度推导 🧮
现在,我们开始推导对数似然函数 LL(W) 关于参数 W 的梯度。梯度是一个向量,其每个分量是 LL(W) 对 W 中每个参数的偏导数。
推导过程涉及链式法则和对数函数的导数性质。核心步骤如下:
- 将对数似然函数
LL(W)写为所有数据点对数概率之和的形式。 - 对求和式中的每一项应用链式法则进行求导。
- 利用逻辑函数(Sigmoid函数)
σ(z) = 1 / (1 + e^{-z})的导数性质:σ'(z) = σ(z) * (1 - σ(z))。 - 将对数概率的导数与逻辑函数的导数结合,并进行化简。
经过推导,最终得到的梯度公式简洁而优美。对于单个数据点 (x_i, y_i),其对梯度的贡献为 (y_i - P(y_i=1 | x_i, W)) * x_i。将所有数据点的贡献相加,就得到了完整的梯度。
以下是梯度公式的向量化表示,适用于高效计算:
# 假设 X 是特征矩阵,y 是标签向量,W 是参数向量,sigmoid 是逻辑函数
# 计算预测概率
predictions = sigmoid(X.dot(W))
# 计算梯度
gradient = X.T.dot(y - predictions)
总结 🎯


本节课中,我们一起学习了如何推导逻辑回归的对数似然函数梯度。我们首先看到,通过对似然函数取对数,可以将复杂的乘积运算转化为求和运算,从而简化求导过程。接着,我们逐步推导,并最终得到了一个清晰、易于计算的梯度表达式 (y_i - P(y_i=1 | x_i, W)) * x_i。理解这个推导过程,不仅有助于我们实现梯度上升算法,也为我们深入理解逻辑回归模型提供了坚实的数学基础。
机器学习(分类,聚类和检索):第3-4课:非常可选:表达对数似然

在本节课中,我们将探讨一个对后续数学推导至关重要的概念:对数似然。我们将看到,通过对似然函数取对数,可以极大地简化梯度计算等操作。本节内容属于高级推导部分,但我们会用简单直白的方式解释其核心思想。
对数函数的重要性
上一节我们介绍了似然函数的概念。本节中,我们来看看为什么对数函数在处理似然函数时如此重要。
关键在于,我们通常需要计算似然函数的梯度以进行优化。直接对原始的似然函数(一个乘积形式)求导非常复杂。而对数函数可以将乘积转化为求和,从而简化求导过程。
具体来说,对于一组函数 F_i 的乘积取对数,其结果等于每个函数对数的和。用公式表示如下:
log(∏_{i=1}^{n} F_i) = ∑_{i=1}^{n} log(F_i)
在我们的分类问题中,似然函数是每个数据点预测概率的乘积。应用上述对数性质,我们可以得到对数似然函数:
log likelihood = ∑_{i=1}^{n} log( P(y_i | x_i, w) )
这样,原本复杂的乘积导数就变成了简单的求和导数,因为和的导数等于导数的和。这是我们在机器学习中经常使用对数似然的核心原因之一。
引入指示函数
在定义了对数似然之后,为了进一步简化表达式,特别是处理二分类(+1和-1)的情况,我们引入指示函数。
指示函数 I(condition) 在条件为真时等于1,否则等于0。利用它,我们可以将对数似然函数中的每一项 log( P(y_i | x_i, w) ) 拆解为两个明确的部分。
以下是具体的拆解方式:
- 当真实标签
y_i = +1时,该项等于I(y_i=+1) * log( P(y_i=+1 | x_i, w) )。 - 当真实标签
y_i = -1时,该项等于I(y_i=-1) * log( P(y_i=-1 | x_i, w) )。
因此,整个对数似然函数可以统一写成:
log likelihood = ∑_{i=1}^{n} [ I(y_i=+1)*log(P(y_i=+1)) + I(y_i=-1)*log(P(y_i=-1)) ]
这种表达方式的优势在于,它清晰地分离了两种类别的情况,使得后续求导时,我们可以分别处理 P(y=+1) 和 P(y=-1) 的概率公式,让数学推导更加条理清晰。
总结
本节课中,我们一起学习了两个关键的数学技巧,它们为后续逻辑回归等模型的推导奠定了基础。
首先,我们了解了取对数的重要性,它将概率的乘积转换为对数的和,从而让梯度计算从处理复杂的乘积法则简化为处理简单的求和。
其次,我们引入了指示函数,它将二分类问题中对数似然项的书写统一化,明确区分了不同类别的情况,为下一步的求导做好了准备。

掌握这些表达形式,是理解许多机器学习模型(尤其是基于概率的模型)训练过程的核心。
机器学习:分类、聚类与检索:3-4:非常可选:推导给定x时y=1的概率

在本节课中,我们将学习如何推导逻辑回归模型中,给定特征x时,目标变量y等于-1的概率。这是计算对数似然函数梯度的一个非常深入的步骤,主要面向对此特别感兴趣的进阶学习者。
上一节我们介绍了如何计算对数似然函数。本节中,我们来看看如何表达y等于-1的概率,因为我们目前只定义了y等于+1的概率。这部分内容属于非常深入的可选推导。
我们需要推导出,在已知x和参数W的情况下,y等于-1的概率。已知y等于+1的概率公式如下:
P(y=+1 | x, W) = 1 / (1 + e{-WT h(x)})
由于概率之和必须为1,因此y等于-1的概率就是1减去y等于+1的概率。以下是推导步骤:
P(y=-1 | x, W) = 1 - P(y=+1 | x, W)
将y=+1的概率公式代入:
P(y=-1 | x, W) = 1 - 1 / (1 + e{-WT h(x)})
为了简化这个表达式,我们对两项同时乘以分母 (1 + e{-WT h(x)}):
P(y=-1 | x, W) = [ (1 + e{-WT h(x)}) - 1 ] / (1 + e{-WT h(x)})
分子中的1相互抵消,最终得到简洁的公式:
P(y=-1 | x, W) = e{-WT h(x)} / (1 + e{-WT h(x)})
推导过程清晰明了,结果也非常简洁。

本节课中,我们一起学习了如何从y=+1的概率出发,推导出逻辑回归模型中y=-1的概率。这个结果是后续进行梯度计算的重要基础。
机器学习:3-4:将对数似然重写为更简单的形式

在本节中,我们将学习如何将逻辑回归的对数似然函数进行重写和简化。我们将从之前推导出的正负类概率公式出发,通过一系列代数变换,得到一个更简洁、更易于后续求导的形式。
上一节我们介绍了正类(y=+1)和负类(y=-1)的概率公式。本节中,我们将把这些公式代入对数似然函数,并进行化简。
首先,我们回顾一下概率公式:
- 正类概率:
P(y=+1) = 1 / (1 + e^{-w^T h(x)}) - 负类概率:
P(y=-1) = e^{-w^T h(x)} / (1 + e^{-w^T h(x)})
现在,我们将这些公式代入针对单个数据点 (x_i, y_i) 的对数似然函数中。
以下是代入和化简的步骤:
步骤一:代入正类概率项
第一项是当 y_i = +1 时的贡献。我们直接代入正类概率公式:
LL_i = 1[y_i=+1] * log( 1 / (1 + e^{-w^T h(x_i)}) )
步骤二:处理负类概率项
第二项是当 y_i = -1 时的贡献。我们首先用 1[y_i=+1] 来表示指示函数 1[y_i=-1],因为两者是互补的:
1[y_i=-1] = 1 - 1[y_i=+1]
然后代入负类概率公式:
LL_i += (1 - 1[y_i=+1]) * log( e^{-w^T h(x_i)} / (1 + e^{-w^T h(x_i)}) )
步骤三:展开并化简对数项
接下来,我们分别展开两个对数项。
-
对于第一项,利用对数性质
log(1/a) = -log(a):
log( 1 / (1 + e^{-w^T h(x_i)}) ) = -log(1 + e^{-w^T h(x_i)})
因此第一项变为:-1[y_i=+1] * log(1 + e^{-w^T h(x_i)}) -
对于第二项中的分式,利用对数性质
log(a/b) = log(a) - log(b):
log( e^{-w^T h(x_i)} / (1 + e^{-w^T h(x_i)}) ) = log(e^{-w^T h(x_i)}) - log(1 + e^{-w^T h(x_i)})
进一步化简,因为log(e^a) = a:
= -w^T h(x_i) - log(1 + e^{-w^T h(x_i)})
因此第二项整体变为:(1 - 1[y_i=+1]) * ( -w^T h(x_i) - log(1 + e^{-w^T h(x_i)}) )
步骤四:合并同类项
现在我们将两项相加并合并含有 log(1 + e^{-w^T h(x_i)}) 的项。
- 来自第一项:
-1[y_i=+1] * log(1 + e^{-w^T h(x_i)}) - 来自第二项:
-(1 - 1[y_i=+1]) * log(1 + e^{-w^T h(x_i)})
将这两部分相加:
[-1[y_i=+1] - (1 - 1[y_i=+1])] * log(1 + e^{-w^T h(x_i)}) = -1 * log(1 + e^{-w^T h(x_i)})
步骤五:得到最终简化形式
合并所有项后,针对单个数据点 i 的对数似然简化形式为:
LL_i = - (1 - 1[y_i=+1]) * w^T h(x_i) - log(1 + e^{-w^T h(x_i)})
我们可以进一步观察这个形式。(1 - 1[y_i=+1]) 在 y_i = +1 时为0,在 y_i = -1 时为1。因此,这个简化形式清晰地表明:
- 当样本为负类(
y_i = -1)时,对数似然包含-w^T h(x_i)项。 - 无论样本类别如何,都包含
-log(1 + e^{-w^T h(x_i)})项。

本节课中我们一起学习了如何将逻辑回归的对数似然函数从包含两个指示函数的复杂形式,重写为一个更紧凑、更优雅的简化形式。这个形式为 LL_i = - (1 - 1[y_i=+1]) * w^T h(x_i) - log(1 + e^{-w^T h(x_i)})。这个简化后的表达式将大大方便我们在下一节中进行梯度计算。
机器学习(分类,聚类和检索):第3-4课:非常可选:推导对数似然的梯度

在本节中,我们将深入探讨逻辑回归模型对数似然函数梯度的推导过程。这是一个进阶主题,旨在展示如何通过数学计算得到梯度公式。我们将从单个数据点的对数似然函数出发,逐步推导其关于参数 w_j 的偏导数。


概述
我们将要学习如何计算逻辑回归模型的对数似然函数关于模型参数 w_j 的梯度。推导过程涉及对复合函数求导,最终会得到一个简洁而优美的结果。理解这个推导有助于深入掌握逻辑回归的训练原理。
对数似然函数的表达形式
上一节我们介绍了单个数据点的对数似然函数。本节中我们来看看它的具体形式。
对于单个数据点 (x_i, y_i),其对数似然函数可以写成以下形式:
L_i(w) = [1 - I(y_i = +1)] * (w^T h(x_i)) - log(1 + exp(-w^T h(x_i)))
其中 I(y_i = +1) 是指示函数,当 y_i = +1 时为1,否则为0。h(x_i) 是特征函数。
对参数 w_j 求偏导
现在,我们将对这个对数似然函数 L_i(w) 关于特定参数 w_j 求偏导数。由于函数是两项之和,其导数也是两项导数之和。
以下是计算步骤:
首先,处理第一项。第一项是 [1 - I(y_i = +1)] * (w^T h(x_i))。指示函数部分与 w_j 无关,可以视为常数因子提出。因此,第一项关于 w_j 的偏导数为:
∂/∂w_j { [1 - I(y_i=+1)] * (w^T h(x_i)) } = [1 - I(y_i=+1)] * ∂/∂w_j (w^T h(x_i))
而 w^T h(x_i) 关于 w_j 的偏导数就是特征 h_j(x_i),因为 w^T h(x_i) = Σ_k w_k * h_k(x_i),只有 w_j * h_j(x_i) 这一项依赖于 w_j。
所以第一项的导数为:
[1 - I(y_i=+1)] * h_j(x_i)
接下来,处理第二项。第二项是 - log(1 + exp(-w^T h(x_i)))。我们需要计算其关于 w_j 的偏导数。
这是一个复合函数的求导过程。经过一系列链式法则计算(具体步骤在此省略),我们可以得到结果:
∂/∂w_j { - log(1 + exp(-w^T h(x_i))) } = h_j(x_i) * [ exp(-w^T h(x_i)) / (1 + exp(-w^T h(x_i))) ]
请注意,表达式 exp(-w^T h(x_i)) / (1 + exp(-w^T h(x_i))) 恰好等于模型预测 y = -1 的概率,即 P(y_i = -1 | x_i, w)。
合并两项结果
现在,我们将第一项和第二项的导数结果合并。
第一项(红色部分)贡献了:
- [1 - I(y_i=+1)] * h_j(x_i)
第二项(蓝色部分)贡献了:
+ h_j(x_i) * P(y_i = -1 | x_i, w)
通过代入关系 P(y_i = +1 | x_i, w) = 1 - P(y_i = -1 | x_i, w) 并进行代数整理,最终可以简化为:
∂L_i(w) / ∂w_j = h_j(x_i) * [ I(y_i = +1) - P(y_i = +1 | x_i, w) ]
这个结果非常直观:梯度等于特征值 h_j(x_i) 乘以真实标签(指示函数)与模型预测概率之间的差值。
扩展到整个数据集
以上是针对单个数据点的梯度。对于包含 n 个数据点的整个数据集,总的对数似然函数关于 w_j 的梯度就是所有数据点贡献的梯度之和。
因此,完整的梯度公式为:
∂L(w) / ∂w_j = Σ_{i=1}^{n} h_j(x_i) * [ I(y_i = +1) - P(y_i = +1 | x_i, w) ]
总结

本节课中我们一起学习了逻辑回归模型对数似然函数梯度的完整推导过程。我们从单个数据点的函数形式出发,分别对两项求导,最终得到了简洁的梯度表达式:特征值乘以(真实标签与预测概率之差)。这个结果不仅优美,而且是逻辑回归使用梯度下降法进行训练的核心。对于勇于探索这一进阶内容的学者,我们表示赞赏,因为此类推导在机器学习中非常常见,是理解模型底层机制的关键。
机器学习(分类,聚类和检索):第3-4课:学习Logistic回归分类器的回顾

在本节课中,我们将回顾Logistic回归分类器的核心学习过程。我们将总结如何定义模型、构建质量度量指标(似然函数),以及如何使用梯度上升算法来找到最佳参数。最后,我们会简要展望下一模块将讨论的正则化与过拟合问题。
模型定义与学习问题
上一节我们介绍了Logistic回归模型的基本形式。本节中,我们来看看如何从训练数据中学习这个模型的参数。
我们拥有一些训练数据。通过一个特征提取函数,我们可以得到特征向量 h(x)。在Logistic回归模型中,一个评论是正面(标记为1)的概率由以下公式给出:
P(y=1 | x) = 1 / (1 + e{-wT h(x)})
其中,w 是我们需要学习的权重参数向量。

质量度量:似然函数
为了评估参数 w 的好坏,我们需要定义一个质量度量指标。对于Logistic回归,我们使用似然函数。
这个似然函数可以被解释为:在给定当前参数 w 的情况下,模型预测结果与训练数据中真实标签一致的概率。我们的学习目标就是最大化这个似然函数。
优化算法:梯度上升
我们使用梯度上升算法来优化似然函数,从而找到最佳的参数 w 和 h。
梯度上升算法的思想非常直观且实现简单:它沿着函数增长最快的方向(即梯度方向)反复更新参数,以逐步逼近最大值点。
以下是梯度上升算法的核心更新步骤:
# 伪代码示例
while not converged:
w = w + learning_rate * gradient_of_likelihood(w, data)
我们有一个可选的深入章节,详细推导了这个梯度公式的来源。理解这个推导有助于深入掌握算法原理,但对于应用而言,直接使用梯度上升更新规则即可。
当前进展总结
至此,你已经能够:
- 定义Logistic回归模型。
- 理解并定义用于评估模型的质量度量指标——似然函数。
- 应用直观的梯度上升算法来优化这个指标并学习模型参数。
即使在这个阶段,你已经具备了从头开始实现自己的Logistic回归算法所需的所有知识,这非常令人兴奋。
下一模块展望
在接下来的模块中,我们将在此基础上更进一步,探索正则化与过拟合的概念。
这在机器学习实践中至关重要,能帮助我们的模型在未知数据上表现得更好。这将是我们下一阶段的学习方向。


本节课中,我们一起回顾了Logistic回归分类器的完整学习流程:从模型定义、似然函数构建到梯度上升优化。你已经掌握了实现该算法的核心要素,并为学习更高级的模型改进技术(如正则化)打下了坚实的基础。
机器学习(分类,聚类和检索):第3-4课:评估分类器与过拟合

在本节课中,我们将学习如何评估分类器的性能,并探讨机器学习中一个核心问题——过拟合。我们将从分类误差的计算开始,理解为何需要区分训练集和验证集,并初步了解如何帮助逻辑回归等模型避免过拟合。
评估分类器性能

上一节我们介绍了逻辑回归作为线性分类器的核心示例及其梯度下降学习过程。本节中,我们来看看如何衡量一个分类器的好坏。

为了探索过拟合的概念,我们首先需要更好地理解在分类任务中如何测量误差。
对于一个分类器,我们通常从一些已标记的数据开始,例如标记为正面或负面的评论。然后,我们将这些数据分为两部分:训练集用于训练模型,验证集用于评估训练好的模型。接下来,我们详细讨论分类器的通用评估方法。
正如在第一门课程中讨论的,我们使用分类错误率来衡量分类器的性能。以下是评估过程:
- 对于一个给定的句子(例如“寿司很棒”),其真实标签为正面。
- 我们将这个句子输入分类器,但隐藏其真实标签,因此分类器不知道它在训练数据中的标记。
- 然后,我们比较分类器的预测输出 \(\hat{y}\) 与真实标签。如果两者一致,则分类正确;否则,分类错误。
我们将在验证集上逐个示例进行此操作,统计正确和错误的数量。
现在,我们可以计算数据上的错误率或分类错误率。其公式很简单:
错误率 = (错误分类的数据点数量) / (数据点总数)
有时我们也会讨论准确率,它是1减去错误率:
准确率 = (正确分类的数据点数量) / (数据点总数)
过拟合问题与应对思路
了解如何评估性能后,我们现在可以转向一个实际构建分类器时必须考虑的重要问题:过拟合。过拟合是机器学习中一个非常显著的问题,对于逻辑回归来说尤其麻烦。
那么,让我们看看在这个背景下如何帮助避免过拟合。在后续课程中,我们将深入探讨具体的正则化技术。本节课的重点是建立评估框架并理解过拟合的基本概念。
本节课总结

本节课中,我们一起学习了分类器性能评估的基础。我们介绍了将数据分为训练集和验证集的重要性,并定义了分类错误率和准确率的计算公式。此外,我们初步探讨了过拟合问题,认识到它是模型在实际应用中需要解决的关键挑战,为后续学习正则化等解决方案奠定了基础。
机器学习(分类,聚类和检索):第3-4课:分类中的过拟合回顾 🧠


在本节课中,我们将要学习机器学习中的一个核心概念——过拟合。我们将首先回顾在回归问题中过拟合的表现和影响,然后探讨这一概念如何迁移到分类问题中。理解过拟合对于构建泛化能力强的模型至关重要。
回归中的过拟合回顾 📈
上一节我们介绍了分类误差,现在可以探讨分类中的过拟合概念。但在开始之前,让我们先回顾一下在回归课程中讨论过的过拟合问题。
在回归课程中,我们有一个运行示例:尝试预测Y轴上的房屋价格,给定房屋的某些特征。在这个例子中,X轴是房屋的平方英尺数或面积。我们在左侧看到一个非常平滑的曲线,它帮助我们根据房屋面积预测其价格。
然而,如果我们不使用左侧那样的二阶多项式,而是使用更高阶的多项式,我们可能会得到一条非常疯狂、曲折的线。这条线对训练数据的拟合极好,但无法泛化到测试集中的数据或真实世界的数据。
在这种情况下,我们说这里的模型 F 对训练数据过拟合了。
在分类中,我们将遇到同样类型的问题,并且必须尝试解决它:当你学习一个在训练数据上表现“太好”(训练误差过低)但在真实误差上表现不佳的模型时,会发生什么。
现在,让我们呈现一些在回归课程中讨论过的图表。在X轴上,我展示了模型复杂度。左侧的模型是一个非常简单的常数模型,而右侧的模型是一个疯狂的、非常高阶的多项式。
以下是训练误差和真实误差随模型复杂度变化的趋势:
- 训练误差:当你使用一个简单模型时,它在训练数据上表现并不好。但如果你使用这个疯狂的高阶多项式,它可能会得到零训练误差。在两者之间,训练误差像这样递减,并最终趋于0。因此,训练误差曲线是递减的。
- 真实误差:训练误差趋于零的问题是,如果你观察底层模型,它在其他房屋数据上表现不佳。因此,当你没有大量数据时,真实误差在模型非常简单时很高,在模型非常复杂时也很高。真实误差函数具有先下降后上升的特征。因此,真实误差曲线呈U形。
所以,过拟合发生在我们选择了在训练数据上表现“太好”(即位于此处右侧)但在真实误差方面表现不佳的模型时。
换句话说,你得到了一些参数 Ŵ,它们具有很低的训练误差但很高的真实误差;而存在另一些我们可以称之为 W* 的参数,它们可能在训练数据上表现不那么好,但在真实误差方面的性能却好得多。
因此,我们希望尽量避免选择这些在训练数据上表现极佳但在现实世界中表现不佳的模型。我们希望从右侧向左移动,以避免过拟合。


以上是针对回归场景的讨论。接下来,我们将在分类场景中探讨它。
机器学习(分类,聚类和检索):第3-4课:分类中的过拟合


概述
在本节课中,我们将要学习分类模型中的过拟合现象。我们将通过一个具体的例子,观察当模型变得过于复杂时会发生什么,并理解如何识别过拟合。
分类中的过拟合现象
上一节我们讨论了分类器的基本概念,本节中我们来看看过拟合在分类器中具体是什么样子。
我们讨论过多种分类器,例如,这里我们为数据拟合一个线性分类器。这是一个预测餐厅评论是正面还是负面的常见例子。我们看到,直线下方的点得分大于零,直线上方的点得分小于零。因此,直线下方预测为正面,直线上方预测为负面。在这个简单例子中,我们得到了一条非常简单的直线。
为了演示这个模块的内容,我创建了一个简单的数据集,如左下角所示,其中包含正面和负面的例子。我将为其拟合一系列不同的逻辑回归分类器,以实际观察过拟合是如何发生的。
拟合线性特征分类器
首先,我将拟合一个使用线性特征的简单分类器。特征包括常数项 w0、x1 的系数 w1 和 x2 的系数 w2。
如果我在这个数据上学习逻辑回归分类器,会得到以下结果:
- 常数项为
0.23。 x1的系数为1.12。x2的系数为-1.07。
在右侧,我展示了这个分类器得到的决策边界,即这条直线。它对应于以下公式等于零的点:
0.23 + 1.12 * x1 - 1.07 * x2 = 0
这是我们观察到的分界线:直线下方的点,其得分 score(x) 大于 0;直线上方的点,其得分 score(x) 小于 0。因此,直线上方的点我预测为负面,直线下方的点我预测为正面。
在这个仅使用简单线性分类器的数据集中,我们看到了一些有趣的现象。它在分离正负样本方面做得相当不错,但在训练数据中仍有几个点被错误分类:这个加号在这里,这个减号在这里。问题是,我能做得更好吗?我能否使用更复杂的特征来拟合一个在数据集上表现更好的模型?
尝试二次特征
为了拟合一个更好的模型,我现在将尝试所谓的二次特征。我不仅考虑 x1 和 x2,还将考虑 x1 的平方和 x2 的平方。
请注意,这不是一般的二次特征,我没有考虑 x1 乘以 x2 这样的交叉项,因为那样会使模型很快变得非常庞大。所以我只使用这种简单的二次特征。
如果我在相同的数据上学习分类器,会得到一个非常酷的决策边界。当将其投影到二维空间时,决策边界变成了这种弯曲的抛物线形状。
在这种情况下,系数如下:
- 常数项为
1.68。 x1的系数为1.39。x2的系数为-0.59。x1的平方项系数为-0.17。x2的平方项系数为-0.96。
请注意,这些数字与上一张幻灯片中的不同,因为参数是与二次项同时更新的。
使用这些二次项,我得到了这边这个漂亮的二次决策边界。它基本上表示以下公式等于零:
1.68 + 1.39 * x1 - 0.59 * x2 - 0.17 * x1^2 - 0.96 * x2^2 = 0
现在,抛物线左侧的点是那些得分 score(x) 小于 0 的点,而右侧的点是那些得分 score(x) 大于 0 的点。你得到了这条漂亮的曲线,是的,你仍然会犯几个错误,但我告诉你这些错误在我看来是可以接受的。我对数据的拟合相当好,你永远不应该期望在真实数据集上做到完全正确。事实上,正如我们将在本模块后面看到的,做到完全正确对你来说可能是一个巨大的警告信号。但我得到了相当好的拟合,而且看起来很漂亮。
顺便注意一下,我在这里学到的系数相当不错,它们看起来是自然的量级,大约在 1、0.5 左右。
更高阶多项式的影响
现在让我们看看当你使用更高阶多项式时会发生什么。

总结
本节课中我们一起学习了分类中的过拟合。我们通过一个具体例子,观察了从简单线性分类器到包含二次特征、乃至更高阶多项式特征的分类器的变化过程。我们发现,随着模型复杂度增加,决策边界可以更好地拟合训练数据,但我们也注意到,追求在训练集上“完美”分类可能是一个过拟合的警告信号。理解过拟合的表现形式,是构建泛化能力强的模型的第一步。
机器学习(分类,聚类和检索):第3-4课:通过高阶多项式特征可视化过拟合

在本节课中,我们将要学习过拟合在分类问题中的表现。我们将通过一个具体的例子,观察当使用不同阶数的多项式特征来拟合逻辑回归分类器时,模型在训练数据上的表现及其决策边界的变化,从而直观地理解过拟合现象。
上一节我们介绍了逻辑回归的基本概念,本节中我们来看看当特征变得非常复杂时会发生什么。
使用6阶多项式特征
接下来,我们看看如果使用6阶多项式特征在相同数据集上拟合逻辑回归分类器会发生什么。
现在,我们的特征最高达到 x2^6 和 x1^6。这意味着特征数量大大增加,需要从数据中学习的系数也更多。如果我将这个数据集输入逻辑回归分类器,会得到以下决策边界。

它在训练数据上拟合得极好。如果仔细观察,它实际上达到了零训练误差。顺便提一下,正如我们之前提到的,这应该是一个警告信号。观察其决策边界,它极其复杂。
有些人可能会用一个技术术语来形容它:疯狂。这个决策边界非常复杂。
因此,尽管它的训练误差为零,但决策边界存在一些奇怪的伪影。例如,我在这里高亮显示空间中的一个区域:即使该区域周围的所有点都被预测为正类,但在那个圆圈的正中间,模型认为分数应该小于零。
对于那个区域,模型预测 y_hat 应该是 -1。
这对我来说毫无意义,因为其周围的每个点都是正类(+1),为什么我会期望中间的点是负类(-1)?数据完全不支持这一点。
事实上,如果你观察系数的幅度,它们开始变得非常大。而自然的抛物线模型的系数大约在 1 和 -0.5 左右,现在我们得到的系数数量级达到了 42 或更高,比之前的系数大了 10 到 40 倍。
正如我们在回归课程中讨论过的,这就是过拟合的早期预警信号。


使用20阶多项式特征
现在,让我们更进一步,拟合一个使用20阶多项式特征的逻辑回归模型。
这意味着特征最高达到 x1^20 和 x2^20。这是非常非常高阶的多项式。观察我们学到的决策边界。


我的意思是,这可以说是真正的疯狂。它真的非常复杂。它正确分类了所有数据,但极不平滑。观察学习到的权重,系数数量级达到了 3000、4000、-2000。它们比我们之前学到的简单抛物线模型的系数要大得多。
它虽然正确分类了所有训练数据,但明显是过拟合了,并且输出了非常大的估计多项式系数。
因此,当我们试图避免过拟合时,需要非常仔细地关注系数的大小。
分类中的过拟合概念
分类中的过拟合概念与回归中的非常相似,区别在于现在的误差是用分类错误来衡量的。
我们可能在这里学到一组参数 W_hat,它在训练数据上表现得似乎非常好(甚至可能产生疯狂的边界),但同时存在另一组参数 W_star,另一组系数 W_star,在真实误差方面会表现得更好。
问题在于,我们如何推动学习过程更接近 W_star 而不是 W_hat?我们将通过推动参数不那么巨大、不那么庞大来实现这一点,就像我们在回归中使用正则化所做的那样,推动参数趋向于零。

总结

本节课中我们一起学习了过拟合在分类问题中的可视化表现。我们观察到,随着多项式特征阶数的增加(从6阶到20阶),逻辑回归模型虽然能在训练集上达到零错误率,但其决策边界变得异常复杂且不合理,同时模型系数(权重)的幅度急剧增大。这明确地指示了过拟合的发生。与回归问题类似,控制模型复杂度(例如通过正则化限制系数大小)是避免分类模型过拟合的关键。下一节我们将探讨用于解决这一问题的具体正则化技术。
机器学习(分类,聚类和检索):3-4:分类器过拟合与过度自信预测 🔍

在本节课中,我们将探讨分类任务中的过拟合现象,特别是逻辑回归模型如何因过拟合而产生过度自信的概率预测。我们将通过公式和示例,理解系数增大如何导致预测概率趋近于0或1,并观察这一现象在实际数据中的表现。
分类中的过拟合概念

上一节我们介绍了回归中的过拟合,本节中我们来看看分类任务中的过拟合有何不同。在分类中,过拟合的概念可能比回归中更为复杂,因为我们不仅预测特定值(如房屋价格)或类别(如评论是正面或负面),还经常回答概率性问题,例如“这条评论是正面的概率是多少?”。
因此,我们需要理解过拟合在概率估计方面的含义。
模型与过拟合机制
以下是逻辑回归模型的核心公式:
概率估计公式:
P(y = +1 | x, w) = σ(w^T h)
其中,σ 是Sigmoid函数,w^T h 是得分函数,取值范围为负无穷到正无穷。
回忆之前模块的内容,过拟合时,系数 w 会变得越来越大。这意味着得分 w^T h 会变得极大(正或负),从而将Sigmoid函数的输出推向 exactly 1 或 exactly 0。
因此,分类中的过拟合,特别是逻辑回归,可能产生破坏性效果。巨大的系数会将得分推向极端值,导致预测概率趋近于1或0。我们不仅是在过拟合,而且对自己的预测变得过度自信,即使本应对结果持有更多不确定性。
简单示例演示
让我们回到之前使用的简单示例,使用两个特征(“awesome”和“awful”的数量)来拟合分类器。
假设初始系数为:awesome: +1, awful: -1。输入一条评论,包含2个“awesome”和1个“awful”。
计算过程:
得分 w^T h = (1*2) + (-1*1) = 1
预测正面评论概率 P = σ(1) ≈ 0.73
这个结果可以接受:评论有两点好评,一点差评,正面概率略高于一半,但并非极度确定。
现在,保持输入不变,将系数放大一倍:awesome: +2, awful: -2。
计算过程:
得分 w^T h = (2*2) + (-2*1) = 2
预测概率 P = σ(2) ≈ 0.88
此时,我们对同一条评论是正面的信心大幅提升至88%。
进一步放大系数:awesome: +6, awful: -6。
计算过程:
得分 w^T h = (6*2) + (-6*1) = 6
预测概率 P = σ(6) ≈ 0.997
概率高达99.7%,这显然不合理。对于一条仅有2个好评和1个差评的评论,如此高的置信度没有意义。
可以看到,决策边界(得分=0)并未改变,但随着系数增大,Sigmoid曲线变得越来越陡峭,预测概率越来越趋近于1(或0)。这是逻辑回归中观察到的一种过拟合现象:不仅决策边界可能变得扭曲,估计的概率也会变得极端。
数据集中的现象
以下是在实际数据集中观察到的同类效果图示。


图中展示了随着模型复杂度增加或正则化不足,分类器对训练数据做出过度自信预测的情况。
本节总结


本节课中我们一起学习了分类任务中过拟合如何导致过度自信的概率预测。我们了解到,在逻辑回归模型中,过拟合会使系数 w 变得过大,从而将得分 w^T h 推向极端值。这导致Sigmoid函数输出趋近于0或1,使得模型对预测结果表现出不合理的、极高的置信度。通过简单示例,我们直观地看到了系数增大如何使预测概率从合理值(如0.73)飙升到近乎绝对确定的值(如0.997)。认识到这一点对于理解模型校准、评估模型可靠性以及后续学习正则化技术至关重要。
机器学习(分类,聚类和检索):第3-4课:可视化过于自信的预测

在本节课中,我们将学习如何通过可视化分类器预测的概率来理解模型的行为,特别是识别模型何时变得“过于自信”。我们将看到,一个复杂的模型可能在决策边界上表现得很奇怪,并且对其预测表现出不合理的、极高的置信度,这是过拟合的另一个信号。
可视化概率图
上一节我们介绍了不同复杂度模型的决策边界。本节中,我们来看看模型预测的概率分布图,这能提供比单纯决策边界更丰富的信息。
下图展示的数据集和模型与之前幻灯片中的相同。右侧绘制的不仅是决策边界,更是模型预测 y_hat 等于 +1(即正类)的概率图。

- 在左侧区域,概率
P(y_hat = +1)近似为 0。这意味着模型几乎肯定位于该区域(例如坐标(-5, 4)附近)的点是负类。 - 在右下角区域,概率
P(y_hat = +1)近似为 1。这意味着模型几乎肯定该区域的点是正类。 - 中间那片白色区域,是概率
P(y_hat = +1)近似为 0.5 的区域。在这个区域,模型对于样本是正类还是负类非常不确定。
这个不确定性区域相当宽。尽管这个一阶多项式(线性)分类器对数据的拟合并不完美,但其不确定性度量看起来是合理的。那些被错误分类的点,实际上也落在了模型不确定的区域里,这使得这个分类器的行为显得相当合理。
二阶多项式拟合
现在,让我们观察使用二阶多项式(二次)特征学习的分类器的概率图。正如之前所见,我们相信这个二次拟合对数据的拟合效果更好。
以下是使用二阶多项式特征时,模型预测 y_hat 等于 +1 的概率图。

可以看到,不确定性区域变窄了。这非常合理:因为模型对数据的拟合更好,所以它不确定的点就更少。事实上,那些仍然存在不确定性的地方,恰恰是位于决策边界附近、本就应该难以判断的区域。这个模型不仅在决策边界上拟合得很好,其输出的概率也很有意义:概率接近0.5的区域,正是模型真正不确定的地方;而概率从0.5向0或1平滑过渡的过程,也符合我们的直觉。
高阶多项式与过于自信的预测

接下来,我们看看使用更高阶特征时会发生什么。例如,使用六阶或二十阶多项式特征。我们之前看到,这些模型的决策边界变得非常扭曲和奇怪。
现在,如果我们观察它们的不确定性区域,会发现这些区域变得极其狭窄。你需要仔细看才能发现图中那些细小的白色条带。

根据这个复杂模型,不仅决策边界是一条奇怪的曲线,而且模型对其预测表示“不确定”的地方,只剩下这些极其细微的条带。这是非常微小的不确定性区域。
这种现象就是过拟合,并伴随着过于自信的预测。可以这样理解:模型确信自己是对的,但实际上它肯定是错的。我们错得离谱,却自信满满,这非常糟糕。
因此,不确定性是分类器中一个非常重要的概念。通过观察不确定性,我们获得了理解过拟合的另一个视角:在分类问题中,过拟合的另一种表现就是产生了这种极其狭窄的不确定性区域。我们的目标就是想尽一切办法来避免这种情况。
总结

本节课中,我们一起学习了如何通过可视化分类器预测的概率来深入理解模型行为。我们对比了不同复杂度模型(线性、二次、高阶多项式)的概率图,发现一个好的模型会给出合理的不确定性区域,而一个过拟合的复杂模型则会表现出“过于自信”的预测,即其不确定性区域变得异常狭窄。这为我们诊断和避免过拟合提供了又一个有力的工具。
机器学习(分类,聚类和检索):3-4:可选:Logistic回归过拟合的另一个视角 🔍

在本节中,我们将深入探讨Logistic回归中过拟合现象发生的另一个原因。我们将引入“线性可分”的概念,并解释为何在数据线性可分时,模型参数会变得极大,从而导致严重的过拟合问题。

线性可分性 📈
上一节我们介绍了过拟合的一般概念,本节中我们来看看一个导致Logistic回归过拟合的特殊情况:线性可分数据。
线性可分数据直观上很好理解。它意味着存在一条直线(或在更高维度中是一个超平面),能够完美地将正例和负例分开。具体来说,对于所有正例样本,其得分 score(x) = ŵᵀh(x) 大于0;而对于所有负例样本,其得分小于0。
这意味着模型在训练集上的误差恰好为零。这是一个重要的警示信号:当训练误差精确为零时,你可能正面临过拟合的风险,尤其是在模型非常复杂的情况下。
在二维空间中,线性可分表现为一条直线。在更高维度(例如10维或1000维)的特征空间中,它则对应一个分离超平面。需要特别注意的是,当你不断添加高阶多项式等复杂特征时,数据往往会变得线性可分,从而更容易陷入训练误差为零的过拟合陷阱。
线性可分为何导致问题?⚠️
为了理解线性可分为何会导致过拟合,让我们看一个具体的例子。
假设存在一个决策边界:1.0 * (#awesome) - 1.5 * (#awful) = 0,它能完美分离正负样本。现在,考虑将这个方程两边同时乘以10,得到 10 * (#awesome) - 15 * (#awful) = 0。这个新的边界依然能完美分离数据。事实上,即使乘以10亿,边界 1,000,000,000 * (#awesome) - 1,500,000,000 * (#awful) = 0 也同样有效。
这说明,存在无数组系数(无论大小)都能定义同一个分离超平面。那么,模型为何会倾向于选择极大的系数呢?答案在于最大似然估计的目标。
最大似然估计的“偏好” 🎯
要理解系数为何会变大,我们需要回顾数据概率的估计过程。考虑一个靠近边界的样本点,例如包含2个“awesome”和1个“awful”的评论。
以下是不同系数下,模型预测该样本为正例的概率:
-
使用系数 [1.0, -1.5]:
- 概率公式为:
P = 1 / (1 + exp(-(2*1.0 + 1*(-1.5)))) - 计算得
P ≈ 0.62。这个预测是合理的,因为样本靠近边界,模型给出了62%的置信度。
- 概率公式为:
-
使用系数 [10, -15]:
- 概率公式为:
P = 1 / (1 + exp(-(2*10 + 1*(-15)))) - 计算得
P ≈ 0.99。此时,尽管样本位置未变,模型却以99%的置信度认为它是正例。
- 概率公式为:
-
使用系数 [10⁹, -1.5*10⁹]:
- 概率公式为:
P = 1 / (1 + exp(-(2*10⁹ + 1*(-1.5*10⁹)))) - 计算得
P ≈ 1.0。系数极大时,模型会以近乎100%的绝对置信度做出预测。
- 概率公式为:
最大似然估计的目标是最大化所有训练样本预测概率的连乘(似然函数)。它会偏好那些对训练数据预测“更确定”的模型。在线性可分的情况下,模型可以通过不断增大系数,使所有训练样本(即使是边界附近的点)的预测概率无限趋近于1或0,从而不断提高训练数据的似然值。理论上,系数会被推向无穷大。


本节总结 📝
本节课中我们一起学习了Logistic回归过拟合的另一个关键视角。
- 我们引入了线性可分的概念,即存在一个超平面能完美分离所有训练样本,导致训练误差为零。
- 我们解释了在线性可分情况下,模型系数有无数种可能的选择,都能实现完美分离。
- 由于最大似然估计倾向于选择预测置信度更高的模型,它会驱动系数不断增大,以逼近训练样本的极端概率(1或0)。
- 这导致了Logistic回归中一种“双重”过拟合问题:既可能学习到复杂、曲折的决策边界,也可能在数据线性可分时产生巨大甚至趋于无穷的模型系数,并伴随着不切实际的高置信度预测。

因此,当你在Logistic回归中观察到训练精度达到100%或系数值异常巨大时,这很可能是一个强烈的过拟合信号,需要采取正则化等应对措施。
机器学习(分类,聚类和检索):第3-4课:惩罚大系数以缓解过拟合

在本节课中,我们将学习如何通过引入正则化技术来缓解逻辑回归中的过拟合问题。我们将探讨如何通过惩罚过大的模型系数,来获得更合理、更泛化的分类结果。

上一节我们介绍了逻辑回归模型及其过拟合问题。本节中,我们来看看如何通过正则化来改进模型。
我们已经看到,过拟合对分类模型,特别是逻辑回归模型,可能产生不良影响。过大的模型参数是导致过拟合的一个关键因素。接下来,我们将引入正则化方法,就像在线性回归中所做的那样,通过惩罚过大的参数来获得更合理的结果。
我们讨论的仍然是同一个逻辑回归模型:我们获取数据,进行特征提取,然后拟合模型 1 / (1 + e^(-w^T x))。但是,机器学习算法的质量评估标准将发生改变,以引导我们远离过大的系数。具体来说,我们将平衡模型对数据的拟合程度与系数的大小,从而避免在逻辑回归中出现过大的系数。
为了衡量总体质量,我们需要平衡两件事:
- 拟合程度的度量,即数据似然,我们希望它越大越好。
- 系数的大小,过大的系数是有问题的。
因此,我们有一项希望最大化(数据似然),另一项希望最小化(系数大小)。我们将优化一个结合了质量与复杂度的度量。
那么这两项具体指什么呢?让我们在逻辑回归的背景下更清晰地定义它们。
逻辑回归中的质量度量是数据似然,我们在之前的模块中已经详细讨论过。这里有一个小提示:我们通常不直接优化数据似然,而是优化其对数,因为这会使数学计算更简单,梯度行为更稳定。我们在上一个模块的可选部分详细讨论过这一点。如果你跳过了那部分,只需将对数视为一种使数值不那么极端的方法。
因此,质量度量将是数据似然的对数,我们希望使其尽可能大。
我们已经知道,似然是我们优化时要使其变大的目标。但同时,我们也希望使某些东西变小,即系数的大小。
与在线性回归中一样,衡量系数大小有不同的度量标准。在本模块中,我们将使用两种:
- 平方和,也称为 L2 范数 的平方。我们将其记为 ||w||₂²。其公式非常简单:
w₀² + w₁² + w₂² + ... + w_d²。 - 绝对值之和,也称为 L1 范数。我们将其记为 ||w||₁。其公式是:
|w₀| + |w₁| + |w₂| + ... + |w_d|。
在线性回归课程中,我们深入探讨了这些概念。我们采用平方或绝对值的主要原因是,我们希望以相同的方式惩罚高度正数和高度负数。通过平方或取绝对值,我们确保这里的输出是正数,并且我们希望这些范数尽可能低。
这两种方法都将惩罚大的系数。然而,正如我们在回归课程中看到的,使用 L1 范数 还会带来一种称为稀疏解的特性。稀疏性不仅在回归中起作用,在分类中也同样重要。在本模块中,我们将初步探讨这两种概念,并从 L2 范数(平方和)开始。
现在我们已经回顾了这些概念,可以正式定义我们的优化问题了。
我们希望最大化一个权衡了以下两方面的目标函数:我的数据似然的对数,以及针对系数大小的某种惩罚项。我们将从 L2 惩罚项 的概念开始。
因此,优化问题可以形式化为:在参数 w 的选择上,最大化以下表达式:
log(数据似然) - λ * ||w||₂²
其中,λ 是一个控制惩罚强度的超参数。

本节课中,我们一起学习了如何通过引入 L2 正则化 来缓解逻辑回归中的过拟合问题。我们定义了需要权衡的两个目标:最大化数据似然的对数以拟合数据,同时最小化模型系数的 L2 范数以控制模型复杂度。通过将这两个目标结合到一个优化问题中,我们可以得到系数更小、泛化能力更强的分类模型。
机器学习(分类,聚类和检索):第3-4课:L2正则化Logistic回归

在本节课中,我们将要学习如何通过L2正则化来改进Logistic回归模型,以防止过拟合,并找到模型复杂度和数据拟合之间的平衡点。
平衡数据拟合与参数大小
上一节我们介绍了Logistic回归模型可能面临的过拟合问题。本节中,我们来看看如何通过引入一个惩罚项来约束模型参数的大小,从而在拟合数据和保持模型简单性之间取得平衡。
我们有两个需要平衡的目标:最大化数据的似然度,以及最小化模型参数的大小。这通过一个参数来控制,该参数决定了我们更侧重于拟合数据,还是更侧重于让参数值保持较小。
这个参数我们称之为 λ(lambda),也称为调优参数或正则化常数。
探索λ的不同取值
以下是λ取不同值时的情况:
- 当 λ = 0 时:优化问题简化为仅最大化似然度。这等同于标准的最大似然估计(MLE) 解。这通常不是一个好主意,因为它无法防止任何过拟合问题。
- 当 λ → ∞ 时:优化问题变为最小化无穷大乘以参数范数。似然度项被完全淹没,我们只关心惩罚参数。这将导致将所有参数 w 设置为0。这同样不是一个好主意,因为它完全忽略了数据,没有进行任何有意义的拟合。
- 当 0 < λ < ∞ 时:这是我们关心的区间。在这个区间内,λ在数据拟合和参数大小之间取得平衡。我们的目标是找到一个合适的λ值,使模型既能很好地拟合数据,又不会过于复杂。
模型名称与λ的选择
这个结合了L2惩罚项来拟合数据的过程,被称为 L2正则化Logistic回归。
那么,如何选择λ呢?其原则与回归课程中介绍的方法完全相同:
- 切勿使用测试数据来选择λ。
- 如果数据量充足,可以使用验证集。
- 如果数据集较小,可以使用交叉验证。
理解偏差-方差权衡
λ可以被视为一个控制模型偏差和方差权衡的参数:
- 当λ非常大时:参数 w 趋向于0,模型忽略数据,导致高偏差。但无论数据如何变化,模型输出都相似,因此方差很低。
- 当λ非常小时:模型能很好地拟合训练数据,因此偏差很低。但数据稍有变动,就可能得到完全不同的决策边界,因此方差很高。
本质上,λ控制着正则化设置下的偏差-方差权衡,这在Logistic回归(或分类)中的作用,与在线性回归中完全一致。

本节课中我们一起学习了L2正则化Logistic回归的核心思想。我们了解到,通过引入一个正则化参数λ,并在目标函数中添加参数的L2范数作为惩罚项,我们可以在模型复杂度和对训练数据的拟合程度之间进行权衡。选择合适的λ值(通过验证集或交叉验证)有助于我们找到偏差和方差之间的最佳平衡点,从而构建出泛化能力更强的分类模型。
机器学习(分类,聚类和检索):第3-4课:可视化L2正则化在逻辑回归中的效果


在本节课中,我们将学习L2正则化如何影响逻辑回归模型。我们将通过一个简单的数据集,观察随着正则化强度的变化,模型的决策边界和系数会发生怎样的改变。这有助于我们理解正则化如何防止过拟合,并提升模型的泛化能力。
观察正则化对决策边界的影响
上一节我们介绍了正则化的基本概念。本节中,我们来看看在一个具体的数据集上,引入正则化惩罚项后,决策边界会发生什么变化。
我们将使用一个包含20次多项式特征的数据集。在不使用正则化(λ=0)的情况下,拟合一个逻辑回归模型会得到一个非常复杂、不规则的决策边界,这通常被称为“疯狂”的决策边界。此时模型的参数值非常大,范围从-3170到3803。
现在,我们保持所有设置不变(相同的特征、相同的数据),只改变正则化参数λ的值,并观察结果。
以下是不同λ值下的结果对比:
- 当 λ = 0 时,我们得到非常大的系数和那个“疯狂”的决策边界。
- 当 λ 较大(例如 λ = 10)时,我们得到较小的系数和一个更平滑、更自然的决策边界。
事实上,相比λ=0的模型,我们更信任λ=10的模型所得到的决策边界。这个边界看起来很像之前用抛物线特征得到的漂亮边界,它很好地拟合了数据。尽管这里我们使用了大量(20次)多项式特征,但一点点的正则化帮助我得到了一个可信的、漂亮的分离平面。
观察正则化对系数的影响
我们也可以观察系数路径,即随着惩罚项λ的增加,我们的系数会发生什么变化。
在开始时(λ=0,无正则化),系数往往很大。但随着λ的增加,它们会变得越来越小,最终趋近于零。
我使用了一个产品评论数据集,挑选了几个词,并用不同强度的正则化拟合了一个逻辑回归模型。
以下是关于系数的观察:
- 具有正系数的词往往与评论的积极方面相关。
- 具有负系数的词往往与评论的消极方面相关。
- 初始时(λ很小),这些词的系数都相当大,除了那些与情感无关的词(如“this”、“review”),它们的系数接近零。
- 随着正则化强度λ的增加,所有系数都变得越来越小。如果继续增加λ,它们最终都会变为零。
通过交叉验证选择最佳λ
如果我使用交叉验证来选择最佳的λ,会得到一个大约在某个位置的结果,我们称之为 λ*。
这就是实际操作:使用交叉验证找到那个既能很好拟合数据,又不会过度拟合的平衡点。
正则化解决过拟合的核心问题
最后,我想展示正则化一个非常激动人心且优美的特性。逻辑回归的正则化不仅能解决“疯狂”的决策边界问题,还能解决我们之前看到的因过拟合导致的“过度自信”预测问题。
我绘制了底部图像,展示了在不同λ下学到的实际决策边界以及模型对数据的不确定性估计。
以下是两种情况的对比:
- 如果 λ = 0,我们会得到这种高度“过度自信”的预测,模型对几乎所有点的预测概率都接近1或0。
- 如果 λ = 1,我不仅得到了一个更自然(类似抛物线)的边界(尽管使用了20次多项式特征),还得到了一个非常自然的不确定性区域。模型不确定是正类还是负类的区域,正好是那些位于正类数据簇和负类数据簇之间的边界点,你会看到这种平滑的过渡。
因此,通过引入正则化,我们解决了逻辑回归中过拟合带来的两个根本问题:不合理的复杂决策边界和过度自信的概率估计。
总结

本节课中,我们一起学习了L2正则化在逻辑回归中的可视化效果。我们看到,随着正则化强度λ的增加:
- 模型的系数会缩小,极端的大系数得到抑制。
- 决策边界从复杂、不规则变得平滑、自然。
- 模型输出的概率估计从“过度自信”变得合理,在类别边界附近能够体现不确定性。
- 通过交叉验证,我们可以找到一个最佳的λ*,在拟合能力和泛化能力之间取得平衡。正则化是控制模型复杂度、防止过拟合的强大工具。
机器学习(分类,聚类和检索):第3-4课:使用梯度上升法学习L2正则化Logistic回归

在本节课中,我们将要学习如何使用梯度上升算法来训练带有L2正则化的Logistic回归模型。我们将看到,只需对标准Logistic回归的学习代码进行微小的修改,就能有效缓解过拟合问题,获得更优的模型参数。
概述

我们已经了解了正则化如何在Logistic回归中发挥作用,帮助我们找到对数据更好的拟合以及更准确的概率估计。现在,让我们最终探讨如何从数据中学习这些系数。我们将使用梯度上升法,并且这仅仅是在学习标准Logistic回归系数的基础上进行一个非常微小的改动。通过这一点点代码变更,我们就能解决之前遇到的所有过拟合问题。
学习算法设置
与之前相同,我们拥有训练数据特征和相同的模型。但现在,我们的质量度量标准是L2正则化的Logistic回归对数似然。我们将讨论如何通过学习算法来优化它,从而得到最优参数 W_hat。
我们将使用之前用过的同类型梯度上升算法:从某个起点开始,沿着梯度方向以小步长(学习率)前进,直到达到解 W_hat。更新公式依然是:W_{t+1} = W_t + η * 梯度。
因此,我们现在需要问自己的唯一问题是:在添加了这个额外的正则化项之后,梯度等于什么?我们需要计算正则化对数似然的梯度。

计算正则化对数似然的梯度

我们已知总的质量函数是数据对数似然(衡量拟合度)与正则化惩罚项(L2范数的平方)的加权和:
总质量 = 对数似然(数据) - λ * (L2范数)^2
我们需要的是这个总质量函数关于参数 W 的导数,以便沿着梯度方向“爬山”。
总和的导数等于各项导数的和。因此,总导数是:
- 对数似然的导数(幸运的是,我们在上一个模块中已经推导过)。
- 减去 λ 乘以二次惩罚项的导数。

可以看到,这仅仅是在你原有代码上的一个小改动:我们只需要在计算梯度时加上 λ 乘以二次惩罚项的导数这一项。

回顾与分解梯度
首先,回顾一下对数似然的导数。它是所有数据点上的求和:
对数似然的导数 = Σ_{数据点} [ (y_i - P(y_i=1|x_i, W)) * x_{ij} ]
其中,y_i 是真实标签(1或0),P(y_i=1|x_i, W) 是模型预测的正类概率,x_{ij} 是第 j 个特征的值。我们在上一个模块中已经详细解释过这一项,因此这里不再赘述,我们将重点放在第二部分:L2惩罚项的导数。
换句话说,我们需要求某个参数 W_j 对于惩罚项 W_0^2 + W_1^2 + ... + W_j^2 + ... + W_D^2 的偏导数。
观察所有这些平方项,只有包含 W_j 的项 W_j^2 在求偏导时起作用。W_j^2 关于 W_j 的导数就是 2 * W_j。
这就是我们代码中唯一需要改变的部分:2 * W_j。
因此,我们总的导数(梯度)将是过去实现的导数(对数似然导数)减去 2 * λ * W_j:
总梯度 = 对数似然导数 - 2λW_j
理解正则化项的作用
现在,让我们解释一下这个额外的项 -2λW_j 对我们的梯度有什么影响。
-
如果 W_j 是正数:
- -2λW_j 是一个负数,它对梯度产生负贡献。
- 这意味着在更新时,我们会减小 W_j 的值(因为我们在正数上加了一个负数)。
- 结果就是,W_j 变得更接近0。
- 如果 λ 更大,这个减小的幅度就更大,W_j 趋向0的速度更快。
- 如果 W_j 本身非常大,这个减量也相应更大,同样会更快地趋向0。
-
如果 W_j 是负数:
- -2λW_j 将是一个正数(因为负负得正)。
- 这意味着在更新时,我们会增加 W_j 的值(在负数上加一个正数)。
- 结果同样是,W_j 变得更接近0。
这非常直观:正则化会将正系数减小一点,将负系数增大一点,从而试图将所有系数向零推动。这正是我们期望正则化在梯度上产生的效果。
算法实现代码
以下是我们在上一个模块中描述的学习Logistic回归模型系数的代码框架。
你从一些初始化的 W 开始(例如全零、随机初始化或手动设置),然后进行多次迭代。在每次迭代中,你逐个系数地更新:
- 计算偏导数 partial_j,即上面提到的长公式:对所有数据点求和
(特征值 * (真实标签 - 预测概率))。 - 执行相同的更新:W_j_{t+1} = W_j_t + 步长 * partial_j。
而你需要在代码中做出的唯一改变就在这里。换句话说,在你计算导数(partial_j)的任何地方,插入减去 2λW_j 这一项。
现在,你就拥有了一个L2正则化Logistic回归的求解器。这将在实践中对你产生巨大的帮助。
总结

本节课中,我们一起学习了如何通过梯度上升法训练L2正则化的Logistic回归模型。核心在于理解总目标函数(正则化对数似然)的梯度由两部分组成:原始对数似然的梯度和正则化惩罚项的梯度。正则化项的导数非常简单,就是 2λW_j。将这个项加入到梯度更新公式中,就能在优化过程中自动将系数向零收缩,从而有效控制模型复杂度,防止过拟合。最终,我们只需在标准Logistic回归的梯度计算代码中添加一行 - 2 * lambda * W_j,即可实现这一强大的正则化效果。
机器学习(分类,聚类和检索):第3-4课:L1正则化的稀疏Logistic回归

在本节课中,我们将要学习L1正则化的Logistic回归。我们将探讨它如何通过引入稀疏性来改进模型,并比较其与L2正则化的效果差异。

概述
之前我们讨论了L2正则化的Logistic回归,并简要提及了L1正则化Logistic回归。本节我们将更详细地探讨L1正则化,特别是它如何产生稀疏模型,以及这种稀疏性对模型效率和可解释性的影响。
稀疏性的概念
首先,我们来回顾稀疏性的概念。一个稀疏模型意味着其许多权重系数 Wj 等于零。这有助于提升模型的效率和可解释性。
例如,假设我们拥有大量数据和特征,权重系数 W 的数量可能达到1000亿。这在许多实际场景中都会出现,例如某些垃圾邮件过滤器就学习了数百亿个参数。
这带来了两个问题:
- 进行预测的成本可能很高,因为需要遍历1000亿个值。
- 然而,如果我能得到一个稀疏解,即许多
Wj实际上等于0,那么在预测时,我只需要关注非零系数Wj。其他所有系数都可以忽略。如果1000亿个系数中只有10万个是非零的,那么进行预测的速度将快得多,这在实践中差异巨大。
稀疏性的另一个影响是,它可以帮助你解释那些非零系数。你可以观察少量非零系数,并尝试理解预测是如何做出的。这种解释在实践中非常有用。
L1正则化Logistic回归
那么,如何学习一个具有稀疏性的Logistic回归分类器呢?答案是使用L1正则化惩罚项。
我们采用相同的对数似然函数 l(W),但额外添加一个L1惩罚项,即所有权重系数绝对值的和:|W0| + |W1| + ... + |WD|。
通过将平方和(L2)改为绝对值之和(L1),我们就得到了所谓的L1正则化Logistic回归,它能产生稀疏解。这是一个微小的改动,却能带来稀疏解。
与L2正则化类似,这里我们也有一个参数 λ,用于控制引入的正则化强度,即惩罚的力度。目标函数变为数据的对数似然减去 λ 乘以这个L1惩罚项。
- 当
λ = 0时,没有正则化,我们得到标准的极大似然解。 - 当
λ = ∞时,只有惩罚项,这将导致所有权重系数W都为0。 - 我们真正关心的是
λ介于0和无穷大之间的情况,这会产生稀疏解,其中一些Wj不为零,但希望许多其他Wj恰好为零。
系数路径对比
现在,让我们重新审视系数路径。下图展示了使用L2惩罚时的系数路径。可以看到,当 λ 参数较小时,学习到的系数较大;当 λ 参数增大时,系数变小。它们从大变小,但永远不会恰好等于零。
然而,如果你观察使用L1正则化时的系数路径,会得到更有趣的结果。例如,开始时,“笑脸”符号的系数是一个较大的正值,但最终会恰好变为0。同样,“皱眉脸”符号的系数是一个较大的负值,但最终也会变为0。你可以看到许多其他词的系数也遵循这个规律。
(注:此处课程中提到的例子是基于产品评论的情感分析,试图判断评论是正面还是负面。)
一个快速的提醒:我们可以观察哪个系数在最长的时间内保持非零。在上图中,有一条线从未触及零或保持为零,这就是单词“disappointed”(失望)的系数。你可能会失望地发现,“皱眉脸”符号并不是那个保持最久的系数。开始时,它的系数并不像“皱眉脸”那么大,因此不那么显著,但它是保持负值时间最长的系数。所以,“皱眉脸”符号可能不是最重要的,“笑脸”符号也不如“disappointed”重要。这可能是因为“disappointed”在更多评论中出现,并且当你说“失望”时,通常意味着这是一条负面评论。
你可以看到这些转变:像“used”(使用过)这样的小数字系数很早就变为零;“笑脸”符号持续了一段时间,然后变为零;“皱眉脸”符号持续了更长时间,然后也恰好变为零。但对于足够大的 λ,除了“disappointed”的系数外,所有这些都变为零。
总结


本节课中,我们一起学习了L1正则化的Logistic回归。我们了解到,通过在目标函数中添加所有权重系数绝对值的和作为惩罚项,可以促使模型产生稀疏解,即许多系数恰好为零。这种稀疏性显著提高了模型预测的效率,并增强了模型的可解释性,使我们能够聚焦于少数关键特征。通过对比L1和L2正则化的系数路径,我们直观地看到了L1正则化在诱导稀疏性方面的独特优势。
机器学习(分类,聚类和检索):第3-4课:Logistic回归中过拟合和正则化的回顾
在本节课中,我们将回顾分类问题,特别是Logistic回归中的过拟合现象,并学习如何使用正则化技术来缓解这一问题。我们将探讨过拟合如何导致决策边界复杂化、参数值增大以及预测过度自信,并介绍L2和L1正则化的基本概念。

过拟合现象回顾
上一节我们介绍了分类模型的基本概念。本节中,我们来看看Logistic回归中的过拟合问题。
过拟合是指模型在训练数据上表现很好,但在新数据上泛化能力差的现象。在Logistic回归中,过拟合通常表现为决策边界变得异常复杂,参数值显著增大,并且模型对预测结果表现出过度自信。
以下是过拟合在Logistic回归中的几个主要表现:
- 决策边界变得非常复杂和扭曲,以“完美”拟合训练数据中的每个点,包括噪声。
- 模型参数(权重)的绝对值倾向于变得非常大。
- 模型输出的概率值会非常接近0或1,表现出对预测的过度自信。
正则化引入
为了解决过拟合问题,我们引入了正则化技术。正则化的核心思想是在优化目标(如损失函数)中添加一个惩罚项,以限制模型参数的大小,从而鼓励更简单、更平滑的模型。
在Logistic回归中,我们通常将原始的损失函数(如负对数似然损失)与一个正则化项相加,形成新的优化目标。
公式表示如下:
新的目标函数 = 原始损失函数 + λ * 正则化项
其中,λ 是一个超参数,用于控制正则化的强度。λ 值越大,对模型复杂度的惩罚越重。

L2正则化
我们首先详细探讨最常用的L2正则化。L2正则化也称为岭回归(Ridge Regression)或权重衰减,它在目标函数中添加了所有权重参数的平方和作为惩罚项。
L2正则化的目标函数公式为:
J(w) = 原始损失函数 + (λ/2) * ||w||²
这里的 ||w||² 表示权重向量 w 的L2范数的平方,即所有 w_j² 的和。添加这项惩罚后,优化过程会倾向于让权重值整体变小,但通常不会将任何权重精确地压缩到零。
使用L2正则化的Logistic回归模型能够有效防止参数值“爆炸式”增长,从而得到更平滑的决策边界和更好的泛化性能。你现在应该能够理解这个思想,并在实践中使用L2正则化来实现它。
L1正则化简介
除了L2正则化,L1正则化也是常用的技术。L1正则化在目标函数中添加的是权重参数的绝对值之和作为惩罚项。
L1正则化的目标函数公式为:
J(w) = 原始损失函数 + λ * ||w||₁
这里的 ||w||₁ 表示权重向量 w 的L1范数,即所有 |w_j| 的和。L1正则化倾向于产生稀疏的权重向量,即它会将一部分不重要的特征的权重直接压缩为零,从而实现特征选择的效果。
虽然我们在这里没有详细描述L1正则化的具体实现方法,但其思路与你之前在线性回归问题中接触过的Lasso回归是相似的。
总结
本节课中,我们一起学习了Logistic回归中的过拟合问题及其解决方案。我们回顾了过拟合如何导致复杂的决策边界和增大的参数值,并引入了正则化作为关键的缓解手段。我们重点介绍了L2正则化的原理与公式,它能有效控制参数大小,提升模型泛化能力。此外,我们也简要了解了L1正则化及其可能带来的特征选择优势。通过这些方法,我们可以将Logistic回归从理论层面推进到实际应用阶段,为处理现实世界的数据做好准备。
机器学习(分类,聚类和检索):第3-4课:使用决策树预测贷款违约 💳

在本节课中,我们将要学习一种新的分类器——决策树。我们将深入探讨其在金融领域,特别是贷款违约预测中的应用。决策树在实践中非常有用,尤其是在与后续模块中将要介绍的“提升”方法结合时。


概述
上一节我们深入探讨了线性分类器,即逻辑回归。本节中,我们来看看另一种分类器:决策树。决策树在实践中极其有用,尤其是在金融数据建模领域。我们将通过一个贷款申请评估的真实案例来学习它。
贷款申请评估问题
假设我想买一套房子,但资金不足,需要向银行申请贷款。银行会审查我的历史记录,例如信用状况、收入水平、贷款期限(如3年、5年、30年)以及其他个人信息(如年龄、婚姻状况)。银行将利用这些信息来预测贷款给我是否存在风险。
以下是贷款决策中通常考量的因素:
- 信用历史:审查过往贷款和信用卡的还款记录。
- 收入:评估当前的收入水平。
- 贷款期限:考虑偿还贷款的时间长度。
- 个人信息:如年龄、婚姻状况等。
基于这些信息,目标是预测贷款是否安全。


作为分类问题的贷款审批
我们可以将贷款审批过程视为一个分类问题。输入信息(来自申请表格的所有数据)记为 X。分类模型会处理这些信息并做出决策:预测结果 ŷ = +1 表示安全贷款,ŷ = -1 表示风险贷款。

决策树分类器简介

在本模块中,我们将使用决策树分类器。它的工作方式可能如下所示:
决策树从一个申请开始,首先检查输入的某个特定特征,例如“信用状况”。如果信用“优秀”,则直接批准贷款,无需查看其他信息。如果信用“一般”,则进一步查看“贷款期限”:短期贷款可能被视为风险较高,而长期贷款则可能被接受。如果信用“差”,则不会停止,而是继续查看“收入”水平:即使信用差,但如果收入很高,银行可能愿意提供长期贷款;但如果收入也不高,那么申请很可能被拒绝。
总结

本节课中我们一起学习了决策树分类器,并了解了它如何应用于预测贷款违约这一金融领域的实际问题。我们看到了决策树如何通过一系列基于特征(如信用、收入、期限)的规则性判断来做出分类决策。下一模块,我们将探讨如何通过“提升”技术来进一步增强决策树的性能。
机器学习(分类,聚类和检索):第3-4课:决策树的直观理解

在本节课中,我们将深入探讨决策树模型。我们将从直观理解开始,学习决策树如何根据输入特征进行预测,并明确我们的目标是学习一个能够对数据做出预测的树结构模型。
决策树的基本概念

上一节我们简要介绍了贷款申请领域的决策树示例。本节中,我们来看看决策树是如何运作的。
我们从一份贷款申请开始。我可以沿着决策树的某一条分支路径进行判断。例如,如果申请人的信用评级为“一般”,且贷款期限为短期(例如3年),那么这份申请将被视为高风险。
如果我选择另一条路径,例如查看一个信用评级为“差”,但收入“高”,且同样是短期贷款的申请人,我可能也会判定其为高风险申请。
通常,我们会得到一个输入 X,它包含了对每个输入特征的赋值。例如,信用=差,收入=高,期限=5年或更长的贷款。然后,我沿着树向下遍历相应的路径,以做出预测 ŷ。在这个例子中,模型预测这是一笔安全的贷款。
总而言之,我们面对的任务是:给定某个输入 Xᵢ,我将沿着该输入对应的特定分支遍历决策树,然后做出预测 ŷᵢ(例如,这笔贷款是安全的)。
因此,我们的目标是学习那棵能让我们对数据进行预测的树 T(x)。
决策树的构建与遍历
以下是决策树构建和预测过程的核心步骤:
- 从根节点开始:决策树从顶部(根节点)的一个问题或条件开始。
- 根据特征值选择分支:根据输入数据在该节点特征上的取值,选择向左或向右的分支。
- 递归遍历:重复步骤2,沿着树向下移动,直到到达一个叶节点。
- 在叶节点获得预测:叶节点不包含判断条件,而是直接提供一个预测结果(例如,“安全”或“风险”)。
用伪代码描述这一预测过程如下:
def predict(tree, input_x):
node = tree.root
while node is not leaf:
if input_x[node.feature] <= node.threshold:
node = node.left_child
else:
node = node.right_child
return node.prediction
学习决策树的目标
我们的核心目标是从数据中自动学习出决策树的结构。这意味着算法需要自行决定:
- 在每个节点上应该使用哪个特征进行划分。
- 该特征的划分阈值是多少。
- 何时停止划分并创建叶节点。
学习过程通常涉及衡量划分“好坏”的指标(如信息增益、基尼不纯度),并通过递归分割数据来构建树,直到满足停止条件(如达到最大深度、节点内样本数过少等)。


本节课中我们一起学习了决策树的直观工作原理。我们明白了决策树如何通过一系列基于特征的判断来对输入样本进行分类或回归预测,并且明确了机器学习的目标是自动从数据中构建出这棵有效的决策树。在接下来的课程中,我们将深入探讨用于构建决策树的具体算法。
机器学习(分类,聚类和检索):第3-4课:从数据中学习决策树的任务

在本节课中,我们将深入探讨如何从数据中学习决策树模型。我们将了解学习任务的定义、评估模型质量的指标,以及为什么寻找最优决策树是一个计算难题。最后,我们将介绍一种在实践中非常有效的启发式方法。

上一节我们介绍了决策树的基本概念。本节中,我们来看看如何从给定的数据集中学习一个决策树模型。
我们被给予一个训练数据集。这个数据集是一个表格,其中每一行对应一个数据点,每一列对应一个特征。例如,在这个例子中,我们有三个特征:信用期限、收入,以及我们试图预测的目标变量贷款状态(Y),即贷款是“高风险”还是“低风险”。
我们的目标是学习一个决策树模型 T(x),它能够根据一个或多个输入特征来预测 Y 的取值。
更一般地说,我们被给予 n 个形式为 (Xi, Yi) 的观测数据,其中 Yi 是真实标签。我们的任务是优化某个质量指标,以拟合一个在该指标下尽可能好的树。
对于决策树,我们将使用的指标是分类错误率。决策树也可以使用其他指标,但本模块我们专注于分类错误率。分类错误率衡量的是我们在训练数据上做出预测时犯错的比例。
其计算公式如下:
分类错误率 = 错误预测的数量 / 总样本数量
与逻辑回归的情况类似,最佳可能值是 0(没有错误),最差可能值是 1(每个预测都错了)。我们希望错误率尽可能接近 0。
既然我们已经明确了分类错误率,就可以更清晰地陈述学习目标:给定一个数据集,找到一个能最小化分类错误率的决策树。
接下来的问题是:这个学习任务有多难?事实证明,这是一个极其困难的学习任务。即使只考虑决策树的一个分支,选择下一个要使用的特征及其顺序也会导致指数级的组合数量。
事实上,对于熟悉计算复杂性理论的读者来说,这是一个NP难问题的典型例子。这是一个非常困难的问题,目前没有能提供性能保证的近似算法。
然而,存在一些简单的启发式思想,在实践中往往表现极佳。今天我们将讨论其中一种思想,称为简单的贪心算法。
其基本思路是:我们逐步地、一层一层地构建决策树,在每一步都力求获得当前可能的最佳分类错误率。

本节课中,我们一起学习了决策树的学习任务。我们明确了目标是最小化分类错误率,并认识到寻找全局最优决策树是一个NP难问题。最后,我们引入了贪心算法作为构建决策树的一种有效且实用的启发式方法。在接下来的课程中,我们将详细探讨这种贪心算法的具体步骤。
机器学习(分类,聚类和检索):3-4:递归贪心算法


在本节课中,我们将学习决策树的核心构建算法——递归贪心算法。我们将从算法的高层概述开始,然后深入探讨实现该算法所需的关键细节。
算法概述
决策树学习算法通常从一个空树开始,该树包含所有数据。我们的目标是构建一棵树,通过一系列基于特征的判断(即“分裂”),将数据逐步分类。


上一节我们介绍了决策树的基本概念,本节中我们来看看如何通过递归贪心算法来构建它。
算法步骤详解
以下是递归贪心算法的高层描述,它是一个非常简单的过程。
- 从空树开始:初始时,我们有一个根节点,它包含整个数据集。例如,在贷款数据中,根节点包含所有被标记为“安全”或“风险”的贷款记录。
- 选择分裂特征:从所有可用特征(如信用评级、贷款期限、收入等)中选择一个特征来分裂当前节点。在我们的例子中,我们选择了“信用评级”作为分裂特征。
- 创建分支:根据所选特征的可能取值,将当前节点的数据划分到不同的子节点中。例如,信用评级有“优秀”、“良好”、“差”三个值,因此会创建三个分支。
- 递归处理子节点:对于每个新创建的子节点(即每个数据子集),重复步骤2和步骤3。但是,如果某个子节点中的数据已经全部属于同一类别(例如,所有贷款都是“安全”的),则停止在该节点上的分裂,并将其标记为叶节点。
这个算法听起来有些抽象,但有两个关键点需要具体化:如何选择最佳的分裂特征,以及何时停止递归分裂。我们将在本模块的剩余部分讨论这两个重要任务。
核心概念与示例
让我们通过一个具体的例子来理解算法的执行过程。
- 初始状态:我们从包含所有数据的根节点开始。可以用一个柱状图来可视化数据中“安全”与“风险”贷款的数量分布。
- 第一次分裂:我们选择“信用评级”作为分裂特征。这会将数据分成三个子集:
- 信用评级 = “优秀”的数据子集(左分支)
- 信用评级 = “良好”的数据子集(中分支)
- 信用评级 = “差”的数据子集(右分支)
- 检查子节点:分裂后,我们再次用柱状图检查每个子节点中的数据。
- 在“优秀”信用分支中,几乎所有贷款都是“安全”的。由于该节点数据已经“纯净”(属于同一类别),我们停止在此分支上的进一步分裂,并预测所有信用优秀的人都会获得安全贷款。
- 在“良好”和“差”信用分支中,数据类别仍然混合(既有安全贷款也有风险贷款)。因此,我们需要对这些节点递归地应用相同的算法,继续选择特征进行分裂。
算法要点总结

本节课中我们一起学习了决策树的递归贪心构建算法。我们了解到,该算法从一个包含全部数据的根节点开始,通过贪婪地选择当前最佳分裂特征来构建树,并在每个子节点上递归地重复这一过程,直到满足停止条件(如节点数据纯净或达到深度限制)。理解如何选择分裂特征和何时停止递归,是掌握该算法的关键。在接下来的课程中,我们将深入探讨这两个核心问题。
机器学习(分类,聚类和检索):第3-4课:学习决策树桩 🌳

在本节课中,我们将要学习决策树构建中的一个核心概念——决策树桩。我们将探讨在构建决策树时,如何选择第一个特征进行划分,并理解这一过程如何简化为学习一个单层决策树,即决策树桩。
概述
上一节我们介绍了构建决策树的贪心算法。本节中,我们来看看这个算法的第一步:如何选择下一个要划分的特征。在我们的例子中,我们首先根据“信用”特征进行了划分,但我们也可以选择其他特征。如何决定呢?事实证明,这个特征选择问题,或者说特征划分学习问题,可以被看作是学习一个被称为“决策树桩”的单层决策树。
对于那些不熟悉树桩概念的人,可以想象一棵大树。如果你把它砍断,只留下底部的一小段,那个东西就被称为树桩。所以,决策树桩就是一棵非常非常短的树。
学习决策树桩

那么,如何从数据中学习一个决策树桩,或者说一个单层的决策树呢?我们被给予一个像之前一样的数据集,我们的目标是学习一个单层决策树。
我们拥有根节点,它包含了所有的数据。其中一些数据点是安全的贷款,一些是风险贷款。在我们的案例中,总共有40个例子。具体来说,其中22个是安全贷款,18个是风险贷款。这就是我们数据的样子。
为了简化可视化,我们将用数字22和18来代表这些类别,而不是显示完整的直方图。
所以,当你看到这个根节点时,你应该将其解释为:我们有40个数据点,22个绿色(安全贷款),18个橙色(风险贷款)。
从那里开始,我们如何构建那个决策树桩呢?
在我们的案例中,我们拥有所有数据,我们根据“信用”进行了划分,并决定一些数据有“优秀”信用,一些是“良好”,一些是“差”。我们将这些子集分别分配给了后续的节点。
用我们新的可视化符号表示:原始的根节点有22个安全和18个风险。对于“优秀”信用,我们有一个子集数据,其中9个是安全的,0个是风险的。对于“良好”信用,我们有9个安全,4个风险。对于“差”信用,我们有4个安全,14个风险。这就是我们在完成划分后,下一层节点的样子。
这些中间的节点,我们称之为中间节点。
现在,对于每个中间节点,我们可以尝试做出一个决策树桩的预测。
例如,对于“差”信用,我们看到其中的数据大多数与风险相关,所以我们预测那是一个风险贷款。对于“良好”信用,我们看到多数(9对4)是安全贷款,所以我们预测那是一个安全贷款。对于“优秀”信用,我们预测那是一个安全贷款,因为里面有9个安全贷款,0个风险。
对于每个节点,我们查看多数值来进行预测。这样,你就学会了你的第一个决策树桩。这是一个相当简单的模型,但为了获得更好的预测或更高的准确性,我们将进一步探索并进行更深的划分。
然而,在我们进一步划分之前,我们将讨论为什么我们选择“信用”作为第一个划分特征,而不是例如贷款期限或收入。
总结


本节课中,我们一起学习了决策树桩的概念。我们了解到,在构建决策树的贪心算法中,第一步的特征选择可以简化为学习一个单层的决策树,即决策树桩。我们通过查看每个划分后子节点中数据的多数类别来进行预测。理解这个简单的模型是后续学习更复杂决策树的基础。下一节,我们将深入探讨如何量化并选择最佳的划分特征。
机器学习(分类,聚类和检索):第3课:选择最佳特征进行分割

概述
在本节课中,我们将要学习如何在构建决策树时,选择最佳的特征进行数据分割。我们将通过比较不同特征分割后的分类错误率,来理解如何做出最优选择。
从数据构建决策树
上一节我们讨论了从数据构建决策树的基本概念,以及数据集的大致样貌。本节中我们来看看,在构建决策树时,如何选择正确的特征进行分割。
我们尝试从数据中学习一个决策树桩,并基于“信用”特征进行了分割。但问题是,什么是最佳的分割特征?我们如何衡量它?
在我们的例子中,我们根据“信用”进行了分割,但我们也可以根据其他特征进行分割,例如贷款期限是三年还是五年。问题是,这两种分割方式哪个更好?什么是更好的分割?这就是我们接下来要探讨的问题。


直观地说,一个更好的分割是能带来最低分类错误率的分割。这正是我们将在算法中探索的核心。
衡量分割质量:分类错误率
我们希望弄清楚,根据“信用”分割和根据“期限”分割哪个更好。我们将通过衡量每个决策树桩所犯的错误数量来实现这一点,并选择犯错最少或错误率最低的那个。
请记住,错误率就是分类器犯错的次数除以数据点的总数。
让我们从根节点开始。这是我们在决策树桩中不做任何分割的情况,我们来衡量在这种情况下得到的错误率。
提醒一下,我们将预测 \(\hat{y}\) 为与特定节点相关联的多数类。在我们的例子中,根节点中拥有最多值的类别是“安全”类。当我们计算做出该预测的分类错误时,我们实际上是在说所有数据点都是安全的。
因此,我们可以说有22个正确的预测(22个是安全的),以及18个错误。所以这里的分类错误率将是 18 除以 (22 + 18),即 40,所以是 18/40 = 0.45。
这是一个二分类问题,得到0.45的错误率意味着结果非常糟糕。因此,不做任何分割会得到一个相当差的结果。
现在的问题是,基于“信用”分割的决策树桩效果如何?与不做任何分割(错误率为0.45)相比,它是否更好?
比较不同分割方式的错误率
让我们看看基于“信用”分割的决策树桩。
- 对于信用“优秀”的数据点,我们预测为“安全”。
- 对于信用“良好”的数据点,我们预测为“安全”。
- 对于信用“差”的数据点,我们预测为“风险”。
这是我们的预测,同样,这是每个节点中数据的多数值。
如果我们查看我们犯了多少错误:
- 对于信用“优秀”的数据,我们犯了0个错误,因为那里所有贷款都是安全的。
- 对于信用“良好”的数据,我们将犯4个错误,因为有4笔风险贷款信用良好。
- 对于信用“差”的数据,我们再次看到4个错误,因为当我们信用差时,有4笔安全贷款。
让我们计算总体错误率。我们犯了 4 + 4 = 8 个错误,总共有40个数据点。所以错误率是 8/40 = 0.2。这比之前的0.45要低。因此,我们从0.45下降到了0.2。基于“信用”分割似乎是个好主意。
现在,让我们看看根据“贷款期限”分割会发生什么。
如果期限是三年,也许有16笔安全贷款和4笔风险贷款。在这种情况下,我们犯了4个错误。
对于五年期贷款,我们预测为“风险”,但有6笔安全贷款。所以现在我们犯了6个错误。
因此,我们这里的总体错误率是 (4 + 6) / 40 = 10/40 = 0.25。
选择最佳特征
综上所述,如果我们查看数据:
- 不做任何分割(根节点)的错误率为 0.45。
- 基于“信用”分割的错误率为 0.2。
- 基于“期限”分割的错误率为 0.25。


现在我们可以回过头来问:最佳选择是什么?我们应该根据“信用”分割还是根据“期限”分割?答案现在变得很明显:基于“信用”分割能带来更低的分类错误率。
因此,这就是我们的贪心算法首先要做的事情,这将是我们在选择过程中的获胜特征。
决策树分割的一般过程
一般来说,决策树分割过程会这样进行:给定节点 M 处的数据子集(到目前为止我们看的是根节点),我们尝试每一个特征 \(X_i\)(在我们的例子中是信用、期限和收入)。
我们考虑根据每个特征的可能值来分割数据,并计算分割后的分类错误率,就像我们刚才手动计算的那样。然后,我们选择具有最低分类错误率的特征(在我们的例子中是“信用”)。
如果我们回到决策树学习算法,我们面临的第一个挑战是弄清楚用什么特征进行分割。现在,我们可以使用这个最小化分类错误率的特征分割选择算法来解决它。
接下来,我们将探索决策树学习算法的其他部分。

总结
本节课中,我们一起学习了如何为决策树选择最佳分割特征。我们通过计算和比较不同特征分割后的分类错误率来实现这一目标。我们发现,选择能最小化分类错误率的特征(如例子中的“信用”特征)是构建有效决策树的关键第一步。这为后续深入学习决策树算法奠定了基础。
机器学习(分类,聚类和检索):第3-4课:何时停止递归


在本节课中,我们将学习如何构建完整的决策树,而不仅仅是决策桩。我们将重点讨论决策树学习算法中的递归过程,以及决定何时停止递归的关键条件。
上一节我们介绍了如何选择最佳特征进行分割。本节中我们来看看如何基于这个分割进行递归,并最终决定何时停止递归。
递归构建决策树
我们的目标已经从学习一个决策桩,扩展为从数据中学习一整棵决策树。
以我们之前基于“信用”特征学习的决策桩为例。在“信用=优秀”的分支中,所有数据点都是安全贷款。因此,无需进一步操作,我们可以直接将其标记为叶节点,因为任何进一步分割的预测结果都将是“安全”。
然而,对于“信用=一般”和“信用=差”的另外两个分支,我们需要分别查看对应这些条件的数据子集,并为每个子集构建下一个决策桩,如此递归下去。
在我们的例子中,如果继续构建:
- 对于“信用=一般”的数据子集,下一个最佳分割特征是“期限”。
- 对于“信用=差”的数据子集,下一个最佳分割特征是“收入”。
- 在“收入=低”的分支中,所有贷款都是高风险,因此可以停止分割。
- 在“收入=高”的分支中,数据点混合了高风险和安全贷款,因此需要继续构建下一个决策桩。
通过这样的递归过程,我们最终可以学习到一棵覆盖所有数据的完整决策树,每个可能的分支路径都通向一个叶节点。
停止递归的条件
我们描述的是一个递归算法:首先选择最佳特征进行分割,然后根据该特征将数据分成决策桩,接着针对决策桩的每个叶节点(或与之关联的数据子集),返回去学习一个新的决策桩。
关键问题是:我们需要一直这样迭代下去吗?还是应该在某个点停止?
以下是决定何时停止递归的两个核心条件。
条件一:数据纯度达到100%
第一个条件我们已经见过。当某个节点关联的所有数据点都属于同一个类别(即输出值 y 完全一致)时,继续分割没有意义。
例如:
- “信用=优秀”的节点中,所有贷款都是“安全”。
- “信用=一般,期限=3年”的节点中,所有贷款都是“高风险”。
对于这些节点,应该停止分割。
条件二:特征已用完
第二个条件发生在另一种情况:我们停止了分割,但该节点内的数据点仍然混合了不同类别的贷款(例如既有安全贷款也有高风险贷款)。然而,我们已经用完了数据集中所有可用的特征。
在我们的例子中,只有三个特征:信用、收入和期限。在决策树的某个分支上,如果这三个特征都已用于分割,那么就没有其他特征可以继续分割了。即使继续分割,结果也不会改变。
算法总结
回顾我们学习决策树的递归算法,其步骤可以概括如下:
- 选择特征:选取能最小化分类错误的特征进行分割,如之前所讨论。
- 检查停止条件:应用我们刚刚描述的两个简单条件:
- 停止,如果该节点所有数据点的
y值一致。 - 停止,如果所有可用特征都已用完。
- 停止,如果该节点所有数据点的
- 递归:如果以上条件均不满足,则对当前分割产生的每个数据子集(节点)重复步骤1和2,直到满足停止条件为止。


本节课中我们一起学习了决策树构建过程中的递归逻辑以及何时停止递归的两个关键条件:数据完全纯净或特征全部用完。理解这些条件是掌握决策树如何从数据中自动学习并形成完整树形结构的基础。
机器学习:3-4:使用决策树进行预测

在本节课中,我们将学习如何利用已训练好的决策树模型来对新数据进行预测。我们将详细介绍预测的流程,并通过一个具体的例子来演示整个过程。
预测流程概述
上一节我们介绍了如何从数据中学习一个决策树模型。本节中,我们来看看如何使用这个模型进行预测。
正如在本模块开始时讨论的,使用决策树进行预测是一个相当简单的过程,本质上是沿着树的结构向下遍历,直到到达一个叶节点。
预测算法详解
以下是使用决策树进行预测的递归算法步骤:
- 从根节点开始:给定一个输入数据点
X_i和决策树的根节点。 - 检查当前节点:
- 如果当前节点是叶节点,则直接返回该叶节点上存储的预测值(例如,“安全”或“有风险”)。
- 如果当前节点是内部节点(即决策节点),则根据输入数据
X_i在该节点特征上的取值,选择对应的分支(子节点)。
- 递归调用:在选定的子节点上,重复步骤2,直到到达一个叶节点并返回预测结果。
这个算法可以形式化地表示为以下伪代码:

def predict(tree_node, input_x):
if tree_node.is_leaf_node:
return tree_node.prediction
else:
# 根据 input_x 在 tree_node.feature 上的值选择分支
child_node = select_child_based_on_feature(tree_node, input_x)
return predict(child_node, input_x)
实例演示
让我们回到最初的贷款审批例子。假设我们有一个新的申请者,其特征为:
- 信用记录:差 (
credit = poor) - 收入:高 (
income = high) - 工作年限:5年 (
employment = 5 years)
我们使用训练好的决策树对这个申请者进行预测:
- 从根节点(“信用记录”)开始。
- 由于信用记录为“差”,我们沿着“差”分支向下走到下一个节点(“收入”)。
- 在“收入”节点,由于收入为“高”,我们沿着“高”分支向下走。
- 到达一个叶节点,该节点的预测是“安全”。
因此,模型预测该申请者的贷款风险为 安全 (y_hat_i = safe)。
总结

本节课中我们一起学习了如何使用决策树模型进行预测。我们了解到,预测过程就是根据输入数据的特征值,从根节点开始,沿着决策树的分支向下遍历,直到到达一个叶节点,该叶节点的值就是最终的预测结果。这个过程可以通过一个简洁的递归算法来实现,易于理解和执行。
机器学习:3-4:决策树的多类分类 🌳

在本节课中,我们将学习决策树如何应用于多类分类问题。我们将看到,决策树不仅能处理二分类任务,也能以几乎相同的方式处理具有多个类别的分类问题。
从二分类到多类分类
上一节我们介绍了决策树在二分类中的应用。本节中我们来看看,当输出类别不止两个时,决策树如何工作。
决策树可用于二分类。决策树也可用于多类分类,且基本无需修改。
多类分类示例
例如,假设在相同的贷款申请场景中,我们有一个分类器来预测输出。但输出不仅仅是贷款“安全”或“有风险”,而是增加了“危险”类别,即某些贷款风险极高,不应考虑。
那么问题在于,我们如何决策一笔贷款是“安全”、“有风险”还是“危险”?
让我们看一个三类分类的例子。我们将看到一个决策树桩的示例,但同样的原理适用于更大的决策树。
构建决策树
以下是构建多类分类决策树的关键步骤:
作为输入,我们给定一个数据集。例如,我们可能只有一个特征“信用”,其值可以是“优秀”、“良好”或“差”。输出则可以是“安全”、“有风险”或“危险”。
观察此处的根节点,你会看到现在有三个可能的类别:安全贷款、风险贷款和危险贷款。如果我们根据“信用”特征进行划分,会自然地看到一些贷款落入“优秀”分支,一些落入“良好”分支,一些落入“差”分支。
对于落入“优秀”分支的贷款,我们看到其中大多数是安全的,因此我们预测为“安全”。对于“良好”分支,我们看到大多数是有风险的,因此预测为“有风险”。但对于“差”信用分支,大多数是危险的,因此我们甚至不考虑这些贷款。
预测与概率
我们讨论了可以根据每个划分中多数类来进行预测。但事实证明,对于决策树,预测某个类别的概率也非常简单。
以下是计算概率的方法:
你只需查看与每个叶子节点相关联的数据中,具有特定标签或值的比例。
例如,对于信用为“差”的情况,我们预测的Y_hat是“危险”。我们实际上可以询问给定输入X时,结果为“危险”的概率。在我们的例子中,如果你的输入引导你进入这个分支,那么11个数据点中有7个是“危险”的。因此,我们说“危险”的概率是 7/11 ≈ 0.64。同样,“安全”贷款的概率是 3/11。
因此,我们有一种方法可以同时预测概率和结果的实际值,这两者在实践中都非常有用。
总结

本节课中,我们一起学习了决策树如何扩展到多类分类问题。我们看到,其核心机制与二分类相同:根据特征进行划分,并在叶子节点根据多数类进行预测。此外,决策树还能通过计算叶子节点中各类别的比例,轻松地输出每个类别的预测概率,这为模型提供了更丰富的信息。
机器学习(分类,聚类和检索):第3-4课:连续输入的阈值分割 📊

在本节课中,我们将要学习如何处理决策树中的连续值特征。之前我们讨论了使用分类数据(如信用等级)构建决策树,但现实数据中常包含像“收入”这样的连续值特征。本节将介绍一种称为“阈值分割”的方法,它能有效地将连续值转换为可用于决策树分割的二元判断。

从分类到连续值
上一节我们介绍了如何使用分类特征(如“信用等级”)来构建决策树。然而,许多重要特征(如收入、年龄)是连续取值的。如果像处理分类数据一样,为收入的每一个可能值(例如30,000、31,400)都创建一个分支,会导致每个分支节点只包含极少的数据点。
例如,如果为每个收入值单独分割,得到的节点可能只包含一个数据点。这会导致严重的过拟合问题,模型会记住训练数据中的噪声,而无法做出可靠的预测。例如,模型可能预测收入30,000为高风险,31,400为低风险,39,500又为高风险,这种预测模式显然不合理且不可信。
因此,我们需要一种更好的方法来处理连续值特征。
引入阈值分割
处理连续值特征的一个自然而有效的方法是使用阈值分割。这种方法不是为每个值创建分支,而是选择一个阈值,将数据划分为“低于阈值”和“高于或等于阈值”两组。
以下是阈值分割的核心步骤:
- 选择一个连续特征(如
income)。 - 为该特征选择一个阈值(如
60000)。 - 根据阈值创建二元分割:
- 左分支:
income < 60000 - 右分支:
income >= 60000
- 左分支:
通过这种方式,我们可以将数据点聚合到两个更大的子集中,从而减少过拟合的风险,并得到更稳定、更可信的预测结果。
可视化阈值分割
为了更好地理解阈值分割,我们可以将其可视化。
单特征分割
假设我们只有收入一个特征,其值分布在一条从10,000到120,000的直线上。如果我们选择60,000作为阈值,那么:
- 直线左侧(收入 < 60,000)的数据点被预测为“高风险”贷款。
- 直线右侧(收入 >= 60,000)的数据点被预测为“安全”贷款。
多特征分割
现在,考虑两个连续特征:收入(Y轴)和年龄(X轴)。数据点分布在二维平面上。
- 我们可能首先根据年龄进行分割,例如选择阈值
age = 38。- 对于
age < 38的群体,高风险贷款比例较高,因此预测为“高风险”。 - 对于
age >= 38的群体,安全贷款比例较高,因此预测为“安全”。
- 对于
- 接着,对于
age >= 38的这个子群体,我们可以进行第二次分割,这次根据收入,选择阈值income = 60000。- 对于
income >= 60000的,预测为“安全”。 - 对于
income < 60000的,即使年龄较大,也可能被预测为“高风险”。
- 对于
构建决策树示例
让我们将上述可视化过程转化为一个具体的决策树结构。


以下是基于年龄和收入两个连续特征构建的决策树示例:
- 根节点:包含所有数据点。
- 第一次分割(基于年龄):
- 条件:
age < 38? - 是(左分支):该节点包含5个高风险和3个安全贷款。由于高风险居多,该叶节点预测为“高风险”。
- 否(右分支):进入下一步分割。
- 条件:
- 第二次分割(基于收入):
- 条件:
income >= 60000? - 是(右分支):该节点数据点被预测为“安全”贷款。
- 否(左分支):该节点数据点被预测为“高风险”贷款。
- 条件:
这棵决策树可以用以下伪代码表示:
if age < 38:
prediction = “高风险”
else:
if income >= 60000:
prediction = “安全”
else:
prediction = “高风险”
通过这种二元阈值分割,我们成功地将连续值特征整合到了决策树模型中,并得到了一个清晰、可解释的决策路径。
总结


本节课中我们一起学习了如何处理决策树中的连续值输入。关键点在于,不能直接为每个连续值创建分支,否则会导致过拟合。我们引入了阈值分割这一核心方法,通过为连续特征(如 income、age)选择一个合适的阈值(如 60000、38),将数据划分为两个子集(例如 feature < threshold 和 feature >= threshold)。这种方法允许我们在决策树中有效地使用连续特征,生成更稳健、更可靠的模型,并通过可视化示例和树结构展示了其实际应用过程。
机器学习(分类,聚类和检索):第3-4课:可选:选择最佳阈值进行分割 📊

在本节中,我们将学习如何为连续值特征(例如收入)选择最佳的分割阈值。例如,是选择 H=38 还是 收入=60000 作为决策树的分支点?我们将介绍一个简单但有效的算法来找到这个最佳点。
上一节我们讨论了决策树的基本概念,本节中我们来看看如何为连续特征自动选择最优的分割阈值。
为什么需要考虑所有可能的分割点? 🤔
我们的目标是:如果决定在某个特征(例如收入)上进行分割,如何选择最佳的分割点 T*(例如60000)来划分树的左右分支。
T* 理论上可以取无限多个值(例如60000.01, 60000.001...)。但问题是,我们需要考虑所有这些值吗?这些小数点后的细微差别真的会影响决策树的质量吗?
实际上,并不需要。我们只需要考虑数据点之间的中点。原因在于:观察数据中收入的实际取值,例如 VA=60000 和 VB=65000。如果这两个数据点之间没有其他数据点,那么无论分割点选在61000、62000还是64000,分类结果都是一样的。分割点左边的数据点集合和右边的数据点集合不会改变。因此,我们只需考虑现有数据点之间的中点作为候选分割点。
寻找最佳分割点的算法 🧮
以下是为一特定特征(例如收入 Xj)选择最佳分割点的具体步骤。
首先,获取该特征在所有数据样本上的取值,并将其排序,得到有序序列:
V1(最低收入), V2, ..., Vn(最高收入)。
接下来,我们只需要考虑每两个相邻数据点之间的中点作为候选分割点。
以下是算法的核心步骤:
- 排序数据:将特征
Xj的所有取值升序排列。 - 生成候选点:对于
i从1到n-1,计算候选分割点ti。ti是Vi和V(i+1)的中点,公式为:
ti = (Vi + V(i+1)) / 2 - 评估每个候选点:对于每个候选分割点
ti,构建一个决策树桩(单层决策树)。该树桩的规则是:如果Xj > ti则分到右分支,否则分到左分支。然后计算该树桩在训练数据上的分类错误率。 - 选择最佳点:遍历所有候选点后,选择那个能产生最低分类错误率的决策树桩所对应的分割点
ti,将其作为最终的最佳分割点T*。
用伪代码描述如下:
# 假设 features 是特征列,labels 是对应标签
sorted_values = sort(unique(features))
best_error = infinity
best_split = None
for i in range(len(sorted_values)-1):
candidate_split = (sorted_values[i] + sorted_values[i+1]) / 2
# 根据 candidate_split 规则预测标签
predictions = (features > candidate_split)
# 计算分类错误率
error = calculate_classification_error(predictions, labels)
if error < best_error:
best_error = error
best_split = candidate_split
# best_split 即为最佳分割点 T*
这个算法简单直接,易于实现,它确保了我们在有限的候选点中找到对当前数据最优的分割阈值。


本节课中我们一起学习了如何为连续值特征选择决策树的分割阈值。核心在于理解无需遍历无限的可能值,只需评估数据点之间的中点。我们介绍了一个清晰的算法:排序特征值、生成中点候选、评估每个候选点的分类错误,并选择错误率最低的点作为最佳分割点 T*。这为构建更精确的决策树模型奠定了基础。
机器学习(分类,聚类和检索):3-4:可视化决策边界


在本节课中,我们将通过一个具体例子,深入探索决策树的工作原理,并将其与我们之前学过的逻辑回归模型进行比较。我们将重点关注决策边界如何随着模型复杂度的变化而变化,并初步了解过拟合的概念。
决策树与逻辑回归的对比
上一节我们介绍了决策树的基本构建过程。本节中,我们来看看一个具体的例子,并将其与逻辑回归的决策边界进行可视化对比。
我们使用的数据集与逻辑回归模块中考虑的例子相同。下图展示了使用简单的一阶多项式特征(即线性特征)进行逻辑回归后得到的决策边界,以及从数据中学到的参数。

现在,让我们看看在相同数据集上构建一个决策树桩(单层决策树)会发生什么。
以下是构建过程:
- 如果我们尝试不同的阈值,会发现最佳分割点是 x1 < -0.07。
- 在分割点的左侧(x1 < -0.07),负例样本更多,因此预测为负类。
- 在分割点的右侧(x1 >= -0.07),正例样本更多,因此预测为正类。
这个结果非常直观。与逻辑回归可以得到斜向决策边界不同,在第一次分割时,决策树只能产生垂直或水平的决策边界。
构建更深的决策树
现在,如果我们继续使用贪心算法,为这些中间节点进行下一次分割,决策边界会变得更加复杂。
以下是深度为2的决策树的分割过程:
- 对于 x1 < -0.07 的数据,我们可能再次在 x1 上分割(例如 x1 < -1.66),两边都预测为负类。
- 对于 x1 >= -0.07 的数据,我们在 x2 上分割,条件是 x2 > 1.55。
- 对于 x2 <= 1.55 的数据,有11个正例,预测为正类。
- 对于 x2 > 1.55 的数据,有3个负例,预测为负类。
现在,我们得到了更有趣的决策区域。右侧的两个节点,一个对应一大片绿色区域,另一个对应顶部的一个小方框。
一个重要的知识点是:对于连续变量,我们可以对同一个变量进行多次分割。这与离散或分类变量不同。
决策树的深度与过拟合
我们可以让决策树学习过程继续进行下去。随着深度增加,决策边界会变得越来越复杂。
以下是不同深度决策树的对比:
- 深度 1:只是一个决策树桩,对应开始时画的垂直线(x1 = -0.07)。效果一般。
- 深度 2:得到一个包含大多数正例的小方框,但这里仍有一些分类错误。
- 深度 10:得到一个非常复杂的决策边界。仔细观察会发现,它基本上没有错误,即训练误差为零。


与逻辑回归的对比及过拟合预览
现在,我们可以将逻辑回归的结果与决策树进行对比,并初步理解下一个模块将详细讨论的过拟合概念。
以下是不同模型的比较:
- 逻辑回归(1阶多项式):从简单的线性决策边界开始。
- 逻辑回归(2阶多项式):对数据拟合得很好,是一个漂亮的抛物线。虽然没有完全分类正确,但表现相当不错。
- 逻辑回归(6阶多项式):决策边界非常复杂,达到了零训练误差,但我们并不完全信任这些预测。
- 决策树:通过深度来控制复杂度。
- 深度 1:决策树桩,效果不太好。
- 深度 3:决策边界略有锯齿,但看起来相当不错,只犯了少量错误。
- 深度 10:决策边界极其复杂,训练误差为零,但很可能过拟合了。


本节课中,我们一起学习了如何可视化决策树的决策边界,并通过与逻辑回归的对比,观察了模型复杂度(决策树深度、多项式阶数)对决策边界形状和模型性能的影响。我们看到了简单的模型可能欠拟合,而过于复杂的模型虽然训练误差低,但可能学习到了噪声,导致过拟合。这为我们接下来深入探讨模型评估与选择奠定了基础。
机器学习(分类,聚类和检索):第3-4课:决策树回顾

在本节课中,我们将回顾决策树的核心概念与构建过程。我们将学习如何从数据中构建决策树,理解其算法原理,并探讨其预测与决策边界的特点。
决策树构建回顾
上一节我们介绍了决策树的基本概念,本节中我们来看看如何从数据中构建一棵决策树。
构建决策树的核心是一个简单、贪婪的递归算法。其主要步骤是选择在哪个特征上进行分割,以及何时停止分割。
以下是构建决策树的关键步骤:
- 选择分割特征:算法需要决定当前节点使用数据中的哪个特征进行分割,以最好地区分不同类别的样本。
- 递归分割:对分割后产生的每个子数据集,重复上述分割过程,构建子树。
- 停止条件:设定规则以决定何时停止分割,例如当节点中的数据都属于同一类别,或没有更多特征可用时。
算法实现与预测
理解了构建过程后,你现在应该能够理解如何从数据中构建决策树,真正实现该算法,并能使用学习到的决策树进行预测。
此外,你也可以探索决策树的决策边界,并思考它们与逻辑回归等其他方法的决策边界有何关联与区别。
过度拟合与展望

在下一个模块中,我们将讨论解决决策树过度拟合的方法。
总结
本节课中我们一起学习了决策树的构建算法。我们回顾了其贪婪递归的本质,核心在于选择分割特征与设定停止条件。你现在已经掌握了从数据构建决策树、进行预测以及分析其决策边界的基本能力。

(注:文末的致谢部分因其为课程结束语,与教程核心内容无关,故未纳入翻译整理。)
机器学习(分类,聚类和检索):3-4:决策树过拟合回顾 🧠

在本节课中,我们将回顾决策树的基础知识,并深入探讨一个关键问题:过拟合。我们将了解什么是过拟合,它为何在决策树中尤为突出,以及它对模型性能的影响。

决策树基础回顾 🌳
上一节我们介绍了决策树,这是一种非常强大的分类器,能够处理多种不同类型的数据。决策树通过一系列规则对数据进行划分,最终做出预测。
在我们的贷款申请评估系统示例中,输入数据 XI 代表贷款申请信息,输出 Y_hat_I 是我们预测的贷款风险类别(安全或高风险)。决策树的目标就是学习从 XI 到 Y_hat_I 的映射规则。
过拟合问题 🔍


然而,决策树有一个显著的缺点:它非常容易过拟合。在深入探讨如何避免之前,我们先花一点时间回顾一下什么是过拟合。

过拟合是指模型在训练数据上表现很好(训练误差很低),但在新的、未见过的数据上表现很差(真实误差很高)的现象。随着模型复杂度增加,训练误差会持续下降并趋近于零,但真实误差会先下降后上升。

更具体地说,过拟合发生在我们最终选择了一个模型参数 W_hat 时,该模型具有低训练误差但高真实误差。而实际上,可能存在另一个模型参数 W_star,它虽然训练误差稍高,但真实误差却低得多。这就是过拟合的核心问题。
我们在逻辑回归中已经见过这个效应。随着多项式次数的增加,决策边界变得异常复杂和“疯狂”,导致严重的过拟合。我们称这种现象为“疯狂过拟合”。
决策树中的过拟合 🌲➡️🍂
决策树模型可以非常快速地变得过度复杂。一个深度很大、分支很多的决策树会记住训练数据中的每一个细节,包括噪声和异常值,从而导致过拟合。
为了避免这种情况,我们需要找到方法在模型复杂度和泛化能力之间取得平衡。这通常意味着我们需要选择一棵不那么复杂(例如,深度较浅)的树。
总结 📝
本节课我们一起回顾了决策树的基础和过拟合的概念。我们了解到:
- 决策树是一种灵活的分类器。
- 过拟合是模型在训练集上表现优异但在新数据上表现不佳的问题,其核心公式可概括为:选择模型时,
训练误差(W_hat) ≈ 0但真实误差(W_hat) >> 真实误差(W_star)。 - 决策树由于其结构特点,特别容易产生过拟合。

在接下来的课程中,我们将学习如何通过“剪枝”等具体技术来避免决策树中的过拟合,从而构建出更稳健的模型。
机器学习(分类,聚类和检索):第3-4课:决策树中的过拟合


在本节课中,我们将要学习决策树模型中的一个核心问题:过拟合。我们将通过观察决策树深度增加时,模型在训练集和验证集上表现的变化,来理解过拟合是如何发生的,以及为什么我们需要警惕训练误差过低的情况。
上一节我们介绍了决策树的基本概念。本节中我们来看看,随着决策树变得复杂,模型的表现会发生什么变化。
当我们开始学习一个决策树时,我们首先学习的是一个决策桩。决策桩是数据之间一个非常简单的边界,例如一条垂直线或水平线。
在这个例子中,决策规则是关于特征 x1 是否小于 -0.07。如果 x1 < -0.07,模型预测为 -1,这对应于决策边界的左侧。如果 x1 > -0.07,模型预测为 +1,这对应于决策边界的右侧。这是一个深度为1的决策树,即决策桩,其决策边界非常简单。
随着我们增加决策树的深度,决策边界会变得越来越复杂。你可以看到,深度增加,决策边界的复杂性也随之增加。
直到我们得到一个深度为10的、极其复杂的决策边界。这个深度为10的决策树在训练集上的误差为零。训练误差从决策桩的 0.22(相对较高),下降到深度为2和3的决策树的 0.13 和 0.10,最后到这个深度为10的疯狂决策树的 0。这应该是一个巨大的警告信号。


我们观察到,对于决策树,随着深度增加,训练误差会持续下降,直到可能达到零。在这个深度为10的决策树案例中,训练误差确实为零。
你可能会说,深度为10的决策树太棒了,它有零训练误差,所以它是一个完美的决策树。但实际上,它并非一个完美的决策树。正如我们所知,即使训练误差为零,真实误差(泛化误差)可能会急剧上升。因此,这可能是一个高度过拟合的决策树。
为了更好地理解为什么决策树的训练误差会随着深度增加而迅速下降,让我们回顾一个简单的例子。
我们使用了一个包含40个数据点的简单数据集,其中22个是安全贷款,18个是风险贷款。我们首先选择在“信用”特征上进行分割。
问题是,为什么我们首先选择在“信用”特征上分割?原因是我们选择首先在“信用”上分割,是因为它最大程度地降低了训练误差,将训练误差从 0.45 降低到了 0.20。这是一个很好的首次分割。
如果我们回顾选择最佳分割特征的算法,其核心是:我们尝试每一个可能的特征,并选择那个能最大程度降低训练误差的特征。
因此,在构建树的每一步,我们都在添加能够降低训练误差的特征。我们不断地添加特征来降低训练误差,最终会将训练误差驱动到零。当然,除非我们到达某个点,无法再降低训练误差,例如用尽了所有特征或正负样本已经无法完全分开。
最重要的是,请记住训练误差倾向于持续下降。这种随着深度增加而下降的趋势,导致了很低的训练误差,但也常常导致产生非常复杂、极易过拟合的树。
以下是一个来自真实贷款数据集的例子,我们实际观察到了严重的过拟合问题。
- 如果我们把树的深度一直增加到18,会看到训练误差(蓝线)下降了很多,大约降至8%,这是极低的。
- 然而,如果你观察验证集误差(橙线),情况就不那么好了,它大约在39%左右。
- 因此,训练误差和验证误差之间存在一个巨大的差距,我们将此表征为一种过拟合。
如果我们能够选择决策树的最佳深度,在这个案例中是深度7,那么验证集误差会略低于35%。换句话说,如果我选择了正确的深度(7),我能得到约35%的验证误差;但如果我任由树生长到训练误差极低(深度18),我却得到了39%的验证误差。
所以,盲目追求深度并不可取,我们需要适时停止。

本节课中我们一起学习了决策树中的过拟合现象。我们看到,随着决策树深度增加,模型会变得过于复杂,完美拟合训练数据(训练误差降至零),但在未见过的验证数据上表现变差(验证误差升高)。这提醒我们,在机器学习中,不能只追求训练集上的完美表现,控制模型复杂度、防止过拟合至关重要。在实践中,我们需要通过验证集来选择合适的模型深度。
机器学习(分类,聚类和检索):第3-4课:奥卡姆剃刀原理:学习更简单的决策树

在本节课中,我们将要学习如何避免决策树模型中的过拟合问题。我们将探讨奥卡姆剃刀原理,并学习两种主要技术——早停法和剪枝法,它们能引导我们构建更简单、泛化能力更强的决策树。

避免决策树过拟合的含义
上一节我们介绍了决策树可能出现的过拟合问题。那么,避免决策树过拟合具体意味着什么?它意味着我们需要提前停止树的生长,或者尝试简化我们学习的树的结构,从而避免严重的过拟合问题。我们将使用一种正则化方法,它会使我们倾向于选择更简单的树。这种方法在哲学上与一个称为“奥卡姆剃刀”的概念相关,接下来让我们讨论这个原理。
🪒 奥卡姆剃刀原理
寻找更简单的树、为数据提供更简单解释的这一思想,其历史可以追溯到很久以前。许多人称之为“奥卡姆剃刀”,源于13世纪左右讨论此概念的威廉·奥卡姆,尽管这一思想甚至可以追溯到更早的毕达哥拉斯和亚里士多德。
其核心概念是:在所有可能的假设或解释(在我们这里就是所有可能的树)中,你应该选择那个能够用尽可能简单的解释来说明数据的那一个。
例如,假设你去看医生,说你有两种症状S1和S2,比如剧烈的头痛和严重的喉咙痛。医生可能有两种解释:
- 脑瘤解释了头痛,而喉咙感染解释了喉咙痛。
- 另一种疾病,比如普通感冒,同时解释了头痛和喉咙痛。
在这种情况下,很可能是一种疾病同时解释了两种症状,而不是两种独立的疾病各解释一种症状。这是一种普遍的理念。奥卡姆的表述是:在相互竞争的假设中,应该选择假设最少的那一个。在这里,“假设最少”就相当于我们所说的“最简单”。
在决策树的语境下,奥卡姆剃刀原理可以表述为:如果你有两棵分类错误率相似的树,请选择更简单的那一棵。
让我们看下面的例子。我们观察到了几件事:
- 我们观察到有两棵树具有相似的验证集错误率。
- 其中一棵树训练错误率很低,但验证错误率更高,这棵树显然是过拟合的,因此复杂度过高的树肯定不好。
- 但有趣的是,对于那两棵验证错误率相同的树(中等复杂度树和更复杂的树),其中一棵训练错误率更高。根据奥卡姆剃刀,更简单的树可能更好,因为它更不容易过拟合。因此,我们很可能会选择那棵中等复杂度的树,它给出了合理的训练错误率和较低的验证错误率。
这是一个在概念上得到验证的想法:尝试选择那些能相对较好地解释数据,并且在验证集上表现良好的更简单的树。
如何定义“更简单”的树?
但要正确应用这一原理,我们必须深入定义什么是一棵“更简单”的树。
问题是:什么让一棵树更简单?我们左边有一棵深度很高、非常复杂的树,右边则是一棵较浅的两层决策树。显然右边那棵更简单。如果它们性能相似,我们就选择更简单的树。总的来说,我们应该尝试引导我们的算法去寻找更简单的树,而不是更复杂的树。
🛠️ 实现更简单决策树的方法

接下来我们将看到的是对决策树算法的修改,它将引导我们走向更简单的树。换句话说,我们要尝试避免复杂的树,专注于更简单的树。问题是如何做到这一点?主要有两种方法:

以下是两种主要方法:
- 早停法:与其让树长得越来越深,不如在某个时刻提前停止,以避免过拟合,从而停在更简单的树上。
- 剪枝法:这是一种更高级的方法,通常效果更好。你先构建一棵较深的树,然后“修剪”掉底部一些不重要的叶子节点(决策),从而得到一棵更简单的树。
在今天的课程中,我们将讨论这两种方法。
总结

本节课中,我们一起学习了如何应用奥卡姆剃刀原理来避免决策树过拟合。我们理解了选择更简单模型的重要性,并介绍了两种实现这一目标的技术:早停法和剪枝法。这些方法通过引导算法构建复杂度适中的树,帮助我们在保持良好解释能力的同时,提升模型在未知数据上的泛化性能。
机器学习(分类,聚类和检索):3-4:学习决策树时的早停 🛑


在本节课中,我们将要学习决策树学习过程中的一个重要技术——早停。早停是一种防止决策树模型过于复杂、从而避免过拟合的策略。我们将探讨三种具体的早停条件,并理解它们如何被整合到决策树的学习算法中。

上一节我们介绍了决策树的基本构建过程,本节中我们来看看如何通过早停来控制树的生长,防止过拟合。
早停的基本概念
早停的核心思想是:在决策树向下生长的过程中,在树变得过于复杂之前就停止分裂。这样做的目的是为了控制模型的复杂度。
随着树深度的增加,模型的复杂度也随之增加。如果我们希望避免那些过于复杂的模型,一个直接的方法就是避免生成非常深的树。

三种早停条件
以下是三种常用的早停条件,它们可以单独或组合使用,以控制决策树的生长。


1. 限制树的最大深度 🌳
第一种早停条件非常简单:为树设置一个最大深度限制。
我们知道,随着树深度的增加,训练误差会持续下降,但真实误差(泛化误差)会先下降后上升。因此,可能存在一个“最佳”的最大深度,在此之前,树足够简单且真实误差较低;在此之后,树变得过于复杂,真实误差开始上升。
这个最大深度 max_depth 是一个需要通过验证集或交叉验证来确定的超参数。切勿使用测试集来选择此类超参数。
2. 当分类误差不再降低时停止 📉
第二种早停条件是:如果继续分裂不能显著降低训练误差,则停止递归。
限制深度是对所有分支进行“一刀切”的限制。但有些分支可能需要更深的分裂才能获得好的效果。因此,我们可以检查在当前节点进行分裂后,分类误差是否得到改善。
例如,假设在一个节点上,不分裂时的训练误差是 0.24。如果尝试所有可能的特征进行分裂后,最佳分裂带来的训练误差仍然是 0.24(或改善幅度小于一个阈值 epsilon,例如 1%),那么就不应该继续分裂,以避免增加不必要的复杂度。
在实践中,通常会设置一个阈值参数 epsilon,只有当误差降低超过这个阈值时才继续分裂。这个规则需要谨慎使用,但在实践中非常有用。
3. 当节点数据量过少时停止 📊
第三种早停条件极其重要,应该始终被包含在算法中:如果节点中剩余的数据点太少,则停止分裂。
当数据量很少时继续分裂,会极大地增加过拟合的风险,因为算法会试图从噪声中寻找模式。
通常,我们会设置一个参数 n_min(例如 10 或 100)。如果一个节点包含的数据点数量 小于或等于 n_min,则立即停止在该节点的递归。对于较小的数据集,n_min=10 是一个不错的起点;对于大型数据集,可以设置为 100。
整合到决策树算法中
回顾之前模块讨论的决策树贪心学习算法,其基本步骤是:
- 从空树开始。
- 选择一个特征进行分裂。
- 如果满足停止条件,则将该节点标记为叶节点,并预测多数类。
- 否则,递归地对子节点回到步骤2。
我们之前已经讨论过两种停止条件(如所有样本属于同一类)。现在,我们将上述三种早停条件加入到这个框架中。

对现有代码进行微小的修改,加入这些早停条件,就能有效帮助防止决策树的过拟合。

总结
本节课中我们一起学习了决策树学习中的早停技术。我们介绍了三种关键的早停条件:
- 限制最大深度:通过
max_depth参数直接控制树的结构。 - 分类误差不再改善时停止:通过阈值
epsilon判断分裂是否带来足够收益。 - 节点数据量过少时停止:通过
n_min参数避免在数据不足的节点上进行不可靠的分裂。

将这些条件整合到决策树构建过程中,可以帮助我们找到复杂度适中、泛化能力更强的模型。记住,超参数如 max_depth、epsilon 和 n_min 需要通过验证集或交叉验证来谨慎选择。
机器学习(分类,聚类和检索):第3-4课:可选:修剪的动机 🌳

在本节中,我们将探讨决策树学习中的一个重要概念——修剪。我们将了解为什么简单的“提前停止”策略可能导致次优的决策树,以及修剪如何作为一种更稳健的替代方案来解决这些问题。

上一节我们介绍了决策树构建中的递归和提前停止条件。本节中,我们来看看这些停止条件可能带来的挑战。
提前停止条件的挑战
以下是两种主要的提前停止条件及其潜在问题:
-
最大深度停止条件:当递归达到预设的最大深度时停止。
- 挑战:如何选择合适的最⼤深度?通常需要使用交叉验证或验证集,但这需要预留数据、多次运行算法,并且为树的不同部分设置统一的深度参数可能过于僵化。
-
训练误差停止条件:当训练误差停止下降时停止。
- 挑战:这个条件可能很危险,因为它可能过早地停止探索,错过后续能显著降低误差的分支。我们用一个反例来说明。
一个关键的反例:异或问题
为了说明第二个停止条件的危险性,我们使用一个经典的反例:异或问题。
假设我们有以下数据集,其中输出 Y 是输入 X1 和 X2 的异或结果:
| X1 | X2 | Y |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
在根节点:我们有两个 Y=1 和两个 Y=0。如果我们预测多数类(例如 Y=1),我们会犯两个错误。训练误差为 2/4 = 0.5。
尝试在 X1 上分裂:分裂后,每个子节点仍然包含一个 Y=1 和一个 Y=0。如果我们继续在每个子节点预测 Y=1,总错误数仍然是2个,训练误差保持 0.5。分裂没有带来改进。
尝试在 X2 上分裂:情况完全相同,训练误差仍为 0.5。
如果应用“训练误差停止条件”,算法会认为任何分裂都无法降低误差,从而在根节点就停止,最终得到一个训练误差为 0.5 的单一节点树。
然而,如果我们不停止并继续分裂,最终可以得到一棵完美的决策树(例如,先按X1分裂,再在每个分支上按X2分裂),其训练误差为 0。
这个例子展示了“训练误差停止条件”可能导致巨大的性能差距:在最佳可能结果(误差0)和实际得到的结果(误差0.5)之间。
引入修剪
正是由于上述“提前停止”策略的局限性,修剪成为了决策树算法中防止过拟合的更佳方法。
修剪的核心思想是:
- 首先,让树充分生长(甚至过度生长),而不施加严格的提前停止限制。
- 然后,自底向上地检查并“剪掉”那些对提升模型泛化能力贡献不大(甚至可能有害)的子树,将其替换为叶节点。
这种方法比简单的自上而下提前停止更稳健,因为它基于更全面的信息(整个子树的表现)来做决策。

本节课中我们一起学习了决策树构建中“提前停止”策略的缺陷,特别是通过异或问题看到了它如何导致次优模型。我们由此引入了修剪的概念,它通过先过度生长再自底向上剪枝的策略,为构建泛化能力更强的决策树提供了一条更可靠的路径。大多数优秀的决策树实现都会采用某种形式的修剪。
机器学习(分类,聚类和检索):第3-4课:可选:修剪决策树以避免过拟合 🌳

在本节课中,我们将要学习一种避免决策树过拟合的新方法:先让树完全生长,然后再进行“修剪”。我们将探讨如何通过平衡模型在训练数据上的表现与模型本身的复杂度,来获得泛化能力更强的决策树。
上一节我们介绍了通过提前停止递归来寻找简单决策树的方法。本节中我们来看看另一种互补的方法:先扩展,后修剪。

从复杂树到简单树

我们的目标是处理那些因递归过深而变得过于复杂的决策树。我们将学习如何通过“修剪”来移除部分结构,从而简化树,以期获得在真实误差上表现更好的模型。
下图是一个动机示例。如果不提前停止,你可能会得到一棵非常复杂的树。我们可以想象一些巧妙的方法来提前停止,但有时我们还是会走得太远。这时,我们就需要回溯。
我们将从这棵复杂的树开始,逐步简化它,直到得到一棵虽然训练误差可能更高,但真实误差更优的合理决策树。

如何衡量树的复杂度?
一个根本的问题是:什么使一棵树更简单?显然,左边非常深的树比右边浅的树更复杂。深度似乎是一个直观的指标。
然而,深度并不是一个很好的度量标准。核心问题在于,有些特征可能比其他特征拥有更多的取值,从而导致更多的分支。在下图中,两棵树深度相同。
那么,哪一棵更简单呢?直观上,叶子节点越多,树就越复杂。因此,我们引入函数 L(T) 来度量一棵树的叶子节点数量。
左边这棵树有5个叶子节点,右边这棵树有2个叶子节点。因此,我们说右边的树更简单。




在拟合与复杂度之间权衡
现在我们可以开始讨论不同决策树的复杂度了。例如,左边超级复杂的树有6个叶子节点,而右边过于简单的树只有1个叶子节点。我们的目标是找到一个介于两者之间的解决方案。
这个折中的方案允许在某些分支上更深,在另一些分支上更浅,但同时尽可能控制叶子节点的数量。就像机器学习中的其他领域一样,我们将在这两个概念之间引入一种权衡。




我们需要权衡的两个量是:模型对数据的拟合程度 和 模型本身的复杂度。
总成本将是拟合度量与复杂度度量的组合。我们在回归、逻辑回归中都见过这种思想,现在在决策树中再次应用。这里的拟合度量就是训练数据上的分类错误率(训练误差),而复杂度度量则是叶子节点的数量。我们将平衡这两者。
更具体地说:
- 我们用 error(T) 表示树 T 在训练数据上的分类错误。
- 用 L(T) 表示树 T 的叶子节点数量。
我们将使用一个神奇的参数 λ 来在这两个量之间进行权衡。这个参数可以通过验证集或交叉验证来调整。
- 当 λ = 0 时,我们回到标准的决策树学习过程,不惩罚复杂度。
- 当 λ → ∞ 时,复杂度惩罚无限大,我们将只学习一棵没有任何决策的树,即只有一个根节点,直接输出数据中的多数类。
当 λ 取中间值时,才是我们发挥的舞台。它将平衡拟合优度与树的复杂度。
具体来说,我们将通过一种基于以下函数的修剪方法,从复杂树过渡到简单树:
总成本 = error(T) + λ × L(T)






本节课中我们一起学习了决策树的后剪枝方法。我们认识到,叶子节点数量是衡量树复杂度的有效指标。通过引入一个权衡参数 λ,并构建总成本函数 error(T) + λ × L(T),我们可以在模型对训练数据的拟合程度与模型复杂度之间取得平衡,从而有效避免过拟合,提升模型的泛化能力。
机器学习(分类,聚类和检索):3-4:可选:树修剪算法 🌳

在本节课中,我们将要学习决策树模型中的一个重要技术——树修剪算法。该算法旨在通过移除决策树中不重要的分支来防止模型过拟合,从而提升其泛化能力。
上一节我们介绍了决策树的构建与成本函数,本节中我们来看看如何利用成本函数对已生成的决策树进行修剪。
修剪的基本思想 ✂️
修剪过程的核心思想相当简单。它利用我们之前描述的成本函数,来评估并“剪掉”决策树中那些不重要的决策。通常,我们从树的底部开始进行修剪。
考虑决策树中的一个分裂点。例如,在根据“信用”和“收入”进行分裂后,我们是否还应该根据“期限”进行分裂?我们可以使用成本函数来决定。
假设包含所有分裂的完整树在训练数据上的错误率为 0.25。这棵树有 6 个叶子节点。如果我们设置正则化参数 λ = 0.3,那么总成本为:
总成本 = 错误率 + λ × 叶子节点数 = 0.25 + 0.3 × 6 = 0.43
现在,让我们看看如果对这个底部分支进行修剪会发生什么。修剪后,树变小了,训练错误率可能会略微上升,例如升至 0.26。但此时叶子节点数减少为 5 个。新的总成本为:
总成本 = 0.26 + 0.3 × 5 = 0.41
虽然训练错误率略有增加,但由于模型复杂度(叶子节点数)降低,总成本反而从 0.43 下降到了 0.41。因此,根据成本函数,这个更小的树是更优的选择,我们将执行这次修剪。
这个简单的例子展示了修剪如何权衡模型复杂度和拟合精度。在实际应用中,面对拥有海量数据和复杂分支的大树,修剪是防止严重过拟合的关键步骤。
系统的修剪过程 🔄
我们不会只对树底部的某一个分裂点进行评估。修剪过程是系统性的。
以下是针对树底部的修剪步骤:
- 从决策树的最底层开始。
- 对每一个候选分裂点,计算修剪前与修剪后的总成本。
- 如果修剪后的总成本更低,则执行修剪。

但这还不够。我们不会就此停止。

我们将沿着树向上回溯,重新审视树中引入的每一个决策分裂点,并评估是否值得将其修剪掉。
例如,我们会依次检查:
- 在“信用”分裂之后,修剪“收入”分裂是否值得?
- 在“信用”分裂之后,修剪“期限”分裂是否值得?
- 甚至,修剪“信用”分裂本身,只保留根节点是否值得?
我们会检查所有这些可能性,并在整个修剪过程结束后,找到成本最低的那棵树,并将其作为我们的最终模型输出。
完整的剪枝决策树算法 📝
为了内容的完整性,这里提供了使用剪枝构建决策树的完整算法参考。它比基础版本稍显复杂,我将其留作参考资料,供那些希望自己实现的人使用。
该算法的实现相对简单,与常规决策树构建方法没有本质不同。然而,这种通过成本函数进行剪枝的核心思想是基础性的,几乎被所有决策树学习方法所采用,尽管在参数和细节上可能有细微的变化和调整,但总体思路是一致的。


本节课中我们一起学习了决策树的修剪算法。我们了解到,修剪通过一个结合了训练误差和模型复杂度(叶子节点数)的成本函数,系统地移除不重要的分支,从而在不过度拟合训练数据的前提下找到更简洁、泛化能力更强的树模型。这是一个防止决策树过拟合的核心技术。
机器学习(分类,聚类和检索):第3-4课:决策树中过拟合和正则化的回顾 🌳

在本节课中,我们将要学习决策树模型中的一个核心挑战——过拟合,并回顾两种用于解决此问题的正则化技术:提前停止和剪枝。我们将详细探讨这两种方法的基本思想及其重要性。
正如我们所见,决策树过拟合是一个必须解决的根本问题。我们已经探讨了两种不同的方法来解决这个问题。
上一节我们介绍了决策树的基本概念,本节中我们来看看如何控制其复杂度以避免过拟合。
应对过拟合的方法

以下是两种主要的正则化策略:
-
提前停止
在向下构建树的过程中,我们会提前停止生长,以避免生成非常复杂的树从而导致过拟合。 -
剪枝
我们先构建一个庞大的树,然后通过“剪、剪、剪”来简化它。
剪枝在实际应用中非常重要,因此我们花了相当多的时间来详细讨论它。虽然在讲座中这是一个可选部分,但我想确保大家都明白,如果你在决策树算法中看到剪枝操作,那执行的就是这种思想。
所以,关于决策树的过拟合,这是一个基础主题,但现在我们已经掌握了如何应对它。


最后,我要感谢我的同事 Krishna Shriar,他在创建这些幻灯片和使本次讲座尽可能出色方面起到了根本性的作用。

本节课中我们一起学习了决策树中的过拟合问题,并回顾了通过提前停止和剪枝进行正则化的两种核心方法。掌握这些技术对于构建泛化能力更强的决策树模型至关重要。
机器学习:第3-4课:缺失数据的挑战

在本节课中,我们将要学习如何处理机器学习中一个非常常见且棘手的问题:缺失数据。我们将探讨缺失数据对模型训练和预测的影响,并介绍一些基本的应对策略。为了更具体地理解这些概念,我们将以决策树算法为例进行说明。
缺失数据的影响
到目前为止,我们讨论的数据看起来都非常“完美”。我们有时会进行一些特征工程,例如将文本转换为词袋模型、计算词频-逆文档频率,或者创建更高级的特征,如多项式、正弦和余弦等。我们进行了特征转换和特征工程,但我们总是假设能够观察到所有数据。也就是说,对于每个数据点的每个特征,我们都能获得其值。
然而,这在现实世界中很少成立。现实世界的数据往往非常混乱,经常充满缺失值和未观测到的值。这是一个我们必须时刻警惕的重要问题。
以决策树为例
处理缺失数据的方法最好在特定学习算法的背景下理解。因此,在本模块中,我们将选择决策树作为例子,以便更清楚地看到缺失数据的影响以及处理它的关键方法。
我们将继续使用贷款数据。输入 X_i 包括贷款期限、信用历史等特征。我们将数据输入到一个复杂的决策树中,试图做出决定:你的贷款是安全的还是高风险的,这将是输出 Y_hat_i。
正如我们之前讨论的,到目前为止我们假设所有数据都被完整观测到,没有任何缺失。因此,对于数据的每一行,我们都能观测到每个特征的值,例如信用是优秀、一般还是差,贷款期限是三年还是五年,收入是高还是低。当然,我们也能观测到输出:安全或高风险。
但在现实中,数据可能存在缺失。例如,在下图高亮的行中,我们可能知道对于这个特定的贷款申请,信用是差的,收入是高,并且最终被证明是高风险的贷款。但是,没有人输入这笔贷款是三年期还是五年期。这种情况可能发生在多个数据点上。问题在于:我们能为此做些什么?它会对我们的学习算法产生什么影响?
训练与预测阶段的影响
缺失数据既会影响我们模型的训练阶段,也会影响预测阶段。
- 训练阶段:当训练数据中存在问号(缺失值)时,我不知道该如何训练模型,因为我不知道那些缺失的值应该是什么。
- 预测阶段:假设我构建了一个很棒的决策树模型并投入使用。当银行输入一个新的申请时,如果某个条目缺失,我们该如何进行预测?
让我们更具体一些。假设我们有一个从数据中学到的决策树,现在有一个特定的输入:信用是差的,贷款期限是五年,但收入是一个问号(未知)。我试图沿着决策树向下走。首先遇到“信用”节点,信用是差的,我通过了。接着遇到“收入”节点,但收入是未知的。我该怎么办?
核心问题定义
我们面临的学习问题是:我们有一些训练数据,研究了一些特征,并将其输入到机器学习模型中。模型使用一个质量度量(如信息增益)来学习一个决策树 T(x)。但现在我们处于一个数据可能在训练时缺失,也可能在预测时缺失的环境中。
我们需要做的是,稍微修改我们的机器学习模型(在这里是决策树模型),使其能够处理这种缺失数据。
处理缺失数据的方法
以下是几种处理缺失数据的基本方法。
1. 丢弃缺失值
最直接的方法是直接丢弃包含任何缺失值的数据行。
优点:
- 实现简单。
- 如果缺失数据是随机且少量的,这可能是一个合理的起点。
缺点:
- 会损失大量信息,尤其是当许多行都有缺失值时。
- 如果数据缺失不是随机的(例如,高收入人群更不愿意报告收入),丢弃数据会导致样本偏差。
2. 填补缺失值
另一种常见的方法是使用一个合理的估计值来填补(或“填充”)缺失值。
常用填补策略:
- 对于数值特征:使用均值、中位数或众数进行填补。
- 公式示例:
缺失值 = 特征列的均值
- 公式示例:
- 对于分类特征:使用众数(最常见的类别)进行填补。
- 更高级的方法:使用其他特征来预测缺失值(例如,用回归或K近邻模型)。
优点:
- 保留了所有数据行,利用了所有可用信息。
缺点:
- 填补的值可能不准确,从而在数据中引入噪声或偏差。
- 如果填补方法不当,可能会扭曲特征之间的关系。
3. 修改算法以处理缺失值
对于像决策树这样的算法,我们可以修改其分裂规则,使其能够处理缺失值。
具体策略:
- 在训练时:计算信息增益时,可以忽略缺失值,或者将缺失值视为一个单独的类别/分支。
- 在预测时:当遇到缺失特征时,可以让数据同时流向所有子节点,并根据每个子节点接收到的训练样本权重来加权最终的预测结果。
优点:
- 算法本身具备了处理缺失数据的能力,无需在预处理阶段进行填补或丢弃。
缺点:
- 实现起来更复杂。
- 可能不适用于所有类型的机器学习算法。
总结
在本节课中,我们一起学习了机器学习中缺失数据带来的挑战。我们了解到,现实世界的数据很少是完整的,缺失值会影响模型的训练和预测。我们介绍了三种主要的应对策略:
- 丢弃缺失值:简单但可能造成信息损失和偏差。
- 填补缺失值:保留数据但可能引入噪声,常用均值、众数或更复杂的模型进行填补。
- 修改算法:使学习算法(如决策树)能够原生处理缺失值,这通常是最优雅但实现较复杂的方法。

选择哪种方法取决于具体的数据情况、缺失机制以及所使用的机器学习算法。理解这些基本概念是构建健壮机器学习模型的重要一步。
机器学习:分类、聚类与检索:3-4:策略1:通过跳过缺失数据进行纯化

在本节课中,我们将要学习处理数据集中缺失值的一种基本策略:纯化,即通过跳过包含缺失值的数据点或特征来清理数据。

上一节我们介绍了缺失数据带来的挑战,本节中我们来看看最直接的处理方法。
概述:什么是纯化?
纯化是指从数据集中移除包含缺失值的部分,最终得到一个所有特征值都被观测到的“纯净”数据集。其核心思想是:从包含某些缺失特征值的数据点出发,通过跳过这些缺失值,得到一个输出为 H(x) 的完整数据集。
两种基本的跳过策略
以下是两种处理缺失数据的基本跳过方法。
1. 跳过包含缺失值的数据点
这是最直观的做法。如果数据集中只有少数数据点存在缺失值,直接移除这些数据点可能是可以接受的。
例如,假设有9个数据点,其中3个存在缺失值。我们可以直接跳过这3个数据点,将数据集从9个减少到6个。
潜在问题:如果某个特征在大量数据点中缺失,这种方法会导致数据集严重缩水。例如,若“期限”特征在9个数据点中的6个里缺失,跳过这些点将使数据集从9个骤减至3个,这会导致用于训练的数据量大幅减少,严重影响模型性能。
2. 跳过包含缺失值的特征
当某个特定特征存在大量缺失值时,另一种简单的策略是跳过整个特征。这样,数据点的数量保持不变,但特征数量减少了。
在上述例子中,与其因“期限”特征缺失而丢弃6个数据点,不如直接移除“期限”这个特征,保留全部9个数据点。
策略选择与挑战
在实际操作中,需要决定是跳过数据点、跳过特征,还是对不同的情况采取不同的跳过组合。这是一个复杂的决策过程。
总的来说,跳过策略(纯化)的优点在于:
- 简单易行:直接简化数据集。
- 通用性强:可应用于任何机器学习算法,因为输入的是一个已处理好的完整数据集。
然而,这种方法也存在一些挑战:
- 数据损失:移除数据点或特征总是痛苦的,因为数据本身具有价值。
- 决策困难:通常不清楚应该移除特征还是数据点,以及不同选择对最终结果的影响。
- 无法处理预测时的缺失:最根本的问题是,这种方法无法处理预测时新数据出现缺失值的情况。训练时我们可以跳过,但当一个新样本带有问号“?”时,此策略无法提供解决方案。
总结


本节课中我们一起学习了处理缺失数据的纯化策略。我们了解到,可以通过跳过包含缺失值的数据点或跳过包含缺失值的特征来清理数据集。虽然这种方法简单通用,但它会导致数据损失,且无法解决预测阶段遇到缺失值的问题。因此,尽管在实践中常见,但需谨慎使用,尤其是在缺失情况严重时。下一节,我们将探讨一种能够更智能地处理缺失数据的决策树改进算法。
机器学习(分类,聚类和检索):3-4:策略2:通过填补缺失数据进行纯化 🧩


在本节课中,我们将要学习处理缺失数据的第二种核心策略:填补。我们将探讨其基本思想、简单实现方法、优缺点,并理解为何在使用时需要格外谨慎。
上一节我们介绍了直接删除含有缺失值的数据行的方法。本节中我们来看看另一种思路:填补。
处理缺失数据的第二种方法是通过所谓的“填补”进行数据纯化。填补是指用某种最佳猜测来填充缺失值(即问号),以推测可能发生的情况。
我个人不喜欢丢弃数据。当数据从九行减少到六行时,会让我感到不适。我认为这不是一个好主意。填补是另一种选择,它意味着我们不去掉那些问号,而是尝试猜测问号可能的值并填充进去。
以下是填补方法的工作流程:你获取可能含有缺失值的输入数据,用最佳猜测填充这些缺失值,从而得到一个所有值都已填充完整的数据集。
例如,在这个九行的数据集中,有三个问号。我们可以说,这三个问号对应的“贷款期限”未知,我将用我的最佳猜测来填充这些值,这里我选择填充为“3年期贷款”。
我为什么选择“3年期贷款”来填充?如果你查看原始数据集,有四个“3年期贷款”和两个“5年期贷款”,所以“3年期”是我的最佳猜测。你可以将其视为最简单的猜测。我采用了一个简单的方法:无论哪个值最常出现,就填充它。
以下是填补在简单方法中的实现规则:
- 对于分类数据(如“优秀”、“一般”、“差”,或“3年期”、“5年期”),只需填入最常出现的值,这称为分布的众数。
- 对于数值数据,我建议你填入平均值或中位数。
这些只是简单的启发式方法。实际上,存在许多更高级、更有趣的填补缺失值的方法,例如期望最大化算法,它是一种以非常有趣的方式完成此任务的算法。


现在我们已经描述了填补的基本概念。接下来,让我们总结一下通过填补处理缺失数据的优缺点。
优点如下:
- 易于理解和实现。
- 可应用于任何模型,因为在你填充数据后,只需将其输入到你已有的机器学习算法中即可,无需修改算法本身。
- 可在预测时使用,因为每当遇到问号,你都可以用与训练数据相同的方式填充它。例如,如果“贷款期限”是问号,就像在训练数据中那样填充为“3年期贷款”。
然而,像这样的填补,尤其是我们描述的简单填补,也可能带来极大的问题,因为它会引入偏差。
我们为每一个“贷款期限”的问号都填入了“3年期”。我们没有使用任何其他信息,而是插入了相同的值,这可能导致严重的系统性错误。
让我们退一步举个例子。我住在美国华盛顿州。假设在华盛顿州,将年龄写入贷款申请是非法的。这意味着,如果贷款申请来自华盛顿州,年龄将始终是一个问号;而在其他州,年龄可能不是问号。但在这里,年龄始终是问号。
如果你在美国全国范围内训练一个模型,所有来自华盛顿州的人的年龄都是问号。你将会把平均年龄(假设是40岁)填入申请中。然后,你就会认为华盛顿州所有申请贷款的人都是40岁。这将在华盛顿州的贷款申请中引入系统性偏差,并导致各种奇怪的行为、不满的用户、糟糕的预测,这是一个坏主意。
因此,像这样的填补有其优点,但它也是一个复杂的概念,因为它可能引入可怕的偏差。
在本模块的第三部分,我们将讨论一种替代方法,它可以解决前两种方法所面临的一些挑战。


本节课中我们一起学习了处理缺失数据的第二种策略——填补。我们了解到,填补通过用最佳猜测(如众数、均值)填充缺失值来保留所有数据,具有易于实现、通用性强等优点。但我们也必须警惕,简单的填补方法可能会在数据中引入系统性偏差,从而影响模型的公正性和准确性。理解这些权衡对于在实际应用中正确选择数据处理方法至关重要。
机器学习(分类,聚类和检索):第3-4课:修改决策树以处理缺失数据 📊

在本节课中,我们将学习如何处理机器学习中一个常见且棘手的问题——缺失数据。我们将重点探讨如何通过修改决策树算法本身,使其能够直接适应并处理数据缺失的情况,从而构建出对缺失数据具有鲁棒性的模型。

上一节我们介绍了缺失数据带来的挑战,本节中我们来看看如何让算法本身学会处理缺失值。
处理缺失数据的最佳方法 💡
处理缺失数据的最佳方法是使你的机器学习算法对缺失数据具有鲁棒性。换句话说,就是让机器学习算法能够适应缺失数据。这正是我们在这个特定模块中要做的事情。我们将在决策树的背景下进行,因为对决策树进行一个简单的修改,就能处理缺失数据。
决策树如何处理缺失值? 🌳
为了更好地理解如何在决策树中处理缺失数据,让我们看一个简单的例子。假设有一个输入样本,其“信用”为“差”,而“收入”未知。在决策树中,我们首先根据“信用=差”选择分支,然后到达“收入”判断节点,但“收入”值是未知的。此时我们该怎么办?
我们将采取的方法是:为未知数据指定一个要遵循的分支。当值未知时,我们明确决定它应该走哪条路。在这个例子中,我们可以将所有未知的“收入”数据都关联到“收入=低”这个分支。因此,如果你的收入未知,就走“低”分支,然后预测这笔贷款是“有风险”的。
在决策树中明确处理未知值 🔍
在修改后的决策树中,我们将明确决定问号或缺失值、未知值应该去向何处。我们引入了在决策树的这一点遇到未知值时的处理规则。但我们可能在决策树的任何一点遇到未知值,因此我们需要在所有地方都做出决定,规定当看到未知值时应该发生什么。
以下是具体的实施思路:
对于每一个决策节点,我们都需要选择它的一个分支来“接收”未知值。请注意,这些将是我们需要做出的、与决策树中每一个菱形决策节点相关联的具体决定。
例如:
- 对于“信用”节点,我们可以让未知值进入“一般”分支。
- 对于“收入”节点(在“信用=差”的前提下),我们可以让未知值进入“低”分支。
- 对于“期限”节点(在“信用=差”且“收入=高”的前提下),我们可以让未知值进入“5年”分支。
然而,关键点在于:我们在决策树不同部分为未知值所做的决定不必相同。例如,在“信用=一般”时查看“期限”,我们可能决定让未知值进入“3年”分支。这就是我们所描述方法的美妙之处——就像我们优化决策树的结构一样,我们也将优化未知值的去向,以最小化分类错误。
修改后决策树的预测过程 🚀
现在,如果我们学习了这样一棵树,并收到一个输入(例如,信用未知、收入高、期限5年),我们可以遍历这棵树进行预测:信用未知,根据规则走指定分支;期限是5年,最终预测为“安全”贷款。
同样,对于另一个输入(信用差、收入高、期限未知),我们会进入决策树的不同分支:信用差 -> 收入高 -> 期限未知(根据规则,等同于5年期贷款),再次预测为“安全”。


方法的优势与局限 ⚖️
总的来说,在算法本身中明确处理缺失数据的方法非常有用。它可以帮助解决训练时和预测时的缺失数据问题,通常能做出更准确的预测。我们刚刚讨论的就是决策树中的一个例子。
然而,这种方法的缺点是需要你修改实际的学习算法来处理缺失数据。对于决策树,我将描述一种可以实现这一点的简单修改。但对于其他算法,这可能非常复杂。即使对于决策树,要使其效果非常好,也可能比我们接下来要讨论的更复杂。但这里的基本思想至关重要。
总结 📝


本节课中,我们一起学习了如何通过修改决策树算法来处理缺失数据。核心思想是:在构建决策树的每个决策节点时,不仅优化基于已知特征的分支规则,同时优化一个额外的规则,即当该特征值缺失(未知)时,样本应该被分配到哪个分支。这种方法通过让算法主动适应数据的不完整性,增强了模型的鲁棒性,是处理缺失数据的一种有效策略。
机器学习(分类,聚类和检索):第3-4课:有缺失数据时的特征分割选择

在本节课中,我们将学习决策树算法如何处理数据集中存在缺失值的情况。核心在于修改特征选择过程,使其同时决定如何处理缺失数据。
🎯 核心算法修改
决策树算法的核心是选择用于分割的特征。我们将修改此处,使其也能决定遇到缺失数据时如何处理。
决策树学习中最重要的问题是确定使用哪个特征进行分割。现在,当我们考虑选择哪个特征时,不仅要决定分割特征,还要决定当遇到缺失值时,数据应流向哪个分支。
从概念上讲,这只是对上一模块描述的算法进行一个非常简单的修改。但现在,我们需要进行额外的搜索,以确定缺失数据的去向。
🌳 决策树中的缺失数据处理
与贪婪学习决策树一样,我们可以专注于学习一个决策树来理解这里的情况。
例如,我们选择按“信用”特征进行分割。信用等级可以是“优秀”、“一般”或“差”。右侧的分支是所有信用等级为“差”的数据点。
现在,我们可能决定将缺失数据放入该分支。因此,我们将把所有缺失数据(以及“一般”信用等级的数据)送入该特定节点。
对于分类数据,处理方式类似。
对于数值数据,我们将使用上一模块讨论的阈值分割法。例如,我们可能以5万美元为阈值分割“收入”特征。我们可能决定将缺失或收入未知的数据,送入收入低于5万美元的那个节点。
这就是我们将在学习算法内部尝试做出的决策。


🔍 如何决定缺失数据的去向
我们必须决定缺失数据的去向。假设我们考虑按“信用”特征分割。如果考虑按“信用”分割,我们应该如何处理缺失数据?应该将其放入信用“优秀”的分支,还是“一般”的分支,或是“差”的分支?
我们不知道哪个最好,但我们有一个处理原则。该原则是:选择能导致最低分类错误率的分支,就像我们之前所做的那样。
让我们通过一个例子来说明。假设我们考虑按“信用”分割,并考虑将缺失数据分配给信用“优秀”的分支。
在这个例子中,我们有3个数据点缺失数据。我们考虑将这3个数据点分配到信用“优秀”的分支。
我们有两种数据:已观测数据和缺失数据。
- 在“优秀”分支中,已观测数据有9个安全贷款和0个风险贷款。
- 在“一般”分支中,有8个安全贷款和4个风险贷款。
- 在“差”分支中,有4个安全贷款和12个风险贷款。
现在,我们有这3个额外的缺失数据点,其中包含2个风险贷款和1个安全贷款。我们正考虑将这2个风险和1个安全贷款加入“优秀”分支。
因此,“优秀”分支的总计变为:10个安全贷款和2个风险贷款。其他两个分支的总计保持不变,因为没有新数据加入。
那么,结果决策树的总体错误率是多少?
- 对于“优秀”分支,我们将预测为“安全”,因此会犯2个错误。
- 对于“一般”分支,我们将预测为“安全”,因此会犯4个错误。
- 对于“差”分支,我们将预测为“风险”,因此会犯4个错误。
总体我们将犯10个错误,总数据点是40个。因此,总错误率是 10 / 40 = 0.25。
我们对每个选项、每个分支都进行同样的计算。
- 如果尝试将未知数据放入“优秀”分支,得到错误率0.25。
- 如果尝试放入“一般”分支,同样得到错误率0.25。
- 如果尝试放入“差”分支,我们得到错误率0.225。

0.225是更低的错误率,因此这是最优选择。所以,最好的做法是将未知数据分配给信用“差”的分支。这恰好与我们之前展示的树中所做的完全一致。

📝 算法总结
这是为考虑缺失数据而对树分割算法进行的修改。虽然描述起来有点复杂,但其核心思想很简单。

总结一下,本节课我们一起学习了如何在决策树学习中处理缺失数据。关键在于将缺失数据的处理嵌入到学习算法本身中。具体做法是,在选择最佳分割特征时,同时评估将缺失数据分配到每个可能分支所带来的分类错误率,并选择能使总体错误率最低的分配方式。这种方法可以提升模型的整体性能。
机器学习(分类,聚类和检索):第3-4课:处理缺失数据的回顾

在本节课中,我们将要学习一个非常基础且重要的概念:如何处理数据集中的缺失值。缺失数据不仅会影响模型的训练过程,也会影响最终的预测结果。我们将探讨几种适用于多种算法的通用处理思路,而不仅仅是决策树。
缺失数据的影响
缺失数据是一个普遍存在的问题,它可能在模型训练时和后续进行预测时都对我们造成影响。对于这两种情况,我们都需要有相应的处理策略。
上一节我们介绍了缺失数据带来的挑战,本节中我们来看看几种基础的应对方法。这些核心思路具有广泛的适用性。
处理缺失数据的基本方法
以下是三种处理缺失数据的基础方法:

-
直接忽略
这种方法直接跳过包含缺失值的数据点。其优点是实现简单,但缺点是可能会丢失大量信息,特别是当缺失情况不是随机发生时,会导致模型产生偏差。 -
数据填补
这种方法试图估算或猜测缺失值是什么。常见的填补方式包括使用特征的平均值、中位数或众数,或者使用更复杂的模型进行预测。填补可以保留数据量,但填补的值可能不准确,从而引入噪声。 -
修改学习算法
这种方法通过调整算法本身来适应缺失数据。以决策树为例,我们可以修改其分裂规则,使其能够处理缺失值。例如,在计算信息增益时,可以按比例将缺失值样本分配到不同的子节点中。
实践中的注意事项
在实践中,你会经常遇到缺失数据,因此必须始终保持警惕。有时,缺失值会以“奇怪”的数值形式出现,而不仅仅是明确的空值。
例如,有时人们会用零(0)来表示未知,你可能会误以为它就是零,但实际上它代表的是缺失。因此,你必须仔细检查数据,并谨慎处理缺失值,因为它会严重影响算法结果的准确性。
今天我们学习了一些处理缺失数据的基础方法。当然,还有更高级的技术可以深入探索,但掌握这些基础是至关重要的,你应该在每次分析中都留意数据缺失的问题。
总结
本节课中我们一起学习了处理缺失数据的重要性与基本方法。我们回顾了忽略、填补和修改算法这三种核心策略,并强调了在实践中识别与谨慎处理缺失值的必要性。这是构建可靠机器学习模型的基础一步。

最后,再次感谢我的同事Krishna Sriar,他在本模块幻灯片的制作和整体构思中提供了至关重要的帮助。
机器学习(分类,聚类和检索):第3-4课:提升问题

概述
在本节课中,我们将要学习一种名为“提升”的机器学习技巧。提升方法能够将多个性能一般的“弱”分类器组合起来,形成一个性能更强的分类器。我们将探讨其背后的直观思想、核心算法及其在现实世界中的巨大影响力。
我们已经学习了像逻辑回归这样的线性分类器,也学习了决策树这种构建分类器以拟合数据的好方法。现在,在这个模块中,我们将讨论一种名为“提升”的方法。这是一种在机器学习中非常神奇的技巧,它可以应用于任何分类器。提升方法通过组合多个分类器,来提高其质量、数据拟合度或降低其错误率,使其变得越来越好。我们今天要讨论的方法对机器学习领域产生了惊人的影响。它相当简单,虽然涉及一点数学,但并不复杂,易于实现,并且当您处理现实世界数据时,它将带来巨大的改变。
从弱分类器到强分类器
我们可以直观地理解提升:我们从所谓的“弱分类器”开始工作。这些可以是简单的逻辑回归模型、浅层决策树,甚至可能是决策树桩。问题是,对于这些简单的或弱分类器,我们能说些什么?它们有一些好的特性:方差低,因此它们往往不会过拟合,这很棒。然而,它们往往有较高的偏差,所以它们不能很好地拟合数据。因此,决策树桩不太可能给你非常高的准确度。
如果你查看与此类模型相关的学习曲线,比如说逻辑回归模型,如果你从一个非常简单的弱分类器开始,你对数据的拟合度不会很好,所以训练误差很高。然而,随着你添加越来越多的特征,训练误差会越来越低。但正如我们所知,真实误差会先下降,然后在你开始过拟合时上升。我们的目标是在偏差和方差之间找到这种最优的权衡。
我们知道弱分类器很好,因为它们方差低。但为了获得高质量、低测试误差的结果,我们需要一些更强的东西。根本问题是:我们如何做到这一点?我们如何从弱分类器过渡到具有更低错误率的东西?
一种方法是添加更多特征。例如,如果我们在逻辑回归中使用多项式特征,我们可以添加二阶多项式、三阶多项式、四阶多项式等等,同时试图避免过拟合。在决策树中,我们可以让决策树越来越深。
但提升方法中的根本问题是:我们是否可以做些别的事情来帮助改进我们的分类器?是否有什么方法可以接受这个弱分类器并将其变成一个更强的分类器?
提升思想的起源与影响
这个提升的想法始于一个美妙的数学猜想。这是莱斯利·瓦利安特在1988年提出的一个问题。问题是:我们能否获取弱分类器,比如说决策树桩,并以某种投票方案将它们组合起来,从而从中得到一个更强的分类器?
令人惊讶的是,罗伯特·沙皮尔等人在仅仅一两年后就提出了一种名为“提升”的算法,真正证明了这是可能的。这个算法彻底改变了整个机器学习领域。事实上,它对整个领域产生了惊人的影响。它是许多计算机视觉任务的默认方法,也是当今工业界部署的许多系统的基础。例如,当你在搜索引擎上搜索某些内容时,决定显示什么搜索结果或显示什么广告的系统。因此,提升方法产生了巨大的影响,它是在许多机器学习竞赛中获胜的技术。有一家名为Kaggle的公司举办了许多这类竞赛,提升方法赢得了其中超过一半的比赛。所以,这是一种非常令人兴奋且非常有用的机器学习方法。


总结
本节课中,我们一起学习了提升方法的基本概念。我们了解到,提升是一种通过组合多个简单的“弱”分类器来构建一个强大分类器的技术。它巧妙地平衡了偏差与方差,从而显著提高了模型的性能。这种方法不仅在理论上优美,而且在实际应用和竞赛中都被证明极其有效,是机器学习工具箱中一个不可或缺的强大工具。
机器学习:第3-4课:集成分类器与提升法

在本节课中,我们将要学习集成分类器的核心概念,特别是提升法的基本思想。我们将了解如何组合多个简单的“弱”分类器来构建一个更强大的预测模型。

集成分类器的核心思想
上一节我们介绍了决策树桩等简单分类器。本节中我们来看看如何将它们组合起来。
提升法的核心是集成分类器的思想。让我们回顾一下决策树桩的概念。一个决策树桩将数据作为输入,并可能查看某个特定特征,例如收入。它会判断收入是否大于10万。如果是,则预测贷款安全;如果不是,则预测贷款有风险。因此,这里的输出 y_hat 是 +1 或 -1,取决于我们认为贷款是安全还是有风险。
为了在本模块中表述清晰,我们将使用以下符号:用 f(x) 表示一个简单的弱分类器或泛指的分类器。
提升法并非从一个单一的决策树桩开始,而是将许多这样的分类器组合在一起,以提高预测能力。例如,我们可能有基于收入进行分割的决策树桩,另一个基于信用历史,还有一个基于储蓄金额,再一个基于市场状况。
组合分类器的投票机制
上一节我们提到了多个分类器,本节中我们来看看如何整合它们的“投票”结果。
假设对于一个特定的输入(例如,你的收入是12万),第一个决策树桩 F1 将投票认为贷款安全(+1)。但你的信用记录不良,因此第二个决策树桩 F2 将投票认为有风险(-1)。第三个树桩因为你的储蓄较低,也投票有风险(-1)。第四个树桩由于市场状况良好,投票安全(+1)。提升法提出的问题是:如何以集成的方式组合来自不同分类器 F1 到 F4 的这些 +1 和 -1 投票?


组合的方式是为每个分类器分配权重。这种构建的模型称为集成模型。这里的权重是 W1, W2, W3, W4。我们将每个分类器的输出乘以其权重,然后将它们相加,最后取结果的符号。如果符号为正,则输出 +1;如果符号为负,则输出 -1。这是一种加权投票方案。
加权投票示例
为了更好地理解加权投票,让我们看一个具体的计算例子。
假设每个分类器的权重如右图所示。那么,我们预测的输出将是以下加权和的符号:
sign(W1 * F1(x) + W2 * F2(x) + W3 * F3(x) + W4 * F4(x))
代入具体数值:
W1 = 2.0,F1投票为+1。W2 = 1.5,F2投票为-1。W3 = 1.5,F3投票为-1。W4 = 0.5,F4投票为+1。
计算加权和:
2.0*(+1) + 1.5*(-1) + 1.5*(-1) + 0.5*(+1) = 2.0 - 1.5 - 1.5 + 0.5 = -0.5
取符号:
sign(-0.5) = -1
因此,即使有两个正票和两个负票,并且最重要的分类器(第一个)投了正票,但加权平均后的最终输出 y_hat 是 -1,即预测为有风险的贷款。这是一个集成分类器的简单示例,这种组合方式是工业界用于解决复杂分类问题的常用方法。
形式化定义与类比

为了确保概念清晰,我们形式化地定义这个集成学习问题。
我们有一些数据,其中标签 y 是 +1 或 -1(本模块仅讨论二分类)。我们有输入 x 和数据,这使我们能够学习 T 个弱分类器 F1, F2, ..., FT,以及从数据中学到的系数 Ŵ1, Ŵ2, ..., ŴT。
一旦学会了这些,进行预测就类似于逻辑回归或线性分类器:它只是每个分类器投票的加权和的符号。
公式表示:
F(x) = sign( Ŵ1 * F1(x) + Ŵ2 * F2(x) + ... + ŴT * FT(x) )
如果你观察这个公式,它看起来很像线性分类模型或逻辑回归。然而,关键区别在于:我们不仅从数据中学习权重 Ŵ,实际上我们还学习这些“特征”——即这里的 F,它们是我们将从数据中学习的弱分类器。因此,我们可以将提升法视为一种从数据中学习特征的方法。


本节课中我们一起学习了集成分类器的基本概念,了解了提升法如何通过加权组合多个弱分类器来构建强分类器。我们看到了加权投票的具体计算过程,并将集成模型的形式与线性模型进行了类比,指出了其同时学习特征(弱分类器)和权重的特点。这是解决复杂机器学习问题的强大范式。
机器学习(分类,聚类和检索):第3-4课:提升方法

概述
在本节课中,我们将要学习提升方法。这是一种通过组合多个弱学习器来构建一个强学习器的技术。我们将从提升的基本概念开始,然后深入探讨一个具体的提升算法示例,并解释如何通过加权数据来迭代改进模型。

提升的基本思想
上一节我们介绍了集成模型,本节中我们来看看提升方法。
考虑一个学习问题:我们获取一些数据,学习一个分类器,该分类器给出输出 F(x),我们用它来预测数据,即 Y_hat = sign(F(x))。

如果我们获取一些数据并尝试进行预测,可能会学习一个决策树桩。例如,我们决定按收入进行划分:收入大于100,000和收入小于100,000。我们如何学习实际的预测呢?我们查看数据行:对于收入大于100,000的行,有三笔安全贷款和一笔风险贷款,因此我们预测 Y_hat = 安全。对于收入小于100,000的行,有四笔安全贷款和三笔风险贷款,我们再次预测 安全。两边的预测都是安全。这个决策树桩看起来还行,但在数据上似乎不够好,未能捕捉到我们所需的信息。
提升方法会如何处理呢?它会评估这个决策树桩,查看它在数据上的表现,然后学习下一个决策树桩或分类器。下一个分类器将专注于第一个分类器表现不佳的数据点。
换句话说,这是一个非常重要的点:我们将查看目前犯错误的地方,并增加这些点的影响力或关注度。然后,我们学习另一个分类器来处理犯错误的数据点,接着再学习一个,如此反复。最终,正如我们将看到的,我们会收敛到一个强大的分类器。
加权数据学习
学习我们犯错误的数据点意味着什么?
这意味着我们将为数据集中的每个数据点分配一个权重 α_i。当权重较高时,意味着该数据点更重要。你可以想象一个学习问题,其中数据不仅像本课程迄今为止所做的那样,而且数据还带有与之相关的权重。现在,我们将从加权数据中学习。
从加权数据中学习意味着什么?可以这样理解:α_i 对应于数据点被计数的次数(如果大于1)。例如,如果 α=2,你可以认为该数据点被计数了两次;如果 α=0.5,你可以认为该数据点被计数了半个数据点。但你的学习算法完全保持不变,只是你不再计数数据点,而是计数数据点的权重。
让我们看看在决策树桩方法中会发生什么。我们有了第一个决策树桩,它并不理想,特别是对于收入较低的人群。因此,我们学习了这些权重,在我们犯错误的地方权重更高。现在,我们学习一个新的决策树桩,假设再次按收入划分:大于100,000和小于100,000。
当我们查看对大于100,000的数据所做的分类决策时,我们做的是:对收入大于100,000的风险数据点的权重求和。在这种情况下,我们求和0.5、0.8和0.7,加起来是2.0;对于安全的数据点,权重是1.2。因此,我们将预测 Y_hat = 安全。这是数据点的加权和。
对于收入小于100,000的数据,采用相同的思路。我们遍历数据点,查看风险和安全的数据点,并求和它们的权重。我们看到风险贷款的总权重是6.5,安全贷款的总权重是3.0。因此,我们将预测 Y_hat = 风险。这个决策树桩现在会稍微好一些。然后,我们将这个分类器与之前的分类器以及其他分类器结合起来,直到我们创建出这个集成分类器。
扩展到其他算法
这种从加权数据中学习的想法不仅限于决策树桩。事实上,大多数机器学习算法都接受加权数据。
我将简要地向你展示,如果你在进行逻辑回归并且有加权数据会发生什么。如果你看下面的方程,这正是逻辑回归导数或更新函数的方程,这是你在学习逻辑回归模型时会实现的东西。
现在你可能会说:“哦,我有这些数据权重,我必须从头开始重新实现一切。天啊天啊天啊。”但事实证明这非常简单。如果你看方程的中间部分,我们在这里对数据点求和。现在,我们只需要对数据点求和,并且对每个数据点的贡献进行加权。因此,我们只需在每个求和项中添加权重 α_i,就完成了。
我们现在有了可以从加权数据中学习的逻辑回归。
我们向你展示了两个例子:决策树桩和逻辑回归。但总的来说,从加权数据中学习是相当容易的。
提升作为贪婪算法
提升可以被视为从数据中学习集成模型的一种贪婪算法。
以下是其工作原理的步骤:
- 我们训练第一个分类器,例如 f1(x),来自数据。如果只有 f1(x),你只需预测 sign(f1) 作为你的输出 Y_hat。
- 然后,你通过给犯错误(或 f1 犯错误)的数据点分配更高权重来重新加权你的数据。
- 现在我们运行另一个分类器 f2,并学习每个分类器的系数。
- 如果我们只做两步,我们的预测是 ŵ1 * f1 + ŵ2 * f2,其符号是 Y_hat。
这就是提升的基本思想:不断添加新的分类器,学习权重(抱歉,是优化权重)以专注于更困难的数据点,然后学习不同分类器之间的系数。




总结
本节课中我们一起学习了提升方法。我们了解到提升是一种迭代的集成技术,它通过给先前模型分类错误的数据点增加权重,并训练新的模型来专注于这些困难样本,从而组合多个弱学习器形成一个强学习器。我们探讨了加权数据学习的概念,并看到了如何将其应用于决策树桩和逻辑回归等算法。最后,我们理解了提升可以被视为一种贪婪算法,它逐步构建一个强大的集成分类器。
机器学习:3-4:AdaBoost概述 🚀

在本节课中,我们将要学习一种特定的提升算法——AdaBoost。AdaBoost是早期机器学习中用于提升的算法之一,它极其有用,实现简单,并且效果显著。课程末尾还有一个有趣的拓展任务,但让我们先从AdaBoost开始。


AdaBoost算法流程 📊
上一节我们介绍了提升算法的基本概念,本节中我们来看看AdaBoost的具体步骤。以下是AdaBoost算法的核心流程:
- 初始化权重:为每个数据点分配相同的初始权重。通常设置为
α_i = 1/n,其中n是数据点的总数。这被称为均匀权重初始化,我们稍后会解释为何这样设置更优。 - 迭代训练弱分类器:对于每一轮迭代
t(从1到T):- 在加权数据上学习一个弱分类器
f_t。 - 计算该分类器的系数
ŵ_t。 - 根据分类器的表现,重新计算每个数据点的权重
α_i。
- 在加权数据上学习一个弱分类器
- 组合最终分类器:完成所有迭代后,最终的预测
ŷ是所有弱分类器f_1, f_2, ..., f_T的加权组合的符号。公式表示为:ŷ = sign( Σ_{t=1}^{T} ŵ_t * f_t(x) )。
核心问题与解决方案 ⚙️
在实现AdaBoost时,我们需要解决两个基本问题。
问题一:如何计算分类器系数 ŵ_t?
这个问题关乎我们信任每个弱分类器 f_t 的程度。如果 f_t 表现很好,我们应给予它较高的权重(系数);如果表现很差,则应给予较低的权重。
问题二:如何更新数据点权重 α_i?
这个问题关乎我们如何强调被错误分类的数据点。我们希望增加那些被当前分类器 f_t 错误分类的数据点的权重,以便在下一轮迭代中,后续的分类器能更关注这些“困难”的样本。
在本模块的主要部分,我们将详细讨论如何计算 ŵ_t 以及如何更新 α_i。这些方法相对简单、直观且极其有效。
总结 ✨

本节课中,我们一起学习了AdaBoost算法的基本框架。我们了解了其从初始化均匀权重开始,迭代训练弱分类器、计算系数并更新数据点权重的流程。同时,我们明确了实现AdaBoost需要解决的两个核心问题:分类器系数的计算和数据点权重的更新。在接下来的课程中,我们将深入探讨这些具体问题的解决方案。
机器学习(分类,聚类和检索):第3-4课:加权误差计算与系数更新

在本节课中,我们将学习如何计算加权误差,并理解如何根据分类器在加权数据上的表现来更新其投票权重。这是AdaBoost等集成学习算法的核心步骤。
上一节我们介绍了加权数据的概念,本节中我们来看看如何具体衡量一个分类器在加权数据上的表现,即计算加权误差。
计算加权误差
加权误差的衡量方式与常规误差类似,但每个数据点的贡献由其权重决定。以下是计算加权误差的步骤:
- 计算错误的总权重:遍历所有数据点,如果分类器预测错误,则累加该数据点的权重。
- 计算数据点的总权重:累加所有数据点的权重。
- 计算加权误差:将错误的总权重除以数据点的总权重。
用公式表示如下:
加权误差 (ε) = (Σ (错误的数据点 i 的权重 α_i)) / (Σ (所有数据点 i 的权重 α_i))
其中,Σ 表示求和,范围是 i=1 到 n(n 为数据点总数)。判断是否为错误的指示函数为:1(预测值 y_hat_i ≠ 真实标签 y_i)。
加权误差 ε 的值在 0 到 1 之间。ε = 0 表示完美分类;ε = 1 表示全部预测错误(但此时反转分类器的预测即可得到完美结果);ε = 0.5 类似于随机猜测的表现。
根据加权误差更新分类器权重
现在我们已经了解了加权误差,接下来看看如何利用它来更新第 T 轮学习到的分类器 F_T 的投票权重 W_hat_T。
这个权重的设定非常直观,它反映了我们对分类器 F_T 的信任程度:
- 如果 F_T 表现好(加权误差低),我们希望赋予它较大的权重。
- 如果 F_T 表现差(加权误差高),我们应该降低它的权重,不信任它的投票。
具体更新公式基于加权误差 ε_T 计算:
W_hat_T = 0.5 * ln( (1 - ε_T) / ε_T )
对这个公式的解读如下:
- ε_T 很小(接近0):
(1 - ε_T) / ε_T的值会很大,ln函数的结果为正且较大,因此 W_hat_T 是一个较大的正数。这表示我们非常信任这个准确的分类器。 - ε_T 很大(接近1):
(1 - ε_T) / ε_T的值会很小(接近0),ln函数的结果为负且绝对值较大,因此 W_hat_T 是一个较大的负数。这表示我们不仅不信任它,反而更相信它的反面预测(即反转它的输出)。 - ε_T = 0.5:
(1 - ε_T) / ε_T = 1,ln(1) = 0,因此 W_hat_T = 0。这表示这个分类器如同随机猜测,我们不给予任何权重。
通过这种方式,AdaBoost算法能够自动地为每一轮产生的弱分类器分配合适的权重,最终将所有弱分类器的加权投票组合成一个强大的集成模型。

本节课中我们一起学习了加权误差的计算方法及其在更新分类器投票权重中的应用。理解加权误差是掌握AdaBoost等提升(Boosting)算法如何聚焦于困难样本、并组合弱分类器的关键。下一节,我们将看到如何利用更新后的权重来调整训练数据本身的分布,为下一轮训练做准备。
机器学习(分类,聚类和检索):第3-4课:计算集成学习系数

在本节课中,我们将学习AdaBoost算法中一个核心步骤:如何为每个集成组件(即每个弱分类器)计算其系数。这个系数决定了该分类器在最终集成模型中的“话语权”。
上一节我们介绍了AdaBoost如何迭代地训练弱分类器并更新数据点的权重。本节中我们来看看,在得到一个弱分类器后,如何计算它的重要性系数。
AdaBoost使用一个公式来计算系数 ŵ_t。这个公式虽然初看有些复杂,但其背后的直觉非常清晰。该公式源于一个著名的Boosting定理,它确保了分类器能够持续改进,并帮助AdaBoost收敛到最优解。
让我们通过分析几种可能的情况来更详细地理解这个公式。
公式解析
计算系数 ŵ_t 的核心公式是:
ŵ_t = ½ * log( (1 - ε_t) / ε_t )
其中,ε_t 是当前弱分类器 f_t 在加权训练数据上的错误率。
以下是几种典型情况的分析:
情况一:优秀分类器
假设分类器 f_t 非常优秀,其加权错误率 ε_t = 0.01。
首先计算中间项:(1 - 0.01) / 0.01 = 99。
然后代入公式:ŵ_t = ½ * log(99) ≈ 2.3。
结论:对于一个优秀的分类器,AdaBoost会赋予它一个较高的正系数(如2.3),使其在最终决策中拥有较大的权重。
情况二:随机分类器
假设分类器 f_t 表现如同随机猜测,其加权错误率 ε_t = 0.5。
计算中间项:(1 - 0.5) / 0.5 = 1。
代入公式:ŵ_t = ½ * log(1) = 0。
结论:对于一个随机分类器(不提供任何有效信息),AdaBoost会通过赋予其系数0来完全忽略它。这好比不信任一个总是说随机话的朋友的意见。
情况三:极差但“有用”的分类器
这是一个非常有趣的情况。假设分类器 f_t 极其糟糕,其加权错误率 ε_t = 0.99,即它几乎把所有样本都分错了。
计算中间项:(1 - 0.99) / 0.99 ≈ 0.01。
代入公式:ŵ_t = ½ * log(0.01) ≈ -2.3。
结论:虽然这个分类器本身很糟糕,但它获得了一个绝对值较大(2.3)但为负的系数。这是因为,如果我们把这个分类器的预测结果取反(即总是做与它预测相反的决定),那么它就会变成一个非常优秀的分类器(错误率从0.99变为0.01)。AdaBoost自动为我们发现了这一点,并通过赋予负系数来实现预测取反的效果。这就像有一个朋友总是给出错误建议,你反其道而行之,反而能做出正确决定。
算法回顾与总结
在本模块的这一部分,我们探讨了如何计算AdaBoost中每个弱分类器的系数 ŵ_t。我们看到,它可以通过一个简洁的公式计算得出:
- 计算当前弱分类器 f_t 在加权数据上的错误率 ε_t。
- 应用公式:ŵ_t = ½ * log( (1 - ε_t) / ε_t )。
这个公式优雅地处理了三种情况:
- 优秀分类器:获得高的正系数。
- 随机分类器:获得零系数,被忽略。
- 极差分类器:获得高的负系数,其预测被取反后利用。
计算出 ŵ_t 后,我们就完成了对集成组件权重的分配。接下来,算法的重点将回到如何根据当前分类器的表现,更新每个训练样本的权重 α_i,使得后续的分类器能更关注之前被错误分类的样本。


本节课中我们一起学习了AdaBoost系数计算的原理与直觉。理解这个公式是掌握AdaBoost如何将弱分类器组合成强分类器的关键一步。
机器学习(分类,聚类和检索):第3-4课:通过重新加权数据关注错误分类点

在本节课中,我们将学习AdaBoost算法中的一个核心步骤:如何根据当前分类器的表现,动态调整训练数据集中每个样本的权重。这一过程旨在让后续的分类器更加关注之前被错误分类的“困难”样本。
上一节我们介绍了如何为每个弱分类器计算一个权重系数(W_hat_T),本节中我们来看看如何利用这个系数来更新每个数据点自身的权重(alpha_i)。
权重更新规则概述
AdaBoost算法提供了一个公式来更新每个数据点的权重 alpha_i。这个公式的直观思想是:增加被错误分类数据点的权重,减少被正确分类数据点的权重。这样,下一个弱分类器在训练时就会更专注于纠正之前的错误。
以下是权重更新的具体规则,它取决于当前分类器 F_T 对数据点 (X_i, Y_i) 的预测是否正确,以及分类器自身的权重 W_hat_T:
- 如果
F_T正确分类了(X_i, Y_i),则新权重为:
alpha_i_new = alpha_i_old * exp(-W_hat_T) - 如果
F_T错误分类了(X_i, Y_i),则新权重为:
alpha_i_new = alpha_i_old * exp(W_hat_T)
规则解读与示例
让我们通过几个具体例子来理解这个更新规则是如何工作的。
情况一:分类正确,且分类器表现良好
假设当前弱分类器 F_T 表现良好,我们为其分配的系数 W_hat_T = 2.3。对于某个被它正确分类的数据点,我们更新其权重:
alpha_i_new = alpha_i_old * exp(-2.3) ≈ alpha_i_old * 0.1
效果:该数据点的权重被大幅减小(乘以0.1),意味着在后续训练中,它的重要性降低,因为当前模型已经能正确处理它。



情况二:分类正确,但分类器表现随机
假设 F_T 是一个随机分类器,其系数 W_hat_T = 0。对于被它正确分类的数据点:
alpha_i_new = alpha_i_old * exp(0) = alpha_i_old * 1
效果:该数据点的权重保持不变。这很合理,因为一个随机分类器的判断没有提供有效信息,所以我们不基于它的结果来调整数据的重要性。
情况三:分类错误,且分类器表现良好
同样假设 W_hat_T = 2.3,但对于一个被错误分类的数据点:
alpha_i_new = alpha_i_old * exp(2.3) ≈ alpha_i_old * 10
效果:该数据点的权重被显著增加(乘以10)。这迫使下一个分类器必须更加关注这个被当前“好”分类器误判的困难样本。

情况四:分类错误,但分类器表现随机
假设 W_hat_T = 0,对于一个被错误分类的数据点:
alpha_i_new = alpha_i_old * exp(0) = alpha_i_old * 1
效果:权重同样保持不变。因为随机分类器的错误判断不具备参考价值,我们不据此调整权重。
算法流程更新
现在,我们可以将权重更新步骤整合到AdaBoost算法流程中:
- 初始化权重:所有数据点的权重
alpha_i设置为均匀分布,即1/n。 - 循环训练弱分类器:
a. 使用当前的权重分布alpha_i训练一个弱分类器F_T。
b. 计算F_T的系数W_hat_T。
c. 使用上述规则更新所有数据点的权重alpha_i。 - 组合所有弱分类器,形成最终强分类器。


总结


本节课中我们一起学习了AdaBoost算法中数据权重更新的关键机制。我们看到了一个直观且有效的规则:根据当前分类器的表现(W_hat_T)和其对每个样本的判断对错,来增加错误分类样本的权重,并减少正确分类样本的权重。这个过程确保了算法能够持续聚焦于整个数据集中最难分类的样本,从而逐步提升整体模型的性能。
机器学习:3-4:AdaBoost算法中的权重归一化

在本节课中,我们将学习AdaBoost算法中的一个关键技术细节:权重归一化。我们将了解为什么需要在每次迭代后对数据点的权重进行归一化处理,以及如何具体操作。
概述
上一节我们介绍了AdaBoost算法如何通过加权错误率来更新数据点的权重。本节中,我们来看看一个随之而来的技术问题:权重的数值稳定性。如果不加处理,某些数据点的权重可能会变得极大或极小,导致计算上的困难。
权重变化的潜在问题
在AdaBoost的迭代过程中,我们反复根据分类器的表现来调整每个数据点的权重。这可能导致权重的数值范围失控。
以下是具体原因:
- 如果一个数据点
Xi经常被分类错误,其权重会反复乘以一个大于1的数(例如,2 × 2 × 2...)。这个权重α_i会变得极大。 - 反之,如果一个数据点
Xi经常被正确分类,其权重会反复乘以一个小于1的数(例如,0.5 × 0.5 × 0.5...)。这个权重α_i会变得极小。
这种极端情况会导致算法出现数值不稳定性,计算机在处理这些差异巨大的权重时可能无法正常运行。
解决方案:权重归一化
为了解决上述问题,我们在每次迭代后,对所有数据点的权重进行归一化,使它们的总和为1。
具体操作是,将每个权重 α_i 除以所有权重的总和。

公式表示如下:
α_i (新) = α_i (旧) / Σ(α_j),其中求和 Σ 针对所有数据点 j。
这种方法能将权重保持在一个合理的范围内,有效避免数值不稳定性的发生。
算法总结
现在,让我们总结完整的AdaBoost算法流程:
- 初始化权重:从均匀权重开始,即所有数据点的权重均为
1/n。 - 训练弱分类器:基于当前权重,学习一个分类器
F_t。 - 计算系数:根据该分类器在加权数据上的错误率,计算其系数(重要性)。
- 更新权重:增加被错误分类数据点的权重,减少被正确分类数据点的权重。
- 归一化权重:将更新后的所有权重进行归一化,使其总和为1。这一步具有重要的实际意义。
总结

本节课中,我们一起学习了AdaBoost算法中权重归一化的必要性和具体方法。通过每次迭代后对权重进行归一化,我们可以确保算法数值稳定,从而可靠地运行。整个AdaBoost算法结构优美,效果卓越,并且非常易于使用。
机器学习(分类,聚类和检索):第3-4课:AdaBoost运行示例

在本节课中,我们将通过一个具体的玩具示例,来探索AdaBoost算法在实际中是如何工作的。这个示例将帮助我们直观理解Boosting机制,包括如何迭代地调整数据权重、组合弱分类器,以及最终可能面临的过拟合问题。
初始分类器 F₁
首先,我们直接使用原始数据来训练第一个分类器。此时,所有数据点具有相同的权重。学习过程是标准的,因为每个数据点的权重相同。在本例中,我们学习的是一个决策桩。
以下是第一个决策桩 F₁ 的决策边界:
# 决策边界近似为 x₁ ≈ -0.07
if x₁ < -0.07:
prediction = -1
else:
prediction = +1
这个边界试图在零点附近将正例与负例分开。它做出了一个垂直分割。
第二个分类器 F₂
为了学习第二个决策桩 F₂,我们需要根据 F₁ 的表现来重新加权数据。具体来说,我们会增加被 F₁ 分类错误的点的权重,并降低分类正确的点的权重。在图中,更大的加号和减号表示更高的权重。
观察更新权重后的数据分布,被错误分类的点(左侧的负号和右侧的正号)权重增加了。
基于这个加权后的数据,我们学习得到第二个决策桩 F₂。与第一次的垂直分割不同,这次我们得到了一个水平分割。
以下是第二个决策桩 F₂ 的决策边界:
# 决策边界近似为 x₂ ≈ 1.3
if x₂ < 1.3:
prediction = -1
else:
prediction = +1
这个边界对于加权后的数据是一个更好的分割。它正确分类了顶部的所有负例,但在底部的负例上犯了一些错误,同时正确分类了底部的正例。
组合分类器
现在我们已经学习了决策桩 F₁ 和 F₂,问题是如何组合它们。根据AdaBoost的公式计算,我们得到第一个决策桩的权重 ŵ₁ = 0.61,第二个决策桩的权重 ŵ₂ = 0.53。这意味着我们比第二个分类器更信任第一个分类器,这很合理,因为第二个看起来效果稍差。
当我们把它们组合起来时,会得到一个非常有趣的决策边界:
- 左上角的点被明确预测为负类(Ŷ = -1)。
- 右下角的点被明确预测为正类(Ŷ = +1)。
- 其他两个区域则存在较高的不确定性。
迭代与过拟合
如果我们继续运行AdaBoost算法,比如进行30次迭代,会观察到两个现象:
- 训练误差变为零,即所有训练数据点都被正确分类。
- 决策边界变得非常复杂和不规则(用技术术语形容,就是变得“疯狂”)。
结合这两个洞察,我们得出结论:这个分类器很可能过拟合了数据。它在训练集上表现完美,但在未见过的测试数据上可能表现不佳。这是Boosting中可能发生的情况,我们将在后续课程中进一步讨论。
总结

本节课中,我们一起学习了集成分类器的概念,即通过组合多个简单分类器并进行投票来做出预测。我们详细描述了AdaBoost算法,这是一种通过“提升”错误分类数据点权重的技术来学习集成分类器的简单而有效的方法。最后,我们通过一个运行示例,看到了AdaBoost如何迭代改进,以及最终可能面临的过拟合挑战。
机器学习(分类,聚类和检索):第3-4课:使用AdaBoost学习提升决策树桩

在本节课中,我们将学习如何将AdaBoost算法具体应用于决策树桩的学习。我们将详细介绍如何选择最佳决策树桩、计算其系数,以及如何更新每个数据点的权重。


概述:AdaBoost与决策树桩
上一节我们介绍了AdaBoost算法的抽象框架。本节中,我们来看看如何将这个框架实例化,用于学习决策树桩。决策树桩是一种非常简洁的默认学习方式,能帮助我们巩固目前所学的概念。
学习最佳决策树桩
以下是AdaBoost算法的核心步骤,我们将据此学习决策树桩 F(t) 并计算其系数 W_hat_t。
第一步是学习下一个决策树桩 F(t)。这类似于标准的决策树桩学习过程。
我们将尝试在每个特征上进行分割,例如收入、信用历史、储蓄和市场状况,并评估每个决策树桩在加权数据上的表现。在多次提升迭代中,我们可能会重复使用同一特征。
以下是评估过程:
- 对于“收入”特征进行分割,加权误差可能是 0.2。
- 对于“信用”特征进行分割,加权误差可能是 0.35。
- 对于“储蓄”特征进行分割,加权误差可能是 0.3。
- 对于“市场状况”特征进行分割,加权误差可能是 0.4。
我们选择具有最低加权误差的最佳特征。因此,我们将选择第一个特征,即“收入 > 100,000”进行分割。
所以,F(t) 将是这样一个决策树桩:如果收入大于100,000,则预测为“安全”;否则预测为“高风险”。
现在,最后一个问题是给这个分类器分配什么系数。我们需要将加权误差 0.2 代入AdaBoost公式进行计算。
公式:
W_hat_t = 0.5 * ln((1 - error_t) / error_t)
代入 error_t = 0.2 进行计算,结果是 0.69。因此,这第一个决策树桩的系数就是 0.69。
更新数据点权重
回到AdaBoost算法,我们已经讨论了如何从数据中学习树桩并计算其系数。接下来,我们谈谈如何更新每个数据点的权重 alpha。
这是一个直观的过程。我们使用刚学到的决策树桩(收入 > 100,000)对数据点进行预测。问题是,这个决策树桩的效果如何?
观察预测结果,它对一些数据点分类正确,对另一些则分类错误。我们将正确的标记为亮绿色,错误的标记为红色。
基于之前每个数据点的权重(图中已标出),我们需要使用上面的标准AdaBoost公式计算新权重。
我们将把计算出的系数 W_hat = 0.69 代入公式,以确定每个权重的乘数。代入计算后,你会发现:
- 对于每个正确的数据点,其权重将乘以
exp(-0.69) ≈ 0.5,即减半。 - 对于每个错误的数据点,其权重将乘以
exp(0.69) ≈ 2,即翻倍。
以下是逐行更新权重的示例:
- 对于第一行(绿色,正确),权重从 0.5 变为 0.25。
- 对于第二行(绿色,正确),权重从 1.5 变为 0.75。
- 对于第三行(红色,错误),权重从 1.5 变为 3.0。
我们可以逐个数据点地根据分类对错,将其权重乘以2或除以2。
总结

本节课中,我们一起学习了如何使用AdaBoost算法来提升决策树桩。我们具体实践了如何选择最佳分割特征以构建决策树桩、如何根据加权误差计算分类器的系数,以及如何根据分类结果更新每个训练样本的权重。构建一个提升的决策树桩分类器极其简单,并且这类模型通常在广泛的数据集上表现非常出色。
机器学习(分类,聚类和检索):第3-4课:提升定理


在本节课中,我们将要学习著名的AdaBoost提升定理,探讨其核心含义及其在实际应用中的影响。提升定理是理解Boosting算法为何有效以及其性能极限的关键。
概述
提升定理由Yoav Freund和Robert Schapire提出,它从理论上解释了为何能够将一系列“弱”分类器组合成一个强大的分类器。我们将首先回顾Boosting算法的起源,然后深入定理的表述、技术条件及其实际意义。
上一节我们介绍了Boosting算法的基本迭代过程,本节中我们来看看支撑其有效性的理论基石——提升定理。
提升定理的起源与现象
Boosting算法的诞生源于一个核心问题:能否组合多个弱分类器来构建一个强分类器?Freund和Schapire提出的Boosting思想彻底改变了机器学习领域。
在实践中,我们观察到Boosting算法一个非常显著的现象。以下是其在训练集上的典型表现:
- X轴:Boosting的迭代次数。
- Y轴:在特定数据集上的训练误差。
我们通常看到,初始的弱分类器(如第一个决策树桩)训练误差可能很高(例如22.5%)。但随着迭代次数增加,训练误差会平滑下降,并最终趋向于零。这意味着算法最终能在训练集上完美分类所有样本。
提升定理的表述
以下是著名的AdaBoost定理的核心内容。定理中的权重 W 概括了算法中的所有选择,该定理对机器学习领域产生了深远影响。
定理:在满足某些技术条件的前提下,当集成分类器中弱分类器的数量 T 趋向于无穷大时,最终组合分类器的训练误差将趋向于零。
用公式可以表示为:
当 T → ∞ 时,训练误差 → 0
图像化理解就是,我们预期Y轴上的训练误差曲线最终会下降到0。虽然过程中可能会有波动,但总体趋势是下降的,并最终稳定在零附近。
定理的技术条件
现在,让我们花点时间讨论定理中提到的“技术条件”。所有定理都有其适用范围,提升定理也不例外。
该技术条件至关重要,它要求:在每一轮迭代 T 中,我们都能找到一个弱分类器(例如决策树桩),其加权分类错误率必须略低于0.5。
换句话说,这个弱分类器在加权后的数据上,其性能必须比随机猜测(错误率50%)好一点点。这看起来是一个很直观的要求。
然而,这个条件并非总能满足。以下是一个极端的反例:
假设一个负类样本点与一个正类样本点在空间位置上完全重合。那么,没有任何一个决策树桩(基于单一特征阈值的分类器)能够将这两个点分开。在这种情况下,提升定理的条件就无法被满足。
尽管如此,在实际应用中,只要数据不是完全不可分的,Boosting算法通常都能将训练误差降至极低水平,即使不一定精确到零。
总结
本节课中我们一起学习了AdaBoost提升定理。我们了解到,该定理从理论上保证了:只要每一轮迭代都能找到比随机猜测稍好的弱分类器,那么随着集成规模的扩大,组合分类器的训练误差可以趋近于零。

我们讨论了定理的技术条件及其重要性,也通过反例明白了该条件的边界。尽管存在严格的理论前提,但提升定理成功地解释了Boosting算法在实践中表现出的强大拟合能力,使其成为机器学习中不可或缺的工具之一。
机器学习(分类,聚类和检索):第3-4课:提升中的过拟合 📈

在本节课中,我们将要学习提升方法(Boosting)中的一个重要现象——过拟合。我们将通过对比决策树与提升决策桩(Boosted Decision Stump)的表现,来理解提升方法对过拟合的鲁棒性,并探讨如何正确选择提升的迭代轮数。
决策树中的过拟合
上一节我们介绍了提升方法的基本原理,本节中我们来看看过拟合问题。首先,回顾一下在决策树模块中观察到的现象。
下图展示了在一个真实的贷款申请数据集上,决策树深度与分类错误率的关系。

以下是关键观察结果:
- 训练错误率:随着决策树深度增加,训练错误率持续下降。
- 测试错误率:测试错误率(可反映真实错误率)先下降,在深度约为7时达到最佳,之后开始回升。
- 过拟合现象:当深度达到18时,训练错误率低至8%,但测试错误率却高达39%。这表明出现了严重的过拟合,且训练与测试错误率之间存在巨大差距。
- 最佳表现:最佳决策树在测试集上的分类错误率约为34%。
提升决策桩的表现
现在,让我们看看在相同数据集上应用提升决策桩(Boosting)的效果。
其表现曲线呈现以下特征:
- 训练错误率:随着提升迭代轮数的增加,训练错误率持续下降,这与理论预测一致。
- 测试错误率:测试错误率同样随着迭代而下降,并未立即观察到过拟合。
- 性能对比:经过18轮提升(即18个决策桩)后,测试错误率为32%。这优于单个最佳决策树的表现(34%)。
- 过拟合程度:训练与测试错误率之间的差距更小,意味着过拟合程度显著降低。
持续提升会怎样?
我们提到提升初期未观察到过拟合,那么如果持续增加迭代轮数,会发生什么呢?
以下是随着决策桩数量(即提升轮数 T)增加的趋势:
- 训练错误率:如定理所预期,持续下降。
- 测试错误率:在经历一段下降后趋于稳定。在相当宽的迭代轮数范围内(例如上图中T的某个区间),测试性能保持恒定。
- 过拟合的显现:如果迭代轮数过多(例如达到5000),最终仍会观察到过拟合,测试错误率开始缓慢上升(例如从最佳的31%升至33%)。但提升方法对过拟合表现得相当鲁棒,错误率上升幅度相对较小。
如何选择提升轮数 T?
在以上示例中,我们使用了测试错误率来讨论过拟合,但在实际建模中,绝不能使用测试集来调整参数。那么,应该如何正确选择提升的迭代轮数 T 呢?
T 是控制模型复杂度的关键参数,类似于正则化中的 λ 或决策树的深度。选择它的原则与选择其他机器学习算法的“魔法参数”相同。
以下是两种标准方法:
- 验证集法:如果拥有大量数据,可以划出一部分作为验证集,专门用于选择最佳 T 值。
- 交叉验证法:如果数据集不是特别大,则应使用交叉验证技术来选择 T 值。
这两种方法能确保我们基于未参与训练的数据来评估模型复杂度,从而得到泛化能力更好的模型。
总结
本节课中我们一起学习了提升方法中的过拟合问题。通过对比发现,提升方法(如提升决策桩)相比单个复杂模型(如深度决策树)对过拟合具有更强的鲁棒性,其测试错误率能在更宽的迭代轮数范围内保持稳定。然而,过度提升最终仍会导致过拟合。关键在于,我们必须使用验证集或交叉验证等正确方法来选择提升的迭代轮数 T,而不能依赖于训练错误率或测试集。




机器学习(分类,聚类和检索):第3-4课:集成方法:提升的影响快速回顾 🚀


在本节课中,我们将对提升(Boosting)方法进行总结,回顾其核心思想、其他相关算法,并探讨它在现实世界中的巨大影响。
提升方法总结 📊
上一节我们介绍了集成分类器的概念,并将其形式化为不同分类器投票的加权组合。我们重点讨论了提升算法,其核心思想是让后续的分类器专注于纠正之前分类器所犯的错误。
具体来说,我们学习了AdaBoost算法,这是用于分类问题的一种特殊提升方法。我们展示了如何计算每个分类器的系数 α_t 以及数据点的权重 D_t(i)。其核心更新公式如下:
- 对于误分类的点,增加其权重:
D_{t+1}(i) = D_t(i) * exp(α_t) - 对于正确分类的点,减少其权重:
D_{t+1}(i) = D_t(i) * exp(-α_t) - 分类器系数
α_t基于其加权错误率ε_t计算:α_t = 0.5 * ln((1 - ε_t) / ε_t)
最终,集成模型的预测是所有弱分类器预测的加权投票:H(x) = sign( Σ α_t * h_t(x) )。
其他集成算法 🔄
除了AdaBoost,还有其他强大的集成学习方法值得了解。
以下是两种重要的相关算法:
- 梯度提升(Gradient Boosting):可以看作是AdaBoost的泛化。它不仅能用于分类问题,还能通过优化其他类型的损失函数来处理更广泛的问题(如回归),是目前最常用的提升算法之一。
- 随机森林(Random Forests):这是一种与提升不同的集成策略,称为“装袋法”(Bagging)。其过程简要概括为:从原始数据中有放回地抽取多个不同的子数据集,在每个子集上独立训练一棵决策树,最后对所有树的输出进行平均(如投票或取均值)。与提升相比,随机森林更容易并行化,但在固定树的数量下(例如100棵树),其性能通常略逊于提升方法。
提升的现实世界影响 🌍
现在,让我们来看看提升方法在机器学习领域产生的巨大影响。它已成为最实用、应用最广泛的机器学习方法之一。
提升方法在众多领域发挥着关键作用:
- 计算机视觉:许多默认算法,如人脸检测,都基于提升方法。
- 机器学习竞赛:在Kaggle或KDD Cup等平台上,大约70%的冠军解决方案使用了提升方法,特别是提升决策树(如XGBoost, LightGBM)。
- 多样化任务:提升方法成功应用于恶意软件检测、欺诈检测、网页搜索排名,甚至像希格斯玻色子探测这样的物理任务。
- 工业部署:集成方法是部署最广泛的先进机器学习技术之一。例如,Netflix的电影推荐系统就使用了集成分类器。在其著名的推荐算法竞赛中,获胜方案正是通过组合大量分类器构建的集成模型。
人们通过不同方式构建集成模型:有时使用提升进行优化,有时使用装袋法等技术,有时甚至手动调整组合权重。其中,我们推荐使用提升方法来自动化这一过程。

课程总结 ✅
在本模块中,我们一起深入探索了集成分类器的世界。
我们首先将集成模型形式化为多个分类器的加权组合。然后,重点学习了提升算法,其核心是让后续分类器专注于纠正前序模型的错误。我们详细探讨了用于分类的AdaBoost算法,包括如何计算分类器系数和数据权重。我们还讨论了如何用决策树桩(Decision Stump)这种极简单的模型作为弱学习器来实现提升。

最后,我们提到了提升的训练误差会收敛到零的理论性质,虽然也需要警惕过拟合,但提升方法在实践中通常表现出很强的鲁棒性。


总而言之,集成方法,尤其是提升,是机器学习工具箱中不可或缺的强大工具,并在解决现实世界复杂问题中持续证明其价值。
机器学习(分类,聚类和检索):第3-4课:案例研究:准确率不是分类的最佳指标 🎯

在本节课中,我们将探讨一个重要的概念:为什么在评估分类器时,仅仅依赖准确率或错误率可能是不够的。我们将通过一个有趣的餐厅广告案例,引入精确率和召回率这两个更细致的评估指标。它们能帮助我们更好地理解分类器在真实世界应用中的表现。
评估分类器的传统方法
在本课程中,我们一直以一种关键方式评估分类器:我们测量分类器的错误率或准确率。然而,事实证明,对于许多现实世界的应用,错误率或准确率并不是衡量分类器是否为你做出正确决策的好指标。
引入精确率与召回率
在本模块中,我们将讨论精确率和召回率。这是一种非常酷且简单的方法,用于评估分类器,它能捕捉到广泛应用程序所需的一些特性。我们将使用一个有趣的应用作为贯穿本模块的示例。
案例背景:餐厅广告活动
设想我拥有一家餐厅,我的目标是将餐厅的客流量增加30%。我计划开展一个创新的广告活动来实现这个目标。但没有人希望他们的广告活动只是垃圾邮件式的群发邮件。因此,我希望广告活动是真实可信的。
我希望实现真实性的方式是:利用顾客的声音来讲述餐厅有多么棒。具体来说,我将查看顾客评论,从中找出精彩的片段——那些描述餐厅优点的关键正面句子,甚至可能找到一些能言善辩的代言人,来清晰地解释他们喜爱餐厅的原因。
我的目标是自动化这个过程:获取餐厅评论,并将人们所说的关键句子或要点发布在我的网站上,这样任何访问网站的人都能看到最新的好评。
自动化流程:使用情感分类器
为了处理大量评论并实现自动化,我将采用我们在专项课程第一门课中描述的方法:将餐厅评论分割成句子。对于每个句子,有些是正面的,有些是负面的。我需要一个分类器来评估它们。
例如,如果句子是“easily the best sushi in town”,这就是我的输入 X。我将把它输入到句子情感分类器中,并获得输出 ŷᵢ,它要么是正面情感,要么是负面情感。
我将对收到的每一条评论中的每一个句子都这样做。事实上,我甚至可以实时进行:每当有新评论出现,我就将其输入这个分类器模型,并尝试预测 ŷᵢ 是否为正面。
- ŷᵢ = +1:这些是“好句子”,是我想要展示和谈论的。
- ŷᵢ = -1:这些是负面句子,我想忽略它们。
我关心的是正面句子,并尽力将它们展示出来,让人们觉得:“哇,这家餐厅太棒了,我要去那里吃寿司!”
关键问题:如何信任分类器?
我如何找到那些正面句子?我将使用一个情感分类器。但我如何知道这个情感分类器真的很好,我可以信任它?我能否放心地将这些句子自动发布到我的网站上,而无需每次都检查?
这正是我们要讨论的关键点:在自动化机器学习时,你必须真正信任一个机器学习模型。 那么,如果我告诉你一个特定的准确率,这个数字是否足以让我信任到可以自动将评论输入到直接显示在网站上的系统中?
总结

本节课我们一起学习了为什么在现实应用中,仅凭准确率评估分类器可能存在问题。我们通过一个餐厅广告的案例,引出了对更细致评估指标的需求。下一节,我们将深入探讨精确率和召回率的具体定义与计算,看看它们如何帮助我们更好地理解和信任分类器在特定任务(如筛选正面评论)上的表现。
机器学习(分类,聚类和检索):第3-4课:什么是分类器的好性能


在本节课中,我们将探讨如何评估分类器的性能。我们将超越简单的准确率,学习两个在现实任务中至关重要的评估指标:精确率与召回率。
上一节我们介绍了分类任务的基本概念,本节中我们来看看如何具体衡量一个分类器的好坏。
为了决定在我的网站上展示哪些句子,我需要确保我的分类器擅长识别这些句子。因此,我需要确保它的性能良好。那么,良好的性能意味着什么?
通常,这取决于具体任务。问题是,对于我决定展示哪些句子这个任务而言,什么才是好的性能?
在第一门课程中,我们曾探讨过什么是好的准确率。我们通常将分类器的准确率与随机分类器进行比较。例如,在我们讨论的二元分类任务中,随机分类器的准确率是50%,即分类错误率为0.5。因此,我们的分类器至少应该比0.5更好。如果有多个类别,随机分类器的错误率是1/k。例如,对于三个类别,错误率约为0.66。所以,我们至少应该比随机分类做得更好。
但这还不足以让我做出决定。仅仅比随机分类好,还不足以让我决定将这个服务部署到我的餐厅网站上。因此,我需要考虑其他因素。
第一门课程中还探讨了类别不平衡的问题。例如,当一个类别的数据远多于另一个类别时会发生什么。举个例子,假设我的分类器声称有90%的准确率。但我的餐厅评价很差,90%的评论都是负面的。这意味着什么?这可能意味着分类器将所有评论都预测为负面。

它从未找到那10%的正面评论。因此,仅从准确率来看,性能可能看起来不错,但它永远找不到我迫切需要的那些正面评论(因为餐厅评价太差,我正拼命想展示它们)。所以,这种情况也很糟糕。
现在,让我们退一步,思考我们手头的任务——这个自动化营销活动任务。并问自己:对我来说,什么是好的性能?是准确率吗?是90%吗?不是。它关乎两件事。
首先,如果我在网站上展示某些内容,它最好是正面的。天哪,如果我在网站上展示了一条负面评论,那就是双重打击。一方面,访问我网站的人会读到关于我的负面信息;另一方面,人们会说没人会想来我的网站了。因此,我要确保的是,每当我展示内容时都非常精确,确保它是正面的。这意味着需要高精确率。
其次,我必须担心的另一件事是,找到所有那些正面评论。也许我的餐厅评价并不那么好,那些正面评论并不常见。所以我必须确保我能找到所有的正面评论,这样我才有机会在网站上展示所有正面评论。这被称为召回率。
所以,精确率衡量的是我在网站上展示的内容有多精确(即展示的是正面评论)。召回率衡量的是我有多擅长从所有评论、所有句子中找到所有的正面评论。
因此,我希望在这两个指标上都表现良好。我们之前讨论的单一准确率数字,在实际应用中,精确率和召回率是评估分类器极其重要的一类指标,人们一直在使用它们。今天我将详细讨论它们。

如果你开始在实践中应用机器学习,你应该对这两个概念非常熟悉。
机器学习(分类,聚类和检索):第3-4课:精确率:实际为正的正预测比例


在本节课中,我们将要学习一个重要的分类评估指标——精确率。我们将了解其正式定义,并通过一个具体的例子来理解它在实际应用中的意义。
定义精确率
上一节我们介绍了分类任务的基本概念,本节中我们来看看如何衡量分类器在预测“正类”时的准确性。
精确率衡量的是,在所有被模型预测为“正类”的样本中,有多少是真正的“正类”。其核心思想是评估“正类预测”的准确度。
公式:精确率 = 真阳性 / (真阳性 + 假阳性)
理解混淆矩阵
为了更清晰地计算精确率,我们需要引入混淆矩阵的概念。混淆矩阵可以帮助我们区分四种不同的预测结果。
以下是混淆矩阵中四种情况的定义:


- 真阳性:真实标签为正,预测标签也为正。
- 真阴性:真实标签为负,预测标签也为负。
- 假阴性:真实标签为正,但预测标签为负。
- 假阳性:真实标签为负,但预测标签为正。
通过例子理解错误类型
现在,我们通过一个餐厅评论筛选的例子来具体感受假阳性和假阴性带来的不同影响。
假设我们有一个模型,用于判断餐厅评论是正面还是负面,并决定是否将其展示在网站上。
- 假阴性:一条真实的正面评论被模型预测为负面。这意味着我们错过了一条好评,没有把它展示出来。虽然不理想,但后果相对较轻。
- 假阳性:一条真实的负面评论被模型预测为正面。这意味着我们把一条差评展示在了网站上。例如,一条说“海藻沙拉很一般”的差评被展示出来,这可能会吓跑潜在顾客,后果非常严重。
计算精确率
基于混淆矩阵,我们可以更精确地定义和计算精确率。
精确率是“真阳性”数量占所有“预测为正类”样本(即真阳性与假阳性之和)的比例。其最佳值为1,表示所有预测为正的样本都是真正的正类;最差值为0,表示所有预测为正的样本实际上都是负类。
回顾我们最初的例子:模型预测了6条句子为正类。其中,4条是真阳性,2条是假阳性。
计算:精确率 = 4 / (4 + 2) = 4/6 ≈ 0.667
这意味着,在模型决定展示的6条评论中,有4条是真实的好评,但有2条是混入的差评。为了维护网站声誉,我们希望模型具有高精确率,以确保展示出来的内容尽可能都是正面的。
总结

本节课中我们一起学习了精确率这一评估指标。我们了解到,精确率关注的是模型预测出的“正类”结果有多纯净。它通过公式 精确率 = 真阳性 / (真阳性 + 假阳性) 进行计算,特别适用于那些需要严格控制“假阳性”(即误报)代价的应用场景,例如在我们的例子中,避免将差评展示在网站上。
机器学习(分类,聚类和检索):第3-4课:召回率详解 📊

在本节课中,我们将要学习分类模型评估中的一个核心指标——召回率。上一节我们介绍了精确率,它衡量了被模型预测为正的样本中,有多少是真正的正样本。本节中我们来看看召回率,它关注的是所有真正的正样本中,有多少被模型成功“召回”或识别出来。
召回率的核心概念

召回率关注的问题是:在所有实际为正的样本中,我的模型成功找出了多少?在餐厅评论的例子中,这意味着在所有真正称赞餐厅的句子中,我的分类器成功识别出了多少句。
我们可以用以下公式来定义召回率:
召回率 = 真正例 / (真正例 + 假反例)
其中:
- 真正例:实际为正,且被模型预测为正的样本。
- 假反例:实际为正,但被模型错误预测为负的样本。
通过示例理解召回率
为了更好地理解,让我们看一个具体的例子。假设我们有一个分类器,用于判断餐厅评论中的句子是否为正面评价。
以下是分类器对所有句子进行预测和真实情况的可视化:

在上图中,分类器预测了一些句子为正面(Y_hat = +1),一些为负面(Y_hat = -1)。然而,当我们查看这些句子的真实标签(Y)时,情况如下:

从图中我们可以看到:
- 分类器成功预测了4个真正的正面句子(真正例)。
- 但是,还有2个真正的正面句子被分类器错误地预测为负面(假反例)。
这意味着,虽然我们找到了4句正面评价,但也错过了2句。如果这两句评价非常精彩,错过它们可能会影响餐厅的声誉和吸引力。这就是召回率不完美的代价。
召回率的计算与解释


根据定义和示例,我们可以计算召回率:
召回率 = 4 / (4 + 2) = 4/6 ≈ 0.667
这个结果意味着,我们的模型成功找出了所有正面评价中的约66.7%。
以下是关于召回率值的关键解读:
- 召回率 = 1:这是最理想的情况,意味着假反例 = 0。模型成功捕获了所有真正的正样本,没有任何遗漏。
- 召回率 = 0:这是最糟糕的情况,意味着真正例 = 0。模型没有成功识别出任何一个真正的正样本,所有正样本都被错误地归类为负样本。
回到我们的餐厅例子,高召回率意味着你几乎发现了所有关于餐厅的正面评价,没有让任何好评“漏网”。
精确率与召回率的权衡
在实际应用中,精确率和召回率往往是一对需要权衡的指标。提高分类阈值(使模型更“谨慎”地预测为正)通常会提升精确率(因为预测为正的样本更可能是真的),但会降低召回率(因为一些真正的正样本会被排除)。反之,降低阈值会提升召回率,但可能引入更多误报,从而降低精确率。
理解这种权衡对于根据具体业务需求调整模型至关重要。例如,在疾病筛查中,我们可能宁愿接受较低的精确率(一些误报),也要追求极高的召回率(尽可能不漏掉任何病人)。
总结
本节课中我们一起学习了召回率这一重要的分类模型评估指标。
- 召回率衡量的是模型找出所有正样本的能力。
- 其公式为:召回率 = 真正例 / (真正例 + 假反例)。
- 高召回率意味着模型遗漏的正样本很少,这对于“宁可错杀,不可放过”的应用场景(如垃圾邮件过滤、安全隐患排查)非常重要。
- 召回率与精确率需要根据实际需求进行权衡。


理解并合理运用召回率,能帮助你更全面地评估分类模型的性能,并做出更符合业务目标的决策。
机器学习(分类,聚类和检索):第3-4课:精确率与召回率的极端情况

在本节课中,我们将要学习精确率与召回率这两个评估指标之间的权衡关系。为了深入理解这种权衡,我们将探讨两种极端情况:一个极端追求高精确率的分类器,以及另一个极端追求高召回率的分类器。通过分析这两种极端,我们能更好地理解它们如何相互制约,并找到适合我们需求的平衡点。

理解精确率与召回率的权衡
上一节我们介绍了精确率和召回率的基本概念。本节中,我们来看看这两个指标在极端情况下的表现。理解这种权衡关系,关键在于审视两种极端分类器的行为:一种是追求极致精确率的分类器,另一种是追求极致召回率的分类器,以及它们有时如何相互对立。
极端情况分析:乐观与悲观的分类器
首先,让我们思考一种我称之为“乐观”的分类器。这种分类器就像生活中的某些乐观主义者,他们认为所有事情都是好的。即使发生了不好的事情,他们也会说“好”。因此,这类分类器会将几乎所有输入都标记为“正面”。
以下是乐观分类器的特点:
- 行为:几乎每个输入句子都被标记为正面,极少被标记为负面。
- 结果:所有真正正面的数据点极有可能都被标记为正面。
- 指标影响:这意味着我们拥有完美的召回率,因为我们找回了所有正面数据点。但我们可能无法获得完美的精确率,因为我们把一大堆负面数据也放进了“正面”这个桶里。
那么,如何应对这种情况呢?我们可以考虑另一种“悲观”的分类器。这种分类器就像那些悲观的朋友,无论你多么努力,为他们做多少事,他们都觉得一切都很糟糕。他们极少有事情会说是“好”的,而一旦他们说好,那件事很可能确实很好,但其他所有事情都被他们标记为“坏”。
以下是悲观分类器的特点:
- 行为:极少将事物标记为正面(例如,标记为+1),其他一切都标记为负面(-1)。
- 结果:悲观者会错过生活中的许多美好事物。
- 指标影响:悲观者拥有高精确率,因为他们标记为“好”的少数事物往往确实是好的。但他们的召回率非常非常低,因为他们无法识别出生活中的大量美好事物。
在极端之间寻找平衡
由此可见,在高精确率、低召回率的模型(悲观者)与低精确率、高召回率的模型(乐观者)之间,存在一个光谱。我们的目标是在这两种世界观之间找到某种平衡,找到一个对我们来说“恰到好处”的点,即在悲观模型和乐观模型之间取得平衡。
具体而言,我们希望:
- 尽可能多地找出正面评价或句子(高召回率)。
- 同时,尽可能减少错误的预测(高精确率)。
这就是我们在餐厅评论分类案例中试图达成的平衡。

总结

本节课中,我们一起学习了精确率与召回率之间的权衡关系。我们通过分析“乐观”和“悲观”这两种极端分类器,理解了高召回率往往以牺牲精确率为代价,而高精确率则可能导致召回率降低。在实际应用中,我们需要根据具体任务的目标,在这两个指标之间找到合适的平衡点。
机器学习(分类,聚类和检索):第3-4课:权衡精确率与召回率

在本节课中,我们将学习如何通过调整一个简单的参数,在精确率与召回率之间进行权衡。我们将看到,一个模型可以从“乐观”的高召回率、低精确率状态,平滑地过渡到“悲观”的低召回率、高精确率状态。

到目前为止,我们讨论了精确率、召回率、乐观模型、悲观模型等不同方面。但整个故事中最令人惊讶的一点是,从低精确率模型过渡到高精确率模型,或者从高召回率模型过渡到低召回率模型,其实非常容易。
我们可以拥有一个非常乐观的低精确率、高召回率模型,也可以拥有一个非常悲观的高精确率、低召回率模型。事实证明,在这两者之间找到一条路径很容易。问题是,我们如何做到这一点?

在本课程早期,我们不仅为每个数据点分配了标签(+1 或 -1),还分配了一个概率值。例如,某个评论有 0.99 的概率是正面的,另一个评论有 0.55 的概率是正面的。
这些概率值在课程早期被提及,它们将具有根本性的作用。现在,你将看到一个它们发挥惊人作用的场景:概率可以用来在精确率和召回率之间进行权衡。让我们来弄清楚这一点。
在课程早期,我们使用一个固定的阈值来决定一个输入句子 Xi 是正面还是负面。我们规定,如果概率大于 0.5,则为正面;如果概率小于或等于 0.5,则为负面。
那么,我们如何仅仅通过改变这个 0.5 的阈值来创建一个乐观或悲观的模型呢?让我们探讨这个想法。
考虑一下,如果我们将阈值从 0.5 设置为 0.999 会发生什么。这意味着一个数据点只有在概率大于 0.999 时才会被标记为 +1。结果就是,只有极少数数据点能满足这个条件。
因此,如果只有极少数数据点满足条件,那么只有极少数数据点会被标记为 +1,绝大多数会被标记为 -1。我们称这个分类器为悲观分类器。
相反,如果我们将阈值改为 0.001,那么几乎任何体验都会被标记为正面。几乎所有数据点都会满足这个条件,因此我们会说所有东西都是 +1。这就是乐观分类器,它会认为一切都好。
因此,通过将阈值从 0.5 调整到接近 0 或接近 1 的值,我们就在乐观和悲观之间切换。
让我们回到逻辑回归的具体例子来理解。我们有一个输入分数 score(x),输出是给定 x 和 w 时 y 等于 +1 的概率 P(y=+1 | x, w)。
这里的阈值 T 是一个分界点,我们规定:如果概率大于或等于 T,则预测 ŷ 为 +1;否则为 -1。在概率曲线上方的一切都会被标记为 +1,下方的一切则标记为 -1。
更具体地说:
- 如果我们将阈值
T设置为一个非常高的值(接近 1),那么阈值线以下的几乎所有点都会被标记为 -1,只有极少数高于阈值的点被标记为 +1。这就是我们最终得到悲观分类器的原因。 - 另一方面,如果我们将阈值
T设置为一个非常小的值(接近 0),那么几乎所有点都在阈值线上方,因此几乎所有点都被标记为 +1,只有极少数被标记为 -1。这样我们就得到了乐观分类器。
因此,让阈值 T 在 0 到 1 之间变化,就能让我们在从乐观到悲观的整个光谱上导航。换句话说,我们想要探索的那个权衡谱,现在可以通过一个在 0 到 1 之间变化的单一参数 T 来实现。


总结
本节课中,我们一起学习了如何利用分类模型输出的概率值,通过调整一个简单的决策阈值 T,来系统地权衡精确率与召回率。
- 将阈值
T设置得很高(例如 0.999)会得到一个悲观分类器,它具有高精确率、低召回率的特点。 - 将阈值
T设置得很低(例如 0.001)会得到一个乐观分类器,它具有低精确率、高召回率的特点。
通过平滑地调整T从 0 到 1,我们可以在两者之间找到满足特定业务需求的平衡点。
机器学习(分类,聚类和检索):第3-4课:精确率-召回率曲线 📈

在本节课中,我们将学习一个用于评估分类器性能的强大工具——精确率-召回率曲线。我们将了解如何通过调整分类阈值来权衡精确率和召回率,以及如何利用该曲线比较不同分类器的优劣。

上一节我们介绍了通过调整阈值可以在乐观分类器和悲观分类器之间切换。本节中,我们来看看一个能直观展示这种权衡关系的可视化工具。

精确率-召回率曲线是理解分类器性能的极其有用的工具。
以下是关于曲线两端点的解释:
- 当阈值非常接近1时:分类器变得非常“悲观”。此时,精确率会非常高(接近1),因为你只对极少数非常有把握的样本预测为正类,并且它们很可能是正确的。然而,召回率会非常低(接近0),因为你会漏掉绝大多数真正的正类样本。
- 当阈值非常接近0时:分类器变得非常“乐观”。此时,召回率会非常高(接近1),因为你几乎能找到所有真正的正类样本。但是,精确率会非常低,因为你也会将许多负类样本错误地预测为正类。
通过不断调整阈值 t,你可以在精确率和召回率之间获得一系列的权衡点。例如,如果你想要一个召回率稍高但仍保持高精确率的模型,可以设置 t = 0.8。如果你追求极高的召回率,并愿意牺牲一些精确率,可以设置 t = 0.2。你可以通过探索这条曲线来理解两者之间的权衡关系。
这种权衡关系并非总是无法避免的。一个完美的分类器,其精确率-召回率曲线会呈现一种理想形态。

理想情况下,无论召回率水平如何,精确率都能保持在1。这条位于顶部的水平线是所有分类器追求的目标。你的算法曲线越接近顶部这条水平线,其性能就越好。
因此,精确率-召回率曲线不仅可以用来理解单个分类器,还可以用于比较不同算法。
例如,假设你有两个分类器A和B。如果在曲线的每一个点上,分类器B的精确率都高于分类器A,那么无论阈值如何选择,分类器B总是更优的选择,因为它能在相同的召回率下提供更高的精确率。
然而,现实情况往往更为复杂。在实践中,你更可能遇到的是像分类器A和C这样的情况。

它们的曲线存在交叉。在某些精确率-召回率区域,一个分类器表现更好,而在其他区域,另一个分类器更优。
以下是具体的选择策略:
- 如果你关注高精确率,即使召回率较低也可以接受,那么应该选择分类器C,因为在该区域它的曲线位置更高。
- 如果你追求高召回率,那么应该选择分类器A,因为在召回率较高的区域(对应较小的阈值
t),它的表现更佳。
这体现了现实世界机器学习应用的复杂性。
如果你必须只选择一个分类器,问题就变成了:在这种情况下,如何在A和C之间做决定?通常你需要一个单一的数字指标来帮助决策。
这取决于你在精确率-召回率权衡曲线上的目标位置。存在许多试图用一个数字来概括性能的指标,例如 F1分数 或 曲线下面积。
对于许多应用,我个人更偏爱一个更简单但极其有用的指标,称为 K值精确率。
假设我的网站只有5个位置来展示句子。我只关心展示在前5位的句子质量,我希望它们尽可能都是好评。
在这种情况下,我关心的指标就是前K个结果的精确率,其中 K = 5。如果前5个句子中有4个是好评,1个是差评,那么我的 Precision@5 就是 4/5 = 0.8。
对于像推荐系统这样的应用,当你访问一个网页,系统向你展示一些你可能想购买的产品时,K值精确率是一个非常好的考量指标。

本节课中我们一起学习了精确率-召回率曲线。我们了解了它如何可视化精确率与召回率之间的权衡,如何用于比较不同分类器在特定需求下的优劣,并介绍了一个在实际应用中非常实用的单一指标——K值精确率。理解这些工具将帮助你更好地评估和选择适合具体场景的机器学习模型。
机器学习(分类,聚类和检索):第3-4课:精确率与召回率回顾 📊

在本节课中,我们将学习如何评估分类器的性能,特别是深入探讨精确率和召回率这两个核心概念。它们不仅是评估我们已讨论分类器的重要工具,也广泛应用于工业界的任何分类问题。
概述:为什么需要超越准确率?
仅仅使用准确率或错误率来评估模型可能并不适用于所有应用场景。因此,我们需要考察其他指标,而精确率与召回率通常是首要考察的对象。
精确率与召回率的定义

上一节我们介绍了评估分类器的必要性,本节中我们来看看精确率与召回率的具体含义。
- 精确率衡量的是,在所有被模型预测为正类的样本中,实际为正类的样本所占的比例。它关注的是预测结果的准确性。
- 公式:
精确率 = 真正例 / (真正例 + 假正例)
- 公式:
- 召回率衡量的是,在所有实际为正类的样本中,被模型正确预测为正类的样本所占的比例。它关注的是模型发现正类样本的全面性。
- 公式:
召回率 = 真正例 / (真正例 + 假反例)
- 公式:
精确率与召回率的权衡
理解了定义后,我们自然会面临一个问题:精确率和召回率之间通常存在此消彼长的关系。为了探索这种权衡,我们引入了决策阈值参数 T。
通过调整分类器输出概率的阈值 T,我们可以得到一系列不同的精确率和召回率组合,从而绘制出优美的精确率-召回率权衡曲线。这条曲线帮助我们直观地理解在不同操作点下模型的性能表现。
模型比较:Precision@K 指标
最后,我们来探讨一个在实际应用中非常实用的模型比较指标——Precision@K。
这个指标特别适用于推荐系统或信息检索等场景,它评估的是在模型返回的前K个结果中,相关结果(正例)所占的比例。以下是其核心要点:
- 定义:在模型预测的前K个最可能为正类的样本中,计算精确率。
- 用途:非常适合评估系统在返回有限数量结果时的性能,例如搜索引擎返回的前10条结果的质量。
总结
本节课中我们一起学习了:
- 认识到仅凭准确率评估模型的局限性。
- 掌握了精确率与召回率的定义与计算方法。
- 理解了二者之间的权衡关系,以及如何通过调整阈值 T 来探索这种权衡。
- 介绍了用于模型比较的 Precision@K 指标及其适用场景。
这些概念是构建和评估高效分类系统的基石。

(注:感谢我的同事Krishna Sriar,他在本模块的幻灯片制作和思想构建中提供了重要帮助。)
机器学习(分类,聚类和检索):第3-4课:大规模数据集的挑战与随机梯度上升法

在本节课中,我们将探讨机器学习领域一个至关重要的现实问题:如何将我们讨论过的算法扩展到真正庞大的数据集上。今天介绍的思想具有广泛的适用性,不仅适用于所有分类问题,也适用于回归课程或本专项课程的第二部分。我们将重点介绍一种名为随机梯度上升的技术,以及与之相关的在线学习概念,后者适用于从数据流中学习,即数据逐条到达的场景。
梯度上升法在大数据集上的局限性
上一节我们回顾了分类中的梯度上升法。现在,我们来看看数据集规模如何影响其运行。
假设我们有一个非常大的数据集和一组待更新的系数 W_t。我们使用梯度上升法,需要在整个数据集上计算梯度。这要求我们对数据进行一次完整的扫描或遍历,计算每个数据点对梯度的贡献。
计算完梯度后,我们更新参数,得到 W_{t+1}。
然而,为了进行下一次更新,我们必须再次回到数据集,进行另一次完整的遍历,计算新的梯度并更新参数,得到 W_{t+2}。
在这个过程中,每次系数更新都需要对全部数据进行一次完整扫描。如果数据量极其庞大,这个过程会变得非常缓慢。
当今数据规模的挑战
如今,数据正变得无比庞大。例如:
- 互联网上有约48亿个网页。
- Twitter每天生成约5亿条推文。
- 我们正步入“物联网”时代,遍布家庭和我们随身携带的设备(如智能手表)都在持续生成海量数据。
- 以YouTube为例,每分钟有300小时的视频被上传,同时拥有超过10亿用户。
对于机器学习而言,如何应对这些海量数据集是一个根本性的挑战。以YouTube的商业模式为例,其核心是通过向用户展示合适的广告来获得收入。关键数字并非每分钟300小时视频或10亿用户,而是每天40亿次的页面或视频观看量。对于每一次浏览,YouTube都需要决定展示哪些广告。这意味着他们需要一个能够每天处理数十亿次事件、并能在毫秒级内做出预测的机器学习算法,以便在用户观看视频时实时决定展示何种广告。显然,传统的梯度上升法无法满足这种对速度和规模的要求。
核心问题总结

本节课中,我们一起学习了传统梯度上升法在处理大规模数据集时的主要瓶颈:每次参数更新都需要遍历全部数据,这在数据量巨大时会导致计算效率极低,无法满足现代应用(如实时广告推荐)对速度和规模的要求。这引出了我们对更高效算法——随机梯度上升法的需求。
机器学习(分类,聚类和检索):第3-4课:可扩展机器学习的时间线与随机梯度

在本节课中,我们将要学习机器学习如何随着数据规模的演变而发展,并介绍一种名为随机梯度的关键技术,它使我们能够在海量数据集上训练复杂模型。
概述:机器学习与数据规模的演变
过去二十年间,数据集的规模持续增长。这一变化对机器学习的研究与实践产生了深远影响。了解这段历史,有助于我们理解当前主流算法背后的设计思想。
从复杂到简单,再到复杂
二十年前,数据集规模普遍较小。为了从有限的数据中榨取最高的准确率,研究者们致力于开发非常复杂的模型,例如核方法和图模型。
十年后,数据规模开始急剧增长,我们进入了所谓的“大数据”时代。由于当时的机器学习算法难以扩展到如此庞大的数据集,而数据量本身又非常充足,研究趋势又回归到了更简单的算法,例如逻辑回归和矩阵分解。甚至有论文讨论了“大数据集的非理性效力”,其核心观点是:面对海量数据,使用简单的线性分类器(如逻辑回归)可能击败复杂的图模型,因为后者在当时无法有效处理大规模数据。
然而,情况继续变化。如今,数据变得更大,我们的目标也更高——我们希望在超大规模数据集上构建更精确的模型。这迫使我们必须设计新型算法,将复杂模型扩展到海量数据上,以追求惊人的准确率。并行计算、GPU加速、大型计算机集群以及本节课将重点讨论的随机梯度等技术,正是在此背景下变得至关重要。
因此,机器学习的演进路径可以总结为:首先回归简单以处理大数据,如今则致力于开发能将复杂模型扩展到海量数据的新算法。这正是我们当前所处的阶段。
核心框架与随机梯度的引入
我们将回到本课程一直使用的框架:获取训练数据,提取特征并构建机器学习模型。但我们将对算法做一个微小的修改——将梯度下降改为随机梯度下降。这一修改将使我们能够扩展到更大的数据集,并且通常表现优异。
以下是随机梯度下降的核心思想:
它做了一件极其简单的事:在更新参数时,不再需要遍历全部数据来计算梯度。假设当前参数为 W_t,随机梯度下降不会使用所有数据计算梯度,而是随机查看数据的一小部分(一个子集),然后基于这一小部分数据计算出的梯度来更新参数,得到 W_{t+1}。接着,它再查看另一小部分数据,更新参数得到 W_{t+2},如此循环往复。
与传统的梯度下降需要完整遍历一遍数据后才进行一次参数更新不同,随机梯度下降以交错的方式,每看一小批数据就立即更新参数。这个小小的改变将为我们带来巨大的 scalability(可扩展性)优势。
总结

本节课中,我们一起回顾了机器学习随数据规模增长的演变历程:从小数据时代的复杂模型,到大数据初期的简单模型回归,再到如今追求在海量数据上扩展复杂模型的新阶段。我们重点介绍了随机梯度下降这一关键技术,它通过每次迭代仅使用数据的一个子集来更新模型参数,从而实现了对超大规模数据集的高效训练。
机器学习(分类,聚类和检索):第3-4课:为什么梯度上升法无法扩展 ⚙️



在本节课中,我们将探讨梯度上升法在处理大规模数据集时面临的计算挑战。我们将分析其计算成本,并理解为什么对于现代海量数据,传统的批处理方法变得不可行。
上一节我们介绍了梯度上升法的基本流程。本节中我们来看看其计算成本的具体构成。
在梯度上升法中,我们从参数空间的某个点开始,计算似然函数的梯度,然后沿梯度方向前进一小步。这个过程不断重复,直至收敛。右侧展示的算法正是我们在本模块中一直使用的方法。
那么,这个算法的计算代价有多大呢?让我们以逻辑回归为例来具体分析。
为了计算梯度,我们需要对每个数据点进行运算。你可以将其理解为每个数据点 (X_i, Y_i) 对梯度的贡献。我们将所有数据点的贡献相加,得到最终的梯度,并用于更新参数。
这里用 ∂L_i/∂W_j 表示第 i 个数据点对参数 W_j 的梯度贡献。我们的做法是汇总所有这些贡献,以计算用于参数更新的最终梯度。
那么,这种方法的计算成本如何呢?让我们通过几个例子来量化一下。
以下是几个计算成本的场景分析:
- 场景一:计算一个数据点的梯度贡献需要 1毫秒,并且我们拥有 10万个 数据点。那么总时间就是 0.1 秒,这完全可以接受。
- 场景二:模型更复杂(如神经网络),计算一个数据点的贡献需要 1秒,数据点数量为 1000个。那么总时间将达到 1000 秒,约合 16.7分钟。等待时间开始变得可观。
- 场景三:回到每个点1毫秒的情况,但数据量激增至 1000万个。总计算时间将变为 2.8小时。情况开始变得棘手。
- 场景四:考虑真正的海量数据,例如 100亿个 数据点,每个点仍只需1毫秒。总时间将高达 115.7天,大约 4个月。而这仅仅是计算一次梯度更新所需的时间。
请记住,在实际训练中,我们需要进行多次梯度更新才能达到收敛。因此,对于像YouTube这样每天产生数十亿数据点的场景,这种传统的批处理梯度上升法显然无法工作,我们必须寻找更高效的替代方案。


本节课中我们一起学习了传统梯度上升法在处理大规模数据时面临的计算瓶颈。通过量化分析,我们清楚地看到,当数据量达到百万乃至亿级时,计算单次梯度更新所需的时间会变得极其漫长,这使得该方法在实际的大规模机器学习应用中不可行。这引出了对更高效优化算法(如随机梯度下降)的需求。
机器学习:3-4:随机梯度下降法

在本节课中,我们将学习一种名为随机梯度下降的优化算法。该算法旨在解决传统梯度下降法在处理大规模数据集时计算成本过高的问题。我们将探讨其核心思想、工作原理,并与标准梯度下降法进行对比。
算法核心思想 🎯
上一节我们介绍了标准梯度下降法,它需要计算所有数据点的贡献总和来更新参数。本节中我们来看看随机梯度下降,它采用了一种截然不同的策略。
随机梯度下降的核心思想非常简单:不使用全部数据点来计算梯度,而是每次只使用一个数据点。这并非精确的梯度,而是对真实梯度的一种近似。每次进行参数更新时,我们都会随机选取一个不同的数据点来估计梯度方向。
这个简单的改变,正如我们将看到的,具有极其强大的效果。
深入理解算法 🔍
现在让我们深入理解这个改变:即使用少量数据(实际上仅一个数据点)来计算梯度,而不是使用整个数据集。
以下是逻辑回归的标准梯度上升算法公式,我们之前课程中已经见过,这里明确写出了梯度表达式:
标准梯度上升(逻辑回归):
w_new = w_old + η * Σ_{i=1}^{n} [ (y_i - P(y_i=1|x_i, w)) * x_i ]
这个公式要求对数据点求和,而这正是我们试图避免的操作。我们不希望在每次迭代更新时都对所有数据点求和。
因此,我们去掉这个求和符号。取而代之的是,我们引入一个外层循环,依次遍历数据点 1 到 n。对于每个数据点,我们计算仅基于该数据点的梯度,然后立即更新参数。我们一次只处理一个数据点。
随机梯度上升(逻辑回归):
对于 i = 1 到 n:
w_new = w_old + η * [ (y_i - P(y_i=1|x_i, w)) * x_i ]
在梯度上升中,我们对所有数据点求和;在随机梯度上升中,我们仅用一个数据点的贡献来近似整个梯度。接下来我们将探讨为什么这样做是有效的。
计算效率对比 ⚡
让我们回到之前的表格,对比分析执行一步梯度下降与随机梯度下降所需的总时间。
以下是不同数据规模下的计算时间对比:
-
计算一个数据点贡献耗时 1 毫秒,拥有 1000 个数据点:
- 梯度下降:
1 ms/点 * 1000 点 = 1 秒完成一次更新。 - 随机梯度下降:仅需
1 毫秒完成一次更新(因为它只查看一个数据点)。
- 梯度下降:
-
计算一个数据点贡献耗时 1 秒,拥有 1000 个数据点:
- 梯度下降:
1 秒/点 * 1000 点 = 1000 秒完成一次更新。 - 随机梯度下降:仅需
1 秒完成一次更新。
- 梯度下降:
-
计算一个数据点贡献耗时 1 毫秒,拥有 1000 万或 100 亿个数据点:
- 梯度下降:时间随数据量线性增长,分别为
10^7 毫秒和10^10 毫秒。 - 随机梯度下降:无论数据量多大,每次更新仍然只需要大约 1 毫秒。
- 梯度下降:时间随数据量线性增长,分别为
这看起来好得令人难以置信,在某种程度上确实如此。但需要记住的关键点是:虽然随机梯度下降的每次更新成本远低于梯度下降,但为了达到相似的优化效果,你可能需要比梯度下降多得多的更新次数。其优势在于,即使需要更多步数,每一步极低的成本使得处理海量数据成为可能。
总结 📝

本节课中我们一起学习了随机梯度下降法。我们了解到,该算法通过每次迭代仅随机使用一个数据点来估计梯度,从而极大地降低了单次参数更新的计算成本,使其能够高效处理大规模数据集。虽然每次更新方向不如标准梯度下降精确,且可能需要更多迭代次数才能收敛,但其卓越的计算效率使其成为现代机器学习中不可或缺的核心优化算法。
机器学习(分类,聚类和检索):第3-4课:比较梯度下降与随机梯度下降 🆚

在本节课中,我们将要学习梯度下降与随机梯度下降这两种优化算法的核心区别。我们将通过对比它们的计算效率、收敛行为以及实际应用中的挑战,来理解为何一个微小的算法改动能带来巨大的性能差异。
概述
上一节我们介绍了梯度下降的基本原理。本节中,我们来看看它的一个重要变体——随机梯度下降。我们将通过对比表格和收敛曲线图,直观地理解两者在速度、稳定性以及对大规模数据的处理能力上的不同。
梯度下降 vs. 随机梯度下降
以下是两种方法的对比表格,蓝色代表梯度下降,绿色代表随机梯度下降。
| 特性 | 梯度下降 (Gradient Descent) | 随机梯度下降 (Stochastic Gradient Descent) |
|---|---|---|
| 更新速度 | 对于大数据集较慢。每次更新需计算整个数据集的梯度。 | 快。每次更新只使用一个数据点,与数据集大小无关。 |
| 总训练时间 | 理论上是 O(N * I),其中 N 是数据量,I 是迭代次数。 |
理论上对于大数据集总是更快。实践中通常也更快。 |
| 参数敏感性 | 对步长等参数相对不敏感。 | 非常敏感。步长选择不当会导致严重问题。 |
| 收敛行为 | 平滑、稳定地收敛到最优解附近。 | 更快地接近高质量解,但会在最优解附近振荡。 |
| 可扩展性 | 处理海量数据(如十亿级)时计算成本过高。 | 能扩展到海量数据,即使在单台桌面电脑上也能处理。 |
收敛行为图解
为了更直观地比较,我们来看一下两者的收敛曲线图。下图展示了在多次遍历数据的过程中,模型对数似然(Y轴,越高越好)的变化。X轴表示接触过的数据点数量(或等效的数据遍历次数)。

- 红线(梯度下降):每完整遍历一次数据集(一个Epoch)才进行一次更新。在10次遍历后,其达到的对数似然值远低于随机梯度下降。
- 蓝线(随机梯度下降):每看到一个数据点就进行一次更新。它更快地达到了更高的对数似然值,但其路径不平滑,存在明显的振荡。
当我们把观察尺度扩大到100次数据遍历时,情况如下:

此时,梯度下降最终也能达到与随机梯度下降相近的解。然而,随机梯度下降的振荡特性依然非常明显——它的性能时好时坏,围绕最优解波动。理解并处理这种振荡,是有效使用随机梯度下降的关键挑战之一。
核心公式与代码描述
两者的核心区别在于梯度计算方式:
- 梯度下降:使用全部
N个数据点的平均梯度。
公式:θ_new = θ_old - η * (1/N) * Σ(∇L_i(θ_old)),其中i从1到N。 - 随机梯度下降:每次随机选取一个数据点
j,使用其梯度。
公式:θ_new = θ_old - η * ∇L_j(θ_old)。
代码示意:
# 梯度下降 (伪代码)
for epoch in range(num_epochs):
total_gradient = compute_gradient(entire_dataset, current_parameters)
parameters -= learning_rate * (total_gradient / dataset_size)
# 随机梯度下降 (伪代码)
for epoch in range(num_epochs):
for data_point in shuffled_dataset: # 遍历每个数据点
single_gradient = compute_gradient([data_point], current_parameters)
parameters -= learning_rate * single_gradient
总结
本节课中我们一起学习了梯度下降与随机梯度下降的对比。我们了解到,将算法从使用整个数据集计算梯度,改为仅使用单个数据点(即随机梯度下降),是一个微小的改动,却能带来巨大的好处:它能让你更快地获得更高质量的模型,并且能够处理规模高达数十亿的数据集。


然而,这种强大能力也伴随着挑战:随机梯度下降对学习率等参数更为敏感,并且其收敛过程存在振荡。在接下来的课程中,我们将重点探讨如何克服这些实际挑战,例如如何设置学习率、如何减少振荡等,从而充分发挥随机梯度下降的威力。
机器学习(分类,聚类和检索):第3-4课:为什么随机梯度会有效 😊

在本节课中,我们将探讨随机梯度下降算法背后的核心思想。我们将理解,为什么仅使用单个数据点来计算梯度方向,而不是使用所有数据点,仍然是一个有效且实用的优化方法。

上一节我们介绍了梯度下降算法。本节中,我们来看看对算法所做的一个微小但重要的修改:从计算所有数据点的梯度,改为每次只计算一个数据点的梯度。这个修改感觉很大,但它为什么有效呢?让我们花点时间建立一些直观理解,这有助于我们理解算法在实际中的行为。
梯度下降的“最佳”方向
首先,回顾一下我们情感分析问题的参数空间。下图展示了仅考虑两个特征(“awful”和“awesome”的系数)时,对数似然函数的等高线图。

假设我们从点 W_t 开始。如果我们计算所有数据点的精确梯度,我们会得到从 W_t 移动到 W_{t+1} 的最佳可能改进方向。这是理论上我们能做的最好的事情。
然而,存在许多其他方向也能改进目标函数(即提高似然值或模型质量)。例如,如果我们选择图中另一个方向,并到达某个参数 W',这仍然是可行的,因为它仍然在“上山”——我们仍在增加似然值。换句话说,W' 的似然值将大于 W_t 的似然值。因此,事实上,任何能带你上山的方向都是好的,梯度方向只是其中最好的那个。
梯度的构成与随机梯度的直觉
梯度方向是每个数据点贡献的总和。具体公式如下:
精确梯度 = Σ_{i=1}^{N} [对数据点 (x_i, y_i) 的贡献]
在上图中,每一条红线代表一个数据点 (x_i, y_i) 对梯度的贡献。有趣的是,大多数贡献都指向“上山”的方向(如图中靠前的红线)。所以,如果我随机选择这些贡献中的任何一个,我大概率会朝着一个能取得进展的方向前进。
当然,也存在一些“坏”的方向(如图中靠后的红线),选择它们会导致负向进展(似然值下降)。但关键在于:平均而言,大多数方向是好的。这就是随机梯度下降有效的原因。
随机梯度下降的工作原理
在随机梯度下降算法中,我们每次只随机选取一个数据点,计算该点贡献的方向,并沿着这个方向迈出一小步。
以下是算法运行的直观过程:
- 第一步,我们可能选取数据点1,并取得一些正向进展。
- 第二步,我们可能选取数据点2,这次可能产生负向进展。
- 第三步,我们选取数据点3,再次取得正向进展。
- 第四步,选取数据点4,正向进展。
- 如此继续……
虽然偶尔会选到“坏”的方向导致暂时后退,但大多数时候我们都在取得正向进展。从整体和长期来看,模型的似然值是在不断改善的。算法通过大量的小步,在噪声中曲折但坚定地向上攀登。

本节课中我们一起学习了随机梯度下降有效的核心直觉。我们明白了精确梯度是最佳方向,但它由许多数据点的贡献组成,其中大多数贡献本身也是“上山”的好方向。随机梯度下降通过每次随机采用其中一个方向,虽然步调有噪声且不稳定,但长期平均效果是正向的,最终能引导我们找到较好的解。这种用计算效率换取一定噪声的策略,在实践中被证明是非常成功的。
机器学习(分类,聚类和检索):第3-4课:收敛路径 🧭

在本节课中,我们将学习梯度下降与随机梯度下降在优化过程中的收敛路径有何不同。我们将通过可视化对比,理解两者在寻找最优解时的行为差异,并总结它们各自的优缺点。
上一节我们介绍了梯度下降与随机梯度下降的基本概念,本节中我们来看看它们在实际优化过程中的收敛路径。

可视化收敛路径

接下来,让我们可视化梯度下降与随机梯度下降所采取的路径,我称之为收敛路径。你将看到,随机梯度下降的路径振荡更多,但它能让你接近最优解。

与之前一样,黑色线条表示梯度下降的路径。你可以看到这条路径非常平滑,表现良好。红色线条表示随机梯度下降的路径。你可以看到这是一条噪声更多的路径。它确实能将我们带到正确的解附近,但需要注意的一点是,它不像梯度下降那样完全停止收敛,而是在最优解附近振荡。


当我们讨论如何在实践中应用随机梯度下降时,这将是我们需要解决的实际问题之一,而且是一个重要问题。
目标函数曲线视图
随机梯度下降在最优解附近振荡的另一种视图,可以在我们使用了很久的这张图中看到。你可以看到梯度下降在平滑地取得进展,而随机梯度下降在取得进展和收敛时,其曲线是带有噪声的,并在最优解附近振荡。
以下是两种方法在目标函数值变化曲线上的表现对比:
- 梯度下降曲线平滑下降。
- 随机梯度下降曲线呈噪声状下降并最终在最优值附近振荡。
核心概念总结
现在,让我们总结一下梯度下降与随机梯度下降的核心机制。
梯度上升(下降)寻找最陡上升(下降)方向以取得最大改进,其实现方式是对所有可能的数据点进行求和。其更新公式的核心部分是计算整个数据集的梯度:
gradient = sum_over_all_data_points( gradient_for_each_point )
随机梯度下降则试图找到一个通常能取得进展的方向。例如,通过随机选取一个数据点来估计梯度。平均而言,它能取得巨大进展。正因如此,它的收敛速度往往快得多,但在最优解附近噪声更大。
以下是两种方法特点的简要对比:
- 收敛速度:随机梯度下降快得多(在今天的简单例子中,它比梯度下降快100倍以上)。
- 收敛行为:梯度下降平滑收敛;随机梯度下降在终点处变得嘈杂(振荡)。




本节课中我们一起学习了梯度下降与随机梯度下降的收敛路径。我们通过可视化对比看到,梯度下降路径平滑,而随机梯度下降路径噪声大、振荡多,但收敛速度显著更快。理解这些差异有助于我们在实际应用中根据需求选择合适的优化算法。
机器学习(分类,聚类和检索):第3-4课:在运行随机梯度前打乱数据

在本节课中,我们将要学习随机梯度下降算法中的一个重要实践步骤:打乱数据。我们将探讨为什么这个步骤至关重要,以及如何正确实施它。
概述

随机梯度下降是一种高效的优化算法,但在实际应用中存在一些需要注意的问题。其中,数据顺序对算法性能的影响是一个关键问题。本节我们将详细讨论这个问题及其解决方案。
回顾随机梯度下降算法
上一节我们介绍了随机梯度下降的基本概念,本节中我们来看看其具体算法步骤。
随机梯度下降算法的步骤如下:
- 初始化参数(例如系数)为某个值,比如全0。
- 在达到收敛条件前,每次处理一个数据点和一个特征。
- 通过计算该单个数据点的梯度来更新该特征的系数。
这意味着我们逐个数据点地扫描数据,并逐个更新参数。例如,处理第一个数据点后,根据其预测误差更新参数;接着处理第二个数据点,再次更新,依此类推。
数据顺序带来的问题
然而,这种逐个处理的方式存在一个潜在风险:如果数据本身是按照某种特定方式隐式排序的,算法可能会表现出不良行为。
例如,假设所有负样本数据点都排在所有正样本数据点之前。在算法运行时,它会连续多次收到负样本,从而连续多次向负方向更新参数。这可能导致参数更新路径出现偏差,影响算法的实际性能和收敛速度。
这种情况在实际数据中很常见,比如数据可能按时间、年龄、地区或其他属性排序。
解决方案:打乱数据
为了解决数据顺序带来的问题,在开始运行随机梯度下降算法之前,必须始终打乱数据的行顺序。
打乱数据的目的是混合所有数据点,避免出现长时间连续的同类样本区域(例如连续的负样本或正样本,或来自同一地区的人群)。我们希望数据是充分混合的。
从算法实现的角度来看,这意味着需要在随机梯度下降循环开始之前,增加一行代码来打乱数据。
代码示例:
# 在开始随机梯度下降前,打乱数据顺序
shuffled_data = original_data.sample(frac=1).reset_index(drop=True)
# 然后使用 shuffled_data 进行后续的随机梯度下降迭代
总结

本节课中我们一起学习了随机梯度下降算法中一个关键的实践步骤:打乱数据。我们了解到,数据的原始顺序(如按标签排序)会导致参数更新出现偏差,从而影响算法性能。因此,在运行随机梯度下降之前,务必先随机打乱数据集,这是确保算法稳定性和效果的重要预处理操作。
机器学习(分类,聚类和检索):第3-4课:选择步长

在本节课中,我们将要学习随机梯度下降中一个关键且具有挑战性的环节:如何选择步长(学习率)。步长的选择直接影响算法的收敛速度与稳定性,是实践中的一项重要技巧。
步长选择的重要性与挑战
上一节我们介绍了随机梯度下降的基本原理,本节中我们来看看如何为其选择合适的步长。步长,通常用符号 η 表示,决定了每次参数更新的幅度。与普通梯度下降类似,步长选择不当会导致问题,但由于随机梯度下降固有的振荡特性,这个问题变得更加棘手和令人困扰。
步长过小或过大的影响


以下是不同步长选择对算法行为的影响:
- 步长过小:如果选择的步长 η 过小,算法收敛速度会非常缓慢。虽然振荡会减少,但需要更多迭代次数才能达到最优解附近。
- 步长适中:存在一个最佳的步长范围,能够使算法以相对较快的速度收敛,同时保持可控的振荡。
- 步长过大:如果步长 η 过大,算法会产生剧烈且不稳定的振荡。这种振荡比普通梯度下降中观察到的要严重得多。在极端情况下,参数更新会完全失控,导致解严重偏离最优值,甚至无法收敛。
选择步长的经验法则
选择随机梯度下降步长的经验法则与普通梯度下降基本相同,但通常需要更多的试错过程。尽管随机梯度下降收敛更快,但寻找合适步长所花费的精力可能成倍增加。
以下是选择步长的一般步骤:
- 准备一系列呈指数级间隔的 η 候选值(例如 0.001, 0.01, 0.1, 1)。
- 在小规模数据或早期迭代中测试这些值。
- 观察训练误差或目标函数值的下降曲线。
- 目标是找到一个介于“过小”(下降太慢)和“过大”(剧烈振荡或不收敛)之间的“刚刚好”的步长。
进阶技巧:衰减步长
对于希望深入探索的学习者,有一个进阶技巧是让步长随着迭代进行而衰减。这种方法有助于减少噪声,使算法行为更加稳定。
一种常见的衰减策略是将步长设置为迭代次数的函数,例如:
η_t = η_0 / t
其中,η_t 是第 t 次迭代时的步长,η_0 是初始步长,t 是当前的迭代次数。这种策略能确保在初期快速进展,在后期精细调整。


本节课中我们一起学习了为随机梯度下降选择步长的方法。我们了解到步长选择至关重要,过小会导致收敛缓慢,过大会引起剧烈振荡甚至发散。实践中的核心方法是进行系统的试错,以找到一个平衡点。此外,我们还介绍了一种让步长随时间衰减的进阶策略,以提升算法稳定性。掌握这些技巧对于成功应用随机梯度下降算法至关重要。
机器学习(分类,聚类和检索):第3-4课:不要相信最后的系数

在本节课中,我们将要学习随机梯度下降法的一个关键特性:它在最优解附近振荡。因此,我们不能简单地信任算法最后找到的参数。我们将介绍一种简单而有效的技术——参数平均法,来获得更稳定、更可靠的最终模型参数。
随机梯度下降的振荡现象
上一节我们介绍了随机梯度下降的基本原理,本节中我们来看看它在收敛过程中的一个具体行为。
正如我们在图表中所见,随机梯度下降倾向于在最优解附近振荡。因此,你永远不应该信任它找到的最后一个参数。

批量梯度下降与随机梯度下降的对比
相比之下,批量梯度下降最终会稳定在最优解上。即使它花费的时间要长得多,比如在这个例子中显示的需要100倍甚至更长的时间(注意X轴的时间尺度),但当你到达那里时,你会感觉非常好。
而随机梯度下降,当你认为它收敛时,实际上它只是在最优解附近振荡。这种行为可能导致糟糕的实际应用效果。
振荡带来的实际问题
以下是振荡行为可能导致的具体问题:
例如,这里给出一些数值说明,在第1000次迭代时的参数 W 可能看起来非常糟糕,但也许在第1005次迭代时的 W 看起来又非常好。因此,我们需要某种方法来最小化选中一个非常糟糕的参数或一个非常好的参数的风险。
解决方案:参数平均法
幸运的是,存在一种在实践中效果非常好、在理论上也应该被采用的简单技术。所有的相关定理都要求类似的做法。
该技术指出:当你确定最终系数 W_hat 时,不要使用最后一个值 W_T(T是最终迭代次数),而应该使用你在整个过程中计算过的所有值的平均值,即所有计算过的系数的平均。
用公式表示,最终的参数 W_hat 应为:
W_hat = (1/T) * Σ_{t=1}^{T} W_t
这里展示的是算法在拟合解决方案、以便在现实世界中进行预测时,应该输出的内容。



总结

本节课中我们一起学习了随机梯度下降法在最优解附近振荡的特性,并理解了为何不能直接信任其最后迭代得到的参数。我们介绍了一种有效的解决方案——参数平均法,即取所有迭代过程中参数的平均值作为最终模型参数。这种方法在理论上得到支持,在实践中也被证明能显著提升模型的稳定性和可靠性。
机器学习(分类,聚类和检索):第3-4课:可选:从数据批次中学习

在本节中,我们将探讨随机梯度下降算法中的一个重要实践技巧:使用数据批次进行学习。我们将了解为什么仅使用单个数据点可能存在问题,以及如何通过处理一小批数据点来获得更稳定、更高效的优化过程。
上一节我们介绍了基本的随机梯度下降,本节中我们来看看如何通过处理多个数据点来改进它。
为什么使用批次?
仅使用一个数据点进行学习通常会产生过多的噪声。通常,我们会使用几个数据点,这被称为小批次。
到目前为止,我们已经说明了两种极端情况:
- 批量梯度下降:使用全部
N个数据点来更新系数。 - 随机梯度下降:仅使用一个数据点来更新系数。
那么,是否存在一种折中方案,让我们每次查看 B 个数据点(例如100个)呢?这就是小批次方法。它能减少噪声,提高稳定性,是一种正确的做法。顺便提一下,100是一个非常好的批次大小数值。
下图展示了我们在研究同一问题时,批次大小为1和批次大小为25的收敛路径对比:


从中我们可以观察到两点:
- 批次大小为25的收敛路径更加平滑,这是一件好事。
- 更有趣的是,当接近最优解时,批次大小为1的路径会在最优点附近剧烈振荡,而批次大小为25的路径振荡更小,行为更好。这种更好的行为使得该方法在实践中更易于使用。因此,使用小批次是一个极佳的选择。
选择批次大小的重要性
现在,我们在随机梯度算法中引入了一个需要调整的新参数:批次大小 B。


以下是选择不同批次大小的影响:
- 如果
B太大:它的行为会类似于批量梯度下降。例如,如果使用批次大小B = N,那它就完全是批量梯度下降算法。在下图中,红线代表批次大小过大的情况。 - 如果
B太小:会产生不良的振荡或整体表现不佳。在下图中,批次大小太小导致收敛效果不理想。 - 如果选择了合适的
B:你会获得非常好的行为,能快速得到一个优秀的解并稳定在其附近。
因此,选择合适的批次大小会产生巨大的影响。

算法实现:引入批次概念
现在,让我们回到简单的随机梯度算法,并通过引入批次大小的概念来修改它。

我们不再一次查看一个数据点,而是一次查看一个批次。对于一个大小为 N 的数据集,如果批次大小为 B,那么我们将有 N / B 个批次。例如,如果我们有10亿个数据点,批次大小为100,那么就有 1,000,000,000 / 100 个批次。
我们逐个批次进行处理。在计算梯度时,我们现在考虑该小批次中的 B 个数据点,而不是单个数据点。下面的公式展示了其背后的数学原理:本质上是使用这 B 个数据点来估计梯度,而不是使用1个或10亿个数据点。
小批次梯度更新公式:
对于每个批次(包含 B 个数据点):
梯度估计 = (1/B) * Σ(对于批次中的每个数据点 i 计算其梯度)
系数更新 = 旧系数 - 学习率 * 梯度估计

总结

在本节课中,我们一起学习了随机梯度下降的一个重要改进:小批次学习。我们了解到,使用单个数据点更新参数噪声过大,而使用全部数据点计算成本又太高。小批次方法通过每次使用一小批数据(如100个)来估计梯度,在计算效率和稳定性之间取得了良好的平衡。它能带来更平滑的收敛路径,并在最优点附近表现出更稳定的行为,是实践中非常推荐使用的技巧。
机器学习(分类,聚类和检索):第3-4课:可选:测量收敛性 📈

在本节中,我们将探讨一个非常实际的问题:如何测量随机梯度下降算法的收敛性。如果每次都需要遍历整个数据集来计算收敛情况,那么使用随机梯度下降的意义就不大了。因此,我们需要新的技术来高效地评估算法是否正在向最优解前进。
上一节我们讨论了随机梯度下降的基本原理,本节中我们来看看如何在实际操作中监控其收敛过程。
如何测量收敛性?
在讲解具体方法前,我们先看一个现象。下图展示了随机梯度下降在单次遍历数据前就接近最优解,而批量梯度下降可能需要100次或更多次遍历才能达到类似效果。

这里存在一个矛盾:如果为了绘制上图中每一个蓝点(代表每次迭代的状态),我们都必须计算整个数据集的似然度,那就意味着每次迭代都要完整遍历一次数据。这会使整个过程变得非常缓慢,失去了随机梯度下降“高效”的优势。我们几乎可以直接使用完整的批量梯度下降了。因此,我们需要重新思考如何计算和展示收敛进度。
一个简单而巧妙的技巧
接下来,我们将介绍一个非常简单、有效且巧妙的方法。我们以逻辑回归的随机梯度上升算法为例,这是我们一直在使用的算法。该算法逐个处理数据点,并计算其对梯度的贡献,我们称之为 partial_J。
现在,如果我们想计算数据的对数似然度以评估当前模型的质量,我们需要为每个数据点计算以下公式:
- 如果数据点是正例(
y_i = +1),则计算log( P(y=+1 | x, w) )。 - 如果数据点是负例(
y_i = -1),则计算log( 1 - P(y=+1 | x, w) )。
这里有一个美妙之处:计算单个数据点似然度所需的公式,与计算该数据点梯度贡献的公式核心部分是相同的。这意味着,在每次迭代 t 中,当我们为当前数据点计算梯度更新时,我们已经顺便计算出了该数据点的似然度。
这很棒,因为我们虽然不能为所有数据点计算(那样成本太高),但可以为当前处理的这一个数据点计算。
从单点似然到平滑曲线
然而,我们不能直接用单个数据点的似然度来衡量整体收敛性,因为可能偶然对某个点分类很好,但对其他点不好,这样得到的信号会非常嘈杂。
为了更平滑、更可靠地衡量进度,我们可以这样做:在每次迭代时,我们不仅计算当前数据点的似然度,还维护一个最近若干个数据点似然度的移动平均值。例如,如果我们想评估第75次迭代后的表现,可以查看最近处理的几十个数据点的似然度,并计算它们的平均值。
通过这种方式,我们可以构建一条平滑的曲线来反映算法性能的整体趋势,而不是受单个数据点噪声影响的剧烈波动。
以下是实现这一过程的关键步骤:
- 初始化:设定移动平均窗口的大小(例如,最后30个数据点)。
- 迭代计算:在每次随机梯度下降迭代中,计算当前数据点的似然度。
- 更新平均值:将这个新的似然度值加入移动平均序列,并移除最旧的值(如果序列已满),然后计算新的平均值。
- 绘制图表:将每次迭代得到的移动平均值绘制出来,即可得到反映收敛趋势的平滑曲线。
实例说明
最后,让我们揭秘之前展示的图表是如何绘制的。图中的蓝线并非基于完整的梯度计算,而是使用了大小为100的小批量数据,这仍然比批量梯度下降收敛得快得多。而为了绘制这条蓝线,我计算了最后30个数据点似然度的移动平均值。


这就是构建收敛性图表的方法,也是你在实施整个随机梯度下降过程中需要采用的方法。


本节课总结:我们一起学习了如何高效地测量随机梯度下降算法的收敛性。核心在于利用计算梯度时已得到的中间结果来获取单点似然度,并通过计算最近若干数据点似然度的移动平均值来构造一条平滑的收敛曲线,从而在避免遍历整个数据集的前提下,有效监控算法的训练进度。这是一个既实用又巧妙的技术。
机器学习(分类,聚类和检索):第3-4课:可选:添加正则化 🧠

在本节中,我们将探讨如何在随机梯度下降算法中引入正则化。正则化是防止模型过拟合的关键技术,理解其在随机梯度更新中的处理方式对于实现一个健壮的机器学习算法至关重要。

上一节我们介绍了随机梯度下降的基本原理,本节中我们来看看如何将正则化项整合到随机梯度更新的框架中。
首先,让我们回顾一下带正则化的目标函数。在逻辑回归等模型中,我们通常优化一个由两部分组成的总体目标:衡量数据拟合程度的对数似然,以及衡量参数复杂度的正则化项。具体公式如下:
总目标 = 对数似然 - λ * 参数复杂度
其中,λ 是一个权衡两项重要性的超参数。当我们使用 L2 正则化时,参数复杂度通常用参数向量 w 的 L2 范数的平方来表示,即 ||w||²。
为了通过梯度下降优化这个总目标,我们需要计算其梯度。总梯度由两部分组成:
- 对数似然部分对每个数据点的梯度贡献之和。
- 正则化部分对参数的梯度贡献。
对于 L2 正则化,正则化部分对第 j 个参数 w_j 的梯度贡献是 -2λ w_j。因此,在标准(批量)梯度下降中,每次更新会用到所有数据点的梯度之和以及这个正则化项。
那么,在随机梯度下降中该如何处理正则化呢?随机梯度下降的核心思想是,每次更新只使用一个(或一小批)数据点的梯度来近似整个数据集的梯度。为了保证这种近似的有效性,我们需要确保所有随机梯度贡献的总和等于完整的梯度。
以下是实现这一点的关键步骤:
为了在随机梯度更新中保持这种一致性,我们需要将正则化项也“分摊”到每个数据点上。一种标准的做法是,将正则化项的梯度贡献除以数据点的总数 n。
因此,对于单个数据点的随机梯度更新,其总梯度贡献变为:
单个数据点的梯度贡献 = 该数据点的似然梯度 - (2λ / n) * w_j
这样,当我们对所有 n 个数据点的随机梯度贡献进行求和时,正则化部分的总和恰好是 -2λ w_j,与批量梯度下降中的正则化梯度完全一致。
如果使用小批量梯度下降,处理方式也类似。假设小批量的大小为 B,那么在该小批量上的更新中,正则化项的贡献需要调整为:
小批量正则化贡献 = - (2Bλ / n) * w_j
这相当于将这个小批量视为 B 个独立数据点,每个点贡献 (2λ / n) * w_j,然后求和。
综上所述,在随机梯度下降中引入正则化只需要对更新规则做一个微小的调整:将正则化系数 λ 缩放为 λ / n(对于单个数据点)或 Bλ / n(对于小批量)。这个调整确保了随机梯度期望与全批量梯度一致,是实践中实现带正则化随机梯度下降的推荐方法。


本节课中我们一起学习了如何在随机梯度下降中整合正则化。核心在于调整正则化项的权重,使其在随机更新中能被正确“分摊”,从而保证优化过程的收敛性和防止过拟合的效果。记住这个简单的缩放规则,你就可以在自己的实现中轻松加入正则化了。
机器学习(分类,聚类和检索):第3-4课:在线学习任务 🎯

在本节课中,我们将要学习在线学习的概念。我们将回顾之前学习的批量学习,并对比介绍数据随时间到达的在线学习模式。我们将通过一个实际的广告定向投放例子,来理解在线学习如何工作及其重要性。
从批量学习到在线学习 🔄

上一节我们介绍了随机梯度下降,这是一种对梯度下降的简单修改,在实践中能显著加速计算,但也带来了一些挑战及其应对方法。
现在,让我们退一步,思考一个更广泛的问题:如何从流式数据中学习?我们将看到,随机梯度下降正是处理随时间到达或流式数据的一种方法。
这就是在线学习的核心思想。但首先,让我们看看到目前为止我们一直在做什么。
在本课程以及回归课程中,我们一直在进行的是批量学习。我获得一个完整的数据集,然后运行某个学习算法(可能是梯度下降,或在数据上进行小批量处理),最终输出我对系数的最佳估计,我们称之为 W_hat。完成后,学习过程就结束了。这就是批量学习。
在线学习则有所不同。实际上,你们在这里所做的也是一种在线学习,但那是另一种类型。我们这里讨论的是在线机器学习。在在线机器学习中,数据是随时间到达的,一次一个数据点。
例如,我们接下来会看到,在网页上投放广告就是一个例子,事情一次只到达一个数据点。因此,数据是不断流入的,机器学习算法每次只看到一小部分数据。
- 在时间步1,它接收一小部分数据,并对系数做出一个估计,比如 W_hat1。
- 然后在时间步2,它看到另一小部分数据,做出另一个系数估计 W_hat2。
- 在时间步3,它做出另一个估计 W_hat3。
- 时间步4,它获得更多一点数据,做出估计 W_hat4。
所以,每个时间步都在生成一个新的估计,从而可以做出新的预测。
一个实际案例:广告定向投放 📈
为了更好地理解这些概念,让我们看一个在线学习发挥巨大作用的、非常实际的现实世界例子:广告定向投放。
假设你正在浏览网页,访问了一个特定的网站。当你看到广告时,幕后发生了什么?
一些关于你的信息(比如你的年龄或访问过的网站)以及关于网站本身的信息(比如网站文本)会被输入到一个机器学习算法中。这个算法将使用一组系数 W_hat_T 来确定向你展示哪些广告最好。我们称算法建议的广告为 y_hat,它可能会向你展示广告A1、A2、A3等等。
你看着网站,心想:“哇,那个广告真有意思!”于是你点击了广告A2。
当你点击广告A2时,机器学习算法会得知你点击了A2,并将 y_T(即它本应在网站上展示的广告的真实标签)分配为A2——这就是你点击的内容。
然后,机器学习算法会利用这个新的 y_T,将其系数从 W_hat_T 更新到 W_hat_{T+1}。
我们到目前为止描述的,实际上正是许多广告系统在实践中的工作方式。这虽然是一个简化的抽象,但确实是现实世界中产生巨大影响的事物。
总结 📝


本节课中我们一起学习了在线学习。我们首先回顾了批量学习,然后引入了数据流式到达的在线学习概念。通过广告定向投放的具体案例,我们看到了在线学习如何实时接收数据、做出预测、根据反馈(如用户点击)更新模型,从而不断适应变化的环境。随机梯度下降是实现这种在线更新的一种有效方法。理解在线学习对于处理实时数据流和构建自适应系统至关重要。
机器学习:第3-4课:使用随机梯度进行在线学习

在本节课中,我们将要学习一种称为“在线学习”的机器学习范式。我们将探讨其核心概念、工作原理,并重点介绍随机梯度下降算法如何作为在线学习的一个有效工具。
概述
在线学习是一种处理随时间到达的数据流的学习方法。在这种模式下,模型需要即时对新数据点做出预测,并根据真实世界的反馈立即更新自身参数。这与传统的批量学习(一次性处理所有数据)形成对比。
在线学习问题示例
上一节我们介绍了在线学习的基本概念,本节中我们来看看一个具体的应用场景。
数据随时间到达。你看到一个输入 X_t,需要做出预测 ŷ_t。例如,输入可能是网页上的文本或关于你的信息,而 ŷ_t 可能是对你可能点击哪个广告的预测。
然后,根据真实世界发生的情况(例如,你点击了广告2,则 y_t 为“ad2”;或者你什么都没点击,则 y_t 为“无”),这个真实标签 y_t 会被反馈给机器学习算法。算法利用这个反馈来改进其系数,从而随时间提升性能。
适用于在线学习的算法
那么,如何设计一个能像这样随时间改进性能的机器学习算法呢?一个好的例子是什么?
事实证明,我们已经见过一个这样的算法:随机梯度下降。
随机梯度下降是一种可以用于在线学习的算法。我们来回顾一下它的流程。
首先,给定一个初始系数集(例如,全部设为0)。在每个时间步 t,你会获得一个输入 X_t。你可以基于当前的系数估计值做出预测 ŷ_t。
然后,你会得到一个真实标签 y_t。你希望将这些信息输入一个算法。随机梯度下降将接收这些输入,并用它们来计算梯度,然后立即更新系数。更新公式如下:
w_j(t+1) = w_j(t) + η * gradient_j(t)
其中,梯度是根据从现实世界观察到的量(X_t, y_t, ŷ_t)计算得出的。
在线学习的优势与挑战
在线学习是本专项课程中尚未深入讨论的一种不同类型的学习,但在实践中非常重要。当数据随时间到达,并且你需要立即决定如何处理它时,基于该决策你将获得一些反馈,并立即更新参数,然后继续处理后续数据。
这种在观察到现实世界信息后立即更新参数的方法非常有用。以下是它的主要优势:
- 模型实时性:模型始终基于最新的数据和世界信息,保持最新状态。
- 计算成本低:你可以使用像随机梯度下降这样的技术,它不需要查看所有数据。事实上,如果数据量过大,你甚至不需要存储所有数据。
然而,在线学习也带来了一些实际挑战:
- 系统复杂性:构建实际系统(包括数据如何与世界交互、参数存储在哪里等)非常复杂,难以维护。
- 性能波动风险:如果你的机器学习算法出现振荡,它可能会做出非常糟糕的决策。没有人希望他们的网站做出愚蠢的行为,并且他们不一定完全信任这些即时的随机梯度更新。
- 预测风险:有时它可能给出糟糕的预测。
因此,在实践中,大多数公司并不完全采用这种严格的在线学习模式。他们通常会将数据保存一小段时间(例如最近一小时、一天或一周的数据),然后使用这些数据批量更新模型。这种做法非常普遍。
例如,一个大型零售商可能每晚更新其推荐系统,并运行一个大型服务来完成此任务。你可以将其视为我们在本模块前面讨论过的“小批量”学习的极端版本,只不过这里的“批量”是一整天的全部数据(例如,对YouTube来说,可能是50亿次页面浏览的数据)。
总结

本节课中我们一起学习了在线学习的概念。我们了解到,在线学习适用于数据流式到达、需要即时预测和更新的场景。随机梯度下降算法是实现在线学习的一个核心工具,它通过逐个数据点地更新模型参数来适应新信息。虽然在线学习具有模型实时和计算高效的优势,但其系统复杂性和潜在的性能波动使得许多公司在实践中采用折衷的“近线”学习方式,即定期使用近期数据批量更新模型。理解这种学习范式有助于我们根据实际应用需求选择合适的机器学习策略。
机器学习:第3-4课:通过并行化扩展到超大数据集:模块回顾


在本节课中,我们将总结关于扩展到大型数据集和在线学习的核心内容。我们回顾了随机梯度下降如何解决大规模数据问题,并简要探讨了更高级的并行与分布式计算方法。
上一节我们介绍了随机梯度下降,本节中我们来看看其他扩展机器学习算法到超大规模数据集的方法。
并行与分布式计算
随机梯度下降是扩展到大型数据集的一种方法,但这并非唯一途径。实际上,许多扩展工作涉及利用多核处理器进行计算。现代处理器通常拥有多个核心,这使得并行计算成为可能。
此外,我们还可以使用大型计算机集群,这些集群可能包含数十台、数百台、数千台甚至数十万台机器。这要求我们使用新型的机器学习算法。
以下是这类算法的关键特点:

- 分布式与并行算法:这类算法可以分布在数千台机器上运行。
- 研究重要性:这是一个非常重要的研究领域,也是我个人研究的重点,即如何设计分布式机器学习算法。
- 课程限制:遗憾的是,在当前课程中我们没有时间深入探讨这个主题。

核心收获总结
本节课中我们一起学习了随机梯度下降及其扩展方法。
总结来说,我们对梯度下降算法进行的小幅修改,可以带来整体运行时间的惊人提升,这在实践中意义重大。虽然随机梯度下降伴随许多实际挑战,但它极其有用。

此外,我们在此看到的同类技术也可应用于在线学习。在线学习是一种完全不同类型的机器学习,同样具有重大的实践意义。
机器学习(分类,聚类和检索):第3-4课:欢迎并介绍聚类和检索任务 😊

在本课程中,我们将深入学习聚类和检索这两种广泛应用的机器学习工具。我们将探讨它们的基本概念、模型与算法,并通过实际案例理解其应用。

概述

聚类和检索是机器学习中两种强大且普遍使用的工具。它们可用于多种场景,例如寻找与当前浏览商品相似的产品,或发现具有相关医疗状况的患者群体。在基础课程中,我们已对聚类和检索的概念进行了高层介绍。现在,我们将深入探讨其背后的模型与算法。
课程结构与预备知识


本课程是一个专项课程的一部分,该系列课程设计为按特定顺序学习。虽然您可以单独学习本课程,但为了获得预期的完整学习体验,我们强烈建议您按顺序学习整个系列。
具体来说,在基础课程中,我们概述了整个专项课程将涵盖的概念。随后,我们在回归和分类课程中深入学习了更详细的内容。这些课程中介绍的通用机器学习概念,将在本聚类与检索课程中再次出现。在本介绍的后半部分,我们会列出您需要预先了解的核心概念列表。
第一部分:检索任务与最近邻搜索
首先,让我们概述本课程的主要内容。请记住,在机器学习基础课程中,我们提到机器学习是关于从数据中提取智能。
在本课程的第一部分,我们将要学习的机器学习方法是用于检索任务的最近邻搜索。具体而言,输入将包括一个特定查询点的特征,以及数据集中所有其他数据点的特征。输出将是查询点的最近邻,即整个数据集中与该查询点最相似的点。
进行最近邻搜索需要遍历所有其他数据点,计算它们与查询点的相似度或距离,然后返回最接近的那个点。
我们将使用一个贯穿本课程的示例:假设我们拥有大量文档,而用户正在阅读其中一篇特定文档(即此处的灰色查询文章)。假设用户喜欢这篇文章,我们希望检索另一篇他们可能也喜欢的相似文章。这就是寻找最近邻的任务。但有时,我们可能希望检索一组最近邻,即一组相似的文档展示给用户。
我们将仅基于文档的文本(即数据点的特征)在所有文档中执行此搜索以检索这些最近邻。检索应用几乎无处不在:例如,我们可能有一张图片,希望找到一组相似的图片;或者我们在购物时,希望获得一组其他可能考虑购买的相似商品;又或者,正如我们讨论的,在阅读文章时希望阅读相关主题的文章。这种想法也出现在许多流媒体场景中,例如听歌、看电影或电视剧时,系统会推荐一组您可能也感兴趣的其他歌曲、电影或电视剧。又或者,作为社交网络的用户,基于您的用户特征,系统会推荐您可能希望连接的其他用户。
总的来说,检索相似项的理念是一个非常强大的工具。在本课程中,我们将讨论提供此类搜索的方法。
第二部分:聚类任务
在本课程的第二部分,我们将转向作为机器学习方法的聚类。这里的输入是数据集中每个数据点关联的特征,输出将是与每个数据点关联的聚类标签。聚类方法的目标是发现这些互不相交的数据点子集。
在讨论聚类时,我们将研究几个案例。其中之一将再次使用文档检索任务的场景:我们拥有整个文档语料库。然而,与仅执行最近邻搜索的简单检索设置不同,这里的目标是发现输入空间的一种结构化表示,即将语料库结构化为可能与语料库中存在的主题相关的分组。
与检索一样,聚类也几乎无处不在。例如,在进行图像搜索时,我们可能不仅想根据给定图像提供一组相关图像,还可能希望实际构建数据结构,以发现相关的图像组。或者,我们可能希望发现像您这样的Coursera学习者群体,基于用户特征和在Coursera上的过往行为,找到彼此相关、兴趣相似的用户,并利用此更好地为学习者推荐课程。
因此,检索和聚类这些看似简单的理念,实际上在现实世界中具有非常重大的影响,并且常常被视为理所当然。您只需打开应用程序或设备搜索某物,就理所当然地认为系统能够提供一组与您的查询相关的其他内容;或者我们可以轻松地从所见数据中发现相关的人群或物品组。那么,我们究竟如何做到这一点呢?这正是本课程要探讨的内容,我们还将涉及如何大规模地实现这些方法。
本课程将涵盖的通用概念
与以往一样,在整个课程中,我们将学习非常有用的通用机器学习概念。例如,在本课程中,我们将讨论无监督学习任务,并探讨诸如MapReduce框架等通过并行化计算来扩展算法规模的方法。
总结


本节课我们一起学习了聚类与检索课程的概述。我们了解到,检索任务的核心是最近邻搜索,其目标是找到数据集中与查询点最相似的点或一组点。而聚类任务的目标是为数据点分配标签,以发现数据中内在的群组结构。这两种方法在推荐系统、信息检索和数据分析等领域有广泛应用。在接下来的课程中,我们将深入探讨实现这些任务的具体算法与技术。
机器学习(分类,聚类和检索):第1课:课程概览 🎯

在本节课中,我们将要学习华盛顿大学机器学习专项课程中关于分类、聚类和检索部分的整体教学理念、核心内容与课程特色。我们将了解这门课程如何通过案例研究、可视化辅助和实践项目来传授核心的机器学习概念与算法。
课程教学理念

本课程将延续我们过往课程的教学哲学。
具体而言,我们将使用案例研究来引出并讲解我们将要教授的关键概念。此外,我们的专项课程教学方式还由一系列其他关键特征所定义。
我们教授一套核心的机器学习概念,并且我们既通过案例研究,也通过使用可视化辅助工具来非常生动地引导学习过程。
课程深度与实践
在这些课程中,我们将延续基础课程的内容,深入讲解课程中提供的各种方法的算法细节。
我们不会仅仅提供一个用于聚类和检索的“方法清单”。我们将重点聚焦于我们认为应用最广泛、最实用的算法,以及那些能为我们提供最多技能、以便学习现在或将来可能存在的其他算法的内容。
在整个课程中,你将获得动手实现这些方法的实践经验。
你不仅将实现这些方法,而且将在真实世界的应用场景中实现它们。因此,你将获得在实际可能遇到的世界数据上部署这些机器学习算法的真实经验。
通过这个过程,你将积累大量关于这些方法的直觉,了解它们潜在的局限性和优势。
最后,我们还会在本课程中教授一套标记为可选的高级概念。这些是视频内容,如果你有兴趣了解一些底层细节和我们即将描述的一些内容,你可以观看这些视频。但如果你选择不看,也完全没有问题。你仍然将获得关于聚类和检索非常全面、透彻的概述,并且仍然能够实现和部署这些方法,只是可能不理解某些证明过程或更详细的概念。这部分内容是为那些对此感兴趣的学员准备的。

核心内容与算法
更具体地说,在本课程中,我们将学习多种不同的模型。
我们将讨论用于搜索的最近邻模型。我们将把聚类作为一个高级任务、一个无监督学习任务来讨论。我们将讨论用于执行聚类的概率模型,例如混合模型。然后,我们将讨论一个更复杂的概率模型,称为潜在狄利克雷分配。
接着,我们将学习与这些模型相关的一系列算法。
以下是本课程将涵盖的主要算法:
- KD树:一种用于执行高效最近邻搜索的数据结构。
- 局部敏感哈希:另一种高效的近似最近邻搜索技术。
- K均值:一种执行聚类的方法。
- MapReduce:我们提到过,这是一种并行化算法以扩展其规模的手段。
- 期望最大化:用于在我们的混合模型中进行推断。
- 吉布斯采样:用于在我们的潜在狄利克雷分配模型中进行推断。
重要的是,在整个课程中,我们将涵盖一系列超越聚类和检索概念本身的基础机器学习概念。
我们将讨论距离度量、近似算法、无监督学习、概率建模、数据并行问题以及贝叶斯推断。因此,本课程确实涵盖了非常广泛的概念。
总结


本节课中,我们一起学习了本课程的整体框架。我们了解到,这门课程将通过案例驱动和实践导向的方式,深入讲解聚类、检索及相关领域的核心模型(如最近邻、混合模型)与关键算法(如K均值、EM算法)。课程不仅注重动手实现,还涵盖了从距离度量到贝叶斯推断等一系列重要的机器学习基础概念,为初学者构建了坚实而全面的知识体系。
机器学习(分类,聚类和检索):第1章:课程内容详解 🧭


在本节课中,我们将详细解析华盛顿大学《机器学习(分类,聚类和检索)》课程的核心内容。课程将分为四个模块,系统性地介绍文档检索、聚类分析以及概率模型等关键主题。
模块一:文档检索与最近邻搜索 📄
上一节我们概述了课程结构,本节中我们来看看第一个模块的具体内容。该模块将围绕文档检索任务展开。其核心场景是:当用户正在阅读一篇文档时,我们希望从海量文档库中搜索并找到内容相似的文档,以推荐给用户。
为实现此目标,我们将重点介绍最近邻搜索。其基本思想是:计算查询文档与库中所有其他文档之间的距离,然后返回距离最小的文档(即最近邻)。执行最近邻搜索有两个关键组成部分:
以下是执行最近邻搜索的两个核心组成部分:
- 文档表示:如何将文档转化为计算机可以处理的数学形式。
- 相似度/距离计算:如何定义并计算两个文档表示之间的相似度或距离。
文档的表示方式以及距离的计算方法,共同决定了我们最终找到的“最近邻”是什么。我们将探讨这些组成部分的不同选择,并讨论其中的权衡。
接下来,我们将探讨如何将最近邻搜索扩展到超大规模数据集。因为对每一个查询都计算其与数据集中所有点的距离,这种暴力方法的计算成本极高。
因此,我们将介绍一种名为 kd树 的巧妙数据结构。在最近邻搜索的上下文中,kd树允许我们在搜索过程中“剪枝”,即排除掉搜索空间中的一大部分数据点,从而加速查询。当然,在某些情况下也可能“运气不佳”,但通常它能显著提升效率。
然而,kd树在高维空间中表现不佳。考虑到文档通常基于大型词汇表进行表示,维度会非常高,此时kd树就不再是一个有吸引力的选择。
于是,我们将转向讨论近似最近邻搜索,使用一种名为局部敏感哈希的技术。本课程将传达的一个重要概念是:在许多实际应用中,我们并不严格要求找到精确的最近邻,找到一个足够接近的近似最近邻通常就足够了。当我们接受这种近似时,在某些情况下可以极大地提升搜索效率。
模块二:聚类与K均值算法 🔍
在了解了如何寻找相似文档后,本节我们将转向聚类的概念。聚类的目标是根据文章自身的内容,自动发现其中相关的文章组。这是一个典型的无监督学习任务。
我们将介绍的第一个聚类算法是 K均值算法。K均值的目标是最小化数据点与其所属簇中心之间的平方距离之和。其核心公式可以表示为:
目标: minimize Σ Σ ||x - μ_k||²,其中外层求和遍历所有簇 k,内层求和遍历属于簇 k 的所有数据点 x。
我们可以将其理解为对数据集的一种“硬”划分,即每个数据点被明确地分配到某一个特定的簇中。重申一下,这是一种无监督学习算法,因为我们只使用输入数据本身,在没有输出标签的情况下,试图从中学习出结构。
随后,在模块二的后半部分,我们将探讨如何使用 MapReduce 框架来将K均值算法扩展到海量数据集。MapReduce是一个用于在多台机器上并行化操作的框架。我们将讨论通用的MapReduce框架(其适用于多种场景),以及它在K均值算法上的具体应用。
模块三:概率模型与混合聚类 🎲
上一节我们介绍了进行“硬分配”的K均值聚类,本节中我们来看看能够捕捉不确定性的概率模型。在聚类任务中,我们的目标是捕捉簇分配中的不确定性。
例如,可能有一篇文章,我们不太确定它应该属于“科学”类还是“世界新闻”类。在没有真实标签的情况下,我们可能希望算法能呈现出这种不确定性,而不是简单地将文档硬性分配到一个给定的簇中。
这种输出结果的一个用途是,可以帮助我们学习用户对一系列不同主题的偏好。如果我们拥有用户对某些文章的喜欢/不喜欢反馈,同时我们也知道这些文章与哪些簇相关联的不确定性,我们就可以将这两部分信息结合起来,更好地描述用户反馈应如何影响我们对该用户主题偏好的学习。
我们将用于聚类的概率模型称为混合模型。在这里,决定数据点分配到哪个簇时,起作用的不仅仅是像K均值中那样的簇中心,还包括簇的形状。同样,与K均值不同,我们不会对数据点进行硬分配,而是进行软分配。数据点可以在多个簇中拥有权重,这些权重基于我们对该数据点属于该簇的不确定性。
我们的目标是从一堆未标记的数据点(如图中灰色的点云)出发,得到一组带有颜色的点。但现在,颜色代表的是数据点分配到各簇的分配比例及其不确定性,呈现为一个完整的色彩光谱。例如,在蓝色和绿色簇之间的点,其颜色是这两种颜色的中间色调,意味着我们不确定这些观测点应分配给蓝色簇还是绿色簇。
我们将用于推断数据点到簇的软分配的算法称为期望最大化算法,简称 EM算法。
模块四:潜在狄利克雷分配模型 📊
最后,在第四个模块中,我们将介绍一个用于分析文档的更复杂的概率模型,称为潜在狄利克雷分配,简称 LDA。

为了理解LDA背后的思想,让我们看一个具体的文档。我们发现这篇文档包含大量与科学相关的词汇,因此基于内容,我们可能将其与其他科学类文章归为一组。但这篇文章也有很多与技术相关的词汇,所以更好的描述或许是将其归入技术类文章。实际上,这篇文章同时关乎科学和技术。
这正是LDA允许我们做的事情:它允许我们提供一种混合成员关系,即一篇文档可以同时属于多个不同的主题。不仅如此,LDA还能提供这些主题在该文档中的相对比例。
具体来说,LDA模型中的每个主题都被描述为词汇表上单词的一个概率分布。例如,科学主题在科学相关词汇上权重更高,而技术主题在技术相关词汇上权重更高,体育主题同理。
但令人惊叹的是,我们将以完全无监督的方式进行这一切。我们仅提供文档中的单词(对于语料库中的所有文档都是如此),仅凭这些信息,我们就能推断出:
- 这些特定主题在词汇表上的分布。
- 每篇文档中各个主题的特定比例。
我们将详细讲解如何提取这类信息。可以看到,这是另一个以无监督方式发现数据中结构的绝佳例子。

总结 📝
本节课中,我们一起学习了本课程四个核心模块的详细内容:
- 文档检索与最近邻搜索:从基础方法到应对大规模数据的近似搜索技术。
- 聚类与K均值:经典的硬划分聚类方法及其并行化扩展。
- 概率模型与混合聚类:引入不确定性,使用混合模型和EM算法进行软分配聚类。
- 潜在狄利克雷分配:更复杂的概率模型,用于发现文档的混合主题结构。
这些内容构成了从基础相似性检索到高级无监督主题发现的一条完整学习路径。
机器学习(分类,聚类和检索):第3-4课:假定的背景知识 📚

在本节课中,我们将介绍成功学习本课程所需具备的背景知识。我们将回顾本专项课程前期课程中的关键概念,并说明本课程对数学和编程基础的要求。

上一节我们介绍了课程的整体内容,本节中我们来看看学习本课程需要哪些预备知识。我们假定你已经学习了本专项课程的前期课程,并掌握其中的核心概念。
以下是前期课程中与本课程相关的重要知识点:
- 机器学习基础课程:我们学习了机器学习的高级概念,包括聚类、检索,以及如何理解机器学习方法的输入、输出和分析。同时,我们也建立了编程和数据操作的基本技能。
- 回归课程:我们深入探讨了如何用特征表示算法输入、理解输出、评估性能,并介绍了均值、方差等基本统计概念。此外,还涵盖了机器学习算法的基础概念、坐标下降等优化算法,以及过拟合和正则化等模型复杂度问题。
- 分类课程:条件分布和最大似然估计等概念对本课程至关重要。线性分类器、多类分类和提升法等概念,我们也会进行类比引用。
如果你没有学习过前期课程,或对某些概念只有模糊印象,强烈建议你回顾相关课程的视频内容。
在数学背景方面,本课程不会像前两门课那样强调微积分,但仍需掌握一些基本的线性代数知识。
以下是需要了解的线性代数概念:
- 向量(Vector)是什么
- 矩阵(Matrix)是什么
- 如何进行矩阵乘法(Matrix Multiplication)
此外,本课程将建立在分类课程的基础上,引入一些概率概念。我们将假定你了解概率的基本法则,例如概率总和为1,且值在0到1之间。我们也会讲解分布和条件分布的概念,但如果你已有相关背景知识,将大有裨益。
在编程经验方面,我们尽量让课程对不同编程语言偏好者开放,但鼓励使用Python。
以下是关于编程的说明:
- 所有作业都将提供Python起始代码,因此使用Python会更容易完成。
- 本课程的重点是教授基础的机器学习概念,而非具体的实现细节,但会要求你动手实现方法。
- 如果你已完成基础课程(以及回归和分类课程),就具备了完成本课程作业所需的技能水平。
与基础课程主要依赖GraphLab Create等预实现算法不同,本课程将深入探讨算法细节,使你能够用任何选择的语言实现它们。你将在本课程中获得实际动手经验。
关于课程作业的结构,我们将遵循与回归和分类课程相同的模式。
以下是作业的一般结构:
- 概念探索:首先使用预实现的算法探索方法,以深入理解概念,避免陷入具体的实现细节或代码调试问题。
- 实际实现:在巩固概念后,你将动手编写算法的实际实现。
最后一个模块关于潜在狄利克雷分配(Latent Dirichlet Allocation)的高级概念时,我们会教授实现所需的所有知识,但作业中不要求实际编码实现。
最后,计算需求与本专项其他课程相同。
以下是计算环境的选择:
- 自有机器:如果你使用自己的电脑,并计划使用SFrame(我们鼓励用于数据操作),则需要一台64位机器。除此之外,一台普通的台式机或笔记本电脑即可。你还需要能连接互联网以下载作业、上传代码,并能安装运行Python以及存储几GB的数据。
- 云端机器:我们也提供了云端预配置的机器。如果你没有自己的64位机器,仍然可以完成本课程。


本节课中,我们一起回顾了学习本课程所需的背景知识,包括前期课程的核心概念、必要的数学和编程基础,以及课程作业的结构和计算环境要求。现在,让我们正式开始学习吧!
机器学习(分类,聚类和检索):第4课:检索作为k近邻搜索

在本节课中,我们将要学习如何将文档检索任务转化为k近邻搜索问题。我们将深入探讨文档的表示方法、距离函数的定义及其影响,并介绍如何将最近邻搜索扩展到大规模文档集合。
文档检索任务
上一节我们介绍了检索的基本概念,本节中我们来看看具体的任务设定。
想象一下,我们正在阅读一本书或一篇文章,例如卡洛斯正在阅读一篇关于足球的文章。我们的目标是,从海量的文章库中,检索出另一篇可能让这位读者感兴趣的文章。
然而,存在成千上万的文章。因此,我们需要思考如何衡量当前文章与所有其他可能推荐文章之间的相似度。即使我们能够定义这种相似度,我们又将如何在这个庞大的文章空间中进行搜索呢?


将检索转化为最近邻搜索

为了解决这个问题,我们首先将文档检索任务转化为执行最近邻搜索的问题。
首先,假设我们可以根据文章之间的相似度,将所有待搜索的文章在空间中排列出来。这正是下图所展示的概念。

然后,我们会得到一个查询文章,即用户当前正在阅读的文章。我们的目标是尝试找出这些其他文章中,哪一篇与用户正在阅读的文章最接近、最相似。
为了实现这个目标,第一步是计算查询文章与所有其他文章之间的距离。
在计算出所有这些距离之后,我们只需搜索与查询文章距离最小的那篇文章。我们称之为最近邻。这篇文章就是我们即将检索并呈现给用户,作为他们可能感兴趣阅读的下一篇文章。

或者,作为我刚才描述的“一个最近邻”方法的替代方案,我们可能希望向读者呈现一组可能的文章,即 K个最近邻。这是检索任务一个更通用的表述。
核心概念与步骤

以下是实现基于k近邻的文档检索的核心步骤:
-
文档表示:将每篇文章(包括查询文章)转化为机器可以处理的数值向量。常用的方法是词袋模型或TF-IDF。
- 词袋模型示例:
document_vector = [count(word1), count(word2), ...] - TF-IDF公式:
TF-IDF(t, d) = TF(t, d) * IDF(t),其中TF(t, d)是词t在文档d中的频率,IDF(t) = log(N / (df(t) + 1)),N是文档总数,df(t)是包含词t的文档数。
- 词袋模型示例:
-
定义距离函数:选择一个度量标准来计算文档向量之间的距离。距离越小,表示文档越相似。
- 欧几里得距离:
distance = sqrt(sum((x_i - y_i)^2)) - 余弦相似度(更常用于文本):
similarity = (A·B) / (||A|| * ||B||),其中A和B是文档向量。距离可以定义为1 - similarity。
- 欧几里得距离:
-
计算与搜索:计算查询文档与文档库中所有文档的距离,然后找出距离最小的K个文档(K个最近邻)。
-
结果呈现:将找到的K个最近邻文档作为检索结果返回给用户。
扩展到大规模文档集
当文档集合非常庞大时,计算查询文档与所有文档的距离会变得非常缓慢且计算成本高昂。这是我们在本模块中,相对于第一门课程,将要涉及的一个新主题:如何扩展最近邻搜索。
解决这一挑战的常见思路是避免穷举搜索。以下是一些关键方法:
- 使用数据结构:利用如KD树、球树或局部敏感哈希等数据结构,来高效地组织文档向量,从而加速近邻查找。
- 近似最近邻搜索:为了追求极致的速度,可以接受找到“近似”最近邻而非精确最近邻的算法,例如基于LSH的方法,这通常能大幅减少计算量。
总结


本节课中我们一起学习了如何将文档检索任务形式化为一个k近邻搜索问题。我们回顾了将文档表示为向量、定义合适的距离函数以衡量相似度的核心步骤。最后,我们指出了在处理大规模文档集合时面临的挑战,并简要介绍了通过专用数据结构和近似算法进行扩展的思路。掌握这些基础是构建高效检索系统的关键。
机器学习(分类,聚类和检索):第3-4课:1-最近邻算法

在本节课中,我们将学习1-最近邻算法的形式化定义和实现步骤。这是一种简单而直观的相似性搜索方法,常用于文档检索等任务。
算法形式化定义
上一节我们介绍了相似性搜索的概念,本节中我们来看看如何形式化地定义1-最近邻算法。
进行1-最近邻搜索时,我们假设有一个查询文档,记作 xq。这是用户正在阅读的文章。同时,我们假设有一个文档语料库,包含所有可供搜索的其他文章,记作 x1, x2, ..., xN,其中 N 是文档总数。
该算法的输出是与查询文档最相似的文章。具体来说,它是与查询文档距离最小的文章。我们将返回的文章记作 X_nearest_neighbor。形式化定义如下:
X_nearest_neighbor = argmin_i distance(xq, xi)
其中,i 遍历语料库中的所有文档。这意味着我们寻找语料库中与查询文档 xq 距离最小的文档 xi,并将其作为最近邻返回。
算法实现步骤
理解了算法的定义后,我们来看看如何用伪代码实现它。
以下是1-最近邻搜索算法的实现步骤:
- 初始化一个变量
distance_to_nearest_neighbor为无穷大(表示尚未找到最近邻)。 - 初始化一个变量
nearest_neighbor_doc为空集(用于存储找到的最近邻文档)。 - 对于语料库中的每一个文档 xi(i 从 1 到 N):
- 计算查询文档 xq 与当前文档 xi 之间的距离 distance(xq, xi)。
- 如果计算出的距离小于当前记录的
distance_to_nearest_neighbor:- 将
nearest_neighbor_doc设置为当前文档 xi。 - 将
distance_to_nearest_neighbor更新为这个新的距离值。
- 将
- 循环结束后,返回
nearest_neighbor_doc,即找到的最近邻文档 X_nearest_neighbor。


本节课中我们一起学习了1-最近邻算法的核心思想、形式化定义以及具体的实现步骤。该算法通过遍历语料库并计算距离,来找到与查询文档最相似的单个文档,是许多检索和推荐系统的基础。
机器学习(分类,聚类和检索):第3-4课:K近邻算法详解 🧠

在本节课中,我们将深入学习K近邻算法。我们将从单近邻算法扩展到更通用的K近邻算法,理解其形式化定义、伪代码实现,并探讨影响算法性能的关键设计选择。
算法概述
上一节我们介绍了单近邻算法,本节中我们来看看其扩展版本——K近邻算法。该算法不再只返回一个最相似的文档,而是返回一组K个最相似的文档。
K近邻的形式化定义
我们有一个查询文档 ( X_Q ) 和一个包含 ( N ) 个文档的语料库 ( X_1 ) 到 ( X_N )。算法的目标是输出一个包含K个最相似文档的列表。
我们定义K近邻集合为 ( X_{\text{nearest neighbor}} ),其中包含文档 ( X_{\text{nearest neighbor 1}} ) 到 ( X_{\text{nearest neighbor K}} )。
该集合的定义是:对于所有不在K近邻集合中的文档 ( X_I ),其与查询文档 ( X_Q ) 的距离,都大于或等于集合中最远的那个近邻文档与查询文档的距离。
用公式表示,即对于所有 ( X_I \notin {X_{\text{nearest neighbor 1}}, ..., X_{\text{nearest neighbor K}}} ),满足:
[
\text{distance}(X_I, X_Q) \geq \max_{J=1}^{K} \text{distance}(X_{\text{nearest neighbor J}}, X_Q)
]
直观地说,K近邻的定义是:任何不在你K近邻集合中的文章,其距离都比集合内最远文档的距离还要远。
K近邻算法伪代码
与单近邻算法类似,我们可以用伪代码来描述K近邻算法的流程。不同之处在于,我们需要记录到目前为止找到的K个最近邻的距离,这是一个排序列表。
以下是算法的步骤:
- 初始化:假设语料库中的前K个文档是初始的K近邻。
- 计算初始距离:计算查询文档与这前K个文档中每一个的距离。
- 创建排序列表:根据距离对这K个文档进行排序,形成一个排序列表(包含距离和对应的文档索引)。
- 遍历剩余文档:对于语料库中剩余的文档(编号从 ( K+1 ) 到 ( N ) ):
- 计算该文档与查询文档的距离 ( \delta_{\text{new}} )。
- 如果 ( \delta_{\text{new}} ) 小于当前K近邻集合中最远邻居的距离(即第K近邻的距离):
- 在当前的排序距离列表中找到 ( \delta_{\text{new}} ) 应插入的位置索引 ( J )。
- 更新列表:将原列表中索引 ( J ) 到 ( K-1 ) 的元素向后移动一位(原第 ( K-1 ) 近邻变成第 ( K ) 近邻,依此类推)。
- 移除原列表中第 ( K ) 近邻(现已被挤出K近邻集合)。
- 在索引 ( J ) 的位置插入这个新文档及其距离 ( \delta_{\text{new}} )。
- 返回结果:遍历完所有文档后,返回最终得到的K个最近邻文档的索引列表。
这个算法是单近邻算法一个相当直接的扩展。
影响算法性能的关键选择
在分析这些算法的过程中,我们发现有两个关键选择直接影响算法的表现:
- 文档表示:我们如何将一篇包含大量文本的文章,转化为一个定量的表示 ( X_Q )。
- 距离计算:我们如何计算两篇文档之间的距离。
这两个选择——文档表示方法以及文档间距离的计算方式——是我们必须做出的决策,它们对于近邻搜索返回的结果至关重要。
总结


本节课中我们一起学习了K近邻算法。我们从其形式化定义出发,理解了它如何返回一组而不仅仅是一个相似文档。接着,我们逐步分析了算法的伪代码实现,看到了它是如何通过维护一个排序列表来高效地找到K个最近邻的。最后,我们指出了决定算法有效性的两个核心设计要素:文档的向量化表示和距离度量方法。理解这些基础是应用和优化近邻搜索算法的关键。
机器学习(分类,聚类和检索):第3-4课:文档表示 📄

在本节课中,我们将要学习如何将文本文档转换为计算机可以理解和处理的数学形式,即文档表示。这是构建文本检索和分类系统的基础。我们将探讨两种核心的表示方法:词袋模型和TF-IDF模型。
词袋模型:简单的词频向量
首先,我们来讨论如何表示文档。一个非常简单的选择是直接将文档表示为一个词频向量。
具体来说,这是词袋模型的一个例子。在这个模型中,我们忽略文档中单词的顺序,只关心每个单词出现的次数。假设我们有一个非常简单的文档,只包含以下两句话:
Carlos calls this sport football. Emily calls this sport soccer.
在词袋模型中,我们统计每个单词出现的次数,并将其作为我们的词频向量。以下是基于整个词汇表构建的向量:
- Carlos: 1
- the: 2
- Emily: 1
- soccer: 1
- calls: 2
- sport: 2
- football: 1
因此,这个简单文档的词频向量表示就是上述的计数结果。
词袋模型的局限性:稀有词的重要性
然而,这种简单的表示方法存在一个问题,它与稀有词有关。
例如,假设一个文档包含大量常见词汇(如“the”、“player”、“field”、“goal”),但只包含少数几个稀有但重要的词汇(如“football”、“Messi”)。这些稀有词可能恰恰突出了这篇文章独特且重要的内容,对于像Carlos这样的用户来说,它们比那些在许多其他体育文章中都可能出现的常见词更有意义。
当我们仅基于原始词频进行距离计算时,这些在文档中出现次数多的常见词会主导计算结果。这对于像“the”、“of”、“in”这类几乎出现在所有文档中、但对评估文档相似性基本无意义的词来说尤其糟糕。它们会完全淹没那些更重要但出现频率较低的词。
TF-IDF:权衡局部频率与全局稀有性
为了解决上述问题,我们可以考虑一种替代的表示方法:TF-IDF(词频-逆文档频率)。我们在第一门课程中讨论过它,但这里有必要回顾一下,因为它是我们将要频繁使用的一种表示方法。
TF-IDF通过以下方式强调重要词汇:
- 强调在局部(当前文档)频繁出现的词。
- 强调在全局(整个语料库)中罕见的词。
如果一个词同时满足这两个条件,那么它很可能是一个重要的词,我们应该在表示中突出它。
为了量化这一点:
- 词频:衡量词汇在文档中出现的频率。这很简单,就是我们之前计算的文档词频。
- 公式:
TF(word, document) = count(word in document)
- 公式:
- 逆文档频率:衡量词汇在整个语料库中的稀有程度。一个常见的计算方式是:
- 公式:
IDF(word) = log( (总文档数) / (1 + 包含该词的文档数) ) - 这个公式的关键在于,它会降低那些在许多文档中都出现的词的权重。
- 公式:
TF-IDF表示法通过将这两个因子相乘,来权衡局部频率和全局稀有性:
- 公式:
TF-IDF(word, document) = TF(word, document) * IDF(word)
通过使用TF-IDF向量作为文档的表示,我们可以:
- 提升那些在当前文档中常见、但在整个语料库中罕见的词的权重。
- 降低那些像“the”、“of”这类在当前文档和几乎所有其他文档中都出现的词的权重。
这样做之后,当我们进行距离计算时,那些对当前阅读文档真正重要的词将在计算中占据更显著的地位。
总结
本节课中,我们一起学习了两种关键的文档表示方法。
- 我们首先介绍了词袋模型,它通过简单的词频向量来表示文档,但容易受到常见词的干扰。
- 接着,我们探讨了TF-IDF模型,它通过结合词频和逆文档频率,能够更好地突出文档中独特且重要的词汇,从而为后续的相似性计算和检索任务提供更有效的表示。

理解这些表示方法是构建高效文本机器学习系统的重要第一步。
机器学习(分类,聚类和检索):第3-4课:距离度量:欧几里得距离和缩放欧几里得距离

在本节课中,我们将要学习如何计算两个数据点之间的距离,这是许多机器学习算法的核心。我们将从简单的欧几里得距离开始,然后探讨在多维特征空间中更实用的缩放欧几里得距离,并理解特征权重和缩放的重要性。
从一维到多维的距离计算
上一节我们讨论了数据表示,本节中我们来看看如何计算两个给定文章之间的距离。
在只有一个特征(一维)的情况下,一个非常简单的度量方法是欧几里得距离。其公式为:
distance = |x1 - x2|
然而,这通常不是我们关注的重点,因为它假设我们的词汇表中只有一个词。在本课程涉及的大多数场景中,我们都需要考虑多个特征或多个维度。
在多维情况下,距离计算变得非常有趣,我们可以考虑使用多种不同的距离函数。其中一个有趣的做法是,我们可以为不同的维度赋予不同的权重。这意味着我们可以为词汇表中的不同词语或不同的特征设置不同的重要性。
以下是几个需要不同权重的例子:
- 回归预测中的特征重要性:回想第二门课程中关于回归预测房价的例子。我们使用最近邻回归来预测房价,并可以为房屋的不同属性设置不同权重。例如,卧室数量、浴室数量和房屋面积对于预测房价非常重要,而楼层数或翻新年份可能重要性较低。
- 文档相似性中的特征权重:在我们的文档示例中,也存在类似的类比。计算两篇文章的相似性时,我们可能希望更重视标题,因为它可能比包含大量噪声词语的文章正文更具信息性。同样,对于科学文章,摘要部分可能比正文更具信息性。
- 特征尺度差异:另一种需要不同权重的情况是,当某个特征在不同观测值之间变化很小,而另一个特征变化很大时。这可能是因为特征的单位不同,或者某个维度本身方差很大。如果直接计算等权重的欧几里得距离,变化大的特征可能会主导距离计算,但实际上,特征一的微小变化可能与特征二的较大变化同等重要。
缩放欧几里得距离
为了解决特征尺度差异的问题,人们通常会对特征进行缩放,这都与尺度有关。具体做法是按观测值分布的某种度量来缩放特征。
以下是两种常见的缩放方法:
- 按范围缩放:对于特征
j,取该列的所有观测值(即数据矩阵的整列),然后将其缩放。缩放因子可以是该列所有值的最大值减去最小值。 - 按方差缩放:另一种方法是按该特征所有观测值方差的倒数进行缩放。
以上所有情况都引入了在不同特征间计算距离时的权重。
正式地,我们可以计算所谓的缩放欧几里得距离。它的形式与标准的多维欧几里得距离非常相似,但现在我们在每个不同的维度上都有一个不同的权重。
缩放欧几里得距离的公式可以表示为:
distance = sqrt( a1*(x1_1 - x2_1)^2 + a2*(x1_2 - x2_2)^2 + ... + ad*(x1_d - x2_d)^2 )
其中 a1 到 ad 是不同特征上的权重,它们代表了这些不同特征的相对重要性。
设置权重的一个例子是将其视为二元权重,即0和1。这是缩放欧几里得距离计算的一个特例。这等价于特征选择,因为如果将权重设置为0,就等于完全排除了该特征,它不会被纳入距离计算。这意味着在评估两篇文章的相似性或距离时,该特征无关紧要。
但请注意,与Lasso或其他特征选择方法不同,在这里我们是预先指定这些权重(或在二元情况下,预先指定包含或排除哪些特征)。
特征工程的重要性
这里我真正想强调的是,我们如何指定数据表示并计算这个距离是极其重要的,同时这也是一项非常具有挑战性的任务。因此,特征工程或特征选择的想法非常重要,但它本质上也是一项困难的任务。机器学习领域有大量关于如何进行特征工程的文献。
但这确实是机器学习中需要进行大量调整的领域之一,这里有一个可以调节的“旋钮”。通常需要大量的领域知识来思考如何设置这些权重或定义这些距离。我想强调的是,这真的很重要,没有一种通用的解决方案。请务必仔细思考,不要只是计算某个距离就假设它代表了应用中的重要距离,而不去思考数据是什么以及在计算该距离时发生了什么。
总结

本节课中我们一起学习了距离度量的核心概念。我们从一维的简单距离出发,引出了在多维空间中计算距离的必要性。我们重点介绍了缩放欧几里得距离,它通过为不同特征引入权重 a_i 来应对特征尺度不一和重要性不同的问题。权重的设置可以基于领域知识(如标题比正文更重要)或数据统计特性(如按范围或方差缩放)。最后,我们强调了特征工程——即如何表示数据和定义距离——是机器学习中至关重要且充满挑战的一环,需要结合具体问题和领域知识进行仔细设计。
机器学习(分类,聚类和检索):第3-4课:使用加权内积表示缩放欧几里得距离

在本节课中,我们将回顾欧几里得距离的计算方式,并学习如何将其改写为内积的形式。这种表示方法不仅有助于理解距离计算的本质,还能为后续讨论其他距离度量方法以及实际计算实现提供便利。
从标准欧几里得距离到内积表示
上一节我们讨论了基本的欧几里得距离。本节中,我们将通过一个数学练习,看看如何将标准的多维欧几里得距离用内积运算来表示。
欧几里得距离衡量的是两个点之间的直线距离。对于数据点 x_i 和查询点 x_q,其距离公式为:
d(x_i, x_q) = √[ Σ_j (x_ij - x_qj)² ]
我们可以将这个计算过程用向量运算来重新表述。具体做法是,构造一个差值向量,其元素是 x_i 和 x_q 在每个维度上的差。
这个差值向量是:v = x_i - x_q
其转置向量为:vᵀ
如果我们计算这个差值向量与其自身转置的内积,即 vᵀ v,得到的结果正是所有维度差值的平方和。因此,要得到欧几里得距离,我们只需对这个内积结果开平方根:
d(x_i, x_q) = √[ (x_i - x_q)ᵀ (x_i - x_q) ]
这种内积表示法清晰地展示了欧几里得距离的核心是计算差值向量的模长。
引入缩放因子:加权欧几里得距离
理解了标准距离的内积表示后,我们现在可以很容易地将其扩展到加权欧几里得距离,即缩放欧几里得距离。
在加权版本中,我们希望不同维度对总距离的贡献不同,因此为每个维度 j 引入一个权重 a_j。这些权重可以构成一个对角矩阵 A:
A = diag(a_1, a_2, ..., a_D)
其中,D 是特征的总维度数。这个矩阵的主对角线元素就是各个维度的权重。
加权欧几里得距离的计算,就是在标准距离公式的每个平方项前乘以对应的权重:
d_A(x_i, x_q) = √[ Σ_j a_j (x_ij - x_qj)² ]
用加权内积表示缩放距离
那么,如何用内积的形式来表达这个加权距离呢?方法非常直接。我们只需要将权重矩阵 A 插入到之前的标准内积表达式中即可。
具体步骤如下:
- 首先,计算标准差值向量:v = x_i - x_q
- 然后,用权重矩阵 A 左乘这个差值向量,得到一个新的缩放后的向量:A v
- 最后,计算这个缩放后向量与原始差值向量 v 的内积,并开方:
d_A(x_i, x_q) = √[ (x_i - x_q)ᵀ A (x_i - x_q) ]
让我们仔细看看这个运算过程。当矩阵 A 作用于向量 v 时,由于 A 是对角矩阵,其结果相当于将 v 的每个元素 (x_ij - x_qj) 乘以对应的权重 a_j,生成一个新的向量。
然后,这个新向量再与原始差值向量 v 做内积。内积运算会将两个向量对应元素相乘后求和。因此,最终求和式中的每一项都变成了 a_j * (x_ij - x_qj) * (x_ij - x_qj) = a_j (x_ij - x_qj)²,这正好符合加权欧几里得距离的定义。
所以,公式 √[ (x_i - x_q)ᵀ A (x_i - x_q) ] 完美地捕捉了缩放欧几里得距离的计算。
本节总结
本节课中我们一起学习了欧几里得距离的两种重要表示形式。
我们首先将标准的欧几里得距离改写为差值向量内积的平方根形式:d = √[ (x_i - x_q)ᵀ (x_i - x_q) ]。接着,我们引入了对角权重矩阵 A 来表示不同维度的重要性,并推导出加权(缩放)欧几里得距离的内积表达式:d_A = √[ (x_i - x_q)ᵀ A (x_i - x_q) ]。

这种内积表示法不仅数学上简洁优美,而且为理解和实现距离计算,以及衔接后续更复杂的距离度量方法(如马氏距离)奠定了坚实的基础。
机器学习(分类,聚类和检索):第3-4课:距离度量:余弦相似度 📐

在本节课中,我们将要学习一种在文本分析等领域非常常用的相似度度量方法——余弦相似度。我们将了解它的定义、计算方法、几何意义以及它与简单内积的区别。
上一节我们介绍了通过计算内积来衡量相似度的基本想法。本节中我们来看看另一种更常用、更自然的度量方法。
内积相似度
一种衡量两篇文章相似度的直接方法是计算它们特征向量之间的内积。对于查询文章向量 Xq 和另一篇文章向量 Xi,其内积定义为:
相似度 = Xi · Xq = Σ (Xi_j * Xq_j)
这个公式表示将两个向量对应维度的值相乘,然后求和。我们可以将其理解为衡量两篇文章在所用词汇及其权重上的重叠程度。
以下是内积相似度的特点:
- 它测量了文章间词汇使用的重叠量。
- 如果两篇文章词汇完全不同,相似度为零。
- 在之前的足球文章例子中,计算出的内积相似度为13。
从内积到余弦相似度
我们之前讨论的简单内积相似度,与一个更流行的度量——余弦相似度——密切相关。余弦相似度的公式如下:
余弦相似度(Xi, Xq) = (Xi · Xq) / (||Xi|| * ||Xq||)
其中,||X|| 表示向量 X 的范数(或长度),计算公式为 √(Σ X_j²)。这个公式可以进一步重写为:
余弦相似度 = (Xi / ||Xi||)ᵀ · (Xq / ||Xq||)
相对于简单的内积,关键区别在于我们首先对向量进行了归一化处理。这是一个非常重要的差异,接下来我们会详细讨论。
余弦相似度的几何意义
可以证明,上述归一化后的内积等价于计算两个向量之间夹角的余弦值,而与向量的长度(大小)无关。这直接源于内积的定义:
Aᵀ · B = ||A|| * ||B|| * cos(θ)
其中 θ 是向量 A 和 B 之间的夹角。
想象一个仅包含两个词汇的二维空间,每篇文章对应一个点。余弦相似度所做的,就是忽略向量从原点出发的长度,只关注这两点与原点连线之间的夹角 θ 的余弦值。
关于余弦相似度,有几点需要注意:
- 它不是像欧氏距离那样的严格距离度量,因为它不满足三角不等式。
- 对于稀疏向量(如文本的TF-IDF向量),它的计算效率极高,因为只需要考虑非零元素。
归一化示例
为了让大家更清楚归一化的含义,我们来看一个例子。假设我们有一个标准的词频或TF-IDF向量。
当我们对其进行归一化时,就是将该向量除以其自身的范数(即所有元素平方和的平方根)。
如果进行此计算,文档的归一化表示就是将每个原始值除以该向量的长度。
余弦相似度的取值范围
现在,让我们更深入地探讨余弦相似度度量,思考一下它的取值范围。
假设有两篇非常相似的文章,它们之间的夹角 θ 非常小。那么 cos(θ) 将近似等于 1,正如我们所期望的,高相似度对应高余弦值。
我们可以通过单位圆来回忆余弦函数:
- 当夹角 θ 为 0 度时,cos(θ) = 1。
- 当夹角 θ 为 90 度时,cos(θ) = 0。
- 当夹角 θ 为 180 度时,cos(θ) = -1。
因此,一般来说,余弦相似度的取值范围是从 -1 到 1。
但是,如果我们限制特征值为正数(例如在处理文档的TF-IDF向量时),那么所有向量都位于正象限内。向量间的夹角范围是 0 到 90 度,因此余弦相似度的实际取值范围是 0 到 1。
在这种情况下,我们通常将距离定义为:
距离 = 1 - 余弦相似度
需要再次记住,虽然这不是一个形式化的距离度量,但我们可以将其用作衡量文章间差异的一种有效方法。


本节课中我们一起学习了余弦相似度。我们了解到它是通过计算向量间夹角的余弦值来衡量相似度,并且对向量长度不敏感。我们还探讨了它的计算方法、几何解释、取值范围,以及如何将其转化为一个简单的距离度量。在处理像文本这样的高维稀疏数据时,余弦相似度是一个非常强大且高效的工具。
机器学习(分类,聚类和检索):第3-4课:是否归一化与其他距离考量

在本节课中,我们将探讨在计算文档相似度时,是否应该对向量进行归一化处理,并介绍除欧氏距离和余弦相似度之外的其他距离度量方法。我们还将讨论如何根据特征的不同类型,组合使用多种距离度量。
是否应该归一化?
上一节我们介绍了余弦相似度。我们发现,余弦相似度与我们最初介绍的、基于向量内积的相似度计算方式的主要区别在于,余弦相似度是在归一化向量上操作的。这引出了一个核心问题:我们是否应该进行归一化?我们应该使用余弦相似度,还是使用简单的向量内积来计算相似度?
为了思考这个问题,我们来看一个例子。假设我们有两个不同的文档:一个绿色文档和一个蓝色文档。我们计算它们之间的相似度。
现在,我们简单地将每个文档的长度加倍。我们加倍的方式是复制文档内容,使其包含完全相同的词汇,但每个词的数量变为原来的两倍。
当我们计算它们在原始空间中的相似度时,相似度是 13。这是我们之前计算的数值。但是,当我们计算长度加倍后的文档相似度时,相似度变成了 52。相似度增加了4倍,而这仅仅是因为文档长度加倍了,内容本身完全没有改变。
这真的是我们想要的吗?我们希望文档仅仅因为变得更长就显得更相似吗?还是我们更关心文档的内容,而不是它的长度?
如果我们对文档进行归一化处理,情况就不同了。这是绿色文档归一化后的表示。当我们使用绿色文档和蓝色文档的归一化表示来计算相似度时,我们得到的相似度是 13 / 24。
现在,如果我们再次将每个文档的长度加倍,然后对这些长度加倍的文档进行归一化,我们会得到完全相同的归一化表示,因此计算出的相似度也完全相同。
由此可见,余弦相似度对文档的长度(即单词的绝对数量或向量的规模)具有不变性。它更侧重于文档的内容,即哪些单词出现了。
一方面,这看起来非常有吸引力。但这并不总是我们期望的。我们并不总是希望忽略文档长度,因为这样做可能会使本质上非常不同的对象看起来比实际更相似。
例如,假设我们有一篇非常长的文章(比如《大西洋月刊》上的一篇文章),另一方面,我们有一条非常短的推文。如果你计算这两者之间的余弦相似度,这条推文和这篇长文章会显得比实际情况相似得多。如果有人正在阅读一篇长文章,我们真的想建议他去读一条推文吗?可能不会。
因此,人们通常的做法是在完全归一化的余弦相似度和完全忽略归一化之间采取一种折中方案。他们通常会对向量中出现的单词计数设置一个上限。
其他距离度量
到目前为止,我们主要关注了欧氏距离和余弦相似度这两种距离度量,因为我们特别关注文档建模或文档检索。但实际上,还有许多其他有趣的距离度量方法可以使用,例如:
- 马氏距离
- 基于排序的距离
- 基于相关性的距离
- 曼哈顿距离
- 杰卡德距离
- 汉明距离
本课程没有详细介绍这些方法,但我想提一下实践中非常常用的一种方法:对不同特征子集使用不同的距离度量。
例如,在我们的文档案例中,我们可能有文档的文本特征(这是我们一直关注的重点),但也可能有“文章被阅读次数”这样的计数特征,这是一个固有的数值型特征。
在这种情况下,我们可能会使用余弦相似度来比较文档的文本内容,因为我们希望这种比较对文档的规模或长度保持不变性。但对于“阅读次数”这种计数特征,我们肯定希望使用其原始形式,不进行归一化,因此我们可能会使用欧氏距离。
你可以考虑为不同的特征计算不同类型的距离度量,然后以你喜欢的方式对它们进行加权(就像我们讨论加权欧氏距离时那样)。但现在,权重不仅可以应用于欧氏距离,还可以应用于所有这些不同形式的距离度量。然后,我们可以将其作为衡量文档(或本例中的其他对象)之间相似度的标准。
如果我们考虑房屋应用,这一点就非常自然。一个房屋列表会有一些文本描述,你可能不关心房产中介是否非常啰嗦,因此你希望对此保持不变性,可以使用余弦相似度来比较不同房屋列表的文本。但对于像“平方英尺数”、“卧室数量”和“浴室数量”这样的特征,这些数字的实际规模非常重要,因此使用欧氏距离会非常自然。
在许多不同的应用领域中,你都会看到这种类型的做法。
总结
在本模块中,我们一起学习了如何以不同方式表示文档,以及如何计算两个文档之间的距离。这些是进行最近邻搜索的基础构件。
到目前为止,我们讨论的结论是为你提供了一系列可供考虑的选项。但希望你能记住的核心信息是:仔细思考你在做什么,以及你的选择所带来的影响。对于如何做某件事,并没有唯一正确的答案。但非常重要的是,要思考你所做的任何选择,对于你正在处理的问题意味着什么。


也许到目前为止的整个模块是一个警示,但希望它不止于此。希望它为你提供了一套可以考虑使用的工具,以及学习其他工具的基础构件。
机器学习(分类,聚类和检索):第3-4课:暴力搜索的复杂度 🧮

在本节课中,我们将要学习最近邻搜索算法的计算复杂度。我们将分析暴力搜索方法在时间和资源上的消耗,并探讨当数据量巨大或查询频繁时,这种基础方法可能面临的挑战。
我们已经建立了如何执行最近邻搜索的框架,包括描述需要运行的算法,并花时间讨论了该算法中两个至关重要的组成部分。
第一个组成部分是如何表示我们感兴趣的文档,第二个组成部分是如何计算两个不同文档之间的距离。
我们证明了这两个组成部分对于方法的性能至关重要。但现在,我想花点时间思考一下,执行最近邻搜索在计算上可能有多么密集。


我们将其称为搜索的复杂度。
那么,暴力搜索的复杂度是多少呢?假设我们有一个给定的查询点。
我们需要做什么?我们需要扫描语料库中的所有文档,计算到每个文档的距离,然后找出哪个距离最小。
这样做的复杂度是多少?对于一个1-最近邻查询,我们必须计算 n 个不同的距离。因此,复杂度是 O(N),其中 N 是语料库中的文档数量。
如果我们想要进行 K 最近邻搜索,即返回 K 个最近的文档,那么复杂度是 O(N log K)。我们得到 log K 项的原因是,如果我们采用一种智能的实现方式,维护一个优先队列并以高效的方式插入,就可以达到这个复杂度。
但是,如果 N 真的非常大,更重要的是,如果你必须对这个语料库一遍又一遍地进行许多、许多次查询呢?
我们能否做一些比这种暴力搜索更高效的事情?

本节课中我们一起学习了暴力搜索最近邻算法的计算复杂度。我们了解到,对于单个查询,其时间复杂度与文档数量 N 成正比;对于K近邻查询,则为 O(N log K)。当数据规模庞大或查询需求频繁时,这种线性扫描的方法可能成为性能瓶颈,这引出了我们对更高效搜索方法的需求。在接下来的课程中,我们将探索能够应对这些挑战的优化策略。
机器学习(分类,聚类和检索):第3-4课:KD树表示 🌳

在本节课中,我们将要学习一种名为KD树的数据结构。它是一种用于高效组织和表示数据的方法,特别适用于低维到中维度的特征空间。通过将数据空间进行轴对齐的划分,KD树能够帮助我们快速剪枝搜索空间,从而在进行最近邻搜索时,无需检查每一个数据点。


KD树的结构与构建 🏗️
上一节我们介绍了KD树的基本概念,本节中我们来看看如何构建一棵KD树。KD树的核心思想是递归地将数据空间划分为更小的子空间。
构建过程从一个包含所有数据点的数据表开始。我们首先选择一个划分维度(即一个特征)和一个划分值(阈值)。根据这个划分,数据点被分成两组:一组满足该特征值小于等于阈值,另一组满足该特征值大于阈值。然后,我们对每个子组递归地重复这个过程,直到满足停止条件(例如,子组中的数据点数量少于某个值,或子空间的宽度达到最小值)。
在树的每个节点上,我们存储三个关键信息:
- 划分所依据的维度。
- 划分所使用的阈值。
- 包含该节点下所有数据点的最小边界框。
以下是构建KD树时需要考虑的几个关键选择:
- 划分维度的选择:常见启发式方法包括选择数据分布最宽的维度进行划分,或者简单地交替选择维度。
- 划分值的选择:可以选择该维度下数据点的中位数,也可以选择该维度边界范围的中心点。
- 停止条件:可以设定当节点内数据点数量少于一个阈值(例如
M个点)时停止划分,或者当边界框的最小宽度达到某个值时停止。
构建选择的影响 ⚖️
正如我们在整个模块中反复强调的,算法的选择至关重要,对于KD树这样的数据结构也不例外。划分值的选择策略(例如使用中位数还是范围中心)会显著影响最终生成的树结构。
不同的数据分布下,不同的选择可能导致树的结构差异巨大。这种结构上的差异,又会直接影响我们后续进行最近邻搜索时需要访问的节点数量,从而影响搜索效率。


本节课中我们一起学习了KD树的基本原理和构建方法。我们了解到,KD树通过递归的轴对齐划分来组织数据,并在每个节点存储划分信息和最小边界框。构建过程中的关键选择(如划分维度、划分值和停止条件)会影响树的结构,进而影响搜索效率。在下一节中,我们将探讨如何利用构建好的KD树进行高效的最近邻搜索。
机器学习(分类,聚类和检索):第3-4课:KD树的最近邻搜索



在本节课中,我们将要学习如何使用KD树来高效地执行最近邻搜索。我们将从查询一个点开始,逐步遍历KD树,并理解如何通过“剪枝”来避免不必要的距离计算,从而显著提升搜索效率。
高效搜索:从查询点到叶节点
上一节我们介绍了KD树的结构,本节中我们来看看如何利用它进行搜索。
首先,我们有一个查询点,在图中用绿色圆圈表示。搜索的第一步是遍历KD树,直到找到包含该查询点的叶节点。
这意味着我们需要将查询点的坐标与树中每个内部节点的分割条件进行比较。例如,第一个内部节点可能根据特征 x1 是否大于 0.5 进行分割。如果查询点的 x1 大于 0.5,我们就沿着“是”的分支向下遍历。这个过程会持续进行,直到我们到达一个叶节点。
# 伪代码:从根节点开始,根据条件遍历至叶节点
current_node = root
while current_node is not internal_node:
if query_point[split_feature] <= split_value:
current_node = current_node.left_child
else:
current_node = current_node.right_child
局部搜索与距离计算
到达叶节点后,我们首先在该叶节点对应的数据点中进行局部搜索。
这个叶节点包含了一组数据点(例如图中的三个点)。我们计算查询点到该节点内每一个点的距离。
计算完这些距离后,我们记录下当前找到的最近邻距离,我们将其称为 R。R 代表了到目前为止找到的最近邻居的距离。
回溯与剪枝:优化搜索范围
一个自然的问题是:搜索到此结束了吗?最近邻一定就在这个初始的叶节点里吗?答案是否定的。
从图示的虚线圆可以看出,其他相邻的“盒子”(即其他叶节点对应的区域)里可能存在更近的点。因此,我们需要继续搜索。
搜索策略是回溯。我们从已检查的叶节点开始,沿着树向上回溯,并检查之前未探索的其他分支。
当我们回溯到一个新的内部节点并准备探索其另一个子分支时,我们会先评估该子节点对应的整个区域(即其“包围盒”)。关键步骤来了:我们计算查询点到这个包围盒的最近可能距离(例如,到盒子边界的距离)。
如果这个到包围盒的距离已经大于我们当前记录的最近邻距离 R,那么就意味着这个包围盒内的所有点都不可能比我们已找到的最近邻更近。
# 伪代码:剪枝条件判断
if distance_to_bounding_box(box, query_point) > current_best_distance_R:
prune_this_branch() # 跳过该分支下的所有点
在这种情况下,我们可以安全地剪枝——即跳过对该分支下所有点的距离计算,直接继续回溯。这个过程会持续进行,直到我们检查完所有可能包含更近点的分支。
总结:KD树的优势
本节课中我们一起学习了KD树最近邻搜索的全过程。
我们从一个查询点出发,遍历至一个叶节点并进行局部搜索。然后通过回溯和剪枝策略,系统地检查其他可能区域,同时避免了对大量不可能成为最近邻的点进行冗余计算。


与需要计算查询点到数据集中所有点距离的暴力方法相比,KD树通过其层次结构和对空间的划分,能够显著减少需要计算的实际距离数量。这在数据集非常庞大或需要执行大量查询时,能带来巨大的效率提升。虽然构建KD树本身需要一定的计算成本,但对于重复使用的场景,它提供的性能收益是非常可观的。
机器学习(分类,聚类和检索):第3-4课:KD树最近邻搜索的复杂度分析 🧮

在本节课中,我们将要学习KD树(K-Dimensional Tree)在构建和进行最近邻搜索时的计算复杂度。我们将分析其最佳与最坏情况下的性能,并理解数据结构与数据分布对效率的影响。
构建KD树的复杂度
上一节我们介绍了KD树的基本结构,本节中我们来看看构建这棵树需要多少计算量。构建KD树的核心步骤是递归地选择分割维度和分割值(例如中位数),将数据点划分到左子树或右子树。
如果最终我们得到一棵近似平衡的二叉树,并且每个叶节点只包含一个数据点,那么整棵树的节点总数与数据点数量 n 有关。
以下是关于树结构的关键公式:
- 总节点数:
2n - 1 - 树的高度(深度):
O(log n)
现在,我们来分析构建过程的复杂度。在树的每一层,我们都需要处理当前节点下的所有数据点以确定分割点。如果使用中位数启发式方法并进行高效实现(例如使用优先队列),那么每一层的操作复杂度是 O(n)。
由于树有 O(log n) 层,因此构建KD树的总时间复杂度为:
O(n log n)
最近邻查询的复杂度
构建KD树需要前期成本,其收益体现在查询阶段。现在,我们分析在KD树中进行一次最近邻搜索的复杂度。
查询的第一步是遍历:从根节点开始,根据查询点的坐标与节点分割超平面的比较,递归地向下遍历,直到到达一个叶节点。这个过程的复杂度是 O(log n),因为树的深度是 O(log n)。
到达叶节点后,我们得到了一个候选最近邻。但搜索并未结束,我们还需要进行回溯,检查其他分支中是否存在更近的点。这是KD树查询效率的关键。
以下是查询复杂度可能出现的范围:
- 最佳情况:如果数据结构良好,回溯过程可以大量“剪枝”(即排除整个分支),那么我们可能只需要检查
O(log n)个节点。 - 最坏情况:如果数据结构不理想或查询点位置特殊,导致无法进行任何有效的剪枝,那么我们可能不得不检查树中几乎所有的
O(n)个节点。
值得注意的是,最坏情况下的复杂度 O(n) 与暴力搜索(线性扫描所有点)相同。这意味着,如果只进行单次查询,并且数据分布或树的结构不理想,使用KD树可能反而会带来额外开销。
KD树的局限性与维度灾难
然而,KD树的效率高度依赖于数据的维度。我们之前展示的所有例子都基于二维空间(例如两个词汇特征)。但在实际机器学习中,我们常常需要处理成百上千维的高维数据。
KD树在高维空间中的表现并不理想。随着维度 D 的增加,回溯过程中需要检查的节点数量可能呈指数级增长。这种现象常被称为“维度灾难”(Curse of Dimensionality)。我们将在本课程后续部分再次讨论这个问题。
总结
本节课中我们一起学习了KD树复杂度的核心内容。我们了解到:
- 构建一棵平衡KD树的时间复杂度为
O(n log n)。 - 进行最近邻查询时,复杂度在最佳情况下可降至
O(log n),但在最坏情况下仍为O(n)。 - 查询效率极大地依赖于数据分布和树的结构,有效的剪枝是提升性能的关键。
- KD树在处理高维数据时面临挑战,其效率可能因“维度灾难”而显著下降。


理解这些复杂度特性,有助于我们在实际应用中判断何时使用KD树是合适的,并为学习其他更适用于高维空间的近似最近邻算法打下基础。
机器学习(分类,聚类和检索):第3-4课:可视化KD树的缩放行为

在本节课中,我们将学习KD树(K-Dimensional Tree)在最近邻搜索中的性能表现。我们将探讨数据分布如何影响搜索效率,分析KD树在不同维度和数据量下的复杂度,并了解如何将其扩展用于K近邻搜索。
KD树搜索效率与数据分布
上一节我们介绍了KD树的基本构建与搜索过程。本节中我们来看看数据分布如何影响KD树的搜索效率。
根据数据在空间中的分布结构,KD树的搜索效率可能接近 O(log N),也可能接近 O(N)。

以下是两种典型情况:
- 均匀分布:当数据点在整个空间内均匀分布时,对于一个给定的查询点,KD树可以修剪掉大量的搜索空间。例如,可能只需要搜索两个不同的子区域(“盒子”)。这种情况下,搜索效率接近 O(log N)。
- 特殊分布(如环形):如果数据点呈现特殊的分布(例如近似分布在一个圆环上),并且我们采用基于中心的启发式方法进行空间划分,最终可能不得不搜索树中的几乎每一个节点。这种情况下,搜索效率接近 O(N),相比暴力搜索没有太大优势。
因此,为了抵消构建KD树数据结构的成本,最好在需要执行大量查询的场景中使用它。
多查询场景下的复杂度分析
假设我们需要为语料库中的每篇文章都找到其最近邻,即执行 N 次查询。
以下是两种方法的复杂度对比:
- 暴力搜索:每次查询的复杂度为 O(N)。因此,执行 N 次查询的总复杂度为 O(N²)。
- KD树搜索:其复杂度取决于数据分布。
- 在理想(均匀分布)情况下,总复杂度约为 O(N log N)。
- 在最坏(特殊分布)情况下,总复杂度可能达到 O(N²),与暴力搜索相同。
需要指出的是,对于大规模数据 N,KD树在理想情况下能带来显著的性能提升。
经验性研究:维度与数据量的影响
接下来,我们通过经验性研究,观察需要检查的节点数量如何随数据量 N 和空间维度 D 变化。
以下是核心发现:
- 增加观测数据量 (N):当增加观测点数量 N 时,所需检查的节点数量大致呈现 对数增长 (log N) 趋势。这与理论预期相符。
- 增加空间维度 (D):当增加空间维度 D(即观测点 X_i 所在的 R^D 空间)时,情况则不同。为了找到最近邻,所需进行的距离计算次数(或搜索的树节点数量)会呈 指数级增长。
对于高维度 D 的场景,使用KD树可能变得没有意义。我们后续将讨论这个问题,并介绍一种在高维场景下更有效的替代方法。
扩展:使用KD树进行K近邻搜索
在讨论高维替代方案之前,我们先了解如何将KD树从单一最近邻搜索扩展到K近邻搜索。
这个扩展非常直观且简单。核心修改如下:
- 原算法(1-NN):在搜索过程中,维护一个变量记录 当前找到的最近邻的距离。
- 扩展算法(K-NN):在搜索过程中,维护一个变量记录 当前找到的第K近邻的距离。

算法流程几乎完全相同。唯一需要在代码中修改的是:不再维护到最近邻的距离,而是维护到当前已找到的第K近邻的距离。
在回溯和剪枝时,判断条件也相应改变:如果一个树节点的边界框与查询点的距离 大于 当前第K近邻的距离,那么该节点内的所有点都不可能是更近的邻居,因此可以安全地剪枝该节点。

总结


本节课中我们一起学习了KD树性能的关键方面。我们了解到,KD树的搜索效率高度依赖于数据分布,在均匀数据下接近 O(log N),在特殊分布下可能退化至 O(N)。通过分析多查询复杂度,我们认识到KD树适用于大量查询的场景以摊销构建成本。经验研究表明,KD树在低维空间中表现良好,但随着维度 D 增加,其性能会因“维度灾难”而指数级下降。最后,我们掌握了如何通过简单修改距离维护策略,将KD树算法从最近邻搜索扩展到K近邻搜索。
机器学习:3.4:使用KD树进行近似k近邻搜索

在本节课中,我们将学习如何使用KD树进行近似k近邻搜索。这是一种在牺牲少量精度的情况下,大幅提升搜索效率的方法。我们将探讨其工作原理、优势以及在高维数据中面临的挑战。
上一节我们详细介绍了KD树在精确最近邻搜索中的应用。本节中,我们来看看如何通过调整搜索策略,实现更高效的近似搜索。
近似搜索的核心思想
到目前为止,我们讨论的所有方法都旨在从所有数据点中找到精确的最近邻。但这个假设依赖于两个前提:一是找到精确最近邻非常重要,二是我们完全信任数据的表示方式和用于计算相似度的距离度量。
如果对数据表示或距离度量没有百分之百的信心,那么找到精确最近邻与找到一个“非常接近”的邻居之间,实际差异可能并不大。因此,一个关键问题是:如果我们不严格要求找到精确最近邻,而只满足于一个相当好的近似,能否让搜索效率变得更高?
在KD树的框架下,实现近似最近邻搜索的方法如下。
实现方法:更激进的剪枝
回忆一下,在精确搜索中,我们会维护一个变量 R,它代表当前已找到的最近邻的距离。
R = distance_to_nearest_neighbor_so_far
在近似搜索中,我们将进行更激发的剪枝,以此换取效率提升,代价是结果变为近似值。具体做法是,不再基于距离 R 进行剪枝,而是基于一个更小的距离 R / α 进行剪枝,其中 α 是一个大于1的数。
这意味着我们使用的搜索半径更小。因此,一个边界框到查询点的距离超过 R / α 的可能性,会比超过 R 的可能性更大,从而更早地被剪枝,减少需要搜索的节点数量。
近似搜索的性质
使用这种更激进的剪枝策略进行搜索,会得到以下性质:
如果我们最终返回的邻居距离为 R,那么可以保证在距离 R / α 的范围内没有其他数据点。
为了更清晰地说明,假设 Xq 是我们的查询点,R 是返回的最近邻距离。那么,在以 Xq 为中心、半径为 R / α 的超球体内,不存在任何数据点。否则,我们就会找到它,并且 R 的值会更小。我们剪枝掉了所有距离超过 R / α 的区域。
通过这种方式,我们得到了一个相当好的近似解。实际上,这里陈述的界限(R / α)是比较宽松的,在实践中,我们找到的邻居通常比这个界限更接近最优解。最重要的是,这节省了大量的搜索工作。
当然,如果参数 α = 1,那么该方法就退化回我们之前讨论的精确最近邻搜索。
近似搜索的实用价值
在许多实际应用中,进行近似最近邻搜索的效果与暴力搜索几乎一样好。这是因为在计算距离时,数据表示本身存在大量“噪声”,并且这个距离是否真的能完美反映相关性(例如,对于一篇我正在阅读的文章,推荐一篇“相当接近”的文章可能就完全能满足我探索相关文献的需求)也存在不确定性。
因此,近似搜索在保持结果实用性的同时,提供了显著的效率优势。
KD树的总结与局限
首先,KD树确实是一种非常巧妙且高效的数据结构。但我们也需要讨论它的其他方面和一些局限。
以下是关于KD树及其变体的一些要点:
- 多种变体:我们讨论了一些启发式方法,例如如何选择分割维度和分割值。实际上,存在大量KD树的变体。
- 其他空间划分方式:除了进行坐标轴对齐的分割,还有其他构建类似树结构的方法,例如球树,它使用超球面而非超平面来划分空间。我们接下来要讨论的方法,就可以被视为这些坐标轴对齐分割的替代方案之一。
高维空间的挑战
无论是对于KD树还是最近邻搜索,当处理高维数据时,事情都会变得极具挑战性。
对于KD树:
我们曾提到,需要检查的节点数量可能随着维度 D 呈指数级增长。一个经验法则是,通常只有当数据点的数量 N 远大于 2^D(2的D次方)时,KD树才是有用的。在高维情况下,我们往往没有足够多的数据点来让KD树发挥价值。
对于最近邻搜索:
高维空间带来的挑战不仅仅是KD树效率下降。从一个非常高维的特征向量来看,很多特征可能基本上是噪声,这些噪声会淹没距离计算中有意义的部分。导致的结果是,在高维空间中,所有点彼此之间都显得非常遥远。
因此,我们真正需要的是能够学习哪些特征是重要的,或者如何权衡不同特征的技术。正如之前提到的,这是一项极具挑战性的任务,需要大量的领域知识或深入的思考和探索。
最后,衷心感谢安德鲁·摩尔(Andrew Moore)允许使用其关于KD树的精彩演示文稿大纲,本节幻灯片的内容在很大程度上借鉴了他的成果。
本节课总结
本节课中,我们一起学习了:
- 近似最近邻搜索的核心思想:通过接受近似结果来大幅提升搜索效率。
- 在KD树中实现近似搜索的关键技术:使用
R / α(α > 1)进行更激进的剪枝。 - 近似搜索的性质:返回距离为
R的邻居,并保证在R / α范围内没有其他点。 - KD树的优势与多种变体。
- KD树和最近邻搜索在高维空间中面临的主要挑战,包括效率下降和“维度灾难”问题。

通过理解近似搜索,我们为处理大规模、高维数据下的相似性检索问题提供了一个实用的工具。在接下来的章节中,我们将继续探索其他可扩展的近似最近邻搜索方法。
机器学习(分类,聚类和检索):3-4:KD树的局限性


在本节课中,我们将要学习KD树这一高效近邻搜索方法的局限性,并探讨为何在高维数据场景下需要考虑其他替代方案。
KD树的优势与挑战
上一节我们介绍了KD树如何通过递归划分空间来组织数据,从而实现高效的最近邻搜索。KD树是一种非常直观的数据存储和查询方式,并且确实能带来显著的搜索效率提升。
然而,KD树也存在一些挑战。

以下是KD树面临的两个主要问题:

- 实现复杂度高:构建和结构化KD树本身可能颇具挑战性。
- 高维性能下降:随着数据维度的增加,使用KD树进行最近邻搜索的效率可能会变得非常低。
接下来,让我们更深入地探讨高维空间带来的问题。
高维空间的“维度灾难”
在高维空间中,一个基本现象是:每个点都与其他点相距甚远。
回想一下KD树的划分过程,在高维空间中,我们得到的是由超矩形构成的不同分区。当我们有一个查询点时,在给定的超矩形分区内,不太可能找到任何距离很近的点。因此,算法会先找到一个当前最近邻点,并以其距离为半径画一个高维超球体。
算法的剪枝规则是:只有当某个分区(bin)到查询点的距离大于当前最近邻距离时,才能将其排除。但在高维空间中,这个以当前最近邻距离为半径的大球体,会在至少一个维度上与大量的超矩形分区相交,导致我们无法剪枝这些分区。
最终结果是,你不得不搜索海量的分区。在某些条件下,可以证明你需要搜索超过 2^D 个不同的超矩形分区(D为维度)。这完全抵消了KD树带来的效率优势,除非观测数据的数量N远远大于2^D。
转向近似最近邻搜索
那么,我们能做什么呢?一个可行的思路是放弃进行精确的最近邻搜索。
实际上,我们在讨论KD树时已经提到过,可以用它来进行近似最近邻搜索。这也将是本节的重点。因为我们通常并不完全信任距离度量能百分之百精确地刻画我们想要的“距离”。在许多应用场景中,我们只需要找到一个与查询点相当接近的邻居,而不必是严格数学意义上的最近邻居。对于很多检索任务来说,这已经能提供足够的性能。
但是,与之前使用KD树进行近似搜索不同,接下来我们将关注一类新方法。这类方法能为我们所做的近似提供概率性保证。
总结

本节课中,我们一起学习了KD树在高效近邻搜索中的局限性。我们了解到,尽管KD树直观且有效,但其实现较为复杂,并且在处理高维数据时,由于“维度灾难”导致搜索效率急剧下降,甚至可能退化为近似暴力搜索。为此,我们引入了转向近似最近邻搜索的必要性,并指出下一节将探讨能提供概率性近似保证的新方法。
机器学习(分类,聚类和检索):第3-4课:作为KD树替代方案的LSH 🧭

在本节课中,我们将学习局部敏感哈希(Locality Sensitive Hashing,简称LSH),这是一种与KD树不同的、用于高效近邻搜索的数据分区方法。我们将通过一个简单的文本数据示例,了解LSH的基本原理、实现方式及其与精确搜索的区别。


从分区数据到哈希表
上一节我们介绍了KD树通过坐标轴对齐的切割来划分数据。本节中我们来看看局部敏感哈希(LSH)如何以另一种根本不同的方式进行数据分区。
我们回到分类课程中使用过的一个例子:假设我们有一些餐厅评论,我们统计每条评论中“awesome”(很棒)和“awful”(糟糕)两个词出现的次数。当我们需要检索相似的评论时,就基于这两个计数来操作。
与分类课程中类似,我们可以用一条简单的直线来划分这些数据点。这条直线就像一个决策边界,其方程可以表示为:
score = 1 * (count of awesome) + 1 * (count of awful) - 5
这里我们定义了一个“分数”项。对于任何以“awesome”和“awful”计数作为输入的评论,我们都可以计算其分数。落在这条线下方的点具有负分数,上方的点则具有正分数。
但在这里,我们使用这些分数的方式与分类课程不同。我们将根据分数的符号,将数据点分配到不同的“桶”中:
- 如果分数的符号为负,所有这些点都被分配到我们称为“0号桶”中。
- 如果分数的符号为正,所有这些点则被分配到“1号桶”中。
这样,我们就将分数的符号转换成了一个二进制索引。
基于哈希表的近邻搜索
在实际操作中,我们使用一种称为“哈希表”的结构来搜索所有与查询点具有相同桶索引的数据点。
哈希表的工作原理是:对于每个桶值(桶0或桶1,我们称之为“键”),我们关联一个“值”的集合,即属于该桶的所有数据点的索引列表。
换句话说,我们取所有桶值为0的数据点,将其索引列在表的第一个元素中;取所有桶值为1的数据点,将其索引列在表的第二个元素中。
当我们获得一个查询点,并根据其分数的符号确定其桶索引后,我们只需在该桶对应的索引列表中搜索近邻即可。
这为近邻搜索提供了一种非常简单的实现方式。其核心思想是画一条线,然后只搜索落在该线同一侧的其他点。
LSH的近似性与权衡
但问题是:这种方法能返回精确的最近邻吗?答案是否定的。
例如,这里有一个绿色的查询点。假设这个恰好在线之上、非常接近绿点的橙色点才是真正的最近邻。如果我们只搜索所有与该绿点具有相同桶值(此处为桶1)的蓝色点,那么我们将无法找到那个橙色的最近邻点。
因此,局部敏感哈希是一种近似近邻搜索方法。它通过牺牲一定的精确度,换取了在大规模数据集中极高的搜索速度。其核心优势在于,能够快速将搜索范围缩小到可能与查询点相似的一个数据子集中。
总结


本节课中,我们一起学习了局部敏感哈希(LSH)的基本原理。我们了解到LSH通过将数据点基于某个随机超平面(在示例中是一条线)的投影符号分配到不同的“桶”中,并使用哈希表来管理这些桶。当进行近邻搜索时,只需在查询点所在的桶内进行查找,从而极大地提高了搜索效率。虽然LSH是一种近似方法,不一定总能找到精确的最近邻,但它在处理高维、大规模数据时,在速度与准确性之间提供了一个优秀的权衡方案。
机器学习(分类,聚类和检索):第3-4课:使用随机线划分点

在本节课中,我们将学习一种使用随机线划分数据点的方法,以实现高效的近似最近邻搜索。我们将探讨如何定义划分线、这种方法的搜索质量以及其带来的效率提升。
🎯 核心概念:随机线划分


到目前为止,我们描述了使用简单直线划分数据点的概念。需要说明的是,在本节讨论的所有方法中,我们假设直线没有截距项,即直线始终通过原点。这是一种非常简单的结构,也是一种将数据划分为两个独立区域的简单方式。通过这种方式,我们可以轻松地搜索落入每个区域的数据点。
然而,我们可能会面临几个问题。其中一个问题是:如何定义一条好的直线来划分数据点?与此相关的问题是:这种最近邻搜索的质量如何?我们说过它提供的是近似最近邻搜索,但实际找到给定查询点的最近邻的概率是多少?最后,这种简单的数据点划分方法能带来何种效率提升?
🧠 如何定义划分线?
让我们从如何定义这条线的问题开始。为此,我们提出一个听起来非常疯狂的想法:如果我们只是随机画一条线呢?即随机放置一条通过原点的直线。这听起来可能非常糟糕,但让我们仔细思考一下。
我们的目标是:如果两个点彼此接近(这里我们关注的是余弦相似度),我们希望这两个点落入同一个区域。为了形式化这一点,假设有两个点 x 和 y,它们之间的夹角为 θ_xy。余弦相似度就是通过这个夹角的余弦值来定义的。
现在,我们开始随机画线。有些线会将 x 和 y 都放入区域0(因为它们的得分都小于0),有些线会将它们都放入区域1(因为得分都大于0)。但我们也可能犯错:有些线会将 x 和 y 分开,放入不同的区域(例如,y 得分为负进入区域0,x 得分为正进入区域1)。
关键问题是:这种情况发生的概率有多大?如果 θ_xy 非常小,那么一条在0到π/2之间均匀随机的直线恰好落入那个小角度范围内的概率也很小。这意味着,x 和 y 被放入不同区域的概率很小。因此,如果 x 是我们的查询点,我们不太可能错过其最近邻 y,因为 y 很可能在同一个区域。
总结来说,随机画线的想法实际上并不疯狂。它在概率意义上提供了良好的性能,能够为大量查询找到精确的最近邻。
⚡ 效率问题与改进思路
到目前为止,我们已经讨论了前两点:展示了如何简单地随机画线,以及这种方法在最近邻搜索中能提供良好的性能。然而,还存在一个非常棘手的第三点:这种方法能带来多大的效率提升?
如果我们只画一条线,结果往往是:当我们有大量数据点时,划分出的两个区域可能仍然包含非常多的数据点。查询仍然需要在这大量的点中进行搜索。因此,我们在效率上似乎有所提升,但提升并不显著。
那么,我们该如何解决这个问题呢?下一节我们将探讨通过使用多条随机线来创建更精细的划分,从而进一步提高搜索效率。
📝 总结

本节课中,我们一起学习了使用随机线划分数据点以实现近似最近邻搜索的基本方法。我们了解到,随机选择通过原点的直线是一种简单有效的划分策略,并且从概率上看,它能很好地保持邻近点在同一区域内。然而,单条划分线在数据量巨大时带来的效率提升有限,这引导我们去思考如何使用多条线来创建更高效的索引结构。
机器学习(分类,聚类和检索):第3-4课:定义更多的桶 🪣

在本节课中,我们将学习如何通过定义更多的“桶”(即分区)来提升近似最近邻搜索的效率。我们将探讨如何利用多条随机线对数据空间进行更精细的划分,从而减少每次查询时需要检查的数据点数量。
上一节我们介绍了使用一条随机线划分空间的方法。本节中,我们来看看如何通过增加随机线的数量来创建更多、更小的分区。
为了更正式地阐述,让我们思考如何减少每次查询时需要检查的数据点数量。一个自然的想法是,通过绘制更多的线来创建更多的分区,使得每个分区包含的数据点更少。这样,当对给定查询点进行搜索时,我们只需要在一个更小的点集中寻找,以返回一个近似的最近邻。
以下是实现这一想法的具体步骤:
- 生成多条随机线:与之前类似,我们在数据空间中随机生成多条线(或超平面)。每条线由一个随机向量 w 和一个随机偏置 b 定义,其方程为 w·x + b = 0。
- 为每个数据点计算二进制向量:对于数据集中的每一个点 x,我们计算它在每条线下的“分数”:
score_i = w_i·x + b_i。然后,我们取每个分数的符号(正或负),生成一个二进制向量。例如,如果某点在三条线下的分数符号分别为负、正、负,则其二进制向量为[0, 1, 0](这里约定负为0,正为1)。 - 将二进制向量映射为哈希表键值:每个唯一的二进制向量对应一个“桶”或分区。我们将这个二进制向量转换成一个整数键值(例如,通过二进制转十进制),用作哈希表的索引。
- 构建哈希表:对于哈希表中的每个键值(即每个桶),我们存储所有具有相同二进制向量的数据点。
当进行查询时,流程如下:
- 对查询点 q 执行相同的操作:计算它在所有随机线下的分数,生成其二进制向量。
- 将此二进制向量转换为键值,并在哈希表中查找对应的桶。
- 仅在该桶包含的数据点集合中进行最近邻搜索。
相对于只使用一条线的方法,我们期望每个桶中包含的数据点更少。这正是提升我们最近邻搜索效率的关键。


本节课中,我们一起学习了如何通过引入多条随机线来定义更多的数据桶。这种方法是对单线划分的自然推广,它通过创建更精细的分区,显著减少了每次查询时需要处理的数据量,从而在保持近似精度的同时,提高了搜索速度。核心在于利用二进制向量对数据点进行快速哈希分桶。
机器学习(分类,聚类和检索):第3-4课:搜索相邻的桶

在本节课中,我们将要学习局部敏感哈希(LSH)中一个重要的优化技巧:搜索相邻的桶。我们将了解为什么仅搜索查询点所在的单个桶可能不够,以及如何通过搜索附近的桶来提升找到最近邻的概率,同时还能在搜索精度和计算效率之间进行灵活的权衡。
概述
上一节我们介绍了通过投掷多条随机线来划分数据空间,并将数据点分配到不同的“桶”中。本节中我们来看看,当进行最近邻搜索时,为什么以及如何搜索查询点所在桶的“邻近”桶。
为什么需要搜索邻近桶?
假设我们的查询点落在下图所示的这个桶中,其二进制编码为 010。

根据我们投掷的线,查询点被编码为 010。我们接下来会在这个桶内(包含数据点4、8和11)计算查询点到这些数据点的距离。
问题是:我们能保证在这个桶里找到真正的最近邻吗?
答案是否定的。我们只能期望返回一个近似最近邻。因为真正的最近邻很可能位于其他某个桶中,并且由于我们投掷的线,它被与查询点分割开了。
更重要的是,当我们投掷多条线时,查询点与其最近邻被分割开的风险比只投掷一条线时更高。因为线越多,其中某一条或多条线将这两个点分开的可能性就越大。
因此,我们看到,投掷多条线实际上是在用精度换取速度。虽然搜索单个桶的效率很高,但找到真正最近邻的概率降低了。
如何定义“邻近”桶?
但这里有一个更好的消息:我们可以控制这种近似程度,也能控制搜索所花费的计算量。因为我们不必只搜索查询点所在的桶,还可以搜索邻近的桶。
那么,什么是“邻近的桶”呢?让我们来看一个例子。
假设查询点位于下图位置,它所在的桶编码是 010。

哪些是邻近的桶呢?它们是编码为 000 和 110 的桶。如果你思考一下这些二进制向量是如何定义的,就会发现:邻近的桶就是那些与当前桶索引仅有一位不同的桶。
例如:
- 将
010的第一位0翻转为1,我们得到110(蓝色桶)。 - 将
010的第二位1翻转为0,我们得到000(橙色桶)。
这相当于让查询点“跨越”了定义当前桶的某一条线,落到相邻的区域。
实践中的搜索策略
回到我们的哈希表结构。假设查询点落在桶2(二进制 010)。我们不仅搜索桶2,还会查看其二进制编码,然后翻转其中的位,去搜索那些邻近的桶。
以下是具体步骤:
- 确定查询点所在的桶索引(例如
010)。 - 搜索该桶本身。
- 生成所有汉明距离为1的桶索引(即仅翻转一位):
- 翻转第一位:
110-> 桶6 - 翻转第二位:
000-> 桶0 - (翻转第三位:
011-> 桶3,如果存在)
- 翻转第一位:
- 搜索这些新生成的桶。
- 计算查询点到所有这些桶内数据点的距离。
这样做的假设是:如果真正的最近邻不在查询点所在的桶,那么它很可能只被一条线与查询点隔开,因此会落在这些汉明距离为1的邻近桶中。
处理更复杂的分割情况
但是,查询点与其最近邻有可能被两条或更多条线分割开。
假设查询点在这里,其最近邻在这里。我们投掷的两条线恰好将这两个点分开了。

在这种情况下,我们需要搜索汉明距离为2的桶(即翻转两位)。对于桶 010,翻转两位可能得到 100、001 或 111 等。我们需要搜索这些桶,并计算其中数据点的距离。
核心概念是:我们搜索的邻近桶范围越广(翻转的位数越多),找到的最近邻质量就越高,但需要计算的距离也越多。
控制精度与计算的权衡
在实践中,使用局部敏感哈希进行最近邻搜索时,我们通常采用以下策略之一:


以下是两种常见的停止搜索条件:
- 设定计算预算:持续搜索邻近的桶(先翻1位,再翻2位,以此类推),直到用尽为该次搜索设定的计算资源(例如,时间限制或最大计算距离数)。
- 设定质量阈值:持续搜索,直到找到一个与查询点距离在某个 ε 范围内的数据点。一旦找到,即认为足够好,停止搜索。
相对于只投掷一条线的方法,这种方法的优势在于我们可以主动控制近似精度与搜索复杂度之间的权衡。我们可以通过搜索更多桶来获得更好的近似结果,也可以在必要时提前终止搜索。而如果只投掷一条线,我们无法知道该搜索哪些点集,也无法在精度和效率之间做出灵活选择。
总结与回顾
本节课中我们一起学习了局部敏感哈希中搜索邻近桶的核心思想。让我们来回顾一下整个流程:
- 数据分区:我们投掷
h条随机线,根据每条线对每个数据点进行打分(0或1),形成一个h位的二进制向量。 - 构建哈希表:这个二进制向量作为键,将所有具有相同向量的数据点放入哈希表的同一个“桶”中。这形成了一个对数据点的固定划分。
- 最近邻搜索:对于一个给定的查询点:
- 用同样的
h条线为其生成二进制编码。 - 以此编码作为键,定位到初始桶。
- 不仅搜索该初始桶,还系统地搜索其“邻近”的桶(通过翻转二进制位实现)。
- 在搜索到的所有数据点中,返回距离查询点最近的那个作为(近似)最近邻。
- 用同样的
这个哈希表数据结构一旦构建完成,就可以为每一个新的查询重复使用。虽然构建哈希表本身需要成本(我们稍后会讨论),但后续的每次查询都能高效地复用这个结构,这是局部敏感哈希的一大优点。


机器学习(分类,聚类和检索):第3-4课:高维空间中的局部敏感哈希

在本节课中,我们将要学习如何将局部敏感哈希(LSH)技术应用于高维空间。我们将探讨当特征维度(例如词汇表大小)非常大时,如何有效地划分空间并进行最近邻搜索。


从二维到高维的扩展
上一节我们介绍了在二维空间中使用随机线进行空间划分的方法。本节中我们来看看当数据存在于更高维度(例如三维或更多维)时,LSH 应如何操作。
如果维度超过两个,例如在三维空间中,我们不再使用随机线,而是考虑使用随机平面或超平面来划分空间。这个平面同样被设定为穿过原点 (0,0,0)。
对于任意数据点 X,其“分数”由以下公式计算:
分数 = v1 * x1 + v2 * x2 + v3 * x3
其中 (x1, x2, x3) 是点的坐标(例如,分别代表词语“awesome”、“awful”和“great”的出现次数),而 (v1, v2, v3) 是定义该平面的随机系数。我们根据该分数的正负来决定点的哈希桶索引。
扩展到 D 维空间时,公式变为:
分数 = v1*x1 + v2*x2 + ... + vD*xD
我们通过随机生成 D 个系数 (v1, v2, ..., vD) 来定义一个随机超平面,用于空间划分。
高维空间中的计算成本
接下来,我们分析在高维空间中对数据点进行分桶的计算成本。
对于每一个数据点,我们需要为每一个随机超平面计算其分数,以确定其在该超平面下的桶索引。这意味着,对于第 i 个超平面及其系数 (v1_i, v2_i, ..., vD_i),我们需要进行 D 次乘法运算(系数与对应特征值相乘)。如果有多个超平面,这个计算需要重复多次。
然而,在高维空间的某些特定应用中,这种乘法运算通常是稀疏的。以下是一些关键应用场景:
- 文本数据与词汇表:当维度是词汇表大小,数据点是文档的词频向量时,任何一篇文档通常只包含词汇表中的一小部分词语。因此,对于大多数维度,特征值
xj为零,对应的乘法vj * xj无需实际计算。这大大减少了实际运算量。
尽管存在计算成本,但一个非常重要的通用事实是:构建哈希表的这一次性成本,会被后续大量的查询操作所抵消。每次进行最近邻查询时,我们直接使用已构建好的哈希表,而无需重新进行上述所有的乘法运算。这使得 LSH 在处理大规模、高维数据的重复查询时非常高效。
总结


本节课中我们一起学习了局部敏感哈希(LSH)在高维空间中的应用。我们了解到,可以通过随机超平面来划分高维空间,每个数据点的归属由超平面系数与特征向量的点积结果决定。虽然在高维下计算点积存在成本,但在像文本处理这样的稀疏数据场景中,计算可以得到优化。更重要的是,一次性的哈希表构建成本,能够为后续大量的快速最近邻查询提供支持,这是 LSH 技术的核心优势之一。
机器学习(分类,聚类和检索):第3-4课:可选:通过多表提升效率 🚀

在本节课中,我们将探讨一种使用局部敏感哈希(LSH)进行更高效最近邻搜索的方法,即使用多个哈希表。虽然这部分内容涉及一些概率分析,属于进阶知识,但我们将尽力用简单直白的方式解释其核心概念和重要性。
概述
之前我们介绍了使用单一哈希表进行最近邻搜索。本节中,我们将看到,通过创建并使用多个哈希表,即使搜索的总桶数相同,我们也能显著提高找到真正最近邻的概率。这种方法的核心在于利用概率的“乘方效应”来降低遗漏目标点的风险。
单表与多表搜索对比
为了理解多表方法的优势,我们先从一个简单的例子开始。
单哈希表场景(搜索多个桶)
假设我们投下两条随机线(H=2),将数据空间划分为4个桶。对于查询点,我们不仅搜索它所在的桶,还搜索所有与之仅相差1比特的相邻桶。
- 搜索桶数:查询点所在桶 + 2个相邻桶 = 3个桶。
- 未找到最近邻的概率:这要求两条线都恰好将查询点与其最近邻分开。如果单条线分开两点的概率是
δ,那么两条线都将其分开的概率是δ²。- 公式:
P_miss_single = δ²
- 公式:
多哈希表场景(每个表只搜一个桶)
现在,我们创建三个独立的哈希表(M=3),每个表都由两条随机线生成。对于每个表,我们只搜索查询点所在的那个桶。
- 搜索总桶数:3个表 × 1个桶/表 = 3个桶(与单表场景相同)。
- 未找到最近邻的概率:这要求查询点与其最近邻在所有三个表中都被分到了不同的桶。在单个表中,两点被分到不同桶的概率是
1 - (1-δ)²(即至少有一条线分开了它们)。这个概率可以简化为2δ - δ²。由于三个表独立,总概率是这个概率的三次方。- 公式:
P_miss_multi = (2δ - δ²)³
- 公式:
以下是两种方法在 δ(两点被分开的概率)变化时的性能对比图。δ 越小,意味着两点越接近。

如图所示,在 δ 较小(即最近邻离查询点很近)的大部分区域内,多哈希表方法(红色线)的未命中概率远低于单哈希表方法(蓝色线)。这说明,在搜索相同数量桶的前提下,多表策略能提供更高的召回率。
推广到更一般的情况
上一节我们以两条线为例。本节中我们来看看当使用更多哈希线(H 更大)时,情况会如何变化。
单哈希表场景(搜索 H+1 个桶)
当我们投下 H 条线时,哈希码有 H 比特。搜索“查询桶及其所有1比特差异的邻居桶”,总共需要搜索 H+1 个桶。未找到最近邻的概率计算更复杂,它等于1减去(两点在同一桶的概率)再减去(两点恰好被一条线分开的概率)。
- 公式:
P_miss_single = 1 - (1-δ)^H - H * δ * (1-δ)^(H-1)
多哈希表场景(创建 M 个表,每表搜1桶)
我们创建 M 个独立的哈希表(通常令 M = H+1 以保持总搜索桶数可比)。在每个表中,只搜索查询点所在的桶。未命中的条件是:在所有 M 个表中,两点都被分到不同桶。
- 单个表中两点在不同桶的概率:
1 - (1-δ)^H - 所有 M 个表均未命中的概率:
[1 - (1-δ)^H]^M
下图对比了当 H=3 和 H=10 时,两种方法的性能差异。


可以清楚地看到:
- 随着哈希线数量
H增加,两种方法的未命中概率整体都下降了(因为编码更精细)。 - 多哈希表方法(品红线)的优势随着
H增大而变得更加显著,其曲线始终远低于单哈希表方法(蓝色线)。
实践中的权衡
在实际应用中,我们通常固定哈希码的宽度(即比特数 H),然后调整哈希表的深度(即表的数量 M)。
- 单哈希表(深度=1):
- 优点:构建成本低,只需维护一个表。
- 缺点:要达到高召回率,需要在同一个表内搜索大量相邻桶,计算开销大。
- 多哈希表(深度=M):
- 优点:通过指数衰减的概率
[1 - (1-δ)^H]^M,可以用相对较少的总搜索桶数(M个桶)获得极高的召回率。 - 缺点:构建和存储
M个独立的哈希表需要更多的内存和预处理时间。
- 优点:通过指数衰减的概率
以下示意图概括了这种权衡:



总结

本节课中我们一起学习了利用多个局部敏感哈希表来提升最近邻搜索效率的原理。核心结论是:与在单个哈希表中搜索多个桶相比,在多个哈希表中各搜索一个桶(保持总搜索开销相近)通常能提供更好的搜索质量(更高的召回率)。这是因为多表策略利用了独立事件的概率乘法原理,使未命中概率随表数量增加而指数级下降。在实际系统中,需要在索引构建成本、存储开销和查询精度之间进行权衡,选择合适的哈希表宽度(H)和深度(M)。
机器学习(分类,聚类和检索):第3-4课:模块回顾与总结 📚

在本节课中,我们将回顾本模块所涵盖的核心内容。本模块聚焦于文档检索任务,并将其形式化为最近邻搜索问题。我们将总结讨论过的算法、数据表示方法、距离度量以及高效搜索技术,并列出学完本模块后应掌握的关键技能。
模块内容回顾
上一节我们介绍了高效近似最近邻搜索的局部敏感哈希方法。现在,让我们对整个模块的学习内容进行一次系统的梳理。
本模块的核心任务是检索感兴趣的文档,我们将其构建为执行最近邻搜索的问题。
我们回顾了用于执行1-最近邻搜索和K-最近邻搜索的算法。我们深入探讨了这些算法的细节,特别是如何表示数据。我们重点讨论了文档的不同表示方法。
一个非常关键的概念是如何计算两个不同数据点之间的距离。我们学习了一系列计算这类距离的不同方法,并讨论了它们之间的权衡。事实上,对于“什么是最佳数据表示”和“应该使用哪种距离度量”,并没有唯一的答案。这很大程度上依赖于领域知识,并且对算法的性能有重大影响,因此需要审慎思考。
当数据观测点数量极大时,暴力搜索的计算开销会非常高昂。因此,在模块的后半部分,我们讨论了实现高效最近邻搜索的方法。
我们介绍了Kd树,这是一种可用于执行最近邻搜索的高效数据结构。我们展示了它的适用场景,但也指出了它在高维空间中可能遇到的困难。
于是,我们转向了局部敏感哈希的概念。它只提供近似最近邻,但我们论证了这在大量实际应用中是完全合理且可行的。局部敏感哈希实现起来非常简单,效率很高,并且能提供具有概率保证的良好近似结果。
学完本模块,你将掌握一些非常强大的工具,这些工具不仅适用于文档检索,还能广泛应用于海量的其他检索任务中。在许多应用中,你都有一个查询点,并希望找到相似的对象,本模块讨论的所有工具都能推广到这些其他应用场景。
学习成果总结
以下是学完本模块后,你应该能够完成的事项:
- 将检索任务形式化为最近邻搜索问题。
- 为文档检索等任务实施并应用不同的数据表示方法。
- 计算各种距离度量,例如欧几里得距离(公式:
distance = sqrt(sum((x_i - y_i)^2)))和余弦相似度(公式:similarity = (A·B) / (||A|| * ||B||)),并理解其权衡。 - 解释Kd树的工作原理及其在高维数据中的局限性。
- 实施局部敏感哈希进行近似最近邻搜索,并理解其概率保证。
- 将本模块的概念应用于文档检索之外的广泛相似性搜索问题。


本节课中,我们一起学习了机器学习中关于分类、聚类和检索的核心模块。我们从文档检索任务出发,深入探讨了最近邻搜索的算法基础、数据表示与距离度量的重要性,并学习了Kd树和局部敏感哈希这两种应对大规模数据搜索挑战的高效技术。这些工具为你解决广泛的相似性匹配与检索问题奠定了坚实的基础。
机器学习(分类,聚类和检索):第3课:聚类的目标 🎯

在本节课中,我们将要学习聚类的核心目标及其在文档分析中的应用。我们将探讨为什么需要发现数据中的分组结构,以及这种结构如何帮助我们改进文档检索和用户偏好学习等任务。
聚类的目标

上一节我们介绍了文档检索任务,即根据用户正在阅读的文章,在语料库中寻找最相似的文章。然而,在许多情况下,我们更感兴趣的是发现数据本身的结构化表示。
本节中,我们来看看聚类的具体目标。聚类的目标是发现相关的文章组。例如,可能有一组文章全部与体育相关,而另一组文章则全部关于世界新闻。如果我们能在数据中发现这种结构,就可以更高效地处理后续任务。

聚类在文档检索中的应用
如果我们能发现数据中的这种分组结构,那么在进行之前讨论的文档检索任务时,就可以利用它。具体步骤如下:
- 当一个人正在阅读一篇文章时,我们先确定这篇文章属于哪个分组。
- 当我们需要为该读者检索另一篇文章时,我们只需在该特定分组内进行搜索。
例如,如果用户正在阅读一篇体育文章,我们可以通过在这个“体育文章”分组内寻找最近邻,来推荐另一篇体育文章。这种方法可以缩小搜索范围,提高检索的效率和相关性。
聚类在用户偏好学习中的应用
实际上,我们可以利用聚类做更复杂的事情。例如,我们可能对了解用户在一系列不同主题上的偏好感兴趣。在这种情况下,我们假设用户不仅对体育感兴趣,可能还有其他兴趣。当我们向该用户推荐文章时,我们可能希望探索他的其他偏好。
以下是利用聚类学习用户偏好的一个示例流程:
- 首先,我们假设已经将文章聚类成不同的相关文章组。
- 用户会阅读语料库中的一部分文章(下图中未变灰的文章)。
- 用户会给出对文章的反馈:“+”表示喜欢,“-”表示不喜欢。

根据上图示例:
- 用户喜欢聚类1(绿色)中的两篇文章。
- 用户喜欢聚类4(😊橙色)中的一篇文章。
- 用户不喜欢在聚类2(蓝色)中阅读的那篇文章。
- 用户不喜欢在聚类4中阅读的另一篇文章。
- 用户喜欢在聚类2中阅读的这篇文章。
随着时间推移,我们可以利用这些反馈来学习用户在不同主题(即不同文章聚类)上的偏好向量。需要说明的是,我们最初可能没有“体育”、“世界新闻”这样的主题标签,但我们知道存在文章分组。我们可以利用这些分组来选择文章,或者事后深入分析这些分组并为其手动添加标签。

本节课中,我们一起学习了聚类的核心目标是发现数据中的自然分组。我们探讨了聚类如何应用于文档检索,通过缩小搜索范围来提高效率;以及如何用于学习用户偏好,通过分析用户在不同文章组上的反馈来构建偏好模型。理解这些目标是应用后续聚类算法的基础。
机器学习:第3课:无监督任务

在本节课中,我们将要学习什么是无监督学习任务,特别是聚类。我们将通过与监督学习进行对比,来理解聚类任务的核心概念、目标以及如何定义和推断聚类。
从监督学习到无监督学习
上一节我们介绍了监督学习的基本设定。在监督学习中,我们的训练数据同时包含输入(特征)和对应的输出(标签)。例如,在回归任务中,我们根据房屋特征预测其价格;在分类任务中,我们根据评论文本预测其情感倾向。
然而,聚类是一种无监督任务。这意味着在训练过程中,我们没有被提供任何输出标签。我们的目标是从输入数据本身中发现其内在的分组结构。
一个具体的例子:文档聚类
为了更好地理解,让我们看一个文档聚类的例子。假设我们有一个文档集合,每个文档只包含两个词汇(Word1和Word2)。我们可以将每个文档表示为一个二维向量,其坐标是这两个词在文档中出现的次数。
- 输入:每个文档
X_i的向量表示。 - 输出:我们希望算法为每个文档
X_i分配一个聚类标签Z_i(例如,1, 2, 3)。


在下面的图示中,每个点代表一个文档。算法需要根据文档之间的相似性(在二维空间中表现为点的距离远近),将它们自动分成不同的组(用不同颜色表示)。

也许红色组对应“世界新闻”主题,绿色组对应“科学”主题,蓝色组对应“娱乐”主题。但关键在于,算法在开始时并不知道这些主题标签,它必须自己发现这些分组。
如何定义和推断聚类?
既然没有标签指导,我们如何让算法学会聚类呢?这涉及到两个核心问题:如何定义一个聚类,以及如何推断出这些聚类。
定义一个聚类
一个聚类通常由两个要素定义:
- 中心:也称为质心,是聚类中所有点的平均位置。
- 形状:描述了聚类中点的分布范围。在上图中,每个聚类被一个椭圆所定义。不同的椭圆有不同的旋转角度和拉伸程度,这代表了数据在不同方向上的分布差异。
为数据点分配聚类
对于一个给定的数据点 X_i(例如一个文档),我们如何决定它属于哪个聚类呢?这基于一个称为得分的概念。
最常见的方法是计算该点到各个聚类中心的距离。得分可以简单地定义为这个距离。点会被分配到距离其中心最近的那个聚类。
在图中,对于标记的 X_i 点,到红色、绿色、蓝色聚类中心的距离分别用线段表示。可以看到,到红色中心的距离最短。因此,如果仅以距离作为得分标准,X_i 将被分配到红色聚类。

总结
本节课中我们一起学习了无监督学习中的聚类任务。我们了解到:
- 聚类是一种无监督任务,其训练数据只有输入,没有输出标签。
- 聚类的目标是直接从数据中发现其内在的分组结构。
- 一个聚类由其中心(质心) 和形状(如椭圆) 定义。
- 为数据点分配聚类的基础是计算其到各聚类中心的距离,并将其归入距离最近的那个簇。

理解这些基本概念是学习具体聚类算法(如K-Means)的重要基础。在接下来的课程中,我们将深入探讨如何实现这些想法。
机器学习(分类,聚类和检索):第3-4课:无监督学习的希望与挑战案例 🎯

在本节课中,我们将探讨无监督学习的基本概念,特别是聚类任务。我们将了解在没有任何标签的情况下,如何从数据中提取结构,并审视在实际应用中可能遇到的各种挑战性案例。
无监督学习的核心思想
执行无监督学习的想法听起来非常大胆,因为我们从未获得任何标签。然而,我们却需要输出标签。有时我们能够做到这一点,主要基于两个因素。
第一个因素是聚类的定义。即我们试图从数据中提取的结构是什么。例如,我们可能正在寻找椭圆形的聚类。
第二个因素是数据本身的结构。在某些情况下,问题相当简单。
聚类问题的难易程度
以下是不同难易程度的聚类问题示例。
简单案例
在某些情况下,数据点分离得相当好。我们可以直观地将其划分为不同的组。例如,可以想象一个算法能够从数据中揭示这种结构。
困难案例
但在其他情况下,这几乎是不可能的。例如,如果必须选择三个不同的聚类,我们可能不知道如何划分这些数据。如果我们查看真实的标签,会发现数据点完全混合在一起。在没有其他信息来区分不同聚类的情况下,很难从这些数据中提取结构。
中间案例
还有一些情况则更为合理。我们的猜测可能相当合理,并且数据本身也证实了这一点。在我们感兴趣的大多数应用中,我们通常处于这种中间场景。仅通过可视化数据并不立即清晰,但如果我们处于类似“不可能案例”的场景中,也无法期望成功执行无监督学习。
聚类定义的关键性
无论数据结构如何,真正关键的是我们如何定义聚类。例如,这里有六个非常流行的、具有挑战性的聚类问题示例。从视觉上看,聚类结构非常明显。但这些聚类看起来并不像我们在前几张幻灯片中看到的简单椭圆。
如果你将这些数据提供给一个仅测量观测点到聚类中心距离的算法,得到的结果可能与视觉上跳出的聚类结构不匹配。对于这些不同的示例,我们展示了在“到最近聚类中心距离”类型的目标下,聚类可能呈现的样子。


这些幻灯片的要点是,聚类可能非常具有挑战性。即使数据看起来非常干净、美观且分离良好,有时也很难定义聚类的含义,并设计算法来发现它。
因此,你必须仔细思考你所提供的数据、你指定的模型或算法所带来的影响。当我们学习本模块及后续模块中的下一组算法时,思考基于数据结构可能面临的挑战是非常有用的。

总结

本节课中,我们一起学习了无监督学习,特别是聚类任务的核心思想。我们认识到,聚类的成功与否高度依赖于对“聚类”本身的定义以及数据的内在结构。我们看到了从简单、清晰分离的数据到复杂、模糊混合数据的各种案例,并理解了仅依赖简单距离度量的算法在处理复杂聚类结构时的局限性。这提醒我们,在实际应用中需要谨慎选择模型和算法,并充分考虑数据的特点。
机器学习(分类,聚类和检索):第3-4课:K-means算法 🧩

在本节课中,我们将要学习一种基础且广泛使用的聚类算法——K-means算法。我们将从算法的基本思想开始,逐步拆解其每一步的具体操作,并通过公式和图示帮助你理解其工作原理。
算法概述
K-means算法基于一个简单的评分定义:通过计算数据点与聚类中心之间的距离,将数据点分配到特定的簇中。算法的目标是找到一组聚类中心,使得所有数据点到其所属簇中心的距离之和最小。
算法步骤详解
上一节我们介绍了K-means算法的基本思想,本节中我们来看看其具体的执行步骤。K-means算法是一个迭代过程,主要包含以下四个步骤。
1. 初始化聚类中心
首先,我们需要指定聚类的数量K,并初始化K个聚类中心。这些中心点可以是随机选择的,也可以基于某些启发式方法确定。
在公式中,我们用希腊字母 μ 表示聚类中心。例如,当K=3时,我们有三个聚类中心:μ₁、μ₂ 和 μ₃。
2. 分配数据点到最近的中心
初始化中心后,我们需要将每个数据点分配到距离它最近的聚类中心所在的簇。
以下是分配过程的数学描述:
z_i = argmin_j || x_i - μ_j ||²
其中:
x_i代表第i个观测数据点。μ_j代表第j个聚类中心。z_i是数据点x_i被分配到的簇标签(即簇的索引j)。argmin是一个运算符,它返回的是使距离|| x_i - μ_j ||²最小的那个索引j,而不是距离的最小值本身。
这个步骤将整个空间划分成了多个区域,每个区域内的点都会被分配到同一个簇。这种划分在几何上被称为 Voronoi 剖分。需要强调的是,这个剖分仅用于可视化理解,算法本身并不需要显式计算它。
3. 重新计算聚类中心
在将所有数据点分配到簇之后,下一步是更新每个簇的中心位置。新的中心被设定为该簇内所有数据点的平均值,也可以理解为该簇的“质心”。
更新聚类中心的公式如下:
μ_j_new = (1 / N_j) * Σ_{i: z_i = j} x_i
其中:
N_j是属于第j个簇的数据点数量。Σ_{i: z_i = j} x_i表示对所有满足z_i = j(即属于簇j)的数据点x_i进行求和。
这个公式的含义是:将簇 j 中所有数据点的坐标相加,然后除以该簇中数据点的总数,得到新的中心点坐标。
4. 迭代直至收敛
最后一步,也是算法的主体循环,是重复执行步骤2和步骤3。我们不断交替进行“分配数据点”和“更新中心”这两个操作,直到算法达到收敛状态。
收敛通常意味着聚类中心的位置不再发生显著变化,或者数据点的簇分配关系保持稳定。我们将在后续内容中更详细地讨论收敛的概念。
总结

本节课中我们一起学习了K-means聚类算法的核心流程。我们首先了解了算法通过最小化数据点到其簇中心的距离来工作的基本原理。接着,我们逐步拆解了算法的四个关键步骤:1)初始化聚类中心;2)根据最小距离将数据点分配到簇;3)根据簇内点的平均值重新计算聚类中心;4)迭代执行步骤2和3直至收敛。理解这些步骤及其对应的数学表达是掌握K-means算法的基础。
机器学习(分类,聚类和检索):第3-4课:K-means作为坐标下降

在本节课中,我们将探讨K-means算法的一个更深层次视角:将其理解为一种坐标下降算法。我们将分析其迭代步骤如何对应目标函数的优化,并讨论算法的收敛性及其对初始化的敏感性。
K-means作为坐标下降算法
K-means算法可能看起来像一种启发式算法,但实际上可以将其视为坐标下降算法的一个例子。
具体来说,K-means在两个步骤之间迭代:一是将观测点分配到最近的聚类中心,二是更新聚类中心。
上一节我们介绍了K-means的基本步骤,本节中我们来看看这些步骤如何对应目标函数的优化。
步骤一:分配观测点
在分配观测点到最近聚类中心的步骤中,我们可以清楚地从这个公式看出,它等价于最小化一个给定的目标函数。
以下是分配步骤的公式化描述:
公式:
[
z_i = \arg\min_{k} | x_i - \mu_k |^2
]
其中,( z_i ) 表示观测点 ( x_i ) 被分配到的聚类索引,( \mu_k ) 是第 ( k ) 个聚类的中心。
步骤二:更新聚类中心
对于第二个步骤,即更新聚类中心,其与目标函数最小化的关系可能不那么明显。但我们可以将这个步骤重写为以下形式,即最小化平方距离之和。
因为计算一组观测点的均值,等价于计算其质心。而最小化平方距离之和,正是计算质心所做的事情。
以下是更新步骤的公式化描述:
公式:
[
\mu_k = \arg\min_{\mu} \sum_{i: z_i = k} | x_i - \mu |^2
]
该公式的解就是属于聚类 ( k ) 的所有观测点 ( x_i ) 的均值。
坐标下降视角
现在我们可以看到,算法在两个不同的步骤之间迭代,其中每一步都代表了某个目标函数的最小化。
因此,从这个角度我们可以看出,K-means是坐标下降算法的一个例子。如果你对坐标下降算法不熟悉,可能是因为你没有学习回归课程。不过没关系,你不需要必须学习那个课程,但如果你想深入了解这类算法,可以参考该课程及其视频以获得更详细的解释。
这里的核心思想是,我们在给定聚类中心 ( \mu ) 的情况下,对聚类指示变量 ( Z ) 进行最小化;然后在给定分配的聚类指示变量的情况下,对聚类中心 ( \mu ) 进行最小化,如此迭代。
K-means的收敛性
接下来,让我们回到K-means收敛性的讨论。
首先,这个算法会收敛吗?如果会,它收敛到什么结果?
需要注意的第一点是,K-means的目标函数景观是一个非常复杂的非凸曲面。因此,我们可以排除算法保证收敛到全局最优解的可能性。但问题是,它至少会收敛到一个局部最优解吗?
由于我们可以将K-means视为坐标下降算法,因此我们知道它确实会收敛到一个局部最优解。
然而,正如前面所说,K-means目标函数的景观非常复杂,存在大量局部极值点。这些局部解之间的质量差异可能非常巨大。
初始化敏感性与示例
让我们看一个例子来说明这一点。
以下是一个数据集,黑点代表数据点。图中彩色的“十”字表示我们初始化的聚类中心。
这是K-means算法的一种初始化方式。另一张图中彩色的圆圈表示算法收敛后各聚类的标签。判断收敛的一种简单方式是观测点的分配不再发生变化。
我们看到,算法将左下角的一小群观测点分成了两个聚类,然后用一个巨大的蓝色聚类捕获了数据中的所有其他点。
但是,如果我们用不同的聚类中心初始化算法,则会收敛到一个完全不同的解。
从视觉上看,这个解可能看起来更合理一些,它最终形成了三个更紧密的组。
让我们再看另一种初始化。在这里,分组看起来相似,但如果我们在这两种初始化之间来回切换,会发现聚类标签发生了交换:粉色聚类变成了蓝色,蓝色变成了粉色。
这说明了,在不同的初始化中,具体哪个观测点被分配到“聚类1”、“聚类2”或“聚类3”并不重要。真正重要的是哪些观测点被分到了同一组,无论这个组被标记为一组、二组还是三组。
另一个需要注意的地方是图中用橙色圆圈高亮显示的观测点。对于这些点,存在很大的不确定性:它们应该属于蓝色聚类还是粉色聚类?如果你回头看另一个解,并在它们之间来回切换,会发现这些观测点的分配发生了变化。在一个解中,它们出现在中间的聚类;在另一个解中,它们出现在右上角的聚类。
这种聚类中的不确定性概念非常重要,我们将在下一个模块中再次讨论。
但这里我们想强调的重点是,K-means对初始化非常敏感,你甚至可能得到比这些例子更不合理的解,这只是因为算法收敛到了一个局部极值点。
总结
本节课中我们一起学习了:
- K-means的坐标下降视角:我们分析了K-means的两个迭代步骤(分配和更新)如何分别对应目标函数在聚类标签 ( Z ) 和聚类中心 ( \mu ) 上的最小化,从而将其理解为一种坐标下降算法。
- 算法的收敛性:K-means保证收敛到一个局部最优解,但由于目标函数非凸且存在大量局部极值,无法保证收敛到全局最优。
- 初始化的敏感性:通过示例我们看到,不同的初始聚类中心会导致算法收敛到截然不同的局部解,这些解的质量和分组方式可能差异很大,并且聚类结果存在不确定性区域。

理解K-means的这些特性,对于在实践中有效应用和解释该算法至关重要。
机器学习:第3-4课:通过K-means++进行智能初始化

在本节课中,我们将要学习一种名为K-means++的算法初始化方法。它旨在解决标准K-means算法对初始中心点选择敏感的问题,通过一种更智能的方式选择初始聚类中心,从而提高最终聚类结果的质量和算法的收敛速度。
上一节我们讨论了K-means算法对初始化的敏感性,本节中我们来看看一种能提供更智能、更可靠的初始化方法。
K-means++ 初始化算法
K-means++的核心思想是,在选择初始聚类中心时,有意识地让它们彼此之间距离更远。这有助于算法找到一个更好的起始点,从而收敛到更优的局部最优解。
以下是K-means++初始化算法的具体步骤:
- 随机选择第一个中心点:从所有数据点中随机选择一个作为第一个聚类中心。
- 计算距离并加权选择:对于数据集中的每一个数据点,计算它与当前已选出的所有聚类中心的最近距离。然后,根据这些距离的平方作为权重,随机选择下一个聚类中心。这意味着距离现有中心越远的点,被选中的概率越大。
- 重复选择:重复步骤2,直到选出K个初始聚类中心。
算法步骤详解
让我们通过一个简单的例子来可视化这个过程。假设我们有以下数据点需要聚类:

第一步:随机选择一个数据点作为第一个聚类中心(例如,图中红色的点)。
第二步:计算所有点到这个红色中心的距离。然后,根据距离的平方作为概率权重,随机选择下一个中心点。由于距离平方的权重,那些远离红色中心的点(例如,图中右上角的点)被选中的概率会非常高。假设我们选中了绿色的点。
第三步:现在,我们有两个中心点(红和绿)。对于每个数据点,计算它到最近的中心点的距离(即到红点或绿点的最小距离)。再次根据这些最小距离的平方作为权重,选择下一个中心点。此时,那些距离现有两个中心都较远的点(例如,图中左下角的点)被选中的概率最大。假设我们选中了蓝色的点。
至此,我们通过K-means++得到了三个初始聚类中心(红、绿、蓝),它们彼此分散,为后续的K-means算法提供了一个良好的起点。

算法优势与代价
运行K-means++初始化本身比完全随机选择初始中心需要更多的计算量,因为它需要多次计算所有数据点到当前中心的距离。
然而,这种代价通常是值得的,因为它带来了两大好处:
- 提升解的质量:K-means++倾向于找到质量更高的局部最优解。
- 加速收敛:由于起始点更好,后续的K-means迭代算法往往能更快地收敛到最终解,从而减少了总体运行时间。
因此,在实践中,使用K-means++进行初始化是一种非常推荐的做法。

总结


本节课中我们一起学习了K-means++智能初始化算法。我们了解到,通过有策略地选择彼此远离的点作为初始聚类中心,K-means++能够有效改善标准K-means算法的性能,帮助其找到更好的聚类结果并加快收敛速度。虽然初始化阶段稍显复杂,但其带来的收益在大多数应用场景中都非常显著。
机器学习(分类,聚类和检索):第3-4课:评估聚类质量与选择聚类数量 📊

在本节课中,我们将学习如何评估聚类结果的质量,以及如何为K均值算法选择合适的聚类数量K。我们将从回顾K均值的目标函数开始,理解其作为质量度量指标的含义,并探讨如何利用该指标来指导K值的选择。
回顾K均值目标函数
上一节我们介绍了K均值聚类算法及其智能初始化方法。本节中,我们来看看如何评估聚类结果的好坏。
K均值算法的目标是最小化所有数据点到其所属聚类中心的平方距离之和。这个目标函数可以用以下公式表示:
目标函数: min Σ Σ ||x_i - μ_j||²
其中,x_i 代表每个数据点,μ_j 代表第j个聚类的中心。我们通过最小化这个总和,来寻找最优的数据点分配方案和聚类中心位置。
这个总和被称为聚类异质性。异质性越小,意味着聚类内部的点越紧密、越相似,聚类效果就越好。因此,我们可以将聚类异质性作为衡量聚类质量的一个指标:数值越低,质量越高。
聚类数量K对异质性的影响
理解了质量度量指标后,一个自然的问题是:聚类数量K的选择如何影响这个指标?
随着K值的增加,算法可以将数据划分成更精细的组别,从而更好地拟合数据。这通常会导致聚类异质性降低。然而,这并非总是好事。如果K设置得过大,例如等于数据点的数量,那么每个点自成一类,异质性将降至零,但这显然失去了聚类的意义——我们只是“记住”了数据,而非发现了有意义的群组结构。这种现象类似于监督学习中的过拟合。
以下是K值增加时异质性变化的典型趋势:
- K值很小:异质性很高,因为每个聚类内部包含了大量不相似的点。
- K值适中:异质性显著下降,我们找到了数据中自然存在的、内部紧密的群组。
- K值很大:异质性继续缓慢下降,但下降幅度变小,同时产生了许多细小而无意义的聚类。
如何选择聚类数量K
既然K值过小或过大都不理想,我们需要一种方法来权衡。一个常用的启发式方法是寻找“肘部”。
我们可以绘制一张图:X轴是K值,Y轴是对应K值下能获得的最小聚类异质性。随着K增大,曲线会快速下降然后趋于平缓。曲线拐弯最明显、形似“肘部”的那个点,通常被认为是一个较好的K值选择。在这一点上,增加更多的聚类(增大K)所带来的异质性改善(曲线下降)已经很小,因此选择这个K值能以更简洁(更少的聚类数)的方式描述数据的主要结构。
需要强调的是,“肘部法则”只是一个启发式方法,并非绝对真理。在实际应用中,选择K值还需要结合对数据本身的理解、业务背景以及后续分析目标。例如,如果你知道数据中大约有5个类别,那么从K=5开始探索就是合理的。
实践中的注意事项
在具体操作时,有几点需要注意:
- 计算最小异质性:我们无法为每个K值穷举所有可能的聚类结果来找到绝对最小的异质性。通常的做法是,对每个K值,运行多次K均值算法(结合随机初始化和K-means++等方法),然后取其中异质性最低的结果作为该K值的代表。
- 计算成本:上述方法计算量较大,尤其是在数据量大、K值尝试范围广的时候。实践中需要根据资源情况权衡。
- K值的影响至关重要:最终选择的K值直接决定了你从数据中提取出的结构。K=2会将所有数据强行分为两类,可能掩盖真实的细分群体;而K值过大则会得到过于琐碎、难以解释的群组。因此,仔细评估和选择K值是聚类分析中关键的一步。
总结
本节课中我们一起学习了如何评估聚类质量和选择聚类数量。我们了解到:
- 聚类异质性(所有点到其聚类中心的平方距离之和)是衡量K均值聚类质量的核心指标,值越小越好。
- 聚类数量K的增加通常会导致异质性降低,但可能引发过拟合,产生无意义的细小聚类。
- 选择K值需要在低异质性和模型简洁性之间取得平衡。“肘部法则” 是一种常用的启发式选择方法,即观察异质性-K曲线拐点处的K值。
- 在实践中,需要通过多次运行算法来近似每个K下的最小异质性,并且最终K值的选择应结合数据洞察与具体应用场景。

通过本模块的作业,你将获得大量关于评估聚类质量和选择K值的实践机会。
机器学习:第3-4课:MapReduce的动机


在本节课中,我们将学习一个用于算法并行和分布式实现的强大且广泛使用的框架——MapReduce。我们将从一个简单的词频统计示例开始,这是MapReduce的“Hello World”示例,然后探讨如何将MapReduce框架应用于并行化K-means算法。
概述:从单机到分布式计算的挑战
假设我们有一台机器和100亿份文档,需要统计整个语料库中每个单词的出现次数。我们可能会初始化一个哈希表,然后遍历每份文档中的每个单词,递增该单词的计数。然而,处理如此庞大的数据量对单台机器来说是一项非常繁重的任务。
那么,如果我们有1000台机器可用,能否以某种方式将这个操作并行化或分布到这些不同的机器上呢?
数据并行任务:按文档分布计算
我们可以均匀地分发数据,例如,将1000万份文档发送到每台机器上。由于词频统计是一个跨文档独立的操作,即一份文档的词频不影响另一份文档,因此我们可以独立地在每台机器上分别统计其分配文档中的单词出现次数。这种可以跨不同数据点完全独立执行的任务,被称为数据并行任务。
以下是每台机器上执行的伪代码:
# 每台机器上的局部词频统计
local_counts = {}
for document in assigned_documents:
for word in document:
local_counts[word] = local_counts.get(word, 0) + 1
完成局部统计后,我们会得到1000个局部哈希表(词频字典)。接下来,我们需要将它们合并起来,以获得整个语料库的总词频。
合并挑战与按单词并行
合并这些哈希表似乎又回到了一个顺序问题:我们需要遍历词汇表中的每个单词,将1000台机器上该单词的局部计数相加。如果词汇表很大,这仍然是一个繁重的任务。
我们能否做得更好?答案是肯定的。我们可以利用多台机器来并行执行这个合并阶段。关键在于,合并操作(即对每个单词的局部计数求和)本身也可以跨单词并行执行,这可以称为按单词的数据并行。
为了实现这一点,我们需要一个关键步骤:将所有机器上关于同一个单词的计数发送到同一台机器上进行汇总。
哈希函数:确保数据正确路由
如何确保所有“学习”这个词的计数都去到同一台机器呢?这里我们使用一个哈希函数。
哈希函数 H 定义在整个词汇表上。它将一个单词(或单词的索引)作为输入,输出一个在1到机器总数范围内的整数。这个整数决定了该单词的所有计数将被发送到哪台机器。
用公式表示发送规则:
将单词 w 的计数发送到机器 H(w)。
例如,H("learning") = 5,那么所有机器上“learning”的局部计数都会被发送到第5号机器。这台机器负责将所有收到的“learning”计数相加,得到该单词在整个语料库中的总计数。
MapReduce抽象
我们刚才描述的过程,正是MapReduce框架的一个典型例子。它包含两个主要阶段:
- Map阶段:一个可以跨数据项(如文档)并行执行的操作。在我们的例子中,就是每台机器独立统计其文档中的词频。
- Reduce阶段:一个可以跨键(如单词)并行执行的操作。在我们的例子中,就是每台负责特定单词的机器,汇总来自所有Map机器的该单词的计数。
MapReduce框架的强大之处在于,它通过定义清晰的Map和Reduce接口,以及一个基于键(如单词)将中间数据分发到Reduce节点的机制(通常使用哈希函数),将程序员从复杂的分布式系统细节(如网络通信、故障处理)中解放出来,使其能够专注于业务逻辑。
总结

本节课我们一起学习了MapReduce的动机和核心思想。我们从一个单机处理海量数据时遇到的性能瓶颈出发,探讨了如何通过数据并行将任务分布到多台机器上。我们遇到了合并局部结果的挑战,并通过引入哈希函数将合并操作也并行化,从而引出了MapReduce的双阶段抽象:Map阶段处理原始数据并生成中间键值对,Reduce阶段则根据键来聚合这些中间结果。这个框架为大规模数据处理,包括我们接下来要看到的并行化K-means算法,提供了强大的基础。
机器学习:第3-4课:一般MapReduce抽象

在本节中,我们将学习MapReduce这一核心计算抽象。MapReduce是一种用于处理大规模数据集的编程模型,它通过两个主要步骤——映射(Map)和归约(Reduce)——来简化并行计算。我们将通过一个简单的例子来理解其工作原理。
上一节我们介绍了MapReduce的基本概念,本节中我们来看看它的两个具体步骤。
映射(Map)步骤
在映射步骤中,我们假设要执行的操作在数据元素(例如文档)上是可并行化的。映射调用的结果是生成一系列键值对。
例如,在我们的词频统计例子中,我们将输入一个文档,然后对于文档中的每一个单词,我们都会输出一个键值对:(单词, 1)。这意味着我们遍历文档,每看到一个单词,就输出该单词和数字1。
以下是映射步骤的伪代码描述:
def map_function(document):
for word in document:
emit(word, 1)
在这个例子中,键(key)是词汇表中的不同单词(如“UW”、“machine”、“learning”),值(value)是该单词的计数。在这个具体实现中,每次遇到一个单词实例,我们只输出计数1。但在MapReduce抽象中,值可以是任何数据类型。
过渡到归约步骤
映射步骤会为所有文档生成大量的键值对。接下来,我们需要将这些中间结果进行汇总。
归约(Reduce)步骤
归约步骤将对与每个键相关联的所有值进行聚合操作。这个操作必须是可交换的和可结合的。
- 可交换意味着操作顺序不影响结果,例如
a + b = b + a,加法是可交换的。 - 可结合意味着分组方式不影响结果,例如
(a + b) + c = a + (b + c),加法也是可结合的。
在归约步骤中,操作必须在不同的键之间是可并行化的。让我强调一下这两个步骤并行化的对象有何不同:
- 在映射步骤中,并行化是针对数据元素(如语料库中的文档)。
- 在归约步骤中,一旦我们生成了这些键值对,我们就取所有的键,并且针对每个键的操作必须能够独立进行。例如,一个单词的总计数不依赖于任何其他单词的总计数。
让我们继续词频统计的例子,看看归约步骤如何工作。
以下是归约步骤的伪代码描述:
def reduce_function(key, list_of_values):
total_count = 0
for value in list_of_values:
total_count += value
emit(key, total_count)
归约器接收一个特定的键以及与该键关联的一个值列表。它的工作就是遍历这个列表,将所有值(在这个例子中就是数字1)累加起来,然后输出最终的键值对 (单词, 总次数)。
具体来说,如果我们对键“UW”调用归约函数,并且与之关联的值列表是 [1, 1, 1, ...](假设出现了很多次),那么归约器将输出 ("UW", 总出现次数)。
MapReduce的背景与应用
MapReduce在函数式编程中有着悠久的历史。近年来,它被谷歌公司推广普及,随后通过雅虎开发的一个名为Hadoop的开源实现获得了广泛的采用,成为处理海量数据的基石技术之一。
总结


本节课中我们一起学习了MapReduce的一般抽象。我们了解到:
- Map(映射)步骤:将输入数据元素转换为独立的键值对,操作在数据元素层面并行。
- Reduce(归约)步骤:对拥有相同键的所有值进行聚合(如求和),该操作需满足交换律和结合律,并在不同的键之间并行执行。
通过词频统计的例子,我们清晰地看到了map函数如何发射(单词, 1)对,以及reduce函数如何将相同单词的计数相加得到最终结果。这种模型极大地简化了大规模分布式计算程序的设计。
机器学习(分类,聚类和检索):第3-4课:MapReduce执行概述与组合器

在本节课中,我们将学习MapReduce框架的执行流程,并了解如何通过“组合器”来优化其性能,以减少网络通信开销。
MapReduce执行概述
上一节我们介绍了MapReduce的基本概念,本节中我们来看看其具体的执行流程。我们假设有一个大型数据集,它将被分割并分配到多台机器上。

以下是MapReduce标准执行流程的步骤:
-
Map阶段:在每台机器上,我们执行一个数据并行的操作。该操作处理分配到此机器的数据分片,并发射出一些键值对。例如,我们可能发射键值对
(UW, 1)。这里,K1可能代表“UW”,V1代表数字“1”。 -
Shuffle阶段:在此阶段,我们收集所有发射出的键值对,并根据键将它们分配到不同的机器上,为Reduce阶段做准备。分配规则是:每个键值对将被发送到机器
H(key),其中H是我们的哈希函数。 -
Reduce阶段:在此阶段,进行聚合操作。对于每一个唯一的键,我们查看与该键关联的所有值,并进行聚合。例如,在词频统计中,这可能会产生
(UW, 30)这样的结果。 -
保存结果:最后,将结果保存到磁盘。
需要注意的是,在Map阶段,不同的机器上可能出现相同的键(例如,K1)。而在Reduce阶段,每台机器上的键是唯一的(我们用 K1', K2' 等表示)。此外,Reduce操作必须是跨键数据并行的。
引入组合器优化
然而,上述朴素的MapReduce实现在Shuffle阶段的通信上可能非常低效。例如,在词频统计中,我们可能会产生大量如 (word, 1) 的键值对,它们都需要被发送到另一台机器,这会产生巨大的通信开销。
为了解决这个问题,我们可以使用组合器。组合器是一个在Map阶段之后、Shuffle阶段之前执行的本地Reduce操作。它的目的是在数据发送到网络之前,先在本地机器上进行部分聚合。
让我们通过一个具体例子来理解:
假设在机器1上,我们统计单词“UW”,最终得到了4002个 (UW, 1) 实例。根据哈希函数 H(UW) = 7,所有这些实例都将被Shuffle到机器7。
不使用组合器:我们需要将4002个 (UW, 1) 键值对全部发送到机器7。
使用组合器:我们可以在机器1本地执行一个Reduce操作,将这些 (UW, 1) 聚合成一个 (UW, 4002)。然后,我们只需要将这一个键值对发送到机器7。


组合器能够工作的关键原因在于,Reduce操作必须是可交换和可结合的。这意味着,先进行本地聚合,再将聚合结果与其他机器的结果进行最终聚合,得到的结果与将所有原始数据一起聚合的结果是相同的。用公式表示,对于操作 ⊕,需要满足:
- 可结合性:
(a ⊕ b) ⊕ c = a ⊕ (b ⊕ c) - 可交换性:
a ⊕ b = b ⊕ a
例如,求和操作就满足这两个条件。
总结


本节课中我们一起学习了MapReduce的标准执行流程,包括Map、Shuffle、Reduce和保存结果四个阶段。更重要的是,我们了解了组合器这一优化技术。通过在Map阶段后、Shuffle阶段前执行本地Reduce操作,组合器可以显著减少需要在网络间传输的数据量,从而提升整体作业性能。这要求底层的Reduce操作必须是可交换和可结合的。
机器学习(分类,聚类和检索):第3-4课:K-means的MapReduce实现 🧩

在本节课中,我们将学习如何利用MapReduce框架来实现K-means聚类算法。我们将看到,K-means的两个核心步骤——分配数据点到簇(分类)和更新簇中心(重新中心化)——可以非常自然地映射到MapReduce的“映射”和“归约”阶段。
上一节我们介绍了K-means算法的基本思想,本节中我们来看看如何将其应用于分布式计算环境。
算法步骤回顾
K-means算法包含两个主要步骤:
- 分类步骤:将每个数据点分配到距离其最近的簇中心。
- 重新中心化步骤:根据分配给每个簇的所有数据点,计算新的簇中心(均值)。
MapReduce框架下的映射
在MapReduce的上下文中分析这两个步骤,我们发现:
- 分类步骤是一个数据并行操作。给定簇中心后,每个数据点的分配可以独立进行,不依赖于其他数据点。这非常适合“映射”阶段。
- 重新中心化步骤是一个聚合操作,且不同簇(不同键)之间的聚合是独立的。这非常适合“归约”阶段。
接下来,我们将详细探讨每个步骤在MapReduce中的具体实现。
分类步骤:映射器实现
在分类步骤中,映射器的任务是:接收当前的簇中心集合和一个数据点,计算该数据点到所有簇中心的距离,并将其分配给最近的簇。
映射器的输入是:
- 簇中心集合
- 单个数据点
映射器的处理逻辑如下:
- 计算数据点到每个簇中心的距离。
- 找出距离最近的簇中心索引。
- 发射一个键值对,其中键是簇标签(索引),值是数据点本身。
例如,如果一个数据点(可能是一个词频向量 [17, 0, 1, 7, 0, 0, 5])被分配到簇2,那么映射器将发射:
(2, [17, 0, 1, 7, 0, 0, 5])
以下是映射器逻辑的伪代码描述:
def mapper(cluster_centers, data_point):
min_distance = INF
assigned_cluster = -1
for j, center in enumerate(cluster_centers):
dist = distance(data_point, center)
if dist < min_distance:
min_distance = dist
assigned_cluster = j
emit(assigned_cluster, data_point)
重新中心化步骤:归约器实现
在重新中心化步骤中,归约器的任务是:接收同一个簇标签(键)下的所有数据点(值列表),计算这些数据点的均值,作为该簇的新中心。
归约器的输入是:
- 键:簇标签
j - 值列表:所有被分配到簇
j的数据点[x1, x2, ..., xn]
归约器的处理逻辑如下:
- 初始化簇内数据点的总和(
total_mass)为0向量。 - 初始化簇内数据点计数(
total_count)为0。 - 遍历值列表中的每个数据点
x:- 将
x加到total_mass上。 - 将
total_count加1。
- 将
- 计算新簇中心:新均值 = total_mass / total_count。
- 发射键值对:
(j, 新均值)。
以下是归约器逻辑的伪代码描述:
def reducer(cluster_label, list_of_data_points):
total_mass = zero_vector
total_count = 0
for x in list_of_data_points:
total_mass += x
total_count += 1
new_center = total_mass / total_count
emit(cluster_label, new_center)
实现注意事项
虽然K-means可以很好地适配MapReduce模型,但有两点需要注意:
- 迭代需求:K-means是一个迭代算法,需要反复执行“分类-重新中心化”步骤直至收敛。这需要一个支持迭代的非标准MapReduce实现(如Spark的迭代计算模型)。
- 效率优化:在基本实现中,每个映射器调用只处理一个数据点,但需要接收整个簇中心集合。当数据点极多时,这会带来大量的数据传输开销。更高效的实现是让每个映射器处理一批数据点,从而分摊簇中心广播的开销,提升整体效率。
总结
本节课中我们一起学习了如何将K-means算法映射到MapReduce框架。我们了解到:
- 映射阶段 对应K-means的分类步骤,这是一个在数据点上数据并行的操作,负责将数据点分配到最近的簇。
- 归约阶段 对应K-means的重新中心化步骤,这是一个在簇标签(作为键)上数据并行的操作,负责聚合簇内所有数据并计算新的均值作为簇中心。

通过这种映射,我们可以利用分布式计算框架的强大能力来处理大规模数据集的聚类任务。
机器学习(分类,聚类和检索):第3-4课:聚类的其他应用 🎯


在本节课中,我们将探讨聚类算法在文档分析之外的广泛应用。我们将看到,从图像搜索到医疗研究,再到商业推荐和城市数据分析,聚类都是一个极其强大的工具。
图像聚类 📸
上一节我们讨论了文档聚类,本节中我们来看看聚类在图像分析中的应用。
聚类可以用于组织图像。例如,你可能希望将所有与海洋、粉色花朵、狗、日落或云彩相关的图片自动分组。这对于像谷歌图片搜索这样的应用非常有用。当用户在谷歌图片中输入一个词时,系统需要从图片数据库中检索并显示一组相关图片。然而,并非所有图片都经过了人工标注。如果我们能自动发现相关的图片组,这将极大地帮助图片搜索。
以下是图像聚类的两个具体应用场景:
- 辅助图像搜索:当用户搜索一个词(如“cardinal”)时,这个词可能有多种含义(如一种鸟、一支棒球队、一种宗教头衔)。如果我们对所有被标注为“cardinal”的图片进行聚类,可能会发现它们自然地分成了几组,分别对应不同的含义。这样,在展示搜索结果时,我们就可以提供一个覆盖了所有可能含义的、多样化的图片集,而不是只显示单一含义(如鸟类)的变体,从而更好地满足用户的实际搜索意图。
- 探索标签多样性:通过聚类被同一标签标注的图片,我们可以发现该标签下隐藏的多样性,并据此构建更丰富的搜索结果。
医疗数据分析 🧠
聚类不仅能用于信息检索,还能应用于像医疗研究这样截然不同的领域。
我们可以考虑根据患者表现出的医疗状况对他们进行分组。如果能够形成这样的分组,我们就可以更好地研究亚群和疾病。例如,假设我们有一组患者的颅内脑电图记录。每位患者都记录了一系列不同的癫痫发作事件。
以下是基于此数据的分析步骤:
- 事件聚类:我们可以根据事件之间的相似性,对这些癫痫发作事件进行聚类。
- 类型研究:基于这些聚类结果,我们可以了解更多关于不同类型癫痫的信息,例如,我们认为存在多少种不同的癫痫类型,以及每种类型的特征是什么。
- 患者聚类:我们还可以根据患者表现出的癫痫类型对患者进行聚类,从而更好地理解癫痫患者群体中的不同亚群。
商业与产品分析 🛒
聚类在商业领域,特别是在电子商务中,有着广泛的应用。
一个应用是分析亚马逊上的产品,根据相似的购买历史对产品进行分组。这里所说的产品“购买历史”,是指观察所有购买过该产品的用户,看看他们在同一次购物或近期历史中还购买了哪些其他商品。我们将这些信息汇总,作为该产品的描述特征。
以下是基于产品聚类的应用:
- 产品归类:例如,当人们购买婴儿床时,我们可能发现他们还经常购买汽车座椅和其他婴儿用品。因此,我们可以将这个婴儿床与亚马逊上其他婴儿用品归为一类。即使卖家将其归类为“家具”,我们也可以通过聚类来修正或添加“婴儿产品”这个标签。
- 产品推荐:这种聚类结构也可用于产品推荐。当用户的购物车中有某些商品时,系统可以推荐他们可能感兴趣的其他相关产品。
此外,我们还可以发现具有相似购买或浏览行为的用户群。通过对用户和产品进行聚类分析,我们可以做很多有趣的事情。
区域数据分析与预测 🗺️
聚类在一个不那么明显的任务中也很有用:小区域数据估计与预测。
想象一下,我们想要在非常小的空间位置(如人口普查区)估算房屋价值。问题是,在任何给定的时间点,每个区域内的房屋销售数据都非常少。我们如何在没有太多数据的情况下评估该区域的价值呢?
以下是解决思路:
- 区域聚类:我们可以尝试发现历史上行为相似的区域集群。
- 信息共享:发现这些区域集群后,我们可以考虑在这些区域之间共享信息,汇总它们的观测数据,从而在局部形成更好的价值估计。
一个结构相似但应用不同的任务是犯罪预测。目标是在下一个时间点预测每个普查区将发生多少起犯罪。
以下是应用方法:
- 聚类预测:同样,我们可以对区域进行聚类以共享信息。事实证明,基于行为相似的区域集群进行预测,比独立处理每个区域能带来更好的犯罪率预测效果。
总结 📝


本节课中我们一起学习了聚类算法在多个领域的广泛应用。我们看到,无论是组织图像、分析医疗数据、理解商业行为,还是进行区域数据估计与预测,聚类的核心思想——根据数据对象之间的“距离”或相似性将其分组——都能通过适当的调整得到应用。关键在于为特定应用定义好数据对象的含义以及对象之间的距离度量方式。这些方法展现了聚类作为一项基础机器学习技术的强大通用性和灵活性。
机器学习(分类,聚类和检索):第3-4课:课程回顾与总结

在本节课中,我们将对模块三和模块四所涵盖的核心内容进行简要回顾与总结。我们主要学习了两种非常重要且广泛应用的算法:K均值聚类和MapReduce框架。
上一节我们介绍了聚类分析的目标及其广泛应用。本节中,我们来回顾一下本模块的核心知识点。
以下是完成本模块学习后,你应该掌握的能力要点:
- 描述聚类的目标:理解聚类分析旨在将数据点分组,使得同一组(簇)内的数据点彼此相似,而不同组之间的数据点相异。
- 执行K均值聚类:能够手动或通过代码实现K均值算法。该算法的核心步骤是迭代更新簇中心(质心)并将每个点分配到最近的质心所属的簇,公式表示为:将点x分配到簇i,其中i = argmin_j ||x - μ_j||^2,其中μ_j是簇j的质心。
- 在MapReduce中实现K均值:理解如何利用MapReduce框架并行化K均值算法。这通常涉及在Map阶段分配数据点到最近的质心,在Reduce阶段汇总并计算新的质心。
- 描述MapReduce框架:解释MapReduce作为一个通用并行计算框架的基本原理,它通过
map和reduce两个函数阶段处理大规模数据集。 - 识别MapReduce的应用场景:能够判断哪些类型的算法或计算任务适合使用MapReduce框架进行并行化处理。


本节课中我们一起学习了K均值聚类这一最常用的聚类工具,以及MapReduce这一用于构建分布式或并行算法的强大框架。这些知识具有很强的通用性,能够广泛应用于众多不同的领域和场景。
机器学习(分类,聚类和检索):第3-4课:概率聚类模型的动机 🎯

在本节课中,我们将要学习概率聚类模型的基本动机。我们将探讨K均值算法的局限性,并理解为何需要转向基于概率模型的聚类方法,例如混合模型。这些方法能够提供更丰富的信息,例如数据点属于各个簇的“软”分配概率,并能更好地处理不同形状和重叠的簇。
在上一模块中,我们讨论了K均值作为一种算法化的聚类方法。现在,在课程的剩余部分,我们将转向基于概率模型的聚类方法,并与K均值进行比较和对比。
那么,我们为何首先对概率方法感兴趣呢?为了说明这一点,我们可以回到我们的任务:学习用户对一组主题的偏好。为此,我们讨论了将文档聚类到一组主题中,然后结合用户对已读文章的反馈和这种聚类结构,来学习用户对这些主题的偏好集合。
但我们很少遇到数据完全可分的情况。例如,在这个场景中,想象有一篇文章,我们不太清楚它是否与关于世界新闻的其他文章更相似,还是与关于科学的其他文章更相似。也许它介于两者之间。但为了讨论方便,假设它更接近这个科学主题,即这个橙色簇。这是否意味着当用户表示他们不喜欢这篇文章时,我们只应在更新用户对簇4的偏好信息时包含该信息?或者,也许这也应该以某种方式影响我们对用户喜欢簇2的看法?因此,我们看到,K均值所做的硬分配并不能完全反映真实情况。相反,我们希望做的是能够以某种方式捕捉这篇文章是分配给簇2还是簇4的不确定性,然后利用这种不确定性从数据集中提取额外信息。
例如,在学习用户对一组主题的偏好时,我们可以考虑做更复杂的事情。
K均值还有其他局限性。请记住,当K均值将数据点分配给一个簇时,它只考虑簇中心。
这意味着它没有考虑簇的形状。你可以认为这等同于假设所有簇都具有这种球对称形状,并且它们都是大小相等的球体。这意味着所有维度都被平等加权,并且在我们计算那个分数时,在所有不同的簇中使用相同的权重。因此,区分这些簇的唯一因素是这些簇的位置,即它们的簇中心。
然而,你可以修改K均值,使用加权欧几里得距离或缩放欧几里得距离,而不是我们在这里展示的这种标准形式的欧几里得距离。但关于这一点有两件事:一是它仍然假设所有簇具有相同的轴对齐椭圆形状,这意味着当我们权衡不同维度的重要性时,在每个不同的簇中权重完全相同;另一件事是权重集必须预先指定。
因此,K均值在以下情况下会遇到困难:
以下是K均值可能遇到困难的情况:
- 如果簇具有不同的分布范围,特别是当它们没有很好地分离时。例如,考虑以下情况:有两个小的橙色和蓝色簇,以及一个非常大的绿色簇。这里说的“大”,不是指簇中数据点的数量多,而是指该簇内点的分布范围。在这种情况下,K均值算法会这样做:如果我们固定簇中心位于这三个位置,并查看我们的Voronoi镶嵌图(这些线所绘制的),它会说这个区域内的所有点都被分配给这个橙色簇,这个区域内的所有点都被分配给这个蓝色簇,只有这里的点被分配给这个绿色簇。结果,它把出现在这个绿色簇中的观测点错误地分配给了橙色或蓝色簇。
- 当簇重叠时。同样,如果我们考虑将簇中心固定在这里,K均值将简单地按如下方式分割这些簇。现在发生的情况不一定是错误的标签,我的意思是,将这些蓝色点分配给橙色簇是不正确的。在这些情况下,如果不事先知道它来自蓝色还是橙色簇,也没有任何其他区分信息,在这些区域(我将它们涂成蓝色),你本应对观测点属于蓝色簇还是橙色(或蓝色与绿色,抱歉,是绿色和橙色)存在不确定性,但K均值却做出了硬分配。K均值做出硬分配,而显然存在不确定性。
- 我们提到的K均值没有考虑的另一点是,如果簇具有不同的形状或这些形状的方向,特别是如果这些形状事先未知,不同维度的权重应该是多少。例如,如果我们看这里的这个观测点,在K均值下,它会说,到蓝色簇的距离更小,所以这个观测点将被分配给蓝色簇,而没有考虑到绿色簇沿这个轴有很大的分布范围。
因此,我们需要的是一种能够考虑簇形状的方法,并说,嗯,不仅仅是看簇中心,我还想考虑到绿色簇沿这个维度有这种分布范围,也许它更可能属于绿色簇,而不是这个紧凑的球形蓝色簇。
这些局限性促使我们采用一种使用混合模型的概率方法。混合模型可以提供数据点到簇的所谓软分配,这些软分配将考虑这些簇分配中的不确定性。
例如,也许我们有一篇文档,软分配会说,该文档有54%的概率是关于世界新闻,45%的概率是关于科学,1%的概率是关于体育,0%的概率是关于娱乐。
混合模型还可以考虑簇的形状,而不仅仅是簇中心。最后,另一个非常重要的事情是,我们将最终学习这些混合模型的参数,并且我们可以实际学习不同维度上的权重。例如,我们可以针对每个簇,学习词汇表中不同单词的相对重要性。

在本节课中,我们一起学习了转向概率聚类模型的动机。我们探讨了K均值在硬分配、忽略簇形状和大小、处理重叠簇等方面的局限性。这些局限性促使我们引入混合模型,它能够提供软分配以量化不确定性,并能学习每个簇的形状和特征权重,从而为聚类问题提供更灵活、更强大的解决方案。
机器学习(分类,聚类和检索):第3-4课:在图像数据集中汇总未知类别 🌄

在本节课中,我们将学习如何使用混合模型来发现图像数据集中未知的类别或分组。我们将以图像聚类作为核心应用场景,因为它直观且视觉吸引力强。我们的目标是让算法自动将相似的图像(如云朵、日落、森林)归为一组,而无需预先知道这些标签。

图像表示方法
为了进行数据分析与建模,我们首先需要将图像转化为数值表示。在本模块及后续作业中,我们将使用一种极其简单的表示方法:计算图像中所有像素的RGB(红、绿、蓝)通道强度平均值,从而为每张图像得到一个三维的RGB向量。
以下是几个示例:
- 一张云朵图像的RGB向量可能是
[0.05, 0.70, 0.9]。 - 一张日落图像的RGB向量可能是
[0.85, 0.05, 0.35]。 - 一张森林图像的RGB向量可能是
[0.02, 0.95, 0.4]。
请注意,所有RGB值都已归一化到0到1之间。
从数据观察到模型构建
上一节我们介绍了如何用RGB向量表示图像。本节中,我们来看看如何通过分析这些数据来构建聚类模型。为了便于理解模型的构建过程,我们先假设自己知道图像的类别标签。
单维度分析:蓝色通道
如果我们只查看所有“云朵”图像的蓝色通道强度,并绘制其直方图,可能会得到类似下图的结果。其平均值较高(例如0.8),且分布近似钟形曲线(即正态分布),大部分图像的蓝色强度集中在0.8附近。
接着,查看所有“日落”图像的蓝色通道。由于日落图像中蓝色较少,其蓝色强度的平均值会低得多(例如0.3),且分布范围可能更窄。
最后,查看“森林”图像的蓝色通道。由于森林图像中可能包含天空部分,其蓝色强度平均值可能略高于日落图像(例如0.42),分布也稍广一些。
然而,关键点在于:我们实际上并没有这些标签。我们拥有的只是一大堆混合在一起的图像及其蓝色强度值。如果绘制所有图像的蓝色强度直方图,可能会看到多个“峰”,例如三个。这正好对应了我们之前假设存在的三个图像类别:日落、森林和云朵。
此时,如果我们观察一张具体的图像(例如蓝色强度约为0.4的森林图像),仅凭蓝色直方图很难精确判断它属于哪个组。它显然不属于蓝色强度高的“云朵”组,但似乎还有另外两个组,我们无法确定它属于哪一个。
引入更高维度:红色通道
在这种情况下,我们可以引入另一个观测维度——红色通道强度。
- 对于森林图像,其红色强度通常很低,因为森林中红色不多。
- 对于日落图像,其红色强度通常非常高,可能集中在0.9左右。
因此,虽然在蓝色维度上难以区分森林和日落图像,但在红色维度上,它们可能变得非常容易区分。这个例子说明,有时我们需要在更高维的空间中观察数据,才能有效地区分不同的聚类。
到目前为止,我们的讨论都基于对数据值(强度值)绘制直方图并观察其中可能存在的结构。接下来,我们将转向一个正式的模型,来捕捉这种聚类结构,并实现我们之前描述的“软分配”。
混合模型简介
以下是混合模型的核心思想与组成部分:
- 模型假设:我们假设观测到的数据(如图像的RGB向量)是由多个不同的“成分”或“簇”生成的。每个簇都有自己的概率分布(通常是多元高斯分布),用于描述属于该簇的数据点的特征。
- 隐变量:对于每个数据点,我们引入一个隐变量
z,表示它来自哪个簇。在聚类任务中,这个z正是我们想要推断的。 - 生成过程:混合模型的生成过程可以描述为:
- 首先,根据混合权重
π(一个概率向量)随机选择一个簇k。公式为:z ~ Categorical(π)。 - 然后,从该簇对应的概率分布
p(x|θ_k)中生成观测数据x。例如,若使用高斯分布,则x ~ N(μ_k, Σ_k)。
- 首先,根据混合权重
- 模型参数:一个混合模型的主要参数包括:
- 混合权重:
π = [π_1, π_2, ..., π_K],其中π_k = P(z=k),且Σ π_k = 1。 - 每个簇的分布参数:例如对于高斯混合模型,每个簇有其均值向量
μ_k和协方差矩阵Σ_k。
- 混合权重:
- 软分配:与“硬分配”(每个点只属于一个簇)不同,混合模型为每个数据点
x_i计算属于各个簇的后验概率γ_{ik} = P(z_i=k | x_i)。这就是“软分配”,它量化了数据点与每个簇的关联程度。
通过期望最大化(EM)等算法,我们可以从无标签数据中自动学习出这些模型参数,从而完成聚类任务。
总结


本节课中,我们一起学习了如何利用混合模型对图像进行聚类。我们从简单的RGB向量表示开始,通过分析单维度(蓝色通道)和双维度(红-蓝通道)数据,理解了在更高维空间中数据更易分离的道理。最后,我们介绍了混合模型的基本概念,包括其生成过程、核心参数以及软分配的思想。这个模型为我们提供了一种强大的数学框架,用于在无监督条件下发现数据中潜在的分组结构。
机器学习:分类、聚类与检索:3-4:单变量高斯分布 🧮

在本节课中,我们将学习高斯分布(也称为正态分布)的基本概念。高斯分布是概率模型中的一个关键组成部分,尤其在处理连续数据时非常有用。我们将了解它的定义、参数以及如何通过调整这些参数来改变分布的形状。
在深入探讨混合模型之前,我们需要先了解一个核心组件,它将成为后续模型描述的关键部分,这就是高斯分布。
让我们回顾一下仅针对云朵图像的蓝色强度直方图。我们曾提到,这个直方图可能看起来像一条钟形曲线。当我们采用基于概率模型的方法时,我们会将每张图像中的蓝色强度视为一个观测到的随机变量,并为这个随机变量设定一个分布。这个分布将包含一组参数,我们的目标是从数据中学习这些参数。我们将使用高斯分布来建模这种类型的数据分布形状。
在这个应用中,我们假设高斯分布能够很好地拟合每一个不同的图像类别(如云朵、日落、森林)以及观测向量的每一个维度(无论是红色、绿色还是蓝色维度)。
一维高斯分布
当我们仅关注蓝色强度这一维度时,这个高斯分布完全由两个参数决定:均值(mean)和方差(variance)。有时人们也使用方差的平方根,即标准差(standard deviation)。
- 均值 决定了高斯分布的中心位置。
- 方差 决定了高斯分布的离散程度。
以下是不同参数组合的高斯分布示例:
- 相同方差,不同均值:下图展示了一个与之前示例方差相同但均值较小的分布。
- 相同均值,不同方差:下图展示了一个与之前示例均值相同但方差较小的分布。
- 方差增大:下图展示了方差逐渐增大的分布示例。
通过调整这两个参数,我们可以改变分布的位置和离散程度。
数学表示
我们使用以下符号来表示高斯分布:
N(x | μ, σ²)
其中:
N代表正态分布(Normal distribution)。x代表该分布所描述的随机变量(在我们的例子中是图像的蓝色强度)。μ是分布的均值。σ²是分布的方差。
竖线 | 右侧表示高斯分布的固定参数。
总结


本节课中,我们一起学习了单变量高斯分布。我们了解到,高斯分布是一个由均值和方差两个参数完全定义的钟形概率分布。均值决定了分布的中心位置,而方差决定了数据的离散程度。这种分布是构建更复杂概率模型(如混合模型)的基础组件。
机器学习:第3-4课:二元和多元高斯分布

在本节课中,我们将学习高斯分布在多维空间中的扩展。我们将从二元高斯分布开始,理解其可视化表示和参数含义,然后将其推广到任意维度的多元高斯分布。核心概念将通过公式和代码进行描述。
二元高斯分布的可视化
上一节我们介绍了一维高斯分布,本节中我们来看看它在二维空间中的形态。当我们在两个随机变量上指定一个高斯分布时,我们为这对变量在其取值范围内的每一个点都分配了概率密度。
与一维情况类似,这个分布只有一个“峰”。例如,在下图中,概率密度最高的区域就是分布的中心点。

这个中心点代表了分布的平均值,也是概率最大的区域。在高斯分布中,均值也等同于分布的众数。当我们远离这个众数时,就进入了概率较低的区域。
另一种更常用的二维高斯分布可视化方法是等高线图。等高线图是上述三维网格图的俯视图。

它绘制了等概率的椭圆曲线,其中颜色深浅代表概率密度的高低。中心点仍然是概率最高的区域,蓝色阴影区域代表低概率。随着我们向任意方向远离峰值,概率都会降低,只是在不同方向上降低的速度不同。
二元高斯分布的参数
在二维空间中,一个高斯分布完全由两个参数决定:一个均值向量和一个协方差矩阵。
- 均值向量
mu:其元素决定了分布沿每个维度的中心位置。例如,mu1将分布中心定在蓝色强度轴上,mu2定在绿色强度轴上。这两个值共同确定了蓝绿强度空间中的分布中心点。 - 协方差矩阵
Sigma:它指定了分布的展布和方向。
以下是协方差矩阵各部分的含义:
- 对角线元素:是每个单一维度的方差。例如,左上角的
sigma_blue^2是蓝色强度方向的方差,右下角的sigma_green^2是绿色强度方向的方差。 - 非对角线元素:如
sigma_blue,green,指定了分布中两个随机变量之间的相关性结构,即这些椭圆的朝向。
协方差结构示例
让我们通过几个例子来理解不同的协方差结构如何影响分布形状。
1. 对角协方差(元素相等)
当协方差矩阵是对角矩阵且对角线元素相等时,意味着两个随机变量之间没有相关性(非对角线为零),并且沿每个维度的展布相同。这会产生一个圆形的分布。
2. 对角协方差(元素不等)
如果协方差矩阵是对角矩阵但对角线元素不相等,意味着变量间仍无相关性,但沿每个维度的展布不同。这会产生轴对齐的椭圆。
3. 完整协方差
如果协方差矩阵是完整的(非对角线元素不为零),则允许两个随机变量之间存在相关性。这会产生非轴对齐的椭圆。例如,在图中展示的情况下,如果蓝色强度高,绿色强度也倾向于高,这称为正相关。
推广到多元高斯分布
我们可以将高斯分布定义在任意维度 d 上,而不仅仅是一维或二维。
- 均值向量
mu:是一个d维向量,其元素数量与随机向量X的维度相同。 - 协方差矩阵
Sigma:是一个d x d的矩阵。其对角线有d个方差参数,非对角线则捕捉这d个随机变量之间的相关性结构。
该矩阵需要是半正定的,这对矩阵元素有一定的约束。在表示法上,我们使用与一维情况类似的符号,但用 mu 和 Sigma 代替了单一的方差项 sigma^2:
N(x | mu, Sigma)
总结

本节课中我们一起学习了高斯分布从一维到多维的扩展。我们首先通过三维网格图和等高线图理解了二元高斯分布的形态。然后,我们深入探讨了其核心参数——均值向量和协方差矩阵——如何共同决定分布的位置、展布和方向。通过分析对角协方差和完整协方差的例子,我们看到了变量间相关性对分布形状的影响。最后,我们将这些概念推广到了任意维度的多元高斯分布,为后续处理高维数据打下了基础。
机器学习(分类,聚类和检索):第3-4课:高斯混合模型 🧮

在本节课中,我们将要学习一种非常重要的混合模型特例——高斯混合模型。我们将详细介绍其核心概念、模型构成以及如何通过加权平均的方式,将多个高斯分布组合起来以描述复杂的数据分布。
上一节我们介绍了高斯分布的基础知识,本节中我们来看看一个非常重要的混合模型特例,也是本课程和作业中会重点强调的模型,它被称为高斯混合模型。请记住,对于我们的任何一个图像类别,以及观测向量的任何一个维度(例如图像中的蓝色强度),我们都将假设一个高斯分布来对该随机变量进行建模。
例如,对于森林类别的图像,如果我们只观察蓝色强度,那么我们可能会得到一个高斯分布,如这里的绿色曲线所示,其中心大约在0.42这个值。这里需要说明的是,我们实际上假设整个三维RGB向量服从一个高斯分布,并且这个高斯分布可以具有相关性结构,这些不同强度值之间会存在相关性,因为图像中的RGB值往往不是独立的,尤其是在给定的图像类别内。但为了便于说明和保持绘图简洁,我们只观察蓝色强度这一个维度。不过,请在脑海中想象这些高斯分布存在于更高维的空间中。
回到我们所说的,我们为每个类别(森林、日落、云)都有一个高斯分布。但请记住,我们当然没有这些图像的标签,我们无法将每个类别分开并单独分析来学习这些分布的参数。相反,我们拥有的是一个相当复杂的、混合了所有这些不同图像类别的强度空间。
再次,如果我们只观察蓝色强度值的切片,那么我们的直方图可能看起来像之前展示过的这个三峰分布。这只是我们数据中值的直方图,但我们将采用基于模型的方法,我们想要以某种方式对这个分布(即我们整个数据集中蓝色强度的分布)进行建模。问题是,我们该如何做到这一点?
为了做到这一点,我们将取每个类别特定的分布,并简单地将它们平均在一起。因此,得到的密度函数将是这些类别特定高斯分布的平均值。但这种简单的平均假设了每个不同的类别在我们的数据中以相等的比例出现,即我们有数量相等的日落、云和森林图像。
但是,如果例如在我们的数据中,森林图像的数量远多于日落或云图像,那么在这种情况下,我们希望在这个混合(即这个平均)中更重地加权森林分布。因此,我们将对这些不同的分布进行加权平均,其中森林分布在该平均中获得更高的权重。


更正式地,我们引入一组聚类权重 π_k,每个聚类K对应一个权重。在这个例子中,我们假设一个具有三个不同聚类的模型(恰好对应于我们拥有森林、云和日落的真实情况),我们将有 π_1、π_2 和 π_3。这些权重捕捉了这些图像在我们整个数据集中的相对比例。
以下是关于这些权重的关键点:
- 每个权重必须在0和1之间。
- 所有聚类的权重之和必须恰好等于1。
这意味着当我们进行加权平均时,我们使用的就是这些权重,这被称为凸组合。请记住,高斯分布是一个分布,这意味着如果我们对该随机变量的分布进行积分,其总和(或质量)为一。在混合模型中,由于我们是对这些各自积分为一的高斯分布进行凸组合,因此整体结果仍然会积分为一,所以它仍然提供了一个有效的分布。
最后,为了完成我们的混合模型规范(特别是高斯混合模型),我们不仅为每个不同的聚类有一个混合权重,在一维情况下,我们还有一个聚类特定的均值 μ_k 和方差 σ_k²。这些均值和方差指定了构成我们混合模型的每个不同分布的位置和展宽。
当我们考虑更高维度的高斯混合模型时(我将只展示二维的图片,而不是我们处理RGB向量时真正使用的三维高斯分布,但二维是我能绘制图的极限),我们最终得到的只是上一张幻灯片讨论的聚类参数的一般化。
以下是高维情况下的参数:
- 混合权重 π_k 完全相同,不随维度变化。
- 但现在,我们不再只是一个均值和标量方差,而是为每个高斯分布都有一个均值向量 μ_k 和协方差矩阵 Σ_k。
这些均值和协方差不仅指定了位置,还指定了这些不同椭圆(等高线)的形状和方向。当我们考虑混合权重时,很难在这种等高线图上标注,只需想象取这些以绿色、紫红色和蓝色显示的分布中的每一个,然后对它们进行加权。这个权重 π_k 是从图板(幻灯片)中延伸出来的,它代表了我们在整体混合中对每个不同混合成分的强调程度。


本节课中我们一起学习了高斯混合模型的核心思想。我们了解到,它通过为每个潜在类别(或聚类)分配一个高斯分布、一个混合权重 π_k,以及相应的参数(均值 μ_k 和方差/协方差 Σ_k),来对复杂的数据分布进行建模。模型通过凸组合(加权平均)这些高斯成分来形成整体的概率密度函数,从而能够灵活地描述多模态数据。
机器学习(分类,聚类和检索):第3-4课:解释高斯混合模型的项

在本节课中,我们将学习高斯混合模型(GMM)中各项的含义,并理解它们如何共同作用以进行聚类。我们将重点关注模型中的先验概率和似然项,并解释它们如何影响对数据点所属簇的“软”分配。
概述
上一节我们介绍了高斯混合模型的基本形式。本节中,我们将深入探讨模型中的两个核心组成部分:先验概率和似然。理解这些项是理解GMM如何量化数据点属于某个簇的不确定性的关键。
先验概率:数据点属于某个簇的初始信念
首先,我们考虑一个基本问题:在观察到数据点本身的具体内容之前,第 i 个数据点属于第 k 个簇的概率是多少?
例如,在我们的图像数据集中,这可能是在看到图像像素之前,问“第 i 张图片是云朵图片的概率是多少?”
这个概率完全由混合权重 π_k 决定。π_k 代表了第 k 个簇在整个数据集中所占的比例或普遍程度。
因此,我们可以说,第 i 个观测值被分配到第 k 个簇的先验概率由 π_k 给出。
公式表示:
P(z_i = k) = π_k
其中 z_i 是第 i 个数据点的簇分配指示变量。
似然:在已知簇类别下观测到数据的概率
现在,我们考虑另一个问题:假设我们已经知道一个数据点来自某个特定的簇(例如,已知一张图片是“云朵”类别的图片),那么观测到该数据点具体特征值(例如其RGB向量 x_i)的概率是多少?
在这种情况下,我们只需查看定义该簇的高斯分布。对于第 k 个簇,其分布由均值 μ_k 和协方差矩阵 Σ_k 参数化。
因此,在已知数据点属于第 k 个簇的条件下,观测到其特征向量 x_i 的概率,就是该高斯分布在 x_i 处的概率密度。
公式表示:
P(x_i | z_i = k) = N(x_i | μ_k, Σ_k)
这个项被称为似然项。
结合先验与似然:形成软分配
理解先验和似然后,我们就能理解GMM如何进行“软”聚类分配。
当我们实际观察到一个数据点 x_i 时,我们需要结合两方面信息来判断它最可能属于哪个簇:
- 先验 (
π_k):每个簇本身的普遍性。即使某个图像看起来不太像典型的“森林”图片,但如果数据集中森林图片占绝大多数,它仍有可能是森林图片。 - 似然 (
N(x_i | μ_k, Σ_k)):该数据点与每个簇的匹配程度。一个非常蓝的图片在“云朵”分布下的概率会很高,而在“日落”分布下的概率则几乎为零。
GMM通过贝叶斯规则将这两者结合起来,计算数据点属于每个簇的后验概率。这个后验概率就是我们的“软”分配,它量化了归属每个簇的不确定性。
例如,一张同时包含云朵和树木的图片,其RGB向量在“云朵”簇和“森林”簇的高斯分布下都可能有一定的似然值。同时,我们需要考虑数据集中云朵和森林图片的先验比例。最终的后验概率会反映这种竞争和不确定性,而不是像K-Means那样做出“非此即彼”的硬性决定。
核心概念总结
以下是高斯混合模型用于聚类时涉及的核心变量和概念:
- 观测数据 (
x_i):第i个数据点的特征向量(例如,图像的RGB值)。 - 簇分配变量 (
z_i):一个隐变量,表示第i个数据点属于哪个簇。在GMM中,我们估计的是它的概率分布。 - 混合权重 (
π_k):第k个簇的先验概率。表示在选择一个数据点时,它来自第k个成分的概率。 - 簇参数 (
μ_k,Σ_k):定义第k个高斯分布的均值和协方差。 - 似然 (
N(x_i | μ_k, Σ_k)):在已知数据点属于第k个簇的条件下,观测到其特征x_i的概率。
总结
本节课中,我们一起学习了高斯混合模型中两项关键组成部分的含义。先验概率 π_k 代表了数据点属于某个簇的初始信念,由该簇在数据中的整体比例决定。似然项 N(x_i | μ_k, Σ_k) 则衡量了在假设数据点来自某个特定簇的条件下,观测到其具体特征值的可能性。

理解这两项是理解GMM如何工作的基础。在下一节中,我们将看到如何利用这两项计算后验概率,从而实现对数据点的软聚类分配,这比K-Means的硬分配更能表达现实数据中固有的不确定性。
机器学习(分类,聚类和检索):第3-4课:扩展高斯混合模型用于文档聚类 📄

在本节课中,我们将学习如何将高斯混合模型应用于文档聚类任务。我们将探讨如何利用该模型处理高维文档数据,并理解其相较于K均值等方法的优势。最后,我们将简要介绍算法如何为数据点提供“软分配”。
在上一节中,我们讨论了混合模型的基本概念。本节中,我们将看看如何将其具体应用于文档聚类。我们的目标是发现相关的文章组,但使用混合模型时,我们旨在处理数据点分配到不同簇的不确定性,例如一篇介于蓝色和橙色簇之间的文章。
对于文档表示,我们将使用标准的TF-IDF向量。这是一个向量,其元素数量等于词汇表的大小。基于此表示,我们可以将文档嵌入到R^V空间,即一个具有V个不同维度的实数空间,其中V是词汇表的大小。下图仅展示两个维度的情况,这相当于我们有一个仅包含两个不同单词的词汇表。
基于此表示,使用高斯混合模型的目标是发现可能如下所示的簇。同样,我们的高斯混合模型将能够为这些簇提供数据点的软分配。在下一节中,我们将从算法层面描述如何提供这些软分配。
但让我们更深入地思考一下,将标准的高斯混合模型应用于这个特定的高维文档表示会怎样。因为在二维情况下,当我们讨论高斯的参数时,我们说过有一个均值向量,它有两个需要学习的参数,用于确定分布的中心。但还有一个协方差矩阵,在二维情况下有四个参数:两个方差项(沿两个维度的扩展)和两个非对角线项(捕捉相关结构)。我们曾简要提到它是一个对称矩阵,因此实际上sigma_12和sigma_21是相等的。所以,在二维情况下,我们只需要指定三个唯一参数,或者说需要从数据中学习三个参数。
然而,当我们面对V个不同维度,并且想象V非常大时,如果我们允许一个完整的协方差矩阵,我们将需要学习V*(V+1)/2个唯一参数。这大约是V2个参数。我们得到V*(V+1)/2而不是V2,是因为它是一个对称矩阵。因此,这并非完全是V^2个参数。
因此,我们不指定这些完整的协方差矩阵,而是假设协方差矩阵具有对角线形式。这意味着,对于我们的每个不同维度(从1到V),都会有一个方差项,而所有非对角线项都将固定为零。这样,我们只需要学习不同维度上的方差。
这意味着,我们不再考虑任意方向的对齐椭圆,而是将自身限制在仅考虑轴对齐的椭圆。这代表了一个限制性假设。但我想提几点:
首先,我们实际上可以学习不同维度上的权重,并且这些权重在不同的簇之间可以不同。例如,在一个簇中,我们可能学到某个单词在计算该簇下观测值的得分时比另一个单词更重要,而这可能与其他簇中的情况不同。
因此,这种表述仍然比K均值中的表述灵活得多。因为在K均值中,典型的表述只假设球面对称的簇,这是轴对齐椭圆的一个特例,即所有方差项都相同(对角线上的所有值都是sigma^2)。我们说过也可以使用加权欧几里得距离的版本,但这会给我们提供在不同簇之间完全相同的轴对齐椭圆。
此外,在K均值的情况下,我们必须预先指定这些权重,而在下一节中,我们将展示我们实际上可以学习这个混合模型的权重,即这些特定于簇的不同维度上的权重。
除了从数据中学习这些不同高斯的参数外,我们还将学习软分配,即任何观测值与任何不同簇相关联的概率。


本节课中,我们一起学习了如何将高斯混合模型的思想扩展到文档聚类。我们理解了在高维TF-IDF向量空间中,使用对角协方差矩阵的实用性和优势,它允许我们学习特定于簇的维度权重,并为数据点提供概率性的软分配,这比K均值等硬分配方法提供了更丰富的信息。
机器学习(分类,聚类和检索):第3-4课:从已知聚类参数计算软分配 🧮


在本节课中,我们将学习如何从一组未标记的数据点出发,计算每个数据点属于各个聚类的“软分配”。软分配量化了数据点属于每个聚类的概率,而非硬性地将其归入单一类别。我们将首先探讨在已知聚类参数的情况下,如何计算这些软分配。
上一节我们介绍了软分配的概念。本节中,我们来看看如何具体计算它。软分配通过一个称为责任向量的量来量化。
对于每个观测数据点 i,我们形成一个责任向量,其元素为 R_i1, R_i2, ..., R_iK,其中 K 是聚类总数。每个元素 r_ik 表示第 k 个聚类对观测点 i 所承担的“责任”,具体来说,它是在给定聚类权重和形状参数的条件下,观测点 i 被分配给第 k 个聚类的概率。用公式表示如下:
r_ik = P(z_i = k | π, μ, Σ, x_i)
这里,z_i 是表示观测点 i 所属聚类的隐变量,π 是各聚类的混合权重,μ 和 Σ 定义了各聚类的中心(均值)和形状(协方差),x_i 是观测到的数据点值。
为了更直观地理解,让我们通过一个包含两个聚类的例子来说明。假设有两个球形对称的聚类,一个绿色,一个蓝色,并且它们拥有大致相同数量的数据点(权重相近)。
以下是几种不同情况下,一个特定观测点(用粉色高亮显示)的责任分配情况:
-
情况一:靠近绿色聚类中心
高亮的观测点距离绿色聚类中心更近。因此,绿色聚类对该点的责任大于蓝色聚类,但两者仍共同承担对该点的责任。 -
情况二:靠近蓝色聚类中心
当高亮点移向蓝色聚类中心时,蓝色聚类将承担更多责任。 -
情况三:位于两聚类中间
如果观测点位于两个聚类的中间位置,则绿色和蓝色聚类将几乎平分对该点的责任,这反映了该数据点聚类归属的高度不确定性。
但是,如果混合模型中一个聚类的权重远大于另一个呢?例如,绿色聚类拥有大量数据点,而蓝色聚类只有少数几个。
在这种情况下,即使观测点位于两个聚类的边界上,我们虽然仍不确定其具体归属,但权重更大的绿色聚类看起来是更可能的解释。因此,由于混合模型中聚类比例的不平衡,绿色聚类对该边界点的责任会超过蓝色聚类,而此前两者的责任是均分的。
在数学上,我们需要将观测点来自任一聚类的先验概率(即混合权重 π_k),与在该聚类下观测到当前数据值的可能性(即似然 P(x_i | μ_k, Σ_k))结合起来考虑。公式如下:
r_ik ∝ π_k * N(x_i | μ_k, Σ_k)
这里,N(x_i | μ_k, Σ_k) 是高斯分布的概率密度函数。例如,一个数据点可能来自高权重聚类(先验概率高)的先验概率很大,但根据其观测值,它在该聚类下的似然却非常低。因此,我们必须同时考虑这两项。
为了使 r_ik 成为一个有效的概率(即所有 k 上的 r_ik 之和为1),我们需要对所有可能的聚类分配进行归一化。完整的计算公式是:
r_ik = [π_k * N(x_i | μ_k, Σ_k)] / [Σ_{j=1}^{K} π_j * N(x_i | μ_j, Σ_j)]
这个公式量化了我们之前的讨论:软分配由先验项(代表从数据集中随机抽取一个样本,它属于某类别的初始概率)和似然项(代表在给定类别下,观测到当前数据值的可能性)共同决定。两者的结合最终决定了我们的软分配。
本节课中我们一起学习了在已知聚类参数(混合权重 π、均值 μ 和协方差 Σ)的情况下,如何计算软分配。总结来说,计算过程非常简单直接:
- 对于每一个可能的聚类
k,计算先验概率π_k与似然N(x_i | μ_k, Σ_k)的乘积。 - 将上述乘积对所有聚类
k求和,得到归一化分母。 - 用每个聚类的乘积除以这个总和,得到归一化的责任值
r_ik,它构成了一个和为1的概率向量。

然而,故事并未结束,因为在现实中,我们通常并不知道这些聚类参数,它们也需要我们从无标签数据中推断出来。这将是后续课程要解决的核心问题。
机器学习(分类,聚类和检索):第3-4课:可选:责任作为贝叶斯规则 📚

在本节中,我们将深入探讨期望最大化算法中“责任”这一核心概念背后的数学原理。具体来说,我们将看到,之前视频中介绍的软分配公式,实际上是贝叶斯规则的一个直接应用。理解这一点,能让我们更深刻地把握混合模型参数估计的逻辑。
在上一节,我们介绍了期望步骤中计算“责任”的公式。本节中,我们来看看这个公式如何从概率论的基本原理——贝叶斯规则中推导出来。

责任公式的回顾与泛化
首先,让我们回顾一下责任的定义。责任 r_ik 表示在给定模型参数和观测数据点 x_i 的条件下,数据点 i 属于聚类 k 的概率。用数学符号表示为:

公式: r_ik = P(z_i = k | x_i, 参数)
为了进行更一般的推导,我们先将模型参数(如混合权重 π_k、均值 μ_k、协方差 Σ_k)统称为 参数。
这样,我们可以将责任公式的分子部分拆解为两项:
- 先验概率:
P(z_i = k | 参数)。在我们的模型中,这直接就是混合权重π_k。 - 似然:
P(x_i | z_i = k, 参数)。这由第k个高斯分布N(x_i | μ_k, Σ_k)给出。
引入事件符号
为了清晰地应用贝叶斯规则,我们引入事件符号:
- 将事件“
z_i = k”记为事件A。 - 将事件“观测到数据点
x_i”记为事件B。
利用这些符号,责任公式的分子可以重写为:
P(A | 参数) * P(B | A, 参数)
在分母中,我们对所有可能的聚类 j 求和。对于每个 j,我们定义事件“z_i = j”为某个事件 C_j。因此,分母中的每一项可以写为:
P(C_j | 参数) * P(B | C_j, 参数)
应用贝叶斯规则
将上述部分组合起来,责任公式变为:
公式:
P(A | B, 参数) = [P(A | 参数) * P(B | A, 参数)] / [Σ_j P(C_j | 参数) * P(B | C_j, 参数)]
现在,观察分母中的求和项 Σ_j P(C_j | 参数) * P(B | C_j, 参数)。根据概率的链式法则,P(C_j | 参数) * P(B | C_j, 参数) 等于联合概率 P(B, C_j | 参数)。
因此,对整个分母求和 Σ_j P(B, C_j | 参数),实际上就是对所有可能的聚类分配 C_j 进行边际化,其结果正是 P(B | 参数),即在给定参数下观测到 x_i 的概率(也称为证据)。
于是,责任公式简化为经典贝叶斯规则的形式:
公式:
P(A | B, 参数) = [P(A | 参数) * P(B | A, 参数)] / P(B | 参数)
这与标准的贝叶斯公式 P(A|B) = P(A) * P(B|A) / P(B) 完全一致,唯一的区别是我们在所有项中都条件依赖于模型参数 参数。
总结
本节课中我们一起学习了责任公式的贝叶斯解释。我们通过以下步骤完成了推导:
- 回顾责任定义:将其视为一个后验概率。
- 泛化与符号化:将模型参数和观测数据抽象为事件。
- 分解与重组:将公式拆分为先验与似然的乘积。
- 应用边际化:将分母的求和识别为对证据项
P(B|参数)的计算。

最终我们得出结论:期望最大化算法中用于软分配的“责任”计算公式,是条件化于模型参数后的贝叶斯规则的一个直接应用。它利用了我们模型中已知的量(聚类分配的先验概率 π_k 和给定聚类后数据点的似然 N(x_i | μ_k, Σ_k)),来计算数据点属于每个聚类的后验概率 r_ik。理解这一点,有助于将EM算法的E步骤牢固地建立在概率论的基础之上。
机器学习(分类,聚类和检索):第3-4课:从已知聚类分配估计聚类参数 🧮

在本节课中,我们将学习当已知数据点属于哪个聚类时,如何估计每个聚类的参数。我们将重点讨论高斯混合模型,并介绍最大似然估计方法。
上一节我们介绍了在已知聚类参数的情况下如何计算软分配。本节中,我们来看看相反的情况:假设我们已知每个数据点的聚类分配,如何推断出聚类的参数。
我们将假设数据点有硬分配,即每个点确定性地属于一个聚类。在图中,这体现为每个数据点有明确的颜色(例如三种颜色),而不是之前软分配时显示的连续颜色谱。
一旦固定了这些聚类分配,一个关键点是:分配给绿色聚类的数据点,会影响我们对紫色或蓝色聚类参数的估计吗?答案是不会。只有分配给特定聚类的观测数据,才会影响该聚类的参数估计。我们在K均值算法中见过类似情况,更新聚类中心时只使用分配给该聚类的点。但现在,我们将进行更一般的参数更新,不仅更新聚类中心,还更新其形状(协方差)。
回到我们的图像聚类任务,假设我们将数据的RGB值以及硬聚类分配存储在下表中。
首先,我们将根据硬聚类分配拆分这个数据表。例如,我们会得到一个属于聚类3的数据表,一个属于聚类2的数据表,以及一个属于聚类1的数据表。然后,在形成每个聚类的参数估计时,我们将完全独立地考虑这些数据表。
以聚类3的数据点为例,我们将使用最大似然估计方法来估计其参数。这意味着我们将搜索所有可能的参数设置,并找到在指定模型下使观测数据可能性最大的设置。
每个聚类由一个高斯分布指定,该分布有两个参数:均值(μ)和协方差(Σ)。让我们花点时间讨论这两个参数的最大似然估计形式。
对于均值,最大似然估计恰好等于样本均值。我们只需对属于聚类K的所有数据点取平均。
以下是估计公式:
均值估计公式:
μ̂_k = (1 / N_k) * Σ_{i ∈ C_k} x_i
其中,N_k 表示分配给聚类 k 的观测数量,C_k 是属于聚类 k 的数据点索引集合,x_i 是第 i 个数据点的向量。
这个公式与K均值算法中更新聚类中心的公式完全相同:查看分配给给定聚类的所有数据点,并计算这些数据点的平均值。
现在,我们还有协方差项,它决定了高斯分布中椭圆的扩散和方向。其最大似然估计由所谓的样本协方差估计给出。
协方差估计公式:
Σ̂_k = (1 / N_k) * Σ_{i ∈ C_k} (x_i - μ̂_k)(x_i - μ̂_k)^T
首先,我们从每个数据点中减去估计的均值,然后计算这些中心化数据点的外积,最后对属于聚类 k 的所有数据点求和,并除以聚类 k 中的观测总数。
在标量情况下(即单变量数据),这就是方差的估计公式:
σ̂_k^2 = (1 / N_k) * Σ_{i ∈ C_k} (x_i - μ̂_k)^2


最后,对于聚类比例(混合权重),我们只需计算聚类 k 中的观测数量,然后除以观测总数。
混合权重估计公式:
π̂_k = N_k / N
其中,π_k 是聚类 k 的权重,N 是数据点总数。需要强调的是,π̂_k 的估计形式并非高斯混合模型特有,它也适用于其他分布(如多项混合分布)的混合模型。然而,前面讨论的均值和协方差估计公式,是专门针对由高斯分布定义每个聚类的情况。
总结


本节课中,我们一起学习了在已知数据点聚类分配的情况下,如何估计聚类参数。核心要点是:
- 参数估计问题在固定分配后会解耦,每个聚类的参数可以独立估计。
- 使用最大似然估计方法,均值估计为样本均值,协方差估计为样本协方差,混合权重估计为各类别的样本比例。
- 这些计算非常直接,但前提是我们知道硬分配。然而在现实中,我们通常并不知道这些分配,这引出了我们接下来要讨论的期望最大化(EM)算法。
机器学习(分类,聚类和检索):第3-4课:从软分配估计聚类参数

在本节课中,我们将要学习如何根据软分配来估计聚类模型的参数。与上一节讨论的硬分配不同,软分配允许每个数据点以一定的概率(或责任)属于所有聚类。我们将探讨如何在这种更灵活的场景下,计算聚类的比例、均值和协方差。
上一节我们介绍了在已知硬分配(即每个数据点明确属于一个聚类)的情况下,如何通过最大似然估计来更新聚类参数。本节中我们来看看,当分配是“软”的时候,即每个数据点以不同的责任值属于所有聚类时,参数估计过程会发生怎样的变化。
在这种情况下,每个观测值不再只属于一个聚类,而是根据其责任向量,被分配到所有聚类中。因此,我们需要一种方法来更新聚类参数,这种方法需要考虑到每个数据点对每个聚类的“部分”贡献。
为了进行基于软分配的最大似然估计,我们需要构建一个带权重的数据表。以下是具体步骤:
首先,对于数据集中的每一个观测值(即每一行数据),我们引入一组权重,这组权重对应于该观测值的责任向量。这与我们在提升方法中处理加权观测值的思路类似,但区别在于,现在每个数据点有一组权重(而非单个权重),且这组权重之和为1。
这些权重将修改我们在进行最大似然估计时所执行的行操作。由于数据点被分割分配到多个聚类中,我们很难直接计算每个聚类中的观测值数量。取而代之,我们可以通过累加每个聚类的责任值,来计算每个聚类的“有效观测数”。
接下来,与硬分配时类似,我们需要为每个聚类构建一个特定的数据表。但不同的是,现在每个观测值都会出现在所有聚类的数据表中,因为每个聚类对该观测值都承担着一定的责任(尽管责任值可能为零)。在每个聚类的数据表中,我们会指定与该聚类相关的观测值权重。
以下是每个聚类数据表的构建方式:
- 聚类1的数据表:包含所有观测值,但每行数据都乘以该观测值对聚类1的责任值。
- 聚类2的数据表:包含所有观测值,但每行数据都乘以该观测值对聚类2的责任值。
- 聚类3的数据表:包含所有观测值,但每行数据都乘以该观测值对聚类3的责任值。
然后,对于每一个聚类,我们使用其对应的加权数据表来计算该聚类参数的最大似然估计。权重会修改计算过程中的行操作。
具体来说,更新后的最大似然估计公式如下,其中我们考虑了观测值的权重:
-
聚类比例:聚类k的比例估计值
π̂_k计算公式为:
π̂_k = N_k_soft / N
其中,N_k_soft = Σ_i r_ik是聚类k的有效观测数(即所有数据点对聚类k的责任值之和),N是数据点的总数(也等于所有有效观测数之和)。 -
聚类均值:聚类k的均值向量估计值
μ̂_k计算公式为:
μ̂_k = (1 / N_k_soft) * Σ_i (r_ik * x_i)
这里,每次对数据点x_i的操作都乘以其对聚类k的责任值r_ik。 -
聚类协方差:聚类k的协方差矩阵估计值
Σ̂_k计算公式为:
Σ̂_k = (1 / N_k_soft) * Σ_i [ r_ik * (x_i - μ̂_k)(x_i - μ̂_k)^T ]
同样,每个外积项都由相应的责任值r_ik加权。
为了验证这些公式的合理性,我们可以检查一个特殊情况:如果责任值 r_ik 只取0或1(即退化为硬分配),那么上述公式应该能还原为上一节的硬分配估计公式。
以下是验证过程:
- 对于聚类比例,当
r_ik为0或1时,N_k_soft就简化为聚类k中观测值的实际计数N_k,公式还原。 - 对于聚类均值,当
r_ik为0或1时,求和项Σ_i (r_ik * x_i)就简化为只对属于聚类k的x_i求和,公式还原。 - 对于聚类协方差,同理,求和项也简化为只对属于聚类k的观测值计算外积,公式还原。
这个验证至少说明,本节给出的基于软分配的估计公式在硬分配这一特例下是正确的,这增加了我们对公式的信心。

本节课中我们一起学习了如何从软分配中估计聚类参数。核心在于引入责任向量作为权重,构建每个聚类的加权数据表,并在此基础上计算加权的最大似然估计。我们推导了聚类比例、均值和协方差的更新公式,并验证了当软分配退化为硬分配时,这些公式与之前的结果一致。这为后续处理更复杂的聚类问题(如期望最大化算法)奠定了基础。
机器学习:第3-4课:EM算法在方程和图片中的迭代

在本节课中,我们将学习期望最大化(EM)算法在高斯混合模型中的应用。我们将看到该算法如何在两个步骤之间循环迭代:E步(估计责任)和M步(更新参数),并通过直观的图片演示其收敛过程。
算法概述
上一节我们介绍了高斯混合模型的基本概念。本节中,我们来看看如何通过迭代算法来估计模型的参数。该算法的核心思想是:如果已知聚类参数,则很容易计算软分配(责任);反之,如果已知软分配,则可以直接估计聚类参数。这启发了一种在两个步骤之间循环的迭代算法。
我们将要介绍的算法是更通用的期望最大化(EM)算法的一个特例。
EM算法的两个步骤
更正式地说,用于高斯混合模型的EM算法将在两个步骤之间循环:
E步(期望步):在给定当前聚类参数估计值的情况下,估计我们的聚类责任。对于高斯混合模型,其公式如下所示,这只是我们之前展示公式的一个具体例子。
M步(最大化步):在给定当前软分配估计值的情况下,计算聚类参数的最大似然估计。此处的更新,即基于一组软分配的最大似然估计,采用我们之前展示的方程形式。
算法流程图示
在图片中,EM算法的工作流程如下。
第一步:初始化参数
算法的第一步是初始化我们的模型参数集。在第0次迭代时,初始化我们的混合权重、均值和协方差。这些参数由图中所示的椭圆表示,每个椭圆都有一个中心、一定的展宽和方向。
第二步:计算责任(E步)
在固定这些聚类参数之后,我们计算责任。第一次迭代时对责任的估计,仅基于为每个聚类计算先验乘以似然项然后进行归一化。图中每个大圆圈代表一个数据点,同时也是一个饼图,表示与该数据点相关的责任。例如,某个数据点在第一次迭代时的责任向量可能是:品红色聚类0.52,蓝色聚类0.4,绿色聚类0.08。
第三步:更新聚类参数(M步)
为每个数据点计算出这些责任后,我们去重新估计聚类参数。我们将在给定第一次迭代的软分配 ( r_{ik} ) 的情况下,最大化似然。这将导致聚类参数的更新估计:第一次迭代的 ( \hat{\pi}_k )、( \hat{\mu}_k ) 和 ( \hat{\Sigma}_k )。从图中可以看到,这些椭圆已经发生了移动和变化。
第四步:迭代至收敛
然后,基于这组新的聚类参数,我们将重新计算责任(第二次迭代的责任估计)。接着,我们将重复清洗和重复这个过程,直到收敛。我们将在下一节更多地讨论收敛性。
以下是收敛时的图示。可以看到,我们的聚类相当清晰,并且很好地捕捉了数据的结构。非常关键的是,如果我们观察某个边界上的数据点,会发现即使在收敛之后,该观测值的聚类分配中仍然存在不确定性。
需要强调的是,这正是我们希望从该算法中得到的结果。与K-means会对观测值应属于蓝色聚类还是品红色聚类做出硬性决定不同,EM算法提供了关于该观测值应与哪个聚类相关联的不确定性度量。这对于其他观测值也是如此,尽管不如这个明显位于两个聚类边界上的观测值那么显著。
总结
总而言之,我们现在通过图示看到了EM算法与K-means的区别。再次强调,EM算法不仅提供了这些软分配,还提供了聚类参数的估计,从而得到了这些不同聚类的形状及其在空间中的位置,而不仅仅是聚类中心的位置。
让我们再看一遍这个过程。请记住,每个小饼图圆圈代表一个数据点,饼图中显示的颜色代表与该观测值当前相关联的责任,即它与模型中三个聚类中任何一个的关联程度。这些椭圆代表本例中的三个不同的二维高斯分布。随着我们浏览这些图,它将展示责任和我们对这些聚类参数估计的更新。
- 这是算法的初始化状态。
- 这是一次迭代后的状态。
- 这是两次迭代后的状态。
- 这是收敛时的状态。


在本节课中,我们一起学习了EM算法在高斯混合模型中的迭代过程,包括其核心的E步和M步,并通过可视化图示理解了参数与责任如何交替更新直至收敛,以及软分配所带来的不确定性优势。
机器学习:3-4:EM算法的收敛、初始化和过拟合 🧠

在本节课中,我们将深入探讨EM算法的具体细节,并比较高斯混合模型EM算法与K均值算法的异同。我们将重点关注EM算法的收敛性、初始化策略以及一个常见的陷阱——过拟合问题。
收敛性 🔄
上一节我们通过饼图展示了EM算法的收敛解。那么,我们如何确保EM算法一定会收敛呢?实际上,我们可以将EM算法的E步和M步重新表述为对一个目标函数的交替最大化过程。从这个角度看,EM算法实际上是一种坐标上升算法。在温和的条件下,可以证明EM算法确实会收敛到目标函数的局部极值点。
在作业中,你将通过计算给定当前模型参数和“责任”值下的数据对数似然度,来监控EM算法的收敛情况。
初始化策略 🚀
基于目标函数非凸的“地形”以及算法收敛到局部极值点的特性,如何初始化EM算法对我们最终找到的局部极值点的质量以及算法的收敛速度都至关重要。
以下是几种常见的初始化方法:
- 随机选择中心点:随机选择一些数据点作为初始聚类中心,将观测值硬性分配给最近的聚类中心,然后利用这些分配来形成初始参数估计,EM算法再从此处开始迭代。
- K-means++式初始化:像K-means++算法描述的那样,顺序地选择聚类中心,而不是一次性随机选择K个不同的数据点。
- K-means结果初始化:先运行K-means算法,然后将其最终解作为EM算法的初始聚类中心。
- 逐步增长法:例如在语音应用中,一种流行的方法是逐步增长混合模型,通过分裂(有时合并)聚类,直到形成K个聚类。
过拟合问题与解决方案 ⚠️
讨论了收敛性和初始化后,现在让我们花点时间讨论一下我们所描述的EM算法的一个潜在缺陷。这个问题源于最大似然估计可能会过拟合数据。
让我们通过一个例子来说明。假设我们只有两个聚类:绿色聚类和蓝色聚类。在算法的某次迭代中,假设只有一个观测值被分配给了绿色聚类,而所有其他观测值都分配给了蓝色聚类(这里我谈论的是硬分配,但同样适用于软分配的情况)。
对于这个绿色聚类中的单个观测值,最大化该聚类数据似然度的做法是什么?我们会简单地将该聚类的均值设置为恰好等于那个数据点,然后将其方差缩小到该数据点周围的零值。对于蓝色聚类,我们会将其均值移动并增加其方差,以覆盖所有显示的数据点。
这看起来不是一个好的解决方案,因为我们有一个数据点对应着一个极其微小的聚类,而两组看起来可分离的观测值却被归入一个更分散的聚类中。然而,这种分配的对数似然度实际上是无穷大的,这完全是因为在一个高斯分布下,如果它绝对确定唯一可能的值就是观测到的值,那么该绿色观测值的似然度是无穷大的。这将完全主导整个分配集的似然度,导致这成为算法偏好的解。
幸运的是,在实践中,很少会遇到这种只有一个观测值被分配到一个聚类的极端简单情况。但这确实可能发生,尤其是在考虑算法初始化方式时需要仔细思考。
然而,在高维空间中,这个问题可能会严重得多。让我们回到文档聚类的例子。假设我们有一个很大的词汇表,每个文档由该词汇表上的词频向量或TF-IDF向量表示。想象一下,对于一个给定的聚类(再次以硬分配为例,但结论可推广),如果该聚类中只有一个文档包含单词W,或者更一般地说,如果该聚类中的所有文档恰好对特定单词W有相同的词频计数,那么对于该单词W,该聚类参数的最大似然估计是什么?仅从该维度看,我们只需将均值设置为该观测到的词频计数,然后将方差缩小到该值周围的零值。
这并非一个牵强的例子。因为如果我们处于一个非常高维的空间(即非常大的词汇表),我们确实可以想象到这样的情况:给定聚类中的所有文档(特别是如果我们有足够多的聚类来划分数据)可能完全不包含某个单词,或者可能只有一个文档包含该单词。因此,这种设置在高维空间中确实可能发生。
其结果是,如果在后续迭代中,我们计算另一个文档的似然度,而该文档对于单词W的词频计数与该聚类指定的值不同,那么该文档在这个给定聚类下的似然度或“责任”将为零。因为这个聚类会说:“不行,你只能拥有我目前文档中观测到的这个值。”因此,我们会看到,如果文档在某个维度(即某个词汇单词)上不一致,其“责任”会骤降至零;如果在该聚类中且在该维度上一致,则“责任”为一。
我想强调的是,在实践中,你最终会通过下溢问题看到这一点。即使你没有将方差精确设置为零,只是将其缩得非常非常小,你也可能会得到这些协方差矩阵,并且无法计算它们的逆矩阵。因此,如果你不纠正这个潜在问题,你的代码可能会因此崩溃。
我们可以考虑一个非常简单的修复方法,称之为平滑参数估计或正则化EM更新。这个简单的修复方法就是不让我们的方差参数变为零。具体做法是,每次我们估计协方差矩阵时,只需向该协方差矩阵添加一个非常小的对角项,以确保没有任何方差为零。
作为另一种方法,你可以采用更正式的贝叶斯方法,对模型参数(即混合模型的聚类比例、均值和协方差)设置先验分布。你可以将此视为在每个聚类中放置所谓的“伪观测值”。这就像你在每个聚类中固定了一组具有某些值的观测值,这将使我们的最大似然估计产生偏差以考虑这些观测值。由于这种结构,它将避免因没有某个值的实际观测值而导致的退化情况。
因此,我们可以将其视为平滑我们的参数估计。但在这种贝叶斯方法中,你将平滑聚类比例、均值和协方差,而不是像我们这里指定的简单方法那样只平滑协方差估计。在作业中进行文档聚类的EM算法时,你将会看到这种类型的平滑处理。
总结 📝

本节课中,我们一起学习了EM算法的几个关键实践方面。我们探讨了EM算法的收敛性原理,它本质上是一种坐标上升算法。我们介绍了多种初始化策略,包括随机选择、K-means++启发式方法以及使用K-means结果作为起点,这些策略对算法结果的质量和速度有重要影响。最后,我们深入分析了最大似然估计在高斯混合模型中可能导致严重过拟合的问题,特别是在高维稀疏数据(如文档聚类)中,方差可能退化到零。我们讨论了两种解决方案:通过添加小常数项来正则化协方差估计,以及采用更系统的贝叶斯方法设置先验分布来平滑所有参数。理解这些细节对于在实际应用中成功部署EM算法至关重要。
机器学习:第3-4课:K-means与高斯混合模型EM算法的关系

在本节课中,我们将探讨高斯混合模型的期望最大化算法与K-means聚类算法之间的深刻联系。我们将看到,在特定条件下,前者可以退化为后者,这有助于我们理解两种算法在思想上的统一性。
从高斯混合模型到K-means
上一节我们介绍了高斯混合模型的EM算法。本节中,我们来看看当模型满足特定条件时,它与我们熟悉的K-means算法有何关联。
为了建立这种联系,我们考虑一个特殊的高斯混合模型。该模型中,每个簇对应的高斯分布都是球面对称的,并且所有簇的协方差矩阵相同,唯一的区别在于它们的中心点位置不同。
这意味着每个簇的协方差矩阵Σ具有以下形式:
Σ = σ² * I
其中,σ²是一个标量方差,I是单位矩阵。也就是说,矩阵对角线上的元素都是相同的σ²,非对角线元素为0。
方差的极限:趋近于零
接下来,我们将这个方差项σ²驱动至零。这意味着每个高斯分布簇都变得无限紧密,分布范围无限小。
由于这些簇是球面对称的,当我们计算一个观测点属于某个簇的相对似然度时,该值仅取决于该点到各簇中心的相对距离。又因为方差被驱动至零,这些相对似然度会趋向于要么是1,要么是0。
这种现象源于簇的“确定性”:零方差(或在极限情况下趋近于零的方差)表明簇内几乎没有不确定性。当然,在计算簇的“责任”时,我们也会考虑不同簇的混合比例,但这一项完全被似然度之间巨大的差异(比值要么是0要么是1)所主导。
硬分配与K-means的等价性
最终导致的结果是:数据点将根据其到簇中心的距离,被完全地、确定性地分配给某一个簇。这与我们在K-means算法中看到的现象完全相同。
因此,当我们对具有上述特性(各维度方差相同且趋近于零)的高斯混合模型应用EM算法时:
- 在E步:如刚才所述,我们估计出的“责任”值将只是0或1。
- 在M步:我们将更新簇的中心。方差在极限下固定为零,而簇中心的估计(以及簇比例的估计)将仅基于那些被硬分配到该簇的数据点来计算其均值。
算法步骤对比
我们可以看到,EM算法的这两个步骤,恰好对应了K-means算法的两个核心操作:
以下是K-means算法的两个核心步骤:
- 分配步骤:根据数据点到簇中心的距离,将每个观测点硬分配给最近的簇。
- 更新步骤:重新计算每个簇的中心,即计算分配给该簇的所有数据点的平均值。
这正是我们上面描述的、在方差趋近于零时高斯混合模型EM算法的E步和M步。

本节课中,我们一起学习了高斯混合模型EM算法与K-means算法之间的理论联系。我们通过将高斯混合模型中各簇的方差驱动至零,展示了EM算法中的软分配如何退化为K-means中的硬分配,并且更新簇中心的步骤也变得完全一致。这揭示了K-means可以被视为高斯混合模型EM算法在特定极限情况下的一个特例,帮助我们从一个更统一的概率视角来理解聚类算法。
机器学习(分类,聚类和检索):3-4:简要回顾 📚

在本节课中,我们将回顾模块三到四的核心内容,总结基于概率模型的聚类方法,特别是高斯混合模型与EM算法,并将其与之前介绍的K均值算法进行对比。
模块内容回顾
在本模块中,我们首先介绍了采用基于概率模型的方法进行聚类的动机,并以高斯混合模型作为此类方法的一个具体示例。
上一节我们介绍了聚类的基本动机,本节中我们来看看具体的算法实现。我们详细阐述了EM算法,这是一个具有广泛适用性的通用算法,并特别针对高斯混合模型进行了具体说明。
在整个模块中,我们将这些基于模型的方法与上一个模块中描述的K均值算法进行了比较和对比。我们在本模块中看到,实际上可以将K均值视为高斯混合模型EM算法的一个特例。因此,为了推断我们的聚类参数和软分配,思考高斯混合模型和EM算法,确实是我们之前展示的K均值算法的一种推广。
但这种推广是有代价的,因为我们需要从数据中学习更多的参数。此外,使用EM算法而非K均值也会带来计算成本——无论是在计算责任值时,还是在估计模型参数时,这些步骤都比K均值中需要执行的步骤更为复杂。
因此,这是在灵活性和获得的描述性输出之间的一种权衡。你可以获得这些捕捉不确定性的软分配,并利用它们做不同的事情,但这是有代价的。
学习目标总结
以下是完成本模块学习后,你应该能够做到的事情列表:
- 解释采用基于概率模型的方法进行聚类的动机。
- 描述高斯混合模型作为概率聚类的一个示例。
- 阐述EM算法的一般原理及其在高斯混合模型中的应用。
- 比较和对比K均值算法与基于高斯混合模型的EM算法。
- 理解将K均值视为EM算法特例的观点。
- 评估使用更复杂的概率模型(如高斯混合模型)所带来的灵活性提升与计算成本增加之间的权衡。


本节课中我们一起学习了基于概率模型的聚类核心思想,掌握了高斯混合模型与EM算法的基本原理,并理解了其与K均值算法的联系与区别。关键在于认识到,更强大的模型能提供更丰富的输出(如软分配),但也需要承担更高的计算和参数学习成本。
机器学习:第3-4课:文档的混合成员模型

概述
在本节课中,我们将学习一种非常流行的文档分析概率模型,称为潜在狄利克雷分配。这个模型是混合成员模型的一个例子。我们将从理解为什么需要混合成员模型开始,然后逐步介绍其核心概念和工作原理。


混合成员模型的动机
上一节我们介绍了聚类模型,其目标是将相关文章分组到不相交的集合或簇中,这些簇代表了语料库中普遍的主题。在这种模型中,每篇文档都被分配到一个单一的主题。
但一个问题随之而来:一篇文章真的只关于一个主题吗?例如,一篇名为《模拟癫痫事件的复杂动态和变化相关性》的文章,其中包含了“患者”、“癫痫”、“脑电图”、“临床”等词语,可能被归类到“科学”主题。然而,文章中也出现了“异步”、“自动”、“模型”等词语,这表明它也可能与“技术”主题相关。
我们之前讨论的软分配可以捕捉到这种将文章分配到“科学”簇还是“技术”簇的不确定性。但也许我们真正想要捕捉的是这篇文章同时关于科学和技术的事实。也就是说,一篇文档可以拥有多个主题的“成员资格”,而不仅仅是一个。
更重要的是,我们不仅希望知道哪些主题存在于文档中,还希望了解这些主题的相对比例,即每个主题在文档中的普遍程度。
这就是混合成员模型的用武之地。它允许我们将任何一个数据点(在此处是文档)与一组不同的簇分配(即主题)关联起来,而不是假设每篇文档只与一个簇或主题相关联。
混合成员模型的核心思想
混合成员模型的核心在于,每篇文档不再由一个单一的隐藏变量(如 Z_i)表示其所属主题,而是由一个主题分布来描述。
具体来说,对于第 i 篇文档:
- 我们引入一个参数
θ_i,它是一个概率向量。 - 这个向量的长度等于主题总数
K。 - 向量中的第
k个元素θ_{i,k}表示第i篇文档中主题k的比例。
用公式表示,对于一篇文档 i 和所有主题 k=1...K,有:
θ_i = (θ_{i,1}, θ_{i,2}, ..., θ_{i,K}),其中 ∑_{k=1}^{K} θ_{i,k} = 1 且 θ_{i,k} ≥ 0。
例如,如果一篇文章 60% 关于科学,40% 关于技术,那么它的 θ_i 向量在科学主题对应的位置值约为 0.6,在技术主题对应的位置值约为 0.4,在其他主题位置的值接近 0。

从主题分布生成词语
理解了文档的主题分布后,我们来看看如何根据这个分布生成文档中的词语。这个过程分为两步:
- 为每个词语选择一个主题:对于文档
i中的第j个词语,我们根据该文档的主题分布θ_i随机抽取一个主题Z_{i,j}。例如,P(Z_{i,j} = “科学”) = θ_{i,科学}。 - 从选定的主题中生成词语:每个主题
k本身也有一个在所有词语上的分布φ_k。确定了词语W_{i,j}的主题Z_{i,j}后,我们再根据该主题的词语分布φ_{Z_{i,j}}来生成这个具体的词语。
以下是这个生成过程的伪代码描述:

对于语料库中的每一篇文档 i:
得到该文档的主题比例向量 θ_i
对于文档 i 中的每一个词语位置 j:
根据多项式分布 Multinomial(θ_i) 抽取一个主题 Z_{i,j}
根据该主题的词语分布 Multinomial(φ_{Z_{i,j}}) 抽取一个词语 W_{i,j}
潜在狄利克雷分配模型
潜在狄利克雷分配 是上述混合成员思想的一个具体实现,也是一个完整的生成式概率模型。它得名于其使用了狄利克雷分布作为先验分布。
LDA 模型的完整生成过程如下:
-
对于每个主题
k(从1到K):- 从狄利克雷分布
Dir(β)中生成主题k的词语分布φ_k。
(β是一个超参数,通常是一个值很小的向量,鼓励主题分布是稀疏的,即每个主题只与少数词语强相关。)
- 从狄利克雷分布
-
对于每篇文档
i(从1到M):- 从狄利克雷分布
Dir(α)中生成文档i的主题分布θ_i。
(α也是一个超参数,通常值较小,鼓励文档的主题分布是稀疏的,即每篇文档只涉及少数几个主题。) - 对于文档
i中的每个词语j(从1到N_i,N_i是文档长度):
a. 根据多项式分布Multinomial(θ_i)抽取一个主题Z_{i,j}。
b. 根据多项式分布Multinomial(φ_{Z_{i,j}})抽取词语W_{i,j}。
- 从狄利克雷分布

总结
本节课我们一起学习了文档分析中的混合成员模型,特别是潜在狄利克雷分配 模型。
- 我们首先探讨了传统硬聚类或软聚类模型的局限性,即它们假定每篇文档仅属于一个主题。
- 为了捕捉文档涉及多个主题的现实情况,我们引入了混合成员模型的概念。其核心是为每篇文档定义一个主题比例向量
θ_i,来描述各个主题在文档中的占比。 - 接着,我们描述了基于主题比例生成文档词语的两步过程:先为每个词语按比例选择一个主题,再从该主题的词语分布中生成具体词语。
- 最后,我们介绍了完整的 LDA 模型。它是一个生成式概率模型,使用狄利克雷分布作为主题分布和文档分布的先验,并通过上述两步过程生成整个语料库。
LDA 使我们能够以更细腻的方式理解文档集合,不仅能发现潜在的主题,还能量化每篇文档中这些主题的混合情况。
机器学习(分类,聚类和检索):第3-4课:另一种文档聚类模型 🧠

在本节课中,我们将学习一种新的文档聚类模型。我们将从回顾上一模块的高斯混合模型开始,然后介绍一种基于“词袋”表示的替代模型。这种模型使用不同的文档表示方式和概率评分机制,是理解后续混合成员模型的重要基础。

上一节我们介绍了使用高斯混合模型对TF-IDF向量表示的文档进行聚类。本节中,我们来看看另一种聚类模型,它基于一种称为“词袋”的文档表示方法。
为了逐步构建文档的混合成员模型,首先介绍一种替代高斯混合模型的聚类模型是有帮助的。
需要强调的是,我们将回到聚类模型的基本假设:每篇文档只被分配到一个单一主题。
文档的“词袋”表示法 📄
到目前为止,我们使用TF-IDF向量来表示文档,并在整个语料库的TF-IDF向量空间中使用高斯混合模型来发现聚类。
现在,我们将采用一种称为“词袋”的替代文档表示法。以下是其工作原理:
- 我们简单地提取文档中出现的所有单词。
- 将它们放入一个“袋子”中。
- 然后摇晃这个袋子,使得单词的顺序不再重要。
因此,文档的表示将简化为一个无序的单词集合。这里“集合”的概念是宽松的,因为如果一个单词在文档中出现多次,这个“集合”中该单词也会出现多次。所以,唯一单词的重复次数在这里是重要的,这与标准的集合不同。这在形式上被称为“多重集”。
基于词袋的聚类模型 🧩
现在,让我们为这种新的文档表示法提出一个聚类模型。首先,我们需要指定一篇给定文档与特定聚类相关联的先验概率。
这些主题的先验概率(即主题的普遍性)与我们在高斯混合模型中的设定完全相同,它们代表了整个语料库中各个主题的普遍程度。
然而,我们的似然项将有所不同。因为与高斯混合模型中在特定高斯分布下为每个文档向量评分不同,我们现在将获取文档及其词袋表示,并在一个“主题-单词”概率向量下为这组单词评分。
具体来说:
- 每个主题都将与一个在词汇表所有单词上的概率分布相关联。
- 利用这个分布,我们可以评估出现在该文档中的单词在这个特定主题下的可能性有多大。
- 然后,我们对每个主题都进行此操作,并像在高斯混合模型的例子中一样,结合先验概率和似然项在各个主题之间进行选择。
为了更清晰地说明:对于每个主题(例如关于科技、体育的主题,尽管我们没有这些标签,它们只是聚类1、2、3……),我们都有一个在词汇表单词上的概率向量。在本幻灯片上,我按照单词在该主题中从最可能到最不可能的概率顺序来展示它们,而在上一张幻灯片中,我只是列出了实际出现在数据或特定文章中的单词。
模型对比:高斯混合 vs. 词袋模型 ⚖️
现在,我们可以比较和对比我们的高斯混合聚类模型与我们刚刚指定的聚类模型。
在这两种模型中:
- 先验主题概率:在我们实际查看文档内容之前,文档来自某个给定聚类的概率由这些
p_k给出。在两种情况下,它们的指定方式完全相同。
但它们的区别在于:
- 高斯混合模型:文档由TF-IDF向量(或某种向量,如词频向量)表示。我们在每个高斯分布下为该向量评分。请记住,每个聚类由一个高斯分布定义,你需要计算给定数据点在每个高斯分布下的评分,然后结合先验和似然项来确定文档的分配。
- 词袋模型:每篇文档都用这种词袋表示法表示。当我们对文档评分时,我们只需查看该文档中每个单词在特定主题的“单词概率向量”下的概率。
总结 📝
本节课中,我们一起学习了:
- 从高斯混合聚类模型过渡到一种新的基于“词袋”表示的聚类模型。
- “词袋”表示法将文档简化为无序的单词多重集,忽略了单词顺序但保留了词频信息。
- 新模型的先验设定与高斯混合模型相同,但似然计算方式不同:它基于每个主题的“单词概率分布”来评估文档中单词出现的可能性。
- 通过对比,我们明确了两种模型在文档表示(TF-IDF向量 vs. 词袋)和评分机制(高斯概率密度 vs. 单词离散概率)上的核心差异。


这种基于词袋和离散概率的聚类模型,为接下来理解更复杂的混合成员模型(如主题模型)奠定了重要基础。
机器学习(分类,聚类和检索):第3-4课:潜在狄利克雷分配(LDA)模型的组成部分 🧩

在本节课中,我们将学习潜在狄利克雷分配(LDA)模型的核心组成部分。我们将了解LDA如何通过为文档中的每个单词分配主题,以及为每个文档定义其特有的主题分布,来构建一个混合成员模型。
上一节我们介绍了基于聚类的文档模型,它试图将整个文档分配给一个单一的主题。本节中,我们来看看LDA模型如何对此进行扩展,为文档中的每个单词单独分配主题。

LDA模型的目标是:为文档关联一组主题,并确定这些主题在文档中的相对比例,即每个主题的普遍程度。
在之前介绍的基于聚类的词袋文档模型中,我们引入了一组主题特定的词汇分布。这意味着,为每个主题关联一个在整个词汇表上的概率分布。
\phi_k \sim \text{Dirichlet}(\beta)
其中,\phi_k 表示第 k 个主题的词汇分布。

聚类模型试图将整个文档分配给一个单一的主题。在进行这种分配时,模型会使用该主题的词汇分布来评估文档中的所有单词。
此外,该模型还引入了一个语料库范围的主题普遍性分布。这个分布描述了在整个语料库的所有文档中,各个主题出现的可能性有多大。
\pi \sim \text{Dirichlet}(\alpha)
其中,\pi 表示全局的主题分布。
在潜在狄利克雷分配(LDA)模型中,我们同样引入了那组主题特定的词汇分布。
但是,当我们观察一个给定的文档时,我们的目标是为每一个单词分配一个主题,而不是将整个文档分配给一个主题。
对于文档 i 中的第 w 个单词,会有一个分配变量 Z_{iw},用来表示该单词被分配到了哪个主题。
Z_{iw} \sim \text{Categorical}(\pi_i)
当我们评估一个文档时,我们将根据每个单词被分配的主题来评估所有单词。例如,所有被分配为“橙色”主题的单词将在橙色主题的词汇分布下进行评估,蓝色主题的单词在蓝色主题下评估,以此类推。这些评估将决定这些主题分配的好坏。
最后,LDA还有另一个不同之处。它没有引入一个语料库范围的主题普遍性分布,而是让每个文档都拥有一个关于其自身内部主题普遍性的分布。
因此,现在不再是全局的 \pi,而是针对文档 i 的 \pi_i。这个向量将代表我们期望的、在这个特定文档中各个主题的普遍程度。
\pi_i \sim \text{Dirichlet}(\alpha)
本节课中,我们一起学习了LDA模型的关键组成部分:主题特定的词汇分布、为每个单词分配主题的机制,以及每个文档独有的主题比例分布。这些元素共同构成了LDA这个强大的主题建模工具,使其能够捕捉文档中复杂的主题混合结构。
机器学习(分类,聚类和检索):第3-4课:LDA推断的目标


在本节课中,我们将学习潜在狄利克雷分配(LDA)模型的推断目标。我们将明确LDA模型的输入与输出,并探讨如何解释推断结果,例如检查学习到的主题的连贯性以及分析文档的主题比例。
模型回顾与推断任务
上一节我们介绍了LDA模型的基本结构。现在,我们转向LDA的推断问题。
LDA模型引入了一组在整个语料库中共享的、特定于主题的词汇分布。对于每个文档以及文档中的每个词,都有一个将该词分配给特定主题的分配变量。最后,每个文档都有一个主题比例向量。这些共同构成了我们的模型参数和分配变量。

然而,在无监督学习任务中,我们只获得文档中的词。我们得到大量文档,并将它们转换为词袋表示。我们仅拥有这些数据。从这些观察到的词中,我们必须推断出所有这些词分配变量、所有文档的主题比例以及主题的普遍性。这看起来是一项极具挑战性的任务。
因此,明确地说,LDA或其推断过程的输入是:
- 语料库中一系列文档的词集合。
而输出将是:
- 在整个语料库中共享的一组特定于主题的词汇分布。
- 每个文档特定的词分配变量。
- 每个文档特定的主题比例。
如何解释推断输出
在讨论执行此推断任务的算法之前,我们先描述如何解释推断的输出。
我们可以检查学习到的主题的连贯性。为此,我们可以获取每个主题下词汇表中词的分布,并按照词在主题中出现的概率对这些词进行排序。我们查看每个主题中最有可能出现的词,然后判断它们是否形成了一个连贯的集合。如果是,我们实际上可以事后为这些主题贴上标签,例如“科学与技术”、“体育”等。这为我们提供了对语料库中存在的主题的定性评估。
需要强调的是,这些主题分布通常不是稀疏向量。它们通常对词汇表中的每个词都分配了一定的概率质量。然而,如果你查看概率最高的词,如果模型运行良好,这些词通常会形成某种可解释的集合。你将在作业中探索这一点。因此,我想强调的是,我们在这些列表中展示的词,以及我们只展示少数几个词的事实,并不是每个主题的完整描述。实际上,每个主题要复杂得多。
我们还可以查看,并且通常非常感兴趣的,是每个文档的主题比例。因为这个向量可以用来关联文档,例如,哪些文档包含相似类型的主题,这可以用于检索任务。你也可以在你的作业中看到这一点。你还可以使用这种主题比例向量将一篇文章分配到多个类别。想象一下,你是一个新闻网站,有一篇文章需要分类,这种表示方式实际上允许你将那篇文章放入多个类别,从而为文章带来更多浏览量,并将其呈现给更多可能感兴趣的人。
最后,你还可以使用这些主题比例来做我们之前描述的事情,比如学习给定用户在一组主题上的偏好。LDA提供的这种描述——一组主题及其相对比例——比我们之前讨论的聚类输出形式更具描述性,无论是对于硬分配还是软分配。软分配实际上只捕捉了分配的不确定性,而不是模型所规定的、每个文档本质上关联着一组可能主题的事实。这使得我们可以在学习用户偏好方面做更高级的事情。
最后,我们尚未描述的是词分配变量。坦率地说,通常我们并不真正对此感兴趣。我们并不真正关心特定文档中的一个词是否与科学相关主题相关联。但是,这些分配变量在推断其他模型参数(通常是真正感兴趣的部分)时将起到至关重要的作用。这就像我们在EM算法中看到的一样,我们将在下一节中详细讨论这一点。
总结

本节课中,我们一起学习了LDA模型的推断目标。我们明确了推断的输入是文档的词集合,输出是主题词汇分布、文档主题比例和词分配变量。我们还探讨了如何通过检查主题中最可能的词来评估主题的连贯性,以及如何利用文档的主题比例进行文档检索、多类别分类和用户偏好建模。理解这些目标是后续学习具体推断算法的基础。
机器学习(分类,聚类和检索):第3-4课:LDA模型中的贝叶斯推断需求 🧠


在本节课中,我们将探讨LDA(潜在狄利克雷分配)模型中的推断问题。我们将了解为什么传统的最大似然估计方法在此处会遇到困难,并介绍贝叶斯推断如何帮助我们解决这些问题。特别是,我们将讨论贝叶斯方法如何通过考虑参数的不确定性来改进预测,并自然地实现参数的正则化。
从聚类算法到LDA推断
上一节我们介绍了用于聚类的K-means和高斯混合模型EM算法。本节中,我们来看看如何将类似的思想应用于基于词袋表示的文档聚类模型,并最终理解LDA模型推断的特殊需求。
对于使用词袋表示的文档聚类模型,我们可以推导出一个类似于高斯混合模型的EM算法。这里,我们不再使用TF-IDF向量的高斯似然,而是使用文档中观察到的词计数的多项分布似然。
具体来说,我们可以查看文档并记录每个词W的出现次数 M_w。我们可以将其视为词W的“成功”次数,其中“成功”的概率由特定主题下该词的概率给出。因此,我们可以使用这个来计算在给定主题下,文档中所有词计数的似然。
这个替代的聚类模型可以被视为多项分布的混合,而不是高斯分布的混合。在这种情况下,我们可以像推导高斯混合模型一样,推导出一个EM算法。
LDA模型的挑战与贝叶斯方法
那么,对于我们的LDA模型,我们能做什么呢?理论上,我们可以推导出一种EM风格的算法来执行模型参数的最大似然估计。
但是,这种最大似然估计存在与我们在高斯混合模型中看到的相同的过拟合问题。在高维空间中,挑战甚至更大,过拟合问题在LDA中往往更加严重,这主要是由于我们需要学习的参数数量非常庞大。
因此,LDA实际上通常被指定为一个贝叶斯模型。当它不是贝叶斯模型时,它实际上不被称为LDA,而是被称为概率潜在语义分析或概率潜在语义索引。
贝叶斯方法主要带来两个好处:
-
考虑参数不确定性:在进行预测时,贝叶斯方法会考虑参数的不确定性。我们不是简单地计算参数的最大似然估计值、固定这些值然后进行预测,而是认为参数可能是这个值、那个值或另一个值。我们在形成预测时,会基于我们认为参数是这些值的可能性大小,对这些预测进行加权平均。
-
自然正则化:贝叶斯方法自然地正则化了我们的参数估计。如果我们考虑最大化我们的目标(即计算最大后验估计),而不是计算最大似然估计,其结果完全类似于我们在专题中多次讨论过的正则化最大似然估计的思想。
贝叶斯框架下的推断算法
在贝叶斯设定的背景下,标准的EM算法不再易于处理,因为其中的E步涉及一个难以处理的期望计算。
因此,我们可以采用一种称为变分EM的方法,通过引入一个近似来处理那个非常复杂的期望。
总结

本节课中,我们一起学习了LDA模型推断的挑战。我们回顾了从硬分配的K-means到软分配的EM算法在聚类中的应用,并探讨了如何将类似思想扩展到基于多项分布的文档聚类模型。我们重点理解了为什么LDA模型需要采用贝叶斯方法:为了克服最大似然估计带来的严重过拟合问题,并利用贝叶斯推断来考虑参数的不确定性以及实现参数的自然正则化。最后,我们了解到在贝叶斯框架下,标准的EM算法变得难以处理,从而引出了对变分推断等近似方法的需求。
机器学习:3-4:吉布斯采样概览

在本节课中,我们将要学习一种名为吉布斯采样的贝叶斯推断算法。我们将了解它与之前方法(如K均值)的区别,理解其工作原理,并探讨如何利用其输出结果进行预测和参数估计。
算法概述
上一节我们介绍了变分EM算法,本节中我们来看看另一种完全不同的算法——吉布斯采样。
在吉布斯采样中,我们将迭代地提供硬分配,就像在K均值算法中一样。但这些硬分配是从一个特定的分布中随机抽取的。回想一下K均值,我们只是通过求解方程得到一个确定的解。而吉布斯采样的关键在于,当我们观察由该算法生成的模型参数和分配变量的随机样本时,这些样本捕捉了这些变量可能取值的不确定性。
我们介绍吉布斯采样,是为了与变分EM形成对比,因为吉布斯采样步骤的更新往往非常直观且易于实现。
直观理解
为了对吉布斯采样的过程有一个直观的认识,让我们来看几个采样样本。
在我们的LDA模型中,包含了所有我们希望进行推断的分配变量和模型参数。下图展示了吉布斯采样器在第10000次迭代时的状态。之所以要看这么靠后的迭代,是因为在像LDA这样的大型模型中,可能需要相当多的迭代次数才能摆脱可能较差的初始化状态,并开始得到一些合理的分配。
假设这是第10000次迭代的样本,这些值是随机分配给每个模型参数和分配变量的。然后,这可能是第10001个样本,第10002个样本。如果我们在这几个样本之间来回切换,观察几次,就能看到值是如何变化的。这体现了该算法内在的随机性。
采样过程与联合模型概率
那么,随着迭代采样的持续进行,我们预期会发生什么呢?
我们可以观察一个称为“联合模型概率”的量。这类似于我们之前监控的似然度,但在贝叶斯模型中,我们不仅要考虑给定特定模型参数集的数据似然度,还要考虑这些模型参数本身的概率。这两个项共同构成了联合模型概率。
如果我们观察吉布斯采样迭代过程中的联合模型概率,通常会得到类似下图的曲线。图中存在一个初始的“预烧期”,我们从初始化状态移动到某个合理的空间,然后在这个空间内徘徊。在整个过程中,联合模型概率可能上升也可能下降。原因在于这是一个随机算法,无法保证我们会增加联合概率。这不是一个优化算法,而这正是它的意义所在——它旨在探索所有可能的解空间,而不是仅仅收敛到一个单一的点。
这与我们在随机梯度下降或上升中看到的情况非常相似,那里也存在随机性,因为我们计算的是梯度的噪声估计,并且我们的目标函数不会简单地单调增加或减少,它实际上可能上下波动。
吉布斯采样的输出与应用
但这里重要的是,在经过足够多的迭代后,吉布斯采样算法产生的随机样本使我们能够形成所谓的正确贝叶斯估计。
为了举例说明这意味着什么,如果我们考虑一个预测任务,我们说过贝叶斯方法会对参数的不确定性进行平均。那么,我们可以利用吉布斯采样的输出来做到这一点:我们可以观察一个给定的样本及其所有模型参数和变量的硬分配,并根据这组分配形成我们的预测;然后观察下一个样本,形成预测;再下一个样本,再形成预测。接着,我们可以对不同样本的这些预测进行平均。自然地,由于吉布斯采样器探索不确定性的方式,它会在高概率区域花费更多时间,在低概率区域花费更少时间,从而形成了一个对参数不确定性的正确贝叶斯平均预测。
我们还可以考虑做另一件事,即提取一个“好的解”。所谓“好的解”,指的是在我们探索过的所有空间中,能够最大化联合模型概率的那组模型参数和分配变量。这是对“最大后验参数估计”的一个估计。
因此,如果我们监控迭代过程中的联合概率,只需找出使联合概率最大化的那次迭代所做的硬分配即可。
总结


本节课中我们一起学习了吉布斯采样的基本原理。我们了解到它是一种通过随机采样来探索参数空间、捕捉不确定性的贝叶斯推断方法。与优化算法不同,它不追求单调改进目标函数,而是通过生成一系列样本,使我们能够对参数进行贝叶斯平均预测,或从中找出具有高联合概率的解。其更新步骤直观,是处理复杂模型推断的一个实用工具。
机器学习(分类,聚类和检索):第3-4课:LDA的标准吉布斯采样器 🧠

在本节课中,我们将要学习潜在狄利克雷分配(LDA)模型中的标准吉布斯采样算法。这是一种用于从复杂概率分布中生成随机样本的马尔可夫链蒙特卡洛方法。我们将详细拆解其步骤,并解释它如何迭代地更新模型中的隐藏变量。
概述
吉布斯采样是一种迭代算法,它通过依次从每个变量的条件分布中采样,来生成来自联合概率分布的样本。在LDA模型中,这意味着我们要循环采样词的主题分配变量、文档-主题比例向量以及主题-词汇分布。与期望最大化(EM)算法不同,吉布斯采样以相同的方式处理所有变量,并且每一步都是随机采样而非确定性计算。
算法详解
上一节我们介绍了吉布斯采样的基本思想,本节中我们来看看它在LDA模型中的具体实现。想象在吉布斯采样的某次迭代中,我们已经有了所有变量(包括主题分配、主题比例和主题-词汇分布)的一个具体实例。
采样词的主题分配
在下一轮迭代中,我们首先考虑重新为文档中的每个词分配主题。对于文档 i 中的第 w 个词,我们计算其属于每个主题 k 的责任(即条件概率)。
公式如下:
r_{iw}^{(k)} = P(Z_{iw} = k | \text{其他变量}, \text{观测数据}) ∝ π_{ik} * φ_{k, v_{iw}}
其中:
π_{ik}是文档i中主题k的先验概率(来自当前文档-主题比例向量)。φ_{k, v_{iw}}是主题k下生成当前词v_{iw}的概率(来自当前主题-词汇分布向量)。- 我们需要对所有可能的主题
k计算这个值,并进行归一化,使其总和为1,形成一个有效的概率质量函数。
以下是计算并采样一个词的主题分配的步骤:
- 计算未归一化概率:对于文档
i中的词w,遍历所有主题k,计算π_{ik} * φ_{k, v_{iw}}。 - 归一化:将所有主题的计算结果求和,然后用每个结果除以总和,得到归一化的责任
r_{iw}^{(k)}。 - 随机采样:根据这个归一化的概率分布(即责任向量),随机抽取一个主题
k作为词w的新分配Z_{iw}。
这个过程会为文档中的每一个词重复执行。
采样文档-主题比例
在更新了文档中所有词的主题分配后,我们可以基于这些新的分配来更新该文档的主题比例向量 π_i。
影响 π_i 的主要信息是当前文档中每个主题被分配到的词的数量。然而,在贝叶斯框架下,这个计数会与狄利克雷先验分布的参数相结合。我们可以将先验视为引入了一组“伪观测”,从而对仅基于文档内计数的分布进行平滑(正则化)。
具体来说,新的文档-主题比例向量 π_i 是从一个以“文档内各主题计数 + 先验参数”为参数的狄利克雷分布中采样得到的。该分布的具体形式超出了本课程范围,但核心思想是:文档内主题使用频次越高,采样出的 π_i 中对应主题的概率通常也越高,同时先验确保了分布的合理性。
我们对语料库中的每一个文档重复上述“采样词分配”和“采样文档主题比例”的过程。
采样主题-词汇分布
更新完所有文档级别的变量后,我们转向更新整个语料库共享的主题-词汇分布 φ_k。
对于每个主题 k 和词汇表中的每个词 v,我们关心的是:在整个语料库中,词 v 被分配到主题 k 的次数。这个计数信息,结合我们为 φ_k 设置的狄利克雷先验(同样起到正则化作用),共同决定了新的主题-词汇分布。
新的 φ_k 向量是从一个以“整个语料库中属于主题k的每个词的计数 + 先验参数”为参数的狄利克雷分布中采样得到的。这样,一个主题下出现越频繁的词,在新分布中获得的概率通常也越高。
迭代过程
完成以上所有步骤(更新所有 Z, π, φ)即完成了吉布斯采样的一次迭代。然后,算法会使用新采样得到的值作为条件,重新开始下一轮迭代,再次循环更新所有变量。
算法流程总结:
- 初始化所有变量(
Z,π,φ)。 - 循环迭代直到达到预设的迭代次数或收敛:
- 对每个文档中的每个词,根据当前
π和φ采样新的主题分配Z。 - 对每个文档,根据新的
Z和先验,采样新的文档-主题比例π。 - 对整个语料库,根据所有文档的新
Z和先验,采样新的主题-词汇分布φ。
- 对每个文档中的每个词,根据当前
- 在多次迭代后,采集的变量值可以被视为来自LDA模型后验分布的(近似)样本。
总结


本节课中我们一起学习了LDA模型的标准吉布斯采样器。我们了解到,该算法通过迭代地、随机地采样三个核心变量:词的主题分配、文档的主题比例以及主题的词汇分布。每一步采样都基于其他变量的当前值以及观测到的文档数据,并融入了贝叶斯先验以进行正则化。这个过程反复进行,最终生成的样本链可用于近似模型的复杂后验分布,进而进行主题推断和参数估计。
机器学习(分类,聚类和检索):第3-4课:什么是折叠吉布斯采样

在本节课中,我们将学习一种用于潜在狄利克雷分配(LDA)模型的更高级的采样技术——折叠吉布斯采样。我们将了解其核心思想、工作原理,以及它与标准吉布斯采样的区别。
概述
上一节我们介绍了LDA模型的标准吉布斯采样实现。本节中,我们来看看一种更精巧的变体:折叠吉布斯采样。这种方法的核心在于,我们可以通过数学分析,将模型参数的不确定性“边缘化”处理,从而只对单词的分配变量进行采样,这能显著提升采样效率。
折叠吉布斯采样的核心思想
折叠吉布斯采样是一种针对LDA模型的优化采样策略。其基本思想是,我们可以在数学上解析地边缘化模型中的所有参数不确定性。这意味着我们不再需要显式地对“主题-词汇”分布和“文档-主题”比例这些模型参数进行采样。
取而代之的是,我们仅对单词的分配变量进行迭代采样。这极大地缩减了吉布斯采样器需要探索的参数空间。在实践中,这通常能带来更好的性能,因为我们通常处理的是海量词汇表,每个主题的词汇分布都包含大量参数,文档的主题比例也是如此。将这些模型参数“折叠”掉,只关注文档中的单词分配变量,非常有帮助。
用公式化的语言描述,在标准吉布斯采样中,我们采样的是联合分布 P(z, θ, φ | w),其中 z 是主题分配,θ 是文档-主题分布,φ 是主题-词汇分布。而在折叠吉布斯采样中,我们通过积分(边缘化)掉 θ 和 φ,直接对条件分布 P(z | w) 进行采样。
工作原理与图示
在折叠吉布斯采样中,我们可以完全“折叠”掉所有模型参数,如下图所示,仅对语料库中每个文档的每个单词的分配变量进行迭代重采样。
但是,这里存在一个需要注意的地方:我们现在必须顺序地重采样每个单词,条件是语料库中所有其他单词的当前分配状态。
与标准采样的关键区别
在之前讨论的未折叠(标准)LDA吉布斯采样实现中,当我们处理一个给定文档时,重采样单词指示变量是一个数据并行问题。每个单词的分配可以完全并行计算,因为它只需要以“主题-词汇”分布和“文档-主题”比例为条件。单词之间的分配是解耦的,不依赖于文档或语料库中其他单词的分配。
然而,在折叠吉布斯采样中,由于我们没有这些模型参数,那么是什么来指导我们将一个给定单词分配给一个给定主题呢?答案是:其他单词及其当前的分配状态。我们可以将语料库中所有其他分配变量视为模型参数的替代品。这导致我们必须顺序采样,失去了跨该操作并行化的能力。
以下是折叠吉布斯采样的关键步骤概述:
- 初始化:随机为语料库中的每个单词分配一个主题。
- 迭代采样:对于语料库中的每一个单词(按顺序):
- 根据当前所有其他单词的主题分配,计算该单词被分配到每个主题的概率。
- 从这个概率分布中采样,为该单词分配一个新的主题。
- 重复:多次重复步骤2,直到分配状态稳定(收敛)。
总结

本节课中,我们一起学习了折叠吉布斯采样。我们了解到,这种方法通过数学上的边缘化技巧,绕过了对LDA模型中“主题-词汇”分布和“文档-主题”比例参数的显式采样,转而仅对单词的主题分配变量进行顺序采样。虽然这牺牲了部分并行性,但极大地减少了参数空间的维度,在实践中往往能获得更优的性能和更快的收敛速度。理解这种采样方法是掌握高级主题模型推断技术的重要一步。
机器学习:3-4:LDA工作示例与初始设置 🧠

在本节课中,我们将通过一个具体的工作示例,来详细说明LDA(潜在狄利克雷分配)模型中的吉布斯采样方法。我们将从算法的初始设置开始,逐步讲解如何为文档中的单词分配主题,并建立后续采样所需的关键统计量。
初始设置与主题分配
上一节我们介绍了LDA模型的基本思想,本节中我们来看看如何为一个简单的文档集进行初始设置。
首先,算法的第一步是选择一个文档。这里我们有一个非常简单的、包含五个单词的文档。
算法的第一步是将这个文档中的每个单词分配到一个主题。以下是随机分配的一组主题,这只是初始化的一种可能方式。
与我们在本机器学习专项课程中见过的每一个迭代算法一样,初始化非常重要。理论上,吉布斯采样在运行足够长时间后会“忘记”初始设置,但有时我们没有足够的时间运行它。因此,初始化并非无关紧要。不过,在这个简单的示例中,我们假设是随机初始化主题。
然后,我们将对语料库中的每一个文档重复这个过程。这个语料库非常小,只包含非常简单的五个单词的文档。
现在,我们已经将语料库中每个单词初始分配到了一个主题。
构建局部与全局统计量
在完成初始分配后,我们需要构建一些统计量,为后续的吉布斯采样做准备。
对于文档 i,我们首先统计每个主题在该文档中出现的次数。例如,主题一出现了两次,主题二出现了一次,主题三出现了两次。这些统计量是局部的,仅针对当前考虑的文档。
同时,我们还需要一些全局的、覆盖整个语料库的统计量。具体来说,对于词汇表中的每一个单词,我们将维护一个计数,记录该单词被分配到某个给定主题的次数。
到目前为止,我们所做的一切都是为了能够运行吉布斯采样器而进行的准备工作。现在,我们有了这些局部和全局的统计量,并且已经初始化了所有单词的分配变量来得到这些统计量。
进入吉布斯采样阶段
接下来,我们可以进入吉布斯采样阶段,它将迭代遍历整个语料库中的每一个单词,并考虑重新采样其主题分配。
首先,让我们看看这个文档中的第二个单词,并考虑重新采样它的值。我将移除它当前的分配。目前,单词“dynamic”被分配给了主题2。
一旦我移除了这个分配,我将去减少所有相关的计数。因此,在这个文档中,主题2的计数减少了一个。在语料库范围内,如果我查看单词“dynamic”,它在主题二中的计数也减少了一个。
以下是移除当前分配 Z_iw = 2 后递减计数的过程。
现在,这个单词在这个文档中只剩下一个问号,因为我们移除了它的分配。当我们考虑重新分配它的值时(即重新采样),我们将基于条件分布 P(Z_iw | 所有其他 Z_jv 和语料库中观察到的所有单词) 来进行。我们将在后续讨论这个条件分布的具体形式。
总结

本节课中,我们一起学习了LDA吉布斯采样的初始设置步骤。我们从一个简单的五词文档开始,随机初始化了单词的主题分配,并建立了后续采样所需的局部文档主题计数和全局单词-主题计数。最后,我们开始进入吉布斯采样的核心步骤,即移除一个单词的当前主题分配,并准备根据条件概率为其重新采样。下一节我们将深入探讨这个条件分布的计算。
机器学习(分类,聚类和检索):第3-4课:LDA工作示例:推导重采样分布 🧮

在本节课中,我们将学习潜在狄利克雷分配(LDA)模型中的一个核心步骤:如何为文档中的单词重新采样其主题分配。我们将通过一个具体示例,详细拆解计算概率、更新计数以及迭代优化的全过程。
概述
LDA是一种用于发现文档集合中潜在主题的生成式概率模型。在模型训练过程中,一个关键步骤是使用吉布斯采样为每个单词重新分配其所属的主题。这个过程依赖于两个核心因素:文档对特定主题的偏好以及主题对特定单词的偏好。我们将通过一个具体的“dynamic”单词示例,一步步展示如何计算重采样分布并更新模型参数。
重采样分布的计算原理
上一节我们介绍了LDA模型的基本框架,本节中我们来看看如何为单个单词计算其属于各个主题的概率。这个概率由两个主要项相乘得到。
1. 文档对主题的偏好
第一项衡量的是当前文档有多“喜欢”某个主题。在LDA的吉布斯采样中,我们无法直接获得文档的主题比例参数 π,因此使用文档中已分配给该主题的单词计数作为替代,并加上狄利克雷先验的平滑参数 α。
其计算公式如下:
公式:
P(文档 i 喜欢主题 k) = (N_{ik} + α) / (N_i - 1 + K * α)
变量解释:
N_{ik}:文档i中(不包括当前正在采样的单词)被分配给主题k的单词总数。N_i:文档i中的总单词数。α:狄利克雷先验参数,起到平滑作用。K:主题总数。
示例解读:
假设一个文档中,主题1和主题3各出现了2次,主题2出现了0次。加上先验平滑后,文档对主题1和3的偏好度会高于主题2。主题2的非零概率完全来自于先验参数 α。
2. 主题对单词的偏好
第二项衡量的是某个主题有多“喜欢”当前这个被观察的单词(例如“dynamic”)。同样,我们使用整个语料库中该单词被分配给该主题的计数作为替代,并加上另一个平滑参数 β。
其计算公式如下:
公式:
P(主题 k 喜欢单词 w) = (C_{kw} + β) / (C_k + V * β)
变量解释:
C_{kw}:在整个语料库中,单词w被分配给主题k的次数。C_k:在整个语料库中,所有单词被分配给主题k的总次数。β:狄利克雷先验参数,起到平滑作用。V:词汇表的大小。
示例解读:
对于单词“dynamic”,可能技术类主题(主题1)非常喜欢它,而另一个关于流体力学的主题(主题2)也可能频繁使用它。但第三个主题(主题3)可能几乎不使用这个词。
3. 形成最终概率
单词“dynamic”在文档 i 中被分配给主题 k 的最终未归一化概率,是上述两项的乘积:
公式:
P(z_i = k | w, 其他分配) ∝ [ (N_{ik} + α) / (N_i - 1 + K * α) ] * [ (C_{kw} + β) / (C_k + V * β) ]
我们可以将这两个概率想象成两个长方形的面积,它们的乘积决定了最终采样时选择每个主题的权重。
采样与更新过程
理解了概率计算后,我们来看看如何根据这个分布进行采样,并更新模型。
采样新主题
根据计算出的概率分布,我们可以通过两种等价方式为当前单词采样一个新的主题:
- 投掷一个
K面的骰子,每个面朝上的概率正比于对应主题的概率值。 - 将所有主题的概率区域堆叠成一个长条,然后随机投掷一个飞镖,飞镖落在哪个区域,就采样哪个主题。
在示例中,由于文档喜欢主题1,且主题1也喜欢单词“dynamic”,因此采样到主题1的概率最高。
更新计数表
采样完成后,我们必须立即更新本地和全局的计数表,以反映这次新的分配。
以下是需要更新的步骤:
- 更新文档-主题计数:在文档
i的本地计数中,将主题k的计数N_{ik}加1。 - 更新主题-单词计数:在全局语料库计数中,将单词“dynamic”在主题
k下的计数C_{kw}加1。
效果:这相当于同时增强了“文档 i 更喜欢主题 k”以及“主题 k 更喜欢单词‘dynamic’”这两个信号。
迭代优化流程
完成一个单词的重新分配后,我们将按照固定的顺序,遍历文档中的每一个单词,以及语料库中的每一篇文档。
以下是完整的迭代循环步骤:
- 随机初始化所有单词的主题分配。
- 对于语料库中的每一个单词:
- a. 移除:暂时移除该单词当前的主题分配,并在本地和全局计数表中将其对应计数减1。
- b. 计算:基于更新后的计数,使用上述公式计算该单词属于每一个主题的概率。
- c. 采样:根据计算出的概率分布,为该单词重新采样一个新的主题。
- d. 更新:将新的主题分配记录到该单词上,并在本地和全局计数表中将对应计数加1。
- 完成一遍对所有单词的遍历后,这称为一次迭代或扫描。
- 重复步骤2多次(通常数百或数千次),直到模型参数(即计数分布)趋于稳定,或者达到预设的计算预算。
这个过程就是吉布斯采样,它通过反复地局部更新,最终使整个模型的分配收敛到一个相对稳定的状态,此时我们便得到了文档的主题分布和主题的单词分布。

总结

本节课中我们一起学习了LDA模型吉布斯采样的核心操作。我们详细拆解了如何为一个单词计算其重采样到各个主题的概率,这个概率由文档主题偏好和主题单词偏好共同决定。随后,我们演示了如何根据这个概率分布进行随机采样,并立即更新计数以保持状态一致。最后,我们概述了遍历整个语料库进行多次迭代的完整流程,这是LDA模型从随机初始状态逐步学习到有意义主题的关键。理解这个重采样过程,是掌握LDA及其变种模型工作原理的基础。
机器学习(分类,聚类和检索):第3-4课:使用折叠吉布斯采样的输出 🧠

在本节课中,我们将学习如何利用折叠吉布斯采样器的输出结果。折叠吉布斯采样器为我们提供了每个单词的主题分配指示变量样本。然而,我们真正关心的通常是主题的可解释性(即主题-词汇分布)以及文档的混合成员关系(即文档-主题比例)。本节将探讨如何从这些单词分配样本中,推断出我们真正感兴趣的模型参数。
上一节我们介绍了折叠吉布斯采样器的运行机制,它主要对单词的主题指示变量进行采样。你可能会想,我们为什么要采样这些单词指示变量?我并不关心它们,这是否完全是浪费时间?


请记住,我们之前讨论过,我们通常感兴趣的是主题-词汇分布(用于解释语料库中存在的主题)以及每个文档内的主题比例(因为这是文档混合成员关系的紧凑描述)。那么,我们该如何处理这个折叠吉布斯采样器的输出呢?我们得到的只是所有这些单词指示变量的样本。
处理采样输出的方法
有多种方法可以处理这些输出,这里我们将描述其中一种。
我们可以查看语料库中所有单词的分配情况,目标是找到最大化联合模型概率的那一组分配。这里指的是折叠模型的联合概率,其中我们已经对所有模型参数进行了积分,只关注这些单词分配变量的概率,当然也包括给定这些分配后单词本身的概率。
然后,对于这组最优的单词分配变量样本,我们可以在运行折叠吉布斯采样器之后,事后对主题-词汇分布进行推断。因为一旦我确定了语料库中每个单词的一组主题指示变量,我就可以形成关于我的主题-词汇分布的条件分布。
这实际上就是我们在讨论未折叠的标准吉布斯采样器时,在高层次上描述过的分布。因此,我们可以考虑从这些条件分布中采样主题-词汇分布。
文档嵌入与主题比例
同样,我们也可以考虑进行所谓的文档嵌入,即为给定文档形成其主题比例向量。这种嵌入就是获取这个文档并形成其混合成员关系的表示。
就像在我们的未折叠标准吉布斯采样器中一样,我们可以形成这些主题比例的条件分布,只需给定我们正在查看的文档中的单词分配。
需要重申的是,当我们查看主题-词汇分布时,这些是语料库级别的参数,我们必须查看在整个语料库中所做的分配来推断它们。但是,当我们查看特定于文档的主题比例时,我们只需要查看在该特定文档内所做的分配。
嵌入新文档
最后,你可以考虑嵌入新文档。假设你获得了一整套新文档,而你已经运行了折叠吉布斯采样器,你该如何处理这些新文档?
正式的做法是使用这些新文档完全重新运行你的采样器,即添加这些新文档并重新采样所有内容,然后重新审视你已经采样过的文档。但在实践中,你通常无法这样做。
因此,你可以考虑一种近似程序:使用我们在前面幻灯片中描述的程序来固定主题-词汇分布,从而固定我们的主题。我们可以将此描述为在已经查看过的一组文档上进行了“训练”。
然后,我们可以通过仅在该文档上运行一个未折叠的吉布斯采样器来嵌入新文档。因为请记住,要在给定文档中形成我们的单词分配和该文档中的主题比例,我们只需要以主题-词汇分布为条件,而不需要语料库中的其他文档。因此,我们可以使用这种类型的程序并行地嵌入每一个新文档。

总结

本节课中,我们一起学习了如何利用折叠吉布斯采样器的输出。我们了解到,虽然采样器直接输出的是单词的主题分配,但我们可以通过这些分配来推断出核心的模型参数:主题-词汇分布和文档-主题比例。关键步骤包括寻找最大化模型概率的分配样本,并基于此进行事后推断。此外,我们还探讨了如何将已“训练”好的主题模型应用于新文档的嵌入,这通常通过固定主题分布并针对新文档运行未折叠吉布斯采样来实现。这些方法使我们能够从采样过程中获得可解释且有用的主题模型结果。
机器学习(分类,聚类和检索):第3-4课:简要回顾

在本节课中,我们将对课程最后一个模块的核心内容进行回顾与总结。我们重点学习了用于主题建模的潜在狄利克雷分配模型以及用于贝叶斯推断的吉布斯采样算法。
上一节我们介绍了LDA模型和吉布斯采样的基本概念,本节中我们来看看完成本模块学习后,你应该掌握哪些核心技能。
以下是完成本模块后你应具备的能力清单:

- 能够解释潜在狄利克雷分配模型及其在文本语料混合成员建模中的应用。
- 理解LDA模型的变体可广泛应用于众多不同领域的混合成员建模问题。
- 能够解释吉布斯采样作为最常用的贝叶斯推断算法之一的基本原理。
- 理解如何在LDA模型的上下文中推导和应用吉布斯采样。
- 认识到吉布斯采样通常是推导贝叶斯模型更新公式时最直观的算法。
- 了解吉布斯采样的初始实现可能并非最具可扩展性的算法。
- 知道学术界存在大量关于如何扩展吉布斯采样算法以处理大规模数据集和模型的研究工作。
最后,我们要特别感谢David Mimno,他在我们讲解折叠吉布斯采样与LDA时提供的示例大纲对本课程帮助极大。


本节课中我们一起学习了LDA主题模型和吉布斯采样算法。LDA是文本分析中强大的混合成员建模工具,而吉布斯采样是实现贝叶斯推断的关键算法。虽然它们在处理大规模问题时面临挑战,但相关研究正在不断推动其发展。恭喜你完成了本课程最后一个模块的学习!
机器学习(分类,聚类和检索):模块1回顾 🎯

在本课程中,我们学习了聚类和检索的基础知识。模块1重点介绍了检索任务,并将其构建为最近邻搜索问题。我们探讨了数据表示、相似性度量以及高效搜索算法等核心概念。本节将对模块1的内容进行全面回顾。
检索与最近邻搜索


上一节我们介绍了课程的整体目标,本节中我们来看看模块1的核心思想。我们将检索任务定义为执行最近邻搜索的问题。我们首先研究了一种称为“单最近邻搜索”的算法。
- 单最近邻搜索:该算法遍历所有数据点,寻找与查询点最相似的数据点。
- K最近邻搜索:这是单最近邻搜索的直接扩展,它返回与给定查询点最相似的K个数据点,而不仅仅是最近的一个。
在单最近邻和K最近邻搜索中,方法的性能取决于两个关键要素:
- 数据表示:我们如何表示数据。在我们的案例研究中,问题是如何表示文档。
- 相似性度量:我们如何衡量两个数据点(例如两个文档)之间的相似性或距离。
数据表示:TF-IDF
我们深入探讨了最近邻搜索的这两个关键组成部分。首先,我们讨论了一种基于TF-IDF(词频-逆文档频率)的文档表示方法。
- 词频:简单地统计文档中每个词出现的次数。我们得到一个长度等于词汇表大小的向量,每个索引位置的值是相应词的出现次数。
- 逆文档频率:为了抵消常见词带来的偏差,我们引入了逆文档频率项,它降低了在整个语料库中普遍使用的词的权重。
TF-IDF表示法就是TF向量与IDF向量的乘积。其公式可以表示为:
TF-IDF(t, d) = TF(t, d) * IDF(t)
其中,TF(t, d)是词t在文档d中的频率,IDF(t)是词t的逆文档频率。这种方法在局部频率和全局稀有性之间进行了权衡。
距离度量:缩放欧氏距离与余弦相似度
接下来,我们转向如何计算不同文章之间的距离。我们讨论的第一种方法是使用缩放欧氏距离。
- 缩放欧氏距离:这是欧氏距离的一个变体。它允许为向量的每个分量指定一组权重,而不是对所有分量赋予相等的权重。例如,对于文档,我们可以为标题、摘要、正文等不同部分分配不同的权重。
然而,在处理文本数据时,一个更常用的距离度量是余弦相似度。
- 余弦相似度:计算两个归一化向量(每个文档一个向量)的内积。这等价于基于两个文档向量之间夹角的余弦值来计算相似度。其公式为:
cosine_similarity(A, B) = (A · B) / (||A|| * ||B||)
但请注意,余弦相似度不是一个严格的距离度量,它不满足三角不等式等性质。
我们讨论了使用余弦相似度的影响。因为它对向量进行了归一化,所以忽略了单个向量的尺度。这可能是一个理想的特性(例如,它忽略了文档长度,使长文档和短文档处于平等地位),但也可能带来问题(例如,可能使一条推文和一篇长文章显得非常相似)。作为替代方案,我们讨论了其他归一化方法,例如简单地限制最大词频来应对文档长度的差异。
需要强调的是,余弦相似度常用于文本数据特征或其他特征向量整体尺度不关键的应用。相反,在某些应用中(如房屋特征:卧室数量、浴室数量、平方英尺),原始数值的尺度非常关键,此时应使用欧氏距离或缩放欧氏距离。
高效搜索:KD树与局部敏感哈希
在本模块中,我们详细讨论了数据表示和距离计算中不同选择和选项之间的权衡。但还有一个非常重要的方面,即搜索的复杂度。
我们提到,暴力搜索(计算查询点到数据集中每个点的距离)的计算量可能非常大。因此,我们首先介绍了一种使用KD树作为高效数据结构的方法。
- KD树:递归地划分特征空间以创建二叉树,数据点存储在该树的叶节点中。
- 搜索原理:利用“当前找到的最近邻距离”小于特征空间划分中许多包围盒的距离这一事实,可以剪枝掉大量空间区域,从而高效执行最近邻搜索。
- 近似搜索:如果我们不要求精确的最近邻搜索,可以通过更激进地剪枝(基于一个“缩小”的距离)来获得更高的效率。
- 局限性:KD树实现起来不简单,并且在处理高维特征空间时扩展性不佳。
作为执行近似最近邻搜索的替代方案,我们介绍了局部敏感哈希。
- 核心思想:在空间中随机放置一组线(或高维中的超平面),这些线将特征空间划分为多个区域(“桶”)。
- 哈希表存储:每个数据点根据其所在的区域获得一个“桶索引”,并存储在以该索引为键的哈希表中。
- 搜索过程:对于查询点,首先搜索其所在的桶。为了提高搜索质量,可以继续搜索相邻的桶(通过翻转桶索引的二进制表示的位来定义相邻桶),直到耗尽计算预算。
与KD树相比,局部敏感哈希实现起来非常简单直接。你在作业中已经实践过,并探索了其返回结果的质量,证明这种简单高效的方法能够返回相当高质量的近邻。
总结

在本节课中,我们一起学习了模块1的核心内容。我们从将检索定义为最近邻搜索问题开始,深入探讨了数据表示(TF-IDF)和距离度量(缩放欧氏距离、余弦相似度)这两个关键组件。接着,我们重点解决了大规模数据下的搜索效率问题,学习了两种高效算法:用于精确和近似搜索的KD树,以及特别适合高维数据和易于实现的局部敏感哈希。通过这些知识,你现在应该能够理解、实现这些方法,并将它们应用于实际问题中。
机器学习(分类,聚类和检索):模块2回顾

在本节课中,我们将回顾模块二的核心内容,重点聚焦于聚类的概念、算法及其可扩展性实现。我们将从检索的深入探讨过渡到聚类,并详细解析K-means算法及其在大规模数据集上的应用。
🔍 检索部分回顾
上一节我们深入探讨了检索。我们的重点不仅在于如何表示数据和计算距离——这对最近邻算法的性能至关重要——还着重研究了如何将最近邻搜索扩展到超大规模数据集。
我们考虑了使用KD树和局部敏感哈希这两种方法,来实现近似最近邻搜索。
🧩 转向聚类
在课程的后半部分,我们将转向聚类这一主题。
在模块二中,我们首先讨论了聚类的含义,并回到了文档分析的例子,其目标是发现相关的文章组。
我们介绍的第一个用于执行聚类的算法叫做 K-means。这可能是使用最广泛的聚类算法。
以下是K-means算法的核心步骤:
- 初始化:随机放置一组聚类中心。
- 分配步骤:将每个数据点硬分配给距离最近的聚类中心。
- 更新步骤:根据分配给每个簇的所有点,重新计算该簇的中心位置。
- 迭代:重复步骤2和步骤3,直到算法收敛(即聚类中心不再变化)。
具体来说,我们将K-means视为一种坐标下降算法。因此,我们知道它会收敛到目标函数的一个局部最优解。重要的是,这不一定是最优的全局解,但算法确实会收敛到某个局部解。
我们通过图示展示了不同的初始化会导致收敛到截然不同的解决方案。因此,在实践中,人们通常会运行多次不同初始化的算法,并选择结果最好的一个。我们讨论了初始化对最终解的质量和收敛速度都有非常显著的影响。
⚙️ 可扩展性与MapReduce
就像在第一个关于检索的模块中一样,我们在模块二中的一个重点也是算法的可扩展性。
为此,我们引入了一个名为 MapReduce 的通用框架,用于在特定设置下跨多台机器并行化计算。我们以两个步骤来讨论MapReduce抽象:
- Map步骤:必须在数据元素上并行执行。
- Reduce步骤:执行某种聚合,必须在键上并行执行。
如果你的算法具有这种结构,就可以考虑使用MapReduce来并行化和分布式计算。
我们展示了K-means确实具有这种结构:
- 分配步骤(将数据点分配给聚类中心)可以看作是在数据元素上并行的Map操作。
- 更新步骤(重新计算每个簇的中心)可以看作是在簇标签(作为键)上并行的Reduce操作。
因此,K-means中包含了Map和Reduce步骤。不过我们提到,K-means需要在这两个步骤之间反复迭代,这是一种非标准的MapReduce实现方式,但它确实可以应用于此场景,并为K-means带来良好的扩展性能。
📝 总结
本节课中,我们一起学习了:
- 从检索到聚类的过渡,回顾了近似最近邻搜索的方法。
- K-means聚类算法的核心思想、步骤及其作为坐标下降算法的特性,理解了其收敛于局部最优解的性质以及初始化的重要性。
- 如何利用MapReduce框架来并行化K-means算法,以应对大规模数据集,并分析了算法步骤如何映射到Map和Reduce操作中。


通过本模块的学习,你掌握了基础且强大的聚类工具K-means,并了解了将其应用于实际大规模问题时的关键考量。
机器学习(分类,聚类和检索):模块3:基于概率模型的聚类回顾 🧩

在本模块中,我们将回顾基于概率模型的聚类方法,特别是混合模型。我们将探讨混合模型如何捕捉数据点分配到不同簇的不确定性,并与K均值算法进行比较,分析其各自的优缺点。
概述
在模块3中,我们延续了关于聚类的讨论,但重点转向了基于概率模型的方法,即混合模型。我们讨论了混合模型如何捕捉数据点分配到簇的不确定性,并通过描述K均值算法的一些失败案例,说明了使用混合模型的动机。K均值算法假设簇是球对称的,并仅基于簇中心分配数据点,因此在许多场景下无法很好地捕捉底层的簇结构。
混合模型与图像分组应用
在讨论混合模型时,我们使用了一个视觉上非常直观的应用:将图像分组到相关的类别中。例如,我们可能有一组未标记、混杂的图像,我们希望将它们分组为日落图像、森林图像和云图像等类别。但问题在于,我们只有这些混合在一起的数据。那么,我们将如何处理呢?
在概率方法中,我们将观测到的量(这里表示为RGB向量)视为随机变量,并研究该向量的分布。这个分布可能具有非常复杂的形式,因为它混合了这些不同的类别。为了理清这个混乱的局面,我们引入了特定于簇的高斯分量(或其他分布,但在此应用中我们主要关注高斯分布),并说明我们的混合模型只是这些不同分量的加权集合,权重基于数据集中每个类别的相对比例。
更正式地说,我们的高斯混合模型定义为一组高斯分量,每个分量由特定的均值(μ)和方差(σ²)定义,以及一个混合权重(π),表示该类在混合中的比重。所有这些图示都针对一维数据,但我们讨论了如何在更高维度上定义高斯混合模型。
文档聚类任务与高维挑战
然后,我们回到了文档聚类任务。回想一下,如果我们使用TF-IDF或简单的词频向量来表示文档,其表示维度等于词汇表的大小(V)。我们讨论了将混合模型扩展到这些高维场景所面临的一些挑战。特别是,我们指出,在实践中,人们通常希望为高斯协方差矩阵指定一个对角形式,以显著减少参数数量。
然而,这种形式仍然比K均值灵活得多。具体来说,在我们的混合高斯模型中,我们仍然会学习这些不同维度上的权重。在指定了混合高斯模型并理解了该概率模型的组成部分之后,我们转向了如何在该模型中进行推断。
期望最大化算法
回想一下,我们只是向算法提供一组未标记的数据点。我们讨论了一种称为期望最大化的算法,它允许我们联合推断模型参数以及描述数据点分配到特定簇的不确定性的软分配。
具体来说,EM算法是一种迭代算法:
- E步:基于当前模型参数的估计,形成软分配。
- M步:给定当前迭代的软分配,计算模型参数的最大似然估计。
然后,我们在这些步骤之间反复迭代,直到收敛。与K均值类似,我们展示了EM可以被描述为一种坐标上升算法,因此具有相同的属性:收敛到目标的局部模式。因此,与K均值一样,初始化非常重要。通常,人们会多次运行算法并选择最佳解。
我们还描述了,对于混合模型,我们比K均值拥有更多的参数,但我们提出了一些方法来处理或至少缓解过拟合问题。
EM算法实践与K均值的关系
在图表中,我们展示了一系列说明EM算法实践的图示。通过EM步骤的迭代,我们可以看到如何学习观测值到特定簇的软分配以及簇参数。即使在算法收敛时,我们仍然可以获得关于给定数据点是被分配到一个簇还是另一个簇的不确定性,而这实际上是我们想要的——我们希望这些不确定性作为算法输出的一部分。
最后,在模块3的结尾,我们非常正式地将高斯混合模型的期望最大化算法与K均值联系起来。具体来说,我们指出,如果我们观察一个具有球对称高斯分布的混合高斯模型(即对角协方差矩阵,且对角线元素相同),然后将方差缩小到零,并运行我们的EM算法,其输出与K均值完全相同。因为我们最终将根据到簇中心的距离,对数据点进行硬分配。因此,高斯混合模型的EM算法确实是K均值算法的一个泛化。
总结

在本模块中,我们一起学习了基于概率模型的聚类方法,重点是高斯混合模型。我们探讨了混合模型如何通过软分配来量化不确定性,从而克服K均值算法在假设和灵活性上的限制。我们详细介绍了期望最大化算法的原理和步骤,并将其与K均值算法联系起来,展示了EM算法是K均值的一个更一般化的形式。通过图像分组和文档聚类的例子,我们看到了混合模型在处理复杂和高维数据时的应用潜力。
机器学习(分类,聚类和检索):模块4:模块回顾与总结 🧠

在本节课中,我们将回顾和总结模块四的核心内容。模块四介绍了一种比简单聚类模型更复杂、能更细致描述数据点及其关系的概率模型。我们将重点回顾混合成员模型及其在文档分析中的具体应用——潜在狄利克雷分配模型。


从聚类模型到混合成员模型
上一模块我们介绍了高斯混合模型等聚类方法。在本模块中,我们首先探讨了一种替代的文档聚类模型。该模型引入了一组主题,每个主题是词汇表上的一个概率分布,代表一个不同的“簇”。
以下是该模型的核心思想:
- 每个文档被分配到一个主题(簇)。
- 分配的依据是:计算文档在其“词袋”表示下,由该主题的词汇分布生成的概率得分。
- 与之前的混合模型类似,整个语料库中,每个主题也有一个特定的普遍性(即主题分布)。
这个模型与高斯混合模型在概念上形成了对比。
潜在狄利克雷分配模型
随后,我们转向了LDA模型本身。LDA与上述聚类模型的关键区别有两点:
- 词级别分配:在LDA中,文档中的每一个词都有一个分配变量,将其链接到一个特定的主题,而不是整个文档只属于一个主题。
- 文档特定主题比例:LDA为每个文档引入了一个主题比例向量,而不是使用一个语料库级别的全局主题分布。这正是实现混合成员表示的关键。
在LDA中,一个文档不属于单一主题,而是以不同的权重(即主题比例)同时属于多个主题。这个主题比例向量可以看作是从文档中学习到的一种特征表示,可用于多种任务,例如将新闻文章分配到网站的多个版块、关联不同文章,或学习用户对不同主题的偏好。
同时,通过观察每个主题的词汇分布,我们可以解释这些主题的实际含义。
如何从数据中学习LDA模型?
与聚类一样,LDA学习是一个完全无监督的任务。我们只有语料库中的文档和词汇,目标是从中提取出主题-词汇分布和文档-主题比例。
由于LDA被指定为一个贝叶斯模型,我们介绍了一种用于学习模型参数和分配变量的贝叶斯推断方法——吉布斯采样算法。
我们首先介绍了吉布斯采样的基础版本,其核心思想是在所有变量(词的主题分配、文档主题比例、主题词汇分布)之间随机迭代,根据其他变量的当前值来重新采样每一个变量。
接着,我们介绍了一种更高效的变体——折叠吉布斯采样。在这种方法中,我们通过分析积分将模型参数(主题词汇分布和文档主题比例)从模型中“折叠”掉,只对词的主题分配指示变量进行采样。
对于一个给定词的主题分配,其条件分布由两项的乘积决定:
- 文档对主题的偏好:给定文档当前对某个主题的“喜爱”程度。
- 主题对词的偏好:该主题生成当前这个词的概率。
计算公式可简化为:
P(主题t | 其他分配) ∝ (文档d中分配给主题t的词数 + α) * (主题t中词w的计数 + β) / (主题t的总词数 + V*β)
(其中α和β是超参数,V是词汇表大小)
我们计算所有可能主题的未归一化概率,然后归一化并从中采样一个新的主题。这个过程在所有文档的所有词上循环进行。

利用采样结果进行贝叶斯推断

最后,我们讨论了如何利用吉布斯采样的输出进行贝叶斯推断。在贝叶斯框架中做预测时,我们需要对模型参数所有可能取值的不确定性进行积分。
我们介绍了两种常用方法:
- 基于样本的预测:利用采样得到的多个样本分别进行预测,然后对结果取平均。
- 最大后验估计:在实践中,也常采用使模型联合概率最大的那个样本(即MAP估计)来得出结论。
总结 📝
本节课中我们一起回顾了模块四的丰富内容。尽管这只是一个简短的回顾,但我们覆盖了大量高级主题和概念。
我们学习了多种不同的模型和算法,并在此过程中掌握了一些超越聚类和检索的、通用且有用的机器学习概念,例如:
- 适用于多种领域的距离度量。
- 近似算法。
- 无监督学习任务。
- 通过数据并行概念实现的可扩展性。
- 贝叶斯模型与贝叶斯推断的核心思想。

完成本课程后,你现在已经拥有一套非常广泛的工具集,可以去解决与回归和分类课程中看到的截然不同的问题了。
机器学习:3-4:为什么需要层次聚类


在本节课中,我们将探讨一种流行的聚类方法——层次聚类。我们将首先了解其动机和优势,然后简要介绍其两种主要类型。
在回顾了之前模块的大量内容后,我们想花些时间讨论另一种非常流行的聚类形式,即层次聚类。
但在深入探讨层次聚类的具体细节之前,我们先花点时间了解一下为什么可能需要使用层次聚类。
层次聚类的优势
以下是层次聚类的主要优点。
- 避免预先设定聚类数量:它允许我们避免必须提前固定聚类数量的棘手问题。当然,我们必须设置其他参数,我们稍后会讨论这一点。
- 可视化不同粒度:捕获层次聚类结果的树状图,可以让我们快速可视化不同粒度下的聚类结果,而无需重新运行算法。
- 灵活的距离度量:层次聚类通常允许我们指定任何想要的距离度量来定义点之间的距离。例如,在我们研究K均值时,我们隐含地指定了欧几里得距离作为距离度量。
- 捕获复杂形状:层次聚类可以捕获比K均值或混合模型所见类型更复杂的簇形状。例如,在K均值中,我们隐含地假设了球对称的簇;而在研究高斯混合模型时,我们假设簇具有椭圆形。这些假设都可能相当具有限制性。我们将展示的是,通过层次聚类,我们可以捕获更复杂的形状,例如这里展示的具有挑战性的簇结构。这些例子是我们在介绍聚类和K均值概念时展示过的,并指出那些算法在处理此类具有挑战性的簇结构时会很困难,尽管它们在我们视觉上非常明显。
层次聚类的两种主要类型
虽然层次聚类算法主要有两大类,但我们将简要介绍它们。
- 分裂式(自上而下):我们从所有数据在一个簇中开始,然后递归地分割这个簇。分裂式算法的一个例子是递归应用K均值。
- 凝聚式(自下而上):我们从每个数据点在自己的簇中开始,然后递归地合并簇。这种方法的一个例子称为单连接,我们稍后将进行描述。

本节课中,我们一起学习了层次聚类的动机、主要优势及其两种基本类型(分裂式和凝聚式)。理解这些概念为我们后续深入学习具体的层次聚类算法奠定了基础。
机器学习:3-4:分裂聚类

在本节课中,我们将要学习一种名为“分裂聚类”的层次聚类方法。我们将了解其基本思想、具体操作步骤以及在实际应用中需要考虑的关键决策。
概述
分裂聚类是一种“自上而下”的层次聚类方法。它从一个包含所有数据点的单一聚类开始,然后递归地将每个聚类分裂成更小的子聚类,从而形成一个树状的层次结构。这种方法特别适用于数据本身具有多层次结构的情况。
分裂聚类的核心思想
上一节我们介绍了层次聚类的概念,本节中我们来看看分裂聚类的具体思路。
分裂聚类的基本思想是,数据在某个粒度上可以被很好地描述为一组聚类。当我们深入观察更细的粒度时,会发现每个聚类本身又可以被更好地描述为一组更小的聚类。我们可以递归地应用这个想法。
用公式化的语言描述,如果我们有一个包含所有数据点的初始聚类 C_0,分裂聚类的目标是递归地将其分割,直到满足停止条件:
C_0 → {C_1, C_2} → {C_{1,1}, C_{1,2}, C_{2,1}, C_{2,2}} → ...
一个具体示例:递归应用K均值
为了更直观地理解,让我们看一个使用K均值算法实现分裂聚类的具体例子。
假设我们的任务是聚类维基百科文章。我们首先将所有文章视为一个大的聚类。
- 第一层分裂:我们应用K均值算法,设置 K=2,将全部文章分裂成两个聚类。通过分析聚类内容,我们可能发现,算法将文章分成了“运动员相关”和“非运动员相关”两大类。
- 第二层分裂:接下来,我们对每一个子聚类递归地再次应用K均值(K=2)。
- 对“运动员”聚类进行分裂,可能得到“棒球运动员”和“足球/冰球运动员”两个子聚类。
- 对“非运动员”聚类进行分裂,可能得到“音乐家、艺术家、演员”和“学者、政治家、政府官员”两个子聚类。
- 继续递归:我们可以继续这个过程。例如,我们可以进一步分裂“足球/冰球运动员”这个聚类,以得到更符合我们期望的粒度。
这个过程构建了一个树状结构,清晰地展示了数据从粗到细的层次化组织方式。
实施分裂聚类时需要做的决策
在实施分裂聚类时,我们需要做出几个关键的选择。以下是需要考虑的主要方面:
- 分裂算法:在每个递归步骤中,我们使用什么算法来分裂一个聚类?上面的例子使用了K均值,但也可以使用其他聚类算法(如基于密度的DBSCAN)。
- 每次分裂的数量:这相当于决定在递归应用K均值时,K 的值是多少。在上面的例子中,我们始终使用 K=2(二分),但这只是一个选择。
- 停止标准:我们何时停止分裂过程?这通常需要一些启发式规则:
- 聚类大小:如果某个聚类的成员数量少于预设的阈值,则停止分裂该聚类。
- 聚类紧密度:如果从聚类中心到最远点的距离小于某个阈值,则认为该聚类已经足够紧凑,停止分裂。
- 预设聚类总数:持续分裂,直到达到预先指定的聚类总数。但这又回到了需要预先设定聚类数量的问题,而这可能正是我们最初想避免的。
需要强调的是,所有这些标准都是启发式的,通常需要结合具体的应用场景知识和直觉,有时甚至需要人工干预,才能得到期望的层次粒度。
总结


本节课中我们一起学习了分裂聚类。我们了解到它是一种通过递归分割来构建层次聚类结构的方法。我们通过递归应用K均值的例子演示了其过程,并讨论了实施时需要做出的关键决策,包括选择分裂算法、确定每次分裂的数量以及制定停止分裂的标准。分裂聚类为我们提供了一种探索数据多层次结构的有效工具。
机器学习:3-4:凝聚聚类

在本节课中,我们将学习一种重要的聚类方法——凝聚聚类。我们将重点探讨其核心思想,并通过一个名为“单连接”的具体例子来理解其工作原理。
上一节我们介绍了分裂聚类,本节中我们来看看凝聚聚类。
凝聚聚类概述
凝聚聚类是一种自底向上的聚类方法。它从每个数据点作为一个独立的簇开始,然后逐步合并最相似的簇,直到所有数据点都合并成一个簇。这种方法会生成一个层次化的聚类结构,允许我们在不同的粒度上观察数据。
单连接算法详解
单连接是凝聚聚类中最常用的一种具体实现。其核心在于如何定义和计算两个簇之间的距离。
算法初始化
所有凝聚聚类方法的第一步都是相同的:将每个数据点视为一个独立的簇。
距离与连接函数
为了合并簇,我们需要定义簇与簇之间的距离。这由两个关键部分组成:
- 距离函数:用于计算任意两个数据点之间的距离。你可以选择任何距离度量,例如欧几里得距离。
距离函数示例:欧几里得距离 distance(x_i, x_j) = sqrt( sum_{k=1}^{n} (x_{ik} - x_{jk})^2 ) - 连接函数:用于基于点与点之间的距离,定义簇与簇之间的距离。对于单连接算法,其连接函数的定义如下:
以下是单连接算法的连接函数定义:
对于任意两个簇(例如簇1和簇2),我们查看这两个簇中所有数据点对。簇1和簇2之间的距离被定义为这些点对之间距离的最小值。
换句话说,我们找到分别来自两个簇的、彼此最接近的两个点,并用这两个点之间的距离来代表两个簇之间的距离。
合并与迭代过程
定义了距离之后,凝聚聚类的合并过程遵循一个清晰的步骤:
- 计算当前所有簇对之间的距离(使用上述单连接定义)。
- 找到距离最小的那一对簇。
- 将这两个簇合并为一个新的簇。
- 重复步骤1-3,不断计算新簇与其他簇之间的距离并合并最接近的簇,直到所有数据点最终合并成一个簇。
在这个过程中,每次迭代都需要重新计算现有簇之间的距离。记住,这个距离始终是两个簇中任意点对之间的最小距离。
总结
本节课中我们一起学习了凝聚聚类,特别是单连接算法。我们了解到:

- 凝聚聚类是一种从底部(单个点)开始,通过不断合并最相似簇来构建层次结构的聚类方法。
- 其核心是定义簇间距离,这依赖于距离函数(点与点之间)和连接函数(簇与簇之间)。
- 单连接算法使用最小点对距离作为簇间距离,并反复合并距离最近的两个簇。
- 与分裂聚类一样,凝聚聚类最终会生成一个在不同粒度上定义簇的层次结构,为我们理解数据提供了灵活性。
机器学习:分类、聚类与检索:3-4:树状图

在本节课中,我们将学习层次聚类结果的一种紧凑表示方法——树状图。我们将解释树状图在凝聚式聚类背景下的含义,并了解如何从中提取出我们想要的聚类划分。
树状图的结构与含义
上一节我们介绍了凝聚式聚类的基本过程,本节中我们来看看如何用一种直观的图形来展示这个过程的结果。
树状图的表示方法如下:沿着X轴,我们放置每一个数据点,但需要精心排序以获得清晰的视觉效果。沿着Y轴,我们表示的是不同聚类之间的距离。
更具体地说,当我们考虑单连接聚类(即查看任意一对聚类中点之间的最小距离)时,特定合并点的高度将代表那两个聚类之间的距离。让我们更详细地描述一下:如果我们观察一个给定的合并点,其下方有两棵独立的子树,每一棵子树代表一个不同的聚类。
在这个例子中,我们有这个蓝色聚类,所有标为蓝色的点都是在算法某次迭代中被分配到该蓝簇的数据点。同样,我们也有这个绿色聚类。然后,蓝色分支和绿色分支合并处的高度,表示的是蓝簇中任何点与绿簇中任何点之间的最小距离。这个最小距离就是我们将蓝色分支与绿色分支合并时放置的位置,它指定了沿Y轴的高度。
因此,在整个树状图中,我们可以看到算法从每个数据点自成一簇开始,到所有数据点合并为一簇结束的过程中,存在的不同聚类以及这些聚类在合并时的距离。
同样,如果我们沿着树状图向下看任何一条路径,它指示的是一个给定数据点在所有不同合并步骤中的簇成员关系,即该数据点属于哪个簇,以及这些簇合并的顺序。
总而言之,我们看到树状图能够捕捉层次聚类结果的所有关键要素:不同的簇成员关系是什么,哪些簇与哪些簇合并,以及它们在合并时彼此之间的距离是多少。
从树状图中提取聚类划分
从树状图中我们可以做的一件重要事情是提取一个划分。请记住,如果我们从头到尾运行凝聚式聚类,我们是从所有数据点各自为簇开始,到所有数据点合并为一簇结束。而我们真正想要的是产生一个介于两者之间的数据点聚类,既不是每个点自成一簇的精细粒度,也不是所有点聚为一簇的粗糙粒度。
这就引出了一个问题:我们如何从这个层次聚类过程中提取一个划分?如何定义一组要生成的聚类?
一个非常简单的方法是沿着树状图的Y轴进行切割。
以下是具体做法:
- 我们选择一个距离阈值
d*。 - 在树状图上画一条高度为
d*的水平线。 - 每一个与该水平线相交的独立分支,就定义了一个单独的聚类。
在这个例子中,我们看到有品红色、蓝色、绿色、橙色和灰色这几个聚类。但请记住,在这个可视化中,每个数据点只是代表我们数据中不同的索引。我们可以做的是回到原始的特征空间,可视化生成的聚类看起来是什么样子。如果我们的数据像之前所有例子一样是二维的(得益于我们方便的二维幻灯片表示),那么这可能是与我们在上一张幻灯片上展示的切割相对应的聚类结果。
当我们考虑改变这个切割点的位置时,我们就在查看不同粒度下数据的不同可能聚类,从非常精细的粒度一直到非常粗糙的粒度。
切割深度的意义
让我们花点时间思考一下在某个水平 d* 处切割树状图意味着什么。
这意味着,对于这次切割产生的聚类结果,不存在距离小于 d* 但尚未合并的聚类对。也就是说,d* 是在这个聚类层次上,我们各聚类之间的最小距离。
总结

本节课中,我们一起学习了树状图。我们了解到树状图是层次聚类结果的一种紧凑而强大的可视化表示。它沿X轴显示数据点,沿Y轴显示聚类合并时的距离。通过沿着Y轴在特定高度进行“切割”,我们可以从完整的层次结构中提取出具有特定粒度的扁平化聚类划分。这种方法允许我们在单一框架下探索数据在不同尺度下的聚类结构。
机器学习:3-4:凝聚聚类细节 🧩

在本节课中,我们将深入探讨凝聚聚类的具体细节。我们将了解在应用此方法时需要做出的关键选择,以及这些选择如何影响最终的聚类结果。
聚类中的关键选择
上一节我们介绍了凝聚聚类的基本流程,本节中我们来看看在具体实施时需要做出的几个核心决策。
以下是凝聚聚类中必须做出的两个主要选择:
- 距离度量:用于计算数据点之间成对距离的公式。例如,欧几里得距离公式为
dist = sqrt((x2-x1)^2 + (y2-y1)^2)。 - 连接函数:用于计算两个簇之间距离的函数。例如,单连接函数定义为两个簇中任意两点之间的最小距离。
如何切割树状图
确定了距离和连接方式后,下一个关键步骤是决定如何切割生成的树状图以获得最终的簇划分。
切割树状图并非只能进行简单的水平切割,我们可以根据数据结构和应用目标进行更复杂的切割。这通常是凝聚聚类中需要结合领域知识的环节。
以下是几种常见的切割策略:
- 基于任务目标:如果目标是数据可视化,通常倾向于生成少量簇,这决定了切割的高度。
- 基于距离阈值:与上一节描述的方法相同,设定一个距离阈值,在树状图中进行水平切割。
- 基于不一致系数:这是一种更复杂的方法。它比较某个合并点的高度与其下方合并的平均高度。如果该高度远高于平均值,则表明此次合并将两个相距很远的簇结合在了一起,这可能是一个理想的切割点。
为了更直观地理解,假设我们有两组内部点距非常小的紧密簇。如果仅基于固定阈值切割,可能会将它们过早地合并。而通过分析合并高度,我们可以识别出这个“大跨度”的合并,从而将这两个紧密簇保持为独立的簇。


需要明确的是,没有一种切割方法是绝对正确的。最终得到的簇集合对切割方式非常敏感,不同的切割会产生截然不同的聚类结果。因此,凝聚聚类也可以被视为一种通过调整阈值或切割方式来探索多种可能聚类方案的工具。
其他重要考量
除了上述选择,应用凝聚聚类时还需考虑计算效率和连接函数带来的影响。
在计算方面,凝聚聚类需要计算所有点对之间的距离,计算成本很高。暴力算法的复杂度约为 O(n² log n),其中 n 是数据点数。虽然可以使用类似KD树和三角不等式等技术优化,但最佳算法的复杂度仍为 O(n²),对于大规模数据依然颇具挑战。
在连接函数方面,单连接可能导致“链式效应”。即当存在一系列点距很小的点时,它们会逐步合并,最终形成一个包含相距很远的成员的细长簇,这在许多应用中并不理想。
为了解决链式问题,可以考虑使用其他连接函数:
- 完全连接:计算两个簇中任意两点之间的最大距离。在上述链式例子中,最大距离会很大,从而阻止合并。
- 沃德准则:关注合并后簇内点的方差增加量,旨在生成方差最小的紧凑簇。
然而,这些替代的连接函数本质上会对簇的形状施加隐含限制(例如,倾向于生成更紧凑的球形簇),这可能排除掉数据中实际存在的其他有效簇形状。因此,每种选择都有其含义,需要根据具体问题仔细权衡。
总结

本节课中我们一起学习了凝聚聚类的关键细节。我们了解到,实施凝聚聚类需要仔细选择距离度量和连接函数,并巧妙地切割树状图以获得有意义的簇。虽然存在计算成本高和参数选择敏感等挑战,但凝聚聚类能够提供多粒度的、描述性强的聚类结果,是一种非常强大的无监督学习方法。
机器学习(分类,聚类和检索):第3-4课:隐马尔可夫模型 🐝


在本节课中,我们将要学习一种专门用于处理时间序列数据的聚类模型——隐马尔可夫模型。我们将了解它如何利用数据点之间的时间顺序信息,来发现数据中随时间变化的动态状态或“簇”。
时间序列中的聚类挑战
上一节我们介绍了不考虑数据顺序的聚类方法。本节中我们来看看当数据点顺序至关重要时的情况,例如在时间序列分析中。
在之前讨论的聚类方法中,每个数据点的索引(如其在数据集中的位置)对最终的聚类结果没有影响。这意味着我们可以随意打乱所有数据的顺序,聚类结果将保持不变。
然而,在时间序列数据中,每个数据点关联的时间戳对于分析至关重要。例如,下图展示了一个单变量时间序列,Y轴是观测值,X轴是时间戳。

我们的目标可能是将这段序列解析为不同的“动态状态”,可以将其理解为随时间出现在数据集中的不同“簇”。图中可能包含绿色、蓝色和红色三种状态,时间序列在这些状态之间切换。
如果我们忽略这些数据点的时间戳,将所有数据点压缩到Y轴上进行一维聚类,将会非常困难。因为时间序列处于绿色状态时的取值范围,与处于蓝色和红色状态时的取值范围有很大重叠。如果没有海量数据,很难区分出这里存在三个不同的簇。
相反,数据在时间上的结构可以帮助我们揭示这种模式。具体来说,数据中存在这样的规律:如果当前处于绿色状态,那么下一时刻很可能继续保持绿色状态;同时,某些状态间的转换(如从绿到蓝或从蓝到红)可能比其他转换更有可能发生。这类信息可以帮助我们从时间序列数据中提取出期望的聚类结构。
在时间序列的背景下,我们可以将此视为一个分割任务。
具体应用:蜜蜂舞蹈分析
为了使概念更具体,让我们观察蜜蜂的舞蹈。当蜜蜂在蜂巢内时,它会在三种不同的舞蹈之间切换,以向其他蜜蜂传达食物源的位置。这三种舞蹈分别是:摇摆舞(红色)、右转舞(绿色)和左转舞(蓝色)。蜜蜂会不断重复这些舞蹈的特定模式来与其他蜜蜂交流。
下图展示了被分割成三种舞蹈的三段不同舞蹈序列。

问题是,我们能否仅通过观察蜜蜂在蜂巢内移动时的身体位置和头部角度,来自动提取出这些信息?
具体来说,当我们观察这些舞蹈时,可以绘制出蜜蜂在每个时间步处于哪种舞蹈的图表。这将显示出特定舞蹈的持续性以及它们之间的切换(摇摆舞、右转舞、左转舞)。
从这种状态图中,我们确实能看到一些模式:不同舞蹈具有持续性(如果你正在跳一种舞蹈,很可能继续跳这种舞蹈);同时,某些状态转换比其他转换更有可能发生。例如,如果当前处于红色舞蹈状态,那么下一时刻很可能切换到绿色舞蹈状态,或者从绿色舞蹈切换到红色舞蹈。当然,其他转换也是可能的。
这种在不同动态状态之间切换的概念出现在许多不同的应用中,而不仅仅是研究蜜蜂。
以下是几个例子:
- 会议音频分割:在会议中,人们轮流发言,我们希望将音频分割成会议期间谁在何时发言。
- 运动动作识别:观察一个人进行一系列锻炼,我们希望分割出这个人是在做开合跳、跑步还是深蹲等。通常,当人们进行不同的锻炼时,他们会反复在一组行为之间切换。
- 股票数据分析:这是一种非常常见的方法,用于分析股票数据,其中股票指数可能在“高波动性”、“低波动性”或“中等波动性”等不同状态之间切换。
隐马尔可夫模型简介
鉴于这种结构在广泛的应用中出现,让我们花点时间讨论一个可以从数据中提取此类信息的模型,这个模型被称为隐马尔可夫模型,简称 HMM。
HMM 与我们之前在本课程中描述的混合模型非常相似。
与混合模型一样,HMM 中的每个观测值都与一个簇指示器(或称为状态)相关联。在讨论 HMM 时,通常将“簇”描述为“状态”,即我们之前提到的动态状态。这里我们将交替使用这两个术语,以便与我们之前描述的混合模型建立联系。关键点是,每个观测值都有一个与之关联的簇分配,但这个分配对我们来说是未知的,我们只能得到观测值本身。
同样,与混合模型类似,HMM 中的每个簇或状态都有一个定义在观测值上的分布。回想一下,在我们的混合模型中,每个混合成分可能是一个高斯分布,定义了图像中蓝色强度的分布,并且这个分布在云、日落和森林的图像中是不同的。在 HMM 中,我们有不同的动态状态,但给定一个特定的状态或簇分配,我们在该状态内的观测值上也有相同类型的分布。
然而,一个关键的区别在于:在 HMM 中,给定观测点的簇分配概率,取决于前一个观测点的簇分配值。正是通过这种方式,我们捕捉到了时间依赖性。我们通过簇分配变量在时间上的这种依赖结构,来提取这种与时间相关的聚类信息。
例如,这可以捕捉到这样的事实:如果我们当前处于摇摆舞状态,那么下一时刻更有可能保持在该状态;或者如果我们当前处于红色状态,那么下一时刻切换到绿色状态的可能性,比切换到蓝色状态的可能性更大。
HMM 的推理算法
最后,HMM 拥有非常巧妙的推理算法,这些算法建立在我们为混合模型描述的方法之上,但增加了处理簇分配变量时间依赖性的挑战。
以下是 HMM 中常用的算法:
- 鲍姆-韦尔奇算法:你可以使用一种非常类似于混合模型中所讨论的 EM 算法,来计算 HMM 参数的最大似然估计。在这个背景下,由于历史原因,它被称为鲍姆-韦尔奇算法。它最初是为 HMM 独立开发的,后来才与期望最大化算法建立了联系。
- 维特比算法:在 HMM 中,你还可以在给定模型参数的情况下,计算最可能的状态序列(即最可能的簇分配序列)。为此,你可以使用维特比算法,它是动态规划的一个例子,允许你高效地在状态集合上进行搜索。
- 前向-后向算法:你还可以使用动态规划,通过前向-后向算法来形成簇变量的软分配。这些软分配在鲍姆-韦尔奇算法中扮演着角色,就像软分配在我们课程早期描述的标准混合模型 EM 算法中扮演的角色一样。
总结
在本节课中,我们一起学习了隐马尔可夫模型。我们了解到,HMM 是一种专门用于时间序列数据的聚类模型,它通过引入状态间的转移概率来捕捉数据在时间上的依赖关系。我们探讨了其核心思想,即当前状态的概率依赖于前一个状态,这使得 HMM 能够识别数据中随时间变化的动态模式。我们还简要介绍了 HMM 相关的关键推理算法,如鲍姆-韦尔奇算法、维特比算法和前向-后向算法。
通过 HMM 这个例子,我们可以看到,本课程中学到的方法为学习机器学习中其他非常重要的算法奠定了非常坚实的基础。




机器学习(分类,聚类和检索):第3-4课:未涵盖内容概览

在本节课中,我们将回顾并总结课程中未详细涵盖的一些重要主题。我们已经学习了聚类、检索等核心方法,但机器学习领域广阔,仍有许多其他有价值的工具和概念。本节将简要介绍这些未涵盖的主题,帮助你了解更广阔的知识领域,并为后续学习指明方向。
检索中的其他距离度量
上一节我们介绍了聚类方法,本节中我们来看看检索领域的一些扩展内容。在检索模块中,我们提到了多种距离度量,但并未深入探讨其细节。

以下是课程中列出但未详细描述的其他距离度量示例:
- 马氏距离
- 余弦相似度
- 杰卡德相似系数
距离度量学习
除了预定义的距离度量,还存在一种称为距离度量学习的技术。这类方法允许算法根据手头的具体任务,自动学习出最有效的距离度量公式。
非参数化聚类与谱聚类
在聚类部分,我们主要讨论了K-Means和层次聚类等方法。我们未涵盖非参数化聚类。虽然层次聚类方法可以用于非参数化场景,但我们没有明确阐述这一点。非参数化聚类是指模型的复杂度或聚类的描述能力可以随着数据点的增加而增长的方法。
另一种重要的方法是谱聚类。该方法对于处理不同形状的簇(例如我们在第二模块中展示的瑞士卷型数据)可能更加鲁棒。谱聚类方法通常不具备良好的大规模数据集可扩展性。
密度估计与异常检测
还有一些概念与我们讨论的内容相关,但并非专门针对检索或聚类。例如,高斯混合模型常被用于密度估计。
我们可以将数据集中所有图像的蓝色强度直方图视为强度的密度分布,并尝试显式地估计该密度的形式,而不仅仅是将高斯混合模型视为数据点聚类的手段。它们是同一工具,服务于不同任务。
在密度估计的框架下,可以进一步探讨异常检测。其核心问题是:给定一个新的数据点,判断它是否与已观测到的数据点存在显著差异。
总结

本节课中我们一起学习了本课程未涵盖的一些机器学习主题,包括检索中的其他距离度量、距离度量学习、非参数化与谱聚类,以及密度估计和异常检测等相关概念。尽管课程内容有限,但你所掌握的工具和知识足以支持你进一步探索和学习这些更高级的方法。
机器学习(分类,聚类和检索):第3-4课:课程总结与展望 🎓

在本节课中,我们将对华盛顿大学《机器学习(分类,聚类和检索)》第3-4课的核心内容进行总结,并展望后续的学习方向。课程重点回顾了聚类与检索的关键方法,并强调了将这些方法扩展到大型数据集的重要性。
上一节我们介绍了课程的核心内容,本节中我们来看看具体的总结与未来展望。
卡洛斯提到了一个重要事实:在课程中,大家不仅学习了算法、模型和方法,还掌握了如何将这些方法扩展到真正的大型数据集。😊
以下是课程中涵盖的关键技术要点:
- 这些技术被广泛应用于当今大多数应用中。
- 应用范围从网页文档检索,一直到处理手机、手表等各类设备上的图像。
卡洛斯与另一位对话者进行了简短的互动,后者提到自己是一个“设备重度使用者”。这引出了课程的关键价值所在:学习者并非只掌握了最基础的知识。
以下是课程中涉及的高级概念:
- 学习了如何通过诸如 Kd树 和 局部敏感哈希(LSH) 等技术扩展到大型数据集。
- 这些是非常酷且在实践中、在现实世界中超级有用的技术。
- 潜在狄利克雷分配(LDA) 也相当不错。
总之,这些是非常高级的概念,大家付出了大量的努力。在这个专业课程中,还有许多令人兴奋的内容有待探索。
因此,我们期待在下一门课程中与大家相见。欢迎大家加入后续课程的学习。😊

本节课中我们一起回顾了聚类与检索的核心方法,特别是扩展到大规模数据集的先进技术(如Kd树和LSH),并鼓励大家继续参与专业课程的后续学习。

浙公网安备 33010602011771号