PyTorch 固定随机种子后,先核对三件事:样本顺序是否一样、训练损失序列是否一样、最终参数是否一样。只看到“设了 torch.manual_seed(7)”不能证明结果可重复,因为数据加载、Python 或 NumPy 随机数以及某些算子还可能引入变化。
PyTorch 2.8 可重复性说明明确指出,跨版本、平台以及 CPU/GPU 执行的完全一致结果不受保证。下面只验证同一软件环境、同一 CPU 玩具代码运行两次的结果,读者应按自己的任务建立对照。

先把随机源和实验条件写清楚
| 对象 | 本例做法 | 实际项目还要检查 |
|---|---|---|
| 模型初始化 | 创建模型前调用 torch.manual_seed | 调用顺序、随机初始化的额外层 |
| 样本乱序 | DataLoader 使用单独 torch.Generator | 分布式采样器、数据增强、多 worker |
| Python 随机数 | 调用 random.seed | 预处理或采样代码是否使用 random |
| 算子行为 | 启用确定性算法检查 | 是否存在不支持确定性实现的操作 |
每次运行都在创建模型和读取器之前重新设种子;不要在每个小批次开头反复设成同一个值,否则可能让原本应变化的数据增强或随机掩码不断重复。
跑两次同种子,再加一个不同种子的对照
以下完整脚本在 Windows、Python 3.11.15、PyTorch 2.8.0+cpu、NumPy 2.3.3 环境实际运行通过,只验证这个 CPU 玩具任务。它不下载模型权重,也不代表真实模型的精度、速度或显存表现。在已启用的独立 Python 环境中可安装相同依赖:
python -m pip install torch==2.8.0 --index-url https://download.pytorch.org/whl/cpu
python -m pip install numpy==2.3.3
保存为 seed_demo.py,运行 python seed_demo.py。样本通过固定公式生成,不涉及真实业务数据;DataLoader 的 num_workers=0,避免把 Windows 多进程启动细节混进这个最小验证。
import random
import torch
from torch.utils.data import DataLoader, TensorDataset
torch.set_num_threads(1)
torch.use_deterministic_algorithms(True)
x = torch.linspace(-1, 1, 12).reshape(-1, 1)
y = 2 * x + 0.5
indices = torch.arange(len(x))
def run(seed):
random.seed(seed)
torch.manual_seed(seed)
data_rng = torch.Generator().manual_seed(seed)
loader = DataLoader(TensorDataset(x, y, indices), batch_size=4,
shuffle=True, generator=data_rng, num_workers=0)
model = torch.nn.Linear(1, 1)
opt = torch.optim.SGD(model.parameters(), lr=0.1)
losses, order = [], []
for _ in range(2):
for xb, yb, ids in loader:
order.extend(ids.tolist())
opt.zero_grad(set_to_none=True)
loss = torch.nn.functional.mse_loss(model(xb), yb)
loss.backward()
opt.step()
losses.append(loss.item())
return order, losses, [p.detach().clone() for p in model.parameters()]
a, b, changed = run(7), run(7), run(8)
print("same_sample_order:", a[0] == b[0])
print("same_losses:", a[1] == b[1])
print("same_parameters:", all(torch.equal(p, q) for p, q in zip(a[2], b[2])))
print("different_seed_changes_order:", a[0] != changed[0])
assert a[0] == b[0] and a[1] == b[1]
assert all(torch.equal(p, q) for p, q in zip(a[2], b[2]))
怎样解读运行结果
本次 CPU 运行输出为:
same_sample_order: True
same_losses: True
same_parameters: True
different_seed_changes_order: True
同一个种子,两次运行的样本顺序、损失列表和参数都相同;换成另一个种子后,样本顺序发生变化。读者应在自己的训练函数外调用两次独立运行,保存顺序或样本 ID、原始损失和参数,然后按允许的数值误差比较,不要只比较四舍五入后的最后一个指标。
这个结果证明的是当前玩具程序的条件得到控制,不代表任何模型跨电脑、跨 GPU 或升级 PyTorch 后都会重现相同参数;验证指标相同也不保证参数完全一致。
增加 NumPy、多个 worker 或 CUDA 时怎样补齐
如果预处理使用 NumPy,全局随机数可设 numpy.random.seed(seed);新建的 numpy.random.default_rng(seed) 是独立生成器,应把 seed 或已有生成器明确传入。只设全局 seed 不会控制所有独立 Generator。
DataLoader 增加 num_workers 时,可在 worker_init_fn 中用 torch.initial_seed() % 2**32 初始化每个 worker 的 NumPy 和 Python 随机数,同时保留读取器的 generator;对应写法见前述官方文档。Windows 使用多进程时还要把入口放进 if __name__ == “__main__”,本文脚本保持单进程。
使用 CUDA 时,核对 cuDNN benchmark、确定性算子支持和文档要求的环境设置。torch.use_deterministic_algorithms(True) 遇到没有可用确定性实现的操作可能报错;这时先定位算子和对应版本说明,不能捕获后静默忽略错误并声称实现了确定性训练。确定性模式也可能带来性能代价。
常见问题:重复了,是不是就能证明实验结论可靠?
不能。单个种子可重复只是调试基础;正式实验还需固定数据版本和切分、记录依赖与设备,并用多个事先选定的种子检查结果波动。跨环境复现应比较任务指标及容差,而不是把本文的逐位比较直接当成普遍承诺。本文没有运行多 worker、CUDA、分布式训练或跨版本实验。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30330.html