1、随机数
在百度百科中对随机数的定义为:
真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等,这样的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高。
根据定义可以看到,真随机数是依赖于物理随机数生成器的。使用较多的就是电子元件中的噪音等较为高级、复杂的物理过程来生成。使用物理性随机数发生器生成的真随机数,可以说是完美再现了生活中的真正的“随机”,也可以称为绝对的公平。
2、伪随机数
在百度百科中对伪随机数的定义为:
真正意义上的随机数(或者随机事件)在某次产生过程中是按照实验过程中表现的分布概率随机产生的,其结果是不可预测的,是不可见的。而计算机中的随机函数是按照一定算法模拟产生的,其结果是确定的,是可见的。我们可以这样认为这个可预见的结果其出现的概率是100%。所以用计算机随机函数所产生的“随机数”并不随机,是伪随机数。
从定义我们可以了解到,伪随机数其实是有规律的。只不过这个规律周期比较长,但还是可以预测的。主要原因就是伪随机数是计算机使用算法模拟出来的,这个过程并不涉及到物理过程,所以自然不可能具有真随机数的特性。
3、随机种子
计算机中产生的随机数是伪随机数,所谓的‘伪’,意思是这些数其实是有规律的,只不过因为算法规律太复杂,很难看出来而已。但是,再厉害的算法,如果没有一个初始值,它也不可能凭空造出一系列随机数来,我们说的种子就是这个初始值。
random随机数是这样生成的:我们将这套复杂的算法(是叫随机数生成器吧)看成一个黑盒,把我们准备好的种子扔进去,它会返给你两个东西,一个是你想要的随机数,另一个是保证能生成下一个随机数的新的种子,把新的种子放进黑盒,又得到一个新的随机数和一个新的种子,从此在生成随机数的路上越走越远。
而在使用numpy时,就会运用到随机种子,其代码模板为
import random
random.seed(10)
print(random.random())
在有的博客的理解的困惑
(1)利用随机种子后,每次生成的随机数相同。这是什么意思?
(2)随机数种子的参数怎么选择?在别人的代码中经常看到np.random.seed(Argument),这个参数不一样,有的是0,有的是1,当然还有其他数。那这个参数应该怎么选择呢?
通过 以下代码做实验:
import numpy as np
if __name__ == '__main__':i = 0while (i < 6):if (i < 3):np.random.seed(0)print(np.random.randn(1, 5))else:print(np.random.randn(1, 5))passi += 1i = 0while (i < 2):print(np.random.randn(1, 5))i += 1print(np.random.randn(2, 5))np.random.seed(0)i = 0while (i <8):print(np.random.randn(1, 5))i += 1
运行结果为:
# 第一个while循环中的i <3
[[1.76405235 0.40015721 0.97873798 2.2408932 1.86755799]]
[[1.76405235 0.40015721 0.97873798 2.2408932 1.86755799]]
[[1.76405235 0.40015721 0.97873798 2.2408932 1.86755799]]
# 第一个while循环中的i > 3
[[-0.97727788 0.95008842 -0.15135721 -0.10321885 0.4105985 ]]
[[0.14404357 1.45427351 0.76103773 0.12167502 0.44386323]]
[[ 0.33367433 1.49407907 -0.20515826 0.3130677 -0.85409574]]
# 第二个while循环
[[-2.55298982 0.6536186 0.8644362 -0.74216502 2.26975462]]
[[-1.45436567 0.04575852 -0.18718385 1.53277921 1.46935877]]
# 单独打印的(2,5)数组
[[ 0.15494743 0.37816252 -0.88778575 -1.98079647 -0.34791215][ 0.15634897 1.23029068 1.20237985 -0.38732682 -0.30230275]]# 最后一个while
[[1.76405235 0.40015721 0.97873798 2.2408932 1.86755799]]
[[-0.97727788 0.95008842 -0.15135721 -0.10321885 0.4105985 ]]
[[0.14404357 1.45427351 0.76103773 0.12167502 0.44386323]]
[[ 0.33367433 1.49407907 -0.20515826 0.3130677 -0.85409574]]
[[-2.55298982 0.6536186 0.8644362 -0.74216502 2.26975462]]
[[-1.45436567 0.04575852 -0.18718385 1.53277921 1.46935877]]
[[ 0.15494743 0.37816252 -0.88778575 -1.98079647 -0.34791215]]
[[ 0.15634897 1.23029068 1.20237985 -0.38732682 -0.30230275]]
通过该实验我们可以得到以下结论:
a:两次利用随机数种子后,即便是跳出循环后,生成随机数的结果依然是相同的。第一次跳出while循环后,进入第二个while循环,得到的两个随机数组确实和加了随机数种子不一样。但是,后面的加了随机数种子的,八次循环中的结果和前面的结果是一样的。说明,随机数种子对后面的结果一直有影响。同时,加了随机数种子以后,后面的随机数组都是按一定的顺序生成的。
b:在同样的随机种子后第六次的随机数生成结果,两行五列的数组和两个一行五列的数组结果相同。说明,在生成多行随机数组时,是由单行随机数组组合而成的。
现在我们回答了第一个疑惑:利用随机数种子,每次生成的随机数相同。这是什么意思? --就是使后面的随机数按一定的顺序生成。
你可以实验,在你的电脑上,当随机数种子参数为0和1时,生成的随机数和我上面高亮的结果相同。说明该参数指定了一个随机数生成的起始位置。每个参数对应一个位置。并且在该参数确定后,其后面的随机数的生成顺序也就确定了。
所以,现在我们回答了我的第二个疑问:随机数种子的参数怎么选择?我认为随意,这个参数只是确定一下随机数的起始位置。
4、深度学习中的随机种子
深度学习网络模型中初始的权值参数通常都是初始化成随机数,而使用梯度下降法最终得到的局部最优解对于初始位置点的选择很敏感。为了能够完全复现作者的开源深度学习代码,随机种子的选择能够减少一定程度上算法结果的随机性,也就是更接近于原始作者的结果
即产生随机种子意味着每次运行实验,产生的随机数都是相同的。但是在大多数情况下,即使设定了随机种子,仍然没有办法完全复现作者paper中所给出的模型性能,这是因为深度学习代码中除了产生随机数中带有随机性,其训练的过程中使用 mini-batch SGD或者优化算法进行训练时,本身就带有了随机性。因为每次更新都是从训练数据集中随机采样出batch size个训练样本计算的平均梯度,作为当前step对于网络权值的更新值,所以即使提供了原始代码和随机种子,想要
复现作者paper中的性能也是非常困难的。
参考链接:
参考链接1
参考链接2