2.1.5 NumPy的数组运算
NumPy数组的一大特色就是批量化运算。批量化,就是对一个复杂的对象进行整体操作,而不是对其中的单个元素逐个进行循环操作。显然,这种方式计算效率更高。
1.数组与数值的算术运算
NumPy支持数组和数值之间进行加、减、乘、除、求余、乘方等算术运算。当一个数组与数值进行算术运算时,NumPy是将数组中的每个元素与数值进行对应的算术运算。代码2-12的第1部分展示了NumPy数组与数值的算术运算的一些例子。
2.数组与数组的算术运算
NumPy数组与数组进行运算时,如果两个数组的形状相同,则运算过程为两个数组对应位置的元素进行相应算术运算。如果形状不同,则要利用NumPy的“广播”特性进行计算。广播是指不同形状的数组之间,借助维度相容性完成数值计算的一种特性。例如,在代码2-12中计算a+2时,可以看作广播特性将数值2扩展成了一个和数组a形状相同的数组,即[2,2,2,2,2],然后与数组a进行对应元素的加法操作。
当两个形状不同的数组进行运算时,只要它们的形状“相容”,就可以利用广播特性在两个数组上进行算术运算。代码2-12的第2部分展示一个三维数组与一个二维数组进行乘法广播运算的例子。
代码2-12 NumPy的算术运算例子
import numpy as np # NumPy数组与数值的算术运算的例子 a = np.array([1, 2, 3, 4, 5], dtype = np.int32) b1 = a+2 #算术加 b2 = a*2 #算术乘 b3 = a**2 #算术乘方 # NumPy数组与数组的算术运算的例子 a = np.arange(24).reshape(2, 3, 4) #生成形状为(2,3,4)的三维数组 weight = np.random.random(size = (3, 4)) #生成二维的权重数组 b4 = a*weight #利用广播特性实现数组和数组相乘
上述代码的第2部分,数组a和数组weight的形状分别是(2,3,4)和(3,4),并不一致。但是它们满足形状相容,可以利用广播特性进行算术运算。这里,相容是指参与运算的两个数组,它们的形状从后向前比较时,每一个维度的形状都相同或者其中一个数组的前面一部分维度的形状均为1。
上述代码中的数组相乘计算过程中,数组a和数组weight的最后一维均为4,倒数第2个维度均为3,a的倒数第3个维度为2,但是weight对应的维度缺失。此时,NumPy自动将算术运算时缺失的维度补齐为1,以满足相容条件。在进行乘法运算时,NumPy利用广播特性,将数组weight广播到数组a的第1个维度上,分别与此维度上的两个形状为(3,4)的子数组进行数组相乘。
如果对不满足相容条件的两个数组进行算术运算,程序将报错。