按需矢量化numpy代码

按需矢量化numpy代码,numpy,Numpy,假设我在Python中有一个非常基本的函数: def f(x, y): return x + y 然后我可以用标量f1,5.4==6.4或者任意形状的numpy向量来调用它。例如,这项工作: x = np.arange(3) y = np.array([1,4,2.3]) f(x, y) 它给出了一个包含条目1、5、4.3的数组 但是如果f更复杂呢?例如,这里的xx和yy是1D numpy数组 def g(x, y): return np.sum((xx - x)**2 + (y

假设我在Python中有一个非常基本的函数:

def f(x, y):
   return x + y
然后我可以用标量f1,5.4==6.4或者任意形状的numpy向量来调用它。例如,这项工作:

x = np.arange(3)
y = np.array([1,4,2.3])
f(x, y)
它给出了一个包含条目1、5、4.3的数组

但是如果f更复杂呢?例如,这里的xx和yy是1D numpy数组

def g(x, y):
   return np.sum((xx - x)**2 + (yy - y)**2)
我急忙补充说,我对这个特定的g不感兴趣,但对一般策略感兴趣。。。然后g5,6可以正常工作,但如果我想通过numpy阵列,我似乎必须使用explict广播等编写一个非常不同的函数。例如:

def gg(x, y):
   xfull = np.stack([x]*len(xx),axis=-1)
   yfull = np.stack([y]*len(xx),axis=-1)
   return np.sum((xfull - xx)**2 + (yfull - yy)**2, axis=-1)
现在可以使用标量和数组。但它看起来像一团乱,很难阅读

有更好的办法吗

鉴于:

我的第一个问题是:

这是用标量x和y写的? xx和yy是什么?你说的是一维数组。一样长? 为什么它们不是参数?因为在这种情况下,它们是固定的? 换言之,这将以常量偏移xx和yy,并取它们的平方和,返回单个值? 我的下一步是探索这个表达的“广播”限制。例如,它运行于可以在xx-x中使用的任何x。它可以是0d数组、单元素1d数组、与xx形状相同的数组,或者任何可以用xx“广播”的数组。这就是彻底理解“广播”的关键所在

g(1,2)
g(xx,xx)
g(xx[:,None],yy[None,:])
xx xx[:,无]虽然生成2d数组。np.sum作为书面形式,取所有值的和,即一个平坦值。你的gg建议你在最后一个轴上求和。如果是这样的话,就把它放在g中

在gg中使用stack会产生:

In [101]: xx
Out[101]: array([0, 1, 2, 3, 4])
In [103]: np.stack([np.arange(3)]*len(xx), axis=-1)
Out[103]: 
array([[0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2]])
我会把它写成x[:,无]

这不适用于标量x;但这是真的

xx-np.asarray(x)[...,None]
np.array或np.asarray通常用作numpy函数的开头,以适应标量或列表输入。。。在处理数量可变的维度时,此功能非常方便。重塑…、-1和[…,无]广泛用于扩展或概括尺寸


通过查看numpy函数的Python代码,我学到了很多。我也从多年的MATLAB工作中学到了关于尺寸的迂腐。跟踪预期和实际阵列形状。它有助于使用将突出显示错误的测试形状。使用2,3数组而不是模糊的3,3数组进行测试。

gg是您想要在数据上使用的实际函数,还是您正在寻找对数据操作任何通用函数/操作集的方法?另外,你的gg似乎不适用于1D输入。那么,是…对您的数据操作任何通用函数/操作集吗?或者可能只是一种编写函数的规范方法,因此,给定一些g,可能我必须手动编写gg,但编写gg应该不会太难。。。我认为gg示例在1D输入上做得很好;非常感谢。我想我已经学会了更仔细地阅读这些文件了。。。并且np.newaxis aka None索引非常方便。尺寸为1且不向前移动的广播规则使其全部连接在一起。链接:
In [101]: xx
Out[101]: array([0, 1, 2, 3, 4])
In [103]: np.stack([np.arange(3)]*len(xx), axis=-1)
Out[103]: 
array([[0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2]])
In [104]: xx-_
Out[104]: 
array([[ 0,  1,  2,  3,  4],
       [-1,  0,  1,  2,  3],
       [-2, -1,  0,  1,  2]])
In [105]: xx-np.arange(3)[:,None]
Out[105]: 
array([[ 0,  1,  2,  3,  4],
       [-1,  0,  1,  2,  3],
       [-2, -1,  0,  1,  2]])
xx-np.asarray(x)[...,None]