使用'None'进行成对运算的numpy索引

时间:2018-06-28 21:37:48

标签: python numpy numpy-broadcasting numpy-ndarray

如果我有两个看起来像这样的numpy数组

a = np.array([1, 2])
b = np.array([3, 4])

我想添加所有成对组合,我可以轻松做到

c = a + b[:, None]
c
array([[4, 5],
       [5, 6]])

获得 1 + 3 2 + 3 1 + 4 2 + 4

为什么这样做? “无”在做什么?我可以打印出

b[:, None]
[[3]
 [4]]

但是我不确定为什么告诉numpy做成对组合。我也很好奇,与itertools.combinations相比,它是否可以在后台有效地实现。

2 个答案:

答案 0 :(得分:3)

要回答问题的第一部分,b[:, None]是一种特殊的切片方式,其行为与b[:, np.newaxis]相同,因为它向数组添加了长度为1的轴。

>>> b.shape
(2,)
>>> b[:, None].shape
(2, 1)

此行为记录在numpy docs [1]中,重点是我的:

  

newaxis对象可用于所有切片操作中,以创建长度为一的轴。 newaxisNone的别名,可以使用None代替它,并得到相同的结果。

所以现在我们有两个数组:

array([1, 2]) + array([[3],
                       [4]])

将这两个数组相加得出:

array([[4, 5],
       [5, 6]])

其背后的“魔力”是numpy broadcasting[2]This article [3]是开始理解该主题的绝佳资源。


文章的主要内容如下:

numpy 操作通常逐个元素完成,这需要两个数组具有完全相同的形状。但是,如果两个数组都具有相同的尾轴 或尾轴之一等于一个 (在您的情况下就是这种行为),则可以放宽此约束。 )。

在您的情况下,发生广播,因此该操作等效于对以下2x2数组求和:

array([[1, 2],    +  array([[3, 3],
       [1, 2]])            [4, 4]])

由于numpy操作是逐个元素完成的,因此将产生所需的输出:

array([[4, 5],
       [5, 6]])

[1] https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#numpy.newaxis

[2] https://docs.scipy.org/doc/numpy-1.13.0/user/basics.broadcasting.html

[3] http://scipy.github.io/old-wiki/pages/EricsBroadcastingDoc

答案 1 :(得分:1)

您正在做的是添加一个新轴:“列”轴。 b以前没有,所以现在是列向量,将按列添加;它基本上就像是在列中重复,而a在行中重复一样:

a+b[:, None] = [1,2] + [[3], = [[1,2], + [[3],[3],
                        [4]]    [1,2]]    [4],[4]]

这是为什么/为什么:

第一件事:numpy在默认情况下进行逐元素加法和乘法。这意味着如果a=np.array([1,2]),那么a+2=np.array([1+2,2+2])=np.array([3,5])

import numpy as np
A = np.array([[1, 2],
              [3, 4]])
B = np.array([[1,1],
              [0,0]])

在这里A+B是明智的,我们会得到

A+B = [[1+1,2+1], = [[2,3],
       [3+0,4+0]] =  [3,4]]

如果我们转置矩阵B(使用B.T

现在B.T将具有值

B.T= np.array([[1,0],
               [1,0]])

如果这次我们按元素进行操作,则会得到:

A+B.T=[[1, 2]  + [[1,0]  =  [[2,2],
       [3, 4]]    [1,0]]     [4,4]]

要注意的另一件事是(B 换位)

a = np.array([1,2])
B+a = [[1,2], + [[2, 3],
       [1,2]]    [1, 2]]

它也是元素级的,但是在两行中!也就是说,a实际上被“重复”为两行,并逐个添加到B

此外,Numpy docs说,None在切片时是写np.newaxis的另一种方式。在您的情况下,切片中的None选项实际上是在加法之前转置b-向量!

可以通过以下方式获得完全相同的结果

import numpy as np
a = np.array([1, 2])
b = np.array([3, 4])

c=a+b.reshape(2,1)
d=a+b.reshape(-1,1)
e=a+b[:, np.newaxis]

此处cde具有相同的值!