摘要:前四篇讲理论,这一篇动手写代码。PyTorch 是 2026 年最主流的深度学习框架------从研究实验室到生产部署,它无处不在。这篇文章从零开始,介绍 PyTorch 最核心的四个概念:Tensor、Autograd、DataLoader、训练循环,并给出可直接运行的代码示例。
一、Tensor:PyTorch 的"基本单位"
什么是 Tensor?
Tensor(张量)是 PyTorch 中的基本数据结构------可以理解为 NumPy 的 ndarray 的升级版,加上GPU 加速 和自动求导功能。
| 维度 | 名称 | 示例 |
|---|---|---|
| 0 维 | 标量(Scalar) | 3.14 |
| 1 维 | 向量(Vector) | 1.0, 2.0, 3.0 |
| 2 维 | 矩阵(Matrix) | 图像(灰度: H×W) |
| 3 维 | 3D 张量 | 图像(RGB: C×H×W) |
| 4 维 | 4D 张量 | 批量图像(N×C×H×W) |
创建 Tensor
import torch
import numpy as np
# 从列表创建
t1 = torch.tensor([[1, 2], [3, 4]])
print(t1)
# tensor([[1, 2],
# [3, 4]])
# 从 NumPy 创建
t2 = torch.from_numpy(np.array([1.0, 2.0, 3.0]))
# 特殊张量
zeros = torch.zeros(3, 4) # 全零
ones = torch.ones(2, 3) # 全一
rand = torch.randn(3, 3) # 标准正态随机
arange = torch.arange(0, 10, 2) # [0, 2, 4, 6, 8]
# 指定设备和数据类型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
t_gpu = torch.tensor([1.0, 2.0], device=device, dtype=torch.float32)
Tensor 的运算
a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])
# 基础运算
print(a + b) # tensor([5., 7., 9.])
print(a * b) # tensor([4., 10., 18.]) ← 逐元素乘
print(a @ b) # tensor(32.) ← 点积
# 矩阵乘法
m1 = torch.randn(3, 4)
m2 = torch.randn(4, 5)
result = m1 @ m2 # shape: (3, 5)
# 形状操作
x = torch.randn(2, 3, 4)
print(x.shape) # torch.Size([2, 3, 4])
print(x.view(2, -1)) # 展平为 [2, 12]
print(x.permute(1,0,2)) # 调换维度为 [3, 2, 4]
Tensor 的"魔法":设备迁移
PyTorch 的一大优势是一行代码切换 CPU/GPU:
# 在 GPU 上创建/运算比 CPU 快几十倍
t = torch.randn(1000, 1000)
# 转移到 GPU(如果可用)
if torch.cuda.is_available():
t = t.cuda() # 或 t = t.to("cuda")
result = t @ t.T # 在 GPU 上执行矩阵乘法
t = t.cpu() # 转回 CPU
二、Autograd:自动求导引擎
在第二篇文章中,我们手动推导了反向传播的数学原理。PyTorch 最强大的功能之一就是自动帮你做这件事。
requires_grad:开启梯度追踪
# 创建一个需要梯度的 Tensor
x = torch.tensor([2.0], requires_grad=True)
w = torch.tensor([3.0], requires_grad=True)
b = torch.tensor([1.0], requires_grad=True)
# 定义计算: y = w * x + b
y = w * x + b
# 反向传播
y.backward()
# 查看梯度
print(x.grad) # tensor([3.]) ← dy/dx = w = 3
print(w.grad) # tensor([2.]) ← dy/dw = x = 2
print(b.grad) # tensor([1.]) ← dy/db = 1
完整的线性回归示例
import torch
# 生成数据: y = 2x + 1 + 噪声
x = torch.randn(100, 1)
y_true = 2 * x + 1 + 0.1 * torch.randn(100, 1)
# 初始化参数
w = torch.randn(1, 1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)
learning_rate = 0.1
# 训练循环
for step in range(100):
# 1. 前向传播
y_pred = x @ w + b
# 2. 计算损失(均方误差)
loss = ((y_pred - y_true) ** 2).mean()
# 3. 反向传播(自动计算梯度!)
loss.backward()
# 4. 梯度下降更新(手动更新)
with torch.no_grad():
w -= learning_rate * w.grad
b -= learning_rate * b.grad
# 清空梯度(重要!)
w.grad.zero_()
b.grad.zero_()
if step % 20 == 0:
print(f"Step {step}: loss = {loss.item():.4f}")
print(f"Final: w = {w.item():.3f}, b = {b.item():.3f}")
# 应该接近 w≈2.0, b≈1.0
关键点:
requires_grad=True告诉 PyTorch 要追踪这个张量的梯度loss.backward()自动从 loss 反向传播到所有开启了梯度的张量.grad保存计算出的梯度值- 每次更新后必须调用
.grad.zero_(),否则梯度会累积
三、Dataset 和 DataLoader:数据流水线
神经网络训练需要反复、批量地读取数据。PyTorch 提供了两个工具来管理这个过程。
自定义 Dataset
from torch.utils.data import Dataset, DataLoader
class MyDataset(Dataset):
"""自定义数据集:只需要实现 3 个方法"""
def __init__(self, data, labels):
self.data = torch.tensor(data, dtype=torch.float32)
self.labels = torch.tensor(labels, dtype=torch.long)
def __len__(self):
"""返回数据集大小"""
return len(self.data)
def __getitem__(self, idx):
"""返回第 idx 个样本 (data, label)"""
return self.data[idx], self.labels[idx]
DataLoader:自动批处理
# 假设有 1000 个训练样本
dataset = MyDataset(all_data, all_labels)
# DataLoader 自动处理:
# - 分批次(batch)
# - 打乱顺序(shuffle)
# - 多进程加载(num_workers)
dataloader = DataLoader(
dataset,
batch_size=32, # 每批 32 个样本
shuffle=True, # 每个 epoch 打乱数据
num_workers=4 # 4 个子进程加载数据
)
# 迭代 DataLoader
for batch_idx, (data, labels) in enumerate(dataloader):
print(f"Batch {batch_idx}: data shape {data.shape}")
# data: [32, 特征维度]
# labels: [32]
break
使用内置数据集(torchvision)
对于计算机视觉任务,PyTorch 提供了常用的公共数据集:
import torchvision
import torchvision.transforms as transforms
# 定义数据预处理
transform = transforms.Compose([
transforms.ToTensor(), # PIL → Tensor
transforms.Normalize((0.5,), (0.5,)) # 归一化到 [-1, 1]
])
# 下载 MNIST 手写数字数据集
train_dataset = torchvision.datasets.MNIST(
root='./data',
train=True,
transform=transform,
download=True
)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
四、构建神经网络模型
方法一:使用 nn.Sequential(快速搭建)
import torch.nn as nn
model = nn.Sequential(
nn.Linear(784, 256), # 输入 784 维 → 隐藏层 256
nn.ReLU(),
nn.Linear(256, 128),
nn.ReLU(),
nn.Linear(128, 10), # 输出 10 类(数字 0-9)
)
print(model)
# Sequential(
# (0): Linear(in_features=784, out_features=256, bias=True)
# (1): ReLU()
# (2): Linear(in_features=256, out_features=128, bias=True)
# (3): ReLU()
# (4): Linear(in_features=128, out_features=10, bias=True)
# )
方法二:继承 nn.Module(更灵活,推荐)
class MLP(nn.Module):
"""自定义多层感知机"""
def __init__(self, input_dim, hidden_dim, num_classes):
super().__init__()
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_dim, hidden_dim)
self.fc3 = nn.Linear(hidden_dim, num_classes)
def forward(self, x):
"""前向传播------你只需要定义这个"""
x = x.view(x.size(0), -1) # 展平 [batch, 784]
x = self.relu(self.fc1(x))
x = self.relu(self.fc2(x))
x = self.fc3(x) # 输出 logits(不需要 softmax)
return x
# 实例化模型
model = MLP(input_dim=784, hidden_dim=256, num_classes=10)
print(f"模型参数量: {sum(p.numel() for p in model.parameters()):,}")
五、完整的训练循环
把前面所有组件组合起来,就是 PyTorch 标准的训练循环模板。
训练函数
def train_one_epoch(model, dataloader, criterion, optimizer, device):
"""训练一个 epoch"""
model.train() # 设置为训练模式
total_loss = 0
correct = 0
total = 0
for data, targets in dataloader:
data, targets = data.to(device), targets.to(device)
# 1. 清零梯度
optimizer.zero_grad()
# 2. 前向传播
outputs = model(data)
loss = criterion(outputs, targets)
# 3. 反向传播
loss.backward()
# 4. 更新参数
optimizer.step()
# 统计
total_loss += loss.item()
_, predicted = outputs.max(1)
total += targets.size(0)
correct += predicted.eq(targets).sum().item()
avg_loss = total_loss / len(dataloader)
accuracy = 100. * correct / total
return avg_loss, accuracy
验证函数
@torch.no_grad() # 不需要梯度,节省内存和计算
def evaluate(model, dataloader, criterion, device):
"""评估模型(不更新参数)"""
model.eval() # 设置为评估模式
total_loss = 0
correct = 0
total = 0
for data, targets in dataloader:
data, targets = data.to(device), targets.to(device)
outputs = model(data)
loss = criterion(outputs, targets)
total_loss += loss.item()
_, predicted = outputs.max(1)
total += targets.size(0)
correct += predicted.eq(targets).sum().item()
return total_loss / len(dataloader), 100. * correct / total
执行完整训练
# ===== 配置 =====
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
batch_size = 64
epochs = 10
learning_rate = 0.001
# ===== 数据 =====
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,)) # MNIST 均值和标准差
])
train_dataset = torchvision.datasets.MNIST('./data', train=True, transform=transform, download=True)
test_dataset = torchvision.datasets.MNIST('./data', train=False, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# ===== 模型、损失函数、优化器 =====
model = MLP(input_dim=784, hidden_dim=256, num_classes=10).to(device)
criterion = nn.CrossEntropyLoss() # 自带 Softmax + NLLLoss
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# ===== 训练循环 =====
for epoch in range(1, epochs + 1):
train_loss, train_acc = train_one_epoch(model, train_loader, criterion, optimizer, device)
test_loss, test_acc = evaluate(model, test_loader, criterion, device)
print(f"Epoch {epoch:2d}: "
f"Train Loss={train_loss:.4f}, Train Acc={train_acc:.2f}% | "
f"Test Loss={test_loss:.4f}, Test Acc={test_acc:.2f}%")
# 输出示例:
# Epoch 1: Train Loss=0.3210, Train Acc=90.45% | Test Loss=0.1689, Test Acc=94.82%
# Epoch 5: Train Loss=0.0892, Train Acc=97.31% | Test Loss=0.0812, Test Acc=97.35%
# Epoch 10: Train Loss=0.0487, Train Acc=98.52% | Test Loss=0.0688, Test Acc=97.98%
六、PyTorch 训练模板速查
每次写一个新的训练任务,都可以复用这个模板:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
# ─── 1. 定义模型 ───
class MyModel(nn.Module):
def __init__(self):
super().__init__()
# 定义层
def forward(self, x):
# 前向传播
return x
# ─── 2. 准备数据 ───
train_loader = DataLoader(...)
test_loader = DataLoader(...)
# ─── 3. 初始化 ───
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = MyModel().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# ─── 4. 训练循环 ───
for epoch in range(epochs):
model.train()
for data, targets in train_loader:
data, targets = data.to(device), targets.to(device)
optimizer.zero_grad()
outputs = model(data)
loss = criterion(outputs, targets)
loss.backward()
optimizer.step()
# ─── 5. 验证 ───
model.eval()
with torch.no_grad():
for data, targets in test_loader:
# 计算准确率
pass
这个模板适用于 90% 以上的深度学习训练任务。只需要替换模型结构和数据加载部分即可。
七、总结
| 组件 | 一句话 | 核心 API |
|---|---|---|
| Tensor | 带 GPU 加速和自动求导的 NumPy | torch.tensor(), .cuda(), .to() |
| Autograd | 自动计算所有参数的梯度 | .backward(), .grad, .grad.zero_() |
| DataLoader | 自动批次加载和打乱数据 | Dataset, DataLoader |
| nn.Module | 构建神经网络的基类 | nn.Linear, nn.ReLU, nn.Sequential |
| 训练循环 | 前向→损失→反向→更新 | optimizer.zero_grad(), loss.backward(), optimizer.step() |
下一步:把这些代码跑起来。用上面的模板训练一个 MNIST 分类器,15 行核心代码就够了。下一篇就用这些知识来完成一个完整的图像分类实战项目。