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


Posted in Python onMay 12, 2021

由于在模型训练的过程中存在大量的随机操作,使得对于同一份代码,重复运行后得到的结果不一致。

因此,为了得到可重复的实验结果,我们需要对随机数生成器设置一个固定的种子。

CUDNN

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

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

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

Pytorch

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

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数目(线程数)不变,基本上也能够重复实验结果。

补充:pytorch 固定随机数种子踩过的坑

1.初步固定

def setup_seed(seed):
     torch.manual_seed(seed)
     torch.cuda.manual_seed_all(seed)
     torch.cuda.manual_seed(seed)
     np.random.seed(seed)
     random.seed(seed)
     torch.backends.cudnn.deterministic = True
     torch.backends.cudnn.enabled = False
     torch.backends.cudnn.benchmark = False
     #torch.backends.cudnn.benchmark = True #for accelerating the running
 setup_seed(2019)

2.继续添加如下代码:

tensor_dataset = ImageList(opt.training_list,transform)
def _init_fn(worker_id): 
    random.seed(10 + worker_id)
    np.random.seed(10 + worker_id)
    torch.manual_seed(10 + worker_id)
    torch.cuda.manual_seed(10 + worker_id)
    torch.cuda.manual_seed_all(10 + worker_id)
dataloader = DataLoader(tensor_dataset,                        
                    batch_size=opt.batchSize,     
                    shuffle=True,     
                    num_workers=opt.workers,
                    worker_init_fn=_init_fn)

3.在上面的操作之后发现加载的数据多次试验大部分一致了

但是仍然有些数据是不一致的,后来发现是pytorch版本的问题,将原先的0.3.1版本升级到1.1.0版本,问题解决

4.按照上面的操作后虽然解决了问题

但是由于将cudnn.benchmark设置为False,运行速度降低到原来的1/3,所以继续探索,最终解决方案是把第1步变为如下,同时将该部分代码尽可能放在主程序最开始的部分,例如:

import torch
import torch.nn as nn
from torch.nn import init
import pdb
import torch.nn.parallel
import torch.nn.functional as F
import torch.backends.cudnn as cudnn
import torch.optim as optim
import torch.utils.data
from torch.utils.data import DataLoader, Dataset
import sys
gpu_id = "3,2"
os.environ["CUDA_VISIBLE_DEVICES"] = gpu_id
print('GPU: ',gpu_id)
def setup_seed(seed):
     torch.manual_seed(seed)
     torch.cuda.manual_seed_all(seed)
     torch.cuda.manual_seed(seed)
     np.random.seed(seed)
     random.seed(seed)
     cudnn.deterministic = True
     #cudnn.benchmark = False
     #cudnn.enabled = False

setup_seed(2019)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Python 相关文章推荐
python类和继承用法实例
Jul 07 Python
Linux中安装Python的交互式解释器IPython的教程
Jun 13 Python
python 字典(dict)按键和值排序
Jun 28 Python
深入理解Python对Json的解析
Feb 14 Python
一百多行python代码实现抢票助手
Sep 25 Python
Python基础教程之if判断,while循环,循环嵌套
Apr 25 Python
python tools实现视频的每一帧提取并保存
Mar 20 Python
python将字母转化为数字实例方法
Oct 04 Python
python实现删除列表中某个元素的3种方法
Jan 15 Python
基于pycharm实现批量修改变量名
Jun 02 Python
基于Python实现粒子滤波效果
Dec 01 Python
JAVA SpringMVC实现自定义拦截器
Mar 16 Python
Python Parser的用法
May 12 #Python
pytorch MSELoss计算平均的实现方法
May 12 #Python
Django如何创作一个简单的最小程序
May 12 #Python
Pytorch中TensorBoard及torchsummary的使用详解
pytorch 一行代码查看网络参数总量的实现
May 12 #Python
pytorch查看网络参数显存占用量等操作
May 12 #Python
Python入门之使用pandas分析excel数据
May 12 #Python
You might like
DC动漫人物排行
2020/03/03 欧美动漫
Re:从零开始的异世界生活 第2季 开播啦
2020/07/24 日漫
页面利用渐进式JPEG来提升用户体验度
2014/12/01 PHP
PHP实现仿百度文库,豆丁在线文档效果(word,excel,ppt转flash)
2016/03/10 PHP
PHP mysqli_free_result()与mysqli_fetch_array()函数详解
2016/09/21 PHP
laravel多条件查询方法(and,or嵌套查询)
2019/10/09 PHP
深入理解javascript学习笔记(一) 编写高质量代码
2012/08/09 Javascript
js汉字转拼音实现代码
2013/02/06 Javascript
jquery实现在网页指定区域显示自定义右键菜单效果
2015/08/25 Javascript
jQuery实现的网页左侧在线客服效果代码
2015/10/23 Javascript
JS实现CheckBox复选框全选、不选或全不选功能
2020/07/28 Javascript
JavaScript每天必学之数组和对象部分
2016/09/17 Javascript
jQuery Dialog 打开时自动聚焦的解决方法(两种方法)
2016/11/24 Javascript
js数字计算 误差问题的快速解决方法
2017/02/28 Javascript
vue组件表单数据回显验证及提交的实例代码
2018/08/30 Javascript
JQuery实现ajax请求的示例和注意事项
2018/12/10 jQuery
小程序getLocation需要在app.json中声明permission字段
2019/04/04 Javascript
微信小程序 调用远程接口 给全局数组赋值代码实例
2019/08/13 Javascript
微信小程序 textarea 层级过高问题简单解决方案
2019/10/14 Javascript
基于javascript实现碰撞检测
2020/03/12 Javascript
Antd-vue Table组件添加Click事件,实现点击某行数据教程
2020/11/17 Javascript
[02:50]【扭转乾坤,只此一招】DOTA2全新版本永雾林渊开启新篇章
2020/12/24 DOTA
为Python的web框架编写前端模版的教程
2015/04/30 Python
python 时间戳与格式化时间的转化实现代码
2016/03/23 Python
浅析Python中的for 循环
2016/06/09 Python
基于python实现名片管理系统
2018/11/30 Python
Python基于Opencv来快速实现人脸识别过程详解(完整版)
2019/07/11 Python
利用CSS3实现的文字定时向上滚动
2016/08/29 HTML / CSS
介绍一下Python中webbrowser的用法
2013/05/07 面试题
财产公证书格式
2014/04/10 职场文书
家长会标语
2014/06/24 职场文书
亲子阅读的活动方案
2014/08/15 职场文书
个人违纪检讨书
2014/09/15 职场文书
2016国培学习心得体会
2016/01/08 职场文书
幼儿教师师德培训心得体会
2016/01/09 职场文书
儿童诗两首教学反思
2016/02/23 职场文书