使用Numpy广播将不同形状的矩阵或数组加减乘除

首先先强调一点很容易混淆的点:

  • 一个shape为(4,)的np.array其实是一行!!一行4列!!而不是4行每行1个元素!!
  • 上面说的这个👆array假设叫x,那么想把x加到一个shape为(9,4)的matrix上是可以直接加的,如果想要把x加到一个shape为(4,9)的matrix上要先转置!而且不能直接转置,因为一个array的转置的形状是不会变的。。正确做法是:先把x变成一个数组,之后再对这个数组转置,这时候x的形状就已经变成了(4,1),成了真正的4行每行1列,也就可以把它加到shape为(4,9)的matrix上去喽~

在我们所以Numpy的过程中,常常会有大量的矩阵数组需要运算,但是不同类型的Numpy怎样进行加减乘除呢?这就要用到我们Numpy的广播。

快速入门Numpy广播

Numpy的广播既是在2个不同的矩阵运算过程中,Numpy将较小的数组拉伸成较大数组的形状(shape),然后Numpy加减乘除不同矩阵的加减乘除运算,好的没我们来看一下一个例子:

1
2
3
a = np.array([3.0, 4.0, 5.0, 6.0])
b = np.array([3.0, 4.0])
print a * b

将会出现这样的错误ValueError: operands could not be broadcast together with shapes (3,), (2,), 在这里,我们只需要将a转换成一个2维数组,即可进行广播,如:

1
2
3
4
5
6
7
8
9
10
11
a = np.array([3.0, 4.0, 5.0, 6.0])
b = np.array([3.0, 4.0])
a.shape = (2,2)
print a * b
# 输出:[[ 3. 4.] [ 5. 6.]] [[ 9. 16.] [ 15. 24.]]

# 例外一个例子
x = np.arange(4)
z = np.ones((3,4))

print x + z

好的到这里其实主要我们已经将完了所有的内容,如果你想要了解更多,可以查看下面的内容,其实都是一些描述性的,我觉得不是那么有必要看

什么是Numpy广播

广播术语描述了在算术运算过程中numpy如何处理具有不同形状的数组。受到某些约束,较小的数组是跨越较大阵列的“广播”,以便它们具有兼容的形状。广播提供了一种向量化数组操作的方法,以便循环发生在C而不是Python中。它不会造成不必要的数据副本,通常会导致高效的算法实现。然而,广播是一个坏主意,因为它导致低效的内存使用减慢了计算的情况。

NumPy操作通常是在逐个元素的基础上完成的。在最简单的情况下,两个阵列必须具有完全相同的形状,如下例所示:

1
2
3
4
a = np.array([3.0, 4.0, 5.0])
b = np.array([3.0, 3.0, 3.0])
print a * b
# 输出:[ 9. 12. 15.]

当数组的形状满足某些限制时,NumPy的广播规则放宽了这个约束。当操作中组合数组和标量值时,会发生最简单的广播示例:

1
2
3
4
a = np.array([3.0, 4.0, 5.0])
b = 3.0
print a * b
# 输出:[ 9. 12. 15.]

上面2个例子的结果相同,在计算期间,我们可以看作b被拉伸成与a相同的形状,新元素 b只是原始标量的副本。拉伸类比只是概念性的。NumPy足够聪明才能使用原始的标量值,而无需实际复制,因此广播操作尽可能地作为记忆和计算效率。

第二个示例中的代码比第一个示例中的代码更有效,因为广播在乘法期间移动较少的内存(b是标量而不是数组)。

一般广播规则

在两个数组上运行时,NumPy将元素的形状进行比较。它从尾随的维度开始,并向前推进。两个尺寸兼容

  • 他们是平等的
  • 其中一个是1

如果不满足这些条件, 则抛出异常,表示阵列具有不兼容的形状。结果数组的大小是输入数组的每个维度的最大大小。ValueError: frames are not aligned 接下来我们看一下一些具体的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
>>> x = np.arange(4)
>>> xx = x.reshape(4,1)
>>> y = np.ones(5)
>>> z = np.ones((3,4))

>>> x.shape
(4,)

>>> y.shape
(5,)

>>> x + y
<type 'exceptions.ValueError'>: shape mismatch: objects cannot be broadcast to a single shape

>>> xx.shape
(4, 1)

>>> y.shape
(5,)

>>> (xx + y).shape
(4, 5)

>>> xx + y
array([[ 1., 1., 1., 1., 1.],
[ 2., 2., 2., 2., 2.],
[ 3., 3., 3., 3., 3.],
[ 4., 4., 4., 4., 4.]])

>>> x.shape
(4,)

>>> z.shape
(3, 4)

>>> (x + z).shape
(3, 4)

>>> x + z
array([[ 1., 2., 3., 4.],
[ 1., 2., 3., 4.],
[ 1., 2., 3., 4.]])

广播提供了一种方便的方式来拍摄两个阵列的外部产品(或任何其他外部操作)。以下示例显示了两个1-d数组的外部加法运算:

1
2
3
4
5
6
7
>>> a = np.array([0.0, 10.0, 20.0, 30.0])
>>> b = np.array([1.0, 2.0, 3.0])
>>> a[:, np.newaxis] + b
array([[ 1., 2., 3.],
[ 11., 12., 13.],
[ 21., 22., 23.],
[ 31., 32., 33.]])

这里,newaxis索引操作符插入一个新轴a,使其成为一个二维4x1数组。将4x1阵列与b形状组合(3,),产生一个4x3数组。

原文出处: 使用Numpy广播将不同形状的矩阵或数组加减乘除 - pytorch中文网