如何评价一个伪随机数生成算法的优劣
以下来自我在知乎的回答。http://www.zhihu.com/question/20222653
谈到随机性,这大概是一个令人困惑哲学问题吧。随机行为精确地说究竟指的是什么,最好是有定量的定义。Kolmogorov曾提出一种判定随机性的方法: 对于无穷的随机数序列,无法用其子序列描述。J.N.Franklin则认为:如果一个序列具有从一个一致同分布的随机变量中独立抽样获得的每个无限序列 都有的性质,则是随机的。这些定义都不是很精确,有时甚至会导致矛盾。可见数学家在谈到这个问题时是多么的审慎。
随机数生成器只是一种产生符合特
定分布的随机数的算法。这些所谓的随机数序列实际上是周期性的。从实用的角度出发,随机数生成器如果能够在尽可能多的场合中产生正确的结果,那么它就是好
的。但是这个愿望无法完全实现。因为每一个生成器都会在特定的场合失效,比如说可能无法达到随机数的均匀性或者随机数之间隐藏着关联。
已经有大量的随机数生成器,但是找到好的、易移植的、达到工业水准的随机数生成器是一个难以实现的目标。生成非均匀分布的标准方法是先产生均匀分布随机数,然后将其转化为特定分布的随机数。我在博客关于随机数的笔记中有简易介绍。Knuth曾经说
. . . look at the subroutine library of each computer installation in your organization, and replace the random number generators by good ones. Try to avoid being too shocked at what you find.
对于不同的应用,这些因素的重要程度并不一样。比如说用物理方法产生的真随机数比由数学方法产生的伪随机数随
机性更强,更难破解,但这并不能说明物理方法产生的随机数质量更高。假设我们并能够事先知道应用的场景,应该如何评价一个生成器的质量呢?我们并不知道采
样的过程、样本的大小或者仿真中的维度。以下两点是很重要的:
- 生成器只提供预测,不提供保证。这是因为我们产生的只是有限数量的随机数,并且转换成特定分布的方法并不是足够好。因此,在特定的场合即使可靠的生成器也会失效。
- 尽管没有保证,但是有数学上的安全性测度。这意味着我们可以从理论上知道周期长度、一些结构性质以及关联性等。周期长度会限制样本的大小;结构信息可以是我们确定在仿真中是否存在副作用;关联性质则对随机模拟而言很重要。
不言而喻,随机数生成的方法应是快速的,占用内存少的,实现简单,可移植,可并发执行,对于不同的参数都应当具有均匀的速度。更加重要的检测内容是对其统计性质的检测。统计检验又分为两类:一类是理论检验,另一类是经验检验。
先
来说说理论检验。顾名思义,理论检验是先验的检验,能够预先告诉我们这些检验的结果将会是如何。如前所述,理论检验主要是检验随机数的周期,内在结构和关
联性。发展这一类型的理论十分困难,至今的得到的结果一般是对整个周期的统计检验。对于线性同余算法得到的随机数,周期长度的平方根是一个比较好的样本大
小的上限。因此对于一个好的生成器,必须能够使得对于某些参数能够得到最大的周期长度,并且能够计算出这样的参数。比如对于线性同余算法而言,最好的乘数
是,模是
.这个观点在很多书籍和论文中都有推荐,但是随着计算机计算能力的提高,这个观点已经不合时宜啦。因为对于现代的计算机而言,这样的周期还是太短了,现在而言m不应小于
.生成器的内部结构如栅栏结构和超平面点的分布也很重要。对于不同的生成器有特定的检测方法。结构检测用到最多的就是谱检验,谱检验就是基于相邻平行超平面之间最大距离的检验,该距离越大,生成器越大。如下图所示:
上图中随机数主要保持在平面内。
对于二维的情况如下图所示:
上图中我们可以用少量的平行线来全部覆盖它们,由许多不同的平行线族,它们将会碰上所有的点。平行覆盖线的数目是一个重要的指标。
将随机数生成器应用在并行进程中尤其要注意的是随机数之间是否关联,即独立性检测。比如用线性同余算法得到的均匀分布经Box-Muller转换成正态分布得到的点落在一条螺旋线上,如下图:
从
理论上可以证明所有的线性和非线性同余序列都存在长周期相关现象。如果几个并行处理器分别使用同一个同余序列的不同段落,分割时就应该避开具有强相关的分
点。以上的3副图给人一种触目惊心的感觉,没想到我们平常用到最多的线性同余算法产生的随机数是如此的”不随机“,我想这种震撼类似于第一次用显微镜观察
微生物发现一个不可思议的微观世界。的确,这类似于我们用超高分倍率的显微镜来观察我们得到的随机数,只有对于很精确的应用情境这种观察才是有价值的,否
则只是杞人忧天、庸人自扰了。在这种情况下,简单的线性同余序列肯定是不适用的,应当使用具有更大周期的生成序列,尽管实际上只要生成这个周期中的很小的
一部分。
理论检验是不够的,我们还需要经验检验。经验检验性对较简单,且有很多的方法。比如:
- 等分布检验:又称均匀性检验,将【0,1[】区间分成k个相等的子区间,落在每个子区间的伪随机数个数应该相等。常用的是
检验。
- 序列检验:相继的数偶独立一致分布。计算的是数偶对的出现次数。
- 间隔检验:用来考察在某个范围内序列的出现的间隔长度。
- 扑克检验:考虑5个相继整数组成的n个组,观察其出现模式。
- ........
经验检验还有很多,不一一赘述了。
当然即使通过了所有的统计测试,这也不能证明什么,但是这提高了我们使用这个生成器的信心。
对
于实际应用中,应该对不同的应用场景选择合适的生成器。当然也有一些通用的测量方法来告诉我们该生成器是否有可能是一个好的生成器。对于并行应用来说,很
多通常情况下很好的生成器都不合适。我们可以为k个进程选择k个生成器,虽然这也不是一个很好的方法。通用的方法如下:
有一个比喻:随机数生成器就像抗生素,每一种都有副作用,没有安全的随机数生成器。好的随机数生成器应该是有理论检验的支持,充分的经验证据和良好的实际表现。遵循以下一些建议对于合理使用随机数生成器很有帮助:
- 不要相信只由一个生成器得到的随机数序列,在使用前用不同的生成器检验它们的结果。
- 不要在没有理论依据和经验支持的情况下将几种生成器结合起来或并行。
- 在使用前了解生成器的特性。