TensorFlow中的随机数 tf.random_uniform
TF中的随机数
Tensorflow中提供了若干算子来生成均匀分布、正态分布的随机数,或者实现随机排列、随机挑选等功能。
Operations |
Functions |
tf.random_normal |
Outputs random values from a normal distribution. 正态分布 |
tf.truncated_normal |
Outputs random values from a truncated normal distribution. 截断的正态分布,偏离大于2倍标准差的数会被丢弃再重新选择 |
tf.random_uniform |
Outputs random values from a uniform distribution. 均匀分布[min,max) |
tf.random_shuffle |
Randomly shuffles a tensor along its first dimension. 第一维随机排列 |
tf.multinomial |
Slices a portion out of input tensor at a uniformly chosen offset. 从输入数据value中随机剪切大小为size的部分数据 |
tf.random_gamma | Draws samples from each of the given Gamma distribution(s). 伽马分布 |
Tensorflow中也通过设置randomseed来产生不同的随机序列。需要注意的是,TF中有两种级别的random seed,一个是operation-level,一个是graph-level,都会影响随机数生成:
- op-level: 在调用上述表格中的算子时,可以显式指定seed参数,若seed参数相同,则在同一张graph里,每次运行生结果相同;若不指定seed参数,则每次使用随机的seed,运行结果不同。
- graph-level: 调用tf.set_random_seed来设置graph-level seed。如果设置了graph-level seed,即使不显式设置算子的seed参数,也可以在同一张graph里,每次生成相同的结果。
根据是否设置op-levelseed和graph-level seed,Tensorflow中有以下4种不同情况:
Set graph-level |
Set op-level |
Results |
√ |
√ |
A random seed is used for this op |
√ |
× |
The system deterministically picks an operation seed in conjunction with the graph-level seed so that it gets a unique random sequence. |
× |
√ |
A default graph-level seed and the specified operation seed are used to determine the random sequence. |
× |
× | Both seeds are used in conjunction to determine the random sequence. |
参考文献:
https://tensorflow.google.cn/api_guides/python/constant_op#Random_Tensors
https://tensorflow.google.cn/api_docs/python/tf/set_random_seed (这里有详细的代码示例)
tf.random_normal探究
以tf.random_uniform为例,再深入看一下。函数接口:
tf.random_uniform( shape, minval=0, maxval=None, dtype=tf.float32, seed=None, name=None )
在/tensorflow/python/ops/random_ops.py定义了random_uniform:
在\tensorflow\core\kernels\random_op.cc中定义了RandomUnifromIntOP:
在random_op.cc中还定义了FillPhiloxRandom:
在\tensorflow\core\lib\random\philox_random.h中定义PhiloxRandom(节选部分代码):
计算了10次ComputeSingleRound:
按论文设置的参数:
在每次ComputeSingleRound里计算低位、高位的乘法:
关于philox_4x32_10
Philox是一种伪随机数生成方法,来自2011年的论文《ParallelRandom Numbers: As Easy as 1, 2, 3》(https://pdfs.semanticscholar.org/38bc/7fc62136ec779d91b86b6e960a06d67b4a97.pdf)。TF代码中的参数设置也是来自这篇文章。
Philox_4x32_10是一种在GPU上速度比较快的方法,下图来自论文。
线性同余法
线性同余法(Linear congruentialgenerator,LCG)是目前应用广泛的伪随机数生成算法,其基本思想是通过对前一个数进行线性运算并取模从而得到下一个数。
线性同余法常用在编程语言函数库中产生随机数,但是不适用于加***的生成。因为当被攻击者获取到某些随机数之后,其种子seed以及A、C、M都会被反向计算出来,即有可能根据以往随机数预测出之后还未产生的随机数。
参考文献:
https://zh.wikipedia.org/wiki/%E7%B7%9A%E6%80%A7%E5%90%8C%E9%A4%98%E6%96%B9%E6%B3%95
https://blog.****.net/Apollon_krj/article/details/78718598
C/C++中的随机数实现
在stdlib.h中,rand()函数可以用来产生随机数,但这不是真正意义上的随机数,是一个伪随机数,是根据一个数(称为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数。
rand()的内部实现是用线性同余法做的,因其周期特别长,故在一定的范围里可看成是随机的。
实现方法:
1. 先调用srand函数,初始化随机数发生器,seed值相同则生成的随机数也相同。一般采用时间作为参数,每次运行的时间不同,产生的随机数也不同。
2. 再调用rand函数就可以生成随机数了。
1. #include <iostream> 2. #include "cstdlib" 3. /* 随机生成1~6之间的整数 */ 4. using namespace std; 5. int main() { 6. //基于当前日期与时间为随机生成器确定种子 7. srand(static_cast<unsigned int>(time(0))); 8. int randomNumber = rand();//rand()的返回值是随机数 9. int num = (randomNumber % 6) + 1; 10. cout << num << endl; 11. return 0; 12. } |
由于rand函数只能返回一定范围内的随机整数,存在很大的局限性。针对这些问题,C++ 11提供了新的随机数库:random-number engines、random-number distributionclasses,来生成不同范围内的随机整数和浮点数、随机分布等。
不过,生成随机数的原理还是相同的。