PyTorch 入门教程¶
概述¶
PyTorch是Facebook开发的深度学习框架,以动态计算图和Pythonic风格著称,是学术界和工业界最流行的深度学习框架之一。
安装配置¶
# CPU版本
pip install torch torchvision torchaudio
# GPU版本(CUDA 11.8)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 验证安装
python -c "import torch; print(torch.__version__); print(torch.cuda.is_available())"
张量基础¶
创建张量¶
import torch
# 从列表创建
x = torch.tensor([1, 2, 3])
# 创建特殊张量
zeros = torch.zeros(3, 3) # 全零
ones = torch.ones(3, 3) # 全一
rand = torch.rand(3, 3) # 随机[0,1)
randn = torch.randn(3, 3) # 标准正态分布
eye = torch.eye(3) # 单位矩阵
# 指定类型
x_float = torch.tensor([1, 2, 3], dtype=torch.float32)
张量操作¶
# 基本运算
a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])
# 逐元素运算
c = a + b # 加法
d = a * b # 乘法
e = torch.dot(a, b) # 点积
# 矩阵运算
mat1 = torch.randn(3, 4)
mat2 = torch.randn(4, 5)
result = torch.matmul(mat1, mat2) # 矩阵乘法
# 形状操作
x = torch.randn(2, 3, 4)
y = x.reshape(2, 12) # 重塑
z = x.permute(1, 0, 2) # 转置
GPU加速¶
# 检查GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 移动到GPU
x = torch.randn(1000, 1000)
x_gpu = x.to(device)
# 在GPU上运算
y_gpu = torch.matmul(x_gpu, x_gpu.T)
自动微分¶
autograd机制¶
# requires_grad=True 开启梯度追踪
x = torch.tensor(2.0, requires_grad=True)
# 前向传播
y = x ** 2 + 3 * x + 1
# 反向传播
y.backward()
# 查看梯度 dy/dx = 2x + 3
print(x.grad) # tensor(7.)
梯度计算示例¶
# 多变量函数
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
w = torch.tensor([0.5, 0.5, 0.5], requires_grad=True)
# 前向传播
y = torch.sum(x * w) + 2
# 反向传播
y.backward()
print(x.grad) # [0.5, 0.5, 0.5]
print(w.grad) # [1., 2., 3.]
神经网络¶
nn.Module基础¶
import torch.nn as nn
class SimpleNet(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(SimpleNet, self).__init__()
self.layer1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.layer2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
x = self.layer1(x)
x = self.relu(x)
x = self.layer2(x)
return x
# 创建模型
model = SimpleNet(784, 256, 10)
print(model)
常用层¶
# 全连接层
linear = nn.Linear(10, 5)
# 卷积层
conv2d = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, padding=1)
# 池化层
pool = nn.MaxPool2d(kernel_size=2)
# Dropout
dropout = nn.Dropout(p=0.5)
# BatchNorm
batchnorm = nn.BatchNorm1d(128)
# 激活函数
relu = nn.ReLU()
sigmoid = nn.Sigmoid()
tanh = nn.Tanh()
CNN示例¶
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2)
)
self.classifier = nn.Sequential(
nn.Linear(64 * 7 * 7, 128),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(128, 10)
)
def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return x
数据处理¶
Dataset与DataLoader¶
from torch.utils.data import Dataset, DataLoader
# 自定义数据集
class CustomDataset(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]
# 创建数据加载器
dataset = CustomDataset(data, labels)
dataloader = DataLoader(
dataset,
batch_size=32,
shuffle=True,
num_workers=2
)
数据增强¶
from torchvision import transforms
transform = transforms.Compose([
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(10),
transforms.ColorJitter(brightness=0.2),
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
模型训练¶
完整训练流程¶
import torch.optim as optim
from torch.utils.data import DataLoader
# 1. 准备数据
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32)
# 2. 定义模型
model = CNN().to(device)
# 3. 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 4. 训练循环
for epoch in range(num_epochs):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
# 5. 测试评估
model.eval()
correct = 0
total = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
_, predicted = torch.max(output.data, 1)
total += target.size(0)
correct += (predicted == target).sum().item()
accuracy = 100 * correct / total
print(f'Epoch [{epoch+1}/{num_epochs}], Accuracy: {accuracy:.2f}%')
学习率调度¶
# StepLR
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
# CosineAnnealing
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=50)
# OneCycleLR
scheduler = optim.lr_scheduler.OneCycleLR(
optimizer, max_lr=0.01, steps_per_epoch=len(train_loader), epochs=num_epochs
)
模型保存与加载¶
# 保存模型
torch.save(model.state_dict(), 'model.pth')
# 保存完整模型
torch.save(model, 'model_full.pth')
# 加载模型
model = CNN()
model.load_state_dict(torch.load('model.pth'))
model.eval()
# 保存检查点
torch.save({
'epoch': epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
}, 'checkpoint.pth')
实战示例:MNIST手写数字识别¶
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# 数据准备
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST('./data', train=False, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000)
# 模型定义
class MNISTNet(nn.Module):
def __init__(self):
super(MNISTNet, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.dropout1 = nn.Dropout(0.25)
self.dropout2 = nn.Dropout(0.5)
self.fc1 = nn.Linear(9216, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = torch.relu(self.conv1(x))
x = torch.relu(self.conv2(x))
x = torch.max_pool2d(x, 2)
x = self.dropout1(x)
x = torch.flatten(x, 1)
x = torch.relu(self.fc1(x))
x = self.dropout2(x)
x = self.fc2(x)
return torch.log_softmax(x, dim=1)
# 训练
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = MNISTNet().to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.NLLLoss()
for epoch in range(1, 11):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
# 测试
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
test_loss += criterion(output, target).item()
pred = output.argmax(dim=1, keepdim=True)
correct += pred.eq(target.view_as(pred)).sum().item()
accuracy = 100. * correct / len(test_dataset)
print(f'Epoch {epoch}: Accuracy {accuracy:.2f}%')
学习资源¶
# 官方资源
- PyTorch官网:https://pytorch.org
- PyTorch tutorials:https://pytorch.org/tutorials
- PyTorch文档:https://pytorch.org/docs
# 推荐课程
- fast.ai Practical Deep Learning
- Stanford CS231n Computer Vision
- Stanford CS224n NLP
下一步学习¶
- TensorFlow入门教程 - 对比学习另一个框架
- 深度学习教程 - 深入理论知识
- 计算机视觉 - CV实战应用