• PyTorch设置可复现/重复实验


    搬来了定型设置的方法,深度学习在训练过程中,由于随机初始化,样本读取的随机性,导致重复的实验结果会有差别,个别情况甚至波动较大。一般论文为了严谨,实验结论能够复现/可重复,通常采取固定随机种子使得结果确定

    确定性设置

    1 随机种子设置

    随机函数是最大的不确定性来源,包含了模型参数的随机初始化,样本的shuffle。

    • PyTorch 随机种子

    • python 随机种子

    • numpy 随机种子

    1. # PyTorch
    2. import torch
    3. torch.manual_seed(0)
    4. # python
    5. import random
    6. random.seed(0)
    7. # Third part libraries
    8. import numpy as np
    9. np.random.seed(0)

    CPU版本下,上述随机种子设置完成之后,基本就可实现实验的可复现了。

    对于GPU版本,存在大量算法实现为不确定结果的算法,这种算法实现效率很高,但是每次返回的值会不完全一样。主要是由于浮点精度舍弃,不同浮点数以不同顺序相加,值可能会有很小的差异(小数点最末位)。

    2 GPU算法确定性实现

    GPU算法的不确定来源有两个

    • CUDA convolution benchmarking

    • nondeterministic algorithms

    CUDA convolution benchmarking 是为了提升运行效率,对模型参数试运行后,选取最优实现。不同硬件以及benchmarking本身存在噪音,导致不确定性

    nondeterministic algorithms:GPU最大优势就是并行计算,如果能够忽略顺序,就避免了同步要求,能够大大提升运行效率,所以很多算法都有非确定性结果的算法实现。通过设置use_deterministic_algorithms,就可以使得pytorch选择确定性算法。

    1. # 不需要benchmarking
    2. torch.backends.cudnn.benchmark=False
    3. # 选择确定性算法
    4. torch.use_deterministic_algorithms()

    RUNTIME ERROR

    对于一个PyTorch 的函数接口,没有确定性算法实现,只有非确定性算法实现,同时设置了use_deterministic_algorithms(),那么会导致运行时错误。比如:

    1. >>> import torch
    2. >>> torch.use_deterministic_algorithms(True)
    3. >>> torch.randn(2, 2).cuda().index_add_(0, torch.tensor([0, 1]), torch.randn(2, 2))
    4. Traceback (most recent call last):
    5. File "", line 1, in <module>
    6. RuntimeError: index_add_cuda_ does not have a deterministic implementation, but you set
    7. 'torch.use_deterministic_algorithms(True)'. ...

    错误原因:

    index_add没有确定性的实现,出现这种错误,一般都是因为调用了torch.index_select 这个api接口,或者直接调用tensor.index_add_。

    解决方案:

    自己定义一个确定性的实现,替换调用的接口。对于torch.index_select 这个接口,可以有如下的实现。

    1. def deterministic_index_select(input_tensor, dim, indices):
    2. """
    3. input_tensor: Tensor
    4. dim: dim
    5. indices: 1D tensor
    6. """
    7. tensor_transpose = torch.transpose(x, 0, dim)
    8. return tensor_transpose[indices].transpose(dim, 0)

    样本读取随机

    1. 多线程情况下,设置每个线程读取的随机种子

    2. 设置样本generator

    1. # 设置每个读取线程的随机种子
    2. def seed_worker(worker_id):
    3. worker_seed = torch.initial_seed() % 2**32
    4. numpy.random.seed(worker_seed)
    5. random.seed(worker_seed)
    6. g = torch.Generator()
    7. # 设置样本shuffle随机种子,作为DataLoader的参数
    8. g.manual_seed(0)
    9. DataLoader(
    10. train_dataset,
    11. batch_size=batch_size,
    12. num_workers=num_workers,
    13. worker_init_fn=seed_worker,
    14. generator=g,
    15. )

    有点短哦~~   whaosoft aiot http://143ai.com 

  • 相关阅读:
    RK3588 I2C设备开发硬件检测
    c语言:关键字(一)
    运维自动化之域名系统
    (GCC)STM32基础详解之全局资源的使用
    git pull and git fetch 到底有什么区别?
    KT148A语音芯片驱动8欧0.5W的喇叭声音小可以换喇叭或者外挂功放吗
    字符串左旋解法和子字符串判断法
    【NR 定位】3GPP NR Positioning 5G定位标准解读(一)
    Leetcode1071. 字符串的最大公因子(三种方法,带详细解析)
    单片机电子元器件-按键
  • 原文地址:https://blog.csdn.net/qq_29788741/article/details/127895434