第二章(2):从零开始掌握PyTorch基础知识,打造NLP学习利器!
目录
- 第二章(2):从零开始掌握PyTorch基础知识,打造NLP学习利器!
- 1. Pytorch基础
- 1.1 Pytorch安装
- 1.1.1 Linux和Windows
- 1.1.2 ROCm和CUDA
- 1.2 创建张量
- 1.2.1 直接创建
- 1.2.2 通过数值创建
- (1)全零张量和全一张量
- (2)依据指定值创建
- (3)随机张量
- (4)等差序列的创建
- (5) 单位矩阵的创建
- 1.2.3 利用已有的张量创建新的张量
- (1) `torch.zeros_like()`和`torch.ones_like()`函数
- (2) `torch.cat()`函数
- 1.3 张量的类型与形状
- 1.3.1 张量类型
- (1 )浮点型数据类型
- 1. torch.float32 或 torch.FloatTensor
- 2. torch.float64 或 torch.DoubleTensor
- (2)整数型数据类型
- 1. torch.int32 或 torch.IntTensor
- 2. torch.int64 或 torch.LongTensor
- (3)布尔型数据类型
- 1. torch.bool 或 torch.BoolTensor
- 1.3.2 张量形状
- (1)改变形状
- 1. view() 函数
- 2. reshape() 函数
- (2)增加维度
- 1. unsqueeze() 函数
- (3)删除维度
- 1. squeeze() 函数
- 1.4 张量操作
- 1.4.1 数学运算
- (1)加法、减法、乘法、除法
- (2)矩阵乘法
- 1.4.2 逻辑运算
- (1)大小比较、相等比较
- 1.5 索引、切片和连接
- 1.5.1 索引
- 1.5.2 切片
- 1.5.3 连接
- (1)`cat()`函数
- (2)`stack()`函数
- 1.6 张量与计算图
- 1.6 总结
1. Pytorch基础
PyTorch是一个基于Python的科学计算库,也是目前深度学习领域中最流行的深度学习框架之一。PyTorch的核心理念是张量计算,即将数据表示为张量,在计算时使用自动微分机制优化模型。在使用PyTorch进行深度学习时,了解张量的基础操作、类型、大小等知识是非常重要的。
本文将介绍如何在PyTorch的安装、创建张量、了解张量的类型与大小、进行张量操作、索引、切片和连接、以及使用CUDA张量进行计算加速。
1.1 Pytorch安装
PyTorch支持Windows、Linux和MacOS等操作系统。
1.1.1 Linux和Windows
在Linux和Windows中,可以通过pip命令安装PyTorch和对应的torchvision和torchaudio包。如下所示:
pip install torch==1.10.0 torchvision==0.11.0 torchaudio==0.10.0
需要注意的是,这里的命令只能安装CPU版本的PyTorch。如果需要安装GPU版本的PyTorch,需要前往官网寻找对应版本的CUDA或ROCm支持。
1.1.2 ROCm和CUDA
在使用ROCm或CUDA时,需要单独指定版本号。以CUDA 10.2为例,可以使用以下命令来安装GPU版本的PyTorch:
pip install torch==1.10.0+cu102 torchvision==0.11.0+cu102 torchaudio==0.10.0 -f https://download.pytorch.org/whl/torch_stable.html
需要注意的是,+cu102表示使用CUDA 10.2,而+f对应的URL是从PyTorch官方网站下载PyTorch库和对应版本的依赖项。
更多安装命令,请参考:Previous PyTorch Versions | PyTorch
1.2 创建张量
1.2.1 直接创建
直接创建是最基本的创建张量的方法,我们可以使用torch.tensor()
函数来直接创建一个张量。该函数会根据输入的数据类型自动推断所创建的张量的数据类型,大小和形状等属性。例如,我们可以用以下代码创建一个大小为(2, 3)
的浮点型张量:
import torch
x = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)
print(x)
实验结果:
tensor([[1., 2., 3.],
[4., 5., 6.]])
上述代码创建了一个大小为(2, 3)
的张量,并赋值给变量x
。张量的内容是由列表表示的,也就是[[1,2,3],[4,5,6]]
。张量中的元素类型为浮点型,这是由可选参数dtype
指定的,若不指定,则为默认的参数类型。
除了torch.tensor()
函数,我们还可以使用torch.from_numpy()
函数来创建张量。这个函数会把一个NumPy数组转换为PyTorch中的张量。这里需要注意的是,该函数创建的张量和原始NumPy数组共享底层的存储空间,也就是说,如果我们修改了张量中的某个元素,原始的NumPy数组也会受到影响。以下代码是一个例子:
import numpy as np
import torch
x = np.array([[1, 2, 3], [4, 5, 6]]) #定义的numpy类型
y = torch.from_numpy(x)
print(y)
y[0][2] = -1
print(x)
实验结果:
tensor([[1, 2, 3],
[4, 5, 6]])
[[ 1 2 -1]
[ 4 5 6]]
上述代码中,我们创建了一个NumPy
数组x
,接着使用torch.from_numpy()
函数将其转换为张量y
。然后我们修改了张量y
中的第一个元素的第三个分量,并且打印了原始的NumPy
数组x
。可以看到,由于y
和x
共享底层的存储空间,所以在修改了y
之后,x
也被修改了。
1.2.2 通过数值创建
除了直接创建以外,我们还可以使用一些预定义的函数来生成特定的张量,例如全零张量,全一张量,以及随机张量等。
(1)全零张量和全一张量
使用torch.zeros()
函数和torch.ones()
函数可以分别创建全零张量和全一张量。示例代码如下:
import torch
x = torch.zeros((2, 3), dtype=torch.float32)
y = torch.ones((2, 3), dtype=torch.float32)
print(x)
print(y)
实验结果:
tensor([[0., 0., 0.],
[0., 0., 0.]])
tensor([[1., 1., 1.],
[1., 1., 1.]])
上述代码中分别使用torch.zeros((2, 3))
函数和torch.ones((2, 3))
函数创建了维度相同的两个张量。同时,也指定了所创建张量的元素类型为浮点型dtype=torch.float32
。
tips:在实际应用中,全零张量和全一张量经常用于初始化神经网络中的权重和偏置等参数。
(2)依据指定值创建
创建相同数值的指定值张量,采用的函数为torch.full()
,示例如下:
import torch
x = torch.full((2, 3), 8)
print(x)
实验结果:
tensor([[8., 8., 8.],
[8., 8., 8.]])
我们使用torch.full((2, 3), 8)
函数创建了一个大小为(2, 3)
的张量,并将其中的所有元素设置为7
。
(3)随机张量
对于深度学习中的模型来说,随机张量是非常重要的。在PyTorch中,我们可以使用torch.randn()
和torch.rand()
等函数来生成正态分布和均匀分布的随机张量。示例如下:
import torch
x = torch.randn((2, 3))
y = torch.rand((3, 4))
print(x)
print(y)
实验结果:
tensor([[-1.2964, 0.8592, -0.5766],
[ 0.9974, -0.7744, -0.6711]])
tensor([[0.6243, 0.9297, 0.7626, 0.4891],
[0.4266, 0.7566, 0.3390, 0.5008],
[0.5415, 0.9943, 0.0577, 0.4002]])
上述代码中,我们使用了torch.randn((2, 3))
和torch.rand((3, 4))
函数来分别创建大小为(2, 3)
和(3, 4)
的张量。其中,torch.randn()
函数生成元素值服从标准正态分布的张量,而torch.rand()
函数生成元素值在区间[0,1)
之间均匀分布的张量。
(4)等差序列的创建
torch.arange()
函数和torch.linspace()
函数可以创建等差序列。其中,torch.arange()
函数的步长是自定义的,而torch.linspace()
函数则是在给定的范围内均匀地分布元素。示例如下:
import torch
x = torch.arange(0, 10, 2)
y = torch.linspace(0, 1, 5)
print(x)
print(y)
实验结果:
tensor([0, 2, 4, 6, 8])
tensor([0.0000, 0.2500, 0.5000, 0.7500, 1.0000])
在上述代码中,我们通过调用torch.arange(0, 10, 2)
函数来创建步长为2
,范围在[0,10)
内的等差序列。同时,我们还使用了torch.linspace(0, 1, 5)
函数来生成在区间[0, 1]
内五个等距的数值。
(5) 单位矩阵的创建
torch.eye(n)
可以创建大小为(n, n)
的单位矩阵,该矩阵的对角线上的元素都是1。示例如下:
import torch
x = torch.eye(3)
print(x)
实验结果:
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
在上述代码中,我们创建了大小为(3, 3)
的单位矩阵,并赋值给变量x
。
1.2.3 利用已有的张量创建新的张量
在PyTorch中,我们还可以利用已有的张量创建新的张量。下面介绍一下常用的这类函数。
(1) torch.zeros_like()
和torch.ones_like()
函数
torch.zeros_like()
和torch.ones_like()
函数是用处创建与某个张量大小相同的全0或者1的张量,示例如下:
import torch
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
y = torch.zeros_like(x)
z = torch.ones_like(x)
print(x)
print(y)
print(z)
实验结果:
tensor([[1, 2, 3],
[4, 5, 6]])
tensor([[0, 0, 0],
[0, 0, 0]])
tensor([[1, 1, 1],
[1, 1, 1]])
在上述代码中,我们首先创建一个大小为(2, 3)
的张量x
,然后使用torch.zeros_like(x)
和torch.ones_like(x)
函数分别创建了与x
大小相同的全0张量y
和全1张量z
。
(2) torch.cat()
函数
torch.cat()
函数可以沿着指定的维度将多个张量拼接成一个新的张量。例如,我们可以将两个大小相同的张量按行(维度0)拼接起来。示例代码如下:
import torch
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
y = torch.tensor([[7, 8, 9], [10, 11, 12]])
z = torch.cat([x, y], dim=0)
p = torch.cat([x, y], dim=1)
print(x)
print(y)
print(z)
print(p)
实验结果:
tensor([[1, 2, 3],
[4, 5, 6]])
tensor([[ 7, 8, 9],
[10, 11, 12]])
tensor([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]])
tensor([[ 1, 2, 3, 7, 8, 9],
[ 4, 5, 6, 10, 11, 12]])
这段代码创建了两个包含有相同维度的张量 x
和 y
,分别表示 2 行 3 列的矩阵。然后,使用 torch.cat()
函数将两个张量按照指定的维度进行拼接,生成了一个新的张量 z
和 p
。其中 dim=0
表示按照第一维(行)进行拼接,而 dim=1
表示按照第二维(列)进行拼接。最后,打印了四个张量的值。可以看到,x
和 y
没有变化,而 z
和 p
分别包含了 x
和 y
的所有元素。其中 z
为拼接后的形状为 4 行 3 列的矩阵,而 p
为拼接后的形状为 2 行 6 列的矩阵。
1.3 张量的类型与形状
1.3.1 张量类型
在 PyTorch 中,张量有多种数据类型,包括浮点型、整数型、布尔型等等。其中浮点型数据类型比较常用,下面将介绍常见的数据类型。
(1 )浮点型数据类型
1. torch.float32 或 torch.FloatTensor
该类型的张量是默认的浮点型,即 32 位浮点型。可以通过以下方式创建:
x = torch.tensor([1, 2, 3], dtype=torch.float32)
y = torch.FloatTensor([1, 2, 3])
2. torch.float64 或 torch.DoubleTensor
该类型的张量是 64 位浮点型,可用于精度要求较高的场合。可以通过以下方式创建:
x = torch.tensor([1, 2, 3], dtype=torch.float32)
y = torch.FloatTensor([1, 2, 3])
(2)整数型数据类型
1. torch.int32 或 torch.IntTensor
该类型的张量是默认的整数型,即 32 位整数型。可以通过以下方式创建:
x = torch.tensor([1, 2, 3], dtype=torch.int32)
y = torch.IntTensor([1, 2, 3])
2. torch.int64 或 torch.LongTensor
该类型的张量是 64 位整数型,可用于精度要求较高的场合。可以通过以下方式创建:
x = torch.tensor([1, 2, 3], dtype=torch.int64)
y = torch.LongTensor([1, 2, 3])
(3)布尔型数据类型
1. torch.bool 或 torch.BoolTensor
该类型的张量包含了两个值 True 和 False,通常用于逻辑运算。可以通过以下方式创建:
x = torch.tensor([True, False, True], dtype=torch.bool)
y = torch.BoolTensor([True, False, True])
1.3.2 张量形状
在 PyTorch 中,张量的形状可以是任意维度的多维数组。下面介绍常见的形状操作。
(1)改变形状
1. view() 函数
该函数用于改变张量的形状,但不会改变张量中的元素个数。例如,将一个形状为 (2, 3) 的张量变成形状为 (3, 2) 的张量:
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
y = x.view(3, 2)
print(x)
print(y)
实验结果:
tensor([[1, 2, 3],
[4, 5, 6]])
tensor([[1, 2],
[3, 4],
[5, 6]])
2. reshape() 函数
该函数与 view() 函数类似,同样用于改变张量的形状。不同的是,reshape() 函数返回一个新的张量对象,而不是原地修改原始张量。例如,将一个形状为 (2, 3) 的张量变成形状为 (3, 2) 的张量:
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
y = x.reshape(3, 2)
print(x)
print(y)
实验结果:
tensor([[1, 2, 3],
[4, 5, 6]])
tensor([[1, 2],
[3, 4],
[5, 6]])
(2)增加维度
1. unsqueeze() 函数
该函数用于在张量的指定位置增加一个维度。例如,将一个形状为 (2, 3) 的张量在第一维处增加一个维度:
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
y = x.unsqueeze(0)
print(x)
print(y)
实验结果:
tensor([[1, 2, 3],
[4, 5, 6]])
tensor([[[1, 2, 3],
[4, 5, 6]]])
(3)删除维度
1. squeeze() 函数
该函数用于删除张量中形状为 1 的维度。例如,将一个形状为 (1, 2, 1, 3) 的张量删除所有形状为 1 的维度:
x = torch.tensor([[[[1, 2, 3]]]])
y = x.squeeze()
print(x)
print(y)
这代码使用 PyTorch 创建了一个四维张量 x,形状为 (1, 1, 1, 3),即一个只有一个元素的四维数组,该元素是一个三元素列表 [1, 2, 3]。然后使用 squeeze() 函数删除了所有形状为 1 的维度,所以返回的张量 y 形状为 (3,),是一个一维张量,包含了原来 x 中的三个数值。
1.4 张量操作
在 PyTorch 中,张量可以进行各种数学运算、逻辑运算等等。下面介绍常见的操作。
1.4.1 数学运算
(1)加法、减法、乘法、除法
使用加法、减法、乘法、除法等符号进行数学运算。例如:
x = torch.tensor([1, 2, 3])
y = torch.tensor([4, 5, 6])
z = x + y
q = x - y
t = x * y
p = x / y
print(z)
print(q)
print(t)
print(p)
实验结果:
tensor([5, 7, 9])
tensor([-3, -3, -3])
tensor([ 4, 10, 18])
tensor([0, 0, 0])
(2)矩阵乘法
使用矩阵乘法运算。例如:
x = torch.tensor([[1, 2], [3, 4]])
y = torch.tensor([[5, 6], [7, 8]])
z = torch.matmul(x, y)
print(y)
实验结果:
tensor([[19, 22],
[43, 50])
1.4.2 逻辑运算
(1)大小比较、相等比较
使用大小比较、相等比较等符号进行逻辑运算。例如:
x = torch.tensor([1, 2, 3])
y = torch.tensor([2, 2, 2])
z = torch.tensor([1, 2, 3])
m = x > y
n = x == z
print(m)
print(n)
实验结果:
tensor([0, 0, 1], dtype=torch.uint8)
tensor([1, 1, 1], dtype=torch.uint8)
这段代码使用 PyTorch 创建了三个一维张量 x、y 和 z,分别包含数字 1, 2, 3,2, 2, 2 和 1, 2, 3。然后使用逻辑运算符 > 和 == 进行大小比较和相等比较,将结果分别赋值给 m 和 n。m 和 n 都是一维张量,包含了每个数字对应的大小比较结果和相等比较结果。最后通过 print() 函数输出 m 和 n 的值,以便在控制台上观察运算结果。
1.5 索引、切片和连接
本小节将介绍PyTorch中关于张量的三个重要操作:索引、切片和连接。在深度学习中,这些操作经常用于对数据进行预处理、选择感兴趣的部分或者组合不同的数据集。
1.5.1 索引
在PyTorch中,我们可以使用索引来访问张量的某个特定元素。为了说明索引的使用方法,我们首先创建一个二维张量:
x = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(x)
实验结果:
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
接下来,我们可以使用方括号[]来进行索引。索引的语法很简单,可以直接使用整数来访问张量的某行某列元素。例如,要访问第一行第二列的元素,我们可以写成:
print(x[0][1])
实验结果:
tensor(2)
我们也可以使用逗号,同时传递两个整数来访问某个特定位置的元素。例如,要访问第二行第三列的元素,我们可以写成:
print(x[1, 2])
实验结果:
tensor(6)
另外,我们可以使用负数来从张量的末尾开始进行索引。例如,要访问最后一行的第一个和第三个元素,我们可以写成:
print(x[-1, 0])
print(x[-1, -1])
实验结果:
tensor(7)
tensor(9)
1.5.2 切片
除了对单个元素进行索引,我们还可以使用切片来访问张量的一部分。切片是指提取张量的子集,例如,我们可以从张量的第二行开始提取两行数据。
切片使用[start:stop:step]
的形式表示,其中start
表示起始索引(包含),stop
表示终止索引(不包含),step
表示步长(默认为1)。
首先,我们可以使用冒号来提取整个行或列。例如,要提取第二行的所有元素,我们可以写成:
print(x[1, :])
实验结果:
tensor([4, 5, 6])
此外,我们还可以使用切片来选择给定范围内的元素,例如,要提取第二行和第三行的所有元素,可以写成:
print(x[1:3, :])
实验结果:
tensor([[4, 5, 6],
[7, 8, 9]])
我们也可以使用负数来从张量的末尾开始进行切片。例如,要提取后两行的所有元素,可以写成:
print(x[-2:, :])
实验结果:
tensor([[4, 5, 6],
[7, 8, 9]])
1.5.3 连接
在深度学习中,我们经常需要将数据集合并为一个更大的数据集。PyTorch中提供了多种方法来连接张量,包括cat()
和stack()
。
(1)cat()
函数
我们可以使用cat()函数按照指定的维度连接张量。
x = torch.tensor([[1, 2, 3],
[4, 5, 6]])
y = torch.tensor([[7, 8, 9],
[10, 11, 12]])
m = torch.cat((x, y), dim=0)
n = torch.cat((x, y), dim=1)
print(m)
print(n)
实验结果:
tensor([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]])
tensor([[ 1, 2, 3, 7, 8, 9],
[ 4, 5, 6, 10, 11, 12]])
(2)stack()
函数
stack()
函数可以将多个张量沿着新的维度堆叠在一起。例如,要堆叠两个行相同的张量,可以写成:
import torch
x = torch.tensor([1, 2, 3])
y = torch.tensor([4, 5, 6])
z = torch.stack((x, y), dim=0)
print(z)
实验结果:
tensor([[1, 2, 3],
[4, 5, 6]])
1.6 张量与计算图
PyTorch中的计算图是深度学习框架的基础概念之一,可以用于进行自动微分、反向传播等操作。计算图是一个由节点和边组成的数据结构,在PyTorch中,张量(Tensor)即为计算图的节点,而计算操作则为边。
PyTorch中的计算图由两种节点组成:叶子节点和非叶子节点。
叶子节点是指不依赖其他节点的节点,也就是输入节点。在PyTorch中,叶子节点可以是用户创建的张量,也可以是从文件加载的数据。
非叶子节点是指依赖于其他节点的节点,也就是计算节点。在PyTorch中,非叶子节点可以是各种操作(如加法、卷积、池化等)。
在PyTorch中,张量与计算图有着密切的联系。每一个张量都会被放入到计算图中,并构成计算图中的一个节点。当我们进行前向传播时,计算图会按照我们编写的代码执行,并生成计算图的输出结果。
在计算图中,每个非叶子节点都有一个grad_fn
属性,它表示该节点的求导公式。这些求导公式是通过自动微分技术生成的,并且是在计算图执行过程中动态生成的。当我们执行反向传播时,PyTorch会遍历计算图,计算每个节点的梯度。
例如:
import torch
# 创建张量并设置 requires_grad=True
x = torch.tensor([3.0, 4.0], requires_grad=True)
y = torch.tensor([5.0, 6.0], requires_grad=True)
# 执行计算
z = x**3 + y**2
# 计算z的梯度
z.backward(torch.tensor([3.0, 5.0]))
# 输出x和y的梯度
print(x.grad)
print(y.grad)
实验结果:
tensor([ 81., 240.])
tensor([30., 60.])
这段代码使用 PyTorch 库创建了两个张量
x
x
x 和
y
y
y,使其设置 requires_grad=True
,表示要计算它们的梯度。然后将它们用于计算另一个张量
z
z
z,公式如下所示:
z = x 3 + y 2 z = x^3 + y^2 z=x3+y2
接下来使用 backward()
方法计算
z
z
z 对
x
x
x 和
y
y
y的梯度,同时传入了一个张量 torch.tensor([3.0, 5.0])
作为权重
z
w
e
i
g
h
t
z_{weight}
zweight。我们计算得到
∂
z
/
∂
x
=
3
x
2
∂z/∂x=3x^2
∂z/∂x=3x2
∂
z
/
∂
y
=
2
y
∂z/∂y=2y
∂z/∂y=2y因此
z
w
e
i
g
h
t
×
∂
z
/
∂
x
=
[
3
,
5
]
∗
[
27
,
48
]
=
[
81
,
2400
]
z_{weight} ×∂z/∂x = [3,5]*[27,48]=[81,2400]
zweight×∂z/∂x=[3,5]∗[27,48]=[81,2400]
z
w
e
i
g
h
t
×
∂
z
/
∂
y
=
[
3
,
5
]
∗
[
10
,
12
]
=
[
30
,
60
]
z_{weight} ×∂z/∂y = [3,5]*[10,12]=[30,60]
zweight×∂z/∂y=[3,5]∗[10,12]=[30,60]并将它们保存在 x.grad
和 y.grad
中,可以通过打印这两个张量的值来查看结果。
1.6 总结
本章节主要介绍了 PyTorch 的基础知识,包括如何安装 PyTorch 和配置环境、如何创建张量(包括直接创建、通过数值创建和利用已有的张量创建新的张量)、如何设置张量的类型和形状、以及如何对张量进行数学和逻辑运算、索引、切片和连接。除此之外,还介绍了计算图的概念及其在 PyTorch 中的应用。具体内容包括:
-
PyTorch 安装:介绍了如何在 Linux 或 Windows 系统中安装 PyTorch,并介绍了如何根据需要选择 ROCm 或 CUDA。
-
创建张量:介绍了如何通过不同的方式创建张量,包括直接创建、通过数值创建和利用已有的张量创建新的张量。其中,通过数值创建又包括全零张量和全一张量、依据指定值创建、随机张量、等差序列的创建和单位矩阵的创建。
-
张量的类型与形状:介绍了 PyTorch 支持的不同数据类型和如何设置张量的形状,包括改变形状(使用
view()
函数和reshape()
函数)、增加维度(使用unsqueeze()
函数)和删除维度(使用squeeze()
函数)。 -
张量操作:介绍了如何对张量进行数学和逻辑运算,包括加法、减法、乘法、除法、矩阵乘法、大小比较和相等比较等。
-
索引、切片和连接:介绍了如何使用索引、切片和连接操作对张量进行操作,包括通过索引获取张量中的元素,通过切片截取部分张量并创建新的张量,以及使用
cat()
函数和stack()
函数将多个张量连接为一个张量。 -
张量与计算图:介绍了计算图的概念及其在 PyTorch 中的应用,包括张量节点和计算节点的概念、自动求导和反向传播等。
参考教程:
Previous PyTorch Versions | PyTorch
计算图——用Pytorch解释李宏毅老师PPT中的实例 - 知乎 (zhihu.com)