<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>数据集、泛化与过拟合 - Google 机器学习速成课程配套中文解读 on 跟我学机器学习</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/</link><description>Recent content in 数据集、泛化与过拟合 - Google 机器学习速成课程配套中文解读 on 跟我学机器学习</description><generator>Hugo</generator><language>zh_CN</language><lastBuildDate>Wed, 28 Oct 2026 23:04:23 +0800</lastBuildDate><atom:link href="https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/index.xml" rel="self" type="application/rss+xml"/><item><title>数据集、泛化与过拟合：简介 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/introduction/</link><pubDate>Thu, 22 Oct 2026 16:59:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/introduction/</guid><description>&lt;h1 id="数据集泛化与过拟合简介"&gt;数据集、泛化与过拟合：简介&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e9%9b%86%e6%b3%9b%e5%8c%96%e4%b8%8e%e8%bf%87%e6%8b%9f%e5%90%88%e7%ae%80%e4%bb%8b"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;预计整个模块学习时长：&lt;/strong&gt; 105 分钟&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;学习目标：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;说出数据与数据集的四个不同特征。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;说出至少四种导致数据不可靠的成因。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;判断什么时候该丢弃缺失数据、什么时候该插补。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;区分直接标签与派生标签。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;说出两种提升人工评分标签质量的做法。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解释为什么要把数据集拆成训练集、验证集和测试集，并指出数据划分中一个潜在问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解释过拟合，并说出它的三种可能成因。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解释正则化的概念，具体包括：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;偏差与方差（对离群值的过度适应……）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$L_2$ 正则化，包括 Lambda（正则化系数）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;早停（Early stopping）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解读不同类型的损失曲线；在损失曲线中识别收敛与过拟合。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;blockquote class='book-hint caution'&gt;
&lt;p&gt;&lt;strong&gt;先修要求：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本模块假设你已经熟悉以下模块中介绍的概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/ml/chapter04/generalization-basics/"&gt;机器学习简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/ml/linear-regression/"&gt;线性回归&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/numerical-data/"&gt;处理数值数据&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/categorical-data/"&gt;处理类别型数据&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;p&gt;这一讲要从两个问题开始——不妨先动手选一选，选完再看解析。&lt;/p&gt;
&lt;h2 id="先回答第一个问题"&gt;先回答第一个问题&lt;a class="anchor" href="#%e5%85%88%e5%9b%9e%e7%ad%94%e7%ac%ac%e4%b8%80%e4%b8%aa%e9%97%ae%e9%a2%98"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;假如在你的机器学习项目里，只能挑一个方向优先改进，下面哪一个影响最大？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;改进数据集的质量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;给模型训练换用更聪明的损失函数&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;details class="example-disclosure" style="margin-top: 1rem;"&gt;
&lt;summary style="cursor:pointer;font-weight:600;"&gt;点击查看答案&lt;/summary&gt;
&lt;div style="margin-top: 1rem;"&gt;
&lt;span style="color: blue;"&gt;
&lt;p&gt;改进数据集的质量。 因为数据胜过一切。数据集的质量和规模，比你用哪个光鲜亮丽的算法来建模，要重要得多。&lt;/p&gt;
&lt;/span&gt;
&lt;span style="color: brown;"&gt;
&lt;p&gt;尽管改进损失函数确实有帮助，因为一个更好的损失函数能让模型训练得更快，但在这张清单上，它只能排在很靠后的位置。&lt;/p&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;h2 id="再来一个更有引导性的问题"&gt;再来一个更有引导性的问题&lt;a class="anchor" href="#%e5%86%8d%e6%9d%a5%e4%b8%80%e4%b8%aa%e6%9b%b4%e6%9c%89%e5%bc%95%e5%af%bc%e6%80%a7%e7%9a%84%e9%97%ae%e9%a2%98"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;凭直觉猜一猜：在你的机器学习项目里，通常要花多少时间在数据准备与转换上？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;超过项目时间的一半&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;不到项目时间的一半&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;details class="example-disclosure" style="margin-top: 1rem;"&gt;
&lt;summary style="cursor:pointer;font-weight:600;"&gt;点击查看答案&lt;/summary&gt;
&lt;div style="margin-top: 1rem;"&gt;
&lt;span style="color: blue;"&gt;
&lt;p&gt;超过项目时间的一半 。是的，机器学习从业者把大部分时间都花在构建数据集和做特征工程上。&lt;/p&gt;
&lt;/span&gt;
&lt;span style="color: brown;"&gt;
&lt;p&gt;不到项目时间的一半，这个预期需要往后调。通常，一个机器学习项目里，通常有 80% 的时间花在构建数据集和转换数据上。&lt;/p&gt;
&lt;/span&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;两个问题指向同一个答案。这一模块里，你将学到更多关于机器学习数据集自身有哪些特征、以及怎样准备数据，才能确保在训练和评估模型时拿到高质量的结果。&lt;/p&gt;</description></item><item><title>数据集：数据的特征 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/data-characteristics/</link><pubDate>Thu, 22 Oct 2026 17:15:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/data-characteristics/</guid><description>&lt;h1 id="数据集数据的特征"&gt;数据集：数据的特征&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e9%9b%86%e6%95%b0%e6%8d%ae%e7%9a%84%e7%89%b9%e5%be%81"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;一个数据集，本质上就是一批样本的集合。&lt;/p&gt;
&lt;p&gt;很多数据集会把数据存成表格（网格），即 $m$ 行样本 $n$ 列特征，比如逗号分隔的 CSV 文件，或者直接来自电子表格与数据库表。表格对机器学习模型来说是一种相当直观的输入格式：你可以把表格的每一行想成一个样本，每一列想成一个候选特征或标签。当然，数据集也可能来自其他形式，比如日志文件和 protocol buffer。&lt;/p&gt;
&lt;p&gt;不管格式如何，模型的能力上限都不会超过它所训练的那份数据。这一节就来看看数据有哪几个关键特征。&lt;/p&gt;
&lt;h2 id="数据的类型"&gt;数据的类型&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e7%9a%84%e7%b1%bb%e5%9e%8b"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;一个数据集里可能装着各种各样的数据类型，包括但不限于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;数值型数据，课程中有一个 &lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/numerical-data/"&gt;单独的小节&lt;/a&gt;专门讲它&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;类别型数据，同样在 &lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/categorical-data/"&gt;单独的小节&lt;/a&gt;里展开&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;人类语言，从单个词语、单句话，一直到整篇文本&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;多媒体，比如图像、视频和音频文件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;其他 ML 系统的输出&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;嵌入向量，课程后面会有专门的小节介绍&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="数据的数量"&gt;数据的数量&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e7%9a%84%e6%95%b0%e9%87%8f"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;作为一条粗略的经验法则：模型可训练的参数有多少，样本数就至少要比它多一个数量级（最好两个）。不过实际情况是，好的模型往往用的样本远不止这个数。&lt;/p&gt;
&lt;p&gt;在特征很少的大数据集上训练出来的模型，通常要优于在特征很多的小数据集上训练出来的模型。Google 长期以来就深谙此道——&lt;strong&gt;用简单的模型去喂海量的数据，往往能取得很好的效果&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;不同的机器学习项目，需要的样本量可能相差得极其悬殊。有些相对简单的问题，几十个样本或许就够了；而另一些问题，一万亿个样本都可能不够用。&lt;/p&gt;
&lt;p&gt;不过，如果你是在一个现成的模型上做微调，而且这个模型此前已经用同一套结构的海量数据训练过，那么小数据集也可能训出好结果。&lt;/p&gt;
&lt;h2 id="数据的质量与可靠性"&gt;数据的质量与可靠性&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e7%9a%84%e8%b4%a8%e9%87%8f%e4%b8%8e%e5%8f%af%e9%9d%a0%e6%80%a7"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;人人都更喜欢高质量的数据，但「质量」这个概念实在太模糊了，可以被定义出无数种版本。课程在这里采用了一个务实的定义：&lt;/p&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;高质量的数据集，能帮助模型达成它的目标。&lt;/p&gt;
&lt;p&gt;低质量的数据集，会妨碍模型达成它的目标。&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;高质量的数据集通常也是可靠的。&lt;strong&gt;可靠性&lt;/strong&gt;指的是你能在多大程度上信任这份数据。用可靠数据训练出来的模型，比用不可靠数据训练出来的模型更有可能给出有用的预测。&lt;/p&gt;
&lt;p&gt;要衡量可靠性，你需要弄清楚三件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;标签错误的普遍程度有多大？比如，如果你的数据是人工标注的，人工标注者犯错的比例有多高？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;你的特征是否有噪声？也就是说，特征里的数值本身是否含有错误？要现实一点——你不可能把数据集里的噪声全部清除干净。有些噪声是正常的；比如，任何位置的 GPS 测量值都会随时间有微小的波动。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数据是否针对你的问题做了恰当的筛选？比如，你的数据集里该不该包含来自爬虫的搜索查询？如果你在做垃圾邮件检测系统，那答案很可能是「该包含」；但如果你想改进的是面向真人的搜索结果，那就「不该包含」。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下几种情况，是数据不可靠的常见成因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;值缺失。比如，某个人忘了填写房屋的年龄。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;样本重复。比如，服务器误把同一批日志上传了两次。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;特征值有误。比如，有人多敲了一个数字，或者温度计被落在了太阳底下。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;标签有误。比如，有人把一张橡树的照片错标成了枫树。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数据中某一段整体有问题。比如，某个特征一向都很可靠，唯独网络持续崩溃的那一天出了岔子。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们建议用自动化手段来标记不可靠的数据。例如，依赖外部正式数据结构信息的单元测试，就能把落在定义范围之外的值标出来。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;注意：&lt;/strong&gt; 任何足够大、足够多样的数据集，几乎必然包含落在你的数据结构信息或单元测试区间之外的异常值。如何处理这些异常值，本身就是机器学习的一道重要课题。&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/numerical-data/"&gt;数值型数据小节&lt;/a&gt;里详细讲了该怎么对付数值型异常值。&lt;/p&gt;&lt;/blockquote&gt;&lt;h2 id="完整样本与不完整样本"&gt;完整样本与不完整样本&lt;a class="anchor" href="#%e5%ae%8c%e6%95%b4%e6%a0%b7%e6%9c%ac%e4%b8%8e%e4%b8%8d%e5%ae%8c%e6%95%b4%e6%a0%b7%e6%9c%ac"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;理想情况下，每个样本都是完整的，也就是说每个样本的每个特征都有值。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="700" src="https://machinelearningwithme.com/images/course/complete_example.svg" alt="图 1. 一个样本，它五个特征全部都有取值。"/&gt; &lt;/div&gt;&lt;center&gt;图 1. 一个完整的样本&lt;/center&gt;
&lt;p&gt;遗憾的是，现实中的样本经常是不完整的，也就是至少有一个特征值缺失。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="700" src="https://machinelearningwithme.com/images/course/incomplete_example.svg" alt="图 2. 一个样本，五个特征里有四个有取值，剩下一个特征被标记为缺失。"/&gt; &lt;/div&gt;&lt;center&gt;图 2. 一个不完整的样本&lt;/center&gt;
&lt;p&gt;不要拿不完整的样本去训练模型。相反，应该用下面两种方式之一把它们修复或者剔除掉：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;删除不完整的样本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;插补缺失值，也就是为那些缺失的值提供有依据的猜测，把不完整样本补成一个完整样本。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;MLWM：&lt;/strong&gt; 最简单的插值策略可以说最值、最大值、最小值等方法。&lt;/p&gt;</description></item><item><title>数据集：标签 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/labels/</link><pubDate>Sun, 25 Oct 2026 12:17:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/labels/</guid><description>&lt;h1 id="数据集标签"&gt;数据集：标签&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e9%9b%86%e6%a0%87%e7%ad%be"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;这一节，我们将聚焦于数据集中的「标签」。&lt;/p&gt;
&lt;h2 id="直接标签与派生标签"&gt;直接标签与派生标签&lt;a class="anchor" href="#%e7%9b%b4%e6%8e%a5%e6%a0%87%e7%ad%be%e4%b8%8e%e6%b4%be%e7%94%9f%e6%a0%87%e7%ad%be"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;先把两种不同类型的标签摆在一起看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;直接标签&lt;/strong&gt;，指的是与模型想要做的预测完全一致的那个标签。也就是说，模型要预测的东西，在你的数据集里原封不动地就躺着某一列。举个例子，一列叫 &lt;code&gt;bicycle owner&lt;/code&gt; 的数据，对于一个「判断某人是否拥有自行车」的二分类模型来说，就是一个直接标签。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;派生标签&lt;/strong&gt;，指的是与模型想要做的预测相似，但并不相同——的标签。比如，一个人订阅了《Bicycle Bizarre》杂志，那他多半——但不一定——拥有自行车。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一般来说，直接标签要优于派生标签。如果你的数据集里提供了可行的直接标签，那大概就该用它。只是很多时候，直接标签并不存在。&lt;/p&gt;
&lt;p&gt;派生标签永远是一种妥协——它是对直接标签的不完美近似。但也有不少派生标签近似得足够接近，照样能派上用场。用派生标签的模型，其效用上限就取决于派生标签与最终预测之间的关联到底有多紧密。&lt;/p&gt;
&lt;p&gt;同时，别忘了每个标签都必须要表示成一个浮点数，这跟 &lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/numerical-data/feature-vectors/"&gt;&lt;strong&gt;特征向量&lt;/strong&gt;&lt;/a&gt; 的情况是一样的（毕竟机器学习本质上就是一堆数学运算）。有时候，直接标签确实存在，却很难表示成一个浮点数——那就退一步，用派生标签。&lt;/p&gt;
&lt;h3 id="练习检验你的理解"&gt;练习：检验你的理解&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a0%e6%a3%80%e9%aa%8c%e4%bd%a0%e7%9a%84%e7%90%86%e8%a7%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;下面，我们再通过几个示例来理解一下。你的公司想做这样一件事：&lt;/p&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;给自行车车主邮寄优惠券（「购买自行车头盔立享 15% 折扣）。&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;那么，模型要做的就变成了：&lt;/p&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;预测出哪些人拥有自行车。&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;可惜的是，数据集里并没有一列叫 &lt;code&gt;bike owner&lt;/code&gt;。不过倒是有那么一列，叫 &lt;code&gt;recently bought a bicycle&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;那么，&lt;code&gt;recently bought a bicycle&lt;/code&gt; 对这个模型来说，是一个好的派生标签，还是一个差的派生标签？&lt;/p&gt;

&lt;span class="subscription-widget subscription-widget--content"
 data-subscription-widget
 data-resource-id="b90d6d7300914392"
 data-resource-text="点击查看答案及分析"
 data-resource-plan="basic"
 data-resource-color="blue"
 data-resource-align="left"
 data-resource-type="content"&gt;
 &lt;button type="button" class="subscription-btn subscription-btn--content" data-subscription-trigger data-type="content" style="font-size: 0.9em;" aria-busy="false"&gt;
 &lt;span class="subscription-btn__text"&gt;点击查看答案及分析&lt;/span&gt;
 &lt;/button&gt;
 &lt;span class="subscription-result" data-subscription-result hidden role="status" aria-live="polite"&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;script&gt;
(function () {
 var script = document.currentScript;
 var widget = script &amp;&amp; script.previousElementSibling;
 if (!widget || !widget.matches || !widget.matches('[data-subscription-widget]')) return;

 var trigger = widget.querySelector('[data-subscription-trigger]');
 var result = widget.querySelector('[data-subscription-result]');
 var icon = trigger.querySelector('.subscription-btn__icon');
 var textEl = trigger.querySelector('.subscription-btn__text');
 
 var originalIcon = icon ? icon.textContent : '';
 var originalText = textEl.textContent;
 var resourceId = widget.dataset.resourceId;
 var planHint = widget.dataset.resourcePlan || '';

 
 
 
 
 
 
 function applyContentStyle() {
 var S = window.MLWM_SUB_STYLE;
 if (S &amp;&amp; typeof S.apply === 'function') {
 S.apply(widget, widget.dataset.resourceColor, widget.dataset.resourceAlign);
 }
 }
 
 
 
 
 
 
 
 
 
 function notifyToggle(expanded) {
 document.dispatchEvent(new CustomEvent('mlwm:subscription-toggle', {
 detail: { resourceId: resourceId, expanded: !!expanded }
 }));
 }

 
 
 
 
 
 
 if (document.readyState === 'loading') {
 document.addEventListener('DOMContentLoaded', applyContentStyle, { once: true });
 } else {
 applyContentStyle();
 }

 
 
 var cached = null;
 var inflight = null;

 
 
 function resolveApiUrl(path) {
 if (window.__ML_API &amp;&amp; typeof window.__ML_API === 'function') return window.__ML_API(path);
 return path;
 }

 function isLoggedIn() {
 return document.documentElement.getAttribute('data-mlwm-auth') === 'in';
 }
 function getToken() {
 try { return localStorage.getItem('mlwm_auth_access') || ''; } catch (_) { return ''; }
 }
 function showLoginModal(opts) {
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.openLoginModal === 'function') {
 window.MLWM_AUTH.openLoginModal(Object.assign({ mode: 'login' }, opts || {}));
 } else {
 window.location.assign('/login/');
 }
 }
 function showToast(msg, type) {
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.showToast === 'function') {
 window.MLWM_AUTH.showToast(msg, type || 'warning');
 }
 }
 function setBusy(busy) {
 trigger.disabled = !!busy;
 trigger.setAttribute('aria-busy', busy ? 'true' : 'false');
 textEl.textContent = busy ? '加载中...' : originalText;
 }
 function clearResult() {
 result.hidden = true;
 result.innerHTML = '';
 delete result.dataset.kind;
 textEl.textContent = originalText;
 trigger.style.display = '';
 }
 function setResult(html, kind) {
 applyContentStyle();
 result.hidden = false;
 result.innerHTML = html;
 result.dataset.kind = kind || 'info';
 }
 function escapeHtml(s) {
 return String(s == null ? '' : s).replace(/[&amp;&lt;&gt;"']/g, function (c) {
 return { '&amp;': '&amp;amp;', '&lt;': '&amp;lt;', '&gt;': '&amp;gt;', '"': '&amp;quot;', "'": '&amp;#39;' }[c];
 });
 }

 
 
 
 
 
 
 
 function renderMarkdown(text) {
 var src = String(text == null ? '' : text);
 if (window.MLWM_MARKED_MD &amp;&amp; typeof window.MLWM_MARKED_MD.render === 'function') {
 var html = window.MLWM_MARKED_MD.render(src);
 if (typeof html === 'string') return html;
 }
 if (typeof marked !== 'undefined' &amp;&amp; typeof marked.parse === 'function') {
 return marked.parse(src);
 }
 return escapeHtml(src);
 }

 
 function isExpanded() { return widget.classList.contains('is-expanded'); }
 function isPinned() { return widget.classList.contains('is-pinned'); }
 function pin() { widget.classList.add('is-pinned'); }
 function unpin() { widget.classList.remove('is-pinned'); }

 function renderContentBox(data) {
 var html =
 '&lt;div class="subscription-content__title"&gt;' +
 '&lt;span class="subscription-content__chevron" aria-hidden="true"&gt;&lt;/span&gt;' +
 '&lt;span class="subscription-content__title-text"&gt;' + escapeHtml(originalText) + '&lt;/span&gt;' +
 '&lt;/div&gt;' +
 '&lt;div class="subscription-content__body"&gt;' + renderMarkdown(data.body) + '&lt;/div&gt;';
 trigger.style.display = 'none';
 setResult(html, 'content');
 widget.classList.add('is-expanded');
 notifyToggle(true);
 
 
 
 if (typeof window.renderMathInElement === 'function') {
 try {
 window.renderMathInElement(result, {
 throwOnError: false,
 delimiters: [
 { left: '$$', right: '$$', display: true },
 { left: '$', right: '$', display: false },
 { left: '\\(', right: '\\)', display: false },
 { left: '\\[', right: '\\]', display: true }
 ]
 });
 } catch (_) { }
 }
 }
 function hideContentBox() {
 trigger.style.display = '';
 clearResult();
 widget.classList.remove('is-expanded');
 unpin();
 notifyToggle(false);
 }

 function renderDenied(body) {
 var detail = body.detail || {};
 
 var requiredPlan = detail.required_plan || planHint || 'pro';
 
 var currentPlan = (detail.current_plan || '').toString().trim();
 var hasCurrent = !!currentPlan;
 
 var title = hasCurrent ? '订阅等级不足' : '尚未订阅';
 
 var bodyText = hasCurrent
 ? '当前订阅为 ' + escapeHtml(currentPlan) + '，获取该资源至少需订阅 ' + escapeHtml(requiredPlan) + ' 套餐。'
 : '当前未订阅，获取该资源至少需订阅 ' + escapeHtml(requiredPlan) + ' 套餐。';
 
 
 result.hidden = true;
 result.innerHTML = '';
 delete result.dataset.kind;
 trigger.style.display = '';
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.openDeniedModal === 'function') {
 window.MLWM_AUTH.openDeniedModal({
 title: title,
 body: bodyText,
 ctaText: '订阅方案',
 ctaHref: '/pricing/'
 });
 } else {
 
 window.location.assign('/pricing/');
 }
 }
 function renderDownload(data) {
 
 
 showToast('已触发下载: ' + (data.title || data.url || ''), 'success');
 var a = document.createElement('a');
 a.href = data.url;
 a.rel = 'noopener noreferrer';
 a.download = '';
 a.style.display = 'none';
 document.body.appendChild(a);
 a.click();
 document.body.removeChild(a);
 }
 function renderError(msg) {
 setResult('&lt;div class="subscription-error"&gt;' + escapeHtml(msg || '请求失败,请稍后再试') + '&lt;/div&gt;', 'error');
 }

 
 
 
 
 
 
 
 
 
 
 function fetchResource() {
 if (cached) return Promise.resolve({ ok: true, data: cached });
 if (inflight) return inflight;

 if (!isLoggedIn()) {
 return Promise.resolve({ ok: false, reason: 'not-logged-in', status: 0, body: null });
 }
 var url = resolveApiUrl('/resource/' + encodeURIComponent(resourceId));
 inflight = fetch(url, {
 method: 'GET',
 headers: { 'Authorization': 'Bearer ' + getToken() }
 })
 .then(function (r) {
 return r.json().then(function (j) { return { status: r.status, body: j }; }).catch(function () { return { status: r.status, body: null }; });
 })
 .then(function (resp) {
 if (resp.status === 401) {
 return { ok: false, reason: 'unauthorized', status: 401, body: null };
 }
 var body = resp.body;
 if (!body || typeof body !== 'object') {
 return { ok: false, reason: 'bad-response', status: resp.status, body: body };
 }
 if (body.code === 2002) {
 return { ok: false, reason: 'denied', status: resp.status, body: body };
 }
 if (body.code === 0 &amp;&amp; body.data) {
 
 if (body.data.type === 'content') {
 cached = body.data;
 return { ok: true, data: cached };
 }
 if (body.data.type === 'download' &amp;&amp; body.data.url) {
 return { ok: true, data: body.data };
 }
 }
 return { ok: false, reason: 'api-error', status: resp.status, body: body };
 })
 .catch(function () {
 return { ok: false, reason: 'network', status: 0, body: null };
 });
 
 inflight.then(function () { inflight = null; }, function () { inflight = null; });
 return inflight;
 }

 
 
 function ensureContent() {
 setBusy(true);
 return fetchResource().then(function (result) {
 setBusy(false);
 if (result.ok) {
 if (result.data.type === 'content') {
 renderContentBox(result.data);
 pin();
 return result.data;
 }
 if (result.data.type === 'download') {
 renderDownload(result.data);
 return null;
 }
 return null;
 }
 if (result.reason === 'not-logged-in') {
 showLoginModal({ bannerMessage: '请先登录后再访问资源' });
 } else if (result.reason === 'unauthorized') {
 showLoginModal({ bannerMessage: '登录已过期,请重新登录' });
 } else if (result.reason === 'denied') {
 renderDenied(result.body);
 } else if (result.reason === 'bad-response') {
 renderError('响应异常');
 } else if (result.reason === 'api-error') {
 renderError((result.body &amp;&amp; result.body.msg) || ('请求失败 (code ' + ((result.body &amp;&amp; result.body.code) || '?') + ')'));
 } else if (result.reason === 'network') {
 renderError('网络异常,请稍后再试');
 }
 return null;
 });
 }

 
 
 
 
 trigger.addEventListener('click', function (e) {
 e.stopPropagation();
 if (isExpanded()) return;
 ensureContent();
 });

 
 result.addEventListener('click', function (e) {
 var titleEl = e.target.closest('.subscription-content__title');
 if (titleEl) hideContentBox();
 });

 
 
 
 

 
 
 
 
 
 
 widget.addEventListener('mlwm:subscription-prefetch', function () {
 
 
 
 
 widget._prefetchPromise = fetchResource().then(function () {}, function () {});
 });
})();
&lt;/script&gt;

&lt;h2 id="人工生成的数据"&gt;人工生成的数据&lt;a class="anchor" href="#%e4%ba%ba%e5%b7%a5%e7%94%9f%e6%88%90%e7%9a%84%e6%95%b0%e6%8d%ae"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;有些数据是人工生成的：由一个或多个人去检查某些信息，然后给出一个值，通常是标签。比如，一位或多位气象学家可以查看天空的照片，辨认出云的类型。&lt;/p&gt;</description></item><item><title>数据集：类别不平衡的数据集 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/imbalanced-datasets/</link><pubDate>Sun, 25 Oct 2026 13:52:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/imbalanced-datasets/</guid><description>&lt;h1 id="数据集类别不平衡的数据集"&gt;数据集：类别不平衡的数据集&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e9%9b%86%e7%b1%bb%e5%88%ab%e4%b8%8d%e5%b9%b3%e8%a1%a1%e7%9a%84%e6%95%b0%e6%8d%ae%e9%9b%86"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;这一节的任务是回答下面三个问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;类别平衡的数据集和类别不平衡的数据集，差别到底在哪？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;为什么使用不平衡的数据集训练一个模型这么难？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;该怎么绕开不平衡数据集带来的种种麻烦？&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="类别平衡与类别不平衡数据集"&gt;类别平衡与类别不平衡数据集&lt;a class="anchor" href="#%e7%b1%bb%e5%88%ab%e5%b9%b3%e8%a1%a1%e4%b8%8e%e7%b1%bb%e5%88%ab%e4%b8%8d%e5%b9%b3%e8%a1%a1%e6%95%b0%e6%8d%ae%e9%9b%86"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;先从一个熟悉的数据集说起。假设某份数据的标签是&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/categorical-data/"&gt;类别型&lt;/a&gt;的，取值只有「正类」和「负类」两种。&lt;/p&gt;
&lt;p&gt;在这样一份数据中，如果正类和负类的数量大致相当——比如 235 个正类、247 个负类，此时我们就说它是一个类别平衡的数据集。&lt;/p&gt;
&lt;p&gt;而在类别不平衡的数据集里，一个标签的出现频率会明显压过另一个。但是在真实世界中，类别不平衡的数据集远比类别平衡的常见：在信用卡交易数据里，欺诈交易可能连 0.1% 都占不到；在医疗诊断数据里，患某种罕见病毒的病人占比可能不到 0.01%。&lt;/p&gt;
&lt;p&gt;在类别不平衡的数据集里：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;出现更多的那个标签，叫做&lt;strong&gt;多数类&lt;/strong&gt;（majority class）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;出现更少的那个标签，叫做&lt;strong&gt;少数类&lt;/strong&gt;（minority class）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="使用不平衡数据集为什么这么难"&gt;使用不平衡数据集为什么这么难&lt;a class="anchor" href="#%e4%bd%bf%e7%94%a8%e4%b8%8d%e5%b9%b3%e8%a1%a1%e6%95%b0%e6%8d%ae%e9%9b%86%e4%b8%ba%e4%bb%80%e4%b9%88%e8%bf%99%e4%b9%88%e9%9a%be"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;训练模型的目标是造出一个能把正类和负类分清楚的模型。要做到这一点，每个批次（batch）里都得同时含有足够多的正类样本和负类样本。&lt;/p&gt;
&lt;p&gt;如果只是轻度不平衡，这倒不成什么问题——哪怕批次很小，通常也能凑齐正负两类样本。但一旦不平衡得很厉害，少数类的样本可能根本不够撑起一次像样的训练。&lt;/p&gt;
&lt;p&gt;举个例子，图 6 展示的这份数据集：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;200 个标签属于多数类。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 个标签属于少数类。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div align=center&gt;&lt;img width="700" src="https://machinelearningwithme.com/images/course/FloralDataset200Sunflowers2Roses.png" alt="图 6. 一片向日葵里藏着两朵玫瑰：202 张图片按网格铺开，绝大多数是黄橙色的向日葵，只有右上方和左下偏左两处是红色的玫瑰。"/&gt; &lt;/div&gt;&lt;center&gt;图 6. 高度不平衡的花卉数据集，向日葵远多于玫瑰&lt;/center&gt;
&lt;p&gt;如果批次大小是 20，大多数批次里一个少数类样本都没有；如果批次大小是 100，每个批次平均也只摊到 1 个少数类样本，这点量根本不够训练。就算把批次再放大，比例依旧悬殊，模型照样可能训不出来。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;注意：&lt;/strong&gt; 在类别不平衡的数据集上，&lt;strong&gt;准确率&lt;/strong&gt;通常不是一个衡量模型好坏的好指标。细节可以看&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/ml/classification/accuracy-precision-recall/"&gt;分类：准确率、召回率与精确率&lt;/a&gt;。&lt;/p&gt;&lt;/blockquote&gt;&lt;h2 id="使用类别不平衡的数据集训练"&gt;使用类别不平衡的数据集训练&lt;a class="anchor" href="#%e4%bd%bf%e7%94%a8%e7%b1%bb%e5%88%ab%e4%b8%8d%e5%b9%b3%e8%a1%a1%e7%9a%84%e6%95%b0%e6%8d%ae%e9%9b%86%e8%ae%ad%e7%bb%83"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;训练过程中，模型其实要同时学会两件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;每个类别长什么样——也就是说，什么样的特征值对应什么类别。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;每个类别有多常见——也就是说，各类之间的相对分布是什么样的。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;常规的训练方式会把这两件事混在一起。而下面这个两步走的技巧——&lt;strong&gt;对多数类别下采样并上调其权重&lt;/strong&gt;——能把它们拆开，让模型两个目标都能达成。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;注意：&lt;/strong&gt; 很多同学读到下面两节时会冒出这么一句：「这不对吧？」——先打个预防针：对多数类别样本下采样、再上调权重，这件事确实有点反直觉。&lt;/p&gt;&lt;/blockquote&gt;&lt;h3 id="第一步对多数类下采样"&gt;第一步：对多数类下采样&lt;a class="anchor" href="#%e7%ac%ac%e4%b8%80%e6%ad%a5%e5%af%b9%e5%a4%9a%e6%95%b0%e7%b1%bb%e4%b8%8b%e9%87%87%e6%a0%b7"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;下采样（downsampling）&lt;/strong&gt;，指的是只用偏低比例的多数类样本参与训练。换句话说，就是人为地把一份不平衡的数据集掰得平衡一点，也就是训练时从多数类里舍掉大量样本。&lt;/p&gt;
&lt;p&gt;下采样能大幅提高「每个批次都含有足够多的少数类样本」的概率，模型因此才能正常、高效地训练。&lt;/p&gt;
&lt;p&gt;比如图 6 那份数据集里，99% 是多数类、1% 是少数类。若按 25 倍的倍数对多数类下采样，就能人为造出一份更平衡的训练集——80% 多数类对 20% 少数类，就像图 7 所示：&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="700" src="https://machinelearningwithme.com/images/course/FloralDatasetDownsampling.png" alt="图 7. 一排 10 个带边框的方格，从左到右前 8 格是黄橙色的向日葵，最后 2 格是红色的玫瑰。"/&gt; &lt;/div&gt;&lt;center&gt;图 7. 按 25 倍的倍数对多数类下采样&lt;/center&gt;
&lt;h3 id="第二步给下采样后的类别上调权重"&gt;第二步：给下采样后的类别上调权重&lt;a class="anchor" href="#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e7%bb%99%e4%b8%8b%e9%87%87%e6%a0%b7%e5%90%8e%e7%9a%84%e7%b1%bb%e5%88%ab%e4%b8%8a%e8%b0%83%e6%9d%83%e9%87%8d"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;下采样会引入&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/ml/classification/prediction-bias/"&gt;预测偏差&lt;/a&gt;：你拿给模型看的，是一个「类别比现实更均衡」的人为世界。要把这个偏差纠回来，就得按你下采样的那个倍数，给多数类上调权重（upweighting）。所谓上调权重，就是让多数类样本上的损失比少数类样本上的损失更「狠」。&lt;/p&gt;</description></item><item><title>数据集：划分原始数据集 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/dividing-datasets/</link><pubDate>Mon, 26 Oct 2026 15:08:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/dividing-datasets/</guid><description>&lt;h1 id="数据集划分原始数据集"&gt;数据集：划分原始数据集&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e9%9b%86%e5%88%92%e5%88%86%e5%8e%9f%e5%a7%8b%e6%95%b0%e6%8d%ae%e9%9b%86"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;任何一个像样的软件工程项目，都会把相当大的一部分精力花在&lt;strong&gt;测试&lt;/strong&gt;上。同样的道理，我们强烈建议你对 ML 模型也做测试，以确认它的预测到底是否正确。&lt;/p&gt;
&lt;h2 id="训练集验证集与测试集"&gt;训练集、验证集与测试集&lt;a class="anchor" href="#%e8%ae%ad%e7%bb%83%e9%9b%86%e9%aa%8c%e8%af%81%e9%9b%86%e4%b8%8e%e6%b5%8b%e8%af%95%e9%9b%86"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;你应当用一组&lt;strong&gt;不同于&lt;/strong&gt;训练样本的例子来测试模型。本节后面「测试集的其他问题」一节会展开说明这一点：在新样本上测试，比在训练用的同一批样本上测试，更能说明模型是真的好用，还是只是把做过的题背下来了。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;MLWM：&lt;/strong&gt; 我们在完成模型训练以后，都会在测试集上对模型的泛化能力进行评估。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;那这些&amp;quot;不同的样本&amp;quot;从哪儿来？在机器学习的传统做法里，答案是&lt;strong&gt;拆分原始数据集&lt;/strong&gt;。于是你可能会想当然地认为，把原始数据集拆成两半就够了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;训练集（training set）&lt;/strong&gt;：模型用来训练的那部分数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;测试集（test set）&lt;/strong&gt;：用来评估训练好的模型的那部分数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div align=center&gt;&lt;img width="700" src="https://machinelearningwithme.com/images/course/PartitionTwoSets.png" alt="图 8. 一根长条被切成两块：左边是占八成左右的黄色「training set」，右边是占两成左右的蓝色「test set」。"/&gt; &lt;/div&gt;&lt;center&gt;图 8. 一个不够理想的划分&lt;/center&gt;
&lt;h3 id="练习检验你的直觉"&gt;练习：检验你的直觉&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a0%e6%a3%80%e9%aa%8c%e4%bd%a0%e7%9a%84%e7%9b%b4%e8%a7%89"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;假设你用训练集训练、用测试集评估，如此反复了好几轮。每一轮，你都依据测试集的结果去调整超参数和特征集。你能看出这种做法有什么问题吗？（只选一个）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 大量重复这一过程，可能导致模型隐式地拟合测试集的特殊之处&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 这种做法没问题。毕竟你是在训练集上训练、在独立的测试集上评估&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 这种做法在计算上效率不高&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D. 每轮测试之后都不要改动超参数或特征集&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;span class="subscription-widget subscription-widget--content"
 data-subscription-widget
 data-resource-id="f1ae51ce292b4024"
 data-resource-text="点击查看答案及分析"
 data-resource-plan="basic"
 data-resource-color="blue"
 data-resource-align="left"
 data-resource-type="content"&gt;
 &lt;button type="button" class="subscription-btn subscription-btn--content" data-subscription-trigger data-type="content" style="font-size: 0.9em;" aria-busy="false"&gt;
 &lt;span class="subscription-btn__text"&gt;点击查看答案及分析&lt;/span&gt;
 &lt;/button&gt;
 &lt;span class="subscription-result" data-subscription-result hidden role="status" aria-live="polite"&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;script&gt;
(function () {
 var script = document.currentScript;
 var widget = script &amp;&amp; script.previousElementSibling;
 if (!widget || !widget.matches || !widget.matches('[data-subscription-widget]')) return;

 var trigger = widget.querySelector('[data-subscription-trigger]');
 var result = widget.querySelector('[data-subscription-result]');
 var icon = trigger.querySelector('.subscription-btn__icon');
 var textEl = trigger.querySelector('.subscription-btn__text');
 
 var originalIcon = icon ? icon.textContent : '';
 var originalText = textEl.textContent;
 var resourceId = widget.dataset.resourceId;
 var planHint = widget.dataset.resourcePlan || '';

 
 
 
 
 
 
 function applyContentStyle() {
 var S = window.MLWM_SUB_STYLE;
 if (S &amp;&amp; typeof S.apply === 'function') {
 S.apply(widget, widget.dataset.resourceColor, widget.dataset.resourceAlign);
 }
 }
 
 
 
 
 
 
 
 
 
 function notifyToggle(expanded) {
 document.dispatchEvent(new CustomEvent('mlwm:subscription-toggle', {
 detail: { resourceId: resourceId, expanded: !!expanded }
 }));
 }

 
 
 
 
 
 
 if (document.readyState === 'loading') {
 document.addEventListener('DOMContentLoaded', applyContentStyle, { once: true });
 } else {
 applyContentStyle();
 }

 
 
 var cached = null;
 var inflight = null;

 
 
 function resolveApiUrl(path) {
 if (window.__ML_API &amp;&amp; typeof window.__ML_API === 'function') return window.__ML_API(path);
 return path;
 }

 function isLoggedIn() {
 return document.documentElement.getAttribute('data-mlwm-auth') === 'in';
 }
 function getToken() {
 try { return localStorage.getItem('mlwm_auth_access') || ''; } catch (_) { return ''; }
 }
 function showLoginModal(opts) {
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.openLoginModal === 'function') {
 window.MLWM_AUTH.openLoginModal(Object.assign({ mode: 'login' }, opts || {}));
 } else {
 window.location.assign('/login/');
 }
 }
 function showToast(msg, type) {
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.showToast === 'function') {
 window.MLWM_AUTH.showToast(msg, type || 'warning');
 }
 }
 function setBusy(busy) {
 trigger.disabled = !!busy;
 trigger.setAttribute('aria-busy', busy ? 'true' : 'false');
 textEl.textContent = busy ? '加载中...' : originalText;
 }
 function clearResult() {
 result.hidden = true;
 result.innerHTML = '';
 delete result.dataset.kind;
 textEl.textContent = originalText;
 trigger.style.display = '';
 }
 function setResult(html, kind) {
 applyContentStyle();
 result.hidden = false;
 result.innerHTML = html;
 result.dataset.kind = kind || 'info';
 }
 function escapeHtml(s) {
 return String(s == null ? '' : s).replace(/[&amp;&lt;&gt;"']/g, function (c) {
 return { '&amp;': '&amp;amp;', '&lt;': '&amp;lt;', '&gt;': '&amp;gt;', '"': '&amp;quot;', "'": '&amp;#39;' }[c];
 });
 }

 
 
 
 
 
 
 
 function renderMarkdown(text) {
 var src = String(text == null ? '' : text);
 if (window.MLWM_MARKED_MD &amp;&amp; typeof window.MLWM_MARKED_MD.render === 'function') {
 var html = window.MLWM_MARKED_MD.render(src);
 if (typeof html === 'string') return html;
 }
 if (typeof marked !== 'undefined' &amp;&amp; typeof marked.parse === 'function') {
 return marked.parse(src);
 }
 return escapeHtml(src);
 }

 
 function isExpanded() { return widget.classList.contains('is-expanded'); }
 function isPinned() { return widget.classList.contains('is-pinned'); }
 function pin() { widget.classList.add('is-pinned'); }
 function unpin() { widget.classList.remove('is-pinned'); }

 function renderContentBox(data) {
 var html =
 '&lt;div class="subscription-content__title"&gt;' +
 '&lt;span class="subscription-content__chevron" aria-hidden="true"&gt;&lt;/span&gt;' +
 '&lt;span class="subscription-content__title-text"&gt;' + escapeHtml(originalText) + '&lt;/span&gt;' +
 '&lt;/div&gt;' +
 '&lt;div class="subscription-content__body"&gt;' + renderMarkdown(data.body) + '&lt;/div&gt;';
 trigger.style.display = 'none';
 setResult(html, 'content');
 widget.classList.add('is-expanded');
 notifyToggle(true);
 
 
 
 if (typeof window.renderMathInElement === 'function') {
 try {
 window.renderMathInElement(result, {
 throwOnError: false,
 delimiters: [
 { left: '$$', right: '$$', display: true },
 { left: '$', right: '$', display: false },
 { left: '\\(', right: '\\)', display: false },
 { left: '\\[', right: '\\]', display: true }
 ]
 });
 } catch (_) { }
 }
 }
 function hideContentBox() {
 trigger.style.display = '';
 clearResult();
 widget.classList.remove('is-expanded');
 unpin();
 notifyToggle(false);
 }

 function renderDenied(body) {
 var detail = body.detail || {};
 
 var requiredPlan = detail.required_plan || planHint || 'pro';
 
 var currentPlan = (detail.current_plan || '').toString().trim();
 var hasCurrent = !!currentPlan;
 
 var title = hasCurrent ? '订阅等级不足' : '尚未订阅';
 
 var bodyText = hasCurrent
 ? '当前订阅为 ' + escapeHtml(currentPlan) + '，获取该资源至少需订阅 ' + escapeHtml(requiredPlan) + ' 套餐。'
 : '当前未订阅，获取该资源至少需订阅 ' + escapeHtml(requiredPlan) + ' 套餐。';
 
 
 result.hidden = true;
 result.innerHTML = '';
 delete result.dataset.kind;
 trigger.style.display = '';
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.openDeniedModal === 'function') {
 window.MLWM_AUTH.openDeniedModal({
 title: title,
 body: bodyText,
 ctaText: '订阅方案',
 ctaHref: '/pricing/'
 });
 } else {
 
 window.location.assign('/pricing/');
 }
 }
 function renderDownload(data) {
 
 
 showToast('已触发下载: ' + (data.title || data.url || ''), 'success');
 var a = document.createElement('a');
 a.href = data.url;
 a.rel = 'noopener noreferrer';
 a.download = '';
 a.style.display = 'none';
 document.body.appendChild(a);
 a.click();
 document.body.removeChild(a);
 }
 function renderError(msg) {
 setResult('&lt;div class="subscription-error"&gt;' + escapeHtml(msg || '请求失败,请稍后再试') + '&lt;/div&gt;', 'error');
 }

 
 
 
 
 
 
 
 
 
 
 function fetchResource() {
 if (cached) return Promise.resolve({ ok: true, data: cached });
 if (inflight) return inflight;

 if (!isLoggedIn()) {
 return Promise.resolve({ ok: false, reason: 'not-logged-in', status: 0, body: null });
 }
 var url = resolveApiUrl('/resource/' + encodeURIComponent(resourceId));
 inflight = fetch(url, {
 method: 'GET',
 headers: { 'Authorization': 'Bearer ' + getToken() }
 })
 .then(function (r) {
 return r.json().then(function (j) { return { status: r.status, body: j }; }).catch(function () { return { status: r.status, body: null }; });
 })
 .then(function (resp) {
 if (resp.status === 401) {
 return { ok: false, reason: 'unauthorized', status: 401, body: null };
 }
 var body = resp.body;
 if (!body || typeof body !== 'object') {
 return { ok: false, reason: 'bad-response', status: resp.status, body: body };
 }
 if (body.code === 2002) {
 return { ok: false, reason: 'denied', status: resp.status, body: body };
 }
 if (body.code === 0 &amp;&amp; body.data) {
 
 if (body.data.type === 'content') {
 cached = body.data;
 return { ok: true, data: cached };
 }
 if (body.data.type === 'download' &amp;&amp; body.data.url) {
 return { ok: true, data: body.data };
 }
 }
 return { ok: false, reason: 'api-error', status: resp.status, body: body };
 })
 .catch(function () {
 return { ok: false, reason: 'network', status: 0, body: null };
 });
 
 inflight.then(function () { inflight = null; }, function () { inflight = null; });
 return inflight;
 }

 
 
 function ensureContent() {
 setBusy(true);
 return fetchResource().then(function (result) {
 setBusy(false);
 if (result.ok) {
 if (result.data.type === 'content') {
 renderContentBox(result.data);
 pin();
 return result.data;
 }
 if (result.data.type === 'download') {
 renderDownload(result.data);
 return null;
 }
 return null;
 }
 if (result.reason === 'not-logged-in') {
 showLoginModal({ bannerMessage: '请先登录后再访问资源' });
 } else if (result.reason === 'unauthorized') {
 showLoginModal({ bannerMessage: '登录已过期,请重新登录' });
 } else if (result.reason === 'denied') {
 renderDenied(result.body);
 } else if (result.reason === 'bad-response') {
 renderError('响应异常');
 } else if (result.reason === 'api-error') {
 renderError((result.body &amp;&amp; result.body.msg) || ('请求失败 (code ' + ((result.body &amp;&amp; result.body.code) || '?') + ')'));
 } else if (result.reason === 'network') {
 renderError('网络异常,请稍后再试');
 }
 return null;
 });
 }

 
 
 
 
 trigger.addEventListener('click', function (e) {
 e.stopPropagation();
 if (isExpanded()) return;
 ensureContent();
 });

 
 result.addEventListener('click', function (e) {
 var titleEl = e.target.closest('.subscription-content__title');
 if (titleEl) hideContentBox();
 });

 
 
 
 

 
 
 
 
 
 
 widget.addEventListener('mlwm:subscription-prefetch', function () {
 
 
 
 
 widget._prefetchPromise = fetchResource().then(function () {}, function () {});
 });
})();
&lt;/script&gt;

&lt;p&gt;把数据集拆成两半是个不错的主意，但更好的做法是把它拆成三份。除了训练集和测试集，第三份是：&lt;/p&gt;</description></item><item><title>数据集：转换数据 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/transforming-data/</link><pubDate>Tue, 27 Oct 2026 12:18:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/transforming-data/</guid><description>&lt;h1 id="数据集转换数据"&gt;数据集：转换数据&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e9%9b%86%e8%bd%ac%e6%8d%a2%e6%95%b0%e6%8d%ae"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;我们都知道机器学习模型只能用浮点数来训练，可一个数据集里，很多特征天生就不是浮点数，所以机器学习中有一件很重要的事，就是把这些非浮点特征转换成浮点表示。&lt;/p&gt;
&lt;p&gt;举个例子。假设有一个叫 &lt;code&gt;street names&lt;/code&gt;（街道名称）的特征。街道名称大多是字符串，比如 &amp;ldquo;Broadway&amp;rdquo; 或 &amp;ldquo;Vilakazi&amp;rdquo;。模型没法在 &amp;ldquo;Broadway&amp;rdquo; 上训练，所以你必须先把 &amp;ldquo;Broadway&amp;rdquo; 变成一个浮点数。至于怎么变，&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/categorical-data/"&gt;处理类别型数据&lt;/a&gt;那一节讲得很清楚。&lt;/p&gt;
&lt;p&gt;更进一步，大多数本来就是浮点数的特征，其实也要再变换一遍。这个变换过程叫归一化（normalization），它是把浮点数收敛到一个受约束的区间里，从而改善模型训练。具体怎么做，可以看&lt;a href="https://machinelearningwithme.com/course/google-machine-learning/data/numerical-data/"&gt;处理数值数据&lt;/a&gt;。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;MLWM：&lt;/strong&gt; 关于「为什么要把特征变换到同一量纲」，可以参见文章&lt;a href="https://machinelearningwithme.com/ml/chapter04/feature-scaling/"&gt;「特征标准化：归一化与标准化的原理及实现」&lt;/a&gt;；把街道名这类字符串变成数值向量的思路，则可以参见&lt;a href="https://machinelearningwithme.com/ml/chapter06/bag-of-words/"&gt;「词袋模型原理：文本特征表示与机器学习建模」&lt;/a&gt; 中的介绍。&lt;/p&gt;&lt;/blockquote&gt;&lt;h2 id="数据太多的时候用抽样"&gt;数据太多的时候用抽样&lt;a class="anchor" href="#%e6%95%b0%e6%8d%ae%e5%a4%aa%e5%a4%9a%e7%9a%84%e6%97%b6%e5%80%99%e7%94%a8%e6%8a%bd%e6%a0%b7"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;有些机构很幸运，手里的数据多得用不完。&lt;/p&gt;
&lt;p&gt;因此，当数据集里的样本太多时，你就必须挑出一个子集来训练模型。在挑的时候，尽可能选那些与模型预测最相关的样本，毕竟，数据虽多，能用得上的才是关键。&lt;/p&gt;
&lt;h2 id="过滤含-pii-的样本"&gt;过滤含 PII 的样本&lt;a class="anchor" href="#%e8%bf%87%e6%bb%a4%e5%90%ab-pii-%e7%9a%84%e6%a0%b7%e6%9c%ac"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;好的数据集里，不该出现含有个人身份信息（PII，Personally Identifiable Information）的样本。这条规矩有助于保护隐私，但也可能对模型产生影响。&lt;/p&gt;
&lt;p&gt;课程后面的「安全与隐私」模块会展开讲这些话题。&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote class='book-hint important'&gt;
&lt;p&gt;&lt;strong&gt;关键术语：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;归一化&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;</description></item><item><title>泛化 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/generalization/</link><pubDate>Tue, 27 Oct 2026 12:33:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/generalization/</guid><description>&lt;h1 id="模型的泛化"&gt;模型的泛化&lt;a class="anchor" href="#%e6%a8%a1%e5%9e%8b%e7%9a%84%e6%b3%9b%e5%8c%96"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;先讲一个故事。&lt;/p&gt;
&lt;p&gt;想象一位来自外星的游客初到地球。为了跟人交流，他挑了一个特定的局部社区，认真听那里居民怎么说话，潜心学了好几个月的语言。等他觉得自己已经掌握了这门语言，准备走向更多人时，却发现自己根本没法跟世界上其他地方的人沟通。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么会这样？&lt;/strong&gt; 因为他学到的，只是极小一部分人群的特定说话习惯——这些经验，搬不到真实而多变的世界里去。&lt;/p&gt;
&lt;p&gt;机器学习模型的训练过程，跟这个故事几乎是同一个道理。这一节要讲的，就是机器学习从业者在训练模型时最常撞上的那个问题。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;MLWM：&lt;/strong&gt; 如果觉得上面举的这个例子没太理解，可以参见 &lt;a href="https://machinelearningwithme.com/ml/chapter04/overfitting-solutions/"&gt;「4.3 过拟合处理方法：常见原因、表现与正则化实战」&lt;/a&gt; 第 4.3.1 节中的内容。&lt;/p&gt;&lt;/blockquote&gt;&lt;h2 id="什么是泛化generalization"&gt;什么是「泛化」（Generalization）&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af%e6%b3%9b%e5%8c%96generalization"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;泛化，指的是模型对全新的、没见过的数据依然能做出高质量预测的能力。&lt;/p&gt;
&lt;p&gt;难点在于：训练模型时用的是训练数据，通常只是真实世界数据的极小子集。所以模型的终极目标，从来不是在训练集上表现好，而是在陌生的真实数据上也能预测得准。&lt;/p&gt;
&lt;h2 id="什么是过拟合overfitting"&gt;什么是「过拟合」（Overfitting）&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af%e8%bf%87%e6%8b%9f%e5%90%88overfitting"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;跟泛化相对的那个概念，叫过拟合。&lt;/p&gt;
&lt;p&gt;如果一个模型在训练数据上的预测准确率极高，可一换到全新的真实数据上，预测质量就大幅下滑——这种现象就叫过拟合。&lt;/p&gt;
&lt;p&gt;原因也不难理解：模型过于死板地贴合了已见数据的那些细节和局部模式，反而认不出新数据里更普遍的规律。&lt;/p&gt;
&lt;h2 id="如何提高模型的泛化能力"&gt;如何提高模型的泛化能力&lt;a class="anchor" href="#%e5%a6%82%e4%bd%95%e6%8f%90%e9%ab%98%e6%a8%a1%e5%9e%8b%e7%9a%84%e6%b3%9b%e5%8c%96%e8%83%bd%e5%8a%9b"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;回到那个外星游客。他发现问题之后，做法其实很朴素：换一批人去听。他开始倾听各种不同人群的讲话，重新学习，最后终于把这门语言用到了全新的场景里。&lt;/p&gt;
&lt;p&gt;机器学习的解法也是同一个：让模型从更广泛、更具代表性、更多样的数据里学习。&lt;/p&gt;
&lt;p&gt;至于怎么在真实的模型训练里检测和防止过拟合——靠训练集与测试集的划分，还是靠正则化——接下来的两节会分别展开。&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote class='book-hint important'&gt;
&lt;p&gt;&lt;strong&gt;关键术语：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;泛化&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;过拟合&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;</description></item><item><title>过拟合 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/overfitting/</link><pubDate>Tue, 27 Oct 2026 14:06:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/overfitting/</guid><description>&lt;h1 id="过拟合现象"&gt;过拟合现象&lt;a class="anchor" href="#%e8%bf%87%e6%8b%9f%e5%90%88%e7%8e%b0%e8%b1%a1"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;过拟合（overfitting）&lt;/strong&gt;，指的是模型把训练集记得太牢，以至于在新数据上反而做不出正确的预测。&lt;/p&gt;
&lt;p&gt;一个过拟合的模型，活像一项在实验室里表现惊艳、到了真实世界里却毫无价值的发明。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt; 过拟合是机器学习里的常见问题，不是学术上的假设情形。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;如图 11 所示，想象每个几何图形代表方块森林里一棵树的位置：青色菱形标记健康树的位置，浅橙色圆形标记病树的位置。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="500" src="https://machinelearningwithme.com/images/course/TreesTrainingSet.svg" alt="图 11. 一个方形的森林里散布着约六十棵树：青色菱形是健康树，主要集中在右上方，也有几棵跑到了左上角；浅橙色圆形是病树，主要集中在左下方，也有几棵散落到别的位置。"/&gt; &lt;/div&gt;&lt;center&gt;图 11. 训练集：方块森林里健康树与病树的位置&lt;/center&gt;
&lt;p&gt;在脑海里画出任意形状——直线、曲线、椭圆……什么都行——把健康树和病树分开。然后，展开下一行，看一种可能的分隔方式。&lt;/p&gt;
&lt;details class="example-disclosure" style="margin-top: 1rem;"&gt;
&lt;summary style="cursor:pointer;font-weight:600;"&gt;点击展开，看一种可能的画法&lt;/summary&gt;
&lt;div style="margin-top: 1rem;"&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/TreesTrainingSetComplexModel.svg" alt="图 12. 与图 11 相同的树木排布，但被一组弯折的多段边界切开：健康树大多被圈在上方的区域，病树大多被圈在下方，只有极少数被分错。"/&gt; &lt;/div&gt;&lt;center&gt;图 12. 用于区分病树与健康树的复杂模型&lt;/center&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;图 12 展示的那组复杂形状，成功地把除两棵之外的所有树都分对了。如果把这些形状当成一个模型，那这就是一个相当完美的模型。&lt;/p&gt;
&lt;p&gt;或者，真是这样吗？我们要知道一个真正优秀的模型，是能对新样本做出正确分类。图 13 展示的是同一个模型在测试集的新样本上做预测时会发生什么：&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/TreesTestSetComplexModel.svg" alt="图 13. 方块里铺满了新的一批树，底下是那套复杂模型划出的边界：上方蓝色区域判定为健康树，下方橙色区域判定为病树。有十来个标记上打了叉的树被分到了错误的区域。"/&gt; &lt;/div&gt;&lt;center&gt;图 13. 测试集：用于区分病树与健康树的复杂模型&lt;/center&gt;
&lt;p&gt;所以，图 12 里那个复杂模型在训练集上干得很漂亮，在测试集上却干得很糟。这就是模型&lt;strong&gt;过拟合&lt;/strong&gt;到训练集数据的典型案例。&lt;/p&gt;
&lt;h2 id="拟合过拟合与欠拟合"&gt;拟合、过拟合与欠拟合&lt;a class="anchor" href="#%e6%8b%9f%e5%90%88%e8%bf%87%e6%8b%9f%e5%90%88%e4%b8%8e%e6%ac%a0%e6%8b%9f%e5%90%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;模型必须在新数据上做出好的预测。也就是说，你的目标是造出一个能「拟合」新数据的模型（泛化能力足够强）。&lt;/p&gt;
&lt;p&gt;前面已经看到，过拟合的模型在训练集上预测出色，在新数据上预测糟糕。而&lt;strong&gt;欠拟合（underfit）&lt;/strong&gt; 的模型则是指连训练数据都预测不好。如果说过拟合模型像一件在实验室里表现良好、在真实世界里表现差劲的产品，那么欠拟合模型就像一件连在实验室里都表现不好的产品。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="450" src="https://machinelearningwithme.com/images/course/underfit_fit_overfit.svg" alt="图 14. 一张直角坐标系图：横轴是训练集上的预测质量，纵轴是真实数据上的预测质量。一条红色倒 V 形曲线从原点升起再落下，左下角标着「欠拟合模型」，右下角标着「过拟合模型」，顶点圈起来标着「拟合良好的模型」。"/&gt; &lt;/div&gt;&lt;center&gt;图 14. 欠拟合、拟合与过拟合模型&lt;/center&gt;
&lt;p&gt;一个&lt;strong&gt;泛化良好&lt;/strong&gt;的模型，能在新数据上做出好的预测。你的目标，就是造出一个能良好泛化到新数据的模型。&lt;/p&gt;
&lt;h2 id="如何检测过拟合"&gt;如何检测过拟合&lt;a class="anchor" href="#%e5%a6%82%e4%bd%95%e6%a3%80%e6%b5%8b%e8%bf%87%e6%8b%9f%e5%90%88"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;下面这几类曲线能帮你发现过拟合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;损失曲线（loss curves）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;泛化曲线（generalization curves）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;损失曲线画出的是模型的损失随训练迭代次数的变化情况。把两条或更多（在不同划分集上的）损失曲线画在同一张图上，就叫泛化曲线。下面这张泛化曲线画的就是两条损失曲线：&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/RegularizationTwoLossFunctions.png" alt="图 15. 一张坐标图：纵轴是损失，横轴是训练迭代次数。蓝色的训练损失一路下降并逐渐走平，红色的验证损失先跟着下降，迭代到某个点之后却掉头向上翘起。"/&gt; &lt;/div&gt;&lt;center&gt;图 15. 一条强烈暗示过拟合的泛化曲线&lt;/center&gt;
&lt;p&gt;注意，两条损失曲线一开始表现相似，之后就分道扬镳了。也就是说，迭代到一定次数之后，训练集的损失继续下降或保持平稳（收敛），而验证集的损失却开始上升。这就暗示了开始出现过拟合现象了。&lt;/p&gt;
&lt;p&gt;相比之下，一个拟合良好的模型（good fitting），它的泛化曲线上的两条损失曲线形状是相似的。&lt;/p&gt;</description></item><item><title>过拟合：模型复杂度 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/model-complexity/</link><pubDate>Tue, 27 Oct 2026 14:35:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/model-complexity/</guid><description>&lt;h1 id="过拟合模型的复杂度"&gt;过拟合：模型的复杂度&lt;a class="anchor" href="#%e8%bf%87%e6%8b%9f%e5%90%88%e6%a8%a1%e5%9e%8b%e7%9a%84%e5%a4%8d%e6%9d%82%e5%ba%a6"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;上一节介绍过下面这个模型，它在测试集上把很多树都分错了。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/TreesTestSetComplexModel.svg" alt="图 16. 与图 13 同一幅画面：方块被上一节那套弯折的多段边界切成蓝橙两块，里面铺着一批新树，其中十来个被打上叉——被分进了错误的区域。"/&gt; &lt;/div&gt;&lt;center&gt;图 16. 上一节中的过拟合模型&lt;/center&gt;
&lt;p&gt;可以看到，上面那个模型里塞满了各种复杂形状。那如果换成一个更简单的模型，会不会有更好的表现？假设你把复杂模型换成一个简单到极点的模型——一条直线。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/TreesTestSetSimpleModel.svg" alt="图 17. 同一片方块林，但只用一条从左上到右下的斜直线分区：右上方的蓝色区域判定为健康树，左下方的橙色区域判定为病树。只有四棵树被判错，比图 16 少得多。"/&gt; &lt;/div&gt;&lt;center&gt;图 17. 一个简单得多的模型&lt;/center&gt;
&lt;p&gt;在新数据上，简单模型比复杂模型泛化得更好。也就是说，在测试集上，简单模型的预测比复杂模型更准。&lt;/p&gt;
&lt;p&gt;简单战胜复杂，这件事已经延续了很久。其实对简单的偏好，可以追溯到古希腊。几个世纪之后，十四世纪一位名叫威廉·奥卡姆（William of Occam）的修士，把这种对简单的偏好总结成了一门哲学，就是&lt;a href="https://wikipedia.org/wiki/Occam%27s_razor"&gt;奥卡姆剃刀&lt;/a&gt;。这门哲学至今仍是许多学科（包括机器学习）的基本原则之一。&lt;/p&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;注意：&lt;/strong&gt; 复杂模型在训练集上通常优于简单模型；但在测试集上（这才是更重要的那一项），简单模型通常优于复杂模型。&lt;/p&gt;&lt;/blockquote&gt;&lt;h3 id="练习检验你的理解"&gt;练习：检验你的理解&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a0%e6%a3%80%e9%aa%8c%e4%bd%a0%e7%9a%84%e7%90%86%e8%a7%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;第1题：&lt;/strong&gt; 你在推导一个物理公式。下面哪个公式更符合奥卡姆剃刀？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 一个含3个变量的公式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 一个含12个变量的公式&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;第2题：&lt;/strong&gt; 你刚启动一个全新的机器学习项目，正要挑选第1批特征。你应该选多少个特征？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 挑 1–3 个看起来预测能力很强的特征&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 挑 4–6 个看起来预测能力很强的特征&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 尽可能多地挑，好早点看出哪些特征预测能力最强&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;span class="subscription-widget subscription-widget--content"
 data-subscription-widget
 data-resource-id="b8215cf7450c4073"
 data-resource-text="点击查看答案及分析"
 data-resource-plan="basic"
 data-resource-color="blue"
 data-resource-align="left"
 data-resource-type="content"&gt;
 &lt;button type="button" class="subscription-btn subscription-btn--content" data-subscription-trigger data-type="content" style="font-size: 0.9em;" aria-busy="false"&gt;
 &lt;span class="subscription-btn__text"&gt;点击查看答案及分析&lt;/span&gt;
 &lt;/button&gt;
 &lt;span class="subscription-result" data-subscription-result hidden role="status" aria-live="polite"&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;script&gt;
(function () {
 var script = document.currentScript;
 var widget = script &amp;&amp; script.previousElementSibling;
 if (!widget || !widget.matches || !widget.matches('[data-subscription-widget]')) return;

 var trigger = widget.querySelector('[data-subscription-trigger]');
 var result = widget.querySelector('[data-subscription-result]');
 var icon = trigger.querySelector('.subscription-btn__icon');
 var textEl = trigger.querySelector('.subscription-btn__text');
 
 var originalIcon = icon ? icon.textContent : '';
 var originalText = textEl.textContent;
 var resourceId = widget.dataset.resourceId;
 var planHint = widget.dataset.resourcePlan || '';

 
 
 
 
 
 
 function applyContentStyle() {
 var S = window.MLWM_SUB_STYLE;
 if (S &amp;&amp; typeof S.apply === 'function') {
 S.apply(widget, widget.dataset.resourceColor, widget.dataset.resourceAlign);
 }
 }
 
 
 
 
 
 
 
 
 
 function notifyToggle(expanded) {
 document.dispatchEvent(new CustomEvent('mlwm:subscription-toggle', {
 detail: { resourceId: resourceId, expanded: !!expanded }
 }));
 }

 
 
 
 
 
 
 if (document.readyState === 'loading') {
 document.addEventListener('DOMContentLoaded', applyContentStyle, { once: true });
 } else {
 applyContentStyle();
 }

 
 
 var cached = null;
 var inflight = null;

 
 
 function resolveApiUrl(path) {
 if (window.__ML_API &amp;&amp; typeof window.__ML_API === 'function') return window.__ML_API(path);
 return path;
 }

 function isLoggedIn() {
 return document.documentElement.getAttribute('data-mlwm-auth') === 'in';
 }
 function getToken() {
 try { return localStorage.getItem('mlwm_auth_access') || ''; } catch (_) { return ''; }
 }
 function showLoginModal(opts) {
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.openLoginModal === 'function') {
 window.MLWM_AUTH.openLoginModal(Object.assign({ mode: 'login' }, opts || {}));
 } else {
 window.location.assign('/login/');
 }
 }
 function showToast(msg, type) {
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.showToast === 'function') {
 window.MLWM_AUTH.showToast(msg, type || 'warning');
 }
 }
 function setBusy(busy) {
 trigger.disabled = !!busy;
 trigger.setAttribute('aria-busy', busy ? 'true' : 'false');
 textEl.textContent = busy ? '加载中...' : originalText;
 }
 function clearResult() {
 result.hidden = true;
 result.innerHTML = '';
 delete result.dataset.kind;
 textEl.textContent = originalText;
 trigger.style.display = '';
 }
 function setResult(html, kind) {
 applyContentStyle();
 result.hidden = false;
 result.innerHTML = html;
 result.dataset.kind = kind || 'info';
 }
 function escapeHtml(s) {
 return String(s == null ? '' : s).replace(/[&amp;&lt;&gt;"']/g, function (c) {
 return { '&amp;': '&amp;amp;', '&lt;': '&amp;lt;', '&gt;': '&amp;gt;', '"': '&amp;quot;', "'": '&amp;#39;' }[c];
 });
 }

 
 
 
 
 
 
 
 function renderMarkdown(text) {
 var src = String(text == null ? '' : text);
 if (window.MLWM_MARKED_MD &amp;&amp; typeof window.MLWM_MARKED_MD.render === 'function') {
 var html = window.MLWM_MARKED_MD.render(src);
 if (typeof html === 'string') return html;
 }
 if (typeof marked !== 'undefined' &amp;&amp; typeof marked.parse === 'function') {
 return marked.parse(src);
 }
 return escapeHtml(src);
 }

 
 function isExpanded() { return widget.classList.contains('is-expanded'); }
 function isPinned() { return widget.classList.contains('is-pinned'); }
 function pin() { widget.classList.add('is-pinned'); }
 function unpin() { widget.classList.remove('is-pinned'); }

 function renderContentBox(data) {
 var html =
 '&lt;div class="subscription-content__title"&gt;' +
 '&lt;span class="subscription-content__chevron" aria-hidden="true"&gt;&lt;/span&gt;' +
 '&lt;span class="subscription-content__title-text"&gt;' + escapeHtml(originalText) + '&lt;/span&gt;' +
 '&lt;/div&gt;' +
 '&lt;div class="subscription-content__body"&gt;' + renderMarkdown(data.body) + '&lt;/div&gt;';
 trigger.style.display = 'none';
 setResult(html, 'content');
 widget.classList.add('is-expanded');
 notifyToggle(true);
 
 
 
 if (typeof window.renderMathInElement === 'function') {
 try {
 window.renderMathInElement(result, {
 throwOnError: false,
 delimiters: [
 { left: '$$', right: '$$', display: true },
 { left: '$', right: '$', display: false },
 { left: '\\(', right: '\\)', display: false },
 { left: '\\[', right: '\\]', display: true }
 ]
 });
 } catch (_) { }
 }
 }
 function hideContentBox() {
 trigger.style.display = '';
 clearResult();
 widget.classList.remove('is-expanded');
 unpin();
 notifyToggle(false);
 }

 function renderDenied(body) {
 var detail = body.detail || {};
 
 var requiredPlan = detail.required_plan || planHint || 'pro';
 
 var currentPlan = (detail.current_plan || '').toString().trim();
 var hasCurrent = !!currentPlan;
 
 var title = hasCurrent ? '订阅等级不足' : '尚未订阅';
 
 var bodyText = hasCurrent
 ? '当前订阅为 ' + escapeHtml(currentPlan) + '，获取该资源至少需订阅 ' + escapeHtml(requiredPlan) + ' 套餐。'
 : '当前未订阅，获取该资源至少需订阅 ' + escapeHtml(requiredPlan) + ' 套餐。';
 
 
 result.hidden = true;
 result.innerHTML = '';
 delete result.dataset.kind;
 trigger.style.display = '';
 if (window.MLWM_AUTH &amp;&amp; typeof window.MLWM_AUTH.openDeniedModal === 'function') {
 window.MLWM_AUTH.openDeniedModal({
 title: title,
 body: bodyText,
 ctaText: '订阅方案',
 ctaHref: '/pricing/'
 });
 } else {
 
 window.location.assign('/pricing/');
 }
 }
 function renderDownload(data) {
 
 
 showToast('已触发下载: ' + (data.title || data.url || ''), 'success');
 var a = document.createElement('a');
 a.href = data.url;
 a.rel = 'noopener noreferrer';
 a.download = '';
 a.style.display = 'none';
 document.body.appendChild(a);
 a.click();
 document.body.removeChild(a);
 }
 function renderError(msg) {
 setResult('&lt;div class="subscription-error"&gt;' + escapeHtml(msg || '请求失败,请稍后再试') + '&lt;/div&gt;', 'error');
 }

 
 
 
 
 
 
 
 
 
 
 function fetchResource() {
 if (cached) return Promise.resolve({ ok: true, data: cached });
 if (inflight) return inflight;

 if (!isLoggedIn()) {
 return Promise.resolve({ ok: false, reason: 'not-logged-in', status: 0, body: null });
 }
 var url = resolveApiUrl('/resource/' + encodeURIComponent(resourceId));
 inflight = fetch(url, {
 method: 'GET',
 headers: { 'Authorization': 'Bearer ' + getToken() }
 })
 .then(function (r) {
 return r.json().then(function (j) { return { status: r.status, body: j }; }).catch(function () { return { status: r.status, body: null }; });
 })
 .then(function (resp) {
 if (resp.status === 401) {
 return { ok: false, reason: 'unauthorized', status: 401, body: null };
 }
 var body = resp.body;
 if (!body || typeof body !== 'object') {
 return { ok: false, reason: 'bad-response', status: resp.status, body: body };
 }
 if (body.code === 2002) {
 return { ok: false, reason: 'denied', status: resp.status, body: body };
 }
 if (body.code === 0 &amp;&amp; body.data) {
 
 if (body.data.type === 'content') {
 cached = body.data;
 return { ok: true, data: cached };
 }
 if (body.data.type === 'download' &amp;&amp; body.data.url) {
 return { ok: true, data: body.data };
 }
 }
 return { ok: false, reason: 'api-error', status: resp.status, body: body };
 })
 .catch(function () {
 return { ok: false, reason: 'network', status: 0, body: null };
 });
 
 inflight.then(function () { inflight = null; }, function () { inflight = null; });
 return inflight;
 }

 
 
 function ensureContent() {
 setBusy(true);
 return fetchResource().then(function (result) {
 setBusy(false);
 if (result.ok) {
 if (result.data.type === 'content') {
 renderContentBox(result.data);
 pin();
 return result.data;
 }
 if (result.data.type === 'download') {
 renderDownload(result.data);
 return null;
 }
 return null;
 }
 if (result.reason === 'not-logged-in') {
 showLoginModal({ bannerMessage: '请先登录后再访问资源' });
 } else if (result.reason === 'unauthorized') {
 showLoginModal({ bannerMessage: '登录已过期,请重新登录' });
 } else if (result.reason === 'denied') {
 renderDenied(result.body);
 } else if (result.reason === 'bad-response') {
 renderError('响应异常');
 } else if (result.reason === 'api-error') {
 renderError((result.body &amp;&amp; result.body.msg) || ('请求失败 (code ' + ((result.body &amp;&amp; result.body.code) || '?') + ')'));
 } else if (result.reason === 'network') {
 renderError('网络异常,请稍后再试');
 }
 return null;
 });
 }

 
 
 
 
 trigger.addEventListener('click', function (e) {
 e.stopPropagation();
 if (isExpanded()) return;
 ensureContent();
 });

 
 result.addEventListener('click', function (e) {
 var titleEl = e.target.closest('.subscription-content__title');
 if (titleEl) hideContentBox();
 });

 
 
 
 

 
 
 
 
 
 
 widget.addEventListener('mlwm:subscription-prefetch', function () {
 
 
 
 
 widget._prefetchPromise = fetchResource().then(function () {}, function () {});
 });
})();
&lt;/script&gt;

&lt;h2 id="正则化"&gt;正则化&lt;a class="anchor" href="#%e6%ad%a3%e5%88%99%e5%8c%96"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;机器学习模型必须同时满足两个互相冲突的目标：&lt;/p&gt;</description></item><item><title>过拟合：$L_2$ 正则化 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/regularization/</link><pubDate>Tue, 27 Oct 2026 16:36:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/regularization/</guid><description>&lt;h1 id="过拟合l2-正则化"&gt;过拟合：L2 正则化&lt;a class="anchor" href="#%e8%bf%87%e6%8b%9f%e5%90%88l2-%e6%ad%a3%e5%88%99%e5%8c%96"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;在上一节中我们提到了「正则化」这个概念，即给复杂模型施加惩罚，逼着它在拟合数据的同时尽量保持简单。可惩罚的力度用什么来衡量、又要惩罚到什么程度呢，就是这一节要回答的问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;$L_2$ 正则化&lt;/strong&gt;（$L_2$ regularization）是最常用的正则化度量，它把所有权重的平方加在一起：&lt;/p&gt;
$$L_2\text{ regularization } = {w_1^2 + w_2^2 + ... + w_n^2}$$&lt;p&gt;公式里每一项都是&lt;strong&gt;平方&lt;/strong&gt;，这也正是大权重会被重罚的原因。&lt;/p&gt;
&lt;p&gt;下面是一个拥有六个权重的模型，$L_2$ 正则化的计算过程：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;权重&lt;/th&gt;
					&lt;th&gt;取值&lt;/th&gt;
					&lt;th&gt;平方值&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;$w_1$&lt;/td&gt;
					&lt;td&gt;0.2&lt;/td&gt;
					&lt;td&gt;0.04&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;$w_2$&lt;/td&gt;
					&lt;td&gt;-0.5&lt;/td&gt;
					&lt;td&gt;0.25&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;$w_3$&lt;/td&gt;
					&lt;td&gt;5.0&lt;/td&gt;
					&lt;td&gt;25.0&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;$w_4$&lt;/td&gt;
					&lt;td&gt;-1.2&lt;/td&gt;
					&lt;td&gt;1.44&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;$w_5$&lt;/td&gt;
					&lt;td&gt;0.3&lt;/td&gt;
					&lt;td&gt;0.09&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;$w_6$&lt;/td&gt;
					&lt;td&gt;-0.1&lt;/td&gt;
					&lt;td&gt;0.01&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;26.83&lt;/strong&gt; = 合计&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这张表里有两件事值得留意。&lt;/p&gt;
&lt;p&gt;第一，接近零的权重对 $L_2$ 正则化的结果影响很小，但大权重的威力却相当惊人。就上面这次计算而言：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;单是 $w_3$ 这一个权重，就贡献了大约 93% 的总复杂度。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;另外五个权重加起来，只贡献了大约 7%。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第二，$L_2$ 正则化的作用方向，是把权重往零推，但永远不会真的推到零。这一点很关键，下面的练习就会考到它。&lt;/p&gt;
&lt;h3 id="练习检验你的理解"&gt;练习：检验你的理解&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a0%e6%a3%80%e9%aa%8c%e4%bd%a0%e7%9a%84%e7%90%86%e8%a7%a3"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;第1题：&lt;/strong&gt; 如果你在训练模型时使用了 $L_2$ 正则化，这个模型的整体复杂度通常会怎么变？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 大概率下降&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 大概率保持不变&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 大概率上升&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;第2题：&lt;/strong&gt; 如果你在训练模型时使用了 $L_2$ 正则化，是否会有特征被从模型中移除？&lt;/p&gt;</description></item><item><title>过拟合：解读损失曲线 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/loss-curves/</link><pubDate>Wed, 28 Oct 2026 09:52:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/loss-curves/</guid><description>&lt;h1 id="过拟合解读损失曲线"&gt;过拟合：解读损失曲线&lt;a class="anchor" href="#%e8%bf%87%e6%8b%9f%e5%90%88%e8%a7%a3%e8%af%bb%e6%8d%9f%e5%a4%b1%e6%9b%b2%e7%ba%bf"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;训练模型的时候，损失曲线是最忠实的那面镜子——模型状态好不好，它一清二楚。如果说要是所有损失曲线都长得像下面这张图，那机器学习就会简单得多。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/metric-curve-ideal.svg" alt="图 20. 一张理想的损失曲线。纵轴标着 Loss，横轴标着 Steps，一条蓝色曲线从左上角的高位出发，先陡峭下降，斜率逐渐变小，最后趋近一个平缓的最低点。"/&gt; &lt;/div&gt;&lt;center&gt;图 20. 理想的损失曲线&lt;/center&gt;
&lt;p&gt;从图20可以看出，此时损失先高后低、一路收敛到某个值附近，这就是教科书上想让你记住的样子。可惜真实的曲线很少这么听话：它可能剧烈振荡，可能突然跳升，可能训练集和测试集各走各的，也可能干脆卡在某个位置反复横跳。&lt;/p&gt;
&lt;p&gt;所以这一节我们不打算再往你脑子里塞新公式，而是换一种练法，四张真实的损失曲线，四道判断题。每一道题都先给你一条曲线，再问你这曲线出了什么问题、可能是什么原因。你需要做的，是把前面几节学过的直觉（数据脏了、学习率不合适、模型过拟合、批次没打乱……）调动起来，用它们去解读一条你从没见过的曲线。&lt;/p&gt;
&lt;h2 id="练习1振荡的损失曲线"&gt;练习1：振荡的损失曲线&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a01%e6%8c%af%e8%8d%a1%e7%9a%84%e6%8d%9f%e5%a4%b1%e6%9b%b2%e7%ba%bf"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;先看第一条。曲线没有往下降，反倒像心电图一样剧烈起伏：&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/metric-curve-ex03.svg" alt="图 21. 一张振荡的损失曲线。纵轴 Loss，横轴 Steps，蓝色曲线在高位与低位之间剧烈地上下起伏，振幅始终不收敛，看不到任何变平的迹象。"/&gt; &lt;/div&gt;&lt;center&gt;图 21. 振荡的损失曲线&lt;/center&gt;
&lt;p&gt;&lt;strong&gt;第1题：&lt;/strong&gt; 面对图 21 这条曲线，你可以尝试做哪些事来改善它？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 按数据模式（schema）检查数据，找出坏样本并从训练集中移除&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 降低学习率&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 把训练集缩到极少量可信样本&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D. 增加训练集里的样本数量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;E. 提高学习率&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="练习2损失曲线突然跳升"&gt;练习2：损失曲线突然跳升&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a02%e6%8d%9f%e5%a4%b1%e6%9b%b2%e7%ba%bf%e7%aa%81%e7%84%b6%e8%b7%b3%e5%8d%87"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;第2条曲线更干脆：本来好好的，突然就炸了。&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/metric-curve-ex02.svg" alt="图 22. 一张损失突然跳升的曲线。纵轴 Loss，横轴 Steps，蓝色曲线先平缓下降到最低点，接着几乎垂直地陡升到高位，并在高位剧烈抖动。"/&gt; &lt;/div&gt;&lt;center&gt;图 22. 损失突然跳升&lt;/center&gt;
&lt;p&gt;&lt;strong&gt;第2题：&lt;/strong&gt; 下面哪些项能解释图 22 中这条突然爆掉的损失曲线？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 输入数据里含有 NaN——比如某个除零操作算出来的值&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 输入数据里混进了一批离群值&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 学习率太低&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D. 正则化率太高&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="练习3测试损失与训练损失背离"&gt;练习3：测试损失与训练损失背离&lt;a class="anchor" href="#%e7%bb%83%e4%b9%a03%e6%b5%8b%e8%af%95%e6%8d%9f%e5%a4%b1%e4%b8%8e%e8%ae%ad%e7%bb%83%e6%8d%9f%e5%a4%b1%e8%83%8c%e7%a6%bb"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;第三条曲线要更细看一点，它有两条线：&lt;/p&gt;
&lt;div align=center&gt;&lt;img width="550" src="https://machinelearningwithme.com/images/course/metric-curve-ex01.svg" alt="图 23. 训练损失与测试损失背离的曲线。纵轴 Loss，横轴 Steps，蓝色的 Train 曲线与红色的 Test 曲线起初重合着一起下降，之后蓝线继续往下走，红线却触底后开始回升；右上角有蓝色 Train、红色 Test 的文字图例。"/&gt; &lt;/div&gt;&lt;center&gt;图 23. 验证损失陡升&lt;/center&gt;
&lt;p&gt;&lt;strong&gt;第3题：&lt;/strong&gt; 下面哪些项最能解释训练集与测试集的损失曲线为什么会出现这种差异？&lt;/p&gt;</description></item><item><title>数据集、泛化与过拟合：测一测你掌握了多少 - Google 机器学习速成课程配套中文解读</title><link>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/quiz/</link><pubDate>Wed, 28 Oct 2026 10:22:00 +0800</pubDate><guid>https://machinelearningwithme.com/course/google-machine-learning/data/overfitting/quiz/</guid><description>&lt;h1 id="过拟合模块随堂测验"&gt;过拟合模块：随堂测验&lt;a class="anchor" href="#%e8%bf%87%e6%8b%9f%e5%90%88%e6%a8%a1%e5%9d%97%e9%9a%8f%e5%a0%82%e6%b5%8b%e9%aa%8c"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote class='book-hint note'&gt;
&lt;p&gt;&lt;strong&gt;随堂测验：&lt;/strong&gt; 共 5 题，你必须至少答对 4 题才能通过。&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote class='book-hint caution'&gt;
&lt;p&gt;请勿作弊！等你确认已经掌握本模块的全部内容之后，再回来作答。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;五道题，横跨「数据集、泛化与过拟合」这一整章：平稳性、缺失值、派生标签、测试集到底该怎么用、正则化究竟在惩罚什么。单看每一题都不算难，但每一道都卡在一个特别容易含糊过去的点上——所以建议你先把 5 题全部做完，再统一展开折叠区对照。一次只对一道题，很容易把「想得起来」误当成「真懂」。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="第-1-题什么是平稳数据集"&gt;第 1 题：什么是平稳数据集&lt;a class="anchor" href="#%e7%ac%ac-1-%e9%a2%98%e4%bb%80%e4%b9%88%e6%98%af%e5%b9%b3%e7%a8%b3%e6%95%b0%e6%8d%ae%e9%9b%86"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;下列哪一个属于平稳（stationary）数据集？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 美国华盛顿州西雅图的降雨量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 贝多芬交响曲的音符目录&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 垃圾邮件里最常出现的词&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D. 电影院的每日售票量&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="第-2-题缺失的里程数据怎么处理"&gt;第 2 题：缺失的里程数据怎么处理&lt;a class="anchor" href="#%e7%ac%ac-2-%e9%a2%98%e7%bc%ba%e5%a4%b1%e7%9a%84%e9%87%8c%e7%a8%8b%e6%95%b0%e6%8d%ae%e6%80%8e%e4%b9%88%e5%a4%84%e7%90%86"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;你准备用一份包含 &lt;code&gt;year&lt;/code&gt;、&lt;code&gt;model&lt;/code&gt;、&lt;code&gt;mileage&lt;/code&gt; 三个特征的数据集，训练一个预测二手车售价的模型。检查数据时你发现：2,500 条样本里，有 150 条的 &lt;code&gt;mileage&lt;/code&gt; 是缺失的。下列哪些做法是合理的？（多选）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 把这 150 条样本从数据集里删掉&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 把 &lt;code&gt;mileage&lt;/code&gt; 这一列整个去掉，只用 &lt;code&gt;year&lt;/code&gt; 和 &lt;code&gt;model&lt;/code&gt; 训练模型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 在所有空的 &lt;code&gt;mileage&lt;/code&gt; 字段里填入 &lt;code&gt;0&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D. 用「车龄 × 全数据集的平均年里程」为每个空字段估一个 &lt;code&gt;mileage&lt;/code&gt; 值&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="第-3-题哪些行为算用户喜欢这部电影"&gt;第 3 题：哪些行为算「用户喜欢这部电影」&lt;a class="anchor" href="#%e7%ac%ac-3-%e9%a2%98%e5%93%aa%e4%ba%9b%e8%a1%8c%e4%b8%ba%e7%ae%97%e7%94%a8%e6%88%b7%e5%96%9c%e6%ac%a2%e8%bf%99%e9%83%a8%e7%94%b5%e5%bd%b1"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;你在训练一个流媒体的电影推荐模型，目标是预测用户对某部电影的态度。下列哪些可以作为「用户喜欢这部电影」的合理派生标签？（多选）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A. 用户把电影存进了「想看」列表&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B. 用户点击了「开始观看」&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C. 用户把这部电影推荐给了另一位用户&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;D. 用户给这部电影打了 5 星&lt;/p&gt;</description></item></channel></rss>