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


Posted in Python onFebruary 20, 2020

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

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

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

1. CUDNN

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

from torch.backends import cudnn
cudnn.benchmark = False      # if benchmark=True, deterministic will be False
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数目(线程数)不变,基本上也能够重复实验结果。

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

以上这篇浅谈PyTorch的可重复性问题(如何使实验结果可复现)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 调用DLL操作抄表机
Jan 12 Python
Python使用函数默认值实现函数静态变量的方法
Aug 18 Python
仅用50行Python代码实现一个简单的代理服务器
Apr 08 Python
Python MySQLdb Linux下安装笔记
May 09 Python
django的聚合函数和aggregate、annotate方法使用详解
Jul 23 Python
django 简单实现登录验证给你
Nov 06 Python
使用pandas实现连续数据的离散化处理方式(分箱操作)
Nov 22 Python
python wav模块获取采样率 采样点声道量化位数(实例代码)
Jan 22 Python
python打印文件的前几行或最后几行教程
Feb 13 Python
python 读取.nii格式图像实例
Jul 01 Python
Python pip安装第三方库实现过程解析
Jul 09 Python
pandas 按日期范围筛选数据的实现
Feb 20 Python
pytorch 模型的train模式与eval模式实例
Feb 20 #Python
pytorch dataloader 取batch_size时候出现bug的解决方式
Feb 20 #Python
pytorch 使用加载训练好的模型做inference
Feb 20 #Python
pytorch中的inference使用实例
Feb 20 #Python
python encrypt 实现AES加密的实例详解
Feb 20 #Python
Python关于反射的实例代码分享
Feb 20 #Python
Python3监控疫情的完整代码
Feb 20 #Python
You might like
模拟OICQ的实现思路和核心程序(一)
2006/10/09 PHP
php 目录与文件处理-郑阿奇(续)
2011/07/04 PHP
基于php中使用excel的简单介绍
2013/08/02 PHP
php实现阳历阴历互转的方法
2015/10/28 PHP
phalcon框架使用指南
2016/02/23 PHP
php使用PDO从数据库表中读取数据的实现方法(必看)
2017/06/02 PHP
php生成随机数/生成随机字符串的方法小结【5种方法】
2020/05/27 PHP
基于Jquery的将DropDownlist的选中值赋给label的实现代码
2011/05/06 Javascript
JQuery实现简单验证码提示解决方案
2012/12/20 Javascript
JavaScript实现简单的时钟实例代码
2013/11/23 Javascript
js获取url中的参数且参数为中文时通过js解码
2014/03/19 Javascript
用JavaScript实现一个代码简洁、逻辑不复杂的多级树
2014/05/23 Javascript
了不起的node.js读书笔记之node的学习总结
2014/12/22 Javascript
教你使用javascript简单写一个页面模板引擎
2015/05/05 Javascript
javascript实现根据iphone屏幕方向调用不同样式表的方法
2015/07/13 Javascript
jQuery入门基础知识学习指南
2015/08/14 Javascript
简单实现限制uploadify上传个数
2015/11/16 Javascript
JavaScript设计模式经典之命令模式
2016/02/24 Javascript
vue组件Prop传递数据的实现示例
2017/08/17 Javascript
基于vue-upload-component封装一个图片上传组件的示例
2018/10/16 Javascript
微信小程序dom操作的替代思路实例分析
2018/12/06 Javascript
Bootstrap 实现表格样式、表单布局的实例代码
2018/12/09 Javascript
vue element upload组件 file-list的动态绑定实现
2019/10/11 Javascript
原生javascript制作的拼图游戏实现方法详解
2020/02/23 Javascript
详解React 条件渲染
2020/07/08 Javascript
python中zip和unzip数据的方法
2015/05/27 Python
Python模块搜索路径代码详解
2018/01/29 Python
Python文本文件的合并操作方法代码实例
2020/03/31 Python
Python多线程正确用法实例解析
2020/05/30 Python
CSS3的Flexbox布局的简明入门指南
2016/04/08 HTML / CSS
机电一体化应届生求职信范文
2014/01/24 职场文书
幼儿教师培训感言
2014/03/08 职场文书
《陈毅探母》教学反思
2014/05/01 职场文书
群众路线领导班子整改方案
2014/10/25 职场文书
工作保证书
2015/01/17 职场文书
企业内部管理控制:采购授权审批制度范本
2020/01/19 职场文书