ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 概述 PyTorch是一个开源的深度学习框架,最初由Facebook's AI Research lab(FAIR)开发和维护。它提供了一个用于构建和训练神经网络模型的强大平台,广泛用于研究、开发和部署深度学习模型。PyTorch的主要特点和功能包括: * 动态计算图:PyTorch采用了动态计算图的方式,使开发人员能够轻松构建和修改计算图。这与其他框架如TensorFlow的静态计算图方式相比更加直观和易于调试。 * 自动求导:PyTorch自带自动求导功能,允许你轻松计算梯度。这在训练神经网络和进行梯度下降优化时非常有用。 * 多种模块和工具:PyTorch提供了深度学习的模块,如神经网络层、优化算法、损失函数等。它还支持GPU加速,允许在CPU和GPU上执行高性能计算。 * 丰富的社区支持:PyTorch拥有庞大的用户和开发者社区,提供了大量教程、示例代码和第三方扩展,有助于加速深度学习项目的开发。 * 深度学习研究:由于其灵活性和易用性,PyTorch在深度学习研究领域非常受欢迎,研究人员可以方便地快速尝试新的想法和算法。 ## 张量 张量 (Tensor) 是深度学习的基础,例如常见的 0 维张量称为标量 (scalar)、1 维张量称为向量 (vector)、2 维张量称为矩阵 (matrix)。Pytorch 本质上就是一个基于张量的数学计算工具包 ``` >>> import torch >>> torch.empty(2, 3) # empty tensor (uninitialized), shape (2,3) tensor([[2.7508e+23, 4.3546e+27, 7.5571e+31], [2.0283e-19, 3.0981e+32, 1.8496e+20]]) >>> torch.rand(2, 3) # random tensor, each value taken from [0,1) tensor([[0.8892, 0.2503, 0.2827], [0.9474, 0.5373, 0.4672]]) >>> torch.randn(2, 3) # random tensor, each value taken from standard normal distribution tensor([[-0.4541, -1.1986, 0.1952], [ 0.9518, 1.3268, -0.4778]]) >>> torch.zeros(2, 3, dtype=torch.long) # long integer zero tensor tensor([[0, 0, 0], [0, 0, 0]]) >>> torch.zeros(2, 3, dtype=torch.double) # double float zero tensor tensor([[0., 0., 0.], [0., 0., 0.]], dtype=torch.float64) >>> torch.arange(10) tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) ``` ### 基于已有的数组或 Numpy 数组创建张量 ``` >>> array = [[1.0, 3.8, 2.1], [8.6, 4.0, 2.4]] >>> torch.tensor(array) tensor([[1.0000, 3.8000, 2.1000], [8.6000, 4.0000, 2.4000]]) >>> import numpy as np >>> array = np.array([[1.0, 3.8, 2.1], [8.6, 4.0, 2.4]]) >>> torch.from_numpy(array) tensor([[1.0000, 3.8000, 2.1000], [8.6000, 4.0000, 2.4000]], dtype=torch.float64) ``` ### 使用 GPU 计算张量 ``` >>> torch.rand(2, 3).cuda() tensor([[0.0405, 0.1489, 0.8197], [0.9589, 0.0379, 0.5734]], device='cuda:0') >>> torch.rand(2, 3, device="cuda") tensor([[0.0405, 0.1489, 0.8197], [0.9589, 0.0379, 0.5734]], device='cuda:0') >>> torch.rand(2, 3).to("cuda") tensor([[0.9474, 0.7882, 0.3053], [0.6759, 0.1196, 0.7484]], device='cuda:0') ``` ### 张量计算 ``` >>> x = torch.tensor([1, 2, 3], dtype=torch.double) >>> y = torch.tensor([4, 5, 6], dtype=torch.double) >>> print(x + y) tensor([5., 7., 9.], dtype=torch.float64) >>> print(x - y) tensor([-3., -3., -3.], dtype=torch.float64) >>> print(x * y) tensor([ 4., 10., 18.], dtype=torch.float64) >>> print(x / y) tensor([0.2500, 0.4000, 0.5000], dtype=torch.float64) ``` 计算函数 ``` >>> x.dot(y) tensor(32., dtype=torch.float64) >>> x.sin() tensor([0.8415, 0.9093, 0.1411], dtype=torch.float64) >>> x.exp() tensor([ 2.7183, 7.3891, 20.0855], dtype=torch.float64) ``` 使用 Pytorch 进行计算的好处是更高效的执行速度,尤其当张量存储的数据很多时,而且还可以借助 GPU 进一步提高计算速度 ``` import torch import timeit M = torch.rand(1000, 1000) print(timeit.timeit(lambda: M.mm(M).mm(M), number=5000)) N = torch.rand(1000, 1000).cuda() print(timeit.timeit(lambda: N.mm(N).mm(N), number=5000)) ``` 输出 ``` 77.78975469999999 1.6584811117500067 ``` ### 自动微分 1. Pytorch 提供自动计算梯度的功能,可以自动计算一个函数关于一个变量在某一取值下的导数,从而基于梯度对参数进行优化,这就是机器学习中的训练过程。 2. 使用 Pytorch 计算梯度非常容易,只需要执行`tensor.backward()`,就会自动通过反向传播 (Back Propogation) 算法完成。 ``` >>> x = torch.tensor([2.], requires_grad=True) >>> y = torch.tensor([3.], requires_grad=True) >>> z = (x + y) * (y - 2) >>> print(z) tensor([5.], grad_fn=<MulBackward0>) >>> z.backward() >>> print(x.grad, y.grad) tensor([1.]) tensor([6.]) ``` ## 加载数据 1. Pytorch 提供了`DataLoader`和`Dataset`类(或`IterableDataset`)专门用于处理数据 2. 它们既可以加载 Pytorch 预置的数据集,也可以加载自定义数据。 3. 数据集类`Dataset`(或`IterableDataset`)负责存储样本以及它们对应的标签 4. 数据加载类`DataLoader`负责迭代地访问数据集中的样本 ### Dataset **映射型 (Map-style) 数据集** 继承自`Dataset`类,表示一个从索引到样本的映射(索引可以不是整数),这样我们就可以方便地通过`dataset[idx]`来访问指定索引的样本。这也是目前最常见的数据集类型 **迭代型 (Iterable-style) 数据集** 继承自`IterableDataset`,表示可迭代的数据集,它可以通过`iter(dataset)`以数据流 (steam) 的形式访问,适用于访问超大数据集或者远程服务器产生的数据 如迭代型 ``` from torch.utils.data import IterableDataset, DataLoader class MyIterableDataset(IterableDataset): def __init__(self, start, end): super(MyIterableDataset).__init__() assert end > start self.start = start self.end = end def __iter__(self): return iter(range(self.start, self.end)) ds = MyIterableDataset(start=3, end=7) # [3, 4, 5, 6] # Single-process loading print(list(DataLoader(ds, num_workers=0))) # Directly doing multi-process loading print(list(DataLoader(ds, num_workers=2))) ``` ### DataLoaders Pytorch 提供了`DataLoader`类专门负责处理这些操作,除了基本的`dataset`(数据集)和`batch_size`(batch 大小)参数以外,还有以下常用参数: * `shuffle`:是否打乱数据集; * `sampler`:采样器,也就是一个索引上的迭代器; * `collate_fn`:批处理函数,用于对采样出的一个 batch 中的样本进行处理(例如前面提过的 Padding 操作)。 ## 训练模型 ### 构建模型 们还是以前面加载的 FashionMNIST 数据库为例,构建一个神经网络模型来完成图像分类。模型同样继承自`nn.Module` ``` import torch from torch import nn device = 'cuda' if torch.cuda.is_available() else 'cpu' print(f'Using {device} device') class NeuralNetwork(nn.Module): def __init__(self): super(NeuralNetwork, self).__init__() self.flatten = nn.Flatten() self.linear_relu_stack = nn.Sequential( nn.Linear(28*28, 512), nn.ReLU(), nn.Linear(512, 256), nn.ReLU(), nn.Linear(256, 10), nn.Dropout(p=0.2) ) def forward(self, x): x = self.flatten(x) logits = self.linear_relu_stack(x) return logits model = NeuralNetwork().to(device) print(model) ```