前置知识: 机器学习

什么是机器学习

00:00
17 min Beginner

机器学习是教计算机从数据中发现模式,而不是手工编写规则

什么是机器学习

机器学习是教计算机从数据中发现模式,而不是手工编写规则。

类型: 学习 语言: Python 前置条件: Phase 1 (数学基础) 时间: ~45 分钟

学习目标

  • 解释监督学习、无监督学习和强化学习的区别,并识别给定问题适用哪种类型
  • 从零实现最近质心分类器,并对照随机基线进行评估
  • 区分分类和回归任务,并为每种任务选择合适的损失函数
  • 评估给定的业务问题是否适合使用 ML,还是用确定性规则更好

问题

你想构建一个垃圾邮件过滤器。传统方法:坐下来写几百条规则。“如果邮件包含 ‘FREE MONEY’,标记为垃圾邮件。如果超过3个感叹号,标记为垃圾邮件。“你花了几周写规则。然后垃圾邮件发送者改变了措辞。你的规则失效了。你写更多规则。这个循环永无止境。

机器学习颠覆了这一点。你不再编写规则,而是给计算机数千封标记好的邮件(“垃圾邮件”或”非垃圾邮件”),让它自己找出规则。计算机能发现你从未想到过的模式。当垃圾邮件发送者改变策略时,你只需在新数据上重新训练,而不是重写代码。

这种从”编写规则”到”从数据中学习”的转变,就是机器学习的核心。每个推荐引擎、语音助手、自动驾驶汽车和语言模型都是这样工作的。

概念

从数据中学习,而非规则

传统编程和机器学习以相反的方向解决问题。

传统编程:你编写规则。程序将规则应用于数据以产生输出。

机器学习:你提供数据和期望输出。算法发现规则。

训练产生的”模型”就是规则,以数字(权重、参数)编码。它从见过的示例中泛化,对从未见过的数据做出预测。

机器学习的三种类型

监督学习:你有输入-输出对。模型学习将输入映射到输出。

  • “这里有10,000张标记为猫或狗的照片。学会区分它们。”
  • “这里有房屋特征和价格。学会预测价格。”

无监督学习:你只有输入,没有标签。模型自行发现结构。

  • “这里有10,000个客户购买历史。找出自然分组。”
  • “这里有1000维数据点。在保持结构的同时降到2维。”

强化学习:智能体在环境中采取行动并获得奖励或惩罚。它学习一种策略(policy)来最大化总奖励。

  • “玩这个游戏。赢+1,输-1。找出策略。”
  • “控制这个机械臂。拿起物体+1,每浪费一秒-0.01。”

你在实践中构建的大部分内容都使用监督学习。无监督学习常用于预处理和探索。强化学习驱动游戏AI、机器人和语言模型的RLHF。

三大类型之外

上面三个类别很清晰,但现实世界的ML经常模糊界限。

半监督学习使用少量标记数据和大量未标记数据。你可能有100张标记的医学图像和100,000张未标记的。技术包括:

  • **标签传播:**构建连接相似数据点的图。标签从标记节点通过图传播到未标记的邻居。
  • **伪标签:**在标记数据上训练模型,用它预测未标记数据的标签,然后在所有数据上重新训练。模型自举其训练集。
  • **一致性正则化:**模型对输入及其轻微扰动版本应给出相同的预测。这即使没有标签也有效。

自监督学习从数据本身创建监督。完全不需要人工标签。模型从数据结构中创建自己的预测任务。

  • **掩码语言建模 (BERT):**隐藏句子中15%的词,训练模型预测缺失的词。“标签”来自原始文本。
  • **对比学习 (SimCLR):**取一张图像,创建两个增强版本。训练模型识别它们来自同一图像,同时区分它们与其他图像的增强版本。
  • **下一词预测 (GPT):**给定所有前面的词,预测下一个词。每个文本文档都成为训练样本。

这些不是三大类型的独立类别。它们是结合监督和无监督思想的策略。自监督学习在技术上是监督的(模型预测某物),但标签是自动生成的,不是人工标注的。

分类 vs 回归

这是两种主要的监督学习任务。

方面分类回归
输出离散类别连续数字
示例”这封邮件是垃圾邮件吗?""房价会是多少?“
输出空间{猫, 狗, 鸟}任意实数
损失函数交叉熵、准确率均方误差、MAE
决策类别之间的边界拟合数据的曲线

分类回答”哪个类别?“回归回答”多少?”

有些问题可以用两种方式表述。预测股票涨跌是分类。预测确切价格是回归。

ML工作流程

每个机器学习项目都遵循相同的流程,无论使用什么算法。

收集数据:收集原始数据。更多数据几乎总是更好的,但质量比数量更重要。

清洗与探索:处理缺失值、删除重复项、可视化分布、发现异常。这一步通常占总项目时间的60-80%。

特征工程:将原始数据转换为模型可以使用的特征。将日期转换为星期几。标准化数值列。编码分类变量。好的特征比花哨的算法更重要。

划分数据:分为训练集、验证集和测试集。模型在训练数据上训练,你在验证数据上调整超参数,在测试数据上报告最终性能。

训练模型:将训练数据输入算法。算法调整内部参数以最小化损失函数。

评估:在验证/测试数据上衡量性能。如果性能不可接受,返回尝试不同的特征、算法或超参数。

部署:将模型投入生产,对新数据进行预测。

监控:随时间跟踪性能。数据分布会变化(数据漂移),模型会退化。当性能下降时,重新训练。

训练集、验证集和测试集的划分

这是初学者最容易搞错的重要概念。你必须在训练期间从未见过的数据上评估模型。否则你测量的是记忆,而不是学习。

划分目的使用时机典型大小
训练集模型从中学习训练期间60-80%
验证集调整超参数,比较模型每次训练运行后10-20%
测试集最终无偏性能估计最后,仅一次10-20%

测试集是神圣的。你只看它一次。如果你不断根据测试性能调整模型,你实际上是在测试集上训练,你报告的数字毫无意义。

对于小数据集,使用k折交叉验证:将数据分成k份,在k-1份上训练,在剩余一份上验证,轮换并平均结果。

过拟合 vs 欠拟合

欠拟合:模型太简单,无法捕捉数据中的模式。一条直线试图拟合弯曲的关系。训练误差高。测试误差高。

过拟合:模型太复杂,记住了训练数据,包括噪声。一条摆动的曲线穿过每个训练点但在新数据上失败。训练误差低。测试误差高。

良好拟合:模型捕捉真实模式而不记忆噪声。训练误差和测试误差都合理地低。

过拟合的迹象:

  • 训练准确率远高于验证准确率
  • 模型在训练数据上表现好但在新数据上表现差
  • 添加更多训练数据能改善性能(模型在记忆,而非学习)

过拟合的修复方法:

  • 获取更多训练数据
  • 降低模型复杂度(更少参数、更简单架构)
  • 正则化(对大权重添加惩罚)
  • Dropout(训练时随机将神经元置零)
  • 早停(当验证误差开始增加时停止训练)

欠拟合的修复方法:

  • 使用更复杂的模型
  • 添加更多特征
  • 减少正则化
  • 训练更长时间

偏差-方差权衡

这是过拟合和欠拟合背后的数学框架。

偏差:模型中错误假设导致的误差。当真实关系是非线性时,线性模型具有高偏差。高偏差导致欠拟合。

方差:对训练数据微小波动敏感导致的误差。高方差模型在不同数据子集上训练时给出非常不同的预测。高方差导致过拟合。

模型复杂度偏差方差结果
太低(弯曲数据用线性模型)欠拟合
刚好良好泛化
太高(10个点用20次多项式)过拟合

总误差 = 偏差^2 + 方差 + 不可约噪声

你无法减少不可约噪声(它是数据本身的随机性)。你想找到偏差^2 + 方差最小化的最佳点。

没有免费午餐定理

没有单一算法对所有问题都最好。在一类问题上表现良好的算法在另一类问题上会表现差。这就是为什么数据科学家尝试多种算法并比较结果。

在实践中,选择取决于:

  • 你有多少数据
  • 有多少特征
  • 关系是线性还是非线性
  • 是否需要可解释性
  • 你能负担多少计算资源

何时不使用机器学习

ML很强大,但并不总是正确的工具。在使用模型之前,先问自己是否真的需要它。

不要使用ML的情况:

  • **规则简单且明确。**税收计算、排序算法、单位转换。如果你能用几个if语句写出来,模型只会增加复杂性而没有收益。
  • **你没有数据或数据很少。**ML需要样本来学习。10个数据点无法训练出任何有意义的东西。先收集数据。
  • **错误的代价是灾难性的,你需要保证正确性。**医疗剂量计算、核反应堆控制、密码学验证。ML模型是概率性的。它们有时会出错。如果”有时出错”不可接受,使用确定性方法。
  • **查找表或启发式规则就能解决问题。**如果简单的阈值或表格能覆盖99%的情况,添加ML只会增加维护成本而没有实质性改进。
  • **你无法解释决策,而可解释性是必需的。**受监管行业(贷款、保险、刑事司法)有时要求每个决策都完全可解释。一些ML模型是可解释的(线性回归、小决策树)。大多数不是。
  • **问题变化的速度快于你重新训练的速度。**如果规则每天变化而重新训练需要一周,模型总是过时的。

使用此决策流程图:

动手构建

code/ml_intro.py 中的代码从零实现了最近质心分类器,这是最简单的ML算法。它演示了核心思想:从数据中学习,然后对新数据进行预测。

步骤1:从零实现最近质心分类器

最近质心分类器计算训练数据中每个类别的中心(均值)。预测时,将每个新点分配给距离最近的类别中心。

class NearestCentroid:
    def fit(self, X, y):
        self.classes = np.unique(y)
        self.centroids = np.array([
            X[y == c].mean(axis=0) for c in self.classes
        ])

    def predict(self, X):
        distances = np.array([
            np.sqrt(((X - c) ** 2).sum(axis=1))
            for c in self.centroids
        ])
        return self.classes[distances.argmin(axis=0)]

这就是整个算法。fit计算两个均值。predict计算距离。没有梯度下降,没有迭代,没有超参数。

步骤2:在合成数据上训练

我们生成一个2D分类数据集,两个类别略有重叠。质心分类器在类别中心之间绘制线性决策边界。

rng = np.random.RandomState(42)
X_class0 = rng.randn(100, 2) + np.array([1.0, 1.0])
X_class1 = rng.randn(100, 2) + np.array([-1.0, -1.0])
X = np.vstack([X_class0, X_class1])
y = np.array([0] * 100 + [1] * 100)

步骤3:对照基线比较

每个ML模型都应该与一个简单基线比较。这里,基线预测随机类别。如果你的ML模型不能超过随机猜测,说明有问题。

baseline_preds = rng.choice([0, 1], size=len(y_test))
baseline_acc = np.mean(baseline_preds == y_test)

质心分类器在这个干净的数据集上应该达到90%+的准确率。随机基线大约50%。

为什么这很重要

最近质心分类器极其简单。它没有超参数,没有迭代,没有梯度下降。但它捕捉了基本的ML模式:

  1. 学习训练数据的表示(质心)
  2. 预测新数据使用该表示(最近距离)
  3. 评估对照基线(随机猜测)

每个ML算法,从逻辑回归到transformer,都遵循相同的三步模式。表示变得更复杂,但工作流程保持不变。

步骤4:质心分类器不能做什么

最近质心分类器假设每个类别形成一个单一的团。它绘制线性决策边界。它在以下情况失败:

  • 类别有多个簇(例如,数字”1”可以有多种写法)
  • 决策边界是非线性的(例如,一个类别环绕另一个类别)
  • 特征尺度差异很大(距离被最大尺度的特征主导)

这些局限性推动了你将学习的每个其他算法。K近邻处理多个簇。决策树处理非线性边界。特征缩放修复尺度问题。每节课都建立在前一节课的局限性之上。

实际使用

sklearn提供了 NearestCentroid 和合成数据生成器:

from sklearn.neighbors import NearestCentroid
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

X, y = make_classification(
    n_samples=500, n_features=2, n_redundant=0,
    n_clusters_per_class=1, random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

clf = NearestCentroid()
clf.fit(X_train, y_train)
print(f"Accuracy: {clf.score(X_test, y_test):.3f}")

交付成果

本课程产出 outputs/prompt-ml-problem-framer.md — 一个将模糊的业务问题转化为具体ML任务的提示。给它一个问题描述(“我们想减少流失”或”预测下个季度的需求”),它会识别学习类型、定义预测目标、列出候选特征、选择成功指标、建立基线,并标记数据泄漏或类别不平衡等陷阱。在任何ML项目开始时使用它,避免构建错误的东西。

关键术语

术语人们怎么说实际含义
模型”那个AI”一个具有可学习参数的数学函数,将输入映射到输出
训练”教AI”运行优化算法调整模型参数,使预测匹配已知输出
特征”输入列”模型用来做预测的数据的可测量属性
标签”答案”训练样本的已知输出,用于计算误差信号
超参数”你调整的设置”训练前设置的参数,控制学习过程(学习率、层数)
损失函数”模型有多错”衡量预测输出与实际输出差距的函数,训练试图最小化它
过拟合”它记住测试集”模型学习了训练特有的噪声而非通用模式,在新数据上失败
欠拟合”它什么都没学到”模型太简单,无法捕捉数据中的真实模式
泛化”在新数据上有效模型训练数据做出准确预测的能力
交叉验证”在不同测试反复将数据分成训练/测试折并平均结果,给出更稳健的性能估计
正则”保持权重较小”在损失函数中添加惩罚项,阻止过于复杂的模型
数据漂移世界变了”输入数据的统计分布随时间变化,导致模型性能下降

练习

  1. 取任意数据集(如Iris、Titanic)。按70/15/15划分为训练/验证/测试集。解释为什么不应在测试集上调整超参数
  2. 列出三个现实世界问题每个问题识别它是分类、回归还是聚,以及是监督还是无监督的。
  3. 一个模型在训练数据上达到99%准确,但在测试数据上只有60%。诊断问题并列出三种你会尝试的修复方法。

延伸阅读

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式