首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Numpy Vectorize签名

Numpy Vectorize签名
EN

Stack Overflow用户
提问于 2020-03-24 13:58:18
回答 1查看 1.3K关注 0票数 1

问题陈述

我必须有两个数组(XY),即维数(n,d)(m,d),并希望对两个矩阵之间的每一行组合应用一个函数。我要应用的功能如下:

代码语言:javascript
运行
复制
def norm(x, y):
    return np.linalg.norm(x-y)

其中xy是不同矩阵的对应行向量。我正在寻找的输出是形状(n,m)的矩阵,其中每个索引都是XY中相应行向量之间差值的范数。

预期解决方案:

因此,如果输入矩阵是:

代码语言:javascript
运行
复制
X = [[1,1,1,1],
    [2,2,2,2]]

Y = [[3,3,3,3],
    [4,4,4,4]]

我想得到以下输出:

代码语言:javascript
运行
复制
[[4,6],
[2,4]]

电流溶液

在这个阶段,我得到的唯一解决方案是使用np.vectorize函数将函数矢量化,并将不同的行映射到函数中,并获得矩阵输出。但是,当对函数应用以下矢量化时:

代码语言:javascript
运行
复制
norm_vec = np.vectorize(norm, signature='(d),(d)->()')

我得到以下输出:

代码语言:javascript
运行
复制
[[4,4]]

似乎该函数只是将函数映射到每个行对,而不是每个行组合。我对vectorize函数仍然非常陌生,也不确定signature参数是如何工作的,但是我的直觉告诉我,这个具有适当签名的函数可以给出正确的解决方案。

有没有人可以让我进一步了解np.vectorize函数是如何工作的,并构建正确的signature以获得我想要的解决方案,或者如果我完全偏离了轨道,就会指出正确的方向。我想避免使用for循环,因为我计划在一些大型矩阵上应用这个函数。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-24 17:44:32

您对signature的使用是可以的,它只需要使用broadcasting

代码语言:javascript
运行
复制
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;因此,让我们集中讨论这一点:

代码语言:javascript
运行
复制
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来做这件事:

代码语言:javascript
运行
复制
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逐行计算的相同结果。

代码语言:javascript
运行
复制
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是实现成对距离的好工具.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60832551

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档