2026/4/16 21:53:31
网站建设
项目流程
来宾网站seo,福田附近公司做网站建设哪家效益快,网站提交至google,网站站点地图#x1f4fa; B站#xff1a;博主个人介绍
#x1f4d8; 博主书籍-京东购买链接*#xff1a;Yocto项目实战教程
#x1f4d8; 加博主微信#xff0c;进技术交流群#xff1a; jerrydev MNIST 入门实战#xff1a;从数据流到模型训练与评估#xff08;含完整代码与流…B站博主个人介绍博主书籍-京东购买链接*Yocto项目实战教程加博主微信进技术交流群jerrydevMNIST 入门实战从数据流到模型训练与评估含完整代码与流程图目标用 MNIST 把深度学习最核心的一条主线走通——数据 → 模型 → 损失 → 反向传播 → 更新参数 → 评估 → 保存/加载 → 推理。读完你会对“训练到底在做什么”“评估到底评估了什么”“.pth 到底是什么”形成清晰、稳定的概念框架并具备继续突破到更复杂任务CIFAR、检测、分割、YOLO、Transformer的基础。1. 你已经做到了什么为什么这条路径很重要你已经跑通了一个完整的 CNN 分类项目数据MNIST模型两层卷积 两层全连接带 Dropout训练CrossEntropyLoss SGD评估test loss test acc保存生成mnist_cnn.pth并且得到了非常合理的结果test acc ≈ 97%test loss 逐步下降这说明数据流DataLoader没问题模型结构forward没问题训练闭环loss → backward → step成立评估逻辑eval no_grad 统计正确参数存档.pth可复用。这条路径是所有 AI 任务的“地基”。以后你换数据集、换模型、换任务本质上还是这条主线只是每一段更复杂。2. 全流程总览一张逻辑图把它串起来下面这张“主线流程图”非常建议你记住┌──────────────┐ │ 数据集 Dataset │ MNIST(train/test) └──────┬───────┘ │ transform(ToTensor/Normalize) ▼ ┌──────────────┐ │ DataLoader │ batch化、shuffle、并行加载 └──────┬───────┘ │ (data:[B,1,28,28], target:[B]) ▼ ┌──────────────┐ │ 模型 Net │ forward: [B,1,28,28] → logits[B,10] └──────┬───────┘ │ ▼ ┌──────────────┐n│ Loss 函数 │ CrossEntropyLoss(logits, target) └──────┬───────┘ │ ▼ ┌──────────────┐ │ backward() │ 自动求梯度: p.grad └──────┬───────┘ │ ▼ ┌──────────────┐ │ optimizer.step│ 更新参数: θ ← θ - lr * grad └──────┬───────┘ │ ▼ ┌──────────────┐ │ 评估 Evaluate │ net.eval no_grad 指标统计 └──────┬───────┘ │ ▼ ┌──────────────┐ │ 保存/加载 .pth │ state_dict() / load_state_dict() └──────────────┘你可以把它理解为Net是“会计算的结构”Loss把“对不对”变成“可优化的数字”Backward给每个参数算出“该往哪改”Optimizer真正“改参数”Evaluate用测试集验证“改得值不值”。3. 数据部分Dataset / Transform / DataLoader 到底做了什么3.1 MNIST 是什么数据MNIST 是手写数字识别数据集图片28×28 灰度图单通道标签0~9 十个类别训练集60000测试集10000在 PyTorch 里一条样本通常表现为image:torch.Tensor形状[1,28,28]label:int范围 0…93.2 为什么 DataLoader 出来是[B,1,28,28]你训练时拿到的是一个 batchdata.shape [B, 1, 28, 28]target.shape [B]四维的含义非常固定维度含义MNIST 示例Bbatch_size32C通道数1灰度H高度28W宽度28只要你看到[B,C,H,W]你就知道它是“图片批次输入”。3.3 transformToTensor Normalize 为什么必做你的 transform 典型是transformtransforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))])ToTensor()把图像从0~255的像素转换为0~1的 float 张量Normalize(mean, std)做标准化[x’ \frac{x - mean}{std}]为什么要标准化让输入分布更稳定梯度更容易优化训练更快、收敛更稳定。你看到min/max出现负数就是 Normalize 生效的直接证据。3.4 你本地的 data/ 目录意味着什么你看到的data/MNIST/raw/ train-images-idx3-ubyte train-labels-idx1-ubyte t10k-images-idx3-ubyte t10k-labels-idx1-ubyte说明数据源来自torchvision.datasets.MNIST(rootdata/, downloadTrue, ...)评估时使用trainFalse对应t10k-*测试集训练时使用trainTrue对应train-*训练集。4. 模型部分Net 是“结构”参数是“记忆”4.1 你写的 Net 到底是什么在 PyTorch 里class Net(nn.Module)定义了网络结构哪些层、如何连接forward(self, x)定义了前向计算输入如何流过这些层模型参数权重、偏置被nn.Conv2d / nn.Linear等层自动创建。一句话模型 结构Net 参数weights/bias。4.2 CNN 为什么有效卷积、池化、全连接各自负责什么可以把 CNN 分为两段特征提取器Conv/Pool分类器Linear直觉理解Conv在局部区域找“笔画、边缘、拐角”Pool让特征更稳、更省计算FC把多个特征组合输出 10 类得分4.3 形状追踪你必须会“追输出形状”以你常用结构为例输入[B,1,28,28]conv1(1→8, k3)[B,8,26,26]maxpool(2)[B,8,13,13]conv2(8→16, k3)[B,16,11,11]maxpool(2)[B,16,5,5]flatten[B,400]因为 1655400fc1[B,40]fc2[B,10]logits只要你追得出 400 的来源你对 CNN 的理解就非常稳。4.4 logits 是什么为什么不是直接输出概率模型输出[B,10]这不是概率而是 logits打分。预测类别通常是predlogits.argmax(dim1)# [B]训练时用CrossEntropyLoss(logits, target)它内部会做 softmax 相关处理所以你不需要手写 softmax。5. 训练部分三件套把“计算结构”变成“会学习的系统”5.1 训练三件套loss / backward / optimizer训练的核心闭环forward模型输出 logitsloss把“错得程度”变成一个数字backward求每个参数的梯度该往哪改step更新参数真的改最简骨架optimizer.zero_grad()logitsnet(data)losscriterion(logits,target)loss.backward()optimizer.step()5.2 为什么一定要 zero_grad()PyTorch 默认会把梯度累加如果不清零上一个 batch 的梯度会污染当前 batch。你可以把它理解为每个 batch 都要单独算一次“该怎么改”不能把历史梯度一直加下去。5.3 net.train() 与 net.eval() 的区别非常关键这不是“可有可无”。尤其你用了 Dropout。net.train()训练模式Dropout 生效net.eval()评估模式Dropout 关闭输出更稳定你出现 test acc 比 train acc 高一点在带 Dropout 的训练里不罕见训练时更难评估时更容易。5.4 为什么 loss 会从 2.3 降下来在 10 类分类里模型完全随机时每类概率大约 1/10交叉熵大约 (\ln(10) ≈ 2.3026)所以你最开始看到 loss ≈ 2.3 非常合理。训练后模型对正确类别给更高分loss 就下降。6. 评估部分你到底评估了什么关键函数和关键变量你目前做的基础评估非常正确平均 losstest avg loss准确率test accuracy评估的关键点6.1 评估数据从哪里来评估使用的是MNIST 测试集test_dstorchvision.datasets.MNIST(data/,trainFalse,...)对应你目录里的t10k-images-idx3-ubytet10k-labels-idx1-ubyte6.2 评估为什么要 no_grad()评估只需要 forward不需要 backward。torch.no_grad()的价值更快更省显存更不容易内存爆6.3 评估最核心的统计逻辑是什么logitsnet(data)losscriterion(logits, target)predlogits.argmax(dim1)correct(pred target).sum()最终avg_loss total_loss / total_samplesacc total_correct / total_samples7. 训练日志该怎么读你这份结果说明了什么你的输出Epoch 1: train loss0.6006, train acc80.70% test loss0.1068, test acc96.75% Epoch 2: train loss0.3271, train acc89.95% test loss0.0856, test acc97.34% Epoch 3: train loss0.2842, train acc91.26% test loss0.0718, test acc97.60%可以简单做三点结论loss 在下降说明优化器在持续把模型往正确方向推acc 在上升说明预测正确率提升test acc 达到 97%说明模型已经学到 MNIST 的主特征你的模型在 3 个 epoch 已经接近“够用”。如果继续训练可能还会涨但收益会变小。8.mnist_cnn.pth到底是什么怎么理解它的“类型”8.1.pth不是模型结构而是模型参数你保存的是torch.save(net.state_dict(),mnist_cnn.pth)state_dict()是一个“参数字典”键是参数名值是张量.pth只是常用后缀名表示 PyTorch 的保存文件一句话mnist_cnn.pth保存的是你训练得到的“记忆”权重/偏置。8.2 为什么必须同时有 Net 才能用.pth.pth本身不包含forward的代码逻辑。可用模型 Net()load_state_dict(mnist_cnn.pth)。8.3 你可以用一行看它内部是什么importtorch sdtorch.load(mnist_cnn.pth,map_locationcpu)print(type(sd))print(list(sd.keys())[:10])你会看到它是 dict里面有conv1.weight、fc2.bias等键。9. 一份“初学者最推荐”的工程组织方式你现在的结构已经很健康jerry_mnist/ create_model.py # 模型结构 get_data.py # 数据准备可选 train_model.py # 训练 评估 保存 eval_basic.py # 建议新增单独评估 mnist_cnn.pth # 训练结果参数 data/ # MNIST 数据缓存推荐原则模型结构独立文件便于复用训练脚本只管训练评估脚本只管评估推理脚本只管推理这样你后面做 CIFAR10、做猫狗分类、做 YOLO都可以复用思路。10. 代码模板最简训练脚本带注释下面是一份“看一眼就懂”的训练框架与你现在的逻辑一致# train_model.py结构示意# 1) 准备 DataLoadertrain_loader / test_loader# 2) 创建模型 net Net().to(device)# 3) 定义 loss optimizer# 4) 循环 epoch# 4.1 net.train()# 4.2 对 train_loaderzero_grad → forward → loss → backward → step# 4.3 net.eval() no_grad()# 4.4 对 test_loaderforward → 统计 loss/acc# 5) 保存参数 torch.save(net.state_dict(), mnist_cnn.pth)你要掌握的是“骨架”以后换任何任务都能套进去。11. 评估进阶从两个指标走向“知道错在哪”你现在评估了 loss/acc这已经是基础合格。接下来想提高理解和实战能力建议加三种评估混淆矩阵看哪些数字互相混淆每类准确率哪个类最弱错误样本可视化错的样本长什么样这三件事会让你从“知道结果不错”升级到“知道怎么继续提升”。12. 从 MNIST 走向更大突破下一步练什么最有效当你把 MNIST 这一套跑稳后推荐你按这个顺序升级12.1 升级数据CIFAR-1032×32 彩色图3 通道更贴近真实视觉任务你会遇到数据增强、过拟合、模型更深12.2 升级模型更规范的 CNNBatchNorm、更多层加 BatchNorm 稳定训练更深的网络、残差结构ResNet12.3 升级任务目标检测YOLO输入输出不再是 10 类得分变为框位置 类别 置信度但注意无论怎么升级“主线流程图”依旧成立。13. 关键知识点清单建议你定期扫一遍数据Dataset / DataLoader[B,C,H,W]含义transformToTensor / Normalize模型nn.Module/forwardConv / Pool / Flatten / Linearlogits 与 argmax训练criterionCrossEntropyLossoptimizerSGD/Adamzero_grad → forward → loss → backward → steptrain()vseval()评估no_grad()avg loss / accuracy错误分析混淆矩阵、错例保存state_dict()/load_state_dict().pth是参数存档不是结构14. 你目前这份项目的一句话“专业总结”你已经完成了一个可复用的 PyTorch 图像分类最小工程使用torchvision.datasets.MNIST构建训练/测试数据流使用自定义 CNN两层卷积 两层全连接 Dropout进行分类使用CrossEntropyLoss SGD完成训练闭环并达到97%测试准确率使用state_dict()将训练得到的参数保存为mnist_cnn.pth可在任意环境中通过load_state_dict()复现推理效果。15. 附你可以直接复制的“推理脚本”骨架可选如果你想快速验证.pth的价值# predict_one_batch.pyimporttorchimporttorchvisionfromtorch.utils.dataimportDataLoaderfromtorchvisionimporttransformsfromcreate_modelimportNet devicecudaiftorch.cuda.is_available()elsecpu# 1) load modelnetNet().to(device)net.load_state_dict(torch.load(mnist_cnn.pth,map_locationdevice))net.eval()# 2) test loadertransformtransforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))])test_dstorchvision.datasets.MNIST(data/,trainFalse,downloadTrue,transformtransform)test_loaderDataLoader(test_ds,batch_size32,shuffleTrue)data,targetnext(iter(test_loader))datadata.to(device)withtorch.no_grad():logitsnet(data)predlogits.argmax(dim1).cpu()print(pred[:10] ,pred[:10].tolist())print(target[:10],target[:10].tolist())结尾你下一步应该做什么最实用如果你想把基础打得更牢建议你立刻做两个小任务写一个eval_basic.py只输出 test loss / test acc你已经理解清楚写一个eval_confusion.py输出混淆矩阵 错例图知道错在哪做完这两步你会对“评估”不再停留在“跑出一个数字”而是能解释为什么这样、如何继续提升。如果你希望我继续按“最小步骤”推进下一步我会在不增加太多代码复杂度的前提下带你实现混淆矩阵 错例可视化这一步对形成实战直觉特别有帮助。