PyTorch 入门核心:Tensor、自动求导与训练闭环实战

PyTorch 入门核心:Tensor、自动求导与训练闭环实战 很多刚开始接触深度学习的人会陷入一种怪圈教程看了几十个小时GitHub 上标星的项目也收藏了一堆但轮到自己独立写训练脚本时还是会卡在第一步。原因通常不是不努力而是没有抓住 PyTorch 的底层主线。我的判断很直接PyTorch 能成为深度学习研究和落地的主流框架靠的不是功能堆叠而是它的设计足够“Python 化”。动态计算图让调试变得和写普通 Python 函数一样自然自动求导机制让反向传播这类复杂的数学推导即使没有系统学过微积分的人也能直接使用。在当前这个时间点如果你想进入 AI 或深度学习领域PyTorch 仍然是性价比最高的切入点。这篇文章不是把官方文档翻译一遍而是从“完成一个能训练的模型”这个真实目标出发抽出 PyTorch 最重要的 3 点核心知识点讲透Tensor 与自动求导、nn.Module 模块化建模、训练循环闭环。全文附有可复制运行的完整源码按 1 周的学习节奏安排但核心内容集中在一篇里读完后你就能写出第一个真正意义上的深度学习训练脚本。1. 这篇文章真正要解决的问题1.1 新手学 PyTorch 最容易踩中的 3 个困境先说说我在社区里看到的高频问题。第一类是把 PyTorch 当 NumPy 用学会了 Tensor 加减乘除但不知道怎么组织成一个可训练的网络第二类是背熟了nn.Linear、nn.Conv2d这些层但不知道数据应该传成什么形状forward里到底该写什么第三类是看得懂别人的训练代码自己从零写的时候却不知道损失函数、优化器、梯度清零、反向传播这些组件是怎么串联起来的。这三个困境的根源都是同一个缺少对 PyTorch 核心机制的闭环理解。框架的 API 只是表层的工具真正支撑一个训练任务跑起来的是“数据 → 模型 → 损失 → 优化”这条链路以及链路上每一步的数据形状和梯度流向。1.2 本文的中心判断先建立闭环再谈模型我见过太多初学者把精力花在“学更多的模型结构”上但连一个最基础的全连接网络都训不收敛。如果你问我现在最想给小白一个什么建议我会说先把一个最小闭环跑通再谈 CNN、RNN、Transformer。什么意思就是第一个练习不要直接上图像分类、目标检测而是先用几十行代码让一个最简单的神经网络在某个数据集上完成“读数据 → 前向传播 → 算损失 → 反向传播 → 更新参数”的完整循环。只要这个基本功扎实了后面不管是玩视觉、文本还是大模型微调底层逻辑都是同一套。所以这篇文章的三个核心知识点也都围绕这个闭环展开。1.3 谁适合读这篇文章这篇文章适合以下三类读者完全没有接触过深度学习框架的小白想快速上手 PyTorch 的 Python 开发者以及学过一些理论但始终没有自己动手训练过模型的学生。如果你已经能熟练使用 PyTorch 训练模型这篇文章的价值可能更多在于查漏补缺比如工程化习惯和精度选型那部分。2. PyTorch 核心概念与 3 点核心知识点2.1 PyTorch 是什么用一句话概括PyTorch 是一个基于 Python 的深度学习框架它由三个层次组成底层是张量计算库可以看作带 GPU 加速的 NumPy中间层是自动求导引擎能自动计算任意复杂函数的梯度上层是深度学习组件库包括神经网络层、损失函数、优化器、数据加载工具等。这三个层次对应到日常使用中就是你用 Tensor 表示数据和参数用自动求导让框架替你算梯度用torch.nn里的组件快速搭出网络结构。PyTorch 的设计哲学是“用起来像 Python”所以它对新手非常友好甚至可以边写边调试。2.2 动态计算图PyTorch 区别于其他框架的核心设计深度学习框架的核心能力是反向传播而反向传播依赖计算图。计算图描述了数据从输入到输出的计算过程也记录了每一步操作之间的依赖关系。PyTorch 使用的是动态计算图每次前向传播都会重新建立计算图这意味着你可以用 Python 的 if、for、print 等原生语法来写模型逻辑图的结构在执行时才确定。这一点和早期的静态图框架有本质区别。静态图的思路是先把完整的计算图定义好再交给执行引擎运行调试起来非常依赖框架自身的工具动态图则让整个建模过程接近“用普通 Python 写程序”的体验这也是 PyTorch 在研究社区快速普及的关键原因。用一句话记住在 PyTorch 里前向传播就是普通的 Python 代码反向传播是自动发生的。2.3 3 点核心知识点总览我把 PyTorch 的内容压缩成下面的 3 点这也是本文后面核心章节的线索编号核心知识点解决的问题对应组件1Tensor 与自动求导数据怎么表示梯度怎么算torch.Tensor、requires_grad、backward2nn.Module 模块化建模网络结构怎么组织nn.Module、nn.Linear、forward3训练循环闭环模型怎么从随机变得有效Dataset、DataLoader、optimizer、loss这三个知识点不是孤立的它们串起来的顺序就是一次完整训练的流程。建议收藏本文按照这个顺序逐步实践。3. 环境准备搭建 PyTorch 开发环境3.1 确认硬件先判断自己能不能用 GPU在动手安装之前先确认自己的电脑硬件。PyTorch 支持 CPU 和 GPU 两种训练方式如果你有 NVIDIA 显卡训练速度会快非常多如果只有 CPU也不用灰心本文的手写数字识别例子用 CPU 也能在几分钟内跑完。可以通过以下命令查看自己的显卡信息# Windows nvidia-smi # Linux lspci | grep -i nvidia如果命令不存在说明机器上可能没有 NVIDIA 驱动也大概率没有 NVIDIA GPU。这种情况下建议安装 CPU 版本。如果你使用的是 AMD GPU在 Windows 上通常建议先用 CPU 学习在 Linux 下可以尝试 ROCm 版本但入门阶段没必要为了 GPU 折腾环境。3.2 安装 Anaconda 并创建虚拟环境强烈建议安装 Anaconda它内置了 Python、pip 和常用的数据科学包还能方便地创建独立环境避免不同项目之间依赖冲突。打开终端创建并激活一个独立的 PyTorch 环境conda create -n pytorch python3.10 -y conda activate pytorchPython 版本选择 3.10 是一个比较稳妥的选择对大多数 PyTorch 版本都有良好的兼容性。如果你已经有 Python 环境也可以直接用 venv但 Anaconda 在管理多个项目环境时更省心。3.3 安装 PyTorchCPU 与 GPU 版本PyTorch 官方提供了非常方便的安装命令生成器你只需要在官网上选择操作系统、包管理器和 CUDA 版本就会生成对应的安装命令。安装命令会随时变化所以最稳妥的方法是访问 PyTorch 官网获取但这里也给出两个最常用的示例。CPU 版本安装命令所有电脑都可以用pip install torch torchvision torchaudioNVIDIA GPU 版本安装命令以 CUDA 11.8 为例pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118如果你的 CUDA 版本或显卡架构不同建议以 PyTorch 官网生成的命令为准。注意 GPU 版本最好从 PyTorch 官方源安装不要随意换国内镜像否则可能装成 CPU 版本这是新手最常遇到的问题之一。3.4 验证安装是否成功安装完成后在 Python 交互环境或脚本中执行import torch print(torch.__version__) print(torch.cuda.is_available())如果输出类似2.x.xcu118的版本号并且torch.cuda.is_available()返回True说明 GPU 环境配置成功。如果返回False也可能是正常的说明你安装的是 CPU 版本或者驱动版本不匹配。对于编写代码环境推荐使用 PyCharm 或 VS Code。PyCharm 社区版免费且对新手友好VS Code 则更轻量。无论选哪个记得把解释器设置为刚才创建的pytorch环境。4. 核心知识点一Tensor 张量操作与自动求导4.1 Tensor 是什么把 Python 数组升级为深度学习最小单元Tensor 是 PyTorch 中最基本的数据结构可以把它理解成一个支持 GPU 加速、支持自动求导的多维数组。普通 Python 列表只能存数据NumPy 数组也只是存数据但 Tensor 额外拥有两个关键能力可以在 GPU 上计算可以记录运算过程用于自动求导。在实际项目中Tensor 承载的角色包括输入数据、模型权重、中间特征、损失值、梯度。整个训练过程本质上就是 Tensor 在不同计算节点之间流动。4.2 Tensor 的 5 个高频操作下面用一段代码演示 Tensor 最常见的几种操作import torch # 1. 从列表或 NumPy 数组创建 a torch.tensor([1.0, 2.0, 3.0]) print(从列表创建:, a) # 2. 创建全零、全一、随机张量 zeros torch.zeros(2, 3) ones torch.ones(2, 3) randn torch.randn(2, 3) # 标准正态分布随机数 print(随机张量形状:, randn.shape) # 3. 数据类型转换 b randn.float() c randn.long() print(默认数据类型:, randn.dtype) # 4. 形状操作 d randn.view(3, 2) print(view 后形状:, d.shape) # 5. 与 NumPy 互转 import numpy as np arr np.array([4, 5, 6]) tensor_from_numpy torch.from_numpy(arr) back_to_numpy tensor_from_numpy.numpy() print(NumPy 互转成功:, back_to_numpy)这段代码几乎覆盖了入门阶段 80% 的 Tensor 操作。需要注意view和reshape的区别view要求张量在内存中是连续的reshape会在必要时自动复制数据。日常使用中优先用reshape更稳妥。4.3 自动求导requires_grad 与 backward自动求导是 PyTorch 的核心能力。你只需要在创建 Tensor 时设置requires_gradTrue然后正常完成数学运算最后调用backward()PyTorch 就会自动把所有中间变量的梯度计算出来。import torch # 创建一个需要梯度的 Tensor x torch.tensor([2.0], requires_gradTrue) print(x.requires_grad:, x.requires_grad) # 定义 y x^2 3x y x ** 2 3 * x # 反向传播自动计算梯度 y.backward() # x.grad 保存了 dy/dx 在 x2 处的值结果应为 2*237 print(x.grad:, x.grad)运行这段代码x.grad会输出tensor([7.])。这里的数学意义是在x2处y对x的导数是 7。PyTorch 帮你完成了求导和链式法则你只需要关心前向计算逻辑。在实际训练中你几乎不会手动定义requires_grad因为nn.Module里的模型参数默认会设置成需要梯度。但理解backward()的存在能让你明白训练循环里那一步loss.backward()到底做了什么。4.4 这里真正容易踩坑的地方新手最容易犯的错误是在不需要梯度的测试阶段忘记关闭梯度计算。默认情况下只要 Tensor 参与了计算就可能构建计算图显存和内存会不断累积。测试或推理时应该使用torch.no_grad()块。with torch.no_grad(): output model(test_data)另一个错误是梯度累积。每次调用backward()梯度是累加到.grad上的不是覆盖。所以训练循环里每轮更新参数前必须先调用optimizer.zero_grad()清零梯度否则梯度会叠加导致模型参数更新异常。5. 核心知识点二nn.Module 与模型构建5.1 为什么模型要按模块化方式写如果你只用 Tensor 操作理论上也能手写一个神经网络的全部计算比如矩阵乘法、激活函数、权重更新。但这样做会非常痛苦权重参数要自己维护梯度要手动清零网络层多了以后代码根本无法维护。nn.Module解决的就是这个问题。它是 PyTorch 中所有神经网络模块的基类给开发者提供了一套统一的结构用__init__定义网络包含哪些层用forward定义数据如何通过这些层。模型参数由框架自动管理调用model.parameters()就能拿到全部可训练参数调用model.to(device)就能把整个模型移动到 GPU。5.2 从 nn.Linear 到 nn.Sequential最简单的网络模块是nn.Linear它代表一个全连接层。你只需要指定输入特征数和输出特征数PyTorch 会自动创建权重矩阵和偏置项。import torch.nn as nn # 一个全连接层输入 784 维输出 128 维 layer nn.Linear(in_features784, out_features128) print(权重形状:, layer.weight.shape) # torch.Size([128, 784]) print(偏置形状:, layer.bias.shape) # torch.Size([128])如果网络结构比较规则可以直接用nn.Sequential把多个层按顺序串起来import torch.nn as nn mlp nn.Sequential( nn.Linear(784, 128), nn.ReLU(), nn.Linear(128, 10) )nn.Sequential适合线性堆叠结构的简单网络但遇到分支结构或复杂数据流时就需要自定义nn.Module。5.3 自定义网络必须写 forward 的原因下面是一个最常见的自定义网络写法import torch.nn as nn import torch.nn.functional as F class MLP(nn.Module): def __init__(self): super().__init__() self.fc1 nn.Linear(784, 128) self.fc2 nn.Linear(128, 64) self.fc3 nn.Linear(64, 10) def forward(self, x): # x 形状: [batch_size, 784] x F.relu(self.fc1(x)) x F.relu(self.fc2(x)) x self.fc3(x) # 最后一层先不做激活交给损失函数 return xforward是前向传播的具体逻辑它会被model(x)自动调用。这里有两个新手容易困惑的点第一不要在__init__里计算输入数据__init__只负责定义组件第二最后一层的输出一般不需要额外加激活函数因为CrossEntropyLoss内部已经包含了 softmax 计算提前加了反而会把数值范围破坏掉。5.4 模型参数的查看与保存训练之前可以查看模型的参数总量model MLP() total_params sum(p.numel() for p in model.parameters()) print(f模型总参数量: {total_params})训练完成后保存模型有两种常见方式。只保存参数推荐torch.save(model.state_dict(), model.pth)保存完整模型torch.save(model, model_full.pth)加载时第一种方式需要重新实例化模型再加载参数第二种方式直接torch.load即可。实际工程里更推荐第一种因为它只保存参数跨环境兼容性更好模型结构始终由代码明确定义。6. 核心知识点三数据加载、损失函数与训练循环6.1 Dataset 与 DataLoader让数据按批次进入模型深度学习训练不能一次性把所有数据塞进模型因为显存放不下而且逐样本更新权重效率也很低。PyTorch 用Dataset定义“数据从哪里来”用DataLoader定义“数据怎么分批、要不要打乱”。Dataset是一个抽象类子类必须实现__len__和__getitem__两个方法。实际开发中如果数据是常见的图片、文本格式可以直接用torchvision或datasets库中现成的数据集如果是自己的业务数据再继承Dataset自定义。DataLoader的核心参数包括参数作用默认值batch_size每个批次包含多少样本1shuffle每个 epoch 是否随机打乱数据Falsenum_workers加载数据的子进程数0训练集一般设置shuffleTrue测试集设置shuffleFalse。6.2 损失函数与优化器怎么选损失函数衡量模型预测与真实标签之间的差距。对于分类任务最常用的是nn.CrossEntropyLoss对于回归任务常用nn.MSELoss。初学者不需要过多纠结先把这两个记住后续遇到特殊任务再扩展。优化器负责根据梯度更新模型参数。最常用的是Adam和SGDimport torch.optim as optim # 如果把所有参数使用相同学习率Adam 通常是最稳的选择 optimizer optim.Adam(model.parameters(), lr0.001) # SGD 是经典方法经常需要配合 momentum 使用 optimizer optim.SGD(model.parameters(), lr0.01, momentum0.9)Adam收敛快、对学习率不那么敏感适合初学者SGD需要更多调参经验但有些场景下泛化效果更好。入门阶段推荐直接选Adam把精力集中在理解训练流程上。6.3 训练循环的标准模板一次训练迭代可以拆成五步这个模板以后会被反复用到def train_one_epoch(model, train_loader, optimizer, criterion): model.train() # 切换到训练模式 for images, labels in train_loader: # 1. 梯度清零 optimizer.zero_grad() # 2. 前向传播 outputs model(images) # 3. 计算损失 loss criterion(outputs, labels) # 4. 反向传播 loss.backward() # 5. 更新参数 optimizer.step()注意model.train()与model.eval()的区别。有些网络层如 Dropout、BatchNorm在训练和测试时的行为不同PyTorch 通过这两个方法切换状态。很多人训练时忘记写model.train()测试时忘记写model.eval()会导致结果不稳定。6.4 评估 loop训练之外的另一个循环训练结束后还需要在测试集上评估模型效果。评估循环和训练循环很相似区别在于不需要计算梯度、不需要更新参数需要统计正确率或损失。def evaluate(model, test_loader, criterion): model.eval() # 切换到评估模式 total_loss 0.0 correct 0 total 0 with torch.no_grad(): for images, labels in test_loader: outputs model(images) loss criterion(outputs, labels) total_loss loss.item() * images.size(0) _, predicted torch.max(outputs, dim1) correct (predicted labels).sum().item() total labels.size(0) avg_loss total_loss / total accuracy correct / total return avg_loss, accuracy这里torch.max(outputs, dim1)返回每个样本在类别维度上的最大值和索引索引就是预测的类别。代码中with torch.no_grad()的作用是让这个循环不构建计算图节省显存和时间。7. 完整实战用 PyTorch 训练手写数字识别模型7.1 项目结构与源码现在把前面三个核心知识点串起来写一个完整的 MNIST 手写数字识别项目。MNIST 是深度学习领域的 Hello World 数据集每张图片是 28x28 的灰度图共 10 个类别。创建文件mnist_train.py完整代码如下import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F from torch.utils.data import DataLoader from torchvision import datasets, transforms # 1. 固定随机种子保证结果可复现 torch.manual_seed(42) # 2. 数据预处理转为 Tensor 并做标准化 transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) # 3. 加载 MNIST 数据集 train_dataset datasets.MNIST( root./data, trainTrue, downloadTrue, transformtransform ) test_dataset datasets.MNIST( root./data, trainFalse, downloadTrue, transformtransform ) train_loader DataLoader(train_dataset, batch_size64, shuffleTrue) test_loader DataLoader(test_dataset, batch_size1000, shuffleFalse) # 4. 定义模型 class MLP(nn.Module): def __init__(self): super().__init__() self.fc1 nn.Linear(28 * 28, 128) self.fc2 nn.Linear(128, 64) self.fc3 nn.Linear(64, 10) def forward(self, x): x x.view(x.size(0), -1) # 展平 [batch_size, 784] x F.relu(self.fc1(x)) x F.relu(self.fc2(x)) x self.fc3(x) return x # 5. 初始化模型、损失函数、优化器 device torch.device(cuda if torch.cuda.is_available() else cpu) model MLP().to(device) criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.parameters(), lr0.001) # 6. 训练循环 def train(epoch): model.train() running_loss 0.0 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() running_loss loss.item() if batch_idx % 200 199: avg_loss running_loss / 200 print(fEpoch {epoch} | Batch {batch_idx 1}/{len(train_loader)} | Loss {avg_loss:.4f}) running_loss 0.0 # 7. 评估循环 def test(): 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) pred output.argmax(dim1) correct (pred target).sum().item() total target.size(0) print(fTest Accuracy: {correct / total:.4f} ({correct}/{total})) # 8. 训练 5 个 epoch if __name__ __main__: for epoch in range(1, 6): train(epoch) test()7.2 数据准备与预处理说明transforms.ToTensor()会把 PIL 图片或 NumPy 数组从数值范围 0-255 转换到 0-1并且把通道维度放到前面变成[C, H, W]形状。transforms.Normalize用 MNIST 数据集的全局均值和标准差做标准化这一步能让训练更稳定。downloadTrue会在第一次运行时自动下载数据集到./data目录。如果下载失败通常是网络问题可以手动下载后放入对应目录或者更换网络环境重试。7.3 模型定义说明这个 MLP 接收的输入形状是[batch_size, 1, 28, 28]但在forward中通过x.view(x.size(0), -1)展平成[batch_size, 784]把二维图片变成一维向量。这是全连接网络处理图片的标准做法不需要卷积网络那么复杂的空间结构。最后一层输出 10 个数值代表模型对 10 个数字的“打分”分数最高的类别就是预测结果。7.4 训练与评估循环说明训练循环中每次迭代加载一个 batch 的 64 张图片经过前向传播、计算损失、反向传播、更新参数五个步骤。评估循环中不计算梯度只在测试集上统计正确率。7.5 运行方式conda activate pytorch python mnist_train.py8. 运行结果与效果验证8.1 预期输出训练开始后你会看到类似下面的输出Epoch 1 | Batch 200/938 | Loss 0.4521 Epoch 1 | Batch 400/938 | Loss 0.2103 Epoch 1 | Batch 600/938 | Loss 0.1712 Epoch 1 | Batch 800/938 | Loss 0.1456 Test Accuracy: 0.9581 (9581/10000)随着训练轮数增加Loss 应该整体逐步下降测试集准确率应该在 97% 左右。如果一切正常5 个 epoch 后准确率会稳定在 97% 以上。这个结果在深度学习评测标准里不算高因为这是一个最简单的两层全连接网络但它证明了整个训练闭环是通顺的。后续想提高准确率可以换成卷积网络或加深层数。8.2 如何判断训练是否正常判断训练是否正常主要看两条曲线训练 Loss 是否在下降测试准确率是否在上升。如果训练 Loss 降得很低但测试准确率不高说明模型过拟合需要增加数据、加正则化或降低模型复杂度如果训练 Loss 一开始就不降甚至还在涨说明学习率可能过大或者数据预处理有误。8.3 训练失败时第一步看哪里不要急着改模型结构先按这个顺序排查确认torch.cuda.is_available()的结果是否符合预期GPU 训练时data和model是否都调用了.to(device)。打印一个 batch 的data.shape和target.shape确认形状与模型forward中期望的输入匹配。打印初始 Loss 是否合理。对于 10 分类任务随机初始化的模型 Loss 应该在ln(10) ≈ 2.3左右如果偏差过大可能是模型或损失函数使用有误。检查是否忘记调用optimizer.zero_grad()这会导致梯度累积训练过程剧烈震荡。9. 常见问题与排查思路问题现象可能原因排查方式解决方案pip 安装 PyTorch 超时或下载慢网络不稳定或使用了默认 PyPI 源检查下载进度和网络连接使用国内 PyPI 镜像或从官网生成命令后在网络较好的时段安装GPU 版本装好后torch.cuda.is_available()返回 FalseCUDA 驱动版本不匹配或安装成了 CPU 版本运行nvidia-smi查看驱动和 CUDA 版本打印torch.__version__看是否带cu后缀重新安装与本地驱动兼容的 CUDA 版本对应的 PyTorch驱动版本需要支持所选 CUDAMNIST 数据集下载失败网络无法访问数据集服务器查看./data目录是否存在手动下载数据集放入./data/MNIST/raw目录或者尝试代理后重试这里不涉及任何非正规网络配置仅指普通网络问题训练 Loss 不下降学习率过大或过小数据未归一化打印初始 Loss 和输入数值范围将学习率调整到 0.001 左右确认ToTensor已使用检查标签范围是否为 0-9Loss 震荡剧烈学习率过大或 batch_size 过小打印每个 batch 的 Loss 值观察波动降低学习率或适当增大 batch_size显存不足 (CUDA out of memory)batch_size 过大或图片分辨率太高查看报错的进程和显存占用调小 batch_size使用torch.no_grad()评估或考虑使用混合精度训练每次运行结果不一致未固定随机种子检查训练脚本是否设置torch.manual_seed训练开始前设置torch.manual_seed(42)如果使用 GPU 再加torch.cuda.manual_seed_all(42)加载模型参数时报 shape 不匹配模型结构与保存时不一致对比当前模型打印的参数形状与state_dict中的键值保持模型类定义一致或者只保存和加载state_dict10. PyTorch 工程化最佳实践与 1 周学习路线10.1 工程化习惯当你从跑通示例走向真实项目时有些工程习惯越早养成越好。首先是固定随机种子。深度学习中很多操作带有随机性包括数据打乱、权重初始化、Dropout 等。如果不固定随机种子同一个脚本两次运行的结果都会有差异这在调试阶段会造成很大的困扰。建议在训练脚本最开头固定torch.manual_seed。其次是使用tensorboard或wandb可视化训练曲线。只看终端打印的 Loss 值很难判断训练趋势把 Loss 和准确率画成曲线后过拟合、不收敛、学习率不合理等问题会直观很多。PyTorch 自带torch.utils.tensorboard可以零成本开始记录。再次是保存最佳模型。很多新手只保存最后一个 epoch 的模型但最后一个 epoch 未必是验证集上效果最好的。更推荐的做法是每个 epoch 结束后在验证集上评估如果准确率超过历史最佳就保存当前模型。最后是模块化拆分训练脚本。把数据加载、模型定义、训练函数、评估函数、配置参数分别放到不同模块中当项目变大时这种拆分能节省大量时间。10.2 精度选择FP32、FP16、BF16、TF32在实际训练和部署中你会遇到 FP32、FP16、BF16、TF32 这些精度术语。它们之间的核心差异是数值范围和精度不同内存占用和计算速度也不同。精度全称内存占用典型使用场景FP32单精度浮点数4 字节默认训练精度通用性强适合入门和小模型FP16半精度浮点数2 字节混合精度训练显存减半速度更快但需要处理数值溢出BF16脑浮点 162 字节大模型训练常用相比 FP16 动态范围更大更适合大数值范围场景TF32截断单精度4 字节在 Ampere 及以上架构 NVIDIA GPU 上矩阵乘法默认使用的精度兼顾精度和速度对刚入门的小白来说不需要手动修改精度默认 FP32 就够了。等到模型规模变大、显存吃紧时可以使用 PyTorch 的自动混合精度功能torch.cuda.amp用很少的代码就能切换到 FP16 训练进一步降低显存占用并提升训练速度。10.3 1 周学习路线安排文章开头承诺了“1 周内快速掌握”这里给你一条经过验证的路线Day 1完成环境安装跑通第 3 章的验证代码理解 Tensor 的基本操作。Day 2手动推导并验证 PyTorch 的自动求导机制把第 4 章的求导例子亲手跑一遍。Day 3使用nn.Module搭建一个 2 层全连接网络尝试修改隐藏层大小观察参数量变化。Day 4把第 7 章的完整代码敲一遍不复制粘贴而是逐行理解后自己写出来。Day 5选择一个简单的公开数据集替换掉 MNIST自己完成数据处理和模型训练。Day 6给模型加一个隐藏层或者把全连接网络改成卷积网络nn.Conv2d对比准确率差异。Day 7尝试用torch.save保存最佳模型写一个独立脚本加载模型做单张图片推理。这条路线不需要每天花大量的时间关键是每天都真正跑代码。只要坚持下来你对 PyTorch 的掌握程度会超过大多数只看教程的人。10.4 后续学习方向当你已经能独立完成一个分类任务后可以根据兴趣继续深入做计算机视觉可以学习torchvision里的预训练模型和迁移学习做自然语言处理可以学习 Transformer 和 Hugging Face Transformers 库做时序预测可以研究 TCN、LSTM 与 Transformer 的结合当模型规模足够大后可以学习混合精度训练和分布式训练。深度学习框架只是工具但工具熟练度决定了你把想法变成实验的速度。PyTorch 的价值在于它把从想法到实验之间的距离压缩到了最短。按照本文的节奏不用刻意追求“学完”只要跑通一个项目你就算真正入门了。后面遇到任何报错欢迎回来翻一翻第 9 节的排查表很多坑是共通的。也可以把本文收藏起来等你开始做自己的第一个深度学习项目时对照每个章节检查一遍自己的流程是否完整。