问题陈述
我必须有两个数组(X
和Y
),即维数(n,d)
和(m,d)
,并希望对两个矩阵之间的每一行组合应用一个函数。我要应用的功能如下:
def norm(x, y):
return np.linalg.norm(x-y)
其中x
和y
是不同矩阵的对应行向量。我正在寻找的输出是形状(n,m)
的矩阵,其中每个索引都是X
和Y
中相应行向量之间差值的范数。
预期解决方案:
因此,如果输入矩阵是:
X = [[1,1,1,1],
[2,2,2,2]]
Y = [[3,3,3,3],
[4,4,4,4]]
我想得到以下输出:
[[4,6],
[2,4]]
电流溶液
在这个阶段,我得到的唯一解决方案是使用np.vectorize
函数将函数矢量化,并将不同的行映射到函数中,并获得矩阵输出。但是,当对函数应用以下矢量化时:
norm_vec = np.vectorize(norm, signature='(d),(d)->()')
我得到以下输出:
[[4,4]]
似乎该函数只是将函数映射到每个行对,而不是每个行组合。我对vectorize
函数仍然非常陌生,也不确定signature
参数是如何工作的,但是我的直觉告诉我,这个具有适当签名的函数可以给出正确的解决方案。
有没有人可以让我进一步了解np.vectorize
函数是如何工作的,并构建正确的signature
以获得我想要的解决方案,或者如果我完全偏离了轨道,就会指出正确的方向。我想避免使用for循环,因为我计划在一些大型矩阵上应用这个函数。
发布于 2020-03-24 17:44:32
您对signature
的使用是可以的,它只需要使用broadcasting
In [374]: def norm(x, y):
...: return np.linalg.norm(x-y)
...:
In [376]: f = np.vectorize(norm, signature='(d),(d)->()')
In [377]:
In [377]: X = np.array([[1,1,1,1],
...: [2,2,2,2]])
...:
...: Y = np.array([[3,3,3,3],
...: [4,4,4,4]])
In [378]: f(X,Y)
Out[378]: array([4., 4.])
In [379]: f(X[:,None,:], Y[None,:,:])
Out[379]:
array([[4., 6.],
[2., 4.]])
您的函数首先执行x-y
;因此,让我们集中讨论这一点:
In [383]: f = np.vectorize(lambda x,y:x-y, signature='(d),(d)->(d)')
In [384]: f(X[:,None,:], Y[None,:,:])
Out[384]:
array([[[-2, -2, -2, -2],
[-3, -3, -3, -3]],
[[-1, -1, -1, -1],
[-2, -2, -2, -2]]])
但我们不需要vectorize
来做这件事:
In [385]: X[:,None,:]-Y[None,:,:]
Out[385]:
array([[[-2, -2, -2, -2],
[-3, -3, -3, -3]],
[[-1, -1, -1, -1],
[-2, -2, -2, -2]]])
norm
接受一个axis
参数;指定最后一个参数,则给出使用vectorize
逐行计算的相同结果。
In [387]: np.linalg.norm(X[:,None,:]-Y[None,:,:], axis=-1)
Out[387]:
array([[4., 6.],
[2., 4.]])
这种适当的“向量化”方法的一个缺点是,广播的差异可能很大,并导致内存错误。
因此,当函数不能使用更快的编译的整体数组方法时,np.vectorize
是非常有用的。但它不是速度工具。它比更显式的迭代要慢。signature
的添加很有趣,但速度更慢。
scipy.spatial.distance.pdist
是实现成对距离的好工具.
https://stackoverflow.com/questions/60832551
复制相似问题