← 返回首页
数组的广播机制
发表时间:2024-01-16 02:02:53
数组的广播机制

数组的广播机制

1.数组的广播机制

Numpy可以转换这些形状不同的数组,使它们都具有相同的大小,然后再对它们进行运算。下面是广播示意图:

术语广播是指 NumPy 在算术运算期间处理不同形状的数组的能力。对数组的算术运算通常在 相应的元素上进行。如果两个阵列具有完全相同的形状,则这些操作被无缝执行。

如果两个数组的维数不相同,则元素到元素的操作是不可能的。然而,在 NumPy 中仍然可以对形状不相似的数组进行操作,因为它拥有广播功能。较小的数组会广播到较大数组的大小,以便使它们的形状可兼容。

如果满足以下条件之一,那么数组被称为可广播的。

广播的规则:

  1. 如果两个数组的维度数不相同,那么小维度数组的形状将会在最左边补 1。
  2. 如果两个数组的形状在任何一个维度上都不匹配,那么数组的形状会沿着维度 为 1 的维度扩展以匹配另外一个数组的形状。
  3. 如果两个数组的形状在任何一个维度上都不匹配并且没有任何一个维度等于 1, 那么会引发异常。

实例:

import numpy as np

# 形状相同的广播
a = np.ones((3, 3))
print(a)
print(a.ndim)
print(a.shape)

print(a+a)
# 相同维度,但其中某一个或多个维度长度为 1 的广播:
b = np.arange(3).reshape(1, 3)
print(b)
print(b.ndim)
print(b.shape)

print(a+b)

c = np.arange(3).reshape(3, 1)
print(c)
print(c.ndim)
print(c.shape)
print(a+c)

# 较少的维度,默认在其前面追加长度为1的维度
d = np.arange(3)
print(d)
print(d.ndim)
print(d.shape)
print(a+d)

# 如果是标量的话,会广播整个数组上
print(a*3)
print(b*3)
print(c*3)

arr1 = np.arange(0, 40, 10)
print(arr1)
print(arr1.shape)

arr2 = np.array([0, 1, 2])
print(arr2)
print(arr2.shape)

#将数组arr1转换为4行1列
arr1=arr1[:,np.newaxis]
print(arr1)
print(arr1.shape)

#数组arr1+arr2,并查看形状
print(arr1+arr2)
print((arr1+arr2).shape)

#现在尝试模拟一个广播的方式, 把arr1中的每个元素拉长三倍
arr1=np.concatenate([arr1,arr1,arr1],axis=1)
print(arr1)

#arr2中的元素拉长4倍
arr2=np.concatenate([arr2,arr2,arr2,arr2]).reshape(4,-1)
print(arr2)

#arr1+arr2
print(arr1+arr2)

#这里我们就能看出,我们将数组扩展到较大的维度再进行通用函数操作,和我们直接进行广播操作结果是一样的。


[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
2
(3, 3)
[[2. 2. 2.]
 [2. 2. 2.]
 [2. 2. 2.]]
[[0 1 2]]
2
(1, 3)
[[1. 2. 3.]
 [1. 2. 3.]
 [1. 2. 3.]]
[[0]
 [1]
 [2]]
2
(3, 1)
[[1. 1. 1.]
 [2. 2. 2.]
 [3. 3. 3.]]
[0 1 2]
1
(3,)
[[1. 2. 3.]
 [1. 2. 3.]
 [1. 2. 3.]]
[[3. 3. 3.]
 [3. 3. 3.]
 [3. 3. 3.]]
[[0 3 6]]
[[0]
 [3]
 [6]]
[ 0 10 20 30]
(4,)
[0 1 2]
(3,)
[[ 0]
 [10]
 [20]
 [30]]
(4, 1)
[[ 0  1  2]
 [10 11 12]
 [20 21 22]
 [30 31 32]]
(4, 3)
[[ 0  0  0]
 [10 10 10]
 [20 20 20]
 [30 30 30]]
[[0 1 2]
 [0 1 2]
 [0 1 2]
 [0 1 2]]
[[ 0  1  2]
 [10 11 12]
 [20 21 22]
 [30 31 32]]

2. 数组与数字运算

import numpy as np

#生成3行5列 值为0-5随机整数的数组
a1 = np.random.randint(0,5,size=(3,5))
print(a1)
#数组中的所有元素都乘2
print(a1*2)
#数组中所有的元素只保留2位小数
a2 =np.random.random((3,3))
print(a2)
print(a2.round(2))

[[1 2 0 0 1]
 [0 0 2 0 4]
 [0 3 4 0 4]]
[[2 4 0 0 2]
 [0 0 4 0 8]
 [0 6 8 0 8]]
[[0.23908068 0.47164088 0.02494872]
 [0.11508108 0.67393144 0.27543608]
 [0.93289384 0.0030417  0.78057539]]
[[0.24 0.47 0.02]
 [0.12 0.67 0.28]
 [0.93 0.   0.78]]

3.数组与数组运算

#数组形状一致时 各个元素相加减(满足数组广播机制)
a1 = np.random.randint(0,5,size=(3,5))
a2 = np.random.randint(0,5,size=(3,5))
print(a1)
print(a2)
print(a1+a2)
#形状不一致的数组不能相加减(不满足数组广播机制)
a3 = np.random.randint(0,5,size=(3,4))
print(a3)
#a1+a3 报错
#print(a1+a3)

#两个数组行数相同 ,其中一个数组列数为1(满足数组广播机制)
a4 = np.random.randint(0,5,size=(3,1))
print(a4)
print(a1+a4)

#两个数组列数相同 ,其中一个数组行数为1(满足数组广播机制)
a5 = np.random.randint(0,5,size=(1,5))
print(a5)
print(a1+a5)

[[2 1 3 4 0]
 [1 2 0 0 2]
 [0 0 3 1 4]]
[[2 0 0 1 2]
 [3 2 2 1 1]
 [2 1 4 2 4]]
[[4 1 3 5 2]
 [4 4 2 1 3]
 [2 1 7 3 8]]
[[2 4 1 3]
 [4 4 2 2]
 [1 1 3 0]]
[[3]
 [4]
 [0]]
[[5 4 6 7 3]
 [5 6 4 4 6]
 [0 0 3 1 4]]
[[0 3 0 4 1]]
[[2 4 3 8 1]
 [1 5 0 4 3]
 [0 3 3 5 5]]

小结: 1. 数组和数字直接进行运算是没有问题的。 2. 两个shape相同的数组是可以进行运算的。 3. 如果两个shape不同的数组,想要进行运算,那么需要看它们是否满足广播原则。