【问题标题】:Perform element-wise subtract from the vector从向量中执行逐元素减法
【发布时间】:2021-06-09 18:17:37
【问题描述】:

我需要从以下等式计算向量的元素减去的总和:

sum(y(i) - y(j)) at i!=j

y 以 numpy 数组的形式给出
一种选择是遍历双循环:

dev = 0

for i in range(y.shape[0]):
   for j in range(y.shape[0]):
      if i == j:
         continue
      dev += y[i, j] - y[i, j]

这绝对不是最佳解决方案。
如何使用带有 numpy 向量的向量化操作对其进行优化?

【问题讨论】:

  • y[i, j] - y[i, j] 将始终为 0... 或 nan。你到底想要什么?一种笛卡尔减法? y 的职业很大吗?否则,您可以做的事情是np.abs(y[:, None] - y[None, :]).sum()/2
  • 这可能是一个不错的code golf

标签: python numpy


【解决方案1】:

y 是平的,例如

>>> y = np.arange(10)
>>> y
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> y.shape
(10,)

您可以按如下方式计算“笛卡尔差”


>>> m = np.abs(y[:, None] - y[None, :])
>>> m
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
       [1, 0, 1, 2, 3, 4, 5, 6, 7, 8],
       [2, 1, 0, 1, 2, 3, 4, 5, 6, 7],
       [3, 2, 1, 0, 1, 2, 3, 4, 5, 6],
       [4, 3, 2, 1, 0, 1, 2, 3, 4, 5],
       [5, 4, 3, 2, 1, 0, 1, 2, 3, 4],
       [6, 5, 4, 3, 2, 1, 0, 1, 2, 3],
       [7, 6, 5, 4, 3, 2, 1, 0, 1, 2],
       [8, 7, 6, 5, 4, 3, 2, 1, 0, 1],
       [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]])

最后

>>> dev = m.sum()/2
>>> dev
165.0

【讨论】:

    【解决方案2】:

    使用itertoolscombination:

    import itertools
    sum([x2 - x1 for x1, x2 in itertools.combinations(y, 2)])
    

    使用np.subtract.outer

    np.abs(np.subtract.outer(y,y)).sum()/2
    

    时间对比:

    方法一(使用Itertools):

    挂起时间:18.9 秒

    方法二(利用 KeepAlive 的笛卡尔差):

    持续时间:491 毫秒

    方法3(使用np.subtract.outer):

    持续时间:467 毫秒

    【讨论】:

    • 您的表现结果显然取决于您采用的y 的示例,即他们的~.size。可能会很好地明确这一点。撇开itertools 的情况不谈,否则我真的不明白这种比较的意义,准谬误。
    • @keepAlive:是的,我拿了 10K 分。是的,最后两个几乎相同。
    • 我想,比如说,5000 点,天真的方法更快?为什么不显示呢?嗯……
    • @keepAlive:天真的方法会更快吗?让我也添加天真的解决方案。
    • 从那以后你改变了你的答案;)(虽然不是计算时间??)在此之前,你有三角形索引的额外成本。从此以后,您的答案对于所有尺寸确实可能更快,因为您没有我的方法所需的垂直/水平重塑成本。
    猜你喜欢
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    相关资源
    最近更新 更多