自然语言处理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。但是,可以在初始化时指定张量,也可以在以后使用类型转换方法将张量转换为另一种类型(floatlongdouble等)。有两种方法可以指定初始化类型,一种是直接调用特定张量类型(如FloatTensorLongTensor)的构造函数,另一种是使用特殊的方法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语言入门基础必备知识串讲-详细梳理!(新人疑惑解决,建议收藏)

C语言入门基础必备知识串讲-详细梳理!(新人疑惑解决,建议收藏)

2-2-运维必备核心技能-nginx基础入门

Python3详细的数组基础操作-入门必备[列表的操作]