【零基础入门】一篇弄懂Tensor(张量)(呕心沥血版)

🌈 个人主页:十二月的猫-CSDN博客
🔥 系列专栏:🏀《PyTorch科研加速指南:即插即用式模块开发》CSDN博客

💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 

目录

1. 前言

2. Tensor

2.1 标量、向量、矩阵与张量

2.2 基本创建方法

2.2.1 CPU版本

2.2.2 GPU版本

2.2.3 Tensor数据类型 

2.3 快速创建方法

2.3.1 torch.zero()

2.3.2 torch.eye()

2.3.3 torch.ones()

2.3.4 torch.rand()

2.3.5 torch.arange()

2.3.6 torch.linspace()

2.4 Tensor常用数学操作

2.4.1 加法操作

2.4.2 另外四种常见的数学操作

2.5 线性代数运算

2.5.1 使用torch.dot()实现内积

2.5.2 使用torch.mv()实现矩阵与向量的乘法

2.5.3 使用torch.mm()将两个矩阵相乘

2.6 连接和切片

2.6.1 torch.cat实现连接

2.6.2 切片

2.6.3 矩阵转置

2.7 变形

3. CUDA加速

4. 总结


1. 前言

  • 👑《PyTorch科研加速指南:即插即用式模块开发》专栏持续更新中,未来最少文章数量为60篇。由于专栏刚刚建立,促销价为9.9。后续将慢慢恢复原价至99.9🍉【在校大学生】评论区留言并私信我免费订阅
  • 👑《PyTorch科研加速指南:即插即用式模块开发》专栏主要针对零基础入门的小伙伴。不需要Python基础,不需要深度学习基础,只要你愿意学,这一个专栏将真正让你做到零基础入门。
  • 🔥每例项目都包括理论讲解、数据集、源代码

正在更新中💹💹

🚨项目运行环境:

  • 平台:Window11
  • 语言环境:Python3.8
  • 运行环境1:PyCharm 2021.3
  • 运行环境2:Jupyter Notebook 7.3.2
  • 框架:PyTorch 2.5.1(CUDA11.8)

        在这一篇中,我们将掌握PyTorch中Tensor对象的创建和运算方法。Tensor是PyTorch中进行数据存储和运算的基本单元。Tensor之于PyTorch,相当于Array之于NumPy。实际上,PyTorch将NumPy 的Array包装成Tensor,为其定义了各式各样的运算方法和函数,Tensor是Array的为了深度学习而有的升级版。

  • Tensor对标Array。
  • Tensor相比Array增加了自动求导、反向传播等功能,适用于深度学习。
  • Tensor被使用于PyTorch、TensorFlow、MxNet等框架。
  • Tensor使用GPU加速计算,Array使用CPU计算。

2. Tensor

        Tensor中文叫做 张量,是PyTorch中最基本的数据类型。其与数学中的向量概念有千丝万缕的联系。

2.1 标量、向量、矩阵与张量

        数学中有这三个概念:

  • 标量:只有大小,没有方向的量。
  • 向量:既有大小又有方向的量。如\overrightarrow{v}=(2,5,8)
  • 矩阵:由多个向量组成的一堆数字。如\boldsymbol{M}=\begin{bmatrix}1&2&3\\4&5&6\\7&8&9\end{bmatrix}

        实际上,标量、向量和矩阵都是张量的特例:标量是零维张量、向量是一维张量、矩阵是二维张量。如下图所示,矩阵不过是三维张量下的二维切面。要找到三维张量下的1个标量,我们需要3个维度的坐标。

        向量维度:指的是向量中元素数量。如:[3, 5, 7]是一个包含 3 个元素的向量,维度是 3;如:[3, 5]是一个包含 2 个元素的向量,维度是 2。

        张量维度:仅仅考虑数据编排形式。数字序列编排则是一维张量(向量),面式编排则是二维张量(矩阵),空间形式编排则是三维张量。

2.2 基本创建方法

在PyTorch中创建张量(以下多称为Tensor)时需要导人torch包,首先在命令行中运行如下命令:

import torch

2.2.1 CPU版本

然后使用torch.Tensor()函数创建Tensor。这里我们传入参数(2,4)来构造一个大小为2x4的矩阵x:

x=torch.Tensor(2,4)
x

结果如下: 

可以看到,这个2×4的矩阵虽然没有初始化,但是已经有了值。

再查看矩阵X类型(张量),输入命令如下:

x.type() #x本身的类型
x.dtype  #张量x中数据的类型

结果如下:

注意:type是函数;dtype是属性

2.2.2 GPU版本

首先创立torch使用的设备device:

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

然后创建tensor对象:

torch.Tensor(2,3).to(device)

结果如下:

​输入下面命令,检查其类型为:

gpu_tensor.type()
gpu_tensor.dtype

结果如下:


2.2.3 Tensor数据类型 

        例如,我们使用torch.DoubleTensor()函数创建一个2x3x4的64位浮点数Tensor(即y):

        从上面的返回值可以看出,变量y的类型是DoubleTensor,即里面每个元素都是64位浮点数。
而且2x3x4的Tensor是由两个3x4的矩阵构成的,符合数学定义。下面对Tensor进行初始化。我们可以通过传入Python原生的List数据结构对其进行初始化:

list = [[1,2,3],[4,5,6],[7,8,9]]
torch.Tensor(list)

        然后通过Python的索引方式来获取Tensor中的元素值:

x[0][2]

        如下图所示,因为在Tensor中索引l从0开始计算,所以x[0][2]表示第1行第3列的元素;又因为其默认类型是torch.FloatTensor,所以返回值为tensor(5.)。

        我们可以通过索引修改Tensor中的元素:

2.3 快速创建方法

下面介绍几个快速创建Tensor的方法:

2.3.1 torch.zero()

用于创建元素全为0的Tensor:

2.3.2 torch.eye()

用于创建主对角线位置元素全为1,其他位置为0的Tensor:

2.3.3 torch.ones()

用于创建元素全为1的Tensor:

2.3.4 torch.rand()

用于创建将元素初始化为区间[0,1)的随机数的Tensor:

2.3.5 torch.arange()

用于创建一个在区间内按指定步长递增的一维Tensor,前两个参数指定区间范围,第三个参数指定步长(默认为1):

2.3.6 torch.linspace()

用于创建一个区间,前两个参数指定区间范围。并将区间划为n块,n由第三个参数决定。

常见快速创建Tensor方法如下: 

2.4 Tensor常用数学操作

在PyTorch官方文档上,Tensor的数学操作方法有90多种,比较常用的有25种数学操作方法。

        Tensor的数学操作的实现方法一般有两种:第一种是直接用Tensor实例调用数学操作方法,第二种是使用torch库的方法。

2.4.1 加法操作

        比如在进行加法操作前,先初始化两个形状相同的Tensor,因为形状不同的Tensor无法直接相加。本例中,初始化两个形状为2x3的Tensor(即a和b):

使用第一种方法:Tensor实例调用数学操作方法。

使用第二种方法:调用torch库函数。

特别地,如果数学操作函数带有下划线,返回值将覆盖对象,如下图中a+b覆盖了b:

数学运算中的广播机制。允许一个张量Tensor中的每个元素加上同一个标量,如:

2.4.2 另外四种常见的数学操作

abs():返回Tensor中每个元素的绝对值(类函数、库函数)

 

ceil():对Tensor中的每个元素向上取整(类函数、库函数)

 

exp():返回Tensor中每个元素的以e为底的指数

max():返回Tensor中所有元素的最大值

2.5 线性代数运算

        除了基本的数学操作外,torch包中还包含了约12种线性代数的相关函数。接下来,我们简单介绍一下其中的3种运算。

2.5.1 使用torch.dot()实现内积

​        假如你已经忘记了或者没有学过点积,请别担心,现在就让我们重新温习一遍。向量的点积
定义起来很简单。假设有两个向量a=[a,a2,... ,an],b=[b,b2,…,bn],那么a与b的点
积定义为:

\vec{a} \cdot \vec{b}=a_{1} b_{1}+a_{2} b_{2}+\cdots+a_{n} b_{n}=\sum_{i=1}^{n} a_{i} b_{i}

        从定义上可以发现,两个向量进行点积,得到的结果是一个标量。将上面代码中张量a和张量b的值代入a与b中,我们可以使用点积定义的公式进行推导: 

\vec{a} \cdot \vec{b}=1\times 2+2\times3+3\times4=20

2.5.2 使用torch.mv()实现矩阵与向量的乘法

​矩阵与向量的乘法规则如下所示:

\begin{bmatrix}a_{11}&a_{12}&\cdots&a_{1m}\\a_{21}&a_{22}&\cdots&a_{2m}\\\vdots&\vdots&\ddots&\vdots\\a_{n1}&a_{n2}&\cdots&a_{nm}\end{bmatrix}\begin{bmatrix}b_1\\b_2\\\vdots\\b_m\end{bmatrix}=\begin{bmatrix}a_{11}b_1+a_{12}b_2+\cdots+a_{1m}b_m\\a_{21}b_1+a_{22}b_2+\cdots+a_{2m}b_m\\\vdots\\a_{n1}b_1+a_{n2}b_2+\cdots+a_{nm}b_m\end{bmatrix}

根据上面的代码,我们可以还原成以下数学表达:

\begin{bmatrix}1&2&3\\2&3&4\\3&4&5\end{bmatrix}\begin{bmatrix}1\\2\\3\end{bmatrix}=\begin{bmatrix}1\times1+2\times2+3\times3\\2\times1+3\times2+4\times3\\3\times1+4\times2+5\times3\end{bmatrix}=\begin{bmatrix}14\\20\\26\end{bmatrix}

答案与上面相同🥰🥰~~~

2.5.3 使用torch.mm()将两个矩阵相乘

​矩阵与矩阵的乘法定义如下:

\begin{bmatrix}a_{11}&a_{12}&\cdots&a_{1s}\\\vdots&\vdots&\ddots&\vdots\\a_{i1}&a_{i2}&\cdots&a_{is}\\\vdots&\vdots&\ddots&\vdots\\a_{n1}&a_{n2}&\cdots&a_{ns}\end{bmatrix}\begin{bmatrix}b_{11}&\cdots&b_{1j}&\cdots&b_{1m}\\b_{21}&\cdots&b_{2j}&\cdots&b_{2m}\\\vdots&\ddots&\vdots&\cdots&\vdots\\b_{s1}&\cdots&b_{sj}&\cdots&b_{sm}\end{bmatrix}=\begin{bmatrix}c_{11}&\cdots&c_{1j}&\cdots&c_{1m}\\\vdots&\vdots&\vdots&\ddots&\vdots\\c_{i1}&\cdots&c_{ij}&\cdots&c_{im}\\\vdots&\vdots&\vdots&\ddots&\vdots\\c_{n1}&\cdots&c_{nj}&\cdots&c_{nm}\end{bmatrix}

其中c_{ij}=a_{i1}b_{1j}+a_{i2}b_{2j}+\cdots+a_{is}b_{sj}。根据上述代码,我们可以还原上述数学表达:

\begin{bmatrix}1&2&3\\2&3&4\\3&4&5\end{bmatrix}\begin{bmatrix}2&3&4\\3&4&5\\4&5&6\end{bmatrix}=\begin{bmatrix}20&26&32\\29&38&47\\38&50&62\end{bmatrix}

其他线性代数操作方法:

import torch

# 创建两个批量张量
input = torch.randn(10, 3, 5)  # (b=10, n=3, m=5)
mat2 = torch.randn(10, 5, 2)   # (b=10, m=5, p=2)

# 使用 bmm 进行批量矩阵乘法
output = torch.bmm(input, mat2)

# 输出的形状为 (b=10, n=3, p=2)
print(output.shape)  # 输出: torch.Size([10, 3, 2])
  • input 张量的形状为 (10, 3, 5),表示批次大小为 10,每个矩阵是 3x5。
  • mat2 张量的形状为 (10, 5, 2),表示批次大小为 10,每个矩阵是 5x2。
  • 结果 output 张量的形状为 (10, 3, 2),表示每对矩阵乘积的结果是一个 3x2 的矩阵。

2.6 连接和切片

2.6.1 torch.cat实现连接

        首先介绍如何使用torch.cat()函数将多个Tensor沿某维度进行连接。我们使用rand()函数随机初始化两个形状为2x2的Tensor:

        cat()函数需要传人两个参数:第一个参数是由需要进行连接的所有Tensor组成的元组;第二个参数是连接的维度。如果让a按照第一个维度(行)与b进行连接,则传人的第二个参数为0:

        如果让a按照第二个维度(列)与b进行连接,则传人的第二个参数为1:

2.6.2 切片

        接下来介绍如何使用torch.chunk()函数将Tensor沿某维度进行切片。我们先初始化一个Tensor实例a:

        再用torch.chunk()函数进行切片。chunk()函数需要传入3个参数:第一个参数为被切片的Tensor对象,第二个参数为切分的块数,第三个参数为切分的维度。下面我们将张量c按第二个维度切分为两块:

2.6.3 矩阵转置

最后介绍如何使用torch.t()函数来转置矩阵。注意,该函数只适用于二维的Tensor(即矩阵):

矩阵转置是将矩阵的行与列互换的操作,不改变矩阵元素的值,只改变排列方式

常见的连接和切片操作: 

2.7 变形

        view()函数可以改变Tensor的形状。在深度神经网络的卷积层与全连接层中,我们时常将高维的Tensor转化为一维的Tensor,这个过程就是使用view()函数完成的。下面举个简单的例子,我们先随机初始化一个2x3x4的Tensor:

接着,使用view()函数将这个Tensor转化成一个2x12的Tensor,总元素的数目保持不变:

当使用-1作为view()函数的参数时,代表该维度数目自动计算。下面的代码表示我们确定第二维为1,第一维自动计算。运行代码后,会得到一个24x1的Tensor:

3. CUDA加速

        在深度学习的训练过程中,经常需要庞大的计算量。用CPU进行数值计算的时间周期较长,难以立即得到计算结果。因此,在实际的深度学习训练过程中,我们通常会利用GPU进行加速运算。使用GPU进行加速计算之前,先运行下面的代码查看计算机是否支持CUDA加速:

torch.cuda.is_available()

        如果返回True,那么恭喜你,你可以直接使用GPU进行加速计算。如果返回False,则可能有两种情况:第一种是计算机没有支持CUDA的NVIDIA显卡,第二种是显卡驱动、CUDA或cuDNN等软件没有成功安装。

        如果确认自己电脑有NVIDIA显卡,但是仍然没有CUDA可以看另一篇文章:【一篇搞定配置】小白如何安装/配置/删除CUDA(详细图文)-CSDN博客
        为了对比CPU和GPU计算速度的差距,我们以一个1000×10000的矩阵与10000×10000的矩阵进行相乘为例,分别使用CPU和GPU进行计算,对比两者花费的时间。
        首先导入time库中的clock()函数用于计时

​下面我们使用cuda()函数。矩阵x和Y接下来进行的任何运算都会调用GPU进行加速计算:

​GPU和CPU在矩阵乘法上的差距: 

因此,GPU在矩阵数值运算的速度远超过CPU。

4. 总结

 【如果想学习更多深度学习文章,可以订阅一下热门专栏】

如果想要学习更多pyTorch/python编程的知识,大家可以点个关注并订阅,持续学习、天天进步你的点赞就是我更新的动力,如果觉得对你有帮助,辛苦友友点个赞,收个藏呀~~~

评论 52
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十二月的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值