嵌套for循环慢python用于计算特殊标准偏差

Posted

技术标签:

【中文标题】嵌套for循环慢python用于计算特殊标准偏差【英文标题】:Nested for loops slow python for calculating special standard deviation 【发布时间】:2018-11-17 20:32:41 【问题描述】:

我正在尝试计算大约 100 个节点的矩阵中拓扑属性的标准偏差。我要编写的代码如下:

如何计算标准差

(需要用方括号括起来)

X 在哪里

如何计算拓扑性质X

但是 a 应该替换为 g。

因此,我编写了以下代码。我尝试使用大约 85 个节点的随机图运行代码。因此,SG 都是 85 x 85 矩阵,其中所有条目都是 0 和 1 之间的浮点数,n 是节点数,在这种情况下为 85。代码中的输入是M_std(type = numpy.ndarray, S in function),它是g_ij的标准差矩阵,M_p(type = numpy.ndarray, G in函数的输入)是 g_ij 的期望值的矩阵。 Derivative 指的是 (delta X)/(delta g_ij)。 Std_1 是广场之间的一切。

import networkx as nx
import numpy as np
import math

def new_calc_std_1(S, G, n):
    std_1 = 0
    for e in range(n):
        for f in range(n):
            derivative = 0
            for i in range(n):
                for j in range(n):
                    for k in range(n):
                        if i == j or i == k or j == k:
                            None
                        elif (e not in [i,j,k]) or (f not in [i,j,k]):
                            None
                        else:
                            if e == i and f == j:
                                deriv += -G[j,i]*G[j,k]*(1-G[k,j])*(1-G[i,k])*(1-G[k,i])
                            elif e == j and f == i:
                                deriv += (1-G[i,j])*G[j,k]*(1-G[k,j])*(1-G[i,k])*(1-G[k,i])
                            elif e == j and f == k:
                                deriv += (1-G[i,j])*G[j,i]*(1-G[k,j])*(1-G[i,k])*(1-G[k,i])
                            elif e == k and f == j:
                                deriv += -(1-G[i,j])*G[j,i]*G[j,k]*(1-G[i,k])*(1-G[k,i])
                            elif e == i and f == k:
                                deriv += -(1-G[i,j])*G[j,i]*G[j,k]*(1-G[k,j])*(1-G[k,i])
                            elif e == k and f == i:
                                deriv += -(1-G[i,j])*G[j,i]*G[j,k]*(1-G[k,j])*(1-G[i,k])
                            else:
                                derivative += 0
            std_1 += (S[e,f]*derivative)**2
    std_1 = math.sqrt(std_1)
    return std_1

这总共花了 21 分钟。我试图找到一个解决方案,然后我读到我必须尽量减少 for 循环的使用,尤其是在 python 中。因此我将代码重写为

def new_new_calc_std_1(S, G, n):
    blwsqrt = 0
    for e in range(n):
        for f in range(n):
            derivative = 0
            for z in range(n):
                if e == f or f == z or z == e:
                    None
                else:
                    derivative += -G[f,e]*G[f,z]*(1-G[z,f])*(1-G[e,z])*(1-G[z,e]) - (1-G[e,z])*G[z,e]*G[z,f]*(1-G[f,z])*(1-G[f,e]) + (1-G[f,e])*G[e,z]*(1-G[z,e])*(1-G[f,z])*(1-G[z,f]) - (1-G[f,z])*G[z,f]*G[z,e]*(1-G[e,z])*(1-G[f,e]) + (1-G[z,e])*G[e,z]*(1-G[f,e])*(1-G[z,f])*(1-G[f,z]) - (1-G[z,f])*G[f,z]*G[f,e]*(1-G[z,e])*(1-G[e,z])
            blwsqrt += (derivative*S[e,f])**2
    std_1 = math.sqrt(blwsqrt)
    return(std_1)

print(new_new_calc_std_1(M_std, M_p, n))

令我惊讶的是,这花费了完全相同的时间。然后我尝试对矩阵进行四舍五入。这也不起作用。然后我读到我可能使用了太多的 python 并且应该更多地使用 scipy,但我不知道在这个特定的实例中如何。 你们知道如何优化此代码以使其花费的时间少于 21 分钟,或者这正是我必须处理的事情。这是上一篇文章的更新版本。对于最后一个,我很抱歉。

附:我正在使用 2,5 GHz Intel Core 5 并在 jupyter notebook 中运行计算。

P.P.S M_std 的一个例子是

[[0.45 0.39 0.45 ... 0.41 0.43 0.39]
 [0.5  0.46 0.5  ... 0.48 0.49 0.47]
 [0.5  0.46 0.49 ... 0.47 0.49 0.46]
 ...
 [0.48 0.42 0.47 ... 0.44 0.46 0.43]
 [0.5  0.46 0.49 ... 0.47 0.49 0.46]
 [0.47 0.42 0.47 ... 0.43 0.46 0.42]]

M_p

[[0.29 0.18 0.28 ... 0.21 0.25 0.19]
 [0.45 0.31 0.44 ... 0.35 0.4  0.32]
 [0.44 0.3  0.42 ... 0.34 0.39 0.31]
 ...
 [0.35 0.23 0.34 ... 0.26 0.31 0.24]
 [0.43 0.3  0.42 ... 0.34 0.39 0.31]
 [0.33 0.22 0.33 ... 0.25 0.29 0.23]]

【问题讨论】:

如果这是工作代码并且您想要优化它,代码审查 SE 将是一个更好的地方 @ThomasMcDonald 用您当前的代码更新您的问题 @ThomasMcDonald 请先更正所有错别字。没有声明 j,也没有声明 k 但你在函数中使用它们。尝试运行代码时应该会看到这些错误 我刚吃完午饭回来 -- 我很高兴看到改进的帖子和解决方案!! 没问题^^。您已经自己优化了它,只需要它运行:P 【参考方案1】:

如果您使用的是 Python2,我建议您使用 xrange 而不是 rangexrange 效率更高,因为它不会预先生成整个序列。

我还建议使用 itertools.product 而不是嵌套的 for 循环。

尝试类似for (e,f,z) in product(xrange(n), xrange(n), xrange(n)):

product docs link

【讨论】:

以上是关于嵌套for循环慢python用于计算特殊标准偏差的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Python 输出嵌套循环的结果 [关闭]

Python - 每列中所选行的标准偏差

用于在 python 中创建列表的单行非嵌套 for 循环

Python打破嵌套的for循环并重新启动while循环

itertools.product 比嵌套 for 循环慢

嵌套for循环中的python数组[重复]