随机数、可复现性与模拟实验
层级:B|建议先修:05-22、06-12、09-01
机器学习中的数据划分、参数初始化、小批量采样、数据增强和 Monte Carlo 都依赖随机数。设置一个种子只是可复现性的起点,不是完整保证。
1. 伪随机数
计算机通常使用伪随机数生成器(PRNG)。它从有限内部状态出发,经确定性递推产生看似随机的序列:
给定相同算法、初始状态和调用顺序,会生成相同序列。初始状态通常由 seed 派生。
PRNG 适合模拟和机器学习,但普通 PRNG 不一定适合密码学;安全令牌应使用密码学安全生成器。
2. 种子的含义
种子不是“随机性的强度”,而是选择随机序列起点的标识。固定种子有利于调试和复现实验;更换种子可评估结果对随机性的敏感程度。
只报告单个幸运种子的最好结果会形成选择偏差。正式比较应预先规定种子或运行多次并报告均值、标准差或置信区间。
3. 多个随机源
一个工程可能同时使用:
- 语言标准库的 RNG;
- NumPy 或其他数值库 RNG;
- CPU 深度学习框架 RNG;
- 每块 GPU 的 RNG;
- 数据加载器子进程 RNG;
- 第三方增强库或环境模拟器 RNG。
只设置其中一个 seed 不够。应建立统一种子策略,并记录所有相关库与设备设置。
4. 全局 RNG 与显式生成器
全局 RNG 容易受调用顺序影响:添加一次日志采样都可能改变后续随机序列。更稳健的做法是为不同用途创建独立生成器或子流,例如:
- 数据划分流;
- 参数初始化流;
- 数据增强流;
- 评估采样流。
这样一个模块增加随机调用不会扰动其他模块。
5. 并行与分布式随机性
多个 worker 若复制完全相同的 RNG 状态,可能生成重复样本;若共享一个全局流,调度顺序又会导致不可复现。
应使用可证明分离的子流、seed sequence、counter-based RNG 或按 worker/rank 派生种子。简单地 base_seed + worker_id 有时可用,但要考虑实验编号、epoch 和重启语义,避免碰撞和重复。
6. 确定性算法
即使随机种子相同,GPU 并行归约、原子操作、cuDNN 算法选择和线程调度也可能产生不同结果。框架通常提供确定性模式,但可能:
- 降低速度;
- 增加内存;
- 禁用某些算子;
- 仍不能保证跨硬件、驱动和版本逐位一致。
应区分:同一环境逐位复现、数值近似复现、统计结论复现。
7. 环境记录
可复现实验至少应记录:
- 代码提交版本与未提交修改;
- 数据版本、预处理和划分索引;
- 依赖库、编译器、驱动和硬件;
- 配置、超参数和命令;
- 全部种子及确定性选项;
- 模型检查点、优化器状态和日志。
只保存最终权重不足以重现训练过程。
8. 数据划分的随机性
划分应在模型训练前固定,并避免同一用户、时间窗口或实体的信息跨集合泄漏。对不平衡分类可分层抽样;对时间序列应按时间划分;对用户行为应按用户或业务实体分组。
“随机打乱再切分”只在样本可交换且不存在组结构时合理。
9. 随机模拟的估计误差
对独立样本的 Monte Carlo 均值
标准误近似为
随机误差只按 下降:若想把误差缩小一半,样本量约需增加到四倍。MCMC 则应使用有效样本量替代 。
10. 方差缩减
为了用更少样本获得更精确估计,可使用:
- 对偶变量:配对负相关样本;
- 控制变量:利用已知期望的相关量校正;
- 重要性采样:从更关注关键区域的分布采样并加权;
- 分层抽样:分别覆盖不同子区域;
- 共同随机数:比较两个系统时使用相同随机输入,降低差值方差。
方差缩减比单纯增加样本常更高效,但必须保证估计量权重和假设正确。
11. 实验比较
比较算法 A 与 B 时,应尽量使用配对设计:在相同数据划分和种子上运行两者,分析每次配对差值。它能消除部分“这次划分本来就更容易”的波动。
报告内容应包括重复次数、汇总统计量、误差条和选择规则,而不是只展示最好一次结果。
12. 复现与稳健性
固定所有随机性可定位 bug,但最终结论还应对合理随机变化稳健。推荐流程:
- 调试阶段固定 seed 和确定性模式;
- 基线确认后运行多个预定 seed;
- 报告分布而非单点;
- 对异常 seed 排查原因,不随意删除;
- 在新环境重现统计结论。
13. 易错点
- 固定 seed 不代表跨库、跨设备、跨版本逐位相同。
- 重复使用同一个 seed 并不自动保证各实验独立;要管理随机流和调用顺序。
- 为追求“确定性”而固定数据增强序列,可能让每个 epoch 看到完全相同增强,改变训练意图。
- 用测试集选择最幸运 seed 与用测试集调参一样会产生泄漏。
常见问答
Q1:论文只跑一次可以吗?
若算法含明显随机性,单次结果无法反映波动。至少应根据成本做多次独立或配对重复,并报告不确定性。
Q2:每个 epoch 应重设同一个 seed 吗?
通常不应简单重设,否则随机顺序和增强可能周期性重复。更合适的是让同一生成器连续推进,或按可记录规则派生不同 epoch 子流。
Q3:为什么固定 seed 后改变 batch size,结果还是完全不同?
随机调用次数、批次组合、并行归约顺序和优化轨迹都改变了;seed 只固定给定执行路径的随机流。
Q4:逐位可复现是最高目标吗?
调试时很有价值,但科学结论更关心不同合理环境和随机种子下是否统计稳健。两者应分别追求。
练习
- 解释伪随机序列为什么既确定又能用于模拟。
- 列出一个深度学习项目中至少四个可能的随机源。
- 为什么 Monte Carlo 误差减半通常需要四倍样本?
- 设计比较两个模型的配对多种子实验。
答案与提示
- 生成器按确定性状态递推,但序列具有适合统计模拟的分布与相关性质;未知状态时看似随机。
- 如标准库、数值库、CPU/GPU 框架、数据加载 worker、增强库和模拟环境。
- 标准误与 成正比,令其减半需 变为四倍。
- 预先选定若干 seed/划分,每个 seed 同时训练 A、B,记录成对指标差,再汇总差值均值与置信区间。