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?
看以下链接