前言
PyTorch 是一个开源的深度学习框架,由 Facebook 开发,广泛应用于学术研究和工业领域。与 TensorFlow 类似,PyTorch 提供了强大的工具用于构建和训练深度学习模型。PyTorch 的动态计算图和灵活的 API 使得它特别适合研究和实验。它还支持 GPU 加速,适用于构建复杂的神经网络。
本教程将详细介绍 PyTorch 的每个常用指令和功能,帮助你从基础知识开始,逐步掌握如何使用 PyTorch 进行深度学习开发。
目录
-
PyTorch 基础
- 安装 PyTorch
- 创建张量(Tensors)
- 张量操作与计算
- 自动微分与反向传播
-
神经网络构建
- 使用
nn.Module
构建神经网络 - 激活函数与损失函数
- 优化器:SGD、Adam 等
- 自定义训练循环
- 使用
-
高级功能
- 数据集与数据加载器
- 使用 GPU 加速模型训练
- 保存与加载模型
-
卷积神经网络 (CNN)
- 构建 CNN 模型
- 训练与评估 CNN
-
递归神经网络 (RNN)
- 构建 RNN 与 LSTM
- 训练与评估 RNN 模型
1. PyTorch 基础
安装 PyTorch
PyTorch 可以通过 pip 安装。你可以根据你的操作系统和硬件(例如 GPU)选择合适的安装命令:
pip install torch torchvision torchaudio
导入 PyTorch:
import torch
创建张量(Tensors)
张量是 PyTorch 中的核心数据结构,它类似于 NumPy 数组,但支持 GPU 加速。
- 创建张量:
# 创建一个 3x3 的随机张量 x = torch.rand(3, 3) print(x) # 创建一个全 0 张量 x = torch.zeros(3, 3) print(x) # 创建一个全 1 张量 x = torch.ones(3, 3) print(x)
- 从列表或 NumPy 创建张量:
import numpy as np # 从列表创建张量 x = torch.tensor([1, 2, 3, 4]) print(x) # 从 NumPy 数组创建张量 np_array = np.array([5, 6, 7, 8]) x = torch.from_numpy(np_array) print(x)
张量操作与计算
PyTorch 提供了多种张量运算函数,如加法、乘法、矩阵乘法等。它们与 NumPy 的操作类似,但支持自动微分。
- 基本运算:
x = torch.rand(3, 3) y = torch.rand(3, 3) # 加法 z = x + y print(z) # 乘法 z = x * y print(z) # 矩阵乘法 z = torch.matmul(x, y) print(z)
- 重塑张量:
x = torch.rand(16) # 重塑为 4x4 的张量 x_reshaped = x.view(4, 4) print(x_reshaped)
自动微分与反向传播
PyTorch 的自动微分机制通过
autograd
实现,它能够自动计算张量的梯度,从而实现反向传播。 - 计算梯度:
# 创建一个张量,并设置 requires_grad=True 以跟踪其梯度 x = torch.tensor([2.0, 3.0], requires_grad=True) # 定义一个简单的函数 y = x[0]**2 + x[1]**3 # 进行反向传播,计算梯度 y.backward() # 输出梯度 print(x.grad) # x[0] 的梯度是 4.0,x[1] 的梯度是 27.0
2. 神经网络构建
PyTorch 提供了 torch.nn
模块,用于构建神经网络。通过继承 nn.Module
类,你可以创建自定义的神经网络。
使用 nn.Module
构建神经网络
以下是一个使用 PyTorch 构建的简单前馈神经网络:
import torch.nn as nn
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(28 * 28, 128) # 输入层到隐藏层
self.fc2 = nn.Linear(128, 64) # 隐藏层
self.fc3 = nn.Linear(64, 10) # 输出层
def forward(self, x):
x = x.view(-1, 28 * 28) # 展平输入
x = torch.relu(self.fc1(x)) # 激活函数 ReLU
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x
# 创建模型实例
model = SimpleNN()
print(model)
激活函数与损失函数
- 激活函数:PyTorch 提供了多种激活函数,可以在网络的前向传播中使用。
# 使用 ReLU 激活函数 x = torch.rand(5, 5) x = torch.relu(x)
- 损失函数:用于计算模型预测与真实标签之间的误差。
criterion = nn.CrossEntropyLoss() # 适用于分类问题的交叉熵损失
优化器:SGD、Adam 等
优化器用于更新模型参数。PyTorch 提供了多种优化器,如 SGD 和 Adam。
- 使用 SGD 优化器:
import torch.optim as optim # 使用 SGD 优化器 optimizer = optim.SGD(model.parameters(), lr=0.01)
- 使用 Adam 优化器:
optimizer = optim.Adam(model.parameters(), lr=0.001)
自定义训练循环
以下是一个简单的训练循环示例,用于训练神经网络模型。
# 假设我们有训练数据 loader
for epoch in range(10):
for batch_idx, (data, target) in enumerate(train_loader):
# 将梯度置零
optimizer.zero_grad()
# 前向传播
output = model(data)
loss = criterion(output, target)
# 反向传播
loss.backward()
# 更新权重
optimizer.step()
print(f'Epoch {epoch + 1}, Loss: {loss.item()}')
3. 高级功能
数据集与数据加载器
PyTorch 提供了 torch.utils.data
模块,用于加载数据集。你可以使用内置的数据集,或者自定义自己的数据集。
- 使用内置数据集(MNIST):
from torchvision import datasets, transforms # 定义数据变换 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) ]) # 加载 MNIST 数据集 train_dataset = datasets.MNIST(root='data', train=True, transform=transform, download=True) test_dataset = datasets.MNIST(root='data', train=False, transform=transform, download=True) # 创建数据加载器 train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False)
- 自定义数据集:
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]
使用 GPU 加速模型训练
PyTorch 支持使用 GPU 加速模型训练。你可以通过将模型和张量移动到 GPU 上来加速计算。
- 检查 GPU 可用性:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') print(device)
- 将模型和数据移动到 GPU:
model.to(device)
# 将数据移动到 GPU
data, target = data.to(device), target.to(device)
保存与加载模型
你可以通过保存和加载模型的权重来持久化训练的模型。
- 保存模型:
torch.save(model.state_dict(), 'model.pth')
- 加载模型:
model = SimpleNN() model.load_state_dict(torch.load('model.pth'))
4. 卷积神经网络 (CNN)
卷积神经网络(CNN)在处理图像数据时非常有效。它能够通过卷积层提取图像的局部特征,并通过池化层减少特征图的维度。以下部分将详细介绍如何在 PyTorch 中构建和训练 CNN 模型。
构建 CNN 模型
我们将使用 PyTorch 的 torch.nn
模块构建一个 CNN 模型来处理 MNIST 手写数字分类任务。该模型包含卷积层、池化层和全连接层。
import torch.nn as nn
import torch.nn.functional as F
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
# 卷积层 1:输入 1 个通道,输出 32 个通道,卷积核 3x3
self.conv1 = nn.Conv2D(1, 32, kernel_size=3)
# 卷积层 2:输入 32 个通道,输出 64 个通道
self.conv2 = nn.Conv2D(32, 64, kernel_size=3)
# 最大池化层:2x2 核
self.pool = nn.MaxPool2D(2, 2)
# 全连接层 1
self.fc1 = nn.Linear(64 * 12 * 12, 128) # MNIST 图像 28x28,经过两次卷积和池化后为 12x12
# 全连接层 2
self.fc2 = nn.Linear(128, 10) # 输出为 10 类别(0-9)
def forward(self, x):
# 前向传播
x = self.pool(F.relu(self.conv1(x))) # 卷积 -> ReLU -> 池化
x = self.pool(F.relu(self.conv2(x))) # 卷积 -> ReLU -> 池化
x = x.view(-1, 64 * 12 * 12) # 展平张量以适配全连接层
x = F.relu(self.fc1(x)) # 全连接层 -> ReLU
x = self.fc2(x) # 输出层
return x
# 实例化模型
model = CNN()
print(model)
训练与评估 CNN 模型
接下来,我们将训练这个 CNN 模型,并在 MNIST 数据集上进行评估。
- 数据加载与准备:
import torch.optim as optim from torchvision import datasets, transforms # 定义图像变换:将图像转换为张量并标准化 transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]) # 加载 MNIST 数据集 train_dataset = datasets.MNIST(root='data', train=True, transform=transform, download=True) test_dataset = datasets.MNIST(root='data', train=False, transform=transform, download=True) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False)
- 编译模型:我们将使用 交叉熵损失 和 Adam 优化器 来训练模型。
criterion = nn.CrossEntropyLoss() # 交叉熵损失函数 optimizer = optim.Adam(model.parameters(), lr=0.001) # Adam 优化器
- 训练模型:以下是训练循环代码,它包括前向传播、计算损失、反向传播以及权重更新。
for epoch in range(10): # 训练 10 个周期 running_loss = 0.0 for i, (inputs, labels) in enumerate(train_loader): # 梯度清零 optimizer.zero_grad() # 前向传播 outputs = model(inputs) loss = criterion(outputs, labels) # 反向传播 loss.backward() optimizer.step() # 打印损失值 running_loss += loss.item() if i % 100 == 99: # 每 100 个 batch 打印一次 print(f'Epoch {epoch + 1}, Batch {i + 1}, Loss: {running_loss / 100:.3f}') running_loss = 0.0
- 模型评估:在测试集上评估模型的准确性。
correct = 0 total = 0 model.eval() # 设置模型为评估模式 with torch.no_grad(): # 禁用梯度计算,以提高推理速度 for inputs, labels in test_loader: outputs = model(inputs) _, predicted = torch.max(outputs, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print(f'Accuracy on test set: {100 * correct / total:.2f}%')
5. 递归神经网络 (RNN)
递归神经网络(RNN)特别适合处理序列数据,例如时间序列、自然语言处理等任务。PyTorch 提供了多种 RNN 层,如 RNN、GRU 和 LSTM。
构建 RNN 与 LSTM 模型
LSTM(长短期记忆网络)是一种改进的 RNN,能够更好地处理长期依赖关系。下面是一个简单的 LSTM 模型。
import torch.nn as nn
class LSTM(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(LSTM, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
# 定义 LSTM 层
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
# 全连接层
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
# 初始化隐藏状态和记忆状态
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
# 前向传播 LSTM
out, _ = self.lstm(x, (h0, c0))
# 取最后一个时间步的输出
out = self.fc(out[:, -1, :])
return out
# 实例化 LSTM 模型
model = LSTM(input_size=28, hidden_size=128, num_layers=2, output_size=10)
print(model)
训练与评估 RNN 模型
- 数据加载:
假设我们使用 MNIST 数据集,但将每行像素视为序列输入。
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False)
- 训练模型:
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(10):
running_loss = 0.0
for i, (inputs, labels) in enumerate(train_loader):
inputs = inputs.view(-1, 28, 28) # 将图像展平为序列形式
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print(f'Epoch {epoch + 1}, Batch {i + 1}, Loss: {running_loss / 100:.3f}')
running_loss = 0.0
- 评估模型:
correct = 0
total = 0
model.eval()
with torch.no_grad():
for inputs, labels in test_loader:
inputs = inputs.view(-1, 28, 28)
outputs = model(inputs)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy on test set: {100 * correct / total:.2f}%')
结论
通过本教程,你已经学习了如何使用 PyTorch 进行深度学习项目的构建与训练。PyTorch 强大的灵活性和动态计算图,使它成为了学术研究和工业应用中的首选工具。它提供了简洁的 API,可以让你轻松实现复杂的神经网络模型,并通过 GPU 加速显著提升训练效率。