如果我评估类似:
numpy.random.choice(2, size=100000, p=[0.01, 0.99])
使用一个均匀分布的随机数float
, say r
,并决定是否r < 0.01
可能会浪费许多生成的随机位(熵)。我听说(二手)生成伪随机数的计算成本很高,所以我假设numpy
不会这样做,而是会使用类似的方案算术编码在这种情况下。
然而,一开始glance看起来choice
确实生成了float
对于每个需要的样品。此外,快速timeit
实验表明,生成n
均匀浮动实际上比n
样本来自p=[0.01, 0.99]
.
>>> timeit.timeit(lambda : numpy.random.choice(2, size=100000, p=[0.01, 0.99]), number=1000)
1.74494537999999
>>> timeit.timeit(lambda : numpy.random.random(size=100000), number=1000)
0.8165735180009506
Does choice
真正生成一个float
对于每个样本,它会出现什么?在某些情况下(特别是如果size
很大并且p
分布不均匀)?如果没有,为什么不呢?
从 NumPy 1.17 开始,原因很大程度上是向后兼容性。也可以看看这个问题 and 这个问题.
从 NumPy 1.17 开始,numpy.random.*
功能,包括numpy.random.choice
,是遗留功能,并且“应保持与当前相同”,根据NumPy 的新 RNG 政策,其中还引入了NumPy 的新随机生成系统。使它们成为遗留功能的原因包括避免全局状态的建议。然而即便如此,NumPy 并没有弃用任何numpy.random.*
尽管 NumPy 的未来版本可能会在 1.17 版本中起作用。
回想一下,在你的例子中,numpy.random.choice
需要一个数组float
s 作为权重。整数权重数组将导致更精确的随机数生成。并且虽然任何float
可以转换为有理数(导致有理值权重,从而产生整数权重),旧的 NumPy 版本似乎不这样做。这些和其他实施决定numpy.random.choice
在不破坏向后兼容性的情况下无法更改。
顺便说一句,算术编码并不是唯一试图避免浪费比特的算法。也许离散分布采样的规范算法是 Knuth 和 Yao 算法(1976),该算法根据所涉及概率的二元展开精确地选择一个随机整数,并将问题视为二叉树上的随机游走。 (该算法平均使用距理论下界最多 2 位的数据。)任何其他整数生成算法最终都可以用相同的方式描述,即二叉树上的随机游走。例如,快速加载骰子滚轴是一种最新算法,其使用的平均位数有一个有保证的界限(在本例中,距理论下限不超过 6 位)。 Han 和 Hoshi 算法(1997 年)是另一种此类算法,但使用累积概率。另请参阅我的部分,“加权选择与替换".
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)