⌚️: 2020年10月19日
📚参考
真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等,这样的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高。 ----百度百科
根据百科上的定义可以看到,真随机数是依赖于物理随机数生成器的。使用较多的就是电子元件中的噪音等较为高级、复杂的物理过程来生成。使用物理性随机数发生器生成的真随机数,可以说是完美再现了生活中的真正的“随机”,也可以称为绝对的公平。
真正意义上的随机数(或者随机事件)在某次产生过程中是按照实验过程中表现的分布概率随机产生的,其结果是不可预测的,是不可见的。而计算机中的随机函数是按照一定算法模拟产生的,其结果是确定的,是可见的。我们可以这样认为这个可预见的结果其出现的概率是100%。所以用计算机随机函数所产生的“随机数”并不随机,是伪随机数。 —百度百科
从定义我们可以了解到,伪随机数其实是有规律的。只不过这个规律周期比较长,但还是可以预测的。主要原因就是伪随机数是计算机使用算法模拟出来的,这个过程并不涉及到物理过程,所以自然不可能具有真随机数的特性。
for (int i = 0; i < 10; ++i)
{
cout<<rand()<<" ";
}
cout<<endl;
连续两次运行这个过程,结果是一样的。(程序简单,自行试验) 这就是伪随机数了!!!! 就好像是在系统中已经有了一个0~RAND_MAX的一个乱序序列,我们调用rand()的时候都是参照这个序列和随机种子的,这里没有设置随机种子,因此随机种子为1,当随机种子为x的时候,我们可以根据这个随机种子x来计算出一个随机数f(x, m),其中m为这个序列中的伪随机数。如果随机种子是固定的,那么每次调用rand()依然可以计算出来了。
由上面我们就知道了,所谓随机数其实是伪随机数,所谓的‘伪’,意思是这些数其实是有规律的,只不过因为算法规律太复杂,很难看出来而已。
但是,再厉害的算法,如果没有一个初始值,它也不可能凭空造出一系列随机数来,我们说的种子就是这个初始值。
random随机数是这样生成的:我们将这套复杂的算法(是叫随机数生成器吧)看成一个黑盒,把我们准备好的种子扔进去,它会返给你两个东西,一个是你想要的随机数,另一个是保证能生成下一个随机数的新的种子,把新的种子放进黑盒,又得到一个新的随机数和一个新的种子,从此在生成随机数的路上越走越远。
深度学习网络模型中初始的权值参数通常都是初始化成随机数, 而使用梯度下降法最终得到的局部最优解对于初始位置点的选择很敏感。为了能够完全复现作者的开源深度学习代码,随机种子的选择能够减少一定程度上算法结果的随机性,也就是更接近于原始作者的结果即产生随机种子意味着每次运行实验,产生的随机数都是相同的。
but 在大多数情况下,即使设定了随机种子,仍然没有办法完全复现paper中所给出的模型性能,这是因为深度学习代码中除了产生随机数中带有随机性,其训练的过程中使用 mini-batch SGD或者优化算法进行训练时,本身就带有了随机性。因为每次更新都是从训练数据集中随机采样出batch size个训练样本计算的平均梯度作为当前step对于网络权值的更新值,所以即使提供了原始代码和随机种子,想要复现作者paper中的性能也是非常困难的
# python
random.seed(1234)
# numpy
np.random.seed(1234)
# torch
torch.manual_seed(1234)
torch.cuda.manual_seed(1234)
torch.cuda.manual_seed_all(1234)
torch.backends.cudnn.benchmark = True
warnings.filterwarnings('ignore')