Учитывая, что функция будет получать индексы как строк, так и столбцов, вы можете напрямую вычислить все значения в векторизованном виде, используя np.aranges
как x1
и y1
координаты:
rows = np.arange(sample.shape[0])
cols = np.arange(sample.shape[1])
x2, y2 = (row[header[i]], row[header[i + 1]])
out = np.exp(-1 * (np.sqrt((x2 - rows[:,None])**2 + (y2 - cols)**2) / 0.8**2))
Мы также можем ускорить вычисления с помощью модуля numexpr
:
import numexpr as ne
rows = np.arange(sample.shape[0])
cols = np.arange(sample.shape[1])
x2, y2 = (row[header[i]], row[header[i + 1]])
out = ne.evaluate('exp(-1 * sqrt((x2- rows2D)**2 + (y2- cols)**2) / 0.8**2)',
{'rows2D': rows[:,None]})
Быстрая проверкаи время:
n_rows = 1000
n_cols = 1000
rows = np.arange(n_rows)
cols = np.arange(n_cols)
x2, y2 = 10, 12
out = ne.evaluate('exp(-1*sqrt((x2- rows2D)**2 + (y2- cols)**2) / 0.8**2)',
{'rows2D': rows[:,None]})
np.allclose(out, point_annotation, rtol=1e-5)
# True
def current_approach(n_rows, n_cols, x2, y2):
point_annotation = np.zeros((n_rows,n_cols)).astype(np.float32)
for j in range(n_rows):
for k in range(n_cols):
value = point_gaussian_value(p1=(j, k), p2=(x2,y2))
point_annotation[j, k] = point_gaussian_value(p1=(j, k), p2=(x2,y2))
def approach_1(n_rows, n_cols, x2, y2):
rows = np.arange(n_rows)
cols = np.arange(n_cols)
out = np.exp(-1 * (np.sqrt((x2- rows[:,None])**2 + (y2- cols)**2) / 0.8**2))
def approach_2(n_rows, n_cols, x2, y2):
rows = np.arange(n_rows)
cols = np.arange(n_cols)
out = ne.evaluate('exp(-1*sqrt((x2- rows2D)**2 + (y2- cols)**2) / 0.8**2)',
{'rows2D': rows[:,None]})
%timeit current_approach(n_rows, n_cols, x2, y2)
# 10.7 s ± 471 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit approach_1(n_rows, n_cols, x2, y2)
# 59.3 ms ± 426 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit approach_2(n_rows, n_cols, x2, y2)
# 965 µs ± 43.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
До 11000x
ускорения при втором заходе!