|
@@ -75,6 +75,261 @@ PyTorch是一个由Facebook开源的深度学习框架,以其简洁易用、
|
|
|
* 通过不断的实践来巩固所学知识,提高解决问题的能力。
|
|
* 通过不断的实践来巩固所学知识,提高解决问题的能力。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+PyTorch 入门手册
|
|
|
|
|
+一、简介
|
|
|
|
|
+PyTorch 是一个基于 Python 的科学计算包,主要用于深度学习。它提供了张量计算、自动求导以及构建和训练神经网络的功能。由于其简洁性、灵活性和强大的 GPU 加速能力,PyTorch 在学术界和工业界都得到了广泛应用。
|
|
|
|
|
+二、安装
|
|
|
|
|
+(一)环境准备
|
|
|
|
|
+Python:确保你已经安装了 Python,建议使用 Python 3.6 及以上版本。
|
|
|
|
|
+包管理器:可以使用 pip 或 conda 来安装 PyTorch。
|
|
|
|
|
+(二)安装步骤
|
|
|
|
|
+pip 安装:
|
|
|
|
|
+CPU 版本:如果你的计算机没有 NVIDIA GPU,可以使用以下命令安装 CPU 版本的 PyTorch:
|
|
|
|
|
+pip install torch torchvision torchaudio
|
|
|
|
|
+
|
|
|
|
|
+GPU 版本:如果你的计算机有 NVIDIA GPU,并且已经安装了相应的 CUDA 驱动和 cuDNN 库,可以根据 CUDA 版本选择对应的安装命令。例如,对于 CUDA 11.3,可以使用以下命令:
|
|
|
|
|
+pip install torch==1.10.0+cu113 torchvision==0.11.1+cu113 torchaudio==0.10.0+cu113 -f https://download.pytorch.org/wholesale/torch_stable.html
|
|
|
|
|
+
|
|
|
|
|
+conda 安装:
|
|
|
|
|
+CPU 版本:
|
|
|
|
|
+conda install pytorch torchvision torchaudio cpuonly -c pytorch
|
|
|
|
|
+
|
|
|
|
|
+GPU 版本:
|
|
|
|
|
+conda install pytorch torchvision torchaudio cuda11.3 -c pytorch
|
|
|
|
|
+
|
|
|
|
|
+具体的 CUDA 版本和命令可以在 PyTorch 官方网站(https://pytorch.org/get-started/locally/)查询。
|
|
|
|
|
+三、基础概念
|
|
|
|
|
+(一)张量(Tensor)
|
|
|
|
|
+定义:张量是 PyTorch 中最基本的数据结构,类似于 Numpy 的 ndarray,但可以在 GPU 上进行计算。张量可以表示标量、向量、矩阵以及更高维的数据。
|
|
|
|
|
+创建张量:
|
|
|
|
|
+直接创建:
|
|
|
|
|
+import torch
|
|
|
|
|
+# 创建一个标量张量
|
|
|
|
|
+scalar = torch.tensor(5)
|
|
|
|
|
+# 创建一个向量张量
|
|
|
|
|
+vector = torch.tensor([1, 2, 3])
|
|
|
|
|
+# 创建一个矩阵张量
|
|
|
|
|
+matrix = torch.tensor([[1, 2], [3, 4]])
|
|
|
|
|
+
|
|
|
|
|
+从 Numpy 数组创建:
|
|
|
|
|
+import numpy as np
|
|
|
|
|
+arr = np.array([[1, 2], [3, 4]])
|
|
|
|
|
+tensor_from_np = torch.from_numpy(arr)
|
|
|
|
|
+
|
|
|
|
|
+创建特殊张量:
|
|
|
|
|
+# 创建全零张量
|
|
|
|
|
+zeros = torch.zeros((2, 3))
|
|
|
|
|
+# 创建全一张量
|
|
|
|
|
+ones = torch.ones((3, 2))
|
|
|
|
|
+# 创建随机张量
|
|
|
|
|
+random = torch.rand((2, 2))
|
|
|
|
|
+
|
|
|
|
|
+张量操作:
|
|
|
|
|
+索引和切片:张量的索引和切片操作与 Numpy 数组类似。
|
|
|
|
|
+matrix = torch.tensor([[1, 2], [3, 4]])
|
|
|
|
|
+# 取第一行
|
|
|
|
|
+row1 = matrix[0]
|
|
|
|
|
+# 取第一列
|
|
|
|
|
+col1 = matrix[:, 0]
|
|
|
|
|
+
|
|
|
|
|
+算术运算:张量支持各种算术运算,如加、减、乘、除等。
|
|
|
|
|
+a = torch.tensor([1, 2])
|
|
|
|
|
+b = torch.tensor([3, 4])
|
|
|
|
|
+c = a + b
|
|
|
|
|
+d = a * b
|
|
|
|
|
+
|
|
|
|
|
+矩阵运算:
|
|
|
|
|
+a = torch.tensor([[1, 2], [3, 4]])
|
|
|
|
|
+b = torch.tensor([[5, 6], [7, 8]])
|
|
|
|
|
+c = torch.mm(a, b)
|
|
|
|
|
+
|
|
|
|
|
+维度变换:
|
|
|
|
|
+matrix = torch.tensor([[1, 2], [3, 4]])
|
|
|
|
|
+# 转置矩阵
|
|
|
|
|
+transposed = matrix.t()
|
|
|
|
|
+# 改变形状
|
|
|
|
|
+reshaped = matrix.view(4)
|
|
|
|
|
+
|
|
|
|
|
+(二)自动求导(Autograd)
|
|
|
|
|
+原理:PyTorch 的自动求导机制允许我们自动计算张量的梯度。通过创建具有requires_grad=True的张量,PyTorch 会自动记录对该张量的所有操作,并在需要时计算梯度。
|
|
|
|
|
+示例:
|
|
|
|
|
+x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
|
|
|
|
|
+y = x * 2
|
|
|
|
|
+z = y.mean()
|
|
|
|
|
+z.backward()
|
|
|
|
|
+print(x.grad)
|
|
|
|
|
+
|
|
|
|
|
+在这个例子中,我们首先创建了一个需要求导的张量x,然后对x进行了乘法和均值运算得到z,最后调用z.backward()计算z关于x的梯度。
|
|
|
|
|
+(三)神经网络(Neural Network)
|
|
|
|
|
+定义:在 PyTorch 中,可以通过继承torch.nn.Module类来定义神经网络。
|
|
|
|
|
+构建简单神经网络:
|
|
|
|
|
+import torch.nn as nn
|
|
|
|
|
+import torch.nn.functional as F
|
|
|
|
|
+
|
|
|
|
|
+class SimpleNet(nnn.Module):
|
|
|
|
|
+ def __init__(self):
|
|
|
|
|
+ super(SimpleNet, self).__init__()
|
|
|
|
|
+ self.fc1 = nn.Linear(10, 20)
|
|
|
|
|
+ self.fc2 = nn.Linear(20, 2)
|
|
|
|
|
+
|
|
|
|
|
+ def forward(self, x):
|
|
|
|
|
+ x = F.relu(self.fc1(x))
|
|
|
|
|
+ x = self.fc2(x)
|
|
|
|
|
+ return x
|
|
|
|
|
+
|
|
|
|
|
+在这个例子中,我们定义了一个简单的神经网络SimpleNet,它包含两个全连接层,输入维度为 10,输出维度为 2。forward方法定义了网络的前向传播过程。
|
|
|
|
|
+四、数据加载与预处理
|
|
|
|
|
+(一)数据加载
|
|
|
|
|
+Dataset 类:PyTorch 提供了torch.utils.data.Dataset类作为所有数据集的基类。要使用自定义数据集,需要继承Dataset类并实现__len__和__getitem__方法。
|
|
|
|
|
+from torch.utils.data import Dataset
|
|
|
|
|
+
|
|
|
|
|
+class MyDataset(Dataset):
|
|
|
|
|
+ def __init__(self, data, labels):
|
|
|
|
|
+ self.data = data
|
|
|
|
|
+ self.labels = labels
|
|
|
|
|
+
|
|
|
|
|
+ def __len__(self):
|
|
|
|
|
+ return len(self.data)
|
|
|
|
|
+
|
|
|
|
|
+ def __getitem__(self, idx):
|
|
|
|
|
+ return self.data[idx], self.labels[idx]
|
|
|
|
|
+
|
|
|
|
|
+DataLoader 类:torch.utils.data.DataLoader类用于将数据集包装成可迭代的对象,方便进行批量训练。
|
|
|
|
|
+from torch.utils.data import DataLoader
|
|
|
|
|
+
|
|
|
|
|
+dataset = MyDataset(data, labels)
|
|
|
|
|
+loader = DataLoader(dataset, batch_size = 32, shuffle = true)
|
|
|
|
|
+
|
|
|
|
|
+在这个例子中,我们将MyDataset包装成DataLoader,设置批量大小为 32,并在每个 epoch 中打乱数据。
|
|
|
|
|
+(二)数据预处理
|
|
|
|
|
+常见预处理操作:常见的数据预处理操作包括标准化、归一化、数据增强等。
|
|
|
|
|
+from torchvision import transforms
|
|
|
|
|
+
|
|
|
|
|
+transform = transforms.Compose([
|
|
|
|
|
+ transforms.ToTensor(),
|
|
|
|
|
+ transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
|
|
|
|
|
+])
|
|
|
|
|
+
|
|
|
|
|
+在这个例子中,我们使用torchvision.transforms对图像数据进行预处理,首先将图像转换为张量,然后进行标准化。
|
|
|
|
|
+五、模型训练与评估
|
|
|
|
|
+(一)训练循环
|
|
|
|
|
+设置训练参数:
|
|
|
|
|
+import torch.optim as optim
|
|
|
|
|
+
|
|
|
|
|
+model = SimpleNet()
|
|
|
|
|
+criterion = nn.CrossEntropyLoss()
|
|
|
|
|
+optimizer = optim.SGD(model.parameters(), lr = 0.01)
|
|
|
|
|
+
|
|
|
|
|
+在这个例子中,我们创建了一个SimpleNet模型,使用交叉熵损失函数和随机梯度下降优化器。
|
|
|
|
|
+2. 训练循环:
|
|
|
|
|
+for epoch in range(10):
|
|
|
|
|
+ for inputs, labels in loader:
|
|
|
|
|
+ optimizer.zero_grad()
|
|
|
|
|
+ outputs = model(inputs)
|
|
|
|
|
+ loss = criterion(outputs, labels)
|
|
|
|
|
+ loss.backward()
|
|
|
|
|
+ optimizer.step()
|
|
|
|
|
+ print(f'Epoch {epoch + 1}, Loss: {loss.item()}')
|
|
|
|
|
+
|
|
|
|
|
+在这个例子中,我们进行了 10 个 epoch 的训练,在每个 epoch 中,遍历数据加载器,进行前向传播、计算损失、反向传播和优化器更新。
|
|
|
|
|
+(二)模型评估
|
|
|
|
|
+评估模式:在评估模型时,需要将模型设置为评估模式,以关闭一些训练时的操作,如 dropout 和批量归一化。
|
|
|
|
|
+model.eval()
|
|
|
|
|
+
|
|
|
|
|
+评估指标:常见的评估指标包括准确率、召回率、F1 值等。
|
|
|
|
|
+correct = 0
|
|
|
|
|
+total = 0
|
|
|
|
|
+with torch.no_grad():
|
|
|
|
|
+ for inputs, labels in loader:
|
|
|
|
|
+ outputs = model(inputs)
|
|
|
|
|
+ _, predicted = torch.max(outputs.data, 1)
|
|
|
|
|
+ total = total + labels.size(0)
|
|
|
|
|
+ correct = correct + (predicted == labels).sum().item()
|
|
|
|
|
+accuracy = correct / total
|
|
|
|
|
+print(f'Accuracy: {accuracy}')
|
|
|
|
|
+
|
|
|
|
|
+在这个例子中,我们计算了模型在测试集上的准确率。
|
|
|
|
|
+六、保存与加载模型
|
|
|
|
|
+(一)保存模型
|
|
|
|
|
+保存整个模型:
|
|
|
|
|
+torch.save(model, 'model.pth')
|
|
|
|
|
+
|
|
|
|
|
+保存模型参数:
|
|
|
|
|
+torch.save(model.parameters(), 'params.pth')
|
|
|
|
|
+
|
|
|
|
|
+(二)加载模型
|
|
|
|
|
+加载整个模型:
|
|
|
|
|
+loaded_model = torch.load('model.pth')
|
|
|
|
|
+
|
|
|
|
|
+加载模型参数:
|
|
|
|
|
+model = SimpleNet()
|
|
|
|
|
+model.load_state_dict(torch.load('params.pth'))
|
|
|
|
|
+
|
|
|
|
|
+七、案例实战:手写数字识别
|
|
|
|
|
+(一)数据集准备
|
|
|
|
|
+MNIST 数据集:我们使用 MNIST 数据集,它包含手写数字的图像和标签。
|
|
|
|
|
+from torchvision import datasets, transforms
|
|
|
|
|
+
|
|
|
|
|
+train_dataset = datasets.MNIST(root = './data', train = true, download = true, transform = transform)
|
|
|
|
|
+test_dataset = datasets.MNIST(root = './data', train = false, download = true, transform = transform)
|
|
|
|
|
+
|
|
|
|
|
+数据加载器:
|
|
|
|
|
+train_loader = DataLoader(train_dataset, batch_size = 64, shuffle = true)
|
|
|
|
|
+test_loader = DataLoader(test_dataset, batch_size = 128, shuffle = false)
|
|
|
|
|
+
|
|
|
|
|
+(二)模型定义
|
|
|
|
|
+定义神经网络:
|
|
|
|
|
+class MNISTNet(nnn.Module):
|
|
|
|
|
+ def __init__(self):
|
|
|
|
|
+ super(MNISTNet, self).__init__()
|
|
|
|
|
+ self.conv1 = nn.Conv2d(1, 16, kernel_size = 3)
|
|
|
|
|
+ self.conv2 = nn.Conv2d(16, 32, kernel_size = 3)
|
|
|
|
|
+ self.fc1 = nn.Linear(32 * 5 * 5, 128)
|
|
|
|
|
+ self.fc2 = nn.Linear(128, 10)
|
|
|
|
|
+
|
|
|
|
|
+ def forward(self, x):
|
|
|
|
|
+ x = F.relu(self.conv1(x))
|
|
|
|
|
+ x = F.max_pool2d(x, 2)
|
|
|
|
|
+ x = F.relu(self.conv2(x))
|
|
|
|
|
+ x = F.max_pool2d(x, 2)
|
|
|
|
|
+ x = x.view(-1, 32 * 5 * 5)
|
|
|
|
|
+ x = F.relu(self.fc1(x))
|
|
|
|
|
+ x = self.fc2(x)
|
|
|
|
|
+ return x
|
|
|
|
|
+
|
|
|
|
|
+(三)模型训练与评估
|
|
|
|
|
+训练模型:
|
|
|
|
|
+model = MNISTNet()
|
|
|
|
|
+criterion = nn.CrossEntropyLoss()
|
|
|
|
|
+optimizer = optim.Adam(model.parameters(), lr = 0.001)
|
|
|
|
|
+
|
|
|
|
|
+for epoch in range(10):
|
|
|
|
|
+ for inputs, labels in train_loader:
|
|
|
|
|
+ optimizer.zero_grad()
|
|
|
|
|
+ outputs = model(inputs)
|
|
|
|
|
+ loss = criterion(outputs, labels)
|
|
|
|
|
+ loss.backward()
|
|
|
|
|
+ optimizer.step()
|
|
|
|
|
+ print(f'Epoch {epoch + 1}, Loss: {loss.item()}')
|
|
|
|
|
+
|
|
|
|
|
+评估模型:
|
|
|
|
|
+model.eval()
|
|
|
|
|
+correct = 0
|
|
|
|
|
+total = 0
|
|
|
|
|
+with torch.no_grad():
|
|
|
|
|
+ for inputs, labels in test_loader:
|
|
|
|
|
+ outputs = model(inputs)
|
|
|
|
|
+ _, predicted = torch.max(outputs.data, 1)
|
|
|
|
|
+ total = total + labels.size(0)
|
|
|
|
|
+ correct = correct + (predicted == labels).sum().item()
|
|
|
|
|
+accuracy = correct / total
|
|
|
|
|
+print(f'Accuracy: {accuracy}')
|
|
|
|
|
+
|
|
|
|
|
+八、总结
|
|
|
|
|
+通过本手册,你学习了 PyTorch 的基础概念、安装方法、数据加载与预处理、模型训练与评估、模型保存与加载以及一个简单的手写数字识别案例。PyTorch 提供了丰富的功能和工具,帮助你构建和训练深度学习模型。在实际应用中,你可以根据具体需求进行调整和优化。如果你对某些部分还有疑问,建议参考 PyTorch 的官方文档(https://pytorch.org/docs/stable/),以获取更详细的信息。
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
## 资源
|
|
## 资源
|
|
|
|
|
|
|
|
[pytorch-cpp C++的PyTorch](http://www.gitpp.com/hugindata/pytorch-cpp)
|
|
[pytorch-cpp C++的PyTorch](http://www.gitpp.com/hugindata/pytorch-cpp)
|