【问题标题】:numpy dot or einsum with arbitrary operator带有任意运算符的 numpy dot 或 einsum
【发布时间】:2016-10-31 21:24:40
【问题描述】:

我想使用np.dot 或(最好)np.einsum 之类的东西来有效地执行它们的相同功能,但使用备用ufunc 而不是np.multiply。例如,考虑这两个数组:

>>> a
array([[0, 1],
       [1, 1],
       [1, 0]])
>>> b
array([[0, 0],
       [1, 0],
       [1, 0],
       [0, 0]])

现在假设我想计算a 的每一行中元素的数量等于b 的每一行中的相应元素。我希望能够执行以下等效操作(注意:下面的输出是虚构的,但值是我希望看到的):

>>> np.dot(a, b.T, ufunc=np.equal)
array([[1, 0, 0, 1],
       [0, 1, 1, 0],
       [1, 2, 2, 1]])

有没有办法做到这一点?

【问题讨论】:

  • 数组是否总是只有0s 和1s?
  • 在我的具体情况下,是的。但我也很好奇更一般情况下的答案。

标签: numpy numpy-ufunc


【解决方案1】:

您可以将 Divakar 答案中的广播与numexpr 一起使用:

numexpr.evaluate('sum(1*(a == b), axis=2)', {'a': a[:,None]})

1*()a workaround. 我已经确认这不会分配大的临时数组。

【讨论】:

  • 我认为numexpr 不支持切片,很高兴知道它支持!
  • 嗯,这只是 local_dict 参数,切片仍然发生在 Python 中:-)
  • 我认为这将是最好的,因为它避免了临时阵列存储。为 @Divakar 投票,以获得优雅的 numpy-only 解决方案。
【解决方案2】:

您可以使用broadcasting 来解决此类匹配计数问题 -

(a[:,None] == b).sum(2)

示例运行 -

In [36]: a
Out[36]: 
array([[0, 1],
       [1, 1],
       [1, 0]])

In [37]: b
Out[37]: 
array([[0, 0],
       [1, 0],
       [1, 0],
       [0, 0]])

In [38]: (a[:,None] == b).sum(2)
Out[38]: 
array([[1, 0, 0, 1],
       [0, 1, 1, 0],
       [1, 2, 2, 1]])

如果您真的想使用 np.einsumnp.equal,这里有一种方法可以塑造早期的方法,从而为我们提供所需的结果 -

np.einsum('ijk->ij',np.equal(a[:,None],b).astype(int))

【讨论】:

  • 这确实产生了预期的结果。一个缺点是(a[:,None] == b)np.equal(a[:,None],b) 的临时存储。在示例中,中间数组的形状为(3, 4, 2),但实际上,最后一个维度可能很大,这就是我希望避免使用它的原因。
  • @bogatron 对于实际用例,ab 的典型形状是什么?
  • 每个数组的第一个维度在 10**5 左右。第二个维度(求和发生的地方)是 64 或 128。
  • @bogatron 匹配的布尔数组 a[:,None] == b 因为是布尔值,所以 8x 比 int/float 数组更有效。即使遇到内存问题,我们也可以在 cols 中运行一个循环并执行类似 a[:,i,None]==b[:,i] 之类的操作,并在每次迭代时累积。除此之外,我没有想法。
  • @Divakar - numexpr ;-) 但你必须使用1*(a[:,None] == b),如mentioned here
【解决方案3】:

numpy github 上有一个老问题,要求对einsum 进行概括,以允许使用其他功能。当前版本只是实现了产品的总和。据我所知,没有人接手这个项目。

几年前,我修补了einsum,修复了“...”符号的处理。所以我很清楚它是如何实现的;并且可能会调整我的 Python/cython 模拟器以添加此功能。实际的einsum 代码是用c 编写的。

我的猜测是,如果您不喜欢 Divakar 的方法,则必须使用 cython 编写自己的版本。

【讨论】:

  • 接受的答案可以满足我的需要,但很高兴看到 einsum 支持此功能。我发现它比许多操作的替代解决方案运行得更快。
猜你喜欢
  • 2023-03-20
  • 1970-01-01
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
相关资源
最近更新 更多