Python 正确编写numpy meshgrid函数

Python 正确编写numpy meshgrid函数,python,numpy,matplotlib,Python,Numpy,Matplotlib,下面的代码可以工作。然而,行计算rez可能不是以numpy开发人员所期望的方式编写的。我怎样才能高效地重写它,而不必在列表之间进行转换 另外,如果您碰巧知道一个关于如何用python编写数学函数的好指南,它同样适用于数字和np.array,请分享:) 编辑:让我解释一下我想做什么 我在2D中生成10个随机点。然后我定义了一个二维任意点(x,y)的损失函数。该函数的结果是所有10个固定点到该任意点的欧几里德距离之和。最后,我想用2d imshow方法绘制这个损失函数 编辑2:根据尼尔斯·沃纳的回答

下面的代码可以工作。然而,行计算rez可能不是以numpy开发人员所期望的方式编写的。我怎样才能高效地重写它,而不必在列表之间进行转换

另外,如果您碰巧知道一个关于如何用python编写数学函数的好指南,它同样适用于数字和np.array,请分享:)

编辑:让我解释一下我想做什么

我在2D中生成10个随机点。然后我定义了一个二维任意点(x,y)的损失函数。该函数的结果是所有10个固定点到该任意点的欧几里德距离之和。最后,我想用2d imshow方法绘制这个损失函数

编辑2:根据尼尔斯·沃纳的回答,可以使用3D阵列和广播,生成以下代码

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()
然而,该代码实际上比列表理解慢(对于10000个随机坐标,步骤0.01,大约慢2-3倍)。对于更大的输入,会出现内存崩溃,这让我相信这种方法会在内部导致3D数组动态编程,在内存分配方面无法很好地扩展

编辑3: 很抱歉,我的例子太少了。在我所面临的原始问题中,坐标X和Y没有解耦以允许分别计算它们。原始函数之一是

def gaussian(X, Y, x, y):
  return sum(np.exp(-(X-x)**2 -(Y-y)**2))

meshgrid
背后的思想是,您可以得到两个或多个数组,只需将它们本身传递到一个操作中即可。所以理想情况下,我们根本不需要for循环

但是,由于要在
X
PX
之间进行“外部差异”,然后在
X
轴上求和,因此还需要使用来首先进行外部乘积,最后在正确的轴上求和:

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)

一种更系统的方法是将总和与标准值区分开来,因为
L2normSquared
函数无法查看
x
vs
x
的特定角色

def normSquared(X, Y, x, y):
    return (X-x)**2 + (Y-y)**2

X = np.random.normal(0, 1, 10)
Y = np.random.normal(0, 1, 10)
x = y = np.arange(-1, 1, 0.1)

rez=normSquared(*np.meshgrid(X,Y,x,y)).sum(axis=(0,1))
normedSquared
理解数组和数字,这里不明确的是
sum

无需重新发明
meshgrid

编辑

若要推迟内存问题,可以提前求和,然后使用稀疏网格:

n=1000000
X = np.random.normal(0, 1, n)
Y = np.random.normal(0, 1, n)
x = np.arange(-1, 1, 0.1)
y = np.arange(-1, 1, 0.1)

Xm,Ym,xm,ym = mesh = np.meshgrid(X,Y,x,y,sparse=True)

rez=((Xm-xm)**2).sum((0,1))+((Ym-ym)**2).sum((0,1))

这在一秒钟内解决了n=1000000的问题。

使用
矩阵乘法
magic,既提高了内存效率,又提高了性能,而不会像这样乱搞
网格
-

a = np.exp(-(PX[:,None]-X)**2)
b = np.exp(-(PY[:,None]-Y)**2)
out = a.dot(b.T)
基准测试

方法和相关职能-

def gaussian(X, Y, x, y):
  return sum(np.exp(-(X-x)**2 -(Y-y)**2))

def org_method(PX, X, PY, Y):
    PXm, PYm = np.meshgrid(PX, PY)
    return np.array([[gaussian(X, Y, x, y) for y in PY] for x in PX])

def matmult_method(PX, X, PY, Y):
    a = np.exp(-(PX[:,None]-X)**2)
    b = np.exp(-(PY[:,None]-Y)**2)
    return a.dot(b.T)
时间安排和核查-

In [256]: X = np.random.normal(0, 1, 1000)
     ...: Y = np.random.normal(0, 1, 1000)
     ...: 
     ...: PX = np.arange(-1, 1, 0.01)
     ...: PY = np.arange(-1, 1, 0.01)

In [257]: np.allclose(org_method(PX, X, PY, Y), matmult_method(PX, X, PY, Y))
Out[257]: True

In [258]: %timeit org_method(PX, X, PY, Y)
1 loop, best of 3: 3.76 s per loop

In [259]: %timeit matmult_method(PX, X, PY, Y)
100 loops, best of 3: 12.2 ms per loop

因此,我们在那里得到了
300x+
的加速。

我不明白你在这里试图做什么操作对不起,检查editSo,
X
Y
是10个元素,但是PX和PY是10000?简单的测试:X,Y有10个元素,PX,PY有步骤0.1;;;中等测试:X,Y有10000个元素,PX,PY有步骤0.1;;;硬测试:X,Y有10000个元素,PX,PY有步骤0.01;;;列表理解可以做艰难的测试。那么,发布的解决方案对你有用吗?谢谢你的回复。此函数的输出与原始函数的输出不同。列似乎混合了好吧,仍然有一个问题。对于少量数据,您的方法比我的方法快,但是对于大量数据(10000点,步骤0.01),您建议的方法比我的方法慢2-3倍。可能是因为你正在创建3D阵列,而内存分配成了一个问题吗?是的,可能是这样。据我所知,平方和不等于平方和。我认为它在这种情况下不起作用,而我的实际用例更复杂,我不认为它可以用这种方式轻松分解。你是对的,结果看起来很相似:-)你的方法崩溃了10000个随机数和MemoryError,而列表理解对此没有问题,甚至更大的输入。4D阵列是一个坏主意,必须有一些更少的内存消耗Hey B.M.谢谢你的努力。看起来我的最小示例太小了。在我原来的问题中,求和并没有解耦,我只是把它做得太简单了。原始函数之一是sum(exp(-(X-X)**2-(Y-Y)**2)),对于这种情况,sum(exp(a+b))=sumxy(expa expb)=sumx(expa)*sumy(expb)。但对于其他情况,您的方法可能是必要的,不会造成很大的效率损失,因为内部循环是矢量化的。再次感谢您的评论。我相信你的数学陈述是不正确的,因为两个和的乘积有干涉项(a+b)*(c+d)=ac+ad+bc+bd,而你只需要对角线项ac+bd,这里没有干涉<代码>b=np.exp((Ym-Ym)**2).sum(0)*np.exp((Xm-Xm)**2.sum(1),
a=np.exp((Xm-Xm)**2+(Ym-Ym)**2.sum((0,1))
<代码>np。allclose(a,b)是
真的
。嘿,迪瓦卡,谢谢你的回复。很抱歉,我提出了一个比我必须解决的问题要简单得多的问题。请检查我的原件的第三版post@AleksejsFomins我想我已经破解了。查看更新。
In [256]: X = np.random.normal(0, 1, 1000)
     ...: Y = np.random.normal(0, 1, 1000)
     ...: 
     ...: PX = np.arange(-1, 1, 0.01)
     ...: PY = np.arange(-1, 1, 0.01)

In [257]: np.allclose(org_method(PX, X, PY, Y), matmult_method(PX, X, PY, Y))
Out[257]: True

In [258]: %timeit org_method(PX, X, PY, Y)
1 loop, best of 3: 3.76 s per loop

In [259]: %timeit matmult_method(PX, X, PY, Y)
100 loops, best of 3: 12.2 ms per loop