三角分布随机变量

Triangular Distribution Random Variables

首先介绍一下我的情况:

我需要一个随机三角分布,并计划使用 Python 的 random.triangular。以下是源码(Python3.6.2):

    def triangular(self, low=0.0, high=1.0, mode=None):
    """Triangular distribution.

    Continuous distribution bounded by given lower and upper limits,
    and having a given mode value in-between.

    http://en.wikipedia.org/wiki/Triangular_distribution

    """
    u = self.random()
    try:
        c = 0.5 if mode is None else (mode - low) / (high - low)
    except ZeroDivisionError:
        return low
    if u > c:
        u = 1.0 - u
        c = 1.0 - c
        low, high = high, low
    return low + (high - low) * (u * c) ** 0.5

我查看了引用的 wiki 页面,发现我想要的用途有一个 special case 可以简化事情,并且可以通过以下功能实现:

def random_absolute_difference():
    return abs(random.random() - random.random())

做一些快速计时显示简化版本的显着加速(每次运行我的代码时,此操作将重复超过一百万次):

>>> import timeit
>>> timeit.Timer('random.triangular(mode=0)','import random').timeit()
0.5533245000001443
>>> timeit.Timer('abs(random.random()-random.random())','import random').timeit()
0.16867640000009487

那么问题来了:我知道python的随机模块只使用伪随机,而random.triangular使用一个随机数,而特殊情况代码使用2个随机数。特例结果的随机性会大大降低吗,因为它们使用了 2 个连续的随机调用,而 random.triangular 只使用了一个?使用简化代码是否还有其他无法预料的副作用?

编辑:参考 this solution to a different question,我为两个分布创建了直方图,表明它们具有可比性:

随机三角分布:

特例简化分布:

在您的情况下,triangular 归结为以下表达式:

1 + (0 - 1) * ((1.0 - u) * (1.0 - c)) ** 0.5

然后进一步到:

1 - 1 * ((1.0 - u) * 1.0) ** 0.5

然后进一步到:

1 - (1.0 - u) ** 0.5

根据我的时间安排,最后一个表达式的运行速度比 random.triangular(mode=0) 快得多,并且速度与 abs(random.random()-random.random()) 相当。请注意,triangular 包含一个 try/except 语句,这可能解释了一些性能差异(例如,将该语句替换为“mode = 0”并查看)。

import timeit
timeit.Timer('random.triangular(mode=0)','import random').timeit()
timeit.Timer('1 - (1.0 - random.random()) ** 0.5','import random').timeit()
timeit.Timer('abs(random.random()-random.random())','import random').timeit()

但是,我看不出为什么使用两个随机数而不是一个随机数会产生“不太随机”的 triangular-distributed 数字——只要这两种方法产生相同的分布。事实上,与仅使用一个随机数相比,使用两个随机数会为您提供更多种类的 triangular-distributed 数,因为有更多的随机数可用于此目的。 (如果您想测试这两种方法的正确性,您可以使用 Kolmogorov–Smirnov 测试以及三角分布的 CDF,因为三角分布是绝对连续的。例如,在 SciPy 在 scipy.stats.kstest 下。如果多次运行测试 return 一个 p-value 非常接近 0,这强烈表明数字来自错误的分布。)