The below code works. However, the line calculating rez is likely not written in the way intended by numpy developers. How can I rewrite it in an efficient way, without converting to and from lists?
Also, if you happen to know a good guide on how to write mathematical functions in python, which would work equally with numbers and np.arrays, please share :)
import numpy as np
from matplotlib import pyplot as plt
def L2normSquared(X, Y, x, y):
return sum((X-x)**2 + (Y-y)**2)
X = np.random.normal(0, 1, 10)
Y = np.random.normal(0, 1, 10)
PX = np.arange(-1, 1, 0.1)
PY = np.arange(-1, 1, 0.1)
PXm, PYm = np.meshgrid(PX, PY)
rez = np.array([[L2normSquared(X, Y, x, y) for y in PY] for x in PX])
print(rez.shape)
plt.imshow(rez, cmap='jet', interpolation='nearest', origin='lower', extent=[-1, 1, -1, 1])
plt.show()
Edit: Let me explain what I am trying to do
I generate 10 random points in 2D. Then I define a loss function for any arbitrary point (x,y) in 2D. Result of that function is the sum of euclidian distances of all 10 fixed points to this arbitrary point. Finally, I want to plot this loss function using 2d imshow method
Edit 2: According to Nils Werner's answer, one can use 3D arrays and broadcasting, producing the following code
import numpy as np
from matplotlib import pyplot as plt
def L2normSquared(X, Y, x, y):
return np.sum((X-x)**2 + (Y-y)**2, axis=0)
X = np.random.normal(0, 1, 10)
Y = np.random.normal(0, 1, 10)
PX = np.arange(-1, 1, 0.1)
PY = np.arange(-1, 1, 0.1)
PXm, PYm = np.meshgrid(PX, PY)
rez = L2normSquared(X[:, None, None], Y[:, None, None], PXm, PYm)
print(rez.shape)
plt.imshow(rez, cmap='jet', interpolation='nearest', origin='lower', extent=[-1, 1, -1, 1])
plt.show()
However, this code is actually slower than list comprehension (for 10000 random coordinates, step 0.01, it is roughly 2-3 times slower). For even larger inputs, there is a memory crash, which leads me to believe that this method internally results in 3D array dynamic programming, which does not scale well in terms of memory allocation.
Edit 3: I am very sorry, but my minimal example was too minimal. In the original problem I am facing, the coordinates X and Y do not decouple to allow them to be calculated separately. One of the original functions is
def gaussian(X, Y, x, y):
return sum(np.exp(-(X-x)**2 -(Y-y)**2))
XandYare 10 elems, but PX and PY are 10000?