我想要在一个范围内生成八个随机数(0到pi / 8),将它们加在一起,取这个和的正弦值,然后这样做N次,得到平均结果。在缩放之后,我得到了正确的答案,但对N > 10^6
来说太慢了,特别是当我平均超过N次n_t = 25
次N = 10^5
时!我目前正在使用N = 10^7
的 12秒运行此代码,这意味着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))
需要 20分钟,而不是# 39; t似乎是最优的(可能是,我不知道!)。
我的代码如下:
showData()
如果有人可以帮我优化,我们将不胜感激!
谢谢:)
答案 0 :(得分:5)
鉴于您需要使用此方法获得结果,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(...)
适用于elementwise。 .mean(axis=0)
会获得第一个剩余维度(10**6
)的平均值,并为您留下与您的试验相对应的1d长度(25
)数组。
答案 1 :(得分:1)
根据中心极限定理,你的随机变量将严格遵循正规定律。
八个均匀变量的总和在[0,π]范围内具有钟形分布。如果我是对的,则分布可以表示为阶数为8的B样条。取正弦值得到范围[0,1]中的值。您可以通过简单的数值积分找到期望μ和方差σ²。
然后使用平均μ和方差σ²/ N的普通发生器。相比之下,这将是即时的。