【问题标题】:Populate numpy matrix from the difference of two vectors从两个向量的差中填充 numpy 矩阵
【发布时间】:2012-03-14 15:05:54
【问题描述】:

是否可以从函数构造numpy 矩阵?在这种情况下,函数是两个向量的绝对差:S[i,j] = abs(A[i] - B[j])。一个使用常规 python 的最小工作示例:

import numpy as np

A = np.array([1,3,6])
B = np.array([2,4,6])
S = np.zeros((3,3))

for i,x in enumerate(A):
    for j,y in enumerate(B):
        S[i,j] = abs(x-y)

给予:

[[ 1.  3.  5.]
 [ 1.  1.  3.]
 [ 4.  2.  0.]]

如果有一个看起来像这样的结构会很好:

def build_matrix(shape, input_function, *args)

我可以通过它的参数传递一个输入函数,并保留 numpy 的速度优势。

【问题讨论】:

  • 这是可能的。你试过什么?
  • @Marcin - 如问题所述,我现在正在使用普通的旧 python 方法来填充矩阵。查看 numpy 的文档表明函数 vectorize 可能有用,但我仍然没有看到如何从函数中构造矩阵。如果您能指出我正确的方向(文档方面),我将不胜感激!
  • 这在普通 python 中应该是可能的。您尝试过什么来创建 build_matrix 函数?你肯定有一些东西,但被困在某个地方,而不是希望有人会为你写这一切。
  • @marcin 我认为您误解了这个问题。我一个可行的解决方案,一个不使用numpy(已发布)的解决方案。我在文档中查看,找到了一个从参数创建 numpy 数组的函数,但 没有找到它。我正在 寻找 本地 numpy 调用,以便我可以编写自己的 build_matrix 函数,而不是“让别人为我写这一切”。问题是使用 numpy 的内部矢量化表示时获得的速度。

标签: python numpy


【解决方案1】:

除了@JoshAdel 所建议的,你还可以使用任何numpy ufuncouter method 来在两个数组的情况下进行广播。

在这种情况下,您只需要np.subtract.outer(A, B)(或者,更确切地说,它的绝对值)。

虽然对于这个例子来说任何一个都相当易读,但在某些情况下广播更有用,而在其他情况下使用 ufunc 方法更干净。

无论哪种方式,了解这两个技巧都会很有用。

例如

import numpy as np

A = np.array([1,3,6])
B = np.array([2,4,6])

diff = np.subtract.outer(A, B)
result = np.abs(diff)

基本上,您可以将outeraccumulatereducereduceat 与任何numpy ufunc 一起使用,例如subtractmultiplydivide,甚至像@987654334 这样的东西@等

例如,np.cumsum 等价于 np.add.accumulate。这意味着如果您需要,您可以通过np.divide.accumulate 实现类似cumdiv 的东西。

【讨论】:

  • 谢谢@JoeKington,你知道广播方法和外部方法之间是否有任何内部差异吗?出于实用性,我没有注意到在我的机器上进行小型测试的任何速度差异,所以我想我可以使用任何一个。
  • @JoeKington +1 绝对是另一套很棒的 numpy 技巧来保持袖手旁观。在某些方面,我实际上更喜欢这种方法,因为我发现语法更具描述性。
  • @talonmies 在我的机器上,对于具有 10,100,1000 和 10000 个元素的数组,广播方法和外部方法的时序几乎相同,广播方法获胜的幅度很小。
【解决方案2】:

我建议看看 numpy 的广播功能:

In [6]: np.abs(A[:,np.newaxis] - B)
Out[6]: 
array([[1, 3, 5],
       [1, 1, 3],
       [4, 2, 0]])

http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html

那么你可以简单地把你的函数写成:

In [7]: def build_matrix(func,args):
   ...:     return func(*args)
   ...: 

In [8]: def f1(A,B):
   ...:     return np.abs(A[:,np.newaxis] - B)
   ...: 

In [9]: build_matrix(f1,(A,B))
Out[9]: 
array([[1, 3, 5],
       [1, 1, 3],
       [4, 2, 0]])

这也应该比您的大型数组解决方案快得多。

【讨论】:

  • 这是完美的,对于大 N 有相当大的增益。我会更多地研究广播,谢谢。
  • 为了避免创建包含差异的中间数组numpexpr,可以使用:c = a[:,None]; result = numexpr.evaluate("abs(c - b)")
  • @J.F.Sebastian - 不管它值多少钱,如果你没有安装numexpr,你也可以通过就地取绝对值来避免它。不过,它稍微有点冗长:c = a[:,None]; result = c - b; np.abs(result, result)
猜你喜欢
  • 2014-11-21
  • 2018-09-20
  • 1970-01-01
  • 2021-01-15
  • 1970-01-01
  • 2017-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多