广播的原则
如果两个数组的后缘维度(从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失维度和(或)轴长度为1的维度上进行。
在上面的对arr每一列减去列平均值的例子中,arr的后缘维度为3,arr.mean(0)后缘维度也是3,满足轴长度相符的条件,广播会在缺失维度进行。
这里有点奇怪的是缺失维度不是axis=1,而是axis=0,个人理解是缺失维度指的是两个arr除了轴长度匹配的维度,在上面的例子中,正好是axis=0。这块欢迎指正
arr.mean(0)沿着axis=0广播,可以看作是把arr.mean(0)沿着竖直方向复制4份,即广播的时候arr.mean(0)相当于一个shape=(4,3)的数组,数组的每一行均相同,均为arr.mean(0)
为了了解这个原则,首先我们来看一组例子:
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
|
# 数组直接对一个数进行加减乘除,产生的结果是数组中的每个元素都会加减乘除这个数。 In [ 12 ]: import numpy as np In [ 13 ]: a = np.arange( 1 , 13 ).reshape(( 4 , 3 )) In [ 14 ]: a * 2 Out[ 14 ]: array([[ 2 , 4 , 6 ], [ 8 , 10 , 12 ], [ 14 , 16 , 18 ], [ 20 , 22 , 24 ]]) # 接下来我们看一下数组与数组之间的计算 In [ 17 ]: b = np.arange( 12 , 24 ).reshape(( 4 , 3 )) In [ 18 ]: b Out[ 18 ]: array([[ 12 , 13 , 14 ], [ 15 , 16 , 17 ], [ 18 , 19 , 20 ], [ 21 , 22 , 23 ]]) In [ 19 ]: a + b Out[ 19 ]: array([[ 13 , 15 , 17 ], [ 19 , 21 , 23 ], [ 25 , 27 , 29 ], [ 31 , 33 , 35 ]]) In [ 20 ]: c = np.array([ 1 , 2 , 3 ]) In [ 21 ]: a + c Out[ 21 ]: array([[ 2 , 4 , 6 ], [ 5 , 7 , 9 ], [ 8 , 10 , 12 ], [ 11 , 13 , 15 ]]) In [ 22 ]: d = np.arange( 10 , 14 ).reshape(( 4 , 1 )) In [ 23 ]: d Out[ 23 ]: array([[ 10 ], [ 11 ], [ 12 ], [ 13 ]]) In [ 24 ]: a + d Out[ 24 ]: array([[ 11 , 12 , 13 ], [ 15 , 16 , 17 ], [ 19 , 20 , 21 ], [ 23 , 24 , 25 ]]) # 从上面可以看出,和线性代数中不同的是,m*n列的m行的一维数组或者n列的一维数组也是可以计算的。 |
这是为什么呢?这里要提到numpy的广播原则:
如果两个数组的后缘维度(从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失维度和(或)轴长度为1的维度上进行。
在上面的代码中,a的维度是(4,3),c的维度是(1,3);d的维度是(4,1)。所以假设有两个数组,第一个的维度是(x_1, y_1, z_1),另一个数组的维度是(x_2, y_2, z_2),要判断这两个数组能不能进行计算,可以用如下方法来判断:
1
2
3
4
5
6
7
8
9
10
|
if z_1 = = z_2 or z_1 = = 1 or z_2 = = 1 : if y_1 = = y_2 or y_1 = = 1 or y_2 = = 1 : if x_1 = = x_2 or x_1 = = 1 or x_2 = = 1 : 可以运算 else : 不可以运算 else : 不可以运算 else : 不可以运算 |
这里需要注意:(3,3,2)和(3,2)是可以运算的,因为对于二维数组(3,2)也可以表示为(1,3,2),套用上述的规则是完全适用的,同理:(4,2,5,4)和(2,1,4)也是可以进行运算的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://segmentfault.com/a/1190000016460482