美文网首页
PyTorch设置随机数种子使结果可复现

PyTorch设置随机数种子使结果可复现

作者: 几时见得清梦 | 来源:发表于2019-08-26 23:53 被阅读0次

    原理

    在神经网络中,参数默认是进行随机初始化的。不同的初始化参数往往会导致不同的结果。

    当得到比较好的结果时我们通常希望这个结果是可以复现的,在pytorch中,通过设置全局随机数种子可以实现这个目的。

    具体操作

    对随机数生成器设置固定种子的操作可以分为四部分。

    1. cuDNN

    cudnn中对卷积操作进行了优化,牺牲了精度来换取计算效率。
    如果需要保证可重复性,可以使用如下设置:

    from torch.backends import cudnn
    cudnn.benchmark = False            # if benchmark=True, deterministic will be False
    cudnn.deterministic = True
    

    不过实际上这个设置对精度影响不大,仅仅是小数点后几位的差别。所以如果不是对精度要求极高,其实不太建议修改,因为会使计算效率降低。

    2. PyTorch

    seed = 0
    torch.manual_seed(seed)            # 为CPU设置随机种子
    torch.cuda.manual_seed(seed)       # 为当前GPU设置随机种子
    torch.cuda.manual_seed_all(seed)   # 为所有GPU设置随机种子
    

    3. Python & NumPy

    如果读取数据的过程采用了随机预处理(如RandomCrop、RandomHorizontalFlip等),那么对python、numpy的随机数生成器也需要设置种子。

    import os
    import random
    import numpy as np
    seed = 0
    random.seed(seed)
    np.random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed) # 为了禁止hash随机化,使得实验可复现。
    

    4. dataloader

    如果dataloader采用了多线程(num_workers > 1), 那么由于读取数据的顺序不同,最终运行结果也会有差异。也就是说,改变num_workers参数,也会对实验结果产生影响。

    目前暂时没有发现解决这个问题的方法,但是只要固定num_workers数目(线程数)不变,基本上也能够重复实验结果。

    对于不同线程的随机数种子设置,主要通过DataLoader的worker_init_fn参数来实现。默认情况下使用线程ID作为随机数种子。如果需要自己设定,可以参考以下代码:

    GLOBAL_SEED = 1
     
    def set_seed(seed):
        random.seed(seed)
        np.random.seed(seed)
        torch.manual_seed(seed)
        torch.cuda.manual_seed(seed)
        torch.cuda.manual_seed_all(seed)
     
    GLOBAL_WORKER_ID = None
    def worker_init_fn(worker_id):
        global GLOBAL_WORKER_ID
        GLOBAL_WORKER_ID = worker_id
        set_seed(GLOBAL_SEED + worker_id)
     
    dataloader = DataLoader(dataset, batch_size=16, shuffle=True, num_workers=2, worker_init_fn=worker_init_fn)
    

    参考

    1. PyTorch的可重复性问题 (如何使实验结果可复现)

    相关文章

      网友评论

          本文标题:PyTorch设置随机数种子使结果可复现

          本文链接:https://www.haomeiwen.com/subject/fmijectx.html