按需矢量化numpy代码

时间:2017-03-24 13:07:10

标签: numpy

假设我在Python中有一个非常基本的功能:

def f(x, y):
   return x + y

然后我可以用标量,f(1, 5.4) == 6.4或任意(但相同)形状的numpy向量来调用它。例如。这有效:

x = np.arange(3)
y = np.array([1,4,2.3])
f(x, y)

给出一个包含条目1,5,4.3的数组。

但如果f更复杂怎么办?例如,xxyy在这里是1D numpy数组。

def g(x, y):
   return np.sum((xx - x)**2 + (yy - y)**2)

(我赶紧补充一点,我对这个特定 g不感兴趣,但在一般策略中...)然后g(5, 6)工作正常,但如果我想要传递numpy数组,我似乎必须用明确的广播等编写一个非常不同的函数。例如:

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)

现在可以使用标量和数组。但它看起来像一团糟,很难读懂。

  

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

假设:

x

我的第一个问题是:

  • 这是用标量yxx写的?
  • yyxx是什么?你说1d数组。相同的长度?
  • 为什么他们没有参数?因为在这种情况下它们是固定的吗?
  • 在文字方面,这会将yyx按固定金额抵消,并取其正方形的总和,返回单个值?

我的下一步是探索广播'这个表达的极限。例如,它适用于xx-x中可以使用的任何xx。这可能是一个0d数组,一个元素1d数组,一个形状与g(1,2) g(xx,xx) g(xx[:,None],yy[None,:]) 相同的数组,或者其他任何可以广播的数组。用`xx。这是对广播'的透彻理解的地方。是至关重要的。

xx-xx[:,None]

np.sum虽然产生了一个二维数组。所写的gg取所有值的总和,即扁平化。您的g建议您想要在最后一个轴上求和。如果是这样,请将其放在def g(x, y): return np.sum((xx - x)**2 + (yy - y)**2, axis=-1)

stack

您在gg中使用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[:,None]

我会把它写成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]])

x

这不适用于标量xx-np.asarray(x)[...,None] ;但这确实

np.array

np.asarraynumpy通常用作...函数的开头,以容纳标量或列表输入。处理可变数量的维度时,reshape(...,-1)非常方便。 [...,None]numpy广泛用于扩展或概括维度。

通过查看 function parsejson(data) { var temp2 = new Array(); if (data) { $.each(data, function (i, val) { vproductid = data[i].productid; vproductname = data[i].product_name; vexpirydt = data[i].expiry; temp2.push({vproductid,vproductname,vexpirydt}); }); console.log([temp2]); return [temp2]; } } 函数的Python代码,我学到了很多东西。我也从多年的MATLAB工作中学到了关于尺寸的迂腐。跟踪预期和实际的阵列形状。它有助于使用突出错误的测试形状。用(2,3)数组测试而不是模糊(3,3)数组。