seed() 和torch中manual_seed的作用

描述

seed() 方法改变随机数生成器的种子,可以在调用其他随机模块函数之前调用此函数。


语法

以下是 seed() 方法的语法:

import random

random.seed ( [x] )

我们调用 random.random() 生成随机数时,每一次生成的数都是随机的。但是,当我们预先使用 random.seed(x) 设定好种子之后,其中的 x 可以是任意数字,如10,这个时候,先调用它的情况下,使用 random() 生成的随机数将会是同一个。

注意:seed()是不能直接访问的,需要导入 random 模块,然后通过 random 静态对象调用该方法。


参数

  • x -- 改变随机数生成器的种子 seed。如果你不了解其原理,你不必特别去设定 seed,Python会帮你选择 seed。

返回值

本函数没有返回值。


实例

以下展示了使用 seed() 方法的实例:

实例

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import random

print random.random()
print random.random()

print "------- 设置种子 seed -------"
random.seed( 10 )
print "Random number with seed 10 : ", random.random()

# 生成同一个随机数
random.seed( 10 )
print "Random number with seed 10 : ", random.random()

# 生成同一个随机数
random.seed( 10 )
print "Random number with seed 10 : ", random.random()

以上实例运行后输出结果为:

0.739880443211
0.78969784712
------- 设置种子 seed -------
Random number with seed 10 :  0.57140259469
Random number with seed 10 :  0.57140259469
Random number with seed 10 :  0.57140259469

torch中manual_seed的作用

torch.manual_seed(seed) – 官方文档说明:设置 (CPU) 生成随机数的种子,并返回一个torch.Generator对象。

设置种子的用意是一旦固定种子,后面依次生成的随机数其实都是固定的。

通过代码说明一下:

import torch

random_seed = 123
torch.manual_seed(random_seed)
print(torch.rand(1)) # 随机生成[0, 1)的数
print(torch.rand(1))

"""
Out:
tensor([0.2961])
tensor([0.5166])
"""

说明:上面手动设置完种子之后,调用了两次torch.rand这个API (随机生成[0, 1]的数),可以发现输出的是两个不同的随机数,不是说已经固定种子了吗?怎么还会生成不同的随机数?实际上,准确来说,手动设置种子之后导致的结果应该是:在每次重新运行上面的程序时,得到的打印结果都是上面两个数。

在每次重新运行程序时,同样的随机数生成代码得到的是同样的结果。
打个比方:设置好种子后,第一次运行程序时,第一个生成的随机数是A,第二个生成的随机数是B, 第三个生成的随机数是C,第四个生成的随机数是D。那么,不管第二次,第三次,还是第n次运行程序时,第一个生成的随机数仍然是A,第二个生成的随机数仍然是B, 第三个生成的随机数仍然是C,第四个生成的随机数仍然是D。

ps:手动设置种子一般可用于固定随机初始化的权重值,这样就可以让每次重新从头训练网络时的权重的初始值虽然是随机生成的但却是固定的。


同样的道理,也可以手动设置GPU的随机数生成种子:
torch.cuda.manual_seed(seed) – 设置当前GPU的随机数生成种子
torch.cuda.manual_seed_all(seed) – 设置所有GPU的随机数生成种子

深度学习中使用随机种子使得实验结果可复现

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

CUDNN

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

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

Python

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

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,深度学习,random,python)