「numpy」numpy ndarray 广播机制、数组间的运算

42 阅读4分钟

numpy ndarray 数组间的运算、广播机制

【目录】

  • 数组与数的运算
  • 数组与数组的运算
  • 广播机制

一、数组与数的运算

 x = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
 y = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
 print(x * 2)
 # 返回结果
 [[ 2  4  6  8 10]
  [12 14 16 18 20]]
 ​
 print(y * 2)
 # 返回结果
 [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]

1.1 公共函数操作

对应原生Python则进行的合并或者复制的功能,但是合并需要满足“同一类”

运算符描述支持的容器类型
+合并字符串、列表、元组
*****复制字符串、列表、元组
in元素是否存在字符串、列表、元组、字典
not in元素是否不存在字符串、列表、元组、字典

1.2 np.ndarray是进行数组运算

对 np.ndarry 进行的是数组的操作,对数组里面的每个数进行运算,需要满足广播机制

二、数组与数组的运算

2.1 数组维数不匹配

 x = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
 y = np.array([[1, 2, 3], [4, 5, 6]])
 print(x + y)
 ​
 Traceback (most recent call last):
   File "D:\hello,numpy.py", line 5, in <module>
     print(x + y)
           ~~^~~
 ValueError: operands could not be broadcast together with shapes (2,5) (2,3) 

发生了报错,很明显这两个数组的维数不匹配,实际运算也没有意义


2.2 数组维数匹配

 x = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
 y = np.array([[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]])
 print(x + y)
 ​
 # 返回结果
 [[ 3  6  9 12 15]
  [18 21 24 27 30]]

运行正确

2.3 数组维数半匹配

 x = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
 y = np.array([[2], [12]])
 print(x + y)
 ​
 # 返回结果
 [[ 3  4  5  6  7]
  [18 19 20 21 22]]

tips : 以上结果基于广播机制的原理

三、广播机制

数组在进行矢量化运算时,要求数组的形状是相等的。当形状不相等的数组执行算术运算的时候,就会出现广播机制,该机制会对数组进行扩展,使数组的shape属性值一样,才可以进行矢量化运算

菜鸟教程

3.1 广播的规则

  • 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 “1” 补齐。
  • 输出数组的形状是输入数组形状的各个维度上的最大值。
  • 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
  • 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。

3.2 简单理解

对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略)

  • 数组拥有相同形状。
  • 当前维度的值相等。
  • 当前维度的值有一个是 1。
 a = np.array([[0, 0, 0], [10, 10, 10], [20, 20, 20], [30, 30, 30]]) # 4 * 3矩阵
 b = np.array([0, 1, 2]) # 1 * 3 矩阵
 print(a + b)
 ​
 # 返回结果
 [[ 0  1  2]
  [10 11 12]
  [20 21 22]
  [30 31 32]]

广播机制示例.png

3.3 一些简单的例子

  • (4, 1)和(3,)组合
  • 也就是二维和一位的组合情况,可以类似对应高维和低维
 a = np.array([[0],[1],[2],[3]])
 b = np.array([1,2,3])
 print(a + b)
 ​
 # 返回结果
 [[1 2 3]
  [2 3 4]
  [3 4 5]
  [4 5 6]]

上述的拓展情况

 a = [[0 0 0]
      [1 1 1]
      [2 2 2]
      [3 3 3]]
 ​
 b = [[1 2 3]
      [1 2 3]
      [1 2 3]]

3.4 拓展技巧

  • 根据shape,从右至左依次对比维数,满足下面两个条件之一即可
  • 条件1:当前维度的值相等。
  • 条件2:当前维度的值有一个是 1。

比如 (4,1) 和 (3,),等价与(4,1)和(1,3)

最右边,1和3,满足条件2,维度数1向维度数3看齐。则(4,1)变成 (4,3)

最左边,4和1,满足条件2,维度数1向维度数4看齐。则(1,3)变成 (4,3)

(4,1)变成 (4,3),则进行——列拓展,复制第一列至其余各列

(1,3)变成 (4,3),则进行——行拓展,复制第一行至其余各行