PyTorch系列 | 随机种子与可复现性

话不多说,先上代码:

def get_random_seed(seed):
    random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

get_random_seed(42)

上述是使用 PyTorch 时比较常见的设置随机种子的代码。通常来说,在不同的 CPU 和 GPU 上,即使设置了相同的随机种子,也不能够保证能复现出相同的结果。但是理论上,在同一设备上是能够进行复现的,一般需要在主程序前,同时固定 PyTorch 、Python、Numpy 的随机种子。

这里解释一下代码中的部分代码:

1.os.environ[‘PYTHONHASHSEED’] = str(seed)

主要是为了禁止 hash 随机化。

2.torch.manual_seed(seed)

torch.cuda.manual_seed(seed) 的功能是类似的,一个是设置当前 CPU 的随机种子,而另一个是设置当前 GPU 的随机种子,如果存在多个 GPU 可以使用 torch.cuda.manual_seed_all(seed) 对全部 GPU 都设置随机种子。

3.torch.backends.cudnn.deterministic = True

这行代码就如同其名字一样,确定是否使用确定性卷积算法(默认是 False ),如果为 True,则能保证在相同设备上的相同输入能够实现相同输出。

4.torch.backends.cudnn.benchmark = False

如果设置 torch.backends.cudnn.benchmark = True 会让程序在一开始时增加额外的预处理时间,以让整个 model 的卷积层寻找到最适合的、最有效率的卷积实现算法,进而实现网络加速,但是与此同时可能会导致结果不可复现。

补充 1:

在这里插入图片描述

在 PyTorch 官网有上图这么一段话,仅使用 torch.manual_seed 就可以固定所有设备的 RNG 的随机种子,包括CPU 和 CUDA 。但是,目前普遍的还是使用文章一开始的那个代码,至于原因…

补充 2:

在确保实验结果可复现,还应该要注意 DataLoader,这是经常被忽略掉的地方,做法是使用 worker_init_fn 去保证可复现性(这里主要是多进程加载数据时会产生这个问题)。

def seed_worker(worker_id):
    worker_seed = torch.initial_seed() % 2**32
    numpy.random.seed(worker_seed)
    random.seed(worker_seed)

DataLoader(
    train_dataset,
    batch_size=batch_size,
    num_workers=num_workers,
    worker_init_fn=seed_worker
)

补充 3:

在 model 中,不仅是卷积层,在其他的 operations 也存在使用非确定性算法的情况,如果想要设置所有的 operations 都使用确定性算法,则可使用 torch.use_deterministic_algorithms(True) ,但是这里会存在一个问题,如果你的 model 中存在一些无法使用确定性算法的 operation,就会报错 RuntimeError ,例如 AdaptiveMaxPool2d 等。

补充 4:

复现依然是个难题,很少见到有人能做到完全复现,所以,只要是能复现到差不多效果,也就不错了。这里面涉及到非常多且难的专业知识,我目前掌握的并不充分,我也会持续学习下去…文中如有错误,欢迎留言指正及补充。

<think>好的,我需要回答用户如何在PyTorch中设置随机种子以确保实验可复现。首先,我应该回忆PyTorch中影响随机的各个部分。通常,随机种子涉及Python的random模块、NumPy、PyTorch的CPU和GPU操作,以及CUDA环境。 用户可能已经知道设置PyTorch随机种子,但可能忽略其他库,比如NumPy或Python内置的random模块。所以,我需要涵盖所有这些方面。另外,使用CUDA时,确定算法和基准模式也会影响结果,特别是当使用GPU时。 接下来,我需要分步骤说明,确保每个可能引入随机的地方都被覆盖。例如,使用torch.manual_seed()来设置PyTorch的CPU和CUDA的随机种子,但如果是多GPU环境,可能需要额外的设置。另外,设置deterministic和benchmark为False可以避免cuDNN的自动优化带来的不确定。 然后,代码示例是必要的,这样用户可以直观地看到如何实现这些设置。需要包括导入模块、设置种子、配置CuDNN等部分。同时,要提到即使设置了这些,完全的可复现可能仍然难以保证,尤其是当使用多线程或不同硬件时,这一点很重要,避免用户遇到问题时感到困惑。 最后,生成相关问题时要围绕用户可能进一步想了解的内容,比如设置种子的必要、处理多GPU情况、避免CuDNN不确定的方法,以及无法完全复现时的解决方法。这些问题可以帮助用户更深入地理解问题,并解决实际应用中可能遇到的困难。</think>### 如何在PyTorch中设置随机种子以确保实验可复现 为确保PyTorch实验的可复现,需固定所有可能影响随机的来源,包括Python、NumPy、PyTorch的CPU/GPU操作以及CUDA环境。以下是具体步骤: --- #### **1. 设置基础随机种子** ```python import random import numpy as np import torch seed = 42 # 可自定义任意整数 random.seed(seed) # Python内置随机模块 np.random.seed(seed) # NumPy随机生成器 torch.manual_seed(seed) # PyTorch的CPU随机种子(同时影响CUDA设备) ``` --- #### **2. 处理GPU相关的随机** 若使用GPU,需额外设置以下参数以限制CUDA的随机行为: ```python if torch.cuda.is_available(): torch.cuda.manual_seed(seed) # 当前GPU的随机种子 torch.cuda.manual_seed_all(seed) # 所有GPU的随机种子(多卡环境) torch.backends.cudnn.deterministic = True # 强制使用确定算法 torch.backends.cudnn.benchmark = False # 关闭cuDNN自动优化 ``` --- #### **3. 完整代码示例** ```python import random import numpy as np import torch def set_seed(seed): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False set_seed(42) ``` --- #### **注意事项** - **硬件/库版本差异**:即使设置相同种子,不同GPU型号或库版本可能导致结果差异[^1]。 - **并行计算**:使用多线程(如DataLoader的`num_workers>0`)可能引入不确定,可通过设置`num_workers=0`或固定`worker_init_fn`缓解。 - **局限**:某些PyTorch操作(如部分卷积实现)天生具有非确定,需依赖`torch.use_deterministic_algorithms(True)`(可能影响能)。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值