PyTorch 作为当前最受欢迎的深度学习框架之一,其设计哲学与 TensorFlow 等框架有着本质区别。我最初接触 PyTorch 时,最吸引我的是它的动态计算图(Dynamic Computation Graph)特性。与静态图框架不同,PyTorch 允许你在代码运行时动态构建和修改计算图,这种即时执行(Eager Execution)模式让调试过程变得异常直观。
重要提示:PyTorch 的 tensor 操作与 NumPy 数组高度相似,这使得已有 Python 科学计算经验的开发者能够快速上手。但要注意的是,PyTorch tensor 能够利用 GPU 加速计算,这是 NumPy 数组无法实现的。
核心优势具体体现在三个方面:
推荐使用 conda 进行环境管理,能有效解决依赖冲突问题。以下是标准安装命令:
bash复制conda create -n pytorch_env python=3.8
conda activate pytorch_env
conda install pytorch torchvision torchaudio -c pytorch
安装完成后,可以通过以下代码验证 GPU 是否可用:
python复制import torch
print(f"PyTorch version: {torch.__version__}")
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"CUDA devices: {torch.cuda.device_count()}")
Tensor 是 PyTorch 中最基本的数据结构,以下是一些必须掌握的核心操作:
python复制# 创建 tensor 的多种方式
x = torch.empty(5, 3) # 未初始化矩阵
y = torch.rand(5, 3) # 随机初始化矩阵
z = torch.zeros(5, 3, dtype=torch.long) # 指定数据类型
# 从已有数据创建
data = [[1, 2], [3, 4]]
tensor = torch.tensor(data)
# 类型转换
float_tensor = tensor.float() # 转为浮点型
numpy_array = tensor.numpy() # 转为 NumPy 数组
操作技巧:使用
torch.set_default_tensor_type()可以全局设置 tensor 类型,比如默认使用 GPU tensor。
PyTorch 的自动微分是通过构建计算图实现的。当设置 requires_grad=True 时,PyTorch 会跟踪所有相关操作:
python复制x = torch.ones(2, 2, requires_grad=True)
y = x + 2
z = y * y * 3
out = z.mean()
print(out) # 输出 tensor(27., grad_fn=<MeanBackward0>)
这个简单的例子中,PyTorch 自动构建了完整的计算历史,可以通过 .grad_fn 属性查看每个 tensor 的创建函数。
反向传播通过 backward() 方法触发:
python复制out.backward() # 计算梯度
print(x.grad) # 打印 d(out)/dx
实际应用中常见的几种情况:
backward()常见错误:忘记清零梯度会导致梯度累加。正确的做法是在每次迭代开始时执行
optimizer.zero_grad()。
PyTorch 通过 nn.Module 类提供神经网络构建的基类。一个典型的网络定义如下:
python复制import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 6, 3)
self.conv2 = nn.Conv2d(6, 16, 3)
self.fc1 = nn.Linear(16 * 6 * 6, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def num_flat_features(self, x):
size = x.size()[1:]
return torch.prod(torch.tensor(size))
训练神经网络需要定义损失函数和优化器:
python复制import torch.optim as optim
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
训练循环的基本结构:
python复制for epoch in range(10): # 训练10个epoch
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad() # 清零梯度
outputs = net(inputs) # 前向传播
loss = criterion(outputs, labels) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
running_loss += loss.item()
print(f'Epoch {epoch+1}, loss: {running_loss/len(trainloader)}')
PyTorch 提供了高效的数据加载工具:
python复制from torch.utils.data import Dataset, DataLoader
class CustomDataset(Dataset):
def __init__(self, data, transform=None):
self.data = data
self.transform = transform
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
sample = self.data[idx]
if self.transform:
sample = self.transform(sample)
return sample
# 使用示例
dataset = CustomDataset(data)
dataloader = DataLoader(dataset, batch_size=4, shuffle=True)
对于图像数据,torchvision 提供了丰富的变换:
python复制from torchvision import transforms
transform = transforms.Compose([
transforms.RandomHorizontalFlip(), # 随机水平翻转
transforms.RandomRotation(10), # 随机旋转
transforms.ToTensor(), # 转为Tensor
transforms.Normalize((0.5,), (0.5,)) # 标准化
])
实用技巧:在数据量不足时,合理的数据增强能显著提升模型泛化能力。但要注意,某些变换(如颜色抖动)可能不适用于所有任务。
PyTorch 提供了灵活的模型保存方式:
python复制# 保存整个模型
torch.save(model, 'model.pth')
# 仅保存模型参数(推荐方式)
torch.save(model.state_dict(), 'model_params.pth')
# 加载模型
model = TheModelClass(*args, **kwargs)
model.load_state_dict(torch.load('model_params.pth'))
model.eval() # 设置为评估模式
当在不同设备间迁移模型时需要注意:
python复制# 保存时指定设备
torch.save(model.state_dict(), 'model.pth',
_use_new_zipfile_serialization=True)
# 加载到指定设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.load_state_dict(torch.load('model.pth', map_location=device))
常见问题:在 CPU 上训练后保存的模型直接加载到 GPU 上会报错。正确的做法是使用
map_location参数指定目标设备。
nn.utils.clip_grad_norm_)torch.autograd.set_detect_anomaly(False)torch.cuda.amp 模块python复制from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
for data, target in dataloader:
optimizer.zero_grad()
with autocast():
output = model(data)
loss = criterion(output, target)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
经过多年 PyTorch 项目实践,我总结出几点关键建议:
对于想系统学习 PyTorch 的开发者,我建议按照以下路径推进: