Python numpy使用记录1.数组计算的broadcasting机制

Python numpy使用记录1.数组计算的broadcasting机制,第1张

Python numpy使用记录1.数组的broadcast机制
  • 前言
  • numpy数组计算
  • broadcasting机制
    • shape要求
    • broadcast说明

前言

本篇开始记录一些使用numpy时的技巧。


numpy事实上已经成为了python的数据处理包。


不过有的numpy *** 作不大好理解,也容易遗忘。


这里的记录是为了增加记忆。


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机制 shape要求

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),满足矩阵乘法的形状要求。


broadcast说明

所谓的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]=1a.shape[-2]=1a.shape[-3]=shape[-3]=4b.shape[-4]=1b没有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]])

实际上就是延着该维度复制更高维的数据。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/578471.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存