- PyTorch深度学习应用实战
- 陈昭明 洪锦魁
- 2242字
- 2024-12-24 10:37:07
3-2 张量运算
张量(Tensor)用于描述向量空间(Vector Space)中物体的特征,包括零维的标量(Scalar)、一维的向量(Vector)、二维的矩阵(Matrix)或更多维度的张量。线性代数则是说明张量如何进行各种运算,它被广泛应用于各种数值分析的领域。以下就以实例说明张量的概念与运算。PyTorch线性代数函数库也都遵循NumPy套件的设计理念与语法,包括传播(Broadcasting)机制,甚至函数名称都相同。
深度学习模型的输入/输出格式以张量表示,所以,我们先熟悉向量、矩阵的相关运算及程序撰写语法。
本节的程序代码请参阅【03_01_张量运算.ipynb】。
3-2-1 向量
向量(Vector)是一维的张量,它与线段的差别是除了长度(Magnitude)以外,还有方向(Direction),数学表示法为:

以图形表示如下:

图3.3 向量(Vector)长度与方向
(1)长度(Magnitude):计算公式为欧几里得距离(Euclidean Distance)。

程序撰写如下:

可以直接调用np.linalg.norm()计算向量长度:

也可以使用PyTorch的torch.linalg.norm()计算,但是要先将向量转换为PyTorch格式。

(2)方向(Direction):使用arctan()函数计算。

移项如下:


计算得到的单位为弧度,可转为大部分人比较熟悉的角度。
(3)向量四则运算规则。
■ 加减乘除一个常数:常数直接对每个元素作加减乘除。
■ 加减乘除另一个向量:两个向量相同位置的元素作加减乘除,所以两个向量的元素个数须相等。
(4)向量加减法:加减一个常数,长度、方向均改变。程序撰写如下:

执行结果:

图3.4 向量加减一个常数,长度、方向均改变
(5)向量乘除法:乘除一个常数,长度改变,方向不改变。

执行结果:

图3.5 向量乘除一个常数,长度改变,方向不改变
(6)向量加减乘除另一个向量:两个向量的相同位置的元素作加减乘除。

执行结果:

图3.6 向量加另一个向量,长度、方向均会改变
(7)“内积”或称“点积”(Dot Product)计算公式如下:

NumPy是以@作为内积的运算符号,而非*。

(8)计算两个向量的夹角,公式如下:

移项:

再利用arccos()计算夹角θ。

3-2-2 矩阵
矩阵是二维的张量,拥有行(Row)与列(Column),可用于表达一个平面的N个点(N×2),或一个3D空间的N个点(N×3),例如:

(1)矩阵加法/减法与向量相似,相同位置的元素作运算即可,但乘法运算通常是指内积,使用@。试对两个矩阵相加:

程序撰写如下:

(2)试对两个矩阵相乘:

左边矩阵的第2维须等于右边矩阵的第1维,即(m,k)×(k,n)=(m,n):

其中左上角的计算过程为(1,2,3)×(9,7,5)=(1×9)+(2×7)+(3×5)=38,右上角的计算过程为(1,2,3)×(8,6,4)=(1×8)+(2×6)+(3×4)=32,依此类推,如下图所示。

图3.7 矩阵相乘

(3)矩阵(A、B)相乘,A×B是否等于B×A?

执行结果:A×B不等于B×A。

(4)矩阵在运算时,除了一般的加减乘除外,还有一些特殊的矩阵,包括转置矩阵(Transpose)、逆矩阵(Inverse)、对角矩阵(Diagonal Matrix)、单位矩阵(Identity Matrix)等。
· 转置矩阵:列与行互换。

(AT)T=A:进行两次转置,会恢复成原来的矩阵。
(5)对上述矩阵作转置,代码如下。

也可以使用np.transpose(A)。
(6)逆矩阵(A-1):A必须为方阵,即列数与行数须相等,且必须是非奇异矩阵(Non-singular),即每一列或行之间不可以相依于其他列或行。

执行结果:

(7)若A为非奇异矩阵,则A @ A-1=单位矩阵(I)。所谓的非奇异矩阵是任一行不能为其他行的倍数或多行的组合,包括各种四则运算。矩阵的列也须符合相同的规则。
(8)试对下列矩阵验算A @ A-1是否等于单位矩阵(I)。


执行结果:

结果为单位矩阵,表示A为非奇异矩阵。
(9)试对下列矩阵验算A@A-1是否等于单位矩阵(I)。


执行结果:

A为奇异(Singular)矩阵,原因如下:
第二列=第一列+1;
第三列=第一列+2;
故A@A-1不等于单位矩阵。
3-2-3 使用PyTorch
(1)显示PyTorch版本。

(2)检查GPU及CUDA Toolkit是否存在。

执行结果为True,表示侦测到GPU,反之为False。
(3)如果要知道GPU的详细规格,可安装PyCuda套件。请注意在Windows环境下,无法以pip install pycuda安装,须在网站Unofficial Windows Binaries for Python Extension Packages (https://www.lfd.uci.edu/~gohlke/pythonlibs/?cm_mc_uid=08085305845514542921829&cm_mc_sid_50200000=1456395916#pycuda)下载对应Python、Cuda Toolkit版本的二进制文件。
举例来说,Python v3.8安装Cuda Toolkit v10.1须下载pycuda-2020.1+cuda101-cp38-cp38-win_amd64.whl,并执行pip install pycuda-2020.1+cuda101-cp38-cp38-win_amd64.whl。
接着就可以执行本书所附的范例:python GpuQuery.py。
执行结果可显示GPU的详细规格,重要信息会排列在前面。
(4)使用torch.tensor建立张量变量,PyTorch会根据变量值决定数据类型,也可以声明特定类型,如整数(torch.IntTensor)、长整数(torch.LongTensor)、浮点数(torch.FloatTensor)。

(5)进行四则运算。

执行结果如下:

如果只要显示数值,可转为NumPy数组,例如:
x.numpy()
(6)NumPy变量转为PyTorch张量变量。

(7)TensorFlow常用的reduce_sum函数是沿着特定轴加总,输出会少一维,以PyTorch撰写可使用sum()替代:

执行结果对每一行加总,输出会少一维:
tensor([6., 15.])
(8)稀疏矩阵(Sparse Matrix)运算:稀疏矩阵是指矩阵内只有很少数的非零元素,如果按一般的矩阵存储会非常浪费内存,运算也是如此,因为大部分项目为零,不须浪费时间计算,所以,科学家针对稀疏矩阵设计了特殊的数据存储结构及算法,PyTorch也支持此类数据类型。

图3.8 稀疏矩阵(Sparse Matrix)
(9)TensorFlow会自动决定变量在CPU或GPU运算,但PyTorch稍麻烦一些,必须手动将变量移动至CPU或GPU运算,不允许一个变量在CPU,另一个变量在GPU,进行运算会出现错误。程序撰写时要注意下列事项:
· 变量移动至CPU/GPU,可使用.to('cpu')或.to('cuda'),若有多张GPU卡,可指定移动至某一张,例如移动至第一张使用.to('cuda:0'),也可以使用.cuda()、.cpu()。
· 虽然手动移动比使用TensorFlow麻烦,不过,这种做法有助于内存管理,碰到GPU内存有限时,可以改在CPU运算,避免类似TensorFlow常见的内存不足(OOM)现象。
· 变量在CPU/GPU移动时会花费一点时间,若运算量不大且不复杂时,可直接在CPU运算。

执行结果。

(10)CPU与GPU变量不可混合运算。

执行结果如下。

为了避免出错,要这样写才对:tensor_gpu+tensor_cpu.cuda()。
(11)要在只有GPU或只有CPU的硬件均能执行,需要撰写如下:

(12)PyTorch稀疏矩阵只须设定值的位置(indices)和数值(values),如下所示,i为位置数组,v为数值数组:

执行结果如下,例如第一个值(3)在(0, 2),第二个值(4)在(1, 0),第三个值(5)在(1, 2):

(13)稀疏矩阵运算写法如下:

执行结果:

(14)要直接禁用GPU卡,可执行下列指令,注意,必须要在文件一开始就执行,否则无效。

(15)若有多张GPU卡,可指定移动至某一张GPU。
