如果我有两个看起来像这样的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相比,它是否可以在后台有效地实现。
答案 0 :(得分:3)
要回答问题的第一部分,b[:, None]
是一种特殊的切片方式,其行为与b[:, np.newaxis]
相同,因为它向数组添加了长度为1的轴。
>>> b.shape
(2,)
>>> b[:, None].shape
(2, 1)
此行为记录在numpy
docs [1]中,重点是我的:
newaxis
对象可用于所有切片操作中,以创建长度为一的轴。newaxis
是None
的别名,可以使用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]
此处c
,d
和e
具有相同的值!