欢迎光临
我们一直在努力

PyTorch 入门实战:从张量到训练循环

摘要:前四篇讲理论,这一篇动手写代码。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 行核心代码就够了。下一篇就用这些知识来完成一个完整的图像分类实战项目。

赞(0)
未经允许不得转载:171主机测评 » PyTorch 入门实战:从张量到训练循环
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址