美文网首页
pytorch训练过程的复现, 可重复

pytorch训练过程的复现, 可重复

作者: Williamongh | 来源:发表于2020-02-02 00:27 被阅读0次

    本文转载自https://blog.csdn.net/hyk_1996/article/details/84307108,同时主要参考了https://blog.csdn.net/u013517182/article/details/93032884https://zhuanlan.zhihu.com/p/81039955

    由于在模型训练的过程中存在大量的随机操作,使得对于同一份代码,重复运行后得到的结果不一致。因此,为了得到可重复的实验结果,我们需要对随机数生成器设置一个固定的种子。

    许多博客都有介绍如何解决这个问题,但是很多都不够全面,往往不能保证结果精确一致。我经过许多调研和实验,总结了以下方法,记录下来。

    全部设置可以分为三部分:

    1. CUDNN

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

    # 大部分情况下,设置这个 flag 可以让内置的 cuDNN 的 auto-tuner 自动寻找最适合当前配置的高效算法,优化运行效率
    # 前提条件是输入的数据维度一致,如果输入在每次 iteration 都变化,会导致 cnDNN 每次都会寻找最优配置,反而降低效率
    torch.backends.cudnn.benchmark = False            # if benchmark=True, deterministic will be False
    
    # 可以将cudnn中具有随机性的操作固定
    torch.backends.cudnn.deterministic = True
    

    2. Pytorch

    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 random
    import numpy as np
    random.seed(seed)
    np.random.seed(seed)
    

    最后,关于dataloader:

    注意,如果dataloader采用了多线程(num_workers > 1), 那么由于读取数据的顺序不同,最终运行结果也会有差异。也就是说,改变num_workers参数,也会对实验结果产生影响。目前暂时没有发现解决这个问题的方法,但是只要固定num_workers数目(线程数)不变,基本上也能够重复实验结果。

    对于不同线程的随机数种子设置,主要通过DataLoaderworker_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)
    

    然而

    上述方法可以使得在CPU情况下, 训练过程完全一致。然而在GPU情况下,上述方法只能使得训练过程尽可能接近。
    如果在GPU训练过程中输出loss的话,可以发现loss在两次训练过程中,小数点后几位不是完全一致的。原因不明,似乎无解。

    相关文章

      网友评论

          本文标题:pytorch训练过程的复现, 可重复

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