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入门篇之面向对象
Oct 20 Python
Python制作爬虫抓取美女图
Jan 20 Python
Python使用itchat模块实现简单的微信控制电脑功能示例
Aug 26 Python
matlab灰度图像调整及imadjust函数的用法详解
Feb 27 Python
Django {{ MEDIA_URL }}无法显示图片的解决方式
Apr 07 Python
python 弧度与角度互转实例
Apr 15 Python
Python matplotlib可视化实例解析
Jun 01 Python
使用K.function()调试keras操作
Jun 17 Python
Python多线程的退出控制实现
Aug 10 Python
Python基于unittest实现测试用例执行
Nov 25 Python
解决numpy数组互换两行及赋值的问题
Apr 17 Python
Python 图片添加美颜效果
Apr 28 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
简单的过滤字符串中的HTML标记
2006/12/25 PHP
php中文字母数字验证码实现代码
2008/04/25 PHP
PHP伪静态写法附代码
2008/06/20 PHP
PHP判断图片格式的七种方法小结
2013/06/03 PHP
神盾加密解密教程(二)PHP 神盾解密
2014/06/08 PHP
PHP将Excel导入数据库及数据库数据导出至Excel的方法
2015/06/24 PHP
PHP读MYSQL中文乱码的快速解决方法
2016/10/01 PHP
PHP 7.4 新语法之箭头函数实例详解
2019/05/09 PHP
checkbox全选/取消全选以及checkbox遍历jQuery实现代码
2009/12/02 Javascript
jQuery插件datalist实现很好看的input下拉列表
2015/07/14 Javascript
Javascript中document.referrer隐藏来源的方法
2017/01/16 Javascript
js 将canvas生成图片保存,或直接保存一张图片的实现方法
2018/01/02 Javascript
Vue-router的使用和出现空白页,路由对象属性详解
2018/09/03 Javascript
vue滚动固定顶部及修改样式的实例代码
2019/05/30 Javascript
解决iView Table组件宽度只变大不变小的问题
2020/11/13 Javascript
[06:33]DOTA2亚洲邀请赛小组赛第二日 TOP10精彩集锦
2015/01/31 DOTA
[00:32]2018DOTA2亚洲邀请赛OpTic出场
2018/04/03 DOTA
[01:02:48]2018DOTA2亚洲邀请赛小组赛 A组加赛 Newbee vs Liquid
2018/04/03 DOTA
Python内置的字符串处理函数详细整理(覆盖日常所用)
2014/08/19 Python
Python模块结构与布局操作方法实例分析
2017/07/24 Python
Python3中条件控制、循环与函数的简易教程
2017/11/21 Python
Python中实现单例模式的n种方式和原理
2018/11/14 Python
Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据示例
2019/01/23 Python
python实现nao机器人手臂动作控制
2019/04/29 Python
python tkinter之顶层菜单、弹出菜单实例
2020/03/04 Python
python爬虫开发之使用Python爬虫库requests多线程抓取猫眼电影TOP100实例
2020/03/10 Python
django 前端页面如何实现显示前N条数据
2020/03/16 Python
Python带参数的装饰器运行原理解析
2020/06/09 Python
前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)
2018/07/12 HTML / CSS
八年级物理教学反思
2014/01/19 职场文书
服装行业创业计划书范文
2014/02/05 职场文书
城管执法人员纪律作风整顿思想汇报
2014/09/13 职场文书
党风廉政建设调研报告
2015/01/01 职场文书
学术研讨会主持词
2015/07/04 职场文书
小学数学新课改心得体会
2016/01/22 职场文书
解决go在函数退出后子协程的退出问题
2021/04/30 Golang