【Python学习笔记】深入剖析随机数种子

一、定义

  • 随机数就是就随机数种子中取出的数。种子就是个序号,这个序号交给一个数列管理器,通过这个序号,你从管理器中取出一个数列,这个数列就是你通过那个序号得到的随机数。
  • 但这个随技术并不真正随机,而是“伪”随机数。因为它是通过某个算法的得到。也就是说你给数列管理器同一个序号将得到同样一个“随机”数列,也就是说种子和随机数列是一一对应的。
  • {An}=f(x), x 就是种子,F()是算法,{An}是数列,这个数列看上去是随机的,这是因为An的通项很复杂。
  • 换句话说,只要计算方法一定,随机种子一定,那么产生的随机数就不会变。
  • 我们可以把上述的数列管理器看成是一个随机数生成器,也可以堪称是一个黑盒。一般来说,算法构造出一系列随机数是需要初始值的,而我们说的种子就是这个初始值。
  • 只要用户不设置随机种子,那么在默认情况下随机种子来自系统时钟(即定时/计数器的值)。

1.1 作用

  • 深度学习网络模型中初始的权值参数通常都是初始化成随机数
  • 而使用梯度下降法最终得到的局部最优解对于初始位置点的选择很敏感
  • 为了能够完全复现作者的开源深度学习代码,随机种子的选择能够减少一定程度上算法结果的随机性,也就是更接近于原始作者的结果
  • 即产生随机种子意味着每次运行实验,产生的随机数都是相同的

但是

  • 在大多数情况下,即使设定了随机种子,仍然没有办法完全复现paper中所给出的模型性能,这是因为深度学习代码中除了产生随机数中带有随机性,其训练的过程中使用 mini-batch SGD或者优化算法进行训练时,本身就带有了随机性。
  • 因为每次更新都是从训练数据集中随机采样出batch size个训练样本计算的平均梯度作为当前step对于网络权值的更新值,所以即使提供了原始代码和随机种子,因此想要复现作者paper中的性能也是非常困难的!!

二、实战

2.1 同样的随机数种子

import numpy as np
import random

np.random.seed(0) # 设定种子为0
print(np.random.rand(1)) # 生成1个随机数
# 输出 [0.5488135]

np.random.seed(0) # 设定种子为0
print(np.random.rand(2)) # 生成2个随机数
# 输出 [0.5488135  0.71518937]

np.random.seed(0) # 设定种子为0
print(np.random.rand(3)) # 生成3个随机数
# 输出 [0.5488135  0.71518937 0.60276338]

np.random.seed(0) # 设定种子为0
print(np.random.rand(4)) # 生成4个随机数
# 输出 [0.5488135  0.71518937 0.60276338 0.54488318]

np.random.seed(0) # 设定种子为0
print(np.random.rand(5)) # 生成5个随机数
# 输出 [0.5488135  0.71518937 0.60276338 0.54488318 0.4236548 ]

np.random.seed(0) # 设定种子为0
print(np.random.rand(6)) # 生成6个随机数
# 输出 [0.5488135  0.71518937 0.60276338 0.54488318 0.4236548  0.64589411]

# 上述运行结果验证了定义里面所说的:只要随机数种子是一样的,那么我们从随机数列中同一个位置里面取到的随机数是一样的!!

2.2 不同的随机数种子

np.random.seed(1) # 设定种子为1
print(np.random.rand(6)) # 生成6个随机数
[4.17022005e-01 7.20324493e-01 1.14374817e-04 3.02332573e-01
 1.46755891e-01 9.23385948e-02]

2.3 不指定随机数种子

  • 系统使用当前的时钟作为随机数种子!
print(np.random.rand(6)) # 生成6个随机数
[0.18626021 0.34556073 0.39676747 0.53881673 0.41919451 0.6852195 ]

三、随机数列的大小是多少呢?

  • 出于好奇,个人想探索一个随机数种子最大能生成几个随机数呢?于是我做了下列实验来探索随机数列的上限。
  • 下面的结果中的省略号是因为随机数过多不便于展示,于是使用了省略号!!
  • 下面句式使用同一个随机数种子生成的,所以生成的随机数列是同一个,这一点从前面几个随机数中可以看出!!!

3.1 设定为百万,没问题

np.random.seed(0) # 设定种子为0
print(np.random.rand(1000000)) # 生成百万个随机数
# 输出为[0.5488135  0.71518937 0.60276338 ... 0.36259133 0.51650652 0.90860588]

3.2 设定为千万,没问题

np.random.seed(0) # 设定种子为0
print(np.random.rand(10000000)) # 生成千万个随机数
# 输出为[0.5488135  0.71518937 0.60276338 ... 0.7016828  0.45616281 0.14553608]

3.3 设定为亿,没问题

np.random.seed(0) # 设定种子为0
print(np.random.rand(100000000)) # 生成一亿个随机数
# 输出为[0.5488135  0.71518937 0.60276338 ... 0.08870192 0.45256207 0.17769845]

3.4 设定为十亿,没问题

np.random.seed(0) # 设定种子为0
print(np.random.rand(1000000000)) # 生成十亿个随机数
# 输出为[0.5488135  0.71518937 0.60276338 ... 0.50437869 0.82084559 0.15720507]

3.5 设定为百亿,内存不够!!

np.random.seed(0) # 设定种子为0
print(np.random.rand(10000000000)) # 生成百亿个随机数

# 出错!!!!!
Traceback (most recent call last):
  File "<input>", line 2, in <module>
  File "mtrand.pyx", line 1154, in numpy.random.mtrand.RandomState.rand
  File "mtrand.pyx", line 420, in numpy.random.mtrand.RandomState.random_sample
  File "_common.pyx", line 256, in numpy.random._common.double_fill
MemoryError: Unable to allocate 74.5 GiB for an array with shape (10000000000,) and data type float64

3.6 设定为一万亿,内存更加不够!!!

np.random.seed(0) # 设定种子为0
print(np.random.rand(1000000000000)) # 生成一万亿个随机数

# 出错!!!!!
Traceback (most recent call last):
  File "<input>", line 2, in <module>
  File "mtrand.pyx", line 1154, in numpy.random.mtrand.RandomState.rand
  File "mtrand.pyx", line 420, in numpy.random.mtrand.RandomState.random_sample
  File "_common.pyx", line 256, in numpy.random._common.double_fill
MemoryError: Unable to allocate 7.28 TiB for an array with shape (1000000000000,) and data type float64

# 结果是内存不够!!

3.7 换了内存为64G的工作站,设定为一万亿,内存还是不够!!!在这里插入图片描述

在这里插入图片描述

  • 降低为百亿还是不行,看来目前是没机会亲自探索出生成的随机数列的大小了!

四、random模块中的随机数种子

  • random是python中用于产生随机数的模块.
  • 随机数生成的原理还是一样的

4.1 示例

import random
random.seed(0)
print(random.random())
# 输出为 0.8444218515250481

random.seed(0)
print(random.random())
# 输出为 0.8444218515250481

4.2 random模块与 numpy.random的对比

  • 虽然使用了同样的随机数种子,但是二者生成的随机数是不一样的!!!
  • 因此二者还是有区别的。
  • random模块生成的随机浮点数的长度貌似比numpy.random的更长;
  • Python标准库的random模块处理的对象类型更宽泛一些,并不局限于数(int,float等),还可以是字符串等类型。
  • 而numpy.random则专门用于处理数学数据,所以传入的为array,这与NumPy库本身的初衷也很一致。
random.seed(0)
print(random.random())
# 输出为 0.8444218515250481
import numpy as np

np.random.seed(0)
print(np.random.rand())
# 输出为 0.5488135039273248
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值