Я пытаюсь оптимизировать фрагмент, который называется много (миллионы раз), поэтому любой тип улучшения скорости (надеюсь, удаляющий for-loop) был бы замечательным.Векторизация для цикла с повторяющимися индексами в python
Я вычисления корреляционной функции некоторой частицы -й со всеми остальными
C_j (| г-г '|) = SQRT (E ((s_j (г') - S_K (г))^2)), усредненной по k.
Моя идея состоит в том, чтобы иметь переменную corrfun, которая помещает данные в некоторые ячейки (r, определенные в другом месте). Я нахожу, какой бит из r каждого s_k принадлежит, и он хранится в ind. Таким образом, ind [0] - индекс r (и, следовательно, corrfun), для которого соответствует точка j = 0. Несколько точек могут попадать в один и тот же ящик (на самом деле я хочу, чтобы ячейки были достаточно большими, чтобы содержать несколько точек), поэтому я суммирую все (s_j (r ') - s_k (r))^2, а затем деля по числу точек в этом бункере (хранится в переменной rw). Код, который я в конечном итоге делает для этого является следующее (нп для NumPy):
for k, v in enumerate(ind):
if j==k:
continue
corrfun[v] += (s[k]-s[j])**2
rw[v] += 1
rw2 = rw
rw2[rw < 1] = 1
corrfun = np.sqrt(np.divide(corrfun, rw2))
записки, RW2 бизнес потому, что я хочу, чтобы избежать деления на 0 проблем, но я вернуть массив Rw и я хочу чтобы иметь возможность различать элементы rw = 0 и rw = 1. Возможно, для этого есть более элегантное решение.
Есть ли способ сделать for-loop быстрее? В то время как я не хотел бы добавлять самостоятельное взаимодействие (j == k), я даже уверен в том, что у меня есть самостоятельное взаимодействие, если это означает, что я могу получить значительно более быстрый расчет (длина ind ~ 1E6, поэтому само взаимодействие, вероятно, будет незначительным).
Спасибо!
Илья
Edit:
Вот полный код. Обратите внимание, что в полном коде я также усредняю по j.
import numpy as np
def twopointcorr(x,y,s,dr):
width = np.max(x)-np.min(x)
height = np.max(y)-np.min(y)
n = len(x)
maxR = np.sqrt((width/2)**2 + (height/2)**2)
r = np.arange(0, maxR, dr)
print(r)
corrfun = r*0
rw = r*0
print(maxR)
''' go through all points'''
for j in range(0, n-1):
hypot = np.sqrt((x[j]-x)**2+(y[j]-y)**2)
ind = [np.abs(r-h).argmin() for h in hypot]
for k, v in enumerate(ind):
if j==k:
continue
corrfun[v] += (s[k]-s[j])**2
rw[v] += 1
rw2 = rw
rw2[rw < 1] = 1
corrfun = np.sqrt(np.divide(corrfun, rw2))
return r, corrfun, rw
отладить проверить это следующим образом
from twopointcorr import twopointcorr
import numpy as np
import matplotlib.pyplot as plt
import time
n=1000
x = np.random.rand(n)
y = np.random.rand(n)
s = np.random.rand(n)
print('running two point corr functinon')
start_time = time.time()
r,corrfun,rw = twopointcorr(x,y,s,0.1)
print("--- Execution time is %s seconds ---" % (time.time() - start_time))
fig1=plt.figure()
plt.plot(r, corrfun,'-x')
fig2=plt.figure()
plt.plot(r, rw,'-x')
plt.show()
Опять же, главный вопрос заключается в том, что в реальных данных п ~ 1E6. Разумеется, я могу переделать его, чтобы уменьшить его, но мне очень хотелось бы на самом деле прокрутить этот набор данных.
Можете ли вы предоставить полностью рабочую программу, включая этапы настройки? –
Несомненно, сейчас я отредактирую полный пост. Хорошо, код теперь поднят – Ilya
Спасибо. В стороне, почему это 'range (0, n-1)' вместо 'range (0, n)'? –