Следующий код работает, но я хотел бы создать Z путем векторизации. Как этого добиться?
import numpy as np
from numpy import sqrt
from math import fsum
points = np.array([[0,0],\
[5,-1],\
[4,6],\
[1,3]])
d = lambda x: fsum([sqrt((x[0]-z[0])**2 + (x[1]-z[1])**2) for z in points])
x = np.linspace(min(points[:,0]),max(points[:,0]),100)
y = np.linspace(min(points[:,1]),max(points[:,1]),100)
X, Y = np.meshgrid(x,y)
Z = np.zeros(np.shape(X))
for (i,j),_ in np.ndenumerate(Z):
Z[i,j] = d([X[i,j],Y[i,j]])
#Z=d([X,Y]) #this fails
Просмотрите документацию по трансляции, и простой гугл на numpy broadcasting
даст много хороших ресурсов.
понятно. если я использую np.mgrid (), тогда Z должен быть создан с помощью x [:, None, None] и y [:, None]. крутой трюк.
Мы можем использовать broadcasting
для работы напрямую с версиями 1D
и, таким образом, быть более эффективным с точки зрения памяти и дать себе векторизованный однострочник, например:
Z = np.sqrt((x[:,None] - points[:,0])**2 + (y[:,None,None] - points[:,1])**2).sum(2)
Сроки опубликованных выборочных данных -
In [80]: %%timeit
...: X, Y = np.meshgrid(x,y)
...: Z = np.zeros(np.shape(X))
...: for (i,j),_ in np.ndenumerate(Z):
...: Z[i,j] = d([X[i,j],Y[i,j]])
10 loops, best of 3: 101 ms per loop
In [81]: %timeit ((x[:,None] - points[:,0])**2 + (y[:,None,None] - points[:,1])**2).sum(2)
1000 loops, best of 3: 246 µs per loop
400x
ускорения есть!
работает как шарм. хотя мне удалось разобраться в коде, мне кажется, что очень трудно органически привить этот навык в программирование. любой учебник по теме с более подробной информацией и интуитивно понятным языком?