问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

Seed Everything - 可复现的 PyTorch(一)

发布网友 发布时间:2024-10-02 03:59

我来回答

1个回答

热心网友 时间:2024-10-11 01:28

为了保证实验的可复现性,许多机器学习的代码都会有一个方法叫seed everything,这个方法尝试固定随机种子以让一些随机的过程在每一次的运行中产生相同的结果。

什么是随机种子?随机数,分为真随机数和伪随机数,真随机数需要自然界中真实的随机物理现象才能产生,而对于计算机来说生成这种随机数是很难办到的。而伪随机数是通过一个初始化的值,来计算来产生一个随机序列,如果初始值是不变的,那么多次从该种子产生的随机序列也是相同的。这个初始值一般就称为种子。

Linux系统中的随机数,在Ubuntu系统中,有一个专门管理随机种子的服务systemd-random-seed.service,该服务负责在计算机启动的时候,从硬盘上加载一个随机种子文件到内核中,以作为随机初始化值在整个系统运行的过程中提供服务。Linux会通过许多硬件信息来获得这个初始化值。可以通过/dev/urandom文件来产生随机字节,然后使用od命令(该命令可将字节转换成希望的格式并打印)来获得随机数:

如果仅希望获得随机数,直接读取/dev/urandom或调用Linux系统调用getrandom()(内部也使用/dev/urandom)是不错的选择。但这种随机数是无法复现的,因为种子是由系统设置的,并且每次开机设置的种子都不一样。在“可复现”的场景中,我们需要的是一种能手动控制随机种子和读取随机序列的方式,以便可以重复获得相同随机序列的功能。

如果一个过程依赖系统产生的随机数,则称这个过程是Non Deterministic(不确定的);相反的如果一个过程对相同的输入种子都有相同的输出,则这个随机过程是Deterministic的。在“可复现”场景中,我们需要保证所有的随机过程都是Deterministic的。

/dev/random可生成“随机性”更强的随机数,但由于其依赖的系统资源更多,导致性能缓慢,因此绝大多数场景都只使用/dev/urandom。

程序中的随机数,在PyTorch中,设置随机种子的方法是torch.manual_seed(777),这里777就是我们所设置的随机种子,设置完毕后,如果多次调用同样的具有随机过程PyTorch方法,就会获得相同的结果,例如下面的代码在多次调用后的打印是一样的:

不论在任何机器或系统,只要使用torch==1.10.0版本(其他版本大概率也是OK的),输出应该都是长这样的。诶?既然随机种子产生跟系统硬件信息相关,那不同的机器至少应该不一样才对呀?上文说了,在要求“可复现”的场景下,是不能使用/dev/urandom来产生随机数的,那剩下的是需要搞清楚PyTorch是如何生成随机数的。

通过torch.manual_seed方法往下找,可以知道PyTorch生成随机数是使用了MT19937(梅森旋转)算法,这个算法的输入只有一个初始化值也不需要其他的环境信息。因此无论在任何机器,只要PyTorch的版本一致(算法部分没有改变)并且设置了随机种子,那么调用随机过程所产生的随机数就是一致的。C++ 11在标准库中直接引入了这个方法:std::mt19937,而PyTorch是自己实现的,官方称性能比C++的版本要更好一些,感兴趣的话可以直接看PyTorch源码。

NumPy的np.random.seed也同样使用MT19937来生成随机数,因此也与硬件无关。要注意的是:np.random.seed只影响NumPy的随机过程,torch.manual_seed也只影响PyTorch的随机过程。通过下面的代码很容易验证这个结果:

由此可以得到这样的程序中所有依赖MT19937算法产生随机数的包,都需要手动设置随机种子,才能使整个程序的随机性是可复现的。

“根据文档,设置torch.manual_seed是对所有的设备设置随机种子。目前似乎没有单独为CPU设备设置随机种子的方法。”

CUDA的随机数,PyTorch中,还有另一个设置随机种子的方法:torch.cuda.manual_seed_all,从名字可知这是设置显卡的随机种子。

在PyTorch的内部,使用CUDA Runtime API提供的curand来设置随机种子,根据curand的文档,他们提供的所有随机数生成算法都是Deterministic的。

上面的代码看起来不够“随机”,因为在不同的GPU设备上产生了相同的结果,如果希望不同设备可以产生不同的随机数,可以这么做:

上面的代码既保证了随机性(不同设备产生不同的随机数),也保证了确定性(多次调用只产生相同结果)。在真实场景中,一般只会用相同的设备来产生随机数,因此torch.manual_seed(777)应该就能满足大多数需求。

不同设备之间的随机数,先问一个问题:“用GPU训练的实验结果,可以在CPU上复现吗?”。

答案是“也许可以”。

根据前文可知,CPU设置随机种子是用PyTorch官方实现的MT19937,而GPU是用到了CUDA Runtime API的curand。因此两套实现是完全不同的,那么对于相同的随机种子,理应产生不同的随机序列,用下面的代码可以验证:

从上面的例子中知道,对于同一个随机种子,在CPU和GPU上产出的结果是不同的,因此这种情况在GPU上的结果是无法在CPU上复现的。那为什么答案是“也许可以”呢?

因为很多代码,都会在CPU上创建Tensor,再切换到GPU上。只要不直接在GPU上创建随机变量,就可以避免这个问题。请看下面的例子:

上面的代码输出值跟CPU一致,但是device是在CUDA上。这样写可能性能不如直接在GPU上直接创建随机变量,但为了保证程序的确定性,牺牲一点性能我认为是值得的。

多进程的随机性,PyTorch的torch.utils.data.DataLoader在num_worker>0的情况下会fork出子进程,而通常又会在加载数据的时候做很多“随机变换”,那么就有必要讨论一下多进程下的随机性是怎样的,

子进程一般会保留父进程的一些状态,这也包括随机种子。因此若不做特殊处理,所有子进程都会产生和父进程相同的随机序列。请看下面的例子:

可以发现两次batch输出的结果是一样的,这是因为主进程中numpy的随机性,被两个worker保留了,因此两个worker的随机性是相同的。

“上面的结果在torch>=1.9.0是不能复现的,因为PyTorch 1.9之后DataLoader默认会给每个worker重新设置随机种子。”

这里我们需要为每一个worker设置不同的随机种子以保证随机性,但每次运行又必须要设置相同的随机种子来保证确定性,更好的代码实现如下:

这段代码将主进程的随机种子设置为777,两个worker分别设置为778和779。因为每次运行随机种子的值是一样的,因此可以保证确定性,另外每一个worker包括主进程的随机种子都不一样,因此随机性也保证了。

类似的,对于分布式训练,也需要做类似的操作,这里考虑单机多卡的情况:

假设有两个GPU进行训练,那么第一个GPU的主进程和两个worker进程的seed为:777,778,779;第二块GPU是:1777,1778,1779。

Seed Everything,最后点题,祭出一个seed_everything:
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
5数字寓意是什么意思 如何在 iPhone14上恢复已删除的照片? 红井源 醇香胡麻油 2.5L-购买最佳价格 python如何实现修改当前文件夹下所有文件名称? python遍历输出所有文件 用Python遍历指定文件夹下所有文件 Python:读取指定路径下的文件,含子文件夹,可指定文件类型 谁有治疗网瘾的好方法? 孩子有网瘾又叛逆怎么办 退伍证名字错了怎么办 tfrecord和tfrecorder 学习Pytorch过程遇到的坑(持续更新中) 浅析pytorch的数据并行 Deepspeed详解与训练使用(单机单卡,单机多卡) 一文读懂GPU通信互联技术 pytorch的单卡训练和单机多卡分布式训练的结果会一致吗? 政治领悟力是什么 考察识别干部特别是高级干部必须首先看是否坚定不移贯彻( )。_百度知... 考察识别干部特别是高级干部必须首先看是否 如何在win10中更改默认浏览器为其他应用? 如何解除电脑默认浏览器? 如何将电脑默认浏览器设置为谷歌浏览器? 如何设置默认浏览器为其它浏览器? 怎样才能睡眠好入睡快(有什么办法能让自己快速入睡) 怎样才能安然入睡? pps曾经推荐过一部电视剧 美国拍的励志型 以零八年奥运冠军肖恩为原型... 公会开荒太阳井,团队中2FQ,1ZS基本毕业。治疗俩牧师,三个小德,一洒满... 下周二准备跟团去太阳井,请问作为一个新手法师有什么要注意的? 绝地求生延迟高/卡顿的解决办法 在Ubuntu上升级CUDA Toolkit 大模型分布式训练并行技术(八)-MOE并行 陕西小吃麦饭有什么烹饪方法? 间尺に合わない 如何幽默地回复女生不回微信? ...L, XL, XXL, XXXL ,加大XXXL ,均码 *分别是指多少啊? 从广州出发 自驾车 至 珠海航展 路线图 怎么和孩子进行有效的沟通? 怎么样和小孩子进行有效的沟通交流? 三国演义中曹操姓什么? 三国曹操姓什么 怎样把受保护的网页内容复制下来? 无法复制文字要怎样才能复制下来啊?急,谢谢各位了 一次性吃30克阿胶会过量或引起不适吗? 经常吃阿胶吃多了会不会有副作用啊??? 三亚市主要旅游景点介绍图三亚主要景点游览路线图 深圳能源REIT下滑25.66%,能源四剑客折戟 中国建投股票 喜欢一个人宅在家极度讨厌外人打扰我这是一种病吗? 蛞蝓为什么叫鼻涕虫? 短暂性脑缺血是脑梗吗