Есть ли способ ускорить эти вложенные циклы (случай Лапласа) Python?

#python #performance #loops #nested-loops

#python #Производительность #циклы #вложенные циклы

Вопрос:

Я пытаюсь ускорить вложенный цикл в моей функции Gram.

Моя функция, которая вызывает большую задержку, — это функция Лапласа (Абеля), потому что она требует вычисления для каждой ячейки матрицы нормы столбца по строке.

abel = lambda x,y,t,p: np.exp(-np.abs(p) * np.linalg.norm(x-y))

 def Gram(X,Y,function,t,p):
    n = X.shape[0]
    s = Y.shape[0]
    K = np.zeros((n,s))
    if function==abel:
        for i in range(n):
            for j in range(s):
                K[i,j] = abel(X[i,:],Y[j,:],t,p)
    else:
        K = polynomial(X,Y,t,p)
    return K
  

Я смог немного ускорить функцию, исключив экспоненциальную часть из уравнения Абеля, а затем применил ее ко всей матрице.

abel_2 = lambda x,y,t,p: np.linalg.norm(x-y) (не обращайте внимания на t и p).

 def Gram_2(X,Y,function,t,p):
    n = X.shape[0]
    s = Y.shape[0]
    K = np.zeros((n,s))
    if function==abel_2:
        for i in range(n):
            for j in range(s):
                K[i,j] = abel_2(X[i,:],Y[j,:],0,0)
        K = np.exp(-abs(p)*K)
    else:
        K = polynomial(X,Y,t,p)
    return K
  

Время сокращается на 50%, однако, я считаю, что двойные циклы (вложенные) по-прежнему являются серьезной проблемой.
Кто-нибудь может помочь с этим?
Спасибо!

Ответ №1:

По сути, вместо того, чтобы проходить циклы один за другим для вычитания X[i,:] Y[j,:] , это сэкономило бы массу времени, просто выбрав X[i,:] и вычтя его из всего Y, а затем применив норму к определенной оси!

В моем случае это было axis=1 .

 def Gram_10(X,Y,function,t,p):
    n = X.shape[0]
    s = Y.shape[0]
    K = np.zeros((n,s))
    if function==abel_2:
        for i in range(n):
# it is important to put the correct slice (:s) , so the matrix provided by the norm goes
# to the right place in the function 
                K[i,:s] = np.linalg.norm(X[i,:]-Y,axis=1)
        K = np.exp(-abs(p)*K)
    else:
        K = polynomial(X,Y,t,p)
    return K