作为一名长期使用PyTorch进行深度学习开发的工程师,我经常被问到如何快速上手这个框架。今天我将通过一个完整的线性回归案例,带你体验PyTorch的核心特性。不同于其他教程使用复杂的图像分类问题,我们从最基础的回归任务开始,这样你能更专注于理解PyTorch的工作原理。
PyTorch近年来已成为增长最快的深度学习框架,这得益于它的几个关键优势:
我们从最简单的线性回归问题开始:y = a + bx + ε。首先生成100个数据点:
python复制import numpy as np
# 设置随机种子保证可复现性
np.random.seed(42)
# 生成特征x和标签y
x = np.random.rand(100, 1)
y = 1 + 2 * x + 0.1 * np.random.randn(100, 1)
# 打乱索引并划分训练集/验证集
idx = np.arange(100)
np.random.shuffle(idx)
train_idx, val_idx = idx[:80], idx[80:]
x_train, y_train = x[train_idx], y[train_idx]
x_val, y_val = x[val_idx], y[val_idx]
提示:在实际项目中,数据划分比例通常根据数据集大小调整。对于大数据集,验证集比例可以更小。
梯度下降是训练模型的核心算法,包含以下步骤:
在Numpy中的实现如下:
python复制# 参数初始化
a = np.random.randn(1)
b = np.random.randn(1)
learning_rate = 0.1
n_epochs = 1000
for epoch in range(n_epochs):
# 前向传播
yhat = a + b * x_train
# 损失计算
error = y_train - yhat
loss = (error ** 2).mean()
# 梯度计算
a_grad = -2 * error.mean()
b_grad = -2 * (x_train * error).mean()
# 参数更新
a = a - learning_rate * a_grad
b = b - learning_rate * b_grad
PyTorch中的基本数据结构是张量(tensor),类似于Numpy数组但支持GPU加速:
python复制import torch
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# 将Numpy数组转换为PyTorch张量并移至指定设备
x_train_tensor = torch.from_numpy(x_train).float().to(device)
y_train_tensor = torch.from_numpy(y_train).float().to(device)
注意:在模型和数据量较大时,GPU加速能显著提升训练速度。但要注意GPU显存限制。
PyTorch的autograd系统自动计算梯度:
python复制# 定义需要计算梯度的参数
a = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
b = torch.randn(1, requires_grad=True, dtype=torch.float, device=device)
for epoch in range(n_epochs):
yhat = a + b * x_train_tensor
loss = ((y_train_tensor - yhat) ** 2).mean()
# 自动计算梯度
loss.backward()
# 手动更新参数(需要禁用梯度追踪)
with torch.no_grad():
a -= learning_rate * a.grad
b -= learning_rate * b.grad
# 清空梯度
a.grad.zero_()
b.grad.zero_()
PyTorch的动态计算图是其核心特性之一:
python复制from torchviz import make_dot
a = torch.randn(1, requires_grad=True, device=device)
b = torch.randn(1, requires_grad=True, device=device)
yhat = a + b * x_train_tensor
make_dot(yhat)
计算图会显示参数(蓝色)、运算(灰色)和梯度起点(绿色),帮助我们理解反向传播过程。
使用优化器自动处理参数更新:
python复制import torch.optim as optim
# 定义优化器
optimizer = optim.SGD([a, b], lr=learning_rate)
for epoch in range(n_epochs):
yhat = a + b * x_train_tensor
loss = ((y_train_tensor - yhat) ** 2).mean()
loss.backward()
optimizer.step() # 执行参数更新
optimizer.zero_grad() # 清空梯度
PyTorch提供多种损失函数实现:
python复制import torch.nn as nn
loss_fn = nn.MSELoss(reduction='mean')
# 在训练循环中使用
loss = loss_fn(y_train_tensor, yhat)
通过继承nn.Module创建自定义模型:
python复制class LinearRegression(nn.Module):
def __init__(self):
super().__init__()
self.linear = nn.Linear(1, 1) # 输入1维,输出1维
def forward(self, x):
return self.linear(x)
model = LinearRegression().to(device)
optimizer = optim.SGD(model.parameters(), lr=learning_rate)
整合所有组件后的完整训练代码:
python复制torch.manual_seed(42)
model = LinearRegression().to(device)
optimizer = optim.SGD(model.parameters(), lr=learning_rate)
loss_fn = nn.MSELoss()
for epoch in range(n_epochs):
model.train() # 设置训练模式
yhat = model(x_train_tensor)
loss = loss_fn(y_train_tensor, yhat)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 验证模型
model.eval()
with torch.no_grad():
y_pred = model(x_val_tensor)
val_loss = loss_fn(y_val_tensor, y_pred)
掌握了基础线性回归后,你可以尝试:
我在实际项目中发现,PyTorch的动态图特性特别适合研究型项目,可以快速实验不同模型结构。对于生产部署,可以考虑使用TorchScript将模型转换为静态图。