合成法生成随机数原理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了合成法生成随机数原理相关的知识,希望对你有一定的参考价值。

参考技术A 随机数产生原理 原创
2017-06-30 18:15:46
 8点赞

大作家佚名 

码龄13年

关注
引言
利用数学的方法产生随机数的优点具有速度快、可对模拟问题进行复算检查、具有较好的统计特性。通过检验符合均匀性、随机性、独立性就可以当作真正的随机数。

随机数
经典的随机数产生方法为是线性同余法,即Linear Congruence Generator (LCG),由Lehmer于1951年提出。
同余:对于两个整数A、BA、B,如果它们同时除以一个自然数M的余数相同,就说A、BA、B对于模M同余,A≡BmodMA≡BmodM。

线性同余法
线性同余发生器是用不连续分段线性方程计算产生伪随机数序列的算法。LCG背后的理论比较容易理解,易于实现。由于计算机产生的随机数都是伪随机数,后面就直接用随机数代替伪随机数的叫法。

LCG定义如下:

Xn+1=(aXn+c)modm
Xn+1=(aXn+c)modm

其中,
XX是随机数序列
m,0<mm,0<m,模
a,0<a<ma,0<a<m,乘子
c,0≤c<mc,0≤c<m,增量,也叫做偏移量
X0,0≤X0<mX0,0≤X0<m,开始值,通常叫做“种子”seed
生成器不断往复运行,将会产生一序列<script type="math/tex" id="MathJax-Element-10"> a,c,ma,c,m取值合适,序列最大周期将达到 mm。这种情况下,序列中所有可能的整数都在某点固定出现。当c=0c=0时候,LCG就变换成了乘法同余发生器,multiplicative congruential generator (MCG), c≠0c≠0时叫做混合同余发生器,mixed congruential generator,MCG。

这里就用Wiki中的列子说明LCG是如何工作的:


当m=9,a=2,c=0,seed=1m=9,a=2,c=0,seed=1时,得:
X0=seed=1X0=seed=1
X2=(a∗X1+c)modm=(2×1+0)%9=2X2=(a∗X1+c)modm=(2×1+0)%9=2
X3=(a∗X2+c)modm=(2×2+0)%9=4X3=(a∗X2+c)modm=(2×2+0)%9=4
X4=(a∗X3+c)modm=(2×4+0)%9=8X4=(a∗X3+c)modm=(2×4+0)%9=8
X5=(a∗X4+c)modm=(2×8+0)%9=7X5=(a∗X4+c)modm=(2×8+0)%9=7
X6=(a∗X5+c)modm=(2×7+0)%9=5X6=(a∗X5+c)modm=(2×7+0)%9=5
X7=(a∗X6+c)modm=(2×5+0)%9=1X7=(a∗X6+c)modm=(2×5+0)%9=1
一个周期结束,如果再继续的话,随机序列将会以周期6重复出现。改变a,c,ma,c,m的值,LCG的周期性也发生了变换。

混合同余发生器 (MCG) 周期长度
通常MCG最大周期位mm,往往由于a,c,ma,c,m的选择使得周期无法达到mm。若想获得最大周期的随机数序列,需要同时满足下述条件:

m和c互质m和c互质。互质整数:公约数只有1的两个整数,如:7,5
a−1可以被ma−1可以被m的所有素因子整除
如果m被4整除,a−1也被4整除如果m被4整除,a−1也被4整除
这三个条件被称为Hull-Dobell定理,虽然LCG能够产生可以通过随机性的正式测试的伪随机数,但对参数c,m和ac,m和a的选择非常敏感。

使用LCG可能出现的问题
历史上,糟糕的因子选择导致了LCG的实施效率低下。在连续调用时,也无法避免序列的相关性。如果我们要自己设计LCG,选择不合适的a,c,ma,c,m往往带来糟糕的结果,却不自知。
历史上有这样的例子RANDU,其中,a=65539,m=231a=65539,m=231,在IBM大型机上使用了许多年,并被广泛应用在其他系统上,现在出现了很多问题,由于使用了糟糕的因子。

ANSI C库中的LCG
ANSI C库中的LCG实现具有一定的缺陷,其中一定数量的实施方法不能很好的工作,这个责任应该由ANSI C委员会及其实施者承担。——“Numerical Recipes”。该评判有明确出处,非笔者臆断!
由ANSI C标准规定rand()返回一个整数值,RAND_MAX通常不是很大。ANSI C标准要求RAND_MAX最大32767。
打开头文件stdlib.h,可以看到定义的十六进制RAND_MAX,使用博客的方法转换为十进制为32767。

/* Maximum value that can be returned by the rand function. */

#define RAND_MAX 0x7fff
1
2
3
1
2
3
ANSI C定义的LCG
打开rand.h头文件查看随机数生成器代码,产生随机数的过程即线性同余法,代码简单、结构清楚清楚。

/***
*rand.c - random number generator
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines rand(), srand() - random number generator
*
*******************************************************************************/

#include <cruntime.h>
#include <mtdll.h>
#include <stddef.h>
#include <stdlib.h>

/***
*void srand(seed) - seed the random number generator
*
*Purpose:
* Seeds the random number generator with the int given. Adapted from the
* BASIC random number generator.
*
*Entry:
* unsigned seed - seed to seed rand # generator with
*
*Exit:
* None.
*
*Exceptions:
*
*******************************************************************************/

void __cdecl srand (
unsigned int seed
)

_getptd()->_holdrand = (unsigned long)seed;


/***
*int rand() - returns a random number
*
*Purpose:
* returns a pseudo-random number 0 through 32767.
*
*Entry:
* None.
*
*Exit:
* Returns a pseudo-random number 0 through 32767.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl rand (
void
)

_ptiddata ptd = _getptd();

return( ((ptd->_holdrand = ptd->_holdrand * 214013L
+ 2531011L) >> 16) & 0x7fff );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
调用方式:

#include <iostream>
#include <random>
#include <time.h>
using namespace std;

void main()

//srand((unsigned)time(NULL));

srand(11);
for (int i = 0; i < 10; i++)
cout << rand() << '\t';
cout << endl;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
均匀分布随机数
均匀分布随机数即等概率随机数,如:扔骰子、掷硬币。使用《数值方法》中的LCG生成服从[0,1][0,1]分布的均匀分布。

#include <iostream>

#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)

float ran1(long *idum)

int j;
long k;
static long iy = 0;
static long iv[NTAB];
float temp;
if (*idum <= 0 || !iy)
if (-(*idum) < 1)
*idum = 1;
else
*idum = -(*idum);
for (j = NTAB + 7; j >= 0; j--)
k = (*idum) / IQ;
*idum = IA*(*idum - k*IQ) - IR*k;
if (*idum < 0)
*idum += IM;
if (j < NTAB)
iv[j] = *idum;

iy = iv[0];

k = (*idum) / IQ;
*idum = IA*(*idum - k*IQ) - IR*k;
if(*idum < 0)
*idum += IM;
j = iy / NDIV;
iy = iv[j];
iv[j] = *idum;
if ((temp = AM*iy) > RNMX)
return RNMX;
else
return temp;


void main()

float ran1(long *idum);

long seed = 10;
for (int i = 0; i < 10;++i)

std::cout << ran1(&seed) << std::endl;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
标准正态分布随机数
现实生活中更多的随机现象是服从正态分布的,如:20岁的成年人体重分布。正太分布随机数可以通过Box-Muller方法从均匀分布随机数转换为标准正态分布随机数。下面代码是《数值方法》中完整代码。

#include <iostream>
#include <math.h>

#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)

float ran1(long *idum)

int j;
long k;
static long iy = 0;
static long iv[NTAB];
float temp;
if (*idum <= 0 || !iy)
if (-(*idum) < 1)
*idum = 1;
else
*idum = -(*idum);
for (j = NTAB + 7; j >= 0; j--)
k = (*idum) / IQ;
*idum = IA*(*idum - k*IQ) - IR*k;
if (*idum < 0)
*idum += IM;
if (j < NTAB)
iv[j] = *idum;

iy = iv[0];

k = (*idum) / IQ;
*idum = IA*(*idum - k*IQ) - IR*k;
if(*idum < 0)
*idum += IM;
j = iy / NDIV;
iy = iv[j];
iv[j] = *idum;
if ((temp = AM*iy) > RNMX)
return RNMX;
else
return temp;


float gasdev(long *idum)
float ran1(long *idum);
static int iset = 0;
static float gset;
float fac, rsq, v1, v2;
if (*idum < 0)
iset = 0;
if (iset == 0)
do
v1 = 2.0*ran1(idum) - 1.0;
v2 = 2.0*ran1(idum) - 1.0;
rsq = v1*v1 + v2*v2;
while (rsq >= 1.0 || rsq == 0.0);
fac = sqrt(-2.0*log(rsq) / rsq);
gset = v1*fac;
iset = 1;
return v2*fac;

else
iset = 0;
return gset;



void main()

float ran1(long *idum);

long seed = 10;
for (int i = 0; i < 10;++i)

std::cout << gasdev(&seed) << std::endl;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
总结
这里详细叙述了LCG生成均匀分布随机数的方法,分析了获得最大周期的条件。随机序列具体服从的分布,可以通过卡方检验得到。由于ANSI C中的LCG随机数的缺陷,vs下编程不建议使用系统自带的随机数生成器。如果只是单独的使用LCG产生随机数,也不建议自己实现LCG(即使实现过程很简单)。最后建议使用《数值方法》中的LCG随机数生成器。

参考

https://en.wikipedia.org/wiki/Linear_congruential_generator
https://en.wikipedia.org/wiki/RANDU
http://baike.baidu.com/link?url=0_DsXFh4U0_s5s9mUrrEAwuW_y1ol3a473KOb8eGxNwUH7C5g_97Pc825aX2bOFqUjDYl-rM_Su-rdiDncwG_dwRyxmjjENIvlmEpyXEZJm
Press, W. H. (2007). Numerical recipes 3rd edition: The art of scientific computing. Cambridge university press.
https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
http://www.cnblogs.com/zztt/p/4025207.html
http://www.cnblogs.com/afarmer/archive/2011/05/01/2033715.html

随机森林原理与Sklearn参数详解

参考技术A 目录

1、集成算法概述

2 、 Sklearn中RandomForestClassifier重要参数详解

3、Sklearn中RandomForestRegressor重要参数详解

4、附录

5、总结

1、集成算法概述: 集成算法的目标是多个评估器建模的结果,汇总后得到一个综合结果,以此来获取比单个模型更好的回归或分类表现。多个模型集成成为的模型叫集成评估器,单个模型叫基评估器。通常说有三种集成算法:装袋法(Bagging)、提升法(Boosting)和stacking。装袋法的基本思想是构建多个相互独立的基评估器,然后通过预测平均或多数表决原则来决定集成评估器的结果。装袋法的典型代表就是随机森林(RandomForest)。

2、RandomForestClassifier重要参数:

n_estimators: integer, optional (default=100), 森林中基评估器的数量,即树的数量。n_estimators越大模型效果越好,但达到一定程度时,精确性趋于稳定。n_estimators越大模型的计算量越大,需要的内存也越大。

random_state: int, RandomState instance or None, optional (default=None), 控制树的生成模式。在DecisionTreeClassifier中random_state生成随机的一棵树,这里的参数控制的是随机生成一片森林模式。 用袋装法集成时,基分类器应当是相互独立的,是不同的。

bootstrap: boolean, optional (default=True), 要让基分类器尽量都不一样,一种方式是使用不同的训练数据集来训练不同的树。而装袋法采用的是有放回采样法,来确保每棵树的随机性。booststrap就是用来控制抽样技术的参数。

oob_score: bool (default=False), 是否启用袋外数据做测试。有放回采样策略中,自助数据集平均包含63%的原始数据被抽中(每个样本从原始数据抽中到自助集的概率为: =63%左右),也就是说袋外数据(out of bag data  简称oob数据)大致占37%。在使用随机森林时,我们可以不划分测试和训练集,只要开启袋外数据支持,就可以用袋外数据测试我们的模型。然后这并不绝对,如果n足够大,则没有数据落入袋外,自然无法使用oob数据来测试模型了。如果需要用袋外数据做测试,则设置该参数为True,实例化并训练模型完成后,可以通过oob_score_来查看真是落入袋外的数据量。

重要属性与接口:

除了estimators_和oob_socre_这两个属性外,作为树模型也有feature_importances这个属性。

常用的接口主要有:apply,fit,predict和score。除此之外,还需要注意随机森林的predict_proba接口,该接口返回预测数据的被分到每一类标签的概率。如果是二分类,则predict_proba返回的数值大于0.5时被划分为1,否则为0。(在sklearn的随机森林中predict_proba返回每棵树的概率,然后取平均概率,从而根据概率值是否大于0.5划分为1,否则为0,来决定样本分类的)

Bagging要求基分类器相互独立,袋装法另一个必要条件是:基分类器的误差率要小于0.5,即准确率大于0.5,集成效果才好于基分类器。所以使用随机森林前,先要观察各基分类器是否都有至少50%的预测正确率。

3、RandomForestRegressor重要参数:

criterion:string, optional (default=”mse”)

1、输入“mse”使用均方误差mean squared err(MSE),父节点和子节点之间的均方误差的差额将被用来作为特征选择的标准,这种方法通过使用叶子节点的均值来最小化L2损失。

2、输入“friedman_mse”使用费尔德曼均方误差,这种指标使用费尔德曼针对潜在分枝中的问题改进后的均方误差。

3、输入“mae”使用绝对平均误差MAE(mean absolute error),这种指标使用叶节点的中值来最小化L1损失。



其中N是样本数量,i是每一个数据样本,fi是模型回归出的数值,yi是样本点i实际的数值标签。因此MSE的本质是回归值与真实值的差异。 在回归树中,MSE不仅是最优的分枝指标,也是最常用的衡量回归树回归质量的指标。

回归树接口:

score: 返回的是R平方,并不是MSE。R平方定义如下:

, , ,

其中u是残差平方和(MSE*N),v是总平方和,N是样本数量,i是每个样本,fi是模型回归出的值,yi是样本点i的实际数值标签。y帽是真实数值标签的平均数。

R2可以为正也可以为负,当残差平方和远远大于模型总平方和时,模型非常糟糕,R2为负;但MSE永远为正。但Sklearn当中使用均方误差作为评判标准时,却是计算“负均方误差”(neg_mean_squared_error)以负数表示。其实就是MSE前加了个负号。

4、附录

参数列表

属性列表

接口列表

5、总结: 本文详细介绍了集成学习中Bagging的典型代表随机森林的工作原理,同时对sklearn中RandomForestClassifier和RandomForestRegressor核心参数、属性、接口进行了介绍。

以上是关于合成法生成随机数原理的主要内容,如果未能解决你的问题,请参考以下文章

在图像文本文档中随机生成合成噪声

如何在 Windows 中通过随机分层源图像来自动生成合成图像?

逆分布函数法生成随机数(指数分布) R语言实现

随机森林原理与Sklearn参数详解

R语言:逆变换法生成密度函数的随机变量

R语言:逆变换法生成密度函数的随机变量