当在不同维数的数组间进行运算时,其中之一或两个都要broadcast以使维数相配。Numpy的实现者关注的是N维对象的复杂功能,broadcasting提供了强有力的支持,但也导致了一些术语上的混淆冲突。
rank
在Numpy文档中,“rank”一词指数组的维数,它与数组本身的状态无关(如线性独立的行数、列数)。一个列向量的rank总是1,一个矩阵的rank总是2,一个N维数组的rank总是N。在传统的线性代数中,rank refers to related numbers within a matrix column or row.
broadcasting
指rank小的数组被复制或扩展,为了能与rank大的数组起作用。
数组与标量
import numpy as np
a=np.array([[1,2],[3,4]])
b=1
a+b
array([[2, 3],
[4, 5]])
两个操作数的rank不匹配,标量被broadcast以使运算能够完成。b被转成2by2的数组,每个元素的值都是b
数组与数组
a=np.array([[1,2,3],[4,5,6]])
b=np.array([[1,2],[3,4],[5,6]])
a+b
Traceback (most recent call last):
ValueError: operands could not be broadcast together with shapes (2,3) (3,2)
a
array([[1, 2, 3],
[4, 5, 6]])
c=np.array([7,8,9])
c
array([7, 8, 9])
a+c
array([[ 8, 10, 12],
[11, 13, 15]])
为什么上面的2种情况第一种不可以而第二种可以?
第二种情况中a的rank是2,c的rank是1,这种情况下,每个维度的长度会被比较。
a.shape
(2,3)
c.shape
(3,)
当两个rank不同的数组进行运算,每个axis的长度从最右开始比较。a和c的最右axis的长度都是3,we are in business.
有一个例外情况,当比较每个axis时,如果其中之一的长度是1,broadcasting也能进行。
z=np.array([1,2])
z.shape
(2,)
v=np.array([[3],[4],[5]])
v.shape
(3,1)
z+v
array([[4, 5],
[5, 6],
[6, 7]])
数组z被扩展为(3,2),数组v被扩展为(3,2),两个操作数都进行了broadcasting
This only occurs when the axis size of one of the multiarrays has the value of one.
why broadcasting
Broadcasting是Numpy运算中固有的,缺少了它运算会变得困难。考虑要将数组中的每一个元素值都加1,或乘以5,如果没有broadcasting
a=np.ones((2,3,4))
tmp=a.shape
for i in range(tmp[0]):
for j in range(tmp[1]):
for k in range(tmp[2]):
a[I,j,k]=a[I,j,k]*5
使用broadcasting
a=np.ones((2,3,4))*5
在更复杂的情况下,如矩阵中的每一行乘以一个向量,没有broadcasting,向量首先被复制成一个矩阵,之后可以进行运算。有broadcasting,复制的阶段可以省略。当数组很大时,可以节省时间和空间。