P5-6.4 训练模式(training mode)与评估模式(evaluation mode)¶
Section ID:
P5-6.4Version:v2026.07.20
在 P5-6.3 里,我们已经把学习(learning)和模型执行(inference)区分成:改变参数的时间和不改变参数、只拿来使用的时间。再往前走一步,就会出现下一个问题。
既然参数没有改变,计算规则也必须永远完全一样吗?
答案并不总是如此。即使使用同一组参数,有些层(layer)在训练用计算状态和评估用计算状态下,也会表现得不同。只有把这个差别真正理解清楚,才不容易把 dropout、batch normalization、validation、test、部署推理混在一起。
训练模式(training mode)是为了准备参数更新而使用的计算环境,评估模式(evaluation mode)则是为了稳定测量或稳定使用当前模型而使用的计算环境。
如果后面在 dropout 或 batch normalization 的说明里又把 mode 区分重新混在一起,更适合回到英文概念词汇表里的 training mode 条目和evaluation mode 条目,先重新确认这两个状态分别在管什么。
需要训练模式与评估模式的问题¶
- 为什么还要再把 training mode 和 evaluation mode 分开?
- 哪些层会对 mode 差异特别敏感,而不是所有层都一样?
- dropout 和 batch normalization 为什么会随 mode 改变行为?
- 为什么在 validation 和 test 里,evaluation mode 会很重要?
这一节专注于区分:即使是同一个模型,哪些计算规则更适合训练阶段,哪些计算规则更适合评估阶段。也就是说,这里是在先分开 learning 与 inference 之后,再继续闭合:同样在使用参数的区间里,为什么还需要 training mode 和 evaluation mode。
同样,这一节也不会马上把所有相关问题都扩开。dropout 和 regularization 的更大意义,会在 P5-8.1、P5-8.2 里再详细接回;optimizer 在整条学习流程里究竟站在什么位置,则会在 P5-7.1、P5-7.2 重新说明。
训练专用行为与执行行为的判断标准¶
- 能把 training mode 和 evaluation mode 解释成
计算规则会不同的两种状态。 - 能说明 dropout 与 batch normalization 为什么对 mode 差异敏感。
- 能解释为什么 validation 与部署时,evaluation mode 很重要。
- 能用可运行的 Python 例子,直观确认 mode 差别。
为什么同一个模型还需要 mode¶
读者很容易把模型想象成一个固定函数。好像只要输入一样,它就应该始终做完全相同的计算,并给出完全相同的结果。
但在深度学习里,有些层为了让训练本身更顺利,会故意引入随机波动,或者依赖当前 batch 的统计量。这些做法在训练阶段可能有帮助,但到了评估或服务执行阶段,反而可能引入不必要的不稳定性。
也就是说,mode 的划分并不只是某个库的语法细节,而是为了下面这两个目的。
- 在训练时允许有助于泛化(generalization)的计算
- 在评估时让结果更稳定、更容易比较和复现
training mode 指的是什么¶
training mode 通常可以先按下面几条来理解。
- 当前处在为了降低损失而进行的学习流程里
- forward 之后还可能继续接上损失计算与反向传播
- 有些层会为了帮助训练,而以特别的方式运作
也就是说,training mode 并不只是调用 optimizer.step() 的那一瞬间,而是指:模型正在使用训练用的计算规则。
evaluation mode 指的是什么¶
evaluation mode 通常在下面这些场景里特别需要。
- 用验证数据(validation set)测量表现时
- 用测试数据(test set)确认最终性能时
- 在部署好的服务里处理真实用户输入时
这时最重要的,不是继续帮助模型摇摆着学习,而是尽量稳定地展现:当前这个模型到底做得怎么样。 因此,训练时那些带有随机波动或批量依赖的规则,往往就需要收起来,改用更固定的计算方式。
先把它压缩成一句话,会更容易记。
评估模式是在测量现在的模型有多好,训练模式则是在把模型继续变得更好。
如果只留下计算规则层面的差异,可以先压缩成下面这张图。
flowchart TD
I["同一个模型输入"]
subgraph T["训练模式"]
T1["Dropout 保持随机性"]
T2["使用当前 batch 统计量"]
T3["继续损失与参数更新"]
end
subgraph E["评估模式"]
E1["关闭 Dropout"]
E2["使用运行统计量"]
E3["稳定测量或服务输出"]
end
I --> T1
T1 --> T2
T2 --> T3
I --> E1
E1 --> E2
E2 --> E3
这张图最先要确认的结果是:即使模型与输入都相同,training mode 会更偏向允许为了更新而出现的波动,而 evaluation mode 会更偏向稳定测量与稳定服务输出。
哪些层对 mode 差异更敏感¶
并不是所有层都对 mode 差异一样敏感。比如常见的线性层(linear layer)或卷积层(convolution layer),在输入和参数相同时,整体计算逻辑通常不会因为 mode 而大幅变化。
但下面这些层或技巧,更适合先按训练中与评估中分别去读。
| 层或技巧 | 训练模式里的特点 | 评估模式里的特点 |
|---|---|---|
| dropout | 会随机关闭一部分激活值 | 不再随机屏蔽,稳定使用全部路径 |
| batch normalization | 使用当前 batch 的统计量 | 使用训练阶段累计下来的统计量 |
也就是说,之所以需要 mode 差异,是因为有一些层会为了帮助训练而故意采取不同的行为。
dropout 为什么在训练中和评估中不同¶
dropout 是一种在训练中随机切断部分节点输出的技巧,用来避免模型过度依赖少数固定路径。
先把它读成下面这句话就够了。
训练时,故意让一部分连接休息一下,避免模型只抓住一两条信号不放。
但如果在评估时也继续每次随机切断节点,那么结果就会变得摇摆不定。这样一来,就很难稳定地测出:当前模型到底本来有多好。
因此,在 evaluation mode 里,通常会停止 dropout 的随机屏蔽,改为使用已经学好的网络结构来稳定计算。
batch normalization 为什么也需要 mode 差异¶
batch normalization 会利用当前 batch 的平均值(mean)和方差(variance)来调整激活值分布。训练中使用当前 batch 的统计量,本来是很自然的;但到了评估阶段,情况就不一样了。
评估数据往往:
- batch 很小
- 甚至可能一次只进来一个样本
- 每次评估时 batch 的组成也可能变化
如果这时还每次都只使用当前 batch 的统计量,结果就可能变得不稳定。所以在 evaluation mode 里,通常会改用训练中累计下来的 running statistics。
先把它记成下面这句话,会更安全。
batch normalization 在训练时会参考当前 batch,而在评估时会更多参考训练过程中积累下来的平均性标准。
为什么 validation 和 test 必须重视 evaluation mode¶
验证集与测试集的职责,是测量当前模型的泛化能力到底怎么样。 如果此时 training mode 还开着,dropout 仍然会继续随机波动,batch normalization 也会继续对当前 batch 的组成很敏感。
结果就会变成:
- 即使是同一个模型,测得的数值也不够稳定
- 分数会被 batch 构成偶然左右
- 和将来真正部署时用户感受到的表现不容易对齐
也就是说,validation 和 test 是公平地测量当前模型的时间,所以 evaluation mode 很重要。
练习与例子¶
mode 区分最适合在这些时刻被拿出来看:验证、部署、小 batch 评估,以及任何计算规则本身会摇动结果解释的时候。即使输入同一个 batch,在 training mode 和 evaluation mode 下,也可能因为不同的计算规则而走出两条不同路径。下面这个例子,会一步一步把这种差别作为中间产物展示出来。
这一版例子不会直接把一长串手工写好的数字塞进去,而是先从一小批用户会话数据算出隐藏层(hidden layer)激活值,再在这些激活值之上,分别施加 dropout 与 batch normalization 的 mode 差异。
输入:
- 每个会话的点击数与停留时间
- 一个简单隐藏层所用的权重与 bias
- dropout 比率
- 两个随机种子,用来复现两次训练模式运行
- evaluation mode 会参考的、过去学习阶段的会话 batch
输出:
- 从输入特征计算出来的隐藏层激活值
- dropout 之后的激活值
- normalization 使用的参考均值
- 减去该参考均值之后的简化输出
问题场景:
- 即使输入相同,训练模式允许波动,而评估模式需要更稳定的基准线
需要确认的概念:
- 在 training mode 里,部分激活值会被随机关闭
- training mode 下的 batch normalization 可以使用当前 batch 的基准
- evaluation mode 会停止 dropout,并改用学习中累计下来的 running mean
输入(input):
我们会使用前面整理好的当前验证会话 batch 与过去学习阶段的会话 batch。这里的隐藏层计算会把最近点击数、停留时间、错误次数分别乘上权重,再加上 bias,然后只应用把负数裁成 0 的 ReLU(rectified linear unit)。而 batch normalization 为了把重点放在参考均值来自哪里,只保留 值 - 参考均值 这一部分。真实的 batch normalization 还会涉及方差,以及可学习的 scale 和 shift,但这一节里先不用把它们都展开。
在看代码之前,先猜一猜:哪些东西直接从数据里算出来,哪些东西会因为 mode 而摇摆或固定,会更容易抓住差别。
| 比较项 | 先猜测会看到什么输出 | 猜测理由 |
|---|---|---|
hidden_activation | 每个会话会得到不同的隐藏层数值 | 因为点击数和停留时间本来就不一样 |
train_run_1 与 train_run_2 的 dropout 后数值 | 即使原始激活一样,结果模式也可能不同 | 因为训练模式下每次运行的 dropout mask 可能不同 |
train_run_1 batch_mean 与 train_run_2 batch_mean | 很可能彼此不同 | 因为活下来的激活值一变,当前 batch 的平均值也会跟着变 |
eval_run | 很可能会保留原本的隐藏层激活值 | 因为评估模式下不会再执行 dropout |
eval reference_mean | 会保持成先前学习 batch 累积出来的固定基准 | 因为评估模式更倾向使用 running mean,而不是当前 batch 的偶然组成 |
这张表的目的,不是让人先把具体数字猜对,而是让人先抓住:训练模式下,即使是同一组隐藏层激活,执行两次也可能因为 dropout 和当前 batch 参考而不同;而评估模式会把这种摇摆停下来,改用稳定基准线。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
输出里首先要确认的是:hidden_activation_summary 是从输入特征计算出来的隐藏层值摘要;然后再按顺序比较 kept/dropped、after_dropout_summary、reference_mean、centered_preview。
这个例子并没有完整复现某个深度学习框架,但这里需要读出的核心很明确。
- 隐藏层激活值是由输入特征计算出来的中间产物
- 在训练模式里,即使放进去的是同一组隐藏层激活,dropout 后保留下来的激活值数量和组成也可能不同
- 只要 dropout 后的值不同,当前 batch 计算出来的参考均值也可能跟着变化
- 在评估模式里,dropout 会停下来,并改用过去学习 batch 累积出来的 running mean 作为更稳定的基准
- 这正是 validation、test、部署时为什么需要 evaluation mode 的原因
先把同一套计算规则重新用图来读。第一张图只展示:验证会话输入里的最近点击数、停留时间、错误次数怎样被变成隐藏层激活值。这里看到的还不是 mode 差异,而只是输入数据被映射成模型内部中间表示的那一步。

第二张图展示的是:同样的隐藏层激活,到了最后一层输出解释时,会因为 mode 不同而怎样变化。train 1 和 train 2 表示两次具有不同 dropout mask 的训练模式执行,eval 则表示关闭 dropout、并用 running mean 作为参考的评估执行。值大于 0 表示输出高于该参考均值,值小于 0 则表示输出低于该参考均值。

前两张图是例子代码本身的直接说明,下面两张图则是把同一种现象拉长到多次执行以后做的摘要。若只是把 train_run_1 和 train_run_2 两条样本线画出来,很容易看起来像是在硬比较人为挑的两个 mask;因此,这里把同样的计算规则应用到更长一点的小 batch 上,并把 30 次 forward pass 里 dropout 后保留下来的比例做成摘要。training mode 下,这个保留比例会跟着 pass 摇摆;evaluation mode 则因为关闭了 dropout,保留比例固定在 1.0 这条基准线上。

normalization 的参考均值也要用同样方式来读。training mode 下,每一次 forward pass 都会用 dropout 之后当前 batch 的数值重新算一个平均值,因此参考均值会波动;evaluation mode 下,基准线则来自学习期间累计好的 running mean,而不是来自这一次 pass 的偶然 mask。

这里再次要强调的是:只看到输出不同,和真正读懂mode 改变了什么计算规则并不是同一回事。
| 比较场景 | 较轻的误解 | 更危险的误解 | 现在先要确认的东西 |
|---|---|---|---|
train_run_1 与 train_run_2 的 after_dropout 不同 | 认为训练时本来就会有一点摇摆 | 直接断言:同样输入却得不同结果,所以模型本身不可信 | 先看是不是处在允许随机性的 training mode |
reference_mean 每次都不同 | 意识到当前 batch 的基准会变化 | 直接认为评估结果全部失真 | 先分清:这是 training mode 的 batch 基准,还是 eval mode 的 running 基准 |
eval_run 看起来更固定 | 意识到评估模式更稳定 | 反而觉得评估也应该像训练那样多摇几次才更真实 | 先确认:验证、测试、部署的目的就是稳定比较 |
因此,这个例子的下一步确认点,不是停在两种 mode 有差别,而是继续问:如果把 mode 用错,会摇坏什么。
| 故意制造的失败场景 | 会看见什么东西被摇坏 | 本节先要确认的结果 |
|---|---|---|
在验证阶段也直接拿 run_training_mode(...) 这样的输出来用 | 同样的输入重跑时,dropout 与当前 batch 基准会不必要地摇摆 | 性能测量会不会比模型本身更受随机性和 batch 构成影响? |
把 drop_rate 从 0.4 提高到 0.7 | 训练模式输出会丢掉更多信息,平均激活值也更不稳定 | dropout 太强时,帮助泛化的效果是否开始被信息损失盖过去? |
| 在评估里也试图像 train run 那样多次摇摆比较 | 原本应该固定的评估基准线被人为摇动 | 评估和允许训练中波动是不是本来就是不同目的? |
也就是说,这一节的实验不会停在training/eval mode 不一样这种定义确认上,而必须继续确认:如果在评估中也保留训练式的波动,究竟会把结果解释哪里弄坏。
随着深度学习模型变深、规模变大,仅靠模型会学习权重这种说法,已经很难把真实学习系统讲清楚。regularization、normalization、batch-based training 这些东西越来越常见之后,学习中和评估中的行为差异,就必须在课程里明确点出来。
特别是 dropout 作为减少过拟合(overfitting)的实用技巧,早已被广泛介绍;batch normalization 也常出现在深层网络的训练稳定性和速度讨论里。因此,在现代深度学习教育里,把 training/eval mode 单独作为一个概念来介绍,是很自然的。
换句话说,这一节不是某个库 API 的小技巧,而是在解释:为什么深度学习模型看起来不像一个永远静止的函数,而更像一个带有运行状态的系统。
什么时候需要单独读 training/eval mode 的差别¶
在先分清 learning 和 inference 之后,下一步就要单独确认:即使是同一个模型,计算规则也会不会有些不同? 这条边界就是 training/eval mode。
| 先出现的问题场景 | 为什么必须单独读 mode 差异 | 紧接着会连到哪里 |
|---|---|---|
| 同样的输入,在训练中和验证中的感觉不一样 | 因为 dropout 与 batch normalization 可能会按 mode 不同而改变行为 | 后面会继续看 optimizer 在什么状态下真正更新 |
| 验证分数看起来忽高忽低 | 可以先明确:evaluation mode 是为了公平且稳定地测量 | 之后还会再去看 regularization 与 normalization 的意义 |
| 部署服务里的输出似乎波动很大 | 如果把训练用的随机行为原样带到服务执行里,就可能变得不稳定 | 会继续连到 inference serving 与 optimizer 分离的问题 |
| 对 dropout、batch normalization 为什么要特别处理没有感觉 | 可以把对 mode 敏感的层单独区分出来读 | 会和后面的正则化、优化器章节接上 |
检查清单¶
- 能解释 training mode 与 evaluation mode 为什么会采用不同的计算规则吗?
- 能说明 dropout 或 batch normalization 为什么必须重视 mode 差异吗?
- 能把 training mode 与 evaluation mode 解释成同一模型的两种不同计算状态吗?
- 能指出 dropout 与 batch normalization 是对 mode 差异特别敏感的代表例子吗?
- 能说明 validation、test、部署时为什么需要 evaluation mode 来提供更稳定的输出吗?
- 当同样输入在训练中和验证中表现感觉不同的时候,能先想到 training/evaluation mode 这条边界吗?
- 当需要压低验证和部署时的输出摇摆时,能说出 evaluation mode 提供的是稳定基准线吗?
- 能理解:这一节之后,课程会继续转向 optimizer,去看 gradient 怎样被改写成真正的更新规则吗?
出处与参考资料¶
- Ian Goodfellow, Yoshua Bengio, Aaron Courville,
Deep Learning, MIT Press, 2016, 确认日期: 2026-06-29. https://www.deeplearningbook.org/ - Nitish Srivastava et al.,
Dropout: A Simple Way to Prevent Neural Networks from Overfitting, JMLR, 2014, 确认日期: 2026-07-19. https://jmlr.org/papers/v15/srivastava14a.html - Sergey Ioffe, Christian Szegedy,
Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift, ICML, 2015, 确认日期: 2026-07-19. https://arxiv.org/abs/1502.03167