各位准备入门深度学习的朋友们,大家好。
相信很多初学者在接触深度学习时,都经历过类似的迷茫:理论看了一大堆,但真正想动手训练一个模型时,却不知道该选择哪个框架;好不容易选定了 PyTorch,又在环境配置、张量操作、模型构建这些环节反复卡壳。网上教程虽然很多,但要么太零散,要么直接丢出一大段源码让你自己琢磨,对新手并不友好。
这篇文章就是为这种情况准备的。我会围绕 PyTorch 框架,从为什么选它开始,带你一步步完成环境搭建、理解核心概念、跑通一个完整的图像分类项目,并整理高频报错和工程实践经验。文章内容覆盖入门到基础实战,代码都经过整理可以直接复制运行。不管你是学生、转行者,还是工作中需要用 AI 解决问题的开发者,这篇教程都值得收藏备用。
1. 为什么深度学习首选 PyTorch 框架
1.1 PyTorch 是什么
PyTorch 是一个基于 Python 的开源机器学习框架,由 Facebook 人工智能研究院(FAIR)团队主导开发,底层使用 Torch 库,核心计算基于张量(Tensor),可以理解为“支持自动求导的 NumPy 增强版”。
在深度学习领域,框架要解决的核心问题有三个:
- 高效地进行张量运算(矩阵乘法、卷积、池化等)。
- 自动计算梯度,让反向传播不再需要手推公式。
- 提供神经网络组件,让模型搭建像搭积木一样方便。
PyTorch 对这三点都给出了很优雅的答案。它的动态计算图机制、命令式编程风格,让模型的调试过程非常接近普通 Python 程序,这也是它被学术界和工业界广泛采用的重要原因。
1.2 PyTorch 与其他框架的对比
很多人喜欢问:“PyTorch 和 TensorFlow 有什么区别?我应该学哪个?”
这里不引战,只客观说差异。TensorFlow 早期采用静态图模式,需要先定义好完整的计算图,再喂数据执行,这种方式对性能优化和分布式部署友好,但调试起来比较麻烦。PyTorch 采用动态图,计算图在每次前向传播时实时构建,你可以像写普通 Python 一样打印中间结果、打断点、逐行检查,对开发者非常友好。
从生态来看,Hugging Face 的 Transformers 库已经成了 NLP 领域的事实标准,底层的首选就是 PyTorch。学术论文开源的代码也大多基于 PyTorch。学会 PyTorch,就意味着你打开了一个可以快速复现前沿模型、灵活改进算法、顺利落地项目的大门。
1.3 PyTorch 的主要应用场景
PyTorch 的应用场景非常广泛,常见的包括:
- 计算机视觉:图像分类、目标检测、语义分割、人脸识别、图像生成。
- 自然语言处理:文本分类、机器翻译、情感分析、大语言模型微调。
- 语音处理:语音识别、语音合成、人声分离。
- 强化学习:游戏智能体、机器人控制策略。
- 工业落地:缺陷检测、预测性维护、推荐系统、时序预测。
无论你将来从事哪个 AI 方向,PyTorch 都是绕不开的基础工具。所以这篇文章会以“框架本身”为核心,帮你把根基打牢。
2. 环境准备与版本说明
2.1 环境选择思路
在开始安装之前,先明确一点:不要盲目追求最新版本。深度学习的版本兼容性非常关键,一个不小心,CUDA 版本不匹配就会浪费大量时间。
本文示例的通用环境如下:
- 操作系统:Windows 10/11 或 Ubuntu 20.04/22.04。
- 编程语言:Python 3.9 或 3.10(建议使用 3.10,兼容性好)。
- 框架版本:PyTorch 2.x(2.0 之后的版本安装方式和旧版有所不同)。
- 构建工具:Anaconda 或 Miniconda,用于创建独立的 Python 虚拟环境。
- IDE:PyCharm 或 VS Code,按个人习惯选择即可。
如果你没有独立的 GPU,或者显卡显存较小,不用担心。本文的核心代码在 CPU 上也能运行,只是训练速度会慢一些。初学者建议先用 CPU 跑通流程,再考虑 GPU 加速。
2.2 安装 Anaconda 与创建虚拟环境
Anaconda 是一个非常流行的 Python 环境管理工具。它集成了 conda 命令,方便我们创建互不干扰的虚拟环境。假设你已经安装好了 Anaconda,打开命令行(Windows 下是 Anaconda Prompt 或 CMD),执行下面命令创建一个名为pytorch的环境:
conda create -n pytorch python=3.10创建过程中会询问是否继续,输入y回车。环境创建完成后,激活环境:
conda activate pytorch激活后,命令行前面应该会出现(pytorch)字样,表示你已经进入了该环境。后续安装的 Python 包都会装在这个环境里,不会影响系统其他环境。
2.3 安装 PyTorch
PyTorch 的安装方式很简单,就是在虚拟环境中执行 pip 命令。关键问题在于,你需要根据自己的机器选择是否安装 CUDA 版本。
如果只是想在 CPU 上先跑通流程,直接执行:
pip install torch torchvision torchaudio如果你有 NVIDIA 显卡,想使用 GPU 加速,需要先确认显卡驱动支持的 CUDA 版本。在命令行执行:
nvidia-smi在输出的右上角可以看到 “CUDA Version: XX.X” 字样,这个数字表示你的驱动最高支持的 CUDA 版本。然后去 PyTorch 官网找到对应的安装命令。举例来说,如果你的驱动支持 CUDA 11.8,可以执行:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118如果 CUDA 版本是 12.1,则执行:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121国内用户如果下载速度慢,可以在 pip 命令后面追加国内镜像源,例如清华源:
pip install torch torchvision torchaudio -i https://pypi.tuna.tsinghua.edu.cn/simple注意,镜像源的切分会改变默认的下载地址,具体以你网络环境为准。安装完成后,进入 Python 环境验证是否成功:
import torch print(torch.__version__) print(torch.cuda.is_available())如果输出类似2.1.2+cu118这样的版本号,且torch.cuda.is_available()在 GPU 机器上输出True,说明安装成功。如果输出False,说明当前环境只能使用 CPU 计算,不影响运行本文示例。
3. PyTorch 核心知识点拆解
3.1 张量(Tensor):PyTorch 的基本数据结构
张量是 PyTorch 中最基础的数据结构,可以理解为多维数组。它和 NumPy 的ndarray非常相似,区别在于张量可以在 GPU 上运行,并且支持自动求导。
下面看几个常见的张量创建方式:
import torch # 从列表创建张量 a = torch.tensor([[1, 2, 3], [4, 5, 6]]) print("a:", a) # 创建全 0 张量 b = torch.zeros(2, 3) print("b:", b) # 创建全 1 张量 c = torch.ones(2, 3) print("c:", c) # 创建随机张量 d = torch.randn(2, 3) print("d:", d) # 和 NumPy 互相转换 import numpy as np e = np.array([1, 2, 3]) tensor_from_np = torch.from_numpy(e) print("tensor_from_np:", tensor_from_np)输出结果中,a是我们指定的值,b和c是固定数值,d是服从标准正态分布的随机数。
张量的常用操作包括:
- 形状操作:
.shape、.reshape()、.view()、.transpose()。 - 数学运算:加法、乘法、矩阵乘法
torch.matmul()或@。 - 设备转移:
.to('cuda')或.cpu()。 - 类型转换:
.float()、.long()、.numpy()。
注意,view()和reshape()都可以改变张量形状,但view()要求张量在内存中是连续的,而reshape()会在需要时自动复制数据。在不确定的情况下,使用reshape()更安全。
3.2 自动求导(autograd):深度学习训练的基石
自动求导是 PyTorch 最核心的机制之一。训练神经网络时,我们需要计算损失函数对每个参数的梯度,然后利用梯度更新参数。这个过程如果手工推导,几乎是不可能完成的任务,而 PyTorch 的autograd包可以自动完成。
要实现自动求导,先要把张量的requires_grad属性设置为True,然后对张量执行运算。之后调用.backward(),梯度就会自动累积到张量的.grad属性中。
来看一个简单例子:
import torch x = torch.tensor(2.0, requires_grad=True) y = x ** 2 + 3 * x + 1 y.backward() print("x的梯度:", x.grad)对于 y = x² + 3x + 1,其导数为 2x + 3。当 x = 2 时,梯度应该是 7。程序输出的tensor(7.)验证了这一点。
再来看一个带矩阵运算的例子,更贴近真实场景:
import torch w = torch.randn(3, 3, requires_grad=True) x = torch.ones(3, 3) y = torch.sum(w * x) y.backward() print("w 的梯度形状:", w.grad.shape) print("w 的梯度内容:", w.grad)这里y等于w * x所有元素的和。由于x所有元素都是 1,所以 w 每个元素的梯度都是 1。
实际训练中,我们一般不会直接用backward()更新参数,而是把梯度交给优化器处理。后面实战部分会展示完整流程。
3.3 nn.Module:构建神经网络的标准方式
PyTorch 提供torch.nn模块,里面包含了构建神经网络所需的各种层(全连接层、卷积层、池化层、循环神经网络层等)以及损失函数。我们自定义的网络必须继承torch.nn.Module,并在__init__方法中定义网络结构,在forward方法中定义前向传播逻辑。
来看一个最简单的三层全连接网络:
import torch import torch.nn as nn class MyNet(nn.Module): def __init__(self): super(MyNet, self).__init__() self.fc1 = nn.Linear(784, 256) self.relu = nn.ReLU() self.fc2 = nn.Linear(256, 10) def forward(self, x): x = self.fc1(x) x = self.relu(x) x = self.fc2(x) return x model = MyNet() # 模拟输入一个 4 张图片的批次,每张图片展开成 784 维向量 dummy_input = torch.randn(4, 784) output = model(dummy_input) print("输出形状:", output.shape)在forward方法中,输入x依次经过全连接层、激活函数、全连接层,最终输出形状为[4, 10],也就是每个样本有 10 个类别的得分。
这里有个非常重要的点:不要手动调用forward()。正确用法是model(x),因为 PyTorch 在__call__内部做了很多前置检查工作。
nn.Sequential可以进一步简化模型定义:
import torch import torch.nn as nn model = nn.Sequential( nn.Linear(784, 256), nn.ReLU(), nn.Linear(256, 10) ) dummy_input = torch.randn(4, 784) output = model(dummy_input) print("输出形状:", output.shape)当你不需要复杂设计时,nn.Sequential够用;如果模型结构比较复杂,比如有多分支结构,就需要自定义nn.Module。
3.4 数据加载:Dataset 与 DataLoader
在真实项目中,数据通常不会一次全部读入内存,而是通过 Dataset 定义数据读取逻辑,再交给 DataLoader 按批次加载。这也是一个新手容易困惑的地方,这里拆开说明。
torch.utils.data.Dataset:抽象类,你需要继承它并实现__len__和__getitem__两个方法。torch.utils.data.DataLoader:负责自动打乱数据、按批次加载、多进程读取等。
下面是一个自定义 Dataset 的示例:
import torch from torch.utils.data import Dataset, DataLoader class MyDataset(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] # 模拟 100 条数据,每条 10 维 data = torch.randn(100, 10) labels = torch.randint(0, 2, (100,)) dataset = MyDataset(data, labels) dataloader = DataLoader(dataset, batch_size=16, shuffle=True) for batch_data, batch_labels in dataloader: print("批次数据形状:", batch_data.shape) print("批次标签形状:", batch_labels.shape) break这里的DataLoader会每次取出 16 条数据组成一个批次。shuffle=True表示每个 epoch 都会重新打乱数据顺序,防止模型学到样本顺序信息。
对于常见的 MNIST、CIFAR-10 等标准数据集,torchvision.datasets已经内置了下载和读取接口,不需要自己写 Dataset。下一节实战会直接使用它。
4. 实战:从零搭建一个 CNN 手写数字识别模型
光看不练是学不会深度学习的。这一节我们实现一个完整的项目:使用卷积神经网络(CNN)对 MNIST 手写数字数据集进行分类。整个项目会用到前面讲的所有核心知识点,包括数据加载、模型构建、自动求导、优化器更新。
4.1 创建项目结构
建议在本地创建一个新文件夹,命名为pytorch_mnist_demo,内部结构如下:
pytorch_mnist_demo/ ├── train.py # 训练脚本 ├── test.py # 测试脚本 ├── model.py # 模型定义 └── data/ # 数据集保存目录为了让代码结构清晰,我们把模型定义单独放一个文件。
4.2 定义 CNN 模型(model.py)
文件路径:model.py
import torch.nn as nn class SimpleCNN(nn.Module): def __init__(self, num_classes=10): super(SimpleCNN, self).__init__() self.features = nn.Sequential( nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=2, stride=2), ) self.classifier = nn.Sequential( nn.Flatten(), nn.Linear(64 * 7 * 7, 128), nn.ReLU(inplace=True), nn.Linear(128, num_classes), ) def forward(self, x): x = self.features(x) x = self.classifier(x) return x这个网络结构非常简单:
- 第一个卷积层:输入 1 个通道,输出 32 个通道,卷积核 3×3,padding=1 保持尺寸不变。
- 最大池化:将 28×28 缩小到 14×14。
- 第二个卷积层:输入 32,输出 64,尺寸仍为 14×14。
- 最大池化:将 14×14 缩小到 7×7。
- 全连接层:把 64×7×7 的特征图展平成 3136 维,经过 128 个神经元后输出 10 类得分。
MNIST 图片是 28×28 的灰度图,所以in_channels=1。经过两次池化后,空间尺寸正好是 7×7,因此展平后的维度是 64×7×7。
4.3 编写训练脚本(train.py)
文件路径:train.py
import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader from torchvision import datasets, transforms from model import SimpleCNN # 1. 设置随机种子,保证实验结果可复现 def set_seed(seed=42): torch.manual_seed(seed) set_seed() # 2. 设备管理:优先使用 GPU device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print("使用设备:", device) # 3. 数据预处理:转为张量并归一化 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) # 4. 下载并加载训练集 train_dataset = datasets.MNIST( root="./data", train=True, transform=transform, download=True, ) train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True) # 5. 初始化模型、损失函数、优化器 model = SimpleCNN(num_classes=10).to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 6. 训练循环 num_epochs = 5 for epoch in range(1, num_epochs + 1): model.train() # 进入训练模式 running_loss = 0.0 correct = 0 total = 0 for images, labels in train_loader: images, labels = images.to(device), labels.to(device) # 梯度清零 optimizer.zero_grad() # 前向传播 outputs = model(images) # 计算损失 loss = criterion(outputs, labels) # 反向传播 + 参数更新 loss.backward() optimizer.step() # 统计损失和准确率 running_loss += loss.item() * images.size(0) _, predicted = torch.max(outputs, 1) total += labels.size(0) correct += (predicted == labels).sum().item() epoch_loss = running_loss / len(train_dataset) epoch_acc = correct / total * 100 print(f"Epoch[{epoch}/{num_epochs}] Loss: {epoch_loss:.4f} Acc: {epoch_acc:.2f}%") # 7. 保存模型权重 torch.save(model.state_dict(), "./mnist_cnn.pth") print("模型已保存到 ./mnist_cnn.pth")这个脚本的核心流程是:
- 设置随机种子,确保结果可复现;
- 自动检测 GPU 和 CPU;
- 将图片数据转换为张量,并做归一化处理,加速模型收敛;
- 使用
torchvision.datasets.MNIST自动下载数据,并封装成 DataLoader; - 初始化模型、交叉熵损失函数、Adam 优化器;
- 执行 5 轮训练,每轮结束后打印损失和准确率;
- 保存模型参数。
这里特别解释几个关键点。
optimizer.zero_grad()用于清空历史梯度。如果不清零,PyTorch 默认会梯度累积,导致参数更新方向错误。
loss.backward()负责计算所有参数的梯度。optimizer.step()根据梯度和学习率更新参数。这三行代码是训练循环里的固定搭配。
model.train()和model.eval()会影响部分层的行为,例如 Dropout 和 BatchNorm。训练时必须调用model.train()。
在 GPU 环境,图片和标签都需要通过.to(device)放到 GPU 上。如果忘记这一步,会报 “Expected all tensors to be on the same device” 错误。
4.4 编写测试脚本(test.py)
训练完成后,我们可以写一个测试脚本,加载保存的模型权重,在测试集上验证准确率。
文件路径:test.py
import torch from torch.utils.data import DataLoader from torchvision import datasets, transforms from model import SimpleCNN # 设备管理 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 数据预处理 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) # 加载测试集 test_dataset = datasets.MNIST( root="./data", train=False, transform=transform, download=True, ) test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False) # 加载模型 model = SimpleCNN(num_classes=10).to(device) model.load_state_dict(torch.load("./mnist_cnn.pth", map_location=device)) model.eval() correct = 0 total = 0 with torch.no_grad(): for images, labels in test_loader: images, labels = images.to(device), labels.to(device) outputs = model(images) _, predicted = torch.max(outputs, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print(f"测试集准确率: {correct / total * 100:.2f}%")注意torch.no_grad()的使用。在推理阶段,我们不需要计算梯度,关闭梯度计算可以节省显存和计算资源,同时加速推理。
model.eval()告诉模型当前处于评估模式,这一点在含 Dropout 的模型中特别重要。如果不切换模式,每次试算结果都会有随机性。
4.5 运行与结果说明
打开命令行,进入pytorch_mnist_demo目录,激活虚拟环境后依次执行:
conda activate pytorch python train.py首次运行会自动下载 MNIST 数据集到./data目录。数据集的下载速度取决于网络环境,如果下载太慢,可以手动下载数据集文件后放到对应的目录中,这是题外话,这里先按下不表。
训练 5 轮后,控制台大概输出如下信息(具体数值受随机种子和软硬件影响,会有小幅波动):
使用设备: cpu Epoch[1/5] Loss: 0.1978 Acc: 93.78% Epoch[2/5] Loss: 0.0573 Acc: 98.20% Epoch[3/5] Loss: 0.0390 Acc: 98.75% Epoch[4/5] Loss: 0.0285 Acc: 99.05% Epoch[5/5] Loss: 0.0223 Acc: 99.25% 模型已保存到 ./mnist_cnn.pth从输出可以看到,只训练了 1 轮,准确率就接近 94%,5 轮之后训练集准确率超过 99%,说明这个简单的 CNN 在 MNIST 上效果非常好。
接着执行:
python test.py输出类似:
测试集准确率: 99.04%也就是说,在模型从未见过的测试集上,准确率也能达到 99% 左右。这验证了模型不仅“记住了”训练集,还真正学到了数字图像的特征。
到这里,你已经完整体验了一个深度学习项目的全流程:数据加载、模型定义、训练、验证、模型保存和加载。
5. 常见问题与排查思路
新手在学习 PyTorch 的过程中一定会遇到各种报错。下面整理了几个最常见的问题和对应的排查思路。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
ModuleNotFoundError: No module named 'torch' | 当前环境没有安装 PyTorch,或激活了错误的 conda 环境 | 检查激活环境;重新执行 pip install torch |
torch.cuda.is_available()返回 False | 安装的是 CPU 版本 PyTorch;CUDA 驱动不匹配 | 查看 nvidia-smi 的 CUDA 版本,去官网安装对应 GPU 版本 |
RuntimeError: Expected all tensors to be on the same device | 模型参数和数据不在同一个设备上 | 模型调用.to(device),数据也要调用.to(device) |
CUDA out of memory | 批次太大、图片太大或显存不足 | 减小 batch_size;降低图片分辨率;使用with torch.no_grad()推理 |
| 训练 Loss 为 NaN | 学习率过高、数据含有 NaN、损失函数使用不当 | 降低学习率;检查数据;添加梯度裁剪torch.nn.utils.clip_grad_norm_ |
| MNIST 数据集下载卡住 | 网络无法访问国外服务器 | 手动下载数据集并放置到本目录;使用国内镜像源(按实际网络选择) |
| 模型预测结果全是同一个类别 | 数据没有归一化、模型未收敛、标签错位 | 检查数据预处理;打印 batch 内标签分布;增加训练轮数 |
除了表格里的问题,这里再补充一个新手经常忽略的细节:在训练循环里一定要调用optimizer.zero_grad()。如果梯度不清零,梯度会在多个批次之间累积,导致 Loss 震荡甚至不收敛。
此外,如果你遇到“与官方文档示例不一致”的情况,多半是 PyTorch 版本差异导致的。以 PyTorch 2.x 来说,torchvision.transforms的某些接口和旧版有所变化,更新代码时最好查阅对应版本的官方文档,不要盲目复制老代码。
6. 最佳实践与工程建议
6.1 工程目录与命名规范
建议把“数据加载”“模型定义”“训练逻辑”“测试逻辑”拆分成独立文件。如果你未来做更复杂的项目,目录结构可以是:
project/ ├── config/ # 配置文件 ├── data/ # 数据集 ├── models/ # 模型定义 ├── utils/ # 工具函数 ├── train.py # 训练入口 ├── test.py # 测试入口 └── requirements.txt # 依赖清单命名方面,模型文件用model.py或models/cnn.py,配置类使用全大写下划线命名,例如LEARNING_RATE = 1e-3。这些规范虽然简单,但能极大提升多人协作时的可读性。
6.2 配置管理
不要在生产代码里硬编码超参数。推荐使用配置文件或命令行参数管理学习率、批次大小、训练轮数等。PyTorch 本身没有强制要求,但工程中常见做法是:
- 使用
argparse接收命令行参数; - 使用
yaml或json配置训练参数; - 将关键超参数记录到日志中。
这样,你调整模型时不需要改源代码,也能追溯某一个实验到底用了哪些参数。
6.3 设备管理与随机种子
训练脚本开头建议统一管理设备:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")与此同时,为了保证实验可复现,在创建模型、加载数据之前先设置随机种子。PyTorch 的随机种子可以直接设置,但如果你使用了 NumPy 或者 Python 内置 random,也需要一起设置:
import random import numpy as np import torch seed = 42 random.seed(seed) np.random.seed(seed) torch.manual_seed(seed)如果你的模型对精度要求较高,还需要考虑 GPU 的确定性计算设置。不过对于刚入门阶段,记住设置 CPU 和 GPU 的种子就够了。
6.4 日志与模型保存
训练过程中不要只打印 Loss,建议同时记录准确率、学习率、时间等关键信息。最简单的做法是使用logging模块,也可以从第三方库(如 TensorBoard 或 wandb)中选择,按需引入即可。
模型保存时,要注意区分两种形式:
torch.save(model.state_dict(), path):只保存权重,文件小,加载时需要先构建模型结构。torch.save(model, path):保存整个模型对象,加载方便,但兼容性较差,不推荐。
推荐使用state_dict方式保存。在测试脚本中,用load_state_dict加载权重时,要确保模型结构定义一致。
6.5 数据处理的边界问题
深度学习模型对数据的分布极其敏感。MNIST 训练集做了Normalize操作,测试集也必须使用完全相同的均值和标准差,否则模型效果会受影响。
批量处理图像时,如果图片尺寸不统一,数据集内部要统一做 resize 或 padding;如果数据分布极不均衡,要考虑类别权重或采样策略。这些都是训练前必须排查的边界问题。
6.6 训练调试技巧
- 先用小规模数据(比如几十条)跑通代码,再上全量数据。
- 如果 Loss 长期不降,可以尝试调大学习率;如果 Loss 爆炸或变 NaN,立刻调小学习率。
- 用
torch.utils.tensorboard或简单打印中间特征图,观察模型是否按预期工作。 - 在遇到显存不足时,优先检查数据张量是否意外被复制、是否在
no_grad下做推理。
7. 总结与下一步学习路线
通过这篇文章,你从零完成了 PyTorch 的完整入门:
- 理解了 PyTorch 框架解决的核心问题,以及为什么它成为深度学习主流框架。
- 搭建了独立的 Python 虚拟环境,并完成了支持 GPU/CPU 的 PyTorch 安装。
- 掌握了张量、自动求导、模型定义、数据加载四个核心知识点。
- 实现了完整的 CNN 手写数字识别项目,训练出了测试准确率约 99% 的模型。
- 整理了常见报错和排查思路,以及工程实践中的关键经验。
接下来你可以按下面的顺序继续提升:
- 尝试把模型改成不同的结构,比如加深卷积层、加入 BatchNorm 和 Dropout,观察效果变化。
- 到 Kaggle 找一些简单的比赛数据集,按照本文流程完整走一遍数据探索、训练、提交。
- 学习迁移学习,用 PyTorch 加载预训练的 ResNet、VGG 等模型,完成自定义图像分类。
- 学习模型部署相关内容,理解 FP32、FP16、BF16、TF32 等浮点数格式对推理性能和精度的影响,为模型上线做准备。
深度学习知识体系庞大,但 PyTorch 是最值得投入时间掌握的框架。它本身设计友好,社区活跃,资料丰富。建议你跟着本文把代码完整跑一遍,遇到问题不要急着跳过,学会看报错信息、查官方文档,这是每个深度学习开发者都必须具备的能力。如果这篇文章对你有帮助,可以先收藏备用,后面实战遇到问题再回来对照排查。