糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > python产生随机数种子_PyTorch固定随机数种子

python产生随机数种子_PyTorch固定随机数种子

时间:2023-01-08 16:00:32

相关推荐

python产生随机数种子_PyTorch固定随机数种子

1. 训练过程

在训练过程中,若相同的数据数据集,相同的训练集、测试集划分方式,相同的权重初始化,但是每次训练结果不同,可能有以下几个原因:

Dropout的存在 ;

PyTorch、Python、Numpy中的随机种子没有固定;

数据预处理、增强方式采用了概率,若没有设置固定的随机种子,结果可能不同。例如常用数据增强库albumentations就采用了Python的随机产生器;

训练数据集被随机打乱了顺序;

向上采样和插值函数/类的向后是不确定的(PyTorch的问题)

举个例子:

import numpy as np

def no_set_seed():

n = 0

while (n < 3):

n += 1

print(np.random.random())

def set_seed():

n = 0

while (n < 3):

np.random.seed(5)

n += 1

print(np.random.random())

if __name__=="__main__":

print(" ***** no set seed result ***** ")

no_set_seed()

print(" ***** set seed result ***** ")

set_seed()

输出:

***** no set seed result *****

0.7831834888867475

0.919347615336164

0.9437836768670717

***** set seed result *****

0.22199317108973948

0.22199317108973948

0.22199317108973948

当我们设定一个随机种子时,那么关于随机数的选取就确定了。

另外,在PyTorch官方文档中说明了在Pytorch的不同提交、不同版本和不同平台上,不能保证完全可重现的结果。此外,即使使用相同的种子,因为存在不同的CPU和GPU,结果也不能重现。

但是对于一个特定的平台和PyTorch发行版上对您的特定问题进行确定性的计算,需要采取几个步骤。在can’t reproduce results even set all random seeds给出了解决方式。

其中包括:

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

torch.backends.cudnn.deterministic = True

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

对PyTorch设置随机种子;

对Python & NumPy设置随机种子:如果读取数据的过程采用了随机预处理(如RandomCrop、RandomHorizontalFlip等),那么对python、numpy的随机数生成器也需要设置种子;

对dataloader设置随机种子:如果dataloader采用了多线程(num_workers > 1), 那么由于读取数据的顺序不同,最终运行结果也会有差异。也就是说,改变num_workers参数,也会对实验结果产生影响。目前暂时没有发现解决这个问题的方法,但是只要固定num_workers数目(线程数)不变,基本上也能够重复实验结果。对于不同线程的随机数种子设置,主要通过DataLoader的worker_init_fn参数来实现。默认情况下使用线程ID作为随机数种子。

参考can’t reproduce results even set all random seeds#7068(comment1),建议采用下面方式解决:在运行任何程序之前写入下面代码(可以放在主代码的开头,在导入模块之后):torch.manual_seed(seed) # 为CPU设置随机种子

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

torch.cuda.manual_seed_all(seed) # if you are using multi-GPU,为所有GPU设置随机种子

np.random.seed(seed) # Numpy module.

random.seed(seed) # Python random module.

torch.backends.cudnn.benchmark = False

torch.backends.cudnn.deterministic = True

将它封装一个函数,参考can’t reproduce results even set all random seeds#7068 (comment2),代码如下:def seed_torch(seed=1029):

random.seed(seed)

os.environ['PYTHONHASHSEED'] = str(seed) # 为了禁止hash随机化,使得实验可复现

np.random.seed(seed)

torch.manual_seed(seed)

torch.cuda.manual_seed(seed)

torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.

torch.backends.cudnn.benchmark = False

torch.backends.cudnn.deterministic = True

seed_torch()

在PyTorch的DataLoader函数中填入为不同的work设置初始化函数,确保您的dataloader在每次调用时都以相同的顺序加载样本(随机种子固定时)。如果进行裁剪或其他预处理步骤,请确保它们是确定性的。(这样的模块可以提供确定性结果(在Pytorch 1.0.0甚至在此版本之前))def _init_fn(worker_id):

np.random.seed(int(seed)+worker_id)

trainloader = DataLoader(trainset, batch_size=batch_size, shuffle=True, num_workers=num_workers, pin_memory=True, worker_init_fn=_init_fn)

当 向上采样和插值函数/类的向后是不确定的(BACKWARD of upsampling and interpolation functionals/classes is non-deterministic)。这意味着,如果你在训练图中使用这样的模块,无论你做什么,都永远不会得到确定性的结果。torch.nn.ConvTranspose2d函数是不确定的,除非你使用torch.backends.cudnn.deterministic = True(原文中说you can try to make the operation deterministic … by setting torch.backends.cudnn.deterministic = True,所以这样做是否能够得到正确结果也是待定的)。

2. 测试过程

在测试过程中,相同的权重,相同的测试数据集,结果不同,可能有以下几个原因:

未设定eval()模式,因为模型中的Dropout和Batchnorm存在,导致结果不固定;

PyTorch、Python、Numpy中的随机种子没有固定,可能运行时依赖的一些第三方库;

有随机性 数据预处理方式中含有概率;

向上采样和插值函数/类的向后是不确定的(Pytorch的问题)

随机种子的设定和训练中的设置类似,可参考第一节内容。

3. 代码随机种子的设定

有的时候,不同的随机种子对应的神经网络结果不同,我们并不想固定随机种子,使其能够搜索最优结果。但是又想能够根据复现最优结果,所以我们需要每次运行代码都根据当前时间设定不同的随机种子,并将随机种子保存下来。

可以使用下面代码产生随机种子,用于固定Pytorch、Python、Numpy中的随机种子,你可以将这个值保存到特定的文件中,用于之后使用。

seed = int(time.time() * 256)

4. 参考链接

原文链接:/john_bh/article/details/107731443

如果觉得《python产生随机数种子_PyTorch固定随机数种子》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。