pytorch用同一个随机种子,使每次训练结果相同,随机种子设置为3407会出现好的效果

2023-7-7更新:

建议使用:

可以使用以下语句代替下方麻烦的操作:

import pytorch_lightning as pl

pl.utilities.seed.seed_everything(3407)

示例:Retmol中使用了上述的方法

def run_training(ckpt_dir=None):  # 'megatron_molbart_checkpoint'):
    deepspeed.init_distributed()
    initialize_megatron()
    args = get_args()
    args.iteration = 0

    pl.utilities.seed.seed_everything(args.seed)

if __name__ == '__main__':
    run_training()

或者使用:

经过我的测试,好像pl的seed_everything函数比下方的代码应该更全一点。

import torch
import numpy as np
import random
import os

def setup_seed(seed=3407):
    random.seed(seed)  # Python的随机性
    os.environ['PYTHONHASHSEED'] = str(seed)  # 设置Python哈希种子,为了禁止hash随机化,使得实验可复现
    np.random.seed(seed)  # numpy的随机性
    torch.manual_seed(seed)  # torch的CPU随机性,为CPU设置随机种子
    torch.cuda.manual_seed(seed)  # torch的GPU随机性,为当前GPU设置随机种子
    torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU.   torch的GPU随机性,为所有GPU设置随机种子
    torch.backends.cudnn.deterministic = True # 选择确定性算法
    torch.backends.cudnn.benchmark = False # if benchmark=True, deterministic will be False
    torch.backends.cudnn.enabled = False


设置随机种子:

在使用PyTorch时,如果希望通过设置随机数种子,在gpu或cpu上固定每一次的训练结果,则需要在程序执行的开始处添加以下代码:

创建文件:utils/fix_random_seed.py:

import torch
import numpy as np
import random
import os

def setup_seed(seed=3407):
    random.seed(seed)  # Python的随机性
    os.environ['PYTHONHASHSEED'] = str(seed)  # 设置Python哈希种子,为了禁止hash随机化,使得实验可复现
    np.random.seed(seed)  # numpy的随机性
    torch.manual_seed(seed)  # torch的CPU随机性,为CPU设置随机种子
    torch.cuda.manual_seed(seed)  # torch的GPU随机性,为当前GPU设置随机种子
    torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU.   torch的GPU随机性,为所有GPU设置随机种子
    torch.backends.cudnn.deterministic = True # 选择确定性算法
    torch.backends.cudnn.benchmark = False # if benchmark=True, deterministic will be False
    torch.backends.cudnn.enabled = False

在main()中加入以下代码就可以实现固定:

from utils.fix_random_seed import setup_seed
setup_seed()

torch.backends.cudnn.benchmark设置为True时,会让CUDNN根据当前硬件情况自动寻找最合适的卷积实现方式,从而减少卷积计算时间;而设置为False时,则会禁用这个自动调优功能,从而更保证卷积计算的结果的可复现性。【torch.backends.cudnn.benchmark设置为True时可能会对模型训练速度带来一定的提升,但并不能保证训练精度提升】

torch.backends.cudnn.deterministic设置为True时,会让CUDNN使用确定性算法来计算卷积操作,从而保证相同输入下卷积计算结果的一致性;而设置为False则允许CUDNN使用非确定性算法计算卷积操作,从而可能得到更高的计算速度。


一些特殊的关于随机化的问题:

1.关于nn.SLTM的问题

实验中发现,如果设置了nn.LSTM的dropout参数,是无法通过随机种子的固定来复现实验结果的。这似乎是一个cuDNN的bug,在此记录一下。

相关讨论见nn.LSTM gives nondeterministic results with dropout and multiple layers

示例如下:

lstm = nn.LSTM(input_size = 256, 
               hidden_size = 128, 
               num_layers = 1, 
               batch_first = True, 
               dropout = 0.5 )

2.关于nn.Embedding()的问题

在数据预处理阶段使用了随机初始化的nn.Embedding(),并将其通过持久化方式pickle保存了下来。

再次使用它时,通过pickle.load()读取,即使固定了随机数种子,此时读取到的nn.Embedding()中的weight与当初保存下来的weight是不同的。

暂不清楚原因。


为什么要将随机种子设置为3407?

看以下链接

https://mp.weixin.qq.com/s/bxspzdoHQlAtKeKJqcP_FA
 

  • 22
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马鹏森

太谢谢了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值