Вложено для циклов медленного Python для расчета специального стандартного отклонения - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь вычислить стандартное отклонение для топологических свойств в матрицах около 100 узлов.Я пытаюсь кодировать следующее:

как рассчитать стандартное отклонение

(должна быть квадратная скобка, закрывающая это)

Где X -

как рассчитать топологическое свойство X

, но a следует заменить на g.

В результате я кодировал следующее.Я пробовал запустить код со случайным графом около 85 узлов.Поэтому S и G представляют собой матрицу 85 на 85, где все записи являются числами с плавающей точкой от 0 до 1, а n - это число узлов, в данном случае 85.Ввод в код: M_std (type = numpy.ndarray, S на входе функции), который представляет собой матрицу стандартных отклонений g_ {ij} и M_p (type = numpy.ndarray, G inввод функции) представляет собой матрицу ожидаемых значений g_ {ij}.Derivative относится к (дельта X) / (дельта 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 минута, или это как раз то, с чем мне приходится иметь дело .Это обновленная версия предыдущего поста.Я очень сожалею о последнем.

PS Я использую 2,5-ГГц Intel Core 5 и выполняю вычисления в ноутбуке Jupyter.

PPS пример 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]]

1 Ответ

0 голосов
/ 13 июня 2018

Если вы используете Python2, я бы посоветовал использовать xrange вместо range.xrange более эффективен, поскольку не генерирует всю последовательность заранее.

Я бы также посоветовал использовать itertools.product вместо вложенных циклов.

Попробуйте что-то вроде for (e,f,z) in product(xrange(n), xrange(n), xrange(n)):

product ссылка на документацию

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...