ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

深度学习入门路线:从Python环境到CNN与Transformer实战

深度学习入门路线:从Python环境到CNN与Transformer实战 这几年经常有同学问我深度学习到底该怎么入门网上资料确实很多但问题也很明显——要么是纯理论推导看完连环境都装不起来要么直接丢出一大段模型代码新手根本不知道每一行在干什么。尤其是 CNN 和 Transformer 这两个概念一个是从图像领域火起来的一个是从 NLP 领域火起来的很多教程把它们拆成两套完全独立的体系去讲结果初学者学完卷积又学注意力脑子里始终没有一条主线。这篇文章我会完整地走一遍基于 Python 的深度学习入门路线从环境搭建开始讲到神经网络的核心原理再分别拆解 CNN 和 Transformer 的底层结构最后用 PyTorch 做一个可以跑起来的图像分类实战把 CNN 和 Transformer 放在同一个任务里对比。整个过程不追求让你一口气吃成胖子而是把每一个环节都拆成“是什么、为什么、怎么用”三层保证零基础的同学也能照着操作。无论你是计算机专业的学生、想转行 AI 的开发者还是工作中需要用到深度学习的算法工程师这篇文章都能帮你把零散的知识点串成一条完整的学习链路。1. 背景与核心概念1.1 深度学习到底在学什么深度学习本质上是一种基于多层神经网络的机器学习方法。这里的“深度”指的是网络层数多、模型表达能力强而不是说它有多高深莫测。传统机器学习需要人工设计特征比如你想让程序识别一张图片里有没有猫你得先告诉程序“猫有耳朵、有胡须、有尾巴”程序再根据这些规则去判断。这种方式在面对“猫的品种不同、拍摄角度不同、光线不同”的情况时会非常脆弱。深度学习的思路完全不同。它会自己从原始数据中逐层提取特征第一层可能学到边缘和颜色第二层学到纹理和形状第三层学到局部结构更深层就能学到“猫脸”“猫耳”这种高层语义特征。这个自动提取特征的过程就是深度学习最大的价值所在。从应用角度来说深度学习目前主要覆盖三大类任务计算机视觉图像分类、目标检测、图像分割、人脸识别。自然语言处理机器翻译、文本分类、问答系统、大语言模型。语音与多模态语音识别、语音合成、图文匹配、视频理解。这三类任务背后核心的模型骨架其实就是神经网络、CNN、RNN/LSTM、Transformer 这几个家族。其中 RNN 类模型在 Transformer 出现之后慢慢退居二线所以这篇文章会重点讲 CNN 和 Transformer这也是目前工业界用到最多的两个架构。1.2 为什么 Python 是深度学习的主流语言深度学习不是只能用 Python 写但 Python 绝对是生态最完善的选择。主要原因有三个第一开发效率高。Python 语法简单写模型的时候可以把关注点放在网络结构本身而不是纠结内存管理和指针。第二开源生态丰富。PyTorch、TensorFlow、Keras、PaddlePaddle 这些主流深度学习框架全部提供 Python 接口而且社区维护的预训练模型、训练工具、可视化工具几乎都优先支持 Python。第三和科学计算栈无缝衔接。NumPy、pandas、Matplotlib、scikit-learn 这些库都是 Python 生态的一部分做数据处理和实验分析时不需要切换语言。1.3 神经网络、CNN、Transformer 的关系很多新手会把这三个概念搞混这里先做一个全局梳理神经网络Neural Network是所有深度模型的底层基础。它由神经元、权重、偏置、激活函数组成通过前向传播计算输出通过反向传播更新参数。CNN卷积神经网络是神经网络的一种特殊结构。它在普通全连接层的基础上引入了“卷积核”和“池化”的概念可以高效处理图片这种网格状数据。Transformer则是一种完全不同的架构思路。它抛弃了卷积改用“自注意力机制”来建模全局依赖关系最初用于机器翻译后来横扫整个深度学习领域。从时间线看神经网络是最早的概念CNN 在 2012 年的 ImageNet 比赛上让深度学习一夜爆火Transformer 在 2017 年由 Google 提出并在 2020 年前后开始取代 CNN 和 RNN成为大模型时代的主流骨架。2. 环境准备与版本说明2.1 硬件与操作系统选择深度学习的实验环境推荐顺序是云 GPU 服务器 本地有 NVIDIA 显卡的电脑 本地纯 CPU 电脑。如果你是纯新手第一台机器不一定要买显卡。像 MNIST、CIFAR-10 这种入门数据集用 CPU 训练也能跑通只是速度慢一些。等理解流程之后再去租 GPU 跑大模型是不错的学习策略。操作系统方面Windows、Linux、macOS 都可以做深度学习开发。需要注意的是NVIDIA GPU 的深度学习加速依赖 CUDA 环境macOS 的 M 系列芯片目前对 PyTorch 也提供了优化支持但很多生态工具仍然优先适配 Linux 和 Windows。本文示例基于 Windows 11 环境演示版本差异不影响整体思路。2.2 Python 与虚拟环境安装深度学习开发强烈建议使用虚拟环境而不是直接把依赖装在系统 Python 里。原因是深度学习项目依赖的库版本很容易冲突比如项目 A 需要 PyTorch 1.13项目 B 需要 PyTorch 2.1如果混装就会引发各种诡异问题。推荐使用 Anaconda 来管理 Python 和虚拟环境。安装 Anaconda 后打开 Anaconda Prompt 创建一个新的环境conda create -n deeplearning python3.10 -y conda activate deeplearningPython 3.10 是一个比较稳妥的选择大多数深度学习框架都已经适配不会像 3.12、3.13 那样偶尔遇到个别库还没跟上版本的情况。安装完成后检查环境是否正常python --version pip --version2.3 安装 PyTorchPyTorch 是目前学术界和工业界使用率最高的深度学习框架非常适合入门学习。安装 PyTorch 时最重要的一个选择是 CPU 版本还是 GPU 版本。如果电脑没有 NVIDIA 显卡安装 CPU 版本pip install torch torchvision如果有 NVIDIA 显卡建议先到 PyTorch 官网首页查看对应 CUDA 版本的安装命令。以 CUDA 11.8 为例pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118注意CUDA 版本需要和显卡驱动匹配。如果驱动版本较老建议先更新显卡驱动再安装对应的 CUDA 运行库。PyTorch 安装包自带了 CUDA 运行库所以不需要额外安装完整的 CUDA Toolkit这一点对新手很友好。验证安装是否成功import torch print(torch.__version__) print(torch.cuda.is_available())如果第二行输出True说明 GPU 可用输出False也没关系代码仍然可以运行只是使用 CPU 计算。3. 核心原理拆解从神经网络到 Transformer3.1 神经网络的最小单元神经元一个最简单的神经元接收多个输入每个输入有一个权重再加上一个偏置然后经过激活函数输出结果。数学形式是output activation(w1*x1 w2*x2 ... wn*xn b)w是权重b是偏置。训练神经网络的过程就是不断调整这些权重和偏置让模型的预测结果接近真实答案。激活函数的作用是给模型引入非线性。如果没有激活函数不管网络叠多少层本质上还是一个线性模型表达能力非常有限。常见的激活函数有 ReLU、Sigmoid、Tanh其中 ReLU 是隐藏层的首选import torch.nn as nn # ReLU 激活函数 activation nn.ReLU()3.2 前向传播与反向传播前向传播指的是数据从输入层经过各隐藏层计算最终得到输出结果的整个过程。反向传播则是根据输出结果和真实标签之间的差距损失值从最后一层往前逐层计算梯度再用梯度下降法更新每一层的参数。这里不建议新手一开始就去啃反向传播的数学推导先用loss.backward()和optimizer.step()把流程跑通再回过头补数学学习效率会高很多。3.3 CNN 的核心思想局部连接与参数共享CNN 解决的核心问题是全连接网络处理图片时参数量太大。假设一张 256×256 的彩色图片像素数量是 196608 个如果第一层全连接层有 1024 个神经元那这一层的参数量就有 2 亿多训练起来几乎不可能。CNN 通过两个关键手段解决这个问题局部连接每个神经元只和输入图片的一个局部区域相连这个区域就是“感受野”。一张图片的特征往往是局部的比如眼睛、鼻子、耳朵不需要看完整张图才能判断。参数共享同一个卷积核会在整张图片上滑动权重是共享的。这意味着不管图片有多大一个卷积核的参数量只取决于卷积核的大小和图片尺寸无关。一个标准 CNN 块通常包含三层操作卷积操作提取局部特征。激活函数引入非线性。池化操作降低特征图尺寸减少计算量。用 PyTorch 定义一个卷积层非常简单import torch.nn as nn # 输入通道3输出通道16卷积核大小3x3 conv_layer nn.Conv2d(in_channels3, out_channels16, kernel_size3, stride1, padding1)这里的padding1是为了保持特征图的宽高尺寸不变。如果不加 padding每经过一次卷积特征图尺寸就会缩小 2 个像素。3.4 Transformer 的核心思想自注意力机制Transformer 和 CNN 最大的不同在于CNN 只能看到局部区域而 Transformer 的注意力机制可以一次性看到整张图片或整段文本中的所有位置。“自注意力”的直观理解是在处理某个位置的数据时模型会自动计算出它与所有其他位置的相关程度然后把信息按相关程度加权聚合起来。以一句话为例“小明在操场上打球因为天气很好”。模型理解“打球”这个词时会重点关注“小明”和“操场”而不是把所有词一视同仁。自注意力的计算分为三步把输入向量分别乘以三个权重矩阵得到查询Query、键Key、值Value。用 Query 和所有 Key 计算相似度得到注意力分数。用 softmax 归一化后加权求和 Value。公式表达为Attention(Q, K, V) softmax(Q * K^T / sqrt(d_k)) * VTransformer 还有两个关键设计位置编码和多头注意力。由于注意力机制本身不包含位置信息模型无法区分“第一个词”和“最后一个词”所以需要把位置编码加到输入向量里。多头注意力则让模型同时从多个子空间关注信息一个头关注语法关系另一个头关注语义关系最后拼接起来。效果比单头注意力更丰富。3.5 为什么最终是 Transformer “胜出”从 CNN 到 Transformer很多人会问一个问题为什么现在的大模型全部用 TransformerCNN 是不是被淘汰了准确地说CNN 没有被淘汰但在通用模型架构这个层面上Transformer 确实成了主流选择。原因可以归结为三点第一建模能力更强。CNN 的卷积操作受感受野限制深层特征需要堆很多层才能看到全图。Transformer 的注意力机制天然建模全局依赖第一层就能看到所有位置。第二训练效率更高。注意力计算的矩阵运算是高度可并行的而 RNN 依赖时间步的串行计算所以 Transformer 在 GPU 上训练效率远超 RNN。第三扩展性好。Transformer 的架构简单统一稍微变形就能处理文本、图像、语音、视频。GPT 系列证明了一个规律参数规模越大Transformer 的泛化能力越强。当然Transformer 的计算复杂度较高所以现在也有 Swin Transformer、Vision Transformer 这些改进版本在不同场景下做效率和效果的权衡。4. 实战基于 PyTorch 的图像分类项目这一节我们用 PyTorch 从零搭建一个图片分类项目分别用 CNN 和 Transformer这里使用小型变体实现并在同一份数据集上对比效果。数据集选用 MNIST 手写数字识别这是深度学习界的“Hello World”。4.1 项目结构设计先创建如下目录结构deeplearning_实战/ ├── data/ # 数据集存放目录 ├── models/ │ ├── __init__.py │ ├── cnn_model.py # CNN 模型定义 │ └── transformer_model.py # Transformer 模型定义 ├── train.py # 训练脚本 ├── predict.py # 推理脚本 └── requirements.txt # 依赖清单4.2 数据准备与加载PyTorch 的torchvision库内置了 MNIST 数据集的下载和加载功能不需要手动去网站下载。代码如下# 文件路径data_loader.py import torch from torch.utils.data import DataLoader from torchvision import datasets, transforms def get_mnist_dataloader(batch_size64, trainTrue): transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) dataset datasets.MNIST( root./data, traintrain, downloadTrue, transformtransform ) dataloader DataLoader( dataset, batch_sizebatch_size, shuffletrain, num_workers0 ) return dataloadertransforms.Normalize是数据标准化操作MNIST 数据集的全局均值和标准差分别是 0.1307 和 0.3081。标准化后模型收敛速度会更快。4.3 定义 CNN 模型下面这个 CNN 模型结构简单但足以跑出 99% 以上的准确率# 文件路径models/cnn_model.py import torch.nn as nn import torch.nn.functional as F class SimpleCNN(nn.Module): def __init__(self, num_classes10): super(SimpleCNN, self).__init__() # 第一个卷积块1通道 - 32通道 self.conv1 nn.Conv2d(in_channels1, out_channels32, kernel_size3, padding1) self.bn1 nn.BatchNorm2d(32) # 第二个卷积块32通道 - 64通道 self.conv2 nn.Conv2d(in_channels32, out_channels64, kernel_size3, padding1) self.bn2 nn.BatchNorm2d(64) # 池化层 self.pool nn.MaxPool2d(kernel_size2, stride2) # 全连接层 self.fc1 nn.Linear(64 * 7 * 7, 128) self.fc2 nn.Linear(128, num_classes) self.dropout nn.Dropout(0.5) def forward(self, x): # 输入 shape: (batch_size, 1, 28, 28) x F.relu(self.bn1(self.conv1(x))) x self.pool(x) x F.relu(self.bn2(self.conv2(x))) x self.pool(x) # 展平 x x.view(x.size(0), -1) x F.relu(self.fc1(x)) x self.dropout(x) x self.fc2(x) return x这里需要注意两个点第一BN 层的意义。BatchNorm2d 对每个 batch 的数据做归一化能让模型在训练过程中更加稳定收敛速度更快。第二featurn map 尺寸变化。MNIST 图片输入是 28×28经过第一层 padding1 的卷积后仍然是 28×28池化后变成 14×14。再经过第二次卷积和池化后变成 7×7。因此展平后的维度是 64×7×7。4.4 定义微型 Transformer 模型Transformer 原生处理的是序列数据对于图片需要先转换成“图像块序列”。这里我们参考 ViTVision Transformer的思路把 28×28 的图片切成 7×7 大小的图像块每个块的特征维度是 7×749一共 4×416 个块。# 文件路径models/transformer_model.py import torch import torch.nn as nn class PatchEmbedding(nn.Module): 把图片切成 patch 并映射成向量 def __init__(self, in_channels1, patch_size7, embed_dim64): super(PatchEmbedding, self).__init__() self.patch_size patch_size self.proj nn.Conv2d(in_channels, embed_dim, kernel_sizepatch_size, stridepatch_size) def forward(self, x): # x shape: (batch, channels, 28, 28) x self.proj(x) # (batch, embed_dim, 4, 4) x x.flatten(2) # (batch, embed_dim, 16) x x.transpose(1, 2) # (batch, 16, embed_dim) return x class SimpleTransformer(nn.Module): 一个简化版的 Transformer 编码器 def __init__(self, num_classes10, embed_dim64, num_heads4, num_layers2): super(SimpleTransformer, self).__init__() self.patch_embed PatchEmbedding() # 类别令牌可学习的分类向量 self.cls_token nn.Parameter(torch.randn(1, 1, embed_dim)) # 位置编码 self.pos_embed nn.Parameter(torch.randn(1, 17, embed_dim)) # Transformer 编码层 encoder_layer nn.TransformerEncoderLayer( d_modelembed_dim, nheadnum_heads, dim_feedforward128, dropout0.1, activationrelu ) self.encoder nn.TransformerEncoder(encoder_layer, num_layersnum_layers) self.fc nn.Linear(embed_dim, num_classes) def forward(self, x): B x.size(0) x self.patch_embed(x) # (B, 16, embed_dim) # 拼接类别令牌 cls_tokens self.cls_token.expand(B, -1, -1) x torch.cat([cls_tokens, x], dim1) # (B, 17, embed_dim) # 加上位置编码 x x self.pos_embed # Transformer 编码 x self.encoder(x) # 取 cls_token 对应的输出做分类 x x[:, 0] x self.fc(x) return x这个模型的思路是把图片分割成小块转换成序列然后像处理文本一样用 Transformer 编码器去处理这些图像块。cls_token是 ViT 里的经典设计它本身没有任何输入信息但在训练过程中会不断聚合整张图片的全局信息最后用它的输出来做分类。4.5 训练脚本实现训练脚本要覆盖几件事加载数据、初始化模型、定义损失函数和优化器、循环训练并验证。# 文件路径train.py import torch import torch.nn as nn from torch.optim import Adam from data_loader import get_mnist_dataloader from models.cnn_model import SimpleCNN from models.transformer_model import SimpleTransformer def train_one_epoch(model, dataloader, criterion, optimizer, device): model.train() total_loss 0 correct 0 total 0 for images, labels in dataloader: images, labels images.to(device), labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() total_loss loss.item() _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() avg_loss total_loss / len(dataloader) accuracy correct / total return avg_loss, accuracy def validate(model, dataloader, criterion, device): model.eval() total_loss 0 correct 0 total 0 with torch.no_grad(): for images, labels in dataloader: images, labels images.to(device), labels.to(device) outputs model(images) loss criterion(outputs, labels) total_loss loss.item() _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() avg_loss total_loss / len(dataloader) accuracy correct / total return avg_loss, accuracy def main(): device torch.device(cuda if torch.cuda.is_available() else cpu) # 加载数据 train_loader get_mnist_dataloader(batch_size64, trainTrue) val_loader get_mnist_dataloader(batch_size64, trainFalse) # 选择模型可切换 cnn / transformer model_type cnn # 改成 transformer 即可切换模型 if model_type cnn: model SimpleCNN(num_classes10).to(device) elif model_type transformer: model SimpleTransformer(num_classes10).to(device) else: raise ValueError(fUnknown model type: {model_type}) criterion nn.CrossEntropyLoss() optimizer Adam(model.parameters(), lr1e-3) epochs 10 for epoch in range(epochs): train_loss, train_acc train_one_epoch(model, train_loader, criterion, optimizer, device) val_loss, val_acc validate(model, val_loader, criterion, device) print(fEpoch {epoch1}/{epochs} | fTrain Loss: {train_loss:.4f} | Train Acc: {train_acc:.4f} | fVal Loss: {val_loss:.4f} | Val Acc: {val_acc:.4f}) # 保存模型权重 torch.save(model.state_dict(), fmodel_{model_type}.pth) if __name__ __main__: main()在这个脚本里设置model_type cnn训练 CNN设置为transformer训练微型 Transformer。4.6 训练结果对比在 CPU 环境下MNIST 数据集训练 10 轮通常只需要几分钟。作者在实际测试中两种模型的最终验证准确率都稳定在 98% 到 99% 之间。这里有一个有意思的现象对于 MNIST 这种小尺寸图片数据集CNN 的表现完全不输给 Transformer而且训练速度更快。这也说明了一个重要经验模型选型要结合任务和数据规模不要盲目追求“最先进”的架构。Transformer 的优势在大规模数据和长序列任务上才会真正体现出来。如果只跑 MNIST你用 ViT 和用 CNN 不会有明显差别甚至 CNN 收敛更快。4.7 推理与可视化训练完成后写一个推理脚本加载图片并输出预测结果# 文件路径predict.py import torch from PIL import Image from torchvision import transforms from models.cnn_model import SimpleCNN def predict_image(model_path, image_path): device torch.device(cuda if torch.cuda.is_available() else cpu) model SimpleCNN(num_classes10) model.load_state_dict(torch.load(model_path, map_locationdevice)) model.to(device) model.eval() transform transforms.Compose([ transforms.Resize((28, 28)), transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) image Image.open(image_path).convert(L) image transform(image).unsqueeze(0).to(device) with torch.no_grad(): outputs model(image) _, predicted torch.max(outputs, 1) print(f预测结果: {predicted.item()}) if __name__ __main__: predict_image(model_cnn.pth, test_image.png)这里有一点需要注意单张图片推理时unsqueeze(0)的作用是增加一个 batch 维度因为模型期望的输入形状是(batch_size, channels, height, width)即使只有一张图也要凑成四维张量。5. 常见问题与排查思路深度学习入门阶段遇到的报错大多集中在环境配置、张量维度、设备不匹配这几个方面。下面是高频问题清单问题现象常见原因解决思路安装 PyTorch 时下载速度慢或超时网络问题使用国内镜像源pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simpletorch.cuda.is_available()返回 FalseCUDA 版本与驱动不匹配更新显卡驱动确认 PyTorch 安装版本对应 CUDAIndexError: Target 10 is out of bounds标签从 1 开始而不是从 0 开始检查数据集的类别编号范围RuntimeError: mat1 and mat2 shapes cannot be multiplied全连接层输入维度计算错误打印特征图尺寸对照计算公式CUDA out of memorybatch size 太大或显存不足调小 batch size使用更小的输入分辨率模型训练 loss 为 NaN学习率过高或数据未归一化降低学习率确认数据经过 Normalize训练时 loss 不下降模型结构有问题或优化器参数不合理先用少量样本过拟合验证模型可收敛5.1 MNIST 模型维度报错怎么排查维度报错是新手遇到最多的一个问题。以 CNN 为例输入图片 shape 是(1, 28, 28)表示单通道、高 28、宽 28经过 DataLoader 打包后变成(64, 1, 28, 28)表示 64 张图。 如果某一步展平后的维度算错了全连接层的输入维度就和真实输入不一致pytorch 会直接抛出矩阵乘法形状不匹配的错误。排查方法很简单在模型 forward 函数里加打印语句。def forward(self, x): print(f输入 shape: {x.shape}) x F.relu(self.bn1(self.conv1(x))) print(fconv1 输出: {x.shape}) x self.pool(x) print(fpool1 输出: {x.shape}) # ... 继续打印每一步跑一次训练看每一层输出的 shape就能准确定位是哪一步算错了。5.2 训练速度很慢怎么办如果你的电脑没有独立显卡训练速度确实是瓶颈。可以试试下面的优化方案调小 batch size比如从 64 改为 32。减小输入图片的尺寸MNIST 也可以缩放到 14×14。降低训练轮数先用 2 轮验证程序能跑通。使用更小的模型减少卷积层通道数。在模型训练验证通过后再迁移到云 GPU 平台上跑完整实验。5.3 conda 创建环境后找不到 torch这种情况通常是环境激活失败。在 Windows 终端里使用 Anaconda Prompt 执行conda activate deeplearning后再确认环境路径conda info --envs运行pip list查看 torch 是否安装成功如果 torch 不在当前环境里可能是直接用了系统 python 来执行代码。可以用python -c import torch; print(torch.__version__)确认下当前 Python 环境的 torch 状态。6. 最佳实践与工程建议6.1 代码工程化规范深度学习项目写久了就会发现训练的代码和调试的代码如果不做整理很快就会变成一团乱麻。建议从一开始就养成工程化习惯。第一配置文件与代码分离。不要把所有超参数都写死在代码里推荐用一个config.yaml或config.py管理学习率、batch size、epoch、模型类型、数据路径等配置。# 文件路径config.py class Config: # 数据配置 data_root ./data batch_size 64 num_workers 0 # 模型配置 model_type cnn # cnn / transformer num_classes 10 embed_dim 64 num_heads 4 num_layers 2 # 训练配置 epochs 10 learning_rate 1e-3 momentum 0.9 device cuda if torch.cuda.is_available() else cpu第二设置随机种子。深度学习训练过程中有大量随机初始化如果不固定种子复现结果会非常困难。import random import numpy as np import torch def set_seed(seed42): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed)第三训练、验证、测试集分离。很多新手训练集和验证集混在一起导致模型过拟合了还不知道。正确做法是训练集用来更新模型参数验证集用来做模型选择和调参测试集只在最终评估时使用一次。6.2 训练过程记录与日志管理不要只靠print来观察训练过程。当训练轮数变多、模型变复杂后你需要一个结构化的日志方案。推荐使用 TensorBoard 或 wandb。TensorBoard 是本地免费的from torch.utils.tensorboard import SummaryWriter writer SummaryWriter(runs/mnist_cnn) for epoch in range(epochs): train_loss, train_acc train_one_epoch(...) val_loss, val_acc validate(...) writer.add_scalar(Loss/train, train_loss, epoch) writer.add_scalar(Loss/val, val_loss, epoch) writer.add_scalar(Acc/train, train_acc, epoch) writer.add_scalar(Acc/val, val_acc, epoch) writer.close()此时在命令行执行tensorboard --logdirruns然后在浏览器里打开http://localhost:6006就能看到训练曲线。6.3 过拟合的识别与处理判断模型是否过拟合看训练集准确率和验证集准确率的差距即可。如果训练集准确率接近 100%但验证集准确率明显更低说明模型把训练样本的细节“背”下来了而不是学到了通用规律。常用解决方案按优先级排序增加数据量或使用数据增强随机裁剪、旋转、翻转。添加 Dropout 或 BatchNorm。使用正则化L2 weight decay。降低模型复杂度。提前停止early stopping。6.4 训练与推理的性能优化训练阶段和提高推理吞吐量侧重点不同。训练时更看重吞吐量和显存占用推理时更看重延迟和模型体积。对于生产级项目可以做这些优化混合精度训练使用 fp16 或 bf16 精度大幅提升训练速度并降低显存占用。模型量化将权重从 fp32 转为 int8减小模型体积提升推理速度。TorchScript 导出把 PyTorch 模型导出为TorchScript在 C 环境中部署。ONNX 转换将模型转为 ONNX 格式方便在不同推理框架上部署。这里特别注意混合精度训练中 fp32、fp16、bf16、tf32 的差异非常关键。简单来说fp32 是标准精度但占用内存大fp16 速度更快但表示范围小bf16 保留了 fp32 的动态范围适合大模型训练tf32 是 NVIDIA Ampere 架构上用于加速 fp32 矩阵运算的精度。实际选型要根据模型和显存情况来衡量。6.5 复现性与版本锁定深度学习框架更新很快PyTorch 1.x 和 2.x 在某些 API 行为上存在差异。在工程项目里建议使用requirements.txt锁定关键依赖torch2.1.0 torchvision0.16.0 numpy1.26.0 pillow10.1.0 tensorboard2.14.0这样即使半年后重新拉起项目也能保证基本可用。需要注意的是完全复现实验结果还需要固定 GPU 型号和 CUDA 版本因为不同 GPU 的浮点数运算结果存在微小差异。事实上不同精度格式fp32、fp16、bf16、tf32的选择会影响结果的精度和训练速度这也是“深度学习模型部署”环节里比较隐蔽的一个坑你本地用 fp32 训练和验证的结果到生产环境用 fp16 或 int8 推理后可能会略有偏差所以在模型上线前最好做一次精度对比验证。7. 总结与学习路线到这里我们已经把“Python 深度学习入门到精通”这条路上的核心节点都走了一遍。你现在应该已经掌握深度学习解决的核心问题是什么以及神经网络、CNN、Transformer 三者的关系。如何从零搭建 Python 深度学习环境包括 Anaconda、PyTorch 的安装与验证。神经网络的神经元、前向传播、反向传播、激活函数等基础概念。CNN 的卷积、池化、参数共享等核心原理以及它为什么适合图片任务。Transformer 的自注意力机制、位置编码、多头注意力以及它为什么能成为大模型的主流架构。用 PyTorch 完成一个图像分类实战项目的完整流程包括数据加载、模型定义、训练和推理。常见的报错排查方法和深度学习工程的规范化习惯。下一步你可以从两个方向继续深入方向一深耕模型原理。读 PyTorch 官方 Tutorial手写一个完整的反向传播过程深入理解梯度消失与梯度爆炸学习 BatchNorm 和 Dropout 的内部实现然后用 ResNet、Vision Transformer 替换本文的简单模型在 CIFAR-10 上跑出更好的实验对比。方向二转向工程应用。学习数据增强、模型部署、ONNX 导出、混合精度训练、分布式训练再把目光放到当前火热的大语言模型和 AIGC 方向研究 GPT、Diffusion 等模型的核心设计思路。实际项目中最优先需要关注的风险是环境版本不一致导致的结果无法复现、训练集与验证集划分不合理导致的评估失真以及模型上线前的浮点数精度变化。这些都不是模型结构本身的问题但往往是最容易让项目“翻车”的地方。深度学习入门并不需要一上来就啃完所有数学公式。先把这条链路跑通再逐步加深理解你会发现它并没有想象中那么难。如果这篇文章对你有帮助建议收藏备用。学习过程中遇到问题欢迎在评论区留下你的报错信息一起交流排查思路。
返回列表