使用Python加快计算贝塔Pert分布

2024-10-06 12:05:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在计算for循环的每次迭代的beta-PERT分布(除其他外,计算分布是最耗时的)。 最初是用R编写的,但花了太长时间才完成,因此尝试使用更快的工具。在

我的一些数据集可能相当大,例如,我刚运行了一个包含153413个案例的案例,在Python中仍然需要大约8个小时(比R更好,但仍然有点长)。在

我对Python很陌生,不知道有没有什么方法可以加快这种计算速度?在

示例代码:

af = lambda pmu, pmin, pmode, pmax: (pmu-pmin)*(2*pmode-pmin-pmax)/((pmode-pmu)*(pmax-pmin))
bf = lambda pmu, pmin, pmode, pmax: (pmax-pmu)/(pmu-pmin)*((pmu-pmin)*(2*pmode-pmin-pmax)/((pmode-pmu)*(pmax-pmin)))

e=5.
shape=4.
max=10.
mu_d = np.arange(0, 10, 0.05)                
d = np.arange(0.025, 60.025, 0.05)
nlocs=153413  # number of rows in dataset


f0_dist = np.zeros(len(mu_d))
f1_dist = np.zeros(len(mu_d))
f2_dist = np.zeros(len(mu_d))

f0 = st.norm.cdf(d, 0.9/2., 0.9/6.)
f1 = st.uniform.cdf(d, 0.001, 0.9)

tic = time.clock()     
    for i in xrange(nlocs):
       for j in xrange(len(mu_d)): # mu_d has 121 values
            Rp_min = mu_d[j] - 1.96*e
            Rp_mode = mu_d[j] - 0.75*e
            Rp_max = max
            Rp_mu=(Rp_min+Rp_max+shape*Rp_mode)/(shape+2)
   dist = st.beta.cdf(d, a=af(Rp_mu, Rp_min, Rp_mode, Rp_max), b=bf(Rp_mu, Rp_min, Rp_mode, Rp_max), loc=Rp_min, scale=1-Rp_min)

    f0_dist[j] = 1 - np.sum(dist*f0*0.05)
    f1_dist[j] = 1- np.sum(dist*f1*0.05)
    f2_dist[j] = 1 - np.sum(dist*0.05)
    temp = 0.4*f0_dist + 0.5*f1_dist + 0.1*f1_dist
    aggr_dist = aggr_dist + temp

toc = time.clock() - tic
print '\nTime elapsed: %.3f seconds\n' % toc

Tags: forlenmodedistnpminmaxrp
1条回答
网友
1楼 · 发布于 2024-10-06 12:05:33

下面是一些修改过的代码:

af = lambda pmu, pmin, pmode, pmax: (pmu-pmin)*(2*pmode-pmin-pmax)/((pmode-pmu)*(pmax-pmin))
bf = lambda pmu, pmin, pmode, pmax: (pmax-pmu)/(pmu-pmin)*((pmu-pmin)*(2*pmode-pmin-pmax)/((pmode-pmu)*(pmax-pmin)))

e=5.
shape=4.
max=10.
mu_d = np.arange(0, 10, 0.05)                
d = np.arange(0.025, 60.025, 0.05)

Rp_max = max
e1_96 = 1.96 * e
e0_75 = 0.75 * e
for i in xrange(nlocs): # e.g 153413
   for mu_d_j in mu_d: # mu_d has 121 values
        Rp_min = mu_d_j - e1_96
        Rp_mode = mu_d_j - e0_75
        Rp_mu=(Rp_min+Rp_max+shape*Rp_mode)/(shape+2)

   dist = st.beta.cdf(d, a=af(Rp_mu, Rp_min, Rp_mode, Rp_max), b=bf(Rp_mu, Rp_min, Rp_mode, Rp_max), loc=Rp_min, scale=1-Rp_min)

解释如下:

保存循环内的所有指令

  • Rp_max = max移出循环
  • 预聚集常量超出循环(对于e1_96e0_75

避免更深层次的引用

  • 只执行mu_d[j]一次并使用局部变量,获取更深的值需要时间

使用for循环来获取值,而不是lst[i]

以下内容:

^{pr2}$

将变成更有效的(和Python):

for mu_d_j in mu_d: # mu_d has 121 values
    #now use mu_d_j

测量时间

这是基本规则,每次修改都要进行评估。 如果你设置了你的期望速度(处理时间),你有机会很快停止优化 够了。在

免责声明

由于我无法运行代码,我不能保证所有更改都是正确的。那就是 有几行,我不确定,他们应该做什么:

最后一行dist =

   dist = st.beta.cdf(d, a=af(Rp_mu, Rp_min, Rp_mode, Rp_max), b=bf(Rp_mu, Rp_min, Rp_mode, Rp_max), loc=Rp_min, scale=1-Rp_min)

是否正确缩进?现在,它对每个nloc循环执行一次。在

结果的dist值在哪里使用?在

如果这是最深层次循环的一部分,那么可以进行更多的优化(使用更少的变量 名称移动一些代码内联)。在

相关问题 更多 >