#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