numpy广播机制

NumPy的广播机制

文章目录

  • NumPy的广播机制
    • Broadcast
    • 最简单的广播机制
    • 稍微复杂的广播机制
    • 广播机制到底做了什么
    • 一个典型的错误案例
    • 一个正确的经典示例
    • 一种更便捷的计算方式

Broadcast

  • 广播是numpy对不同形状(shape)的数组进行数值计算的方式,对数组的算术运算通常在相应的元素上进行。如果两个数组a和b形状相同,即a.shape==b.shape为True时,那么a*b的结果就是a与b数组的对应位相乘。这要求维数相同,并且各维度的长度相同。

    例如:

    import numpy as np
    
    a = np.array([1, 2, 3])
    b = np.array([4, 5, 6])
    print(a*b)
    
    
    # 运行结果为array([4,10,18])
    

    最简单的广播机制

    当一个常数与一个array对象相乘时,这时就会触发numpy的广播机制

    import numpy as np
    
    a = np.array([1, 2, 3])
    print(a*2)
    
    
    # 运行结果为array([2,4,6])
    

    或许你把这当作理所应当,但是这就是通过广播机制来实现的。

    image-20220531203320430

稍微复杂的广播机制

import numpy as np
a = np.array([[0, 0, 0],
              [10, 10, 10],
              [20, 20, 20],
              [30, 30, 30]])
b = np.array([1, 2, 3])
print(a+b)

输出结果是:

array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23],
       [31, 32, 33]])

初学者可能认为这样的运算会报错,但是这的确是正确的,原因还是广播机制

广播机制到底做了什么

我们观察上面这个稍显复杂的例子:

a.shape=(4,3)b.shape=(1,3),两个矩阵axis=1的数据宽度是相同的,但是axis=0的数据宽度不一样,并且b.shape[0]=1,这就是广播机制的触发条件,这时numpy会把b沿axis=0的方向复制4份,即形状变成(4, 3),与a的一致,接下来就是对应位相加即可。

如下图:

image-20220531205124124

一个典型的错误案例

image-20220531214301106

import numpy as np
a = np.array([[0, 0, 0],
              [10, 10, 10],
              [20, 20, 20],
              [30, 30, 30]])
b = np.array([0, 1, 2, 3])
a+b

提示无法进行广播:

numpy广播机制_第1张图片

能否广播必须从axis的最大值向最小值看去,依次对比两个要进行运算的数组的axis的数据宽度是否相等,如果在某一个axis下,一个数据宽度为1,另一个数据宽度不为1,那么numpy就可以进行广播;但是一旦出现了在某个axis下两个数据宽度不相等,并且两者全不为1的状况,就无法广播。

一个正确的经典示例

import numpy as np
a = np.arange(6).reshape((2, 3, 1))
b = np.arange(6).reshape((1, 3, 2))
print(a)
print(b)
print(a+b)
print((a+b).shape)

结果:

a是:
array([[[0],
        [1],
        [2]],

       [[3],
        [4],
        [5]]])
        
b是:
array([[[0, 1],
        [2, 3],
        [4, 5]]])
        
a+b是:
array([[[ 0,  1],
        [ 3,  4],
        [ 6,  7]],

       [[ 3,  4],
        [ 6,  7],
        [ 9, 10]]])

运算过程是:

  • 1不等于2,所以对a的axis=2进行广播,a变为

    array([[[0,0],
            [1,1],
            [2,2]],
    
           [[3,3],
            [4,4],
            [5,5]]])
    
  • axis=1时3等于3,不进行广播

  • axis=0时,2不等于1,所以对b的axis=0进行广播,b变为:

    array([[[0, 1],
            [2, 3],
            [4, 5]],
      
           [[0, 1],
            [2, 3],
            [4, 5]]])
    
  • 最后a、b的shape变为一样,运算结果即为:

    array([[[ 0,  1],
            [ 3,  4],
            [ 6,  7]],
    
           [[ 3,  4],
            [ 6,  7],
            [ 9, 10]]])
    

一种更便捷的计算方式

注:np.newaxis表示增加一个数据宽度为1的维度

因此a[:, np.newaxis] = array([[0],[10],[20],[30]])

import numpy as np
a = np.array([0, 10, 20, 30])
b = np.array([0, 1, 2])
a[:, np.newaxis]+b

结果:

array([[ 0,  1,  2],
       [10, 11, 12],
       [20, 21, 22],
       [30, 31, 32]])

广播过程:

numpy广播机制_第2张图片

你可能感兴趣的:(Python,python,矩阵,线性代数)