【问题标题】:Numpy: Subtract 2 numpy arrays row wiseNumpy:逐行减去 2 个 numpy 数组
【发布时间】:2017-04-14 12:57:39
【问题描述】:

我有 2 个 numpy 数组 a 和 b,如下所示:

a = np.random.randint(0,10,(3,2))
Out[124]: 
array([[0, 2],
       [6, 8],
       [0, 4]])
b = np.random.randint(0,10,(2,2))
Out[125]: 
array([[5, 9],
       [2, 4]])

我想从 a 中的每一行中减去 b 中的每一行,并且所需的输出是 shape(3,2,2):

array([[[-5, -7],        [-2, -2]],

       [[ 1, -1],        [ 4,  4]],

       [[-5, -5],        [-2,  0]]])

我可以这样做:

print(np.c_[(a - b[0]),(a - b[1])].reshape(3,2,2))

但我需要一个完全矢量化的解决方案或一个内置的 numpy 函数来执行此操作。

【问题讨论】:

  • 我所说的完全矢量化解决方案(之前因式分解是一个错字)的意思是我不想通过像 b[i] 这样的索引来引用数组 b,因为这个数组中的行数可以改变我想要一个解决方案,它总是输出一个形状数组 (3,len(b),2)

标签: python numpy


【解决方案1】:

只需使用np.newaxis(它只是 None 的别名)将单例维度添加到 a,然后让广播完成剩下的工作:

In [45]: a[:, np.newaxis] - b
Out[45]: 
array([[[-5, -7],
        [-2, -2]],

       [[ 1, -1],
        [ 4,  4]],

       [[-5, -5],
        [-2,  0]]])

【讨论】:

  • 这比我的最佳解决方案快 40%。你能更好地解释这里发生了什么吗?有点抽象
  • 这对于大型数组来说内存效率非常低;我想从500 x 3078 数组中减去5000 x 3078 数组,这将占用500 * 3072 * 5000 * 8 / 1e9 = 61.44 千兆字节。
  • 这真的是一个很好的答案。我们甚至可以用标量列表减去向量,得到矩阵:a = np.array([1,2,3,4,5,6])b = np.array([1,2,3])a[:, np.newaxis]-b。导致形状为(6,3)
【解决方案2】:

我不确定什么是完全分解的解决方案,但这可能会有所帮助:

np.append(a, a, axis=1).reshape(3, 2, 2) - b

【讨论】:

  • 感谢您的回答,但请在问题中查看我的 cmets。
【解决方案3】:

使用 np.subtract() 可以节省一点时间,使用 np.concatenate() 可以节省更多时间

import numpy as np
import time

start = time.time()
for i in range(100000):

    a = np.random.randint(0,10,(3,2))
    b = np.random.randint(0,10,(2,2))
    c = np.c_[(a - b[0]),(a - b[1])].reshape(3,2,2)

print time.time() - start

start = time.time()
for i in range(100000):

    a = np.random.randint(0,10,(3,2))
    b = np.random.randint(0,10,(2,2))
    #c = np.c_[(a - b[0]),(a - b[1])].reshape(3,2,2)
    c = np.c_[np.subtract(a,b[0]),np.subtract(a,b[1])].reshape(3,2,2)

print time.time() - start

start = time.time()
for i in range(100000):

    a = np.random.randint(0,10,(3,2))
    b = np.random.randint(0,10,(2,2))
    #c = np.c_[(a - b[0]),(a - b[1])].reshape(3,2,2)
    c = np.concatenate([np.subtract(a,b[0]),np.subtract(a,b[1])],axis=1).reshape(3,2,2)

print time.time() - start

>>>

3.14023900032
3.00368094444
1.16146492958

参考:

confused about numpy.c_ document and sample code

np.c_ 是进行数组连接的另一种方式

【讨论】:

  • 感谢您的回答,但请在问题中查看我的 cmets。
  • 啊,我明白了,这增加了一个转折点。我不确定你在原始操作中分解是什么意思,会思考的;看看我能不能变出什么来。尽管如此,减少 CPU 负载总是一个优点
【解决方案4】:

广播的文档中读到,它说:

在对两个数组进行操作时,NumPy 会比较它们的形状 元素方面。它从尾随维度开始,并按其 前进的道路。两个维度兼容时

they are equal, or
one of them is 1

回到你的情况,你希望结果是形状(3, 2, 2),遵循这些规则,你必须玩弄你的尺寸。 现在是执行此操作的代码:

In [1]: a_ = np.expand_dims(a, axis=0)

In [2]: b_ = np.expand_dims(b, axis=1)

In [3]: c = a_ - b_

In [4]: c
Out[4]: 
array([[[-5, -7],
        [ 1, -1],
        [-5, -5]],

       [[-2, -2],
        [ 4,  4],
        [-2,  0]]])

In [5]: result = c.swapaxes(1, 0)

In [6]: result
Out[6]: 
array([[[-5, -7],
        [-2, -2]],

       [[ 1, -1],
        [ 4,  4]],

       [[-5, -5],
        [-2,  0]]])

In [7]: result.shape
Out[7]: (3, 2, 2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多