PyTorch随机数控制全指南:从种子设置到状态管理
主要函数总览
函数 | 作用 | 适用范围 |
---|---|---|
torch.seed() | 自动生成并设置随机种子 | 主要影响 CPU,GPU 行为依赖具体版本 |
torch.initial_seed() | 查询初始种子值 | CPU |
torch.manual_seed() | 设置全局随机种子 | CPU/CUDA |
torch.get_rng_state() | 获取 CPU 随机状态 | CPU |
torch.set_rng_state() | 恢复 CPU 随机状态 | CPU |
torch.cuda.get_rng_state() | 获取 GPU 随机状态 | CUDA |
torch.cuda.set_rng_state() | 恢复 GPU 随机状态 | CUDA |
torch.seed()
- 在 PyTorch 中,
torch.seed()
是一个用于设置随机数生成器(RNG)种子的函数,以确保实验的可重复性。 torch.seed()
会将所有随机数生成器(包括 CPU 和 CUDA 设备)的种子设置为同一个随机初始值(基于系统时间或熵源)。它返回一个 64 位整数作为生成的种子值。
seed = torch.seed()
作用范围
- PyTorch 的全局随机状态:影响所有使用 PyTorch 随机数生成器的操作,例如:
- 模型权重初始化(如
torch.nn.init
) - 数据集的随机打乱(如
DataLoader(shuffle=True)
) - 随机增强(如图像变换中的
RandomCrop
) - 任何使用
torch.rand()
、torch.randn()
等函数的操作。
- 模型权重初始化(如
- CUDA 设备:如果使用了 GPU,CUDA 的随机种子也会被同步设置。
与 manual_seed()
的区别
torch.seed()
:自动生成一个随机种子并设置它(无需参数),适合快速实验但不精确控制种子值。torch.manual_seed(seed)
:需要手动指定一个整数作为种子(如torch.manual_seed(42)
),适合需要完全可复现的实验。
栗子
import torch# 自动生成并设置随机种子
seed = torch.seed()
print("Generated seed:", seed) # 例如输出: 123456789# 验证随机性
a = torch.rand(1) # 随机张量
b = torch.rand(1) # 另一个随机张量
print(a, b) # 每次运行结果不同(除非种子固定)
注意事项
- 多设备/进程: 在分布式训练中,需为每个进程单独设置种子(可能还需设置
torch.cuda.manual_seed_all()
)。 - 其他库的影响: PyTorch 的种子不控制 NumPy、Python 内置
random
等库,需单独设置(如np.random.seed(42)
)。 - 性能: 频繁调用
torch.seed()
可能影响性能,建议在实验开始时只设置一次。
常见用途
- 调试:通过固定种子复现问题。
- 实验对比:确保不同模型在相同数据划分和初始化条件下训练。
torch.manual_seed()
- 在 PyTorch 中,
torch.manual_seed()
是一个用于手动设置随机数生成器(RNG)种子的函数,目的是确保实验的完全可复现性。- 为 CPU 和 GPU(CUDA) 的随机数生成器设置一个确定的种子值。
- 影响所有基于 PyTorch 的随机操作(如张量初始化、数据打乱、Dropout 等)。
- 与
torch.seed()
(自动生成随机种子)不同,manual_seed()
需要显式指定种子值。
import torch
seed=14
torch.manual_seed(seed) # seed 必须是一个整数(通常选 42、123 等)
参数 | 类型 | 说明 |
---|---|---|
seed | int | 任意整数(范围:0 到 2⁶⁴-1) |
作用范围
- PyTorch 全局随机状态:
- 影响
torch.rand()
,torch.randn()
,torch.randint()
等随机函数。 - 控制模型初始化(如
nn.Linear
的权重)。 - 数据加载器的打乱(如
DataLoader(shuffle=True)
)。
- 影响
- CUDA 设备:如果使用 GPU,CUDA 的随机种子也会被同步设置(等同于调用
torch.cuda.manual_seed_all()
)。
与 torch.seed()
对比
函数 | 种子来源 | 适用场景 |
---|---|---|
torch.seed() | 自动生成 | 快速实验,无需精确复现 |
torch.manual_seed() | 手动指定 | 需要完全可复现的结果 |
栗子
import torch# 设置随机种子为 42
torch.manual_seed(42)# 生成随机张量(结果可复现)
a = torch.rand(2, 2)
print(a)
# 输出(每次运行相同):
# tensor([[0.8823, 0.9150],
# [0.3829, 0.9593]])# 重新设置相同种子会得到相同结果
torch.manual_seed(42)
b = torch.rand(2, 2)
print(b == a) # 所有元素为 True
注意事项
- GPU 确定性:即使设置了种子,CUDA 操作可能因并行计算导致轻微差异。若需完全确定性,需额外设置。(注意:可能降低训练速度)
torch.backends.cudnn.deterministic = True # 启用确定性算法 torch.backends.cudnn.benchmark = False # 关闭自动优化
- 多进程/多GPU: 在分布式训练中,需为每个进程单独设置种子。
torch.manual_seed(42 + rank) # rank 是进程编号 torch.cuda.manual_seed_all(42 + rank)
- 其他库的种子:PyTorch 的种子不控制 NumPy 或 Python 内置
random
模块,需单独设置:import numpy as np import random np.random.seed(42) random.seed(42)
常见用途
- 调试模型:通过固定种子复现训练过程中的错误。
- 实验对比:确保不同模型在相同初始化条件下公平比较。
- 教学演示:让学生获得与教程一致的随机结果。
torch.initial_seed()
- 在 PyTorch 中,
torch.initial_seed()
是一个用于获取当前随机数生成器(RNG)的初始种子值的函数。它通常用于调试或验证随机种子的设置情况。 - 返回当前随机数生成器的初始种子值(即通过
torch.manual_seed()
或torch.seed()
设置的种子)。 - 如果未手动设置种子,则返回一个基于系统时间或默认熵源生成的种子值。
- 主要用于调试或检查随机状态,确保实验的可复现性。
seed = torch.initial_seed()
- 返回值:一个
int
类型的整数,表示当前 RNG 的初始种子。
栗子
示例 1:获取默认种子
import torch# 未设置种子时,返回自动生成的种子
default_seed = torch.initial_seed()
print("Default seed:", default_seed) # 例如:42(每次运行可能不同)
示例 2:获取手动设置的种子
import torch# 手动设置种子
torch.manual_seed(42)# 获取当前初始种子
current_seed = torch.initial_seed()
print("Current seed:", current_seed) # 输出:42
示例 3:验证种子是否生效
import torch# 设置种子并生成随机张量
torch.manual_seed(42)
a = torch.rand(2, 2)# 检查初始种子
print("Initial seed:", torch.initial_seed()) # 输出:42# 重新设置相同种子,应得到相同随机张量
torch.manual_seed(42)
b = torch.rand(2, 2)print("a == b:", torch.all(a == b)) # 输出:True
注意事项
-
initial_seed()
vsmanual_seed()
torch.manual_seed(seed)
:设置随机种子。torch.initial_seed()
:获取当前初始种子值(不修改 RNG 状态)。
-
与
torch.seed()
的区别torch.seed()
:重新生成并设置随机种子(返回新种子)。torch.initial_seed()
:仅查询当前初始种子(不修改 RNG)。
-
GPU(CUDA)种子
torch.initial_seed()
仅返回 CPU 随机数生成器的种子,不涉及 CUDA。- 要获取 CUDA 种子,需使用
torch.cuda.initial_seed()
。
-
多进程/分布式训练
- 在分布式训练中,每个进程可能有不同的初始种子,需单独检查。
- 典型应用场景
- 调试随机初始化问题:检查模型权重初始化是否一致。
- 实验复现:记录初始种子,确保后续实验可复现。
- 随机性验证:确认
DataLoader
或Dropout
是否按预期工作。
总结对比
函数 | 作用 | 返回值 |
---|---|---|
torch.manual_seed() | 设置随机种子 | None |
torch.seed() | 自动生成并设置随机种子 | 新种子 (int ) |
torch.initial_seed() | 获取当前初始种子 | 当前种子 (int ) |
如果需要在 PyTorch 中确保实验的可复现性,建议结合:
torch.manual_seed(42)
torch.backends.cudnn.deterministic = True # 启用确定性 CUDA 计算
torch.backends.cudnn.benchmark = False # 关闭自动优化
torch.get_rng_state()
- 在 PyTorch 中,
torch.get_rng_state()
是一个用于获取当前随机数生成器(RNG)完整状态的函数,它返回一个表示内部随机状态的张量。这个功能在需要保存和恢复随机状态时非常有用,例如在实验的某个阶段冻结随机性,稍后恢复。
- 返回一个
torch.ByteTensor
,表示 PyTorch 当前 CPU 随机数生成器的内部状态。该状态可以保存到磁盘或传递给torch.set_rng_state()
以恢复之前的随机状态。 - 不影响 CUDA 的随机状态(GPU 的随机状态需使用
torch.cuda.get_rng_state()
)。
rng_state = torch.get_rng_state()
- 返回值:一个
torch.ByteTensor
,包含当前 RNG 的完整状态信息。
栗子
- 案例参考
torch.set_rng_state()
的栗子。
注意事项
-
仅适用于 CPU:
torch.get_rng_state()
只返回 CPU 的随机状态。 对于GPU,需使用torch.cuda.get_rng_state()
和torch.cuda.set_rng_state()
。 -
状态张量的内容不透明:返回的
ByteTensor
是 PyTorch 内部使用的二进制数据,用户无需解析其内容。 -
与
initial_seed()
的区别:initial_seed()
返回初始种子值(整数),而get_rng_state()
返回完整的运行时状态(张量)。 -
多线程/分布式训练:在并行环境中,每个线程的随机状态独立管理,需分别保存和恢复。
典型应用场景
- 实验复现:在代码的特定位置保存随机状态,确保后续操作可重复。
- 调试随机性:比较不同阶段的随机状态,定位不一致问题。
- 强化学习:在环境交互过程中冻结随机状态,便于回放。
torch.set_rng_state()
- 在 PyTorch 中,
torch.set_rng_state()
是一个用于恢复随机数生成器(RNG)状态的函数,通常与torch.get_rng_state()
配合使用,以实现随机状态的保存和恢复。以下是详细介绍:
- 恢复 CPU 随机数生成器的内部状态,使其回到某个特定的随机状态。
- 通常与
torch.get_rng_state()
结合使用,先保存随机状态,稍后恢复。 - 仅影响 CPU 的随机状态,GPU(CUDA)的随机状态需要使用
torch.cuda.set_rng_state()
。
torch.set_rng_state(new_state)
- 参数:
new_state
(torch.ByteTensor
):要恢复的随机状态,通常由torch.get_rng_state()
获取。- 返回值:
None
(仅修改内部 RNG 状态)。
- 返回值:
栗子
示例 1:保存和恢复随机状态
import torch# 生成一些随机数
a = torch.rand(2, 2)
print("First random tensor:\n", a)# 保存当前随机状态
saved_state = torch.get_rng_state()# 生成另一组随机数(状态已变化)
b = torch.rand(2, 2)
print("Second random tensor (different from a):\n", b)# 恢复之前保存的随机状态
torch.set_rng_state(saved_state)# 重新生成随机数,结果应与第一次相同
c = torch.rand(2, 2)
print("Restored random tensor (same as a):\n", c)print("a == c:", torch.allclose(a, c)) # 输出: True
示例 2:结合 manual_seed
使用
import torch# 设置固定种子
torch.manual_seed(42)# 获取初始随机状态
initial_state = torch.get_rng_state()# 生成随机张量
x = torch.rand(2, 2)
print("x:\n", x)# 修改随机状态(例如运行其他随机操作)
_ = torch.rand(100, 100) # 消耗随机数,改变状态# 恢复初始状态
torch.set_rng_state(initial_state)# 重新生成张量,结果应与 x 相同
y = torch.rand(2, 2)
print("y == x:", torch.allclose(x, y)) # 输出: True
示例3:完整代码示例(CPU + GPU)
import torch# === CPU 随机状态管理 ===
torch.manual_seed(42)
cpu_state = torch.get_rng_state()
a = torch.rand(2, 2)
print("CPU - First sample:\n", a)torch.set_rng_state(cpu_state)
b = torch.rand(2, 2)
print("CPU - Restored sample == first sample:", torch.allclose(a, b))# === GPU 随机状态管理 ===
if torch.cuda.is_available():torch.cuda.manual_seed_all(42)gpu_state = torch.cuda.get_rng_state()c = torch.rand(2, 2, device='cuda')print("GPU - First sample:\n", c)torch.cuda.set_rng_state(gpu_state)d = torch.rand(2, 2, device='cuda')print("GPU - Restored sample == first sample:", torch.allclose(c, d))
- 通过合理使用
get_rng_state()
和set_rng_state()
,可以精确控制 PyTorch 中的随机性,确保实验的可控性和可复现性。
注意事项
- 仅适用于 CPU :
torch.set_rng_state()
仅恢复 CPU 的随机状态,不影响 GPU(CUDA)。 要恢复 GPU 的随机状态,需使用torch.cuda.set_rng_state()
。 - 状态张量必须匹配 :
new_state
必须是一个有效的随机状态张量(通常由torch.get_rng_state()
返回),否则可能引发错误。 - 与
manual_seed
的区别torch.manual_seed(seed)
重置整个 RNG 状态(基于给定的种子)。torch.set_rng_state(state)
精确恢复某个历史状态(更细粒度控制)。
- 多线程/分布式训练:在并行计算中,每个线程需单独管理随机状态。
典型应用场景
- 实验复现:在代码的特定位置保存随机状态,稍后恢复以复现结果。
- 调试随机性:比较不同阶段的随机状态,定位不一致问题。
- 强化学习:在环境交互过程中冻结随机状态,便于回放实验。
总结对比
函数 | 作用 | 适用范围 |
---|---|---|
torch.seed() | 自动生成并设置随机种子 | 主要影响 CPU,GPU 行为依赖具体版本 |
torch.initial_seed() | 查询初始种子值 | CPU |
torch.manual_seed() | 设置全局随机种子 | CPU/CUDA |
torch.get_rng_state() | 获取 CPU 随机状态 | CPU |
torch.set_rng_state() | 恢复 CPU 随机状态 | CPU |
torch.cuda.get_rng_state() | 获取 GPU 随机状态 | CUDA |
torch.cuda.set_rng_state() | 恢复 GPU 随机状态 | CUDA |
torch.set_rng_state()
用于精确恢复 CPU 的随机状态,适用于需要完全控制随机性的场景。与torch.get_rng_state()
配合使用,可实现实验的完整复现。- GPU 的随机状态需通过
torch.cuda.set_rng_state()
管理。