- 前言
- numpy数组计算
- broadcasting机制
- shape要求
- broadcast说明
本篇开始记录一些使用numpy时的技巧。
numpy事实上已经成为了python的数据处理包。
不过有的numpy *** 作不大好理解,也容易遗忘。
这里的记录是为了增加记忆。
首先记录一下numpy数组的基础。
numpy的基本数据结构是np.ndarray
,是多维的张量,np.ndarray
由标量构成。
numpy的标量与python内置的数据类型可以混用,不过python的数字标量分为整型与浮点型,而numpy则把整型细分为np.int8, np.uint8, np.int32
等,浮点型细分为np.float32, np.float64
等,此外还有np.bool, np.str_
等类型。
np.ndarray
的几个比较重要的信息为:ndim
维度,shape
形状,size
元素个数,dtype
数据类型。
其中维度等于形状的长度,元素个数等于每个维度的乘积。
可以通过np.array()
将python scalar, list, tuple等转换成np.ndarray
import numpy as np
# 从list创建数据类型为np.int32的np.ndarray
a = np.array([[1, 2], [3, 4], [5, 6]], dtype=np.int32)
print(a.ndim) # 2
print(a.shape) # (3, 2)
print(a.size) # 6
print(a.dtype) # dtype('int32')
# 可以使用 astype 方法转换np.ndarray的数据类型
a = a.astype(np.float32)
print(a.dtype) # dtype('float32')
np.ndarray
之间可以进行张量运算,服从线性代数的运算法则,也能和标量计算:
b = np.array([1, 2], dtype=np.float32)
c = b + b # array([2., 4.])
d = b / 2 # array([0.5, 1.])
e = b + 1 # array([2., 3.])
f = c * e # array([4., 12.])
需要注意的是,numpy中计算时*
表示逐元素乘法,而@
表示矩阵乘法(矢量相乘时是计算内积)。
此外,numpy还支持线性代数计算(求范数,取逆,转置等),统计运算(求平均,标准差,中位数等),三角函数,傅里叶变换等等,功能非常强大。
broadcasting(广播)是numpy特有的机制(也被pytorch,paddle等深度学习框架应用),主要用于不同形状张量之间的计算。
首先有一点要确定:张量计算必须符号线性代数的运算法则,特别是shape形状。
以加减法为例,shape不同的张量不能进行加减计算:
import numpy as np
a = np.ones(shape=[2, 3])
b = np.ones(shape=[3, 2])
a + b # error!
a * b # error!
a @ b # ok! because the shapes of a, b satisfy matmul
shape不符时的报错为ValueError: operands could not be broadcast together with shapes (2,3) (3,2)
,其中就提到了这两个计算不符合broadcasting
机制。
而a.shape=(2, 3), b.shape=(3, 2)
,满足矩阵乘法的形状要求。
所谓的broadcasting机制,就是把形状不符合计算要求,但满足某些条件的两个张量,变成形状符合计算要求的张量后,再做计算的过程。
该过程不会改变原张量的值。
broadcast要求两个张量同时满足以下条件:
①至少有一维
②两个张量从最后一维开始,一对一比较当前维度的大小,当前维度必须相等,或者该维度为1,或者没有维度。
broadcast的过程为:
比较当前维度大小,如果维度不相等,某一张量维度为1或者没有维度,则把该张量的该维度扩张到维度相等,直到两张量形状满足计算要求。
举个例子:
import numpy as np
a = np.ones(shape=[3, 1, 5, 4, 1, 2])
b = np.ones(shape=[1, 4, 6, 1])
a + b # ok! because the shapes of a, b satisfy broadcast for +
张量a, b
形状不满足加法,那就看是否满足broadcast
条件。
从后往前比较a, b
的维度b.shape[-1]=1
,a.shape[-2]=1
,a.shape[-3]=shape[-3]=4
,b.shape[-4]=1
,b
没有shape[-5], shape[-6]
(也就是没有维度)。
因此a, b
是满足broadcast条件的,也就可以做加法计算。
扩张维度的意思,也可以举个例子:
import numpy as np
a = np.ones(shape=[2, 2]) # array([[1, 1],
# [1, 1]])
b = np.array([1, 2], dtype=np.float32) # array([1, 2])
a + b # ok! b is extended to array([[1, 2],
# [1, 2]])
实际上就是延着该维度复制更高维的数据。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)