自然语言处理PyTorch 基础入门(必备基础知识)
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自然语言处理PyTorch 基础入门(必备基础知识)相关的知识,希望对你有一定的参考价值。
PyTorch 基础
在本书中,我们广泛地使用 PyTorch 来实现我们的深度学习模型。PyTorch 是一个开源、社区驱动的深度学习框架。与 Theano、Caffe 和 TensorFlow 不同,PyTorch 实现了一种“基于磁带的自动微分”方法,允许我们动态定义和执行计算图形。这对于调试和用最少的努力构建复杂的模型非常有帮助。
动态 VS 静态计算图 像 Theano、Caffe 和 TensorFlow 这样的静态框架需要首先声明、编译和执行计算图。虽然这会导致非常高效的实现(在生产和移动设置中非常有用),但在研究和开发过程中可能会变得非常麻烦。
像 Chainer、DyNet 和 PyTorch 这样的现代框架实现了动态计算图,从而支持更灵活的命令式开发风格,而不需要在每次执行之前编译模型。
动态计算图在建模 NLP 任务时特别有用,每个输入可能导致不同的图结构。
PyTorch 是一个优化的张量操作库,它提供了一系列用于深度学习的包。
这个库的核心是张量,它是一个包含一些多维数据的数学对象。
0 阶张量就是一个数字,或者标量。
一阶张量(一阶张量)是一个数字数组,或者说是一个向量。类似地,二阶张量是一个向量数组,或者说是一个矩阵。
因此,张量可以推广为标量的n
维数组。
在以下部分中,我们将使用 PyTorch 学习以下内容:
- 创建张量
- 操作与张量
- 索引、切片和与张量连接
- 用张量计算梯度
- 使用带有 gpu 的 CUDA 张量
在本节的其余部分中,我们将首先使用 PyTorch 来熟悉各种 PyTorch 操作。我们建议您现在已经安装了 PyTorch 并准备好了 Python 3.5+ 笔记本,并按照本节中的示例进行操作。我们还建议您完成本节后面的练习。
安装 PyTorch
第一步是通过在 pytorch.org 上选择您的系统首选项在您的机器上安装 PyTorch。选择您的操作系统,然后选择包管理器(我们推荐conda/pip
),然后选择您正在使用的 Python 版本(我们推荐 3.5+)。这将生成命令,以便您执行安装 PyTorch。在撰写本文时,conda 环境的安装命令如下:
conda install pytorch torchvision -c pytorch
注意:如果您有一个支持 CUDA 的图形处理器单元(GPU),您还应该选择合适的 CUDA 版本。要了解更多细节,请参考 pytorch.org 上的安装说明。
请参考: PyTorch 最新安装教程(2021-07-27)
创建张量
首先,我们定义一个辅助函数,描述(x
),它总结了张量x
的各种性质,例如张量的类型、张量的维数和张量的内容:
Input[0]:
def describe(x):
print("Type: {}".format(x.type()))
print("Shape/size: {}".format(x.shape))
print("Values: \\n{}".format(x))
PyTorch 允许我们使用torch
包以许多不同的方式创建张量。创建张量的一种方法是通过指定一个随机张量的维数来初始化它,如例 1-3 所示。
示例 1-3:在 PyTorch 中使用torch.Tensor
创建张量
Input[0]:
import torch
describe(torch.Tensor(2, 3))
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 3.2018e-05, 4.5747e-41, 2.5058e+25],
[ 3.0813e-41, 4.4842e-44, 0.0000e+00]])
我们还可以创建一个张量通过随机初始化值区间上的均匀分布(0,1
)或标准正态分布(从均匀分布随机初始化张量,说,是很重要的,正如您将看到的在第三章和第四章),见示例 1-4。
示例 1-4:创建随机初始化的张量
Input[0]:
import torch
describe(torch.rand(2, 3)) # uniform random
describe(torch.randn(2, 3)) # random normal
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0.0242, 0.6630, 0.9787],
[ 0.1037, 0.3920, 0.6084]])
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[-0.1330, -2.9222, -1.3649],
[ 2.3648, 1.1561, 1.5042]])
我们还可以创建张量,所有张量都用相同的标量填充。对于创建 0 或 1 张量,我们有内置函数,对于填充特定值,我们可以使用fill_()
方法。
任何带有下划线(_
)的 PyTorch 方法都是指就地(in place)操作;也就是说,它在不创建新对象的情况下就地修改内容,如示例 1-5 所示。
示例 1-5:创建填充的张量
Input[0]:
import torch
describe(torch.zeros(2, 3))
x = torch.ones(2, 3)
describe(x)
x.fill_(5)
describe(x)
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0., 0., 0.],
[ 0., 0., 0.]])
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 1., 1., 1.],
[ 1., 1., 1.]])
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 5., 5., 5.],
[ 5., 5., 5.]])
示例 1-6 演示了如何通过使用 Python 列表以声明的方式创建张量。
示例 1-6:从列表创建和初始化张量
Input[0]:
x = torch.Tensor([[1, 2, 3],
[4, 5, 6]])
describe(x)
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 1., 2., 3.],
[ 4., 5., 6.]])
值可以来自列表(如前面的示例),也可以来自 NumPy 数组。当然,我们也可以从 PyTorch 张量变换到 NumPy 数组。
注意,这个张量的类型是一个double
张量,而不是默认的FloatTensor
。这对应于 NumPy 随机矩阵的数据类型float64
,如示例 1-7 所示。
示例 1-7:从 NumPy 创建和初始化张量
Input[0]:
import torch
import numpy as np
npy = np.random.rand(2, 3)
describe(torch.from_numpy(npy))
Output[0]:
Type: torch.DoubleTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0.8360, 0.8836, 0.0545],
[ 0.6928, 0.2333, 0.7984]], dtype=torch.float64)
在处理使用 Numpy 格式数值的遗留库(legacy libraries)时,在 NumPy 和 PyTorch 张量之间切换的能力变得非常重要。
张量类型和大小
每个张量都有一个相关的类型和大小。使用torch
时的默认张量类型。张量构造函数是torch.FloatTensor
。但是,可以在初始化时指定张量,也可以在以后使用类型转换方法将张量转换为另一种类型(float
、long
、double
等)。有两种方法可以指定初始化类型,一种是直接调用特定张量类型(如FloatTensor
和LongTensor
)的构造函数,另一种是使用特殊的方法torch.tensor
,并提供dtype
,如例 1-8 所示。
示例 1-8:张量属性
Input[0]:
x = torch.FloatTensor([[1, 2, 3],
[4, 5, 6]])
describe(x)
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 1., 2., 3.],
[ 4., 5., 6.]])
Input[1]:
x = x.long()
describe(x)
Output[1]:
Type: torch.LongTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 1, 2, 3],
[ 4, 5, 6]])
Input[2]:
x = torch.tensor([[1, 2, 3],
[4, 5, 6]], dtype=torch.int64)
describe(x)
Output[2]:
Type: torch.LongTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 1, 2, 3],
[ 4, 5, 6]])
Input[3]:
x = x.float()
describe(x)
Output[3]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 1., 2., 3.],
[ 4., 5., 6.]])
我们利用张量对象的形状特性和尺寸方法来获取其尺寸的测量值。访问这些度量的两种方法基本上是相同的。在调试 PyTorch 代码时,检查张量的形状成为必不可少的工具。
张量操作
在创建了张量之后,可以像处理传统编程语言类型(如+
、-
、*
和/
)那样对它们进行操作。除了操作符,我们还可以使用.add()
之类的函数,如示例 1-9 所示,这些函数对应于符号操作符。
示例 1-9:张量操作:加法
Input[0]:
import torch
x = torch.randn(2, 3)
describe(x)
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0.0461, 0.4024, -1.0115],
[ 0.2167, -0.6123, 0.5036]])
Input[1]:
describe(torch.add(x, x))
Output[1]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0.0923, 0.8048, -2.0231],
[ 0.4335, -1.2245, 1.0072]])
Input[2]:
describe(x + x)
Output[2]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0.0923, 0.8048, -2.0231],
[ 0.4335, -1.2245, 1.0072]])
还有一些运算可以应用到张量的特定维数上。正如您可能已经注意到的,对于 2D 张量,我们将行表示为维度 0,列表示为维度 1,如示例 1-10 所示。
示例 1-10:基于维度的张量操作
Input[0]:
import torch
x = torch.arange(6)
describe(x)
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([6])
Values:
tensor([ 0., 1., 2., 3., 4., 5.])
Input[1]:
x = x.view(2, 3)
describe(x)
Output[1]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0., 1., 2.],
[ 3., 4., 5.]])
Input[2]:
describe(torch.sum(x, dim=0))
Output[2]:
Type: torch.FloatTensor
Shape/size: torch.Size([3])
Values:
tensor([ 3., 5., 7.])
Input[3]:
describe(torch.sum(x, dim=1))
Output[3]:
Type: torch.FloatTensor
Shape/size: torch.Size([2])
Values:
tensor([ 3., 12.])
Input[4]:
describe(torch.transpose(x, 0, 1))
Output[4]:
Type: torch.FloatTensor
Shape/size: torch.Size([3, 2])
Values:
tensor([[ 0., 3.],
[ 1., 4.],
[ 2., 5.]])
通常,我们需要执行更复杂的操作,包括索引、切片、连接和突变(indexing,slicing,joining and mutation)的组合。与 NumPy 和其他数字库一样,PyTorch 也有内置函数,可以使此类张量操作非常简单。
索引,切片和连接
如果您是一个 NumPy 用户,那么您可能非常熟悉示例 1-11 中所示的 PyTorch 的索引和切片方案。
示例 1-11:切片和索引张量
Input[0]:
import torch
x = torch.arange(6).view(2, 3)
describe(x)
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0., 1., 2.],
[ 3., 4., 5.]])
Input[1]:
describe(x[:1, :2])
Output[1]:
Type: torch.FloatTensor
Shape/size: torch.Size([1, 2])
Values:
tensor([[ 0., 1.]])
Input[2]:
describe(x[0, 1])
Output[2]:
Type: torch.FloatTensor
Shape/size: torch.Size([])
Values:
1.0
示例 1-12 演示了 PyTorch 还具有用于复杂索引和切片操作的函数,您可能对有效地访问张量的非连续位置感兴趣。
示例 1-12:复杂索引:张量的非连续索引
Input[0]:
indices = torch.LongTensor([0, 2])
describe(torch.index_select(x, dim=1, index=indices))
Output[0]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 2])
Values:
tensor([[ 0., 2.],
[ 3., 5.]])
Input[1]:
indices = torch.LongTensor([0, 0])
describe(torch.index_select(x, dim=0, index=indices))
Output[1]:
Type: torch.FloatTensor
Shape/size: torch.Size([2, 3])
Values:
tensor([[ 0., 1., 2.],
[ 0., 1., 2.]])
Input[2]:
row_indices = torch.arange(2).long()
col_indices = torch.LongTensor([0, 1])
describe(x[row_indices, col_indices])
Output[2]:
Type: torch.FloatTensor
Shape/size: torchC语言入门基础必备知识串讲-超详细!(新人疑惑解决)
C语言入门基础必备知识串讲-详细梳理!(新人疑惑解决,建议收藏)
C语言入门基础必备知识串讲-详细梳理!(新人疑惑解决,建议收藏)