三角分布随机变量
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,这强烈表明数字来自错误的分布。)
首先介绍一下我的情况:
我需要一个随机三角分布,并计划使用 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,这强烈表明数字来自错误的分布。)