应用实例与前沿展望 🦾

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_53.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_55.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_57.png

IRL 这类方法常被用于训练机械手臂。传统方法需要为每个动作精确编程,极其繁琐。而通过 IRL,我们只需向机器人示范几次,它就能学会该技能。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_59.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_61.png

研究前沿甚至可以让智能体学会“达成指定目标”。例如,给机器看一张“摆好盘子”的图片,它就能自行规划动作达成该状态。训练时,智能体会自己给自己设定各种虚拟目标并尝试达成,从而泛化出强大的目标达成能力。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_62.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_64.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_66.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_68.png

关于IRL的一个常见问题是:它能否让机器“青出于蓝”,表现超过人类专家?答案是肯定的。因为机器并非单纯模仿,而是学习奖励函数。我们可以在学到的奖励函数基础上,添加新的优化目标(如“更快完成任务”),从而引导机器找到超越人类示范的更优解。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_70.png


总结 📚

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_72.png

本节课我们一起学习了在没有明确奖励函数的情况下,如何通过专家示范来训练智能体。

  1. 我们首先指出了行为克隆这种简单模仿方法的局限性。

  2. 接着,我们深入探讨了逆向增强式学习的核心思想:从专家示范中反推奖励函数。

  3. 我们详细讲解了IRL的迭代算法流程,并将其与生成对抗网络的框架进行了类比,揭示了其中的内在联系。

  4. 最后,我们看了IRL在机器人操控等领域的应用,并展望了其让智能体性能超越人类的可能性。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/9cb7faa5a4d1bb58734da1f97e71aa5e_74.png

通过本节学习,你应该对如何让机器从观察中学习有了更深刻的理解。

81:作业12(Homework12)说明 🚀

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_1.png

在本节课中,我们将学习李宏毅机器学习课程作业12的具体内容与要求。本次作业的主题是深度强化学习,目标是训练一个智能体在OpenAI的LunarLander环境中成功着陆。

概述

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_3.png

本次作业要求你实现深度强化学习算法,训练一个智能体(紫色飞船)在月球着陆器环境中,成功降落在两个黄色标志之间。你将学习策略梯度(Policy Gradient)和演员-评论家(Actor-Critic)等算法的基本原理与实现,并按要求提交代码、结果和报告。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_5.png

作业环境与目标

本次作业采用OpenAI的LunarLander环境。环境中有一个紫色飞船,目标是训练智能体控制飞船,使其成功着陆在地面的两个黄色标志之间。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_7.png

核心算法讲解

上一节我们介绍了作业的基本环境与目标,本节中我们来看看需要实现的核心算法。

策略梯度(Policy Gradient)

策略梯度是一种直接优化策略的强化学习方法。以下是其伪代码流程:

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_9.png

  1. 初始化策略参数 θ。

  2. 对于每一个包含 T 个时间步的回合(episode):

    • 在每一个时间步 t,根据当前状态 s_t,采样一个动作 a_t,并得到奖励 r_t。
  3. 对于一个回合及其每个时间步,计算折扣奖励(Discounted Reward) G_t:

    • G_t = ∑_{k=t}^{T} (γ^{k-t} * r_k),其中 γ 是折扣因子。
  4. 使用状态和奖励更新策略参数 θ:

    • θ ← θ + α * ∇_θ log π_θ(a_t|s_t) * G_t

    • 其中,α 是学习率,∇_θ log π_θ(a_t|s_t) 是动作对数概率的梯度。

演员-评论家(Actor-Critic)

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_11.png

演员-评论家算法在策略梯度的基础上引入了价值函数作为基线(Baseline),以降低方差。它与策略梯度的主要区别在于优势函数(Advantage Function)的计算。

  1. 算法框架与策略梯度相似。

  2. 我们需要一个基线函数 V_β(s),其中 β 是价值网络的参数。

  3. 在每个时间步,我们计算优势估计 A_t:

    • A_t = G_t - V_β(s_t)

    • 我们希望 V_β(s) 尽可能接近真实的折扣奖励 G_t,因此需要通过最小化两者之间的差距(如均方误差)来训练价值网络。

  4. 使用计算出的优势 A_t 来更新策略模型(演员):

    • θ ← θ + α * ∇_θ log π_θ(a_t|s_t) * A_t

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_13.png

训练结果与评估

在训练过程中,系统会自动生成两张图表用于评估性能。

  • 左图 - 总奖励(Total Reward):显示每个训练回合所获得奖励的总和。

  • 右图 - 最终奖励(Final Reward):显示从环境中获得的最后一个奖励值,主要反映飞船是否成功着陆。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_15.png


提交要求

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_17.png

以下是本次作业需要提交的内容清单。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_19.png

1. Python代码文件

  • 正确提交至指定调用接口可获得2分。

2. 动作列表(Action Sequence)

  • 此部分最高可获得4分。

  • 动作列表是你的智能体与环境交互所产生的一系列动作序列,将由示例代码自动生成。

  • 请注意:禁止手动修改动作列表文件,否则提交将被拒绝。

  • 评分基于平均总奖励(Average Total Reward):

    • 平均总奖励 ≥ 209.69:获得4分。

    • 平均总奖励为负或未提交有效结果:获得0分。

    • 在此区间之间:按线性比例给分。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_21.png

3. 实验报告

  • 报告需要回答指定问题。

报告问题详解

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_23.png

上一节列出了提交内容,本节我们详细看看报告中的问题。

问题一:高级算法实现

  • 你需要实现一个高级强化学习算法(例如:带基线的策略梯度、演员-评论家、A2C、A3C等)。

  • 在报告中需解释你的实现与基础策略梯度算法的区别。

  • 请清晰描述你的实现过程。如果描述不清,评分者将直接检查代码,若发现不一致可能会扣分。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_25.png

问题二:关于MuZero的多选题

  • 提供了MuZero论文的链接,要求你阅读后回答问题。

  • 请注意,此题要求选出错误的描述,请仔细作答。


重要注意事项

以下是完成作业时需要特别注意的事项列表。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_27.png

  • 运行环境:作业默认不使用GPU。建议使用Google Colab完成。若使用其他环境,需自行解决可复现性问题。只要能在评测系统上复现结果,使用任何环境均可。

  • 训练时间:作业12的训练时间应控制在30分钟以内。

  • 提交格式:需将代码等文件压缩成单个压缩包提交。请勿提交模型检查点或大型数据集。

  • 结果复现:提交的代码必须在评测系统上能复现出提交的结果,否则成绩可能计为0分。

  • 加分项:本次作业包含加分项,规则与以往作业相同。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_29.png

联系与公告

如有任何问题,可以通过以下方式联系助教:

  • 发送邮件至指定邮箱,邮件标题请注明“Homework Twelve”。

  • 或在课程相关在线平台直接提问。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_31.png

请留意课程页面发布的官方公告,以获取作业的确切起止时间等信息。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_33.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_35.png

总结

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/1d26257014badebe327cf8f7d26a6134_37.png

本节课中,我们一起学习了作业12的完整说明。我们了解了在LunarLander环境中应用强化学习的目标,学习了策略梯度和演员-评论家算法的核心思想与更新公式,明确了代码、动作列表和报告三部分的提交要求与评分标准,并注意到了完成作业时的各项重要细节。现在,你可以开始着手实现你的强化学习智能体了。

82:神经网络压缩(一)—— 神经网络剪枝与大乐透假说 🧠✂️

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_1.png

在本节课中,我们将学习神经网络压缩(Network Compression)技术,特别是神经网络剪枝(Pruning)方法。我们将探讨为何需要压缩模型、剪枝的基本原理与步骤,并分析著名的“大乐透假说”(Lottery Ticket Hypothesis)及其争议。


概述:为何需要压缩神经网络?

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_3.png

在之前的课程中,我们已经见识了许多庞大的模型,例如BERT或GPT。本节课我们将探讨能否将这些庞大的模型缩小,即用更少的参数达到相近的性能,这就是神经网络压缩的目标。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_5.png

我们之所以关注模型压缩,是因为很多时候需要在资源受限的环境下部署模型。例如,在智能手表或无人机等物联网设备上,内存和计算能力有限。如果模型过于庞大,这些设备可能无法运行。

有人可能会问,为何不将数据传到云端计算后再传回结果?主要原因有两个:延迟(Latency)和隐私(Privacy)。对于需要实时响应的应用(如自动驾驶传感器),云端计算的延迟可能无法接受。此外,将数据传到云端可能涉及隐私泄露风险。因此,在设备端直接进行运算和决策是更好的选择。


神经网络剪枝(Pruning)的基本概念

上一节我们介绍了模型压缩的必要性,本节中我们来看看第一种压缩技术:神经网络剪枝。

剪枝,顾名思义,就是修剪掉神经网络中一些不重要的参数。俗话说“树大必有枯枝”,一个庞大的神经网络中有许多参数,但并非所有参数都在发挥作用。许多参数可能只是“划水”,没有实际贡献。这些无效的参数只会占用空间和浪费计算资源,因此可以考虑将它们移除。

神经网络剪枝的基本思想是:从一个大型网络中找出并移除那些无用的参数。这类似于人脑发育的过程:婴儿出生时神经元连接很少,六岁时连接大量增加,但随着年龄增长,一些连接会逐渐消失。神经网络剪枝也有类似的效果。

早在20世纪90年代,就有一篇名为“Optimal Brain Damage”的论文提出了剪枝的概念。它将剪除权重视为一种“脑损伤”,而“最优”意味着要找到对网络损伤最小的剪枝方法。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_7.png


剪枝的基本流程

以下是进行神经网络剪枝的基本步骤框架:

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_9.png

  1. 训练一个大型网络:首先,训练一个庞大的神经网络。

  2. 评估参数重要性:评估网络中每个参数或神经元的重要性。判断参数重要性的简单方法是看其绝对值大小,绝对值越大通常影响越大。也可以借鉴终身学习(Lifelong Learning)中计算参数重要性的方法。

  3. 移除不重要部分:将不重要的参数或神经元从模型中移除,得到一个较小的网络。

  4. 微调网络:剪枝后,模型的性能通常会下降。因此,需要对剩余的参数进行微调(Fine-tuning),以恢复部分性能。

  5. 迭代过程:上述评估、剪枝、微调的步骤可以反复进行多次。实验表明,一次性剪除大量参数可能对网络造成不可逆的损伤,因此采用迭代方式效果更好。


以参数 vs. 神经元为单位的剪枝

上一节我们介绍了剪枝的流程,本节中我们来看看剪枝时选择不同单位(参数或神经元)会有什么差异。

在实践上,选择不同的剪枝单位会有显著区别。

以参数(Weight)为单位进行剪枝:

  • 剪枝后,网络结构会变得不规则。例如,某个神经元的输入或输出连接数可能与其他神经元不同。

  • 这种不规则结构在实现上非常困难。主流框架(如PyTorch)通常要求每一层的输入输出维度是固定的。

  • 即使用技巧实现,也不利于GPU加速,因为GPU擅长处理规则的矩阵运算。

  • 因此,实践中常将剪掉的权重值设为零,而非真正移除。但这并没有真正减少模型大小,只是“自嗨”式的压缩。

以神经元(Neuron)为单位进行剪枝:

  • 剪枝后,网络架构仍然是规则的。你只需要调整每一层的神经元数量即可。

  • 这种方法易于实现,也便于利用GPU进行加速。

文献中的实验也证实了这一点。实验显示,即使剪除了95%以上的参数(权重剪枝),模型的推理速度也几乎没有提升,甚至可能变慢。这是因为不规则网络无法有效利用硬件加速。因此,以神经元为单位的剪枝通常是更实用的选择。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_11.png


大乐透假说(Lottery Ticket Hypothesis)

一个自然的问题是:既然先训练大网络再剪枝能得到一个小网络,为什么不直接训练一个小网络呢?普遍的答案是:大网络通常更容易训练成功。直接训练小网络往往无法达到剪枝后小网络的性能。

这引出了一个著名的假说——大乐透假说。它试图解释为何大网络更好训练。

假说核心思想:

训练神经网络就像抽乐透,结果具有随机性。初始参数好,结果就好;初始参数差,结果就差。如何提高“中奖率”?就是买更多彩票(即拥有更多参数)。

一个大网络可以看作是许多小网络(子网络)的集合。训练大网络相当于同时训练许多子网络。只要其中有一个子网络成功“中奖”(即能被成功训练),整个大网络就成功了。网络越大,包含的子网络越多,成功训练的概率就越高。

实验验证:

实验设计如下:

  1. 随机初始化并训练一个大网络,得到一组参数(紫色)。

  2. 对该网络进行剪枝,得到一个小网络及其参数(红色)。

  3. 如果直接创建一个结构相同、但重新随机初始化的小网络(绿色)并训练,效果会很差。

  4. 但如果创建的小网络,其初始化参数继承自剪枝后保留的那些红色参数(即大网络中“幸运”的子网络参数),则能训练出好效果。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_13.png

这说明,大网络中确实存在一些“幸运”的子网络初始化配置。剪枝过程恰好保留了这些“中奖彩票”。而随机初始化则很难再次抽中同样的好运气。


对假说的延伸研究与争议

大乐透假说非常知名,但其正确性并非没有争议。

延伸研究:

一篇名为“Deconstructing Lottery Tickets”的论文进一步研究后发现:

  1. 参数训练前后的绝对值变化大小与剪枝效果相关。

  2. 初始化参数的正负号比其具体数值更重要。只要保持剪枝后参数的正负号不变,即使将其值替换为固定的常数(如+α/-α),模型也能成功训练。

  3. 甚至存在一种极端情况:在一个随机初始化的大网络中,可能已经存在一个无需训练、剪枝后直接就能有效工作的子网络。

争议与反驳:

另一篇同时期(ICLR 2019)的论文“Rethinking the Value of Network Pruning”提出了不同观点。其实验表明:

  • 如果增加训练轮数(Epoch),直接训练得到的小网络性能可以媲美甚至超过“训练大网络+剪枝”得到的小网络。

  • 大乐透假说观察到的现象,可能只在学习率较小和以权重为单位进行剪枝的特定设置下才显著。

因此,关于大乐透假说的有效性和普适性,目前仍是一个开放的研究问题。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_15.png


总结

本节课我们一起学习了神经网络压缩的重要性及其首个关键技术——剪枝(Pruning)。我们了解了剪枝的基本流程、以不同单位(参数/神经元)剪枝的实践差异,并深入探讨了试图解释“大网络优势”的大乐透假说及其相关的实验研究与争议。

核心要点总结:

  • 压缩目的:为了在资源受限的边缘设备上部署模型,并兼顾低延迟与隐私保护。

  • 剪枝步骤:训练大网络 → 评估重要性 → 剪枝 → 微调 → 迭代。

  • 实践建议:以神经元为单位的剪枝更利于工程实现与加速。

  • 大乐透假说:认为大网络包含许多子网络,其训练成功类似于“抽中彩票”,剪枝保留了“中奖彩票”。但这仍是假说,存在不同学术观点。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/a6e60307ceaa4ef18b775c3de5262174_17.png

通过学习,你应该对如何缩减模型规模有了初步认识,并了解到模型优化不仅是技术问题,也伴随着有趣的理论探索。

83:神经网络压缩 (二) 🧠

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_1.png

概述

在本节课中,我们将继续学习神经网络压缩技术。上一节我们介绍了网络剪枝,本节中我们将看看另一种重要的压缩方法——知识蒸馏,并探讨从参数量化、网络架构设计到动态计算等多个面向来压缩神经网络。


知识蒸馏 (Knowledge Distillation) 🧪

知识蒸馏的概念与网络剪枝有相似的精神,但其实现方式不同。

它的核心流程是:先训练一个大型网络,这个网络被称为教师网络 (Teacher Network)。然后,我们希望得到一个更小的网络,即学生网络 (Student Network)。学生网络并非直接对原始数据学习,而是去学习教师网络的输出。

以下是知识蒸馏的具体步骤:

  1. 将训练数据输入教师网络,教师网络会为每个输入生成一个概率分布作为输出。例如,在手写数字识别中,对于一张图片,教师可能输出:数字“1”的概率是0.7,“7”是0.29,“9”是0.01。

  2. 将同样的图片输入学生网络,但训练目标不是数据的真实标签,而是教师网络输出的这个概率分布。学生网络的目标是让自己的输出分布尽可能逼近教师的输出分布。

你可能会问:为什么不直接训练一个小网络呢?原因与网络剪枝类似:直接训练的小网络性能,往往不如通过向大网络(教师)学习得到的小网络(学生)性能好。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_3.png

知识蒸馏技术并非全新,Hinton在2015年发表的《Distilling the Knowledge in a Neural Network》使其广为人知。但更早的文献(如2013年的《Do Deep Nets Really Need to be Deep?》)已使用了类似概念。

为什么知识蒸馏有效?一个直观的解释是:教师网络为学生提供了额外的“软标签”信息。直接告诉学生“这是一张‘1’的图片”可能很困难,因为‘1’可能与‘7’、‘9’等数字有相似之处。而教师网络会输出“这是‘1’的概率是0.7,是‘7’的概率是0.2”,这揭示了类别间的相似性,使学生网络更容易学习。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_5.png

一个神奇的现象是:即使某些类别的训练数据从未给学生网络看过,仅凭教师网络揭示的类别间关系(例如“7”和“1”有点像),学生网络也有可能学会识别该类别。

教师网络也可以是集成模型 (Ensemble)。集成是机器学习比赛中常用的技巧,即训练多个模型并将它们的输出进行平均或投票,作为最终结果。虽然集成能提升性能,但计算开销巨大。通过知识蒸馏,我们可以将多个模型集成起来的结果作为教师,让学生网络去学习这个集成输出,从而用一个轻量级的学生网络来逼近集成的性能。

知识蒸馏中的技巧:温度 (Temperature)

在知识蒸馏中,常对Softmax函数进行一个小修改,即引入温度参数。

首先,回顾标准Softmax公式:

对于一个神经元的输出向量 z,其第 i 个类别的概率为:

公式:p_i = exp(z_i) / sum(exp(z_j)) for j in all classes

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_7.png

引入温度 T 后的Softmax变为:

公式:p_i = exp(z_i / T) / sum(exp(z_j / T)) for j in all classes

其中,T 是一个需要调节的超参数。当 T > 1 时,它会使原本尖锐的概率分布变得平滑。

为什么要这样做?如果教师网络的输出非常集中(例如某个类别概率为1,其余为0),那么让学生去学习这个输出就和直接学习真实标签没有区别,失去了知识蒸馏的意义。通过设置一个较大的 T,可以在不改变类别排序的前提下,让概率分布更平滑,从而让学生网络能更好地学习到类别间的关系信息。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_9.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_11.png

参数量化 (Parameter Quantization) 🔢

参数量化的目标是:用更少的存储空间来保存网络参数。请注意,在本课程作业中,由于限制的是参数数量而非存储大小,因此此方法可能不直接适用,但仍值得了解。

最简单的量化方法是降低数值精度:例如,将参数从32位浮点数(float32)转换为16位浮点数(float16)甚至8位整数(int8),这样存储空间可直接减半,且性能通常下降很小。

更进一步的方法是权值聚类 (Weight Clustering):

  1. 对网络中所有权重数值进行聚类(例如分成4类)。

  2. 每一类用一个代表值(如该类权重的均值)来表示。

  3. 存储时,只需保存一个“聚类中心值表”和每个权重所属的“聚类索引”。如果只有4类,那么每个权重只需2个比特即可表示其索引,极大地压缩了存储空间。

还可以结合霍夫曼编码 (Huffman Encoding) 等无损压缩技术,对常见的聚类索引使用更短的码,进一步减少平均存储长度。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_13.png

二值化权重 (Binary Weights)

参数量化的终极形式之一是二值化权重,即每个参数只能是+1或-1。这样每个参数仅需1个比特存储。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_15.png

你可能会认为二值化网络的性能会很差,但事实并非如此。例如,在论文《BinaryConnect》中,作者在MNIST和CIFAR-10数据集上实验发现,二值化网络的错误率有时甚至略低于全精度网络。一个可能的原因是,二值化给模型能力施加了更强的限制,反而有助于防止过拟合。


网络架构设计 (Network Architecture Design) 🏗️

通过设计更高效的网络架构,可以直接减少参数量。本节介绍本次作业的主力方法:深度可分离卷积 (Depthwise Separable Convolution)。

在讲解它之前,我们先快速回顾标准卷积 (Standard Convolution):

  • 输入特征图有 I 个通道。

  • 每个卷积核是一个3D张量,其“深度”必须与输入通道数 I 相同(例如3x3xI)。

  • 如果有 O 个卷积核,则输出特征图有 O 个通道。

  • 总参数量 = 卷积核尺寸 (如 K x K) x 输入通道数 I x 输出通道数 O。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_17.png

深度可分离卷积将标准卷积分解为两个步骤:

第一步:深度卷积 (Depthwise Convolution)

  • 输入有 I 个通道,就使用 I 个卷积核。

  • 每个卷积核只负责一个输入通道,在单个通道上进行卷积。

  • 输出特征图通道数仍为 I。这一步负责处理空间特征(同一通道内像素间的关系),但忽略了通道间的关系。

第二步:逐点卷积 (Pointwise Convolution)

  • 使用 O 个大小为 1x1 的卷积核。

  • 这些1x1卷积核的作用是:对深度卷积输出的 I 个通道进行线性组合,以生成 O 个输出通道。

  • 这一步专门负责融合通道间的关系。

参数量对比:

  • 深度卷积参数量:K x K x I (每个通道一个KxK核)

  • 逐点卷积参数量:1 x 1 x I x O (O个1x1xI的核)

  • 总参数量:K x K x I + I x O

与标准卷积参数量 (K x K x I x O) 的比值约为:1/O + 1/(K*K)。由于 O 通常较大,比值主要由 1/(K*K) 决定。当K=3时,参数量可减少到约1/9;当K=2时,可减少到约1/4。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_19.png

原理:深度可分离卷积的本质是一种低秩近似 (Low-rank Approximation)。它将一个全连接层(可视为大矩阵)分解为两个更薄矩阵的乘积,从而在保持表达能力的同时显著减少参数。


动态计算 (Dynamic Computation) ⚡

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_21.png

动态计算的目标与前几种方法不同:它并非单纯追求网络变小,而是希望同一个网络能根据可用计算资源动态调整其计算量。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_23.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_25.png

应用场景:

  1. 同一模型需部署在不同算力的设备上。

  2. 同一设备在不同状态下(如电量充足 vs 电量不足)对算力的需求不同。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_27.png

为什么不直接准备多个不同大小的网络? 因为存储多个网络模型会占用大量空间。我们期望一个模型就能灵活适配。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_29.png

实现动态计算的方法

1. 动态深度 (Dynamic Depth)

  • 训练一个很深的网络,并在中间层插入额外的“提前退出分支”。

  • 每个分支都可以输出分类结果。

  • 训练时,要求所有分支的输出都尽量接近真实标签。

  • 推理时,算力充足则使用最终输出;算力不足则可在浅层分支提前输出结果。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_31.png

2. 动态宽度 (Dynamic Width)

  • 训练时,让网络同时以多种“宽度”(即激活不同比例的神经元子集)进行前向传播。

  • 要求所有宽度下的输出都接近真实标签。

  • 推理时,根据可用算力选择对应的宽度。

3. 网络自适应决策

  • 让网络根据输入样本的“难度”自行决定需要多少计算量。对于简单样本,早期层就能做出准确判断并提前退出;对于复杂样本,则运行到深层。

  • 这可以进一步节省计算资源。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_33.png


总结 🎯

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_35.png

本节课我们一起学习了多种神经网络压缩与加速技术:

  1. 知识蒸馏:让小型学生网络学习大型教师网络的输出分布,以提升小模型性能。

  2. 参数量化:通过降低数值精度、权值聚类等方法,减少存储每个参数所需的比特数。

  3. 网络架构设计:重点介绍了深度可分离卷积,通过将标准卷积分解为深度卷积和逐点卷积,大幅减少参数量。

  4. 动态计算:使网络能够根据可用计算资源或输入难度,动态调整其深度或宽度。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/6f265fb5b21f41a90e902fa589cd2483_37.png

需要注意的是,这些技术并非互斥。在实际应用中,为了达到极致的压缩效果,可以组合使用多种技术,例如先进行知识蒸馏,再进行网络剪枝,最后对权重进行量化。

84 - 近端策略优化 (PPO) 🚀

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_1.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_3.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_5.png

概述

在本节课中,我们将要学习强化学习中的一个重要算法——近端策略优化。我们将从策略梯度的基础出发,探讨如何将其从“在线策略”改进为更高效的“离线策略”方法,并最终理解PPO算法的核心思想和实现方式。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_7.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_9.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_11.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_13.png

从策略梯度到PPO

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_15.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_17.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_19.png

上一节我们介绍了策略梯度方法。本节中我们来看看它的一个重要变体——近端策略优化。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_21.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_23.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_25.png

PPO是目前OpenAI默认的强化学习算法。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_27.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_29.png

在讲解PPO之前,我们需要先理解在线策略和离线策略这两种训练方法的区别。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_31.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_33.png

在线策略 vs. 离线策略

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_35.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_37.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_39.png

我们知道,在强化学习中,我们要训练的是一个智能体。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_41.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_43.png

如果我们用来与环境互动的智能体,和我们要学习的智能体是同一个,这叫做在线策略。如果我们学习的智能体,和与环境互动的智能体不是同一个,这叫做离线策略。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_45.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_47.png

拟人化地说,如果智能体一边与环境互动一边学习,这叫在线策略。如果它是在旁边看别人玩,通过观察来学习,这叫离线策略。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_49.png

以下是棋魂的比喻:

  • 如果阿光自己下棋自己学,这是在线策略。

  • 如果他在旁边看佐为下棋,这是离线策略。

为何需要离线策略?

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_51.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_53.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_55.png

让我们回想一下之前讲过的策略梯度。我们之前讲的策略梯度,是在线策略还是离线策略的做法呢?

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_57.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_59.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_61.png

它是在线策略的做法。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_63.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_65.png

为什么?我们之前讲在做策略梯度时,需要一个智能体,需要一个策略,需要一个执行者。这个执行者先去与环境互动,搜集资料,收集很多轨迹。根据收集到的资料,按照策略梯度的公式去更新策略的参数。这就是我们之前讲过的策略梯度。所以它是一个在线策略的算法,拿去与环境互动的策略和要学习的策略是同一个。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_67.png

今天的问题是,在更新的公式里,其中有一项期望值,是针对你当前策略参数θ所采样出的轨迹τ取的期望。所以当你更新参数后,一旦参数从θ变成θ‘,这个概率就不对了,之前采样出的数据就变得不能用了。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_69.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_71.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_73.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_75.png

所以我们之前就讲过,策略梯度是一个会花很多时间来采样数据的算法。你会发现大多数时间都在采样数据。与环境互动后,接下来就要更新参数。每次更新完参数一次,你只能做一次梯度下降。更新完参数一次,接下来你就要重新再去收集数据,然后才能再次更新参数。这显然是非常花时间的。

离线策略的优势

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_77.png

现在我们想从在线策略变成离线策略的好处是,我们希望可以用另外一个策略,另外一个执行者θ‘去跟环境做互动,用θ‘收集到的数据去训练θ。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_79.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_81.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_83.png

假设我们可以用θ‘收集到的数据去训练θ,意味着我们可以把θ‘收集到的数据使用非常多次。在做梯度上升时,我们可以执行梯度上升好几次,可以更新参数好几次,都只要用同一批数据就好了。因为假设现在θ有能力从另外一个执行者θ‘所采样的数据来学习的话,那θ‘就只要采样一次,采样多一点的数据,让θ去更新很多次,这样就会比较有效率。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_85.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_87.png

重要性采样

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_89.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_91.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_93.png

那么怎么做呢?这边就需要介绍一个叫做重要性采样的概念。这个重要性采样的概念不是只能用在强化学习上,它是一个通用的想法,可以用在很多其他地方。我们先介绍这个通用的想法。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_95.png

假设现在你有一个函数f(x),你要计算从分布P采样x,再把x带到f里面得到f(x),你要计算这个f(x)的期望值。怎么做呢?假设你今天无法对分布P做积分,那你可以从分布P去采样一些xi,那么这个期望值,就近似于你采样到的xi,把xi带到f(xi)里面,然后取它的平均值。假设你知道怎么从分布P做采样的话,你要算这个期望值,你只需要从分布P做采样就好。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_97.png

但是我们现在有另外一个问题。我们无法从分布P里面采样数据。我们只能从另外一个分布Q去采样数据。Q这个分布可以是任何分布。我们不能从P采样数据,但我们可以从Q去采样x^i。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_99.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_101.png

我们不能够直接套用从P采样的近似公式,因为那个公式假设你的xi都是从P采样出来的。从Q采样出来的xi套那个公式,你不会等于左边这一项期望值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_103.png

所以怎么办?作为一个修正,这个修正是这样的。期望值这一项,其实就是积分f(x)乘上P(x)。我们现在上下都同乘Q(x),上下同乘Q(x)不会改变任何事。但是我们可以把这个式子写成,对Q里面所采样出来的x取期望值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_105.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_107.png

我们从Q里面采样x,然后再去计算f(x)乘上P(x)除以Q(x),再去取期望值。左边这一项会等于右边这一项。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_109.png

要算左边这一项,你要从分布P采样x。但要算右边这一项,你不是从分布P去采样x,你是从分布Q去采样。你从分布Q采样出来以后,再代入f(x)乘上P(x)/Q(x),接下来你就可以计算左边这项你想要算的期望值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_111.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_113.png

所以就算是我们不能够从P里面采样数据,你想要计算这一项的期望值也是没有问题的。你只要能够从Q里面去采样数据,代入这个式子,你就一样可以计算从分布P采样x代入f以后所算出来的期望值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_115.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_117.png

这两个式子唯一不同的地方是,一个是从P做采样,一个是从Q做采样。因为它是从Q里面做采样,所以采样出来的每一笔数据你需要乘上一个权重,修正这两个分布之间的差异。而这个权重就是P(x)的值除以Q(x)的值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_119.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_121.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_123.png

所以Q(x)其实它是任何分布都可以。这边唯一的限制就是你不能够在P(x)不为零但Q(x)为零的时候使用,不然会没有定义。假设Q(x)是零的时候,P(x)也都是零的话,那这样P/Q是有定义的,这个时候你就可以应用重要性采样这个技巧。所以你就可以从本来是从P做采样,换成从Q做采样。

重要性采样的问题

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_125.png

这个跟我们刚才讲的有什么关系呢?跟刚才讲的从在线策略变成离线策略有什么关系呢?在继续讲之前,我们来看一下重要性采样的问题。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_127.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_129.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_131.png

在理论上你可以把P换成任何的Q,但是在实践上并没有那么容易。实践上P跟Q还是不能够差太多,如果差太多的话,会有一些问题。什么样的问题呢?

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_133.png

虽然我们知道左边这个式子的期望值等于右边这个式子的期望值。左边这个随机变量的分布是P,右边这个随机变量(f(x) * P(x)/Q(x))的分布是Q。我们现在如果不是算期望值,而是算方差的话,这两个方差你觉得他会一样吗?它们是不一样的。两个随机变量,它们的均值一样,并不代表它的方差一样。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_135.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_137.png

所以今天你可以实际算一下,f(x)这个随机变量跟f(x)乘以P/Q这个随机变量,它们的方差是不是一样的。计算后会发现,如果P除以Q差距很大的话,后面这一项的方差就会很大。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_139.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_141.png

所以虽然理论上它的期望值一样,也就是说你只要对分布P采样足够多次,对分布Q采样足够多次,你得到的结果会是一样的。但是假设你采样的次数不够多,因为它们的方差差距是很大的,所以你就有可能得到非常大的差别。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_143.png

如果这个地方你听的不是很懂,那没有关系,这边举一个具体的例子,告诉你说当P跟Q的差距很大的时候,会发生什么样的问题。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_145.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_147.png

假设P的分布集中在左侧,Q的分布集中在右侧,f(x)在左侧是负的,在右侧是正的。如果我们要计算f(x)的期望值,它的分布是从P的分布来采样,那显然这一项是负的。因为f(x)在P(x)几率高的区域是负的,只要采样都会采样到这个地方,所以理论上这一项算出来会是负的。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_149.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_151.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_153.png

接下来我们改成从Q这边做采样。因为Q在右边这边的几率比较高,所以如果你采样点不够的话,那你可能都只采样到右侧。如果你都只采样到右侧的话,你会发现算起来右边这一项搞不好是正的。因为你这边采样到这些点,然后你去计算它们的f(x) * P/Q都是正的,所以你采样这些点他们都是正的,所以你取期望值以后也都是正的。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_155.png

但为什么会这样?那是因为你采样的次数不够多。因为假设你采样次数很少,有可能只采样到右边这边。但左边这边几率虽然很低,但也不是没有可能被采样到。假设你今天好不容易终于采样到左边的点,因为左边的点P跟Q是差很多的,Q很小,P很大,所以今天f(x)好不容易采样到一个负的,这个负的就会被乘上一个非常大的权重,就可以平衡掉刚才那边一直采样到正值的情况。最后终究还是可以算出这一项的期望值是负的。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_157.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_159.png

但问题就是这个前提是你要采样足够多次,这件事情才会发生。但有可能采样次数不够,那左式和右式就有可能有很大的差距。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_161.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_163.png

所以这是重要性采样的问题。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_165.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_167.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_169.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_171.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_173.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_175.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_177.png

将重要性采样用于离线策略

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_179.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_181.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_183.png

现在要做的事情就是把重要性采样这件事,用在离线策略的情况。我要把在线策略的训练算法,改成离线策略的训练算法。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_185.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_187.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_189.png

怎么改呢?之前我们是拿θ这个策略去跟环境互动,采样出轨迹τ,然后计算目标函数。现在呢,我们不根据θ,我们不用θ去跟环境做互动。我们假设有另外一个策略,它的参数是θ‘,它就是另外一个执行者。他的工作是他要去做示范,他要去示范给你看。这个θ‘,他的工作是要去示范给θ看,他去跟环境做互动,告诉θ说他跟环境做互动时会发生什么事,然后借此来训练θ。我们要训练的是θ这个模型,θ‘只是负责做示范的,负责跟环境做互动。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_191.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_193.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_195.png

所以我们现在采样出的τ是从θ‘采样出来的,不是从θ采样出来。但我们本来要求的目标函数是针对θ的期望。我们实际上做的时候是拿θ‘去跟环境做互动,所以采样出来τ是从θ‘采样出来的。这两个分布不一样,但没有关系。我们之前说过,假设你本来是从P做采样,但你发现你不能够从P做采样(就现在我们说我们不拿θ去跟环境做互动,所以不能从P做采样),你永远可以把P换成另外一个Q,然后在后面这边补上一个重要性权重。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_197.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_199.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_201.png

所以现在的状况就是一样,把θ换成θ‘以后,要在目标函数里面补上一个重要性权重。这重要性权重就是某一个轨迹τ,它用θ算出来的几率除以这个轨迹τ,它用θ‘算出来的几率。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_203.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_205.png

这一项是很重要的,因为今天你要学习的执行者θ跟θ‘是不太一样的,所以θ‘会遇到的状况、会见到的情形跟θ见到的情形不见得是一样的,所以中间要做一个修正的项。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_207.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_209.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_211.png

所以我们做了一下修正,因为我们现在数据不是从θ采样出来的,是从θ‘采样出来的。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_213.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_215.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_217.png

离线策略的好处

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_219.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_221.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_223.png

我们从θ换成θ‘有什么好处呢?我们刚才就讲过,因为现在跟环境互动的是θ‘,而不是θ,所以今天你采样出来的东西跟θ本身是没有关系的。所以你就可以让θ‘去跟环境做几次互动,采样一大堆数据以后,θ可以更新参数很多次,然后一直到θ可能训练到一定的程度,它被更新很多次以后,θ‘再重新去做采样。这就是在线策略换成离线策略的妙用。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_225.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_227.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_229.png

具体的目标函数

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_231.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_233.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_235.png

我们其实上周有讲过,实际上在做策略梯度的时候,我们并不是给一整个轨迹τ都一样的分数,而是每一个状态-动作对我们会分开来计算。所以我们上周其实都讲过,我们实际上更新梯度的时候,我们的式子是长这个样子的:

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_237.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_239.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_241.png

我们用θ这个执行者去采样出s_t跟a_t,采样出这个状态和动作的对。我们会计算这个状态-动作对的优势函数A^θ(s_t, a_t),估测它有多好。这一项就是那个累计的奖励减掉基线。接下来后面会乘上log p_θ(a_t | s_t)。也就是说如果这一项是正的,就要增加这个动作的几率,这一项是负的,就要减少几率。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_243.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_245.png

那我们现在就用了重要性采样的技术,把在线策略变成离线策略。我就把在线策略变成离线策略,就从θ变成θ‘。所以现在s_t, a_t它不是θ跟环境互动以后所采样到的数据,它是θ‘另外一个执行者跟环境互动以后所采样到的数据,但是拿来训练我们要调整参数的模型θ。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_247.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_249.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_251.png

但是我们有说过,因为θ‘跟θ是不同的模型,所以你要做一个修正的项。而这项修正项就是重要性采样的技术,把s_t, a_t用θ采样出来的几率除掉s_t, a_t用θ‘采样出来的几率。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_253.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_255.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_257.png

这边其实有一件事情我们需要稍微注意一下。这边A有一个上标θ,代表这个是执行者θ跟环境互动的时候所计算出来的A。但是实际上,当我们今天从θ换到θ‘的时候,这一项其实你应该改成A{θ‘},而不是Aθ。因为这个优势函数A这一项是怎么来的?这一项是想要估测说现在在某一个状态,采取某一个动作,接下来会得到的累计奖励的值减掉基线。之前是θ在跟环境做互动,所以你观察到的是θ可以得到的奖励。但现在不是θ跟环境做互动,现在是θ‘在跟环境做互动,所以你得到的这个优势函数,其实是根据θ‘所估计出来的优势函数。但我们现在先不要管那么多,我们就假设这两项可能是差不多的。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_259.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_261.png

接下来呢,这个p_θ(s_t, a_t)这一件事情你可以拆解成p_θ(s_t)的几率乘上p_θ(a_t|s_t)的几率。然后接下来这边需要做一件事情,是我们假设当你的模型是θ的时候,你看到s_t的几率跟你的模型是θ‘的时候,你看到s_t的几率是差不多的,你把它删掉,因为它们是一样的。为什么可以假设它是差不多的?当然你可以找一些理由,举例来说,会看到什么状态往往跟你采取什么样的动作是没什么太大的关系的。但是有一个更直接的理由就是,这一项到时候真的要你算,你会算吗?你不觉得这一项其实你不太能算吗?尤其是你如果输入是图像的话,同样的s_t根本就没有出现过第二次,所以根本没办法估这一项。所以干脆就无视这个问题。而p_θ(a_t|s_t)这个几率你是会算的,对不对?这个很好算,因为你有θ这个参数,它就是个网络,你就把s_t带进去,它就会告诉你某一个动作的几率是多少。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_263.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_265.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_267.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_269.png

所以这一项你只要知道θ参数,知道θ‘参数,这个就可以算。那p(s_t)这一项不太好算,这就说服自己说这一项其实不太会有影响,我们只管前面这个部分就好了。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_271.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_273.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_275.png

推导目标函数

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_277.png

所以现在,我们得到了一个新的目标函数。这一项是那个梯度。那其实我们可以从这个梯度去反推原来的目标函数。怎么从梯度去反推原来的目标函数呢?这边有一个公式,f(x)的梯度等于f(x)乘上gradient log f(x)。所以我们要做的事情,就是这个是梯度的项,我们要还原说原来没有取梯度之前的样子。那是什么样子呢?其实就是把这个梯度拿掉,所以就变成下面这个式子。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_279.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_281.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_283.png

所以实际上当我们应用重要性采样的时候,我们要去优化的那个目标函数长什么样子呢?我们要去优化的那个目标函数就长这样。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_285.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_287.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_289.png

我们把它写作J^{θ‘}(θ)。这个括号里面,θ代表是我们要去优化的那个参数,θ‘代表是我们拿θ‘去做示范。现在在跟真正在跟环境互动的是θ‘,是θ‘在跟环境互动。你用θ‘去跟环境互动,采样出s_t, a_t以后,那你要去计算s_t和a_t的优势函数A^{θ‘}(s_t, a_t),然后呢你再去把它乘上p_θ(a_t|s_t),再除掉p_{θ‘}(a_t|s_t)。那这两项都是好算的,这一项A你是可以从数据里面估测出来的。所以这一整项你是可以算的。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_291.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_293.png

那么实际上在更新参数的时候,就是按照上面这个式子来更新参数。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_295.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_297.png

所以我们现在做的事情就是,我们可以把在线策略换成离线策略。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_299.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_301.png

近端策略优化 (PPO)

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_303.png

但是我们会遇到的问题是,我们在前面讲重要性采样的时候,我们说重要性采样有一个问题:其实你的p_θ跟p_{θ‘}不能差太多。差太多的话,你重要性采样的结果就会不好。如果p_θ跟p_{θ‘}差太多的话,重要性采样的结果就会不好。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_305.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_307.png

所以怎么避免它差太多呢?这个就是PPO在做的事情。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_309.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_311.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_313.png

PPO 的核心思想

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_315.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_317.png

PPO虽然如果你看它原始的论文,它里面写了很多的数学式,但它实际上做的事情是怎样呢?它实际上做的事情就是这样,它说我们原来在离线策略的方法里面,我们要优化的是这个目标函数。但是我们又说,因为这个目标函数它牵涉到重要性采样,而重要性采样要求p_θ不能跟p_{θ‘}差太多,你做示范的模型跟那个真正的模型不能够差太多,差太多的话,重要性采样的结果就会不好。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_319.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_321.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_323.png

所以我们在训练的时候多加一个约束。这个约束是什么?这个约束是θ跟θ‘这两个模型,它们输出的动作分布的KL散度。简单来说这一项的意思,就是要衡量说θ跟θ‘有多像。然后我们希望在训练的过程中,我们训练出来的θ跟θ‘越像越好,因为θ如果跟θ‘不像的话,最后你做出来的结果就会不好。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_325.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_327.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_329.png

所以在PPO里面有两个式子,一方面就是优化你本来要优化的东西,但是再加一个约束,这个约束就好像那个正则化项一样。我们在做训练的时候,不是有L1跟L2正则化吗?这一项也很像正则化项。正则化做的事情,就是希望最后训练出来的θ不要跟θ‘太不一样。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_331.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_333.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_335.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_337.png

PPO 与 TRPO

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_339.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_341.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_343.png

PPO有一个前身叫做TRPO。TRPO写的式子呢是这个样子的,它唯一不一样的地方是说,这个约束摆的位置不一样。PPO是直接把那个约束放到你要优化的那个式子里面,然后接下来你就可以用梯度上升的方法去最大化这个式子。但是如果是在TRPO的话,它是把KL散度当做一个约束,希望θ跟θ‘的KL散度小于一个δ。你知道在做那种有约束的优化时,如果你用基于梯度下降的优化方法,有约束是很难处理的。所以你会发现PPO在实践上比TRPO容易得多。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_345.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_347.png

文献上的结果是,PPO跟TRPO可能表现差不多,但是PPO在实践上比TRPO容易得多。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_349.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_351.png

关于KL散度的注意点

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_353.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_355.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_357.png

这边要注意一下,就是这边所谓的KL散度到底指的是什么?这边我是直接把KL散度当做一个函数,它吃的输入是θ跟θ‘。但我的意思并不是说把θ当做一个分布,把θ‘当做一个分布,算这两个分布之间的距离。我不是这个意思。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_359.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_361.png

今天这个所谓的θ跟θ‘的距离,并不是参数上的距离,而是它们的行为上的距离。假设你现在有一个模型θ,你有另外一个模型θ‘。所谓的参数上的距离,就是你算这两组参数有多像。但这不是我今天这边所讲的这个距离。我这边所讲的不是参数上的距离,我这边所讲的是它们的行为上的距离。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_363.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_365.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_367.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/db6658133db27bd03532a790377cbc37_369.png

就是你输入进去一个状态s,然后今天它会输出一个分布,它对动作空间输出一个分布。假设你有三个可能的动作,它会输出三个几率值。那我们今天所指的距离,则是行为距离,也就是说给同样的状态的时候,它们输出的这个动作分布之间的差距。这两个动作的分布都是一个几率分布,所以就可以计算这两个几率分布

85:深度强化学习第三讲 - Q-learning (基本概念) 🧠🤖

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_1.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_3.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_5.png

概述

在本节课中,我们将要学习强化学习中的一种核心方法——Q-learning。我们将从Q-learning的基本概念开始,介绍其背后的两种价值函数,并详细讲解如何训练Q函数以及实际应用中的关键技巧。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_7.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_9.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_11.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_13.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_15.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_17.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_19.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_21.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_23.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_25.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_27.png

Q-learning简介

Q-learning是一种基于价值(value-based)的强化学习方法。与直接学习策略(policy)的方法不同,基于价值的方法旨在学习一个“评论家”(critic)。这个评论家并不直接采取行动,而是负责评估在给定状态下,某个行动者(actor)的行为有多好或多差。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_29.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_31.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_33.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_35.png

状态价值函数

首先,我们介绍一种评论家,称为状态价值函数(State Value Function)。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_37.png

公式定义:V^π(s)

  • V^π 是一个函数。

  • 输入:一个状态 s。

  • 输出:一个标量值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_39.png

这个标量的含义是:假设我们有一个策略(行动者)π,当它观察到状态 s 时,从该状态开始一直与环境互动到游戏结束,所获得的累积奖励的期望值有多大。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_41.png

核心概念强调:价值函数的输出与特定的行动者 π 紧密相关。它评估的是“在状态 s 下,如果接下来都由策略 π 来决策,预计能得到多少回报”,而不是孤立地评估状态 s 本身的好坏。不同的策略在同一个状态下,预期回报可能截然不同。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_43.png

如何估计状态价值函数

上一节我们介绍了状态价值函数的概念,本节中我们来看看如何实际估计这个函数 V^π(s)。主要有两种方法:

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_45.png

1. 蒙特卡洛方法(MC-based)

这种方法非常直观:让策略 π 去与环境多次互动,直接统计从状态 s 开始到游戏结束所获得的实际累积奖励 G。由于我们无法遍历所有可能的状态,通常会用神经网络来拟合 V^π(s)。

训练方式:这是一个回归问题。我们将状态 s 输入网络,希望网络的输出值逼近实际观测到的累积奖励 G。通过最小化预测值与目标值 G 之间的误差(如均方误差)来训练网络。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_47.png

2. 时序差分方法(TD-based)

蒙特卡洛方法需要等到整个回合(episode)结束才能进行更新,对于长回合任务效率较低。时序差分方法可以在每一步进行更新。

其核心基于以下公式:

V^π(s_t) = r_t + V^π(s_{t+1})

这个公式表明,当前状态 s_t 的价值,应该等于立即奖励 r_t 加上下一个状态 s_{t+1} 的价值。

训练方式:我们同样用神经网络来拟合 V^π。在训练时,我们希望网络对 s_t 的输出值 V(s_t) 与 r_t + V(s_{t+1}) 尽可能接近。通过最小化二者之间的差异来更新网络参数。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_49.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_51.png

MC与TD方法的比较

以下是两种方法的主要区别:

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_53.png

  • 方差:MC方法使用从状态到回合结束的完整奖励和 G 作为目标,G 是多个随机奖励的和,因此方差较大。TD方法只使用单步奖励 r_t,方差较小。

  • 偏差:TD方法的目标值依赖于当前价值网络 V(s_{t+1}) 的估计,如果估计不准,则会引入偏差。MC方法的目标 G 是实际观测值,无偏差。

  • 结果差异:即使观察相同的训练数据,MC和TD方法估算出的价值函数也可能不同,因为它们对数据背后因果关系的假设不同。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_55.png


状态-行动价值函数(Q函数)

除了评估状态的价值,我们更常使用一种能评估“状态-行动对”价值的函数,即 Q函数(State-Action Value Function)。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_57.png

公式定义:Q^π(s, a)

  • Q^π 是一个函数。

  • 输入:一个状态 s 和一个行动 a。

  • 输出:一个标量值。

这个标量的含义是:在状态 s 下,强制采取行动 a(无论策略 π 本身是否会采取这个行动),然后接下来一直使用策略 π 进行决策,直到游戏结束所能获得的累积奖励期望值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_59.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_61.png

输出形式:

  1. 输入 s 和 a,输出单个标量值。

  2. 对于离散行动空间,更常见的写法是:输入状态 s,网络输出一个向量,向量的每个元素对应在状态 s 下采取每个可能行动的Q值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_63.png


从Q函数到更好的策略

虽然Q函数 Q^π 是为评估特定策略 π 而设计的,但神奇的是,一旦我们学到了 Q^π,我们就可以据此得到一个更好的新策略 π’。

定义“更好”:对于所有可能的状态 s,新策略 π’ 的价值都不低于原策略 π,即 V^{π’}(s) >= V^π(s)。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_65.png

如何找到 π’:

新策略 π’ 的决策规则非常简单:在每一个状态 s 下,选择那个能使当前Q值最大的行动。

公式:π’(s) = argmax_a Q^π(s, a)

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_67.png

可以证明,按照这个规则得到的新策略 π’,其表现一定不差于原来的策略 π。这样,我们就能通过“评估Q函数 -> 改进策略 -> 用新策略收集数据 -> 评估新Q函数”的循环,使策略不断进化。这就是Q-learning的核心思想。

注意:对于连续行动空间,求解 argmax_a 操作会变得困难,这是后续需要解决的问题。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_69.png

Q-learning的训练技巧

上一节我们介绍了Q-learning的基本框架,本节中我们来看看在实际训练中必不可少的三个关键技巧。

技巧一:目标网络(Target Network)

在应用TD思想训练Q函数时,我们希望满足:Q(s_t, a_t) = r_t + Q(s_{t+1}, a*)。如果直接用同一个网络同时计算预测值和目标值,会导致训练不稳定,因为目标值也在不断变化。

解决方法:使用两个结构相同但参数更新不同步的网络。

  • 主网络(Q):负责产生预测值 Q(s_t, a_t),其参数持续更新。

  • 目标网络(Q’):负责产生目标值 r_t + Q’(s_{t+1}, a*),其参数在一段时间内保持固定。

  • 操作:将主网络的输出向目标网络产生的固定目标值进行回归拟合。每隔一定步数(如C步),将主网络的参数复制给目标网络。

技巧二:探索(Exploration)

如果完全按照Q函数的最大值贪婪地选择行动(argmax),智能体可能会过早地局限于某个看似不错的行动,而无法探索其他可能更好的行动,导致收集到的数据有偏。

以下是两种常用的探索策略:

  • ε-贪心(ε-greedy):以 1-ε 的概率选择Q值最大的行动,以 ε 的概率随机选择行动。通常 ε 随着训练进行而逐渐减小。

  • 玻尔兹曼探索(Boltzmann Exploration):根据Q值计算一个概率分布,Q值越高的行动被选中的概率越大,但低Q值行动也有一定机会。公式为:P(a|s) ∝ exp(Q(s, a))。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_71.png

技巧三:经验回放(Replay Buffer)

让智能体与环境交互收集数据是强化学习中最耗时的部分。经验回放可以提升数据利用效率。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_73.png

操作方法:

  1. 维护一个固定大小的缓冲区(Buffer)。

  2. 智能体与环境交互得到的每一步经验(s_t, a_t, r_t, s_{t+1})都被存入缓冲区。

  3. 训练时,随机从缓冲区中采样一小批(mini-batch)经验数据,用于更新Q网络。

好处:

  1. 提升数据效率:一条经验可以被多次用于训练,减少了与环境交互的次数。

  2. 稳定训练:随机采样打破了经验之间的相关性,使用于更新网络的数据批(batch)更加多样,有助于训练稳定。

  3. 支持异策略学习:缓冲区中的经验可能来自不同的策略,这使Q-learning天然是一种异策略(off-policy)算法,能更灵活地利用历史数据。


典型的Q-learning算法流程

结合以上所有技巧,一个典型的Q-learning算法步骤如下:

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_75.png

  1. 初始化:初始化主Q网络 Q 和目标网络 Q’(令 Q’ = Q)。初始化经验回放缓冲区 D。

  2. 循环每个回合(Episode):

    a. 交互:对于每一步 t,根据当前状态 s_t 和Q网络(配合探索策略,如ε-贪心)选择行动 a_t。执行 a_t 获得奖励 r_t 和新状态 s_{t+1}。将经验 (s_t, a_t, r_t, s_{t+1}) 存入缓冲区 D。

    b. 采样:从缓冲区 D 中随机采样一个批次的经验数据 (s_i, a_i, r_i, s_{i+1})。

    c. 计算目标:对于批次中的每个样本,计算目标值 y_i = r_i + γ * max_{a} Q’(s_{i+1}, a)。(γ 为折扣因子,通常小于1,此处为简化未在前文强调)。

    d. 更新网络:将 Q(s_i, a_i) 向 y_i 回归,通过梯度下降更新主Q网络 Q 的参数。

    e. 更新目标网络:每隔C步,将目标网络参数更新为当前主网络的参数(Q’ <- Q)。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/bfffb4cd647ef3cf4d38c9da7911d03a_77.png

总结

本节课中我们一起学习了Q-learning的基本原理。我们从基于价值的强化学习概念出发,介绍了状态价值函数 V(s) 和更重要的状态-行动价值函数 Q(s, a)。我们学习了如何使用蒙特卡洛和时序差分方法来估计这些价值函数,并比较了它们的优劣。核心在于,我们可以通过评估当前策略的Q函数,并采用 argmax 规则来改进策略,从而不断迭代优化。最后,我们详细讲解了实际训练Q-learning时的三个关键技术:目标网络、探索机制和经验回放,它们共同保证了算法训练的稳定性和效率。

86:深度强化学习进阶技巧 🚀

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_1.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_3.png

在本节课中,我们将学习训练Q-learning模型时的一些高级技巧。这些技巧旨在解决Q值高估、提升训练效率、改进探索策略等问题,帮助你构建更稳定、更强大的强化学习智能体。


1. Double DQN 🎯

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_5.png

上一节我们介绍了基础的Q-learning。本节中我们来看看如何解决Q值被高估的问题。

在实践操作中,你会发现Q值往往被高估。下图来自Double DQN的原始论文,展示了四个不同游戏中的结果。横轴是训练时间,红色锯齿线是Q函数估计出的平均Q值。随着策略变强,这个值会不断上升。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_7.png

但问题是,Q网络估计出的值(红色线)远大于实际通过策略玩游戏得到的真实累计奖励(绿色线)。Double DQN的目标就是让估计值与实际值更接近。

为什么Q值会被高估?

这与我们计算目标值的方式有关。在更新Q网络时,我们使用以下目标:

target = r + max_a Q(s', a)

这个max操作总是会选择被高估的那个动作的Q值来构建目标,从而导致目标值系统性偏高。

Double DQN的解决方案

Double DQN的核心思想是使用两个Q网络来解耦“选择动作”和“评估价值”这两个步骤。

  • 选择动作的网络 (Q):用于选择下一个状态s‘下哪个动作a‘能给出最大的Q值。

  • 评估价值的网络 (Q‘):用于计算在状态s‘下,执行动作a‘所对应的Q值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_9.png

最终的目标值计算公式变为:

target = r + Q‘(s‘, argmax_a Q(s‘, a))

这样做的好处:即使第一个网络Q高估了某个动作的价值,只要第二个网络Q‘没有高估这个动作,最终的目标值就不会被高估。这类似于“立法”与“行政”的分离。

实际实现:你通常已经有两个网络——正在更新的在线网络(online network)和固定参数的目标网络(target network)。在Double DQN中,你只需用在线网络来选择动作,用目标网络来计算该动作的价值。这通常只需修改一行代码。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_11.png

2. Dueling DQN ⚔️

接下来,我们介绍一种通过改变网络架构来提升学习效率的方法——Dueling DQN。

Dueling DQN的核心是修改了Q网络的输出结构。它不再直接输出每个动作的Q值,而是将输出分解为两个部分:

  1. 状态价值 V(s):一个标量,代表状态s本身的好坏。

  2. 优势函数 A(s, a):一个向量,每个维度代表在状态s下,采取特定动作a相对于平均水平的优势。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_13.png

最终的Q值由这两部分相加得到:

Q(s, a) = V(s) + A(s, a)

具体网络结构:

  • 输入状态s。

  • 网络输出一个标量V(s)和一个向量[A(s, a1), A(s, a2), ...]。

  • 将V(s)加到向量A(s, a)的每一个元素上,得到最终的Q值向量[Q(s, a1), Q(s, a2), ...]。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_15.png

这样做有什么好处?

考虑一个Q值表格。更新时,如果我们只想提高某几个动作的Q值,网络可以选择只更新V(s)。由于V(s)被加到所有动作的Q值上,这相当于间接更新了所有未被采样到的动作的Q值,从而更高效地利用了数据。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_17.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_19.png

如何避免网络退化?

如果不加约束,网络可能学到一个简单的解:令A(s, a)全为0,让V(s)等于Q值,这就退化成了普通的DQN。为了避免这种情况,我们需要对优势函数A(s, a)施加约束。

一个常见的约束是强制每个状态下所有动作的优势值之和为零:

sum_a A(s, a) = 0

这使得V(s)可以理解为该状态下所有动作Q值的平均值。这个约束可以通过在网络输出A(s, a)后,添加一个去均值(zero-mean)的归一化层来实现。这个层没有额外参数,但能保证优势函数的和为零,从而鼓励网络更多地利用V(s)来传递更新信息。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_21.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_23.png

3. 优先级经验回放 🎲

之前我们从经验回放缓冲区(replay buffer)中均匀采样数据来训练。但并非所有经验都一样重要。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_25.png

优先级经验回放(Prioritized Experience Replay)的基本思想是:让训练难度更大(即TD误差更大)的经验有更高的概率被采样到。TD误差是网络预测值与目标值之间的差距,误差大说明这个经验当前学得不好,应该多学几次。

以下是其核心要点:

  • 它改变了采样数据的分布,不再是均匀采样。

  • 实现时,不仅会改变采样概率,通常还会相应调整参数更新的权重,以纠正因非均匀采样引入的偏差。具体细节可参考相关论文或由助教进一步讲解。


4. 多步引导(Multi-step)🔄

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_27.png

我们曾讨论过蒙特卡洛(MC)方法和时序差分(TD)方法各有优劣。多步引导是一种在两者间取得平衡的方法。

传统的一步TD只存储单步经验(s_t, a_t, r_t, s_{t+1})。多步引导则存储连续的N步经验:

(s_t, a_t, r_t, s_{t+1}, ..., s_{t+N}, a_{t+N}, r_{t+N}, s_{t+N+1})

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_29.png

更新时,目标值由前N步的真实奖励和第N步后的估计Q值共同构成:

target = r_t + γ * r_{t+1} + ... + γ^{N-1} * r_{t+N-1} + γ^N * max_a Q(s_{t+N}, a)

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_31.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_33.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_35.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_37.png

优点:相比一步TD,它减少了因Q值估计不准确带来的偏差,因为更多使用了真实奖励。

缺点:与MC方法类似,由于累加了多项奖励,目标值的方差会增大。

平衡:通过调整步数N,你可以在偏差(bias)和方差(variance)之间进行权衡。N是一个需要调节的超参数。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_39.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_41.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_43.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_45.png


5. 噪声网络(Noisy Net)🎹

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_47.png

之前我们使用ε-greedy在动作空间上加噪声进行探索。噪声网络(Noisy Net)提出了一种不同的探索方式:在参数空间上加噪声。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_49.png

具体做法:

  1. 在每个回合(episode)开始时,从你的Q网络中采样一组噪声,加到其所有参数上,得到一个带噪声的Q网络 Q_θ̃。

  2. 在整个回合中,都使用这个固定的 Q_θ̃ 网络来与环境交互,直到回合结束。

  3. 下一个回合开始时,重新采样一组新的噪声,生成新的 Q_θ̃。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_51.png

与ε-greedy的本质区别:

  • ε-greedy:给定相同的状态,智能体可能采取不同的动作(有时贪婪,有时随机)。

  • Noisy Net:在一个回合内,网络参数固定。因此,给定相同或相似的状态,智能体会采取一致的探索行为。这被称为“状态依赖的探索”(state-dependent exploration),是一种更系统、更一致的测试环境的方式。

研究表明,这种探索方式通常比ε-greedy更有效,能让智能体学到更优的策略。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_53.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_55.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_57.png

6. 分布式Q函数(Distributional Q-function)📊

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_59.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_61.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_63.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_65.png

标准的Q函数输出的是期望累计奖励。但实际上,在给定状态和动作下,由于环境的随机性,累计奖励是一个分布(distribution)。不同的分布可能有相同的期望值,但风险不同。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_67.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_69.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_71.png

分布式Q函数的目标是直接建模这个奖励的分布,而不仅仅是它的期望。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_73.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_75.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_77.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_79.png

实现思路:

  1. 将可能的累计奖励范围(如-10到10)离散化成多个区间(bin)。

  2. 对于每个动作,Q网络输出一个概率向量,表示奖励落在每个区间的概率。

  3. 例如,对于三个动作,网络会输出三个分布(如三个条形图),每个分布的概率和为1。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_81.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_83.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_85.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_87.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_89.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_91.png

好处:

  • 除了选择期望值最大的动作,你还可以考虑分布的形状(例如方差)。在期望值相近时,可以选择风险更小的动作。

  • 它能捕捉到更多关于环境随机性的信息。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_93.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_95.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_97.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_99.png

实验表明,分布式Q函数能学习到有意义的奖励分布,并能反映游戏进程(如开局时奖励分布偏右,随着危险增加逐渐左移)。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_101.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_103.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_105.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_106.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_108.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_110.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_112.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_114.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_116.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_118.png

7. 彩虹(Rainbow)🌈

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_120.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_122.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_124.png

最后,我们将所有上述技巧结合起来,就得到了强大的Rainbow方法。

研究表明,将这些彼此兼容的技术组合在一起,能带来显著的性能提升。下图展示了Rainbow(彩色线)在多个Atari游戏上的平均性能远超任何单一技术。

进一步分析发现,在Rainbow中:

  • 贡献显著的技术:多步引导(Multi-step)、优先级回放(Prioritized Replay)、分布式Q函数(Distributional)对性能提升至关重要。

  • 贡献一般的技朮:噪声网络(Noisy Net)、Dueling架构也有正面贡献。

  • 贡献较小的技术:Double DQN在Rainbow中作用不明显。论文解释称,因为分布式Q函数本身就有避免高估的倾向(由于输出范围有限,可能反而会低估大奖励),所以减轻了对Double DQN的需求。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_126.png


总结 📝

本节课我们一起学习了多种用于改进和稳定Q-learning训练的高级技巧:

  1. Double DQN:通过解耦动作选择和价值评估,解决Q值高估问题。

  2. Dueling DQN:通过分解Q值为状态价值和优势函数,提升学习效率。

  3. 优先级经验回放:根据TD误差优先级采样经验,聚焦难点。

  4. 多步引导:平衡MC和TD方法,在偏差和方差间取得权衡。

  5. 噪声网络:在参数空间进行系统、一致的探索。

  6. 分布式Q函数:建模奖励的完整分布,而不仅仅是期望值。

  7. 彩虹(Rainbow):集成以上所有技术,达到最佳性能。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/c7778683fb368d3e382bf3ca4ab9da8f_128.png

理解这些技巧的原理,能帮助你在实践中根据具体问题选择和组合合适的方法,构建更强大的强化学习模型。

87:网络压缩 📦

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_0.png

在本课程中,我们将学习网络压缩技术。我们将了解如何训练一个参数量小但性能优异的模型,并完成一个图像分类任务。课程将涵盖知识蒸馏、深度可分离卷积等核心技术,并指导你完成作业。

任务与数据集概述

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_2.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_4.png

本次作业的主题是网络压缩。我们的终极目标是训练出一个模型尺寸小,同时又能兼顾性能的模型。具体任务是训练一个非常小的模型来完成课程3中的图像分类任务。

我们使用的数据集与课程3类似,主要区别在于评估集做了一些调整。因此,你不能直接使用课程3的原始数据集,必须使用本次作业专门提供的 -11 版本数据集进行训练。请务必使用作业13的版本,否则在预测时可能会出现重大错误。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_6.png

同时,禁止尝试寻找测试集的原始标签,也不允许使用任何额外的数据集。

网络压缩技术简介

上一节我们介绍了任务目标,本节中我们来看看实现网络压缩会用到的一些关键技术。如果你对这些概念还不熟悉,可以参考李宏毅老师2021年的相关YouTube视频进行复习。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_8.png

知识蒸馏

知识蒸馏的核心思想是,从一个训练良好的教师网络中学习知识。学生网络通常是一个较小的网络,我们希望通过教师网络的输出或隐藏层的表示来提取有用的信息。

最常见的方法是使用教师网络输出的概率分布作为训练目标,希望学生网络能预测出与教师网络相似的概率分布。

在本次作业中,你需要实现一个用于知识蒸馏的损失函数。我们会提供一个在 -11 测试集上准确率达到 89.9% 的预训练 ResNet-18 教师网络。当然,你也可以自己从头训练教师网络,但必须遵循规则:不能使用额外数据,且权重必须随机初始化。

知识蒸馏损失函数通常结合了交叉熵损失和KL散度损失,公式如下:

总损失 = α * KL散度损失(教师输出/温度T, 学生输出/温度T) + (1 - α) * 交叉熵损失(学生输出, 真实标签)

其中,α 和 T 是可调节的超参数。

架构设计:深度可分离卷积

为了构建参数更少的学生网络,我们需要在架构设计上下功夫。深度可分离卷积是一种能显著减少参数量的设计。

它分为两步:

  1. 深度卷积:在每个输入通道上独立进行空间卷积,提取局部特征,此时通道间不互通。

  2. 逐点卷积:使用 1x1 卷积来组合深度卷积输出的通道,提取通道间的信息。

通过简单的计算可以比较参数量:

  • 标准卷积层参数量:I * O * K * K (I: 输入通道数, O: 输出通道数, K: 卷积核大小)

  • 深度可分离卷积参数量:I * K * K + I * O

当卷积核 K 较大时,深度可分离卷积在参数量上具有显著优势。因此,实现深度可分离卷积是通过本次作业强基线的重要步骤。

作业规则与评分标准

了解了核心技术后,我们需要明确完成作业必须遵守的规则和评分标准。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_10.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_12.png

以下是本次作业的基本规则:

  • 禁止分享代码和预测结果文件。

  • Kaggle 每日提交上限为5次。

  • 禁止使用额外数据集。

  • 禁止寻找测试集的真实标签。

  • 禁止使用任何预训练模型(需从头训练)。

  • 违反上述规则总成绩将打九折,且作业计零分。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_14.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_16.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_18.png

此外,针对网络压缩任务,还有额外规定:

  • 参数量限制:学生模型的总参数量不得超过 100K (10万)。

  • 模型验证:提交到 Kaggle 的预测结果必须来自参数量符合要求的学生模型。我们会严格检查,禁止提交教师网络的预测结果。

  • 测试数据用途:测试数据仅可用于最终学生模型的推理预测,不可用于任何形式的训练(例如,不能用教师网络对测试数据生成伪标签供学生网络学习)。

  • 集成学习:如果使用集成技术,所有学生模型的参数量总和不得超过 100K。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_20.png

评分标准如下:

  • 报告:4分

  • Kaggle竞赛:2分 (Public/Private 数据集各占0.5分)

  • 通过基线:4分 (Simple, Medium, Strong, Boss 基线各占1分)

  • 竞赛加分:Kaggle Leaderboard 前三名可额外获得1分 (作业满分10分,最高可得11分)

基线攻略指南

明确了规则,接下来我们看看如何通过各个基线。以下是达成各条基线的建议路径。

Simple Baseline

  • 直接运行并提交我们提供的示例代码即可。

Medium Baseline

  • 需要实现前面提到的知识蒸馏损失函数(KL散度损失)。

  • 在示例代码中启用知识蒸馏训练,并适当延长训练时间。

Strong Baseline

  • 需要调整模型架构,使用深度可分离卷积替代部分或全部标准卷积层。

  • 在此基础之上,可以尝试加深或加宽网络。

  • 可以参考 MobileNet, ShuffleNet 等著名轻量级网络的设计。

  • 可以应用在课程3中学到的数据增强技术和超参数调优技巧。

  • 预计训练时间为 8~12 小时。

Boss Baseline

  • 在 Strong Baseline 基础上,实现更高级的知识蒸馏技术。

  • 例如:FitNet (从教师网络的中间层表示学习)、Relational KD、DML 等。

  • 也可以尝试进一步提升教师网络的性能(但必须遵守“无额外数据”规则)。

代码示例与关键点讲解

理论介绍完毕,现在让我们结合示例代码,具体讲解实现中的关键点。你可以通过作业说明中的链接找到 Kaggle 或 Colab 上的完整 Notebook。

首先,需要安装并导入必要的包,特别是 torchsummary,用于计算模型参数量。

!pip install torchsummary
import torch
import torch.nn as nn
import torchvision.transforms as transforms
from torchsummary import summary

数据预处理部分需要注意,我们提供的教师网络输入尺寸是 224x224,而非课程3中的 128x128。调整训练变换时请留意这一点。

定义学生网络时,必须遵循以下函数签名,以便我们进行验证:

def get_student_model():
    # 你可以在此函数内自由设计你的学生网络
    # 但不要更改函数名和参数
    model = YourStudentNetwork()
    return model

使用 torchsummary 检查参数量是否合规:

student_model = get_student_model()
summary(student_model, (3, 224, 224)) # 查看 Total params 是否 <= 100,000

知识蒸馏损失函数的实现示例如下:

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_22.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_24.png

class KnowledgeDistillationLoss(nn.Module):
    def __init__(self, alpha, T):
        super().__init__()
        self.alpha = alpha
        self.T = T
        self.ce_loss = nn.CrossEntropyLoss()
        self.kl_loss = nn.KLDivLoss(reduction='batchmean')

    def forward(self, student_logits, teacher_logits, labels):
        # 计算交叉熵损失
        ce = self.ce_loss(student_logits, labels)

        # 计算KL散度损失,应用温度缩放
        student_soft = F.log_softmax(student_logits / self.T, dim=1)
        teacher_soft = F.softmax(teacher_logits / self.T, dim=1)
        kl = self.kl_loss(student_soft, teacher_soft) * (self.T ** 2)

        # 组合损失
        total_loss = (1 - self.alpha) * ce + self.alpha * kl
        return total_loss

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_26.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_28.png

在训练循环中,你需要同时将数据输入教师网络和学生网络,用教师网络的输出来计算蒸馏损失。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_30.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_32.png

报告问题详解

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_34.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_36.png

最后,我们来详细说明报告需要回答的问题。报告主要包含代码提交、理论理解和网络剪枝实验三部分。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_38.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_40.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_42.png

第一部分:代码提交

  1. 复制粘贴你最终的学生网络模型定义代码(即 get_student_model 函数内容)。

  2. 复制粘贴 torchsummary 对你学生模型的输出结果,需显示总参数量。

  3. 复制粘贴你实现的知识蒸馏损失函数代码。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_44.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_46.png

第二部分:理论理解

  • 回答关于知识蒸馏中温度参数 T 作用的单选题。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_48.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_50.png

第三部分:网络剪枝实验

  • 根据提供的 PyTorch 剪枝教程和示例代码,对教师网络进行不同比例(如 20%, 40%, 60%, 80%)的剪枝。

  • 在验证集上评估剪枝后的模型精度,并绘制 “剪枝比例 vs. 模型精度” 的关系图。

  • 鼓励对学生网络进行同样的实验并比较。

  • 回答关于 PyTorch 剪枝实现方式是否真能减少推理时间的单选题。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_52.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_54.png

提交注意事项与总结

在本节课中,我们一起学习了网络压缩的基本概念和技术,包括知识蒸馏和深度可分离卷积。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_56.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_58.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_60.png

提交时请特别注意:

  • 代码提交:除了常规的代码文件,还必须提交你最好的学生模型权重文件 (.ckpt 或 .pth 文件)。该文件体积很小,可在 Kaggle 运行后下载。

  • 报告提交:将报告提交到 Gradescope。

如果你有任何问题,欢迎在作业13的讨论区提出。

最后,请务必填写课程的后测问卷(链接在视频描述中),你的反馈对我们非常重要,且不会影响你的课程成绩。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/dd0b56d9e28b5fd7ca666457662e66b3_62.png

祝你顺利完成作业!

88:机器终身学习 (Life Long Learning, LL) (一) - 为什么今日的人工智能无法成为天网?灾难性遗忘 (Catastrophic Forgetting) 🤖🧠

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_0.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_2.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_4.png

在本节课中,我们将要学习机器终身学习的基本概念,探讨为什么当前的人工智能系统难以像人类一样持续学习新技能而不遗忘旧知识,并深入理解“灾难性遗忘”这一核心挑战。

概述

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_6.png

机器终身学习,或称持续学习,指的是让机器学习系统能够像人类一样,在一生中持续学习一系列任务,并且在学习新任务时不会忘记旧任务的知识。这是实现通用人工智能的关键一步。

什么是终身学习?

终身学习从字面翻译来看,指的是“活到老,学到老”。如果你用“lifelong learning”作为关键词搜索,通常找到的是关于人类如何终身学习的内容。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_8.png

但是,机器也需要进行终身学习。这非常接近人类对人工智能的想象:我们先教机器做一件事,比如语音识别;然后再教它第二件事,比如图像识别;接着教它第三件事,比如翻译。我们不断教它新技能,最终它就能掌握无数技能。

这个构想就是终身学习的目标。终身学习常缩写为LLL。它也有很多其他名称,例如持续学习或永不停止学习。一个不那么时髦的名字是增量学习。

你可能会想,终身学习这个目标太过远大,我又不做天网,它对我有什么意义呢?

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_10.png

终身学习的实际应用

在真实的应用场景中,终身学习也是派得上用场的。举例来说,今天你在实验室里开发出一个模型,用收集的数据训练它。模型上线后,它会获取来自用户的反馈。我们希望收集数据这件事能形成一个循环:模型上线后收集新数据,新数据让我们更新模型参数;参数更新后又能收集更多数据,如此不断循环,最终系统会越来越厉害。

你可以把旧数据看作是过去的任务,把来自用户反馈的新数据看作是新的任务。因此,这种情境也可以看作是一个终身学习问题:机器不断在线收集数据,并用这些数据更新模型。

终身学习的难点

终身学习有什么难点呢?不就是让机器不断看新数据,不断更新参数就做到了吗?为什么终身学习会是一个值得研究的问题呢?

以下举一个简单的例子来说明终身学习的难点出在什么地方。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_12.png

灾难性遗忘的实例

假设我们现在有两个任务。第一个任务是做手写数字识别,但输入的图片带有大量噪声。第二个任务也是手写数字识别,但输入的是没有噪声的清晰图片。我们要让机器学会这两个任务。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_14.png

有人可能会说,这不算是两个任务,而是同一个任务的不同领域。这样想也没问题。实际上,在终身学习的文献中,所谓的不同任务通常指的就是这种等级,更像是不同领域,而不是截然不同的任务。

我训练了一个非常简单的神经网络,它只有三层,每层50个神经元。先在任务一上训练。训练完后,任务一的正确率达到90%。即使还没看过任务二的数据,模型在任务二上也达到了96%的正确率,迁移效果非常好。

然后,我们让同一个模型继续去学习任务二。注意,是同一个模型,用任务一更新后的参数作为起点,继续用任务二的数据来更新。

结果如下:任务二的正确率变得更高了,从96%提升到97%。但糟糕的是,机器忘记了怎么做任务一:任务一的正确率从90%暴跌到只有80%。它忘记了之前已经学会的技能。

有人看到这里可能会觉得,这有什么奇怪的呢?这个网络很小,脑容量有限,学完新任务当然就忘了旧任务。

对比实验:同时学习

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_16.png

但是,如果我告诉你另一个实验呢?假设我们把任务一和任务二的数据直接混合在一起,同时训练这个网络,会发生什么事?

我们得到的结果是这样的:任务一可以得到89%的正确率,任务二可以得到98%的正确率。也就是说,对这个网络而言,它完全有能力同时学好任务一和任务二。虽然它每层只有50个神经元,但这已经足够了。

然而,如果不是同时学,而是先学任务一再学任务二,它在学任务二的时候,就会忘记任务一学过的东西。它有足够的能力把两个任务都学好,但当你让它依序学习时,它却无法记住旧的任务。

另一个例子:问答任务

我刚才举的是图像识别的例子。接下来我再举一个自然语言处理的例子,说明刚才看到的状况不是一个特例,而是一个非常普遍的现象。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_18.png

这个例子是问答任务。我们使用一个非常简单的QA数据集,叫做BABI。它包含20个用固定模板生成的简单问答任务。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_20.png

我们让机器依序学习这20个任务,看看它能否都学会。我们观察任务五的正确率变化。

纵轴是任务五的正确率,横轴是依序学习20个任务的过程。先让机器学任务一到四,此时任务五正确率为0(这很正常,因为它还没学)。学完任务五后,正确率直接冲到100%。但是,当我们继续学习任务六、任务七……时,任务五的正确率暴跌至0%。机器只要一学新任务,旧任务马上就忘得精光。

你可能会以为,是不是机器就是没有能力学好多个任务?其实不是的。

如果我们把20个任务的资料全部混合在一起,让机器同时学习,结果会怎样呢?右边这张图显示,机器可以同时学会多个任务,很多任务都能达到很高的正确率。

这个实验告诉我们:机器明明有能力学多个任务,但当你让它依序学一个一个任务时,它就是不肯把多个任务都学会。它是“非不能也,是不为也”。

灾难性遗忘

当机器依序学习多个任务时,它就像一个脑袋有洞的人,新的任务进来,旧的东西就掉出去了。它永远学不会多个技能。

这个状况叫做灾难性遗忘。在“遗忘”前面特别加上“灾难性”这个形容词,因为机器的遗忘程度太过分了,基本上是学不会新技能,所以这种遗忘是灾难性的。

为什么不把所有数据混在一起训练?

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_22.png

讲到这,你可能会有一个问题:刚才不是看到只要把多个任务的资料统统混在一起,机器就可以学会多个任务了吗?这种把所有任务数据混在一起训练的方法叫做多任务学习。那终身学习还有什么好研究的?

但是你想一想,假设现在要让机器学习第1000个任务。为了避免遗忘前面999个任务,你必须把前面999个任务的数据全部拿出来,和第1000个任务的数据混在一起进行训练。这在实践上可能有问题:

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_24.png

  1. 存储问题:机器需要把它一辈子看过的所有数据都存储下来,你可能没有那么大空间。

  2. 计算问题:把1000个任务的数据全部混在一起,训练数据量太大,训练时间会非常长。

如果机器一定要做多任务学习才能掌握多个技能,那就好比一个人要学一门新课,必须把他这辈子所有学过的教材全部重读一遍才行。这显然非常没有效率。

在文献上,通常把多任务学习看作是终身学习的性能上限。虽然当任务多时不切实际,但它给出了机器理论上能达到的最好结果。在研究终身学习时,往往会先跑一个多任务学习的结果作为上限,再比较你的终身学习方法能逼近这个上限多少。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_26.png

为什么不每个任务单独训练一个模型?

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_28.png

为什么不执着于终身学习,而是每个任务单独训练一个模型呢?这样确实没有灾难性遗忘的问题。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_30.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_32.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_34.png

但是,我们会遇到其他问题:

  1. 存储开销:如果要学的技能非常多(比如上亿个),每个技能一个模型,存储开销巨大。

  2. 知识无法共享:不同任务的模型之间知识无法互通,无法从其他任务中汲取单一任务学不到的资讯。

  3. 不符合智能本质:对人类来说,我们只有一个大脑,却可以学会多种任务。为什么机器不能做到同样的事情呢?这就是终身学习想要探讨的问题。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_36.png

终身学习 vs. 迁移学习

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_38.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_40.png

有的同学可能会说,这听起来跟迁移学习挺像的。迁移学习也是让机器在任务一上学习,希望学到的技能能迁移到任务二。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_42.png

虽然两者都涉及多个任务,但关注点不同:

  • 迁移学习在意的是:机器在第一个任务上学到的技能,对第二个任务有没有帮助。只关注新任务的表现。

  • 终身学习在意的是:当机器学完第二个任务时,回过头去第一个任务还能不能解。关注旧任务的表现。

如何评估终身学习系统?

在讲解终身学习的技术之前,我们先了解一下如何评估一个终身学习系统做得好不好。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_44.png

首先,你需要定义一系列任务让机器依序学习。在文献中,这些任务通常比较简单,例如:

  • 任务一:识别正常的手写数字。

  • 任务二:识别经过特定规则打乱像素后的手写数字。

  • 任务三:识别旋转了15度的手写数字。

  • 或者,任务一:区分数字0和1;任务二:区分数字2和3;以此类推。

评估方法如下:

你有一系列任务(假设有T个)。你有一个随机初始化的模型,先在所有任务的测试集上测试,得到T个初始正确率。

然后,让模型依序学习:

  1. 学完任务一后,在所有T个任务上测试一次正确率。

  2. 学完任务二后,再次在所有T个任务上测试。

  3. …

  4. 学完最后一个任务T后,最后测试一次。

你会得到一个表格,其中元素 R_ij 表示:训练完第 i 个任务后,在第 j 个任务测试集上的正确率。

根据这个表格,有几种常见的评估指标:

  1. 最终平均准确率:最常用的指标。计算模型学完所有任务后(即表格的最后一行),在所有任务上正确率的平均值。这个值综合反映了模型最终保留了多少旧知识。

    • Final Average Accuracy = (1/T) * Σ_{j=1 to T} R_Tj
  2. 逆向迁移:衡量学习新任务对旧任务的影响。通常计算模型在学完所有任务后,在某个旧任务上的表现,相比刚学完该任务时的表现,下降了多少。

    • Backward Transfer (对任务j) = R_Tj - R_jj

    • 这个值通常是负的(因为会遗忘)。如果一个方法能使其为正,说明学新任务反而让旧任务做得更好了,那就非常厉害。

  3. 正向迁移:衡量在学习某个任务之前,从其他任务中提前学到了多少。计算在还未学习任务j,但学完了其他所有任务时,在任务j上的表现,相比完全没学习任何任务时的提升。

    • Forward Transfer (对任务j) = R_{T-1, j} - R_{0, j}

    • 这个指标通常不是终身学习的关注重点。

总结

本节课中,我们一起学习了机器终身学习的基本概念。我们了解到,理想的AI应该能够像人类一样持续学习新技能而不遗忘旧知识。然而,当前的机器学习模型在依序学习多个任务时,会遭遇“灾难性遗忘”问题:学会新任务的同时,几乎完全忘记了旧任务。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/b0c4581ba02dd6535a7f043d44e384d9_46.png

我们探讨了为什么简单的解决方案(如多任务学习或为每个任务单独训练模型)在实践中存在局限。最后,我们介绍了评估终身学习系统的常用方法和指标。理解了这些基础问题和评估方式,下一节课我们将深入探讨解决灾难性遗忘、实现真正终身学习的技术方法。

89:终身学习 (Life Long Learning) (二) - 灾难性遗忘的克服之道 🧠

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_1.png

在本节课中,我们将要学习克服机器学习中“灾难性遗忘”问题的几种核心方法。灾难性遗忘是指模型在学习新任务时,会严重遗忘旧任务知识的现象。我们将深入探讨三种主要的解决思路,并理解其背后的原理与实现方式。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_3.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_5.png

上一节我们介绍了终身学习的概念和灾难性遗忘问题,本节中我们来看看具体的解决方法。

选择性突触可塑性 (Selective Synaptic Plasticity) 🔒

第一个解法叫做选择性突触可塑性。从字面上看,这个方法的目标是:只让神经网络中的一部分神经元或连接具有“可塑性”(即可被改变),而另一部分连接则被“固化”,其数值在后续学习中不再改变。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_1.png

这类方法也称为基于正则化 (Regularization-based) 的方法,是终身学习领域中发展最完整的研究方向。我们将花较多时间讲解它。

灾难性遗忘为何发生?

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_7.png

为了理解解法,我们先分析问题产生的原因。假设有两个任务:任务一和任务二。为简化,假设模型只有两个参数:θ1 和 θ2。

  • 左右两张图分别代表任务一和任务二的损失函数(即误差曲面)。

  • 颜色越偏蓝色代表损失越小,越偏白色代表损失越大。

  • 我们从随机初始参数 θ0 开始,通过梯度下降在任务一上训练,得到参数 θB。

  • 接着,我们将 θB 作为初始值,在任务二的误差曲面上继续训练,得到最终参数 θ*。

此时,θ* 在任务二上表现好(处于蓝色低损失区),但若将其拿回任务一上测试,会发现表现很差,因为 θ* 的位置对任务一而言损失很高。这就是遗忘。

核心解决思路

解决思路是:每个参数对旧任务的重要性不同。对于旧任务重要的参数,我们在学习新任务时应尽量保持其不变;只去更新那些对旧任务不重要的参数。

具体做法是:为每个参数 θi 配备一个“守卫”值 bi。bi 的大小代表了该参数对旧任务的重要性,bi 越大,意味着该参数越重要,越不希望被改变。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_9.png

我们通过修改损失函数来实现这一约束。新的损失函数 L' 为:

L' = L(θ) + Σ_i [ bi * (θi - θi^B)^2 ]

其中:

  • L(θ) 是新任务原本的损失。

  • θi^B 是从旧任务学得的参数值。

  • 第二项是正则化项,它惩罚新参数 θi 与旧参数 θi^B 的偏离程度。

  • bi 控制惩罚的强度。bi 大则强制参数不变,bi 小则允许参数改变。

如果所有 bi = 0,则退化为普通训练,会发生灾难性遗忘。

如果所有 bi 都设得非常大,则新参数被强制接近旧参数,这会导致模型无法学习新任务,这种现象称为 顽固性 (Intransigence)。

因此,关键在于如何为每个参数设定合适的 bi 值。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_11.png

如何设定 bi 的值?

bi 是人为设定的,其核心思想是:评估每个参数对旧任务损失的影响程度。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_13.png

  • 如果一个参数(如 θ1)的微小变动对旧任务的损失影响很小,则说明它对旧任务不重要,可以赋予较小的 b1,允许它在学习新任务时自由更新。

  • 如果一个参数(如 θ2)的微小变动会显著增大旧任务的损失,则说明它很重要,应赋予较大的 b2,限制它在学习新任务时的变化。

通过这种方式,在训练新任务时,梯度更新的方向就会被引导至那些对旧任务不重要的参数方向上,从而在学会新任务的同时,最大程度地保护旧任务的知识。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_13.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_15.png

实验结果

下图展示了一个经典方法 EWC 的实验结果。图中横轴是依序训练任务A、B、C的过程,纵轴是各任务的正确率。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_15.png

  • 蓝色线 (bi=0):发生明显的灾难性遗忘。学完B后,A的正确率下降;学完C后,A和B的正确率都下降。

  • 绿色线 (所有bi=1):虽然缓解了遗忘(A的正确率保持较好),但产生了顽固性,导致新任务B和C学不好(正确率上升缓慢或不高)。

  • 红色线 (选择性设置bi):在防止遗忘(A的正确率保持好)和学习新任务(B和C的正确率较高)之间取得了最佳平衡。

文献中存在多种计算 bi 的具体方法(如 EWC, SI, MAS, RWalk, SCP等),它们各有特点,是作业中探讨的重点。


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_17.png

上一节我们详细介绍了基于正则化的方法,本节中我们快速了解另外两种解决思路。

基于梯度方向修正的方法:Gradient Episodic Memory (GEM) 📐

GEM 方法不在参数值上施加约束,而是在梯度更新方向上施加约束。

其做法是:

  1. 在新任务(任务二)上计算梯度 G。

  2. 在更新参数前,回到旧任务(任务一)上计算其梯度方向 G_old(蓝色箭头)。

  3. 如果新任务的梯度 G 与旧任务的梯度 G_old 方向不一致(内积为负),则对 G 进行修正,得到一个新的更新方向 G‘。

  4. G‘ 需要满足:与 G_old 的内积非负(不损害旧任务),同时与原始 G 的差异尽可能小(尽可能完成新任务的学习)。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_19.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_19.png

这种方法的一个潜在问题是:计算旧任务的梯度 G_old 需要用到旧任务的部分数据。这与终身学习希望不存储旧数据的初衷略有违背。但 GEM 通常只需存储少量数据即可,如果其存储开销小于存储整个旧模型和 bi 值的开销,则仍是一个可行的方案。


动态分配神经资源 (Additional Neural Resource Allocation) 🧩

这种思路的核心是:为不同的任务分配或使用不同的网络参数,避免直接修改旧任务所用的参数。

以下是两种代表性方法:

渐进式网络 (Progressive Neural Network)

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_21.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_23.png

  • 做法:冻结为任务一训练好的网络。当学习任务二时,新建一个网络,该网络可以接收任务一网络的隐藏层输出作为额外输入。任务二只训练这个新增网络的参数。

  • 优点:完全避免了灾难性遗忘。

  • 缺点:每学一个新任务,模型就会增长一部分。随着任务增多,模型会变得非常庞大。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_25.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_27.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_29.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_29.png

打包网络 (PackNet) 与 压缩-打包-增长 (CPG)

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_31.png

  • PackNet做法:预先初始化一个较大的网络。学习每个新任务时,只使用和更新网络中分配给该任务的一部分参数,其他参数被“掩码”冻结。

  • 优点:模型总参数量固定,不会无限增长。

  • CPG做法:结合了渐进和打包的思想,模型既可以增长新参数,每个任务又只使用部分参数,是一种更灵活的策略。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_33.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_33.png


记忆回放 (Memory Replay) 🔄

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_35.png

这是一个非常直观的方法:既然把新旧数据混合训练可以避免遗忘,但又不能存储旧数据,那么我们可以训练一个生成模型 (Generative Model) 来“回忆”旧数据。

  • 做法:

    1. 在学习任务一时,同时训练一个分类器和一个能够生成类似任务一数据的生成器。

    2. 学习任务二时,不仅使用任务二的真实数据,还使用任务一的生成器产生的“伪数据”来一起训练分类器。

    3. 如此循环,每学完一个任务,就更新生成器使其能生成所有已学任务的数据。

  • 评价:该方法需要额外训练和维护生成模型,会占用一定资源。但在实践中,这种方法往往能取得接近“多任务学习”(同时看到所有数据)的性能上限,效果非常显著。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_37.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_39.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_39.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_41.png


扩展讨论与总结 🎯

任务顺序的重要性

任务的学习顺序对终身学习的效果有显著影响。在某些顺序下,灾难性遗忘问题可能更严重;而在另一些顺序下,问题可能自然缓解。因此,在严谨的研究中,通常会测试所有可能的任务排列顺序并取平均性能。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_43.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_49.png

更复杂的场景

我们讨论的场景假设所有任务的结构(如类别数)相同。实际上,终身学习还有更复杂的场景,例如:

  • 增量分类:新任务会引入新的类别。

  • 领域增量学习:任务的数据分布发生变化,但类别空间可能不变。

  • 任务增量学习:本节课主要讨论的类型,模型需要明确知道当前是哪个任务。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_45.png

这些场景有相应的研究方法(如 LwF, iCaRL等),是更前沿的探索方向。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_47.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_49.png


https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_51.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_53.png

本节课中我们一起学习了克服机器学习中灾难性遗忘的三大类方法:

  1. 选择性突触可塑性:通过给参数施加重要性加权正则化,保护重要参数。

  2. 梯度 episodic memory:通过修正梯度更新方向,使其不损害旧任务。

  3. 动态资源分配与记忆回放:通过分配独立参数或生成伪数据,物理上隔离或模拟旧任务数据。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/412d58837b4e5169d761f2cd837aba3b_55.png

每种方法都有其优缺点和适用场景,理解其核心思想是设计或应用终身学习算法的关键。终身学习是一个活跃的研究领域,仍有诸多挑战等待解决。

90:作业14:持续学习 📚

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/656b24c6ec2f7e7dbe1f3ff09313b1b9_1.png

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/656b24c6ec2f7e7dbe1f3ff09313b1b9_3.png

在本节课中,我们将学习持续学习的基本概念,并完成作业14。我们将了解什么是持续学习、它面临的挑战,以及几种主流的解决方法。最后,我们将通过实践代码,在旋转MNIST数据集上应用这些方法。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/656b24c6ec2f7e7dbe1f3ff09313b1b9_5.png


概述 🎯

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/656b24c6ec2f7e7dbe1f3ff09313b1b9_7.png

持续学习的终极目标是让模型能够在所有任务上都表现良好,但有一个限制:模型需要连续地在不同任务上进行训练。例如,我们可能在任务一上训练并测试,然后在任务二上训练并测试,依此类推。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/656b24c6ec2f7e7dbe1f3ff09313b1b9_9.png

上一节我们介绍了课程目标,本节中我们来看看持续学习面临的核心问题。

灾难性遗忘 🧠

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/656b24c6ec2f7e7dbe1f3ff09313b1b9_11.png

这种方法可能会遇到一个严重问题,即“灾难性遗忘”。具体来说,如果一个模型先在任务一上训练,然后在任务二上训练,之后在任务二上测试可能会有不错的效果。但如果再将该模型在任务一上测试,其效果可能会显著下降。

我们的目标是,当模型在任务一上训练后,再在任务二上训练,之后在任务一、任务二乃至任务三上测试时,都能保持良好的性能。

https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/leemldl-2026/img/656b24c6ec2f7e7dbe1f3ff09313b1b9_13.png

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐