【问题标题】:Optimising the generation of a large number of random numbers using python 3使用python 3优化大量随机数的生成
【发布时间】:2016-12-06 08:52:45
【问题描述】:

我想在一个范围内(0 到 pi/8)生成八个随机数,将它们加在一起,取这个和的正弦值,然后做 N 次,取平均结果。扩大规模后,我得到了正确答案,但对于N > 10^6 来说太慢了,尤其是当我对 N 次试验进行平均时,n_t = 25 更多次!我目前让N = 10^5 的代码在 12 秒 左右运行,这意味着 N = 10^7 需要 20 分钟,这似乎不是最佳的(可能是,我不知道!)。

我的代码如下:

import random
import datetime
from numpy import pi
from numpy import sin
import numpy
t1 = datetime.datetime.now()

def trial(N):
    total = []
    uniform = numpy.random.uniform
    append = total.append
    for j in range(N):
        sum = 0
        for i in range (8):
            sum+= uniform(0, pi/8)
        append(sin(sum))
    return total

N = 1000000
n_t = 25
total_squared = 0
ans = []
for k in range (n_t):
    total = trial(N)
    f_mean = (numpy.sum(total))/N
    ans.append(f_mean*((pi/8)**8)*1000000)
sum_square = 0
for e in ans:
    sum_square += e**2
sum = numpy.sum(ans)
mean = sum/n_t
variance = sum_square/n_t - mean**2
s_d = variance**0.5
print (mean, " ± ", s_d)
t2 = datetime.datetime.now()
print ("Execution time: %s" % (t2-t1))

如果有人可以帮助我优化它,将不胜感激!

谢谢你:)

【问题讨论】:

  • 最终目标是什么?如果只是计算平均值,请进行数学计算,而不是进行冗长的模拟,否则无论如何都会出现统计错误。
  • 所以你想生成2 十亿个随机数?这肯定需要时间。
  • sum= numpy.sum(numpy.random.random_sample(8)) * pi_8 可能会加快一点速度
  • @JulienBernu 这是一种蒙特卡罗方法,用于对 sin(x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7)dx_0...dx_7 进行八维积分,范围为每个 x 从 0 到 pi/8
  • 但是为什么不做分析呢?仅当分析解决方案难以处理时,使用 MC 才有意义,这里似乎并非如此......

标签: python python-3.x optimization random numbers


【解决方案1】:

鉴于您需要使用此方法获得结果,np.sin(np.random.uniform(0,np.pi/8,size=(8,10**6,25)).sum(axis=0)).mean(axis=0) 可以很快为您提供 25 次试验...这是完全矢量化的(而且简洁,始终是一个奖励!)所以我怀疑您可以做得更好。 ..

解释:

您生成一个大小为(8 x 10**6 x 25) 的大随机3d 数组。 .sum(axis=0) 将为您提供第一维的总和 (8)。 np.sin(...) 按元素应用。 .mean(axis=0) 将为您提供第一个剩余维度 (10**6) 的平均值,并为您提供与您的试验相对应的一维长度数组 (25)。

【讨论】:

  • 谢谢!这是如何工作的,我该如何实施?抱歉,我一周前才开始学习 python,所以我不太清楚自己在做什么!
  • 这将首先在内存中生成所有内容,对吗?所以 N=1e7 至少需要 8GB。在一些现代计算机中仍然可以,但在内存方面并不便宜。不过,那里的向量很好的方法。 +1
  • 为我工作了大约 30 秒 10**7。如果您的内存有限,您可以将最后一个维度 (n_trials=25) 反向量化为基本的 for 循环
  • 是的! numpy、scipy 和其他库已经有大量有效实现的东西。在你的情况下,一定要使用.std().var()
【解决方案2】:

根据中心极限定理,您的随机变量将严格遵循正态定律。

八个均匀变量之和在 [0, π] 范围内呈钟形分布。如果我是对的,分布可以表示为 8 阶的 B 样条曲线。取正弦会给出 [0, 1] 范围内的值。您可以通过简单的数值积分找到期望 µ 和方差 σ²。

然后使用均值 µ 和方差 σ²/N 的正态生成器。相比之下,这将是瞬时的。

【讨论】:

  • 好吧,如果你要学习数学,不要半途而废;)
  • @JulienBernu:我不会半途而废。我告诉 OP 他如何生成一个与从 8N 值计算的具有相同特征的随机变量。但它仍然是一个随机值。
猜你喜欢
  • 1970-01-01
  • 2017-05-02
  • 2013-12-04
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 2017-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多