用Bing图片制作器制作的图片,提示 "彩色pytorch张量丢失在太空中"
PyTorch是一个为促进机器学习和深度学习模型的开发(创建、训练和部署)而创建的python库。它收集了对多维数据进行数学运算的模块,支持GPU加速和自动分化。在PyTorch中,数据是以张量的形式存储的。
张量是一个多维数组,存储相同数据类型的数字元素(就像*numpy.*ndarray类型,不同的是张量可以在GPU上运行)。张量是用来表示深度学习数据(即代表图像、音频、文本等的大数据)的数据结构。标量、向量和矩阵是张量的例子。
- 一个张量 标量是一个没有维度的对象,在几何学上由一个 点.在张量的语言中,它的秩等于0。一个标量也可以定义为长度为1的矢量或1x1维的矩阵。
- 一个张量 向量是一个有一个维度的对象,概念上是一个线性数据结构或一个按线组织的标量集合。在张量的语言中,它的等级为 1,长度等于元素的数量*(n*)。在几何学上,它由一条水平或垂直的 线也就是一个行向量或列向量。
- 一个张量 矩阵是一个组织成行和列的标量的集合。它是一个二维的数据结构,在几何上由一个 平面.用张量的语言来说,它的秩是 2,并且有一个定义明确的形状属性来决定它的每个维度的大小。
按照这个推理,一个等级为3的张量是一个ixj维度的k矩阵的集合。
更高等级的张量也是可行的。一个n维的张量将有n 级。
图中说明了4个不同等级的张量的几何结构,从等级0到等级3。术语torch.Size([])表示张量的形状。
注意:本文旨在对PyTorch张量进行一个亲切的介绍。一些插图和代码被全面介绍,以帮助非严谨的科学爱好者掌握这个主题。有一个我制作的练习笔记本,里面有这里描述的几乎所有方法的例子。这个笔记本可以在 GitHub链接作为一个Colab笔记本。(你可以下载该笔记本并在谷歌Colab中运行,如果你安装了PyTorch,也可以在本地运行)。
对于初学者,我还推荐以下pytorch.org的教程:
-pytorch.org/utorials/be…
-pytorch.org/utorials/be…
PyTorch.torch库
要使用PyTorch的API,您需要导入如下的Torch包:
**import** torch
如果你打算在你的机器上安装PyTorch,请参考PyTorch网站以获得正确的安装命令,这将取决于你的首选软件包管理器和你的计算机系统偏好。
PyTorch的张量数据类型
数据在张量中以数字的形式存储,默认的数据类型是浮点数字。然而,PyTorch支持多种数字数据类型。
该表显示了一些张量数据类型。目前的信息并不意味着详尽无遗。
基本上,张量数据类型可以通过以下三种不同的方式之一进行编程定义:
- 在创建时,通过向构造函数方法提供dtype 参数、
- 或通过调用 torch.Tensor.to(device=None, dtype=None)方法并提供dtype 参数、
- )或通过铸造函数。例如: torch.Tensor.double*(memory_format=torch.preserve_format);torch.Tensor.bool(memory_format=torch.preset_format);torch.Tensor.int(memory_format=torch.preset_format)*; ecc.Tensor.com.cn (memory_format=torch.preset_format)
调用 torch.get_default_dtype*()*来找出默认的数据类型是什么。
并且 torch.can_cast*(from, to)*来了解在PyTorch的铸造规则下是否允许进行类型转换:https://pytorch.org/docs/stable/tensor_attributes.html#type-promotion-doc
注意:有可能通过调用方法来设置默认的浮点类型 torch.set_default_tensor_dtype*(t)*并将新的浮点张量类型作为函数参数传入。
创建操作
创建OPP是用于实例化张量的方法,也就是说,它们是张量构造器。它们有几个,每个都有不同的目的,这取决于张量将存储的数据和张量将具有的形状。
- 要用预先存在的数据源创建一个张量,可以使用方法 火炬.张量(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
这个方法构造一个没有自动格拉德历史的张量(即一个叶子张量)。参数数据可以是列表、元组、NumPy ndarray、标量和其他类型。 - 要创建一个充满初始化、内存数据的特定大小的张量,请使用方法
torch.empty*(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False, memory_format=torch.contiguous_format)* - 要创建一个具有特定大小的张量,填充一个给定的标量(零、一、随机或特定值),请使用以下方法之一:
torch.zeros*(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)*
火炬.一*(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)*
火炬.rand*(size, generator=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False)*
torch.full*(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)*
注意:
**torch.*_like()方法
带有***_like的方法用于重现一个输入张量的形状。它们返回一个与输入张量相同大小的张量,并填充标量值0(torch.zeros_like**(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preset_format))或1**(torch. ones_like**(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preset_format))。
要了解更多关于创建操作的信息:https://pytorch.org/docs/stable/torch.html#tensor-creation-ops
特性、属性和内置方法
每个张量都有一组固有的特征,如属性、属性和内置方法,可以调用它们来了解一个给定的张量组件的具体细节。
- 张量的属性: 火炬.dtype; torch.device; 火炬.布局; torch.Tensor.grad; 火炬.张量.request_grad
- 张量属性: torch.Tensor.storage*();*torch.Tensor.shape
- 张量内置方法: torch.Tensor.size*(dim=None);torch.Tensor.storage_offset();火炬.张量.stride(dim)*
要了解更多,请参见:https://pytorch.org/docs/stable/tensor_attributes.html
存储器、大小、storage_offset和stride
这些张量组件被用来定义张量的数据存储位置和几何形状。
其中 存储器是分配来存储张量数据的内存。默认情况下,它是一个连续的内存块。
张量 大小是由每个维度中的元素数量决定的。例如,一个二维张量的大小由其行数*(i*)和列数*(j*)决定,即2d_tensor.size() = tensor(i,j)。
张量 stride是指沿每个维度(例如二维张量中的行或列)的连续数组开始的元素之间的存储位置的数量*+1*。
储存器 存储器偏移是张量中第一个元素的相应存储索引。
使用方法 torch.as_strided*(input, size, stride, storage_offset=None)来修改一个张量的大小*、stride和storage_offset。
张量视图(下面讨论)能够通过其偏移量和stride值索引到原始张量存储。
图:使用torch.as_strided(input, size, stride, storage_offset=None)方法在张量V的三个不同视图(X、Y和Z)中划分大小、存储偏移和stride。
索引
通过索引,张量的内容可以被逐个元素或分块访问,也可以被修改。
图中说明了按元素、按行块和按列块进行索引;然后修改一个元素和一个元素块。
该方法 裂解*(torch.Tensor, split_size/split_sections, dim=0)沿指定的维度返回输入张量的小块。每个卡盘是原始张量的一个视图*。
视图张量
A 视图张量是一个副本张量,它与原始张量共享相同的基础存储(即内存和数据)。几个PyTorch张量可以共享相同的存储,这样内存就只被分配一次。这样的功能可以对张量进行快速的操作,如重塑、切片和元素明智的操作。然而,需要注意的是,修改视图张量中的数据也会改变原始张量中的数据,反之亦然。
调用方法 torch.Tensor.view(*shape)*来创建一个现有张量的视图。
视图操作
一些PyTorch张量方法会返回一个输入张量的视图,而不是返回一个新的张量。在PyTorch中有几个视图操作,不限于以下方法:
- torch.as_strided*(input, size, stride, storage_offset=None)*
以指定的大小、stride和storage_offset创建一个现有张量输入的视图。 - torch.Tensor.detach*()*
返回一个新的张量,从当前图形中分离出来。 - torch.narrow*(input, dim, start, length)*
返回一个新的张量,它是输入张量的缩小版(https://pytorch.org/docs/stable/generated/torch.narrow.html#torch.narrow) - torch.select*(input, dim, index)*
返回输入张量的视图,作为沿指定维度*(dim*)和索引的切片。 - torch.squeeze*(input, dim=None)*
返回一个具有输入张量的所有指定维度的张量,但是去掉了尺寸为1的维度。 - torch.unsqueeze*(input, dim)*
返回一个新的张量,在指定的位置插入一个尺寸为1的张量。 - torch.transpose*(input, dim0, dim1)*
返回一个张量,它是输入张量的转置版本。给定的尺寸dim0和dim1被交换了。 - torch.t*(input)*
返回2维或更少的张量的转置维数0和1。 - torch.permute*(torch.Tensor)*
返回输入张量的 permuted 维度的视图。 - torch.reshape*(input, shape)*
返回具有指定形状的输入张量的视图。如果形状兼容,该方法返回输入张量的视图,否则返回一个副本(同样适用于 torch.flatten()和 torch.Tensor.reshape_as()). - torch.split*(torch.Tensor, split_size/split_sections, dim=0)*
沿着指定的维度返回输入张量的大块。每个块是原始张量的一个视图。 - torch.chunk*(input, chunks, dim=0)*
试图将一个张量分割成指定数量的块。每个块是输入张量的一个视图。
连贯性问题
默认情况下,PyTorch张量被分配在一个连续的内存块中(密集的非重叠内存),内存_format = torch.contiguous_format。
然而,请注意,在一个连续的张量上调用视图方法有可能产生一个非连续的张量(见下面的例子)。
这里有两个重要的方法:
- 方法是
火炬。Tensor.is_contiguous*(memory_format=torch.contiguous_format)*
是用来验证数据的连续性的。如果自我张量在内存中按照内存格式指定的顺序连续,它返回True。其中'memory_format'参数指定内存分配顺序,默认等于torch.contiguous_format。 - 该方法
火炬。Tensor.contiguous*(memory_format=torch.contiguous_format)*
是用来创建一个张量的连续副本的。它返回一个在内存中连续的张量,包含与自我 张量相同的数据,并具有特定的内存格式。当自我 张量不连续时,调用此方法来强制复制数据。警告:如果self张量已经在指定的内存格式中,这个函数返回self张量。
就地方法
PyTorch的就地方法是由方法的名称加上尾部的下划线表示。这些方法允许操作者直接修改自张量,而不是返回一个新的张量。
OUT参数
一些方法有一个名为 "out "的参数。这个功能允许提供一个张量作为参数来接收操作的输出。
它对于创建一个操作的输出的副本很有用。
复制张量
使用 torch.clone*()*方法将张量值复制到一个新的存储中,例如,将一个视图张量转化为一个新的、独立的张量。
操纵张量的形状
可以修改张量的形状,同时仍然保留其元素的数量。最常用的方法是: torch.squeeze*(input, dim=None)和 torch.unsqueeze(input, dim);torch.reshape(input, shape);以及 torch.flatten(input, start_dim=0, end_dim=- 1)*。
**1.这些方法 torch.squeeze(input, dim=None)和 torch.unsqueeze(input, dim)允许从一个张量中移除或添加一个范围为1的维度。然而,这些函数只适用于范围为1的维度。
参数dim是一个int或者一个整数的tuple,代表输入应该被挤压或者取消挤压的指定维度。
**2.2.另一种改变张量形状而又保持其元素数的方法是使用以下方法 torch.reshape(input, shape)。
3.方法 torch.flatten*(input, start_dim=0, end_dim=- 1)通过将输入*重塑为一个一维的张量而使其扁平。这个方法可以返回原始对象、一个视图或副本。(了解更多信息请访问:https://pytorch.org/docs/stable/generated/torch.flatten.html?highlight=torch+flatten#torch.flatten)
拆分张量
使用方法分割张量 tensor.split*(tensor, split_size_or_sections, dim=0),其中split_size_or_sections*是一个整数或一个整数列表,代表单个块的大小或每个块的大小列表。
使用张量的数学运算
PyTorch提供了几种方法来对张量进行数学运算。PyTorch的张量支持元素-明智的操作、线性代数操作和点乘操作。
- 元素运算:方法是根据数学运算,用第二张量中的相应元素来操作第一张量中的每个元素。例如:元素的加法、减法、乘法、除法、幂的运算等。
- 矩阵运算(线性代数运算):乘法的特点是向量的线性组合。例如:转置、行列式、逆、眼、矩阵乘法。
(了解更多关于**torch.linalg**
在:https://pytorch.org/docs/stable/linalg.html) - 点积(或内积):这些方法将第一个张量和第二个张量的相应元素的乘积沿其最后一维相加。
- 使用方法 torch.dot*(input, other, out=None)在两个具有相同元素数的一维张量之间进行点乘。
- 使用方法 torch.inner(input, other, out=None)在更高维度的张量之间进行点乘。这个方法将输入和其他元素的乘积沿其最后一个维度相加。注意:如果input和other都是非标量,它们的最后一维的大小必须匹配。
- 使用方法 torch.mm(input, other, out=None)来进行二维*张量之间的点乘。该方法将输入和其他元素的乘积沿其最后一维相加。注意:只适用于相同大小和形状的矩阵。
广播语义
广播是一种在具有不同形状的张量之间进行操作的方法。如果满足以下条件,两个张量x和y是可广播的:
- 每个张量必须至少有一个维度
- 后面的维度一致:比较每个维度的大小,从右到左开始,它们必须:相等,或者其中一个维度的大小为1,或者其中一个维度在其中一个张量中不存在。
要了解更多关于广播语义和向后兼容性的信息,请参见pytorch.org/docs/stable…
torch.autograd包
该 **autograd**
包使PyTorch能够跟踪计算图,并轻松计算梯度,该操作主要在训练深度学习模型时执行。
在模型训练过程中,参数的值是根据损失函数相对于给定参数的梯度进行优化。在大型神经网络中,要手动实现这一过程将是一场噩梦。令我们欣慰的是 **autograd**
通过提供计算自动微分的方法,使这个训练步骤自动化。
要计算梯度,可以使用 **autograd**
在创建张量时,将张量的requires_grad属性设置为True,或者以后通过调用方法 torch.required_grad_**(True)。
下面是一些重要的方法,但不限于此:
- torch.Tensor.requires_grad_**(requires_grad=True)
就地设置自我张量的requires_grad属性 - torch.tensor.backward*(gradient=None, inputs=None)*
计算输入张量相对于图叶的梯度之和。 - torch.tensor.detach*()*
返回一个从当前图形中分离出来的新张量。 - torch.no_grad*()*
禁用梯度计算。 - torch.tensor.item*()*
返回存储在张量中的值(作为Python数字)。注意:该方法只适用于具有单个值的张量。
要了解更多关于 **autograd**
见:
将张量移动到GPU和CPU内存中
在CPU中创建的张量可以被移动到GPU中,反之亦然,使用方法是 torch.Tensor.to(device=None, dtype=None)。
其他移动张量的方法有:
- 在构造过程中,提供设备参数
- 使用方法: torch.Tensor.cpu*()或 torch.Tensor.cuda()*
保存和加载张量
用以下方法轻松地保存和加载张量 保存*(torch.Tensor, file_name)和 torch.load(file_name)。*
注意:在保存PyTorch文件时,请使用扩展名*".pt "或".pth"*。
了解更多关于序列化语义的信息,请访问:https://pytorch.org/docs/stable/notes/serialization.html#saving-loading-tensors
其他一些PyTorch.torch方法
PyTorch提供了无数的方法来操作张量。Chillee提出了一个PyTorch实数运算符面的分类图。到Chillee在dev-discuss.pytorch.org/t/where-do-…,他们达到了2055个条目(如下图),是300多个面向用户的运算符。
图:PyTorch操作符的分类法。源于此:Chillee 2021年。2000多个PyTorch操作符从何而来:比你想知道的更多。PyTorch开发讨论。
下面是除了本文前面介绍的之外的几个基本使用的运算符:
- torch.manual_seed*(seed)*
设置用于生成随机数的种子。返回一个Torch.Generator对象。 - torch.stack*(input, dim=0, out=None)*
沿着给定的维度串联一连串的张量。 - torch.argmax*(torch.Tensor)*
返回输入张量中具有最大值的元素的索引。 - torch.sum*(input, dtype=None)*
返回输入张量中所有元素的和。 - torch.no_grad*()* / torch.enable_grad*()*
禁用/启用梯度计算。