一、PyTorch 基础
1.1 什么是 PyTorch
PyTorch 是 Facebook 开发的动态图深度学习框架,特点是:
- 语法接近 Python,容易上手
- 动态计算图,调试方便
- GPU 加速无缝集成
- 生态丰富,支持所有主流模型
1.2 核心概念:张量(Tensor)
张量 = 多维数组,是 PyTorch 最基本的数据结构,替代 NumPy 数组,支持 GPU 加速。
python
运行
import torch
# 创建张量
x = torch.tensor([1, 2, 3]) # 一维张量
y = torch.tensor([[1, 2], [3, 4]]) # 二维张量
z = torch.zeros(2, 3) # 全零张量
w = torch.randn(3, 3) # 随机正态分布张量
# 张量属性
print(x.shape) # 形状
print(x.dtype) # 数据类型
print(x.device) # 设备(CPU/GPU)
# 张量运算
a = torch.tensor([1, 2])
b = torch.tensor([3, 4])
print(a + b) # 加法
print(a * b) # 乘法
print(torch.matmul(a, b)) # 矩阵乘法
# 与 NumPy 互转
np_array = x.numpy() # 张量转 NumPy
tensor = torch.from_numpy(np_array) # NumPy 转张量
1.3 自动求导(Autograd)
PyTorch 最强大的功能之一,自动计算梯度,不用手动写反向传播。
python
运行
# 创建需要求导的张量
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2 + 3 * x + 1
# 自动计算梯度
y.backward()
# 查看梯度 dy/dx
print(x.grad) # 输出 7.0(2*2+3=7)
二、神经网络模块(nn.Module)
所有神经网络都继承自 nn.Module,这是 PyTorch 的核心。
2.1 定义模型的标准写法
python
运行
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(MyModel, self).__init__()
# 定义层
self.linear1 = nn.Linear(input_dim, hidden_dim)
self.relu = nn.ReLU()
self.linear2 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
# 前向传播
x = self.linear1(x)
x = self.relu(x)
x = self.linear2(x)
return x
# 创建模型
model = MyModel(input_dim=10, hidden_dim=20, output_dim=2)
print(model)
2.2 常用层
表格
| 层类型 | 作用 | 代码 |
|---|---|---|
| 线性层(全连接) | 普通神经网络层 | nn.Linear(in_features, out_features) |
| 卷积层 | 图像处理 | nn.Conv2d(in_channels, out_channels, kernel_size) |
| 池化层 | 降维 | nn.MaxPool2d(kernel_size) |
| 激活函数 | 引入非线性 | nn.ReLU(), nn.Sigmoid(), nn.Tanh() |
| Dropout | 防止过拟合 | nn.Dropout(p=0.5) |
| BatchNorm | 加速训练 | nn.BatchNorm2d(num_features) |
2.3 常用损失函数
表格
| 任务类型 | 损失函数 | 代码 |
|---|---|---|
| 回归任务 | 均方误差 | nn.MSELoss() |
| 二分类 | 二元交叉熵 | nn.BCEWithLogitsLoss() |
| 多分类 | 交叉熵 | nn.CrossEntropyLoss() |
三、数据加载与处理
3.1 Dataset 与 DataLoader
这是 PyTorch 加载数据的标准方式:
Dataset:存储数据和标签DataLoader:批量加载数据,支持打乱、多线程
python
运行
from torch.utils.data import Dataset, DataLoader
# 自定义数据集
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]
# 创建数据集
data = torch.randn(100, 10) # 100个样本,每个10维
labels = torch.randint(0, 2, (100,)) # 二分类标签
dataset = MyDataset(data, labels)
# 创建数据加载器
dataloader = DataLoader(
dataset,
batch_size=32, # 批量大小
shuffle=True, # 打乱顺序
num_workers=0 # 多线程(Windows下建议0)
)
# 遍历数据
for batch_data, batch_labels in dataloader:
print(batch_data.shape, batch_labels.shape)
3.2 内置数据集
PyTorch 提供了很多常用数据集,不用自己下载:
python
运行
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,
download=True,
transform=transform
)
test_dataset = datasets.MNIST(
root='./data',
train=False,
download=True,
transform=transform
)
四、模型训练与评估
4.1 标准训练流程
这是所有 PyTorch 模型训练的通用模板,你之前写的线性回归和 MNIST 都是这个流程:
python
运行
import torch.optim as optim
# 1. 定义模型、损失函数、优化器
model = MyModel(input_dim=10, hidden_dim=20, output_dim=2)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 2. 训练循环
epochs = 10
for epoch in range(epochs):
model.train() # 训练模式
running_loss = 0.0
for batch_data, batch_labels in dataloader:
# 梯度清零
optimizer.zero_grad()
# 前向传播
outputs = model(batch_data)
# 计算损失
loss = criterion(outputs, batch_labels)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
running_loss += loss.item()
# 打印训练信息
print(f'Epoch {epoch+1}, Loss: {running_loss/len(dataloader):.4f}')
4.2 模型评估
python
运行
model.eval() # 评估模式(关闭 Dropout 和 BatchNorm)
correct = 0
total = 0
# 不计算梯度,节省内存
with torch.no_grad():
for batch_data, batch_labels in test_dataloader:
outputs = model(batch_data)
_, predicted = torch.max(outputs.data, 1)
total += batch_labels.size(0)
correct += (predicted == batch_labels).sum().item()
print(f'Accuracy: {100 * correct / total:.2f}%')
五、保存与加载模型
5.1 保存和加载模型参数(推荐)
python
运行
# 保存模型参数
torch.save(model.state_dict(), 'model.pth')
# 加载模型参数
model = MyModel(input_dim=10, hidden_dim=20, output_dim=2)
model.load_state_dict(torch.load('model.pth'))
model.eval() # 评估模式
5.2 保存和加载整个模型(不推荐)
python
运行
# 保存整个模型
torch.save(model, 'model_full.pth')
# 加载整个模型
model = torch.load('model_full.pth')
model.eval()
六、GPU 加速
6.1 检查 GPU 是否可用
python
运行
print(torch.cuda.is_available()) # 输出 True 表示可用
6.2 将模型和数据移到 GPU
python
运行
# 方法1:使用 .cuda()
model = model.cuda()
data = data.cuda()
labels = labels.cuda()
# 方法2:使用 device(推荐,更灵活)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
data = data.to(device)
labels = labels.to(device)
七、优化器
7.1 常用优化器
python
运行
# SGD(随机梯度下降)
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# Adam(最常用)
optimizer = optim.Adam(model.parameters(), lr=0.001)
# RMSprop
optimizer = optim.RMSprop(model.parameters(), lr=0.001)
7.2 学习率调度器
动态调整学习率,提高模型性能:
python
运行
from torch.optim.lr_scheduler import StepLR
# 每10个epoch,学习率乘以0.1
scheduler = StepLR(optimizer, step_size=10, gamma=0.1)
# 在训练循环中添加
for epoch in range(epochs):
# ... 训练代码 ...
scheduler.step()
八、迁移学习
使用别人预训练好的模型,在自己的数据上微调,这是实际项目中最常用的方法。
python
运行
from torchvision import models
# 加载预训练的 ResNet18
model = models.resnet18(pretrained=True)
# 冻结所有层
for param in model.parameters():
param.requires_grad = False
# 替换最后一层,适应自己的任务(比如二分类)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 2)
# 只训练最后一层
optimizer = optim.Adam(model.fc.parameters(), lr=0.001)
九、常见问题与最佳实践
- 梯度爆炸 / 消失:使用 BatchNorm、残差连接、合适的初始化
- 过拟合:增加数据、使用 Dropout、L2 正则化、早停
- 训练慢:使用 GPU、增大 batch_size、使用混合精度训练
- 内存不足:减小 batch_size、使用梯度累积、释放不需要的张量
十、进阶内容
- 自定义层 :继承
nn.Module实现自己的层 - 混合精度训练 :使用
torch.cuda.amp加速训练,节省内存 - 分布式训练 :使用
torch.distributed在多 GPU / 多机器上训练 - TorchScript:将 PyTorch 模型转换为可部署的格式
- ONNX:将模型导出为 ONNX 格式,在其他框架上运行
总结
PyTorch 的核心就是张量 + 自动求导 + nn.Module,掌握了这三个,你就能写任何深度学习模型。
你之前学习的线性回归、CNN、Transformer 都是基于这个框架的。