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 行核心代码就够了。下一篇就用这些知识来完成一个完整的图像分类实战项目。

相关推荐
黄贵根1 小时前
JavaScript实现教培行业意向登记系统
开发语言·javascript·ecmascript
小趴蔡ha3 小时前
02 Anaconda、Python 与机器学习开发环境入门
python·机器学习·anaconda
jikemaoshiyanshi3 小时前
AWS 中国峰会 2026 有哪些 AI Agent 相关演讲可以看?按业务、研发与生产阶段选看
大数据·人工智能
zzzll11113 小时前
Claude Code离线安装方案揭秘
开发语言·php
网易易盾4 小时前
AI互动产品安全合规体系架构:制度/技术/运营/证据四层落地
人工智能·安全·aigc·内容安全
新知图书4 小时前
4.3 链接速读
人工智能·语音识别·ai助手·千问
江苏久众新视4 小时前
SOP-AI实战:基于AI视觉与视频检测,精准管控空调管件装配防漏防错
人工智能
wling03014 小时前
vasp虚频计算-python脚本
开发语言·windows·python·vasp计算
郝学胜-神的一滴5 小时前
Qt 高级编程 040:按钮悬浮弹出滑块弹窗的完整攻略
开发语言·c++·qt·软件工程·用户界面
xrandzj5 小时前
Python面向对象编程入门:类、实例、初始化与封装实践
开发语言·python