ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

深度学习21个项目实例:从环境配置到迁移学习的实践指南

深度学习21个项目实例:从环境配置到迁移学习的实践指南 简介这是面向深度学习初学者的项目合集包含二十一个可运行实例覆盖数据预处理、模型构建、训练验证到部署评估的完整流程帮助读者动手掌握深度神经网络、卷积神经网络、循环神经网络、长短时记忆网络及生成对抗网络等主流模型的实际应用。资源包共九百一十一个文件以五百一十一个Python脚本、一百零四张JPG与六十六张PNG图像、五十五个Markdown说明文档为主体辅以proto、shell、config等配置整体约五十五点八一MB。Python脚本对应各项目核心代码图像用于数据集与训练可视化Markdown文档提供思路注释目录结构清晰便于检索。目前已有六千七百人学习浏览适合希望系统提升深度学习实践能力的初学者及求职者。通过完成这些实例可熟悉常用框架用法积累模型调优与部署经验为后续研究和工作打下扎实基础。1. 深度学习21个项目实例为什么跑了那么多入门教程你手里还是没有一个能用的项目很多人在入门深度学习时会遇到一个很典型的困境教程看了一堆MNIST和CIFAR-10也跑通了但一到自己手里有张乱糟糟的表格、一批没标注的图片就不知道从哪下手。我拆过的这套21个项目实例资源做的事情就是把这个断层补上。它把图像分类、目标检测、文本情感分析、语音识别、GAN生成这些常见任务拆成21个完整可复现的工程每个都带数据准备、网络搭建、训练与评估代码。换句话说你跟着做完21个得到的不是“会调库”而是一套能直接迁移到毕设或工作里的方法。适合刚跑通框架、想做实战项目的人也适合需要快速验证想法的从业者这份深度学习实例里每个项目都是独立闭环拿来改一改就能用。2. 项目全景与选型21个项目怎么排布先跑哪个、后跑哪个2.1 任务域与难度梯度图像、文本、语音、综合四类怎么分我拿到这套资源的第一件事不是急着跑代码而是把21个项目按任务域重新排了一遍。整理完之后你会发现它并不是21个孤立的小例子而是在按“视觉感知—序列建模—生成与决策”这条线递进。常见的分布大致是图像识别类占三分之一包括手写数字识别、猫狗分类、验证码识别、人脸表情识别目标检测与分割类有交通标志检测、人脸检测、用YOLO做目标框定位、语义分割文本类包括情感分析、垃圾邮件分类、新闻文本分类、聊天机器人语音类一般有两个简单的语音命令识别和声纹分类剩下的就是GAN生成人脸、风格迁移、自编码器、推荐系统和强化学习打游戏这类综合项目。我建议你不要被这个列表吓到也不要从第一个项目老老实实往后刷。正确做法是先明确自己的目标域。如果你手里只有一堆图片那就先做图像识别类因为CNN里的卷积、池化、全连接是后面目标检测和分割的基础如果你平时处理的是评论、邮件、简历这些文本那就先跳到情感分析和垃圾邮件分类把词嵌入、LSTM、注意力机制吃透再回头补图像部分。难度梯度上手写数字和猫狗分类是入门级通常跑通一次只需要十几分钟到YOLO和GAN时训练时间、显存、调参复杂度都会明显上来至少要预留出半天到一天的时间专门去啃。我实际拆项目时有个习惯先把21个项目的“数据来源”和“依赖库”列出来。这份资源里每个项目都有独立的requirements.txt或import清单但因为你会在一个环境里连续跑多个项目版本冲突会很酸爽。所以我建议你用一张表格记录每个项目用到的框架版本、数据集大小、训练时长和显存占用这样你在做到第7、8个项目时不会因为前一个项目留下的CUDA版本问题把自己搞到心态崩。表头可以按“项目名、任务类型、框架、数据集、单epoch时间、显存峰值”来设计每跑完一个就填一行后面做毕设或项目选型时直接翻这张表比再看一遍代码快得多。2.2 框架、环境与硬件选型先看数据再看算力这套资源里的项目绝大多数是基于PyTorch写的少数给的是TensorFlow或Keras版本。我给你的选型建议很直接所有项目优先用PyTorch跑因为调试时print中间张量最方便动态图机制也允许你在训练循环里随时打断改逻辑。如果某个项目只给了TensorFlow代码也别慌看它的网络结构是不是通用的ResNet、VGG、LSTM那套是的话直接对照着在PyTorch里重写反而能加深理解。除非你本身熟练TensorFlow否则不要在初学阶段同时维护两套框架。环境配置是这里第一个大坑。深度学习环境配置别看网上一堆教程真正容易翻车的不是装PyTorch而是CUDA版本、显卡驱动和Torch版本三者对不上。我一般会用conda新建一个独立环境不给全局环境添乱。命令如下conda create -n dl21 python3.9 -y conda activate dl21 conda install pytorch torchvision torchaudio pytorch-cuda11.8 -c pytorch -c nvidia pip install opencv-python matplotlib pandas scikit-learn tqdm这里的-n dl21是指定环境名避免和已有的环境冲突pytorch-cuda11.8是我根据自己显卡驱动定的版本号如果你的显卡驱动比较新可以用12.x如果显卡是老型号或者根本没有NVIDIA卡就不要装CUDA版直接执行conda install pytorch cpu torchvision torchaudio -c pytorch。后三行pip包里opencv负责图像读写和增强pandas和scikit-learn用来处理结构化数据tqdm用来显示训练进度条。装完之后建议你跑一行python -c import torch; print(torch.cuda.is_available())输出True才说明环境没问题。硬件上我拆完这套项目后给你一个大概的底数2G显存能跑跑基础CNN4G可以跑小型ResNet8G可以跑YOLO和一般分割模型16G以上再考虑训练完整的GAN或大Batch的Transformer。如果没有独立GPU用CPU也不是不行但一定要把数据规模先砍到十分之一比如原来用5万张图先用5千张验证流程等代码逻辑跑通后再上大锅。这点极其重要很多人一上来就用全量数据在CPU上跑半小时后发现代码里有个维度错了时间全白费。我自己的习惯是任何项目先拉通一个小数据集确认loss能下降、验证指标能变化再切回完整数据集。3. 复现一个实战项目数据准备、训练脚本与参数调优的完整链路3.1 数据准备与预处理从文件夹到DataLoader拿里面最典型的“猫狗分类”项目来说数据准备的流程和很多真实业务场景是一样的你拿到的是一堆散落在文件夹里的图片需要让PyTorch能按类名读取。这里最常用的工具是torchvision.datasets.ImageFolder它要求目录结构是data/train/cat/xxx.jpg和data/train/dog/xxx.jpg这样的二级目录类名就是文件夹名。很多新手之所以翻车就是把所有图片直接扔进train目录结果ImageFolder把整个目录当成一类训练出来的模型准确率永远在50%上下。下面这段是标准的预处理写法可以直接抄进你自己的项目里from torchvision import datasets, transforms from torch.utils.data import DataLoader train_transform transforms.Compose([ transforms.Resize((224, 224)), # 统一尺寸适配预训练网络输入 transforms.RandomHorizontalFlip(), # 随机翻转增加样本多样性 transforms.ColorJitter(brightness0.3, contrast0.3), # 颜色抖动抗过拟合 transforms.ToTensor(), # HWC转CHW像素归一化到0~1 transforms.Normalize(mean[0.485, 0.456, 0.406], # 用ImageNet的均值和方差做标准化 std[0.229, 0.224, 0.225]) ]) train_data datasets.ImageFolder(rootdata/train, transformtrain_transform) train_loader DataLoader(train_data, batch_size32, shuffleTrue, num_workers4, pin_memoryTrue) print(类别映射:, train_data.class_to_idx) print(样本数:, len(train_data))这段代码里Resize((224, 224))是把所有图片缩放到同一个大小否则同一个batch里张量形状不一致PyTorch会直接报错。RandomHorizontalFlip和ColorJitter都是数据增强它们的意义是让模型不会死记硬背每一张图片的像素排列而是学到猫和狗更本质的特征。Normalize里的mean和std为什么是这三个值因为后面要用预训练模型时预训练权重是在ImageNet上练的输入数据也要服从相同的分布不然效果会打折扣。num_workers4是开4个子进程加载数据能显著提高GPU利用率但如果你是在Windows上跑这个值不要设太大否则会引发内存问题。class_to_idx这个字典非常重要它记录了“猫”对应0、“狗”对应1后面做预测时要靠它反查标签。3.2 训练脚本与参数调优学习率、batch size与epochs怎么定数据准备好了下一步就是把网络结构搭起来。对于猫狗分类这种小任务直接从头训练一个深层CNN不是不行但效果不如用预训练的ResNet18做微调。所谓微调就是把ImageNet上已经学会识别纹理、形状、物体边界的权重拿过来只把最后一层全连接换成你自己的类别数。这在21个项目实例里是最常用的一招也是通用性最强的一招。下面这份训练脚本是我整理过的最小可用版本import torch import torch.nn as nn from torchvision import models model models.resnet18(weightsmodels.ResNet18_Weights.IMAGENET1K_V1) num_ftrs model.fc.in_features # 原始全连接层输入维度是512 model.fc nn.Linear(num_ftrs, 2) # 替换成二分类输出 model model.cuda() criterion nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.parameters(), lr1e-3) scheduler torch.optim.lr_scheduler.StepLR(optimizer, step_size5, gamma0.1) for epoch in range(15): model.train() running_loss 0.0 for images, labels in train_loader: images, labels images.cuda(), labels.cuda() optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() * images.size(0) scheduler.step() print(fEpoch {epoch1}: loss{running_loss/len(train_loader.dataset):.4f})写这个脚本时有几个参数需要你特别留意。第一weightsmodels.ResNet18_Weights.IMAGENET1K_V1是PyTorch新版本推荐写法旧代码里的pretrainedTrue在新版会报警告最好照我这样写。第二model.fc nn.Linear(num_ftrs, 2)里的2必须和你的类别数一致如果是做21个项目里的表情识别就改成对应的表情类别数。第三Adam默认学习率1e-3对微调来说通常合适但如果loss出现震荡先降到1e-4试试。第四StepLR(step_size5, gamma0.1)的意思是每5个epoch把学习率乘以0.1这是一个非常粗粒度的退化策略适合快速验证等你想认真跑指标时可以换成ReduceLROnPlateau它会根据验证loss是否停滞自动调整。参数调优时一个容易被忽略的点是batch size对学习率的牵制。你在帖子里看到各种“最佳batch size”都不如自己试但有个基本规律batch size翻倍学习率也大约翻倍batch size减半学习率也要减半。如果直接改小batch size却不减学习率训练loss就会像心电图一样上下乱跳。另外验证集一定不能忘。上面这个脚本为了省篇幅没有写验证部分但你在实际复现时每个epoch结束后要在验证集上算一次准确率并且保存验证准确率最高那次的模型权重。我用torch.save(model.state_dict(), best_model.pth)做这件事之后预测时直接加载这个文件而不是用最后一个epoch的模型这能让你少走很多弯路。4. 复现路上的常见问题与避坑环境、显存、过拟合与版本撕裂4.1 类别标签全反了但训练loss还正常下降现象训练loss确实在降验证准确率却一直卡在50%左右怎么调参都没用。后来我随机打印了8张验证图片和它们的预测标签发现模型把猫全猜成了狗把狗全猜成了猫而且置信度很高。原因问题几乎都出在数据目录结构上。ImageFolder读取时按文件夹名的字母顺序分配类别索引比如文件夹叫cat和dog那么cat是0、dog是1。但是有人在划分数据集的时候把cat的图片放到了dog文件夹里或者某个文件夹下面多了一层子目录导致标签错位。而训练loss正常下降是因为模型确实学到了东西只是学到了一个反向映射。解决每次开始训练前打印train_data.class_to_idx再手动取一个batch用matplotlib或直接print(images, labels)对比图片内容和标签。我一般会写一行断言assert len(train_data.class_to_idx) 2先保证类别数对再检查具体映射。数据准备阶段多花两分钟能给训练阶段省出两个小时排错。4.2 显存不够把batch size从32改到4后模型完全不收敛现象在2G显存的机器上跑YOLO或稍大一点的模型几轮迭代后直接CUDA out of memory。我按网上建议把batch size改成4不再爆显存了但loss开始震荡甚至越训越高。原因batch size从32变成4之后每个batch的梯度方向噪声变得非常大模型参数更新的路径像无头苍蝇一样乱撞。而且学习率还是为32这个batch size调的对于4来说明显偏大等效于每一步都迈得太猛直接跨过了loss洼地。更麻烦的是有些带BatchNorm的模型在batch size1时统计量会失真导致后面的层完全乱套。解决不要直接用一个很小的batch size硬扛。正确做法是保持逻辑上的batch size不变用梯度累积来凑。比如你想用32但每步只能装8那就设batch_size8、accumulation_steps4每4个mini-batch之后再做一次参数更新。在代码里就是loss.backward()之后先不调optimizer.step()等累计了4次再更新更新前把梯度平均一下。如果连8都装不下那就要么换更小的网络要么降低输入图片分辨率。4.3 loss卡在0.693附近一动不动模型输出的全是常数现象二分类项目里训练loss从一开始的0.7慢慢爬到0.693附近然后几十个epoch都不动。准确率稳定在50%跟抛硬币一样。原因0.693这个值在白噪声分类器上非常典型它等于-ln(0.5)说明模型的输出已经退化成对每个样本都给出相同的概率完全没有在学特征。最常见的原因是学习率过大导致权重在初始点附近反复震荡或者数据里两个类别的图像质量差异太大模型直接学到了“判断为多数类”的捷径。另一个容易被忽略的原因是BatchNorm层在batch size为1或2时统计量崩溃让整个网络输出变成常数。解决先看训练集里两类的样本数量是不是严重失衡再尝试把学习率降到1e-4甚至1e-5让模型慢慢进入状态最后确保batch size至少大于4。如果是预训练模型还要检查训练循环开头是不是忘了写model.train()如果你把model.eval()遗留在上一个验证环节BN层就不会更新统计量loss同样会卡死。4.4 环境版本不一致昨天还能跑的代码今天突然报错现象前一个项目用的PyTorch 1.12后一个项目依赖PyTorch 2.1我在同一个conda环境里直接pip升级结果训练时torch.utils.data开始报一些莫名其妙的RuntimeError甚至import torch都会出现undefined symbol: cudnn_xxx的C级别报错。原因这是典型的套件版本撕裂。PyTorch、CUDA、cuDNN三者是强耦合关系你用pip直接覆盖安装很可能把与CUDA配套的cuDNN版本搞乱。深度学习项目本身不是每行代码都会碰到这些底层库但当版本不匹配时往往不是你代码写错了而是二进制库互相冲突。解决我给每个大项目单独开一个conda环境并固定核心版本号。环境跑通后马上用conda env export environment.yaml导出一份清单。这样哪天环境崩了直接conda env create -f environment.yaml就能恢复。另外尽量不要在conda环境里用pip安装torch或torchvision除非你能明确知道pip默认提供的包与当前CUDA版本匹配。4.5 准确率很高但少数类全被吞掉现象一个文本情感分类项目90%的样本是正向10%是负向。训练后准确率达到90%看起来非常漂亮但一检查混淆矩阵负向样本几乎全被预测成正向AUC只有0.5左右。原因数据集类别不平衡时模型不需要学习任何特征只要把所有样本都预测成多数类就能拿到90%的准确率。这个现象在21个项目实例里不少见尤其是验证码识别这种类别分布天然不均匀的任务。DeepLearning模型本质上是在最小化期望损失如果多数类的样本数量碾压少数类模型就会选择最简单的捷径。解决用一个带权重的采样器或者给损失函数加类别权重。下面这段代码放在DataLoader之前比手动复制少数类样本更稳class_counts [3000, 500] # 两个类别的样本数 num_total sum(class_counts) weights [num_total / c for c in class_counts] sample_weights [weights[label] for label in train_data.targets] sampler torch.utils.data.WeightedRandomSampler( sample_weights, num_samplesnum_total, replacementTrue) train_loader DataLoader(train_data, batch_size32, samplersampler)WeightedRandomSampler的实现逻辑是样本数少的类别被抽中的权重高每个epoch里模型见到少数类的次数就会增加。你在替换成自己的数据集时只需要把class_counts换成你统计出的每类样本数。注意num_samples最好设成所有样本的总数这样每个epoch处理的样本量大致保持不变不会出现一个epoch特别长一个特别短的问题。5. 从复现到自研三个迁移学习技巧让你的毕设直接用上这套资源前面几章都在讲怎么跑通和避坑但这份21个项目实例的价值跑通只是起点。真正值钱的是把里面已经训练好的权重和网络结构迁移到你自己任务上的能力。这里给你三个我反复用的技巧。第一个技巧是替换分类头。无论你拿到的是猫狗分类的ResNet、还是表情识别的小型CNN最后一层全连接的输出维度都是跟着原始类别数走的。你可以像前面那样先打印model.fc或model.classifier的in_features然后把最后一层替换成nn.Linear(in_features, my_num_classes)。如果你的任务和源任务差异较大比如源任务是图像你手头是音频波谱图那就不只替换分类头还需要把输入的in_channels改成1同时观察第一层卷积的效果。第二个技巧是分层冻结。数据量少、自己的数据集只有几千张时千万别让整个网络从头到尾随意微调。常见的做法是先冻结所有层的参数只训练最后两层或分类头等分类头在验证集上不再提升后再解冻最后几个卷积层一起微调学习率降到原来的十分之一。在PyTorch里冻结很简单遍历模型参数并把requires_grad置为False就行。这个操作能明显减少过拟合因为预训练模型前面的卷积核提取到的棱角、颜色、纹理特征在绝大多数视觉任务里是通用的。第三个技巧是学会用验证曲线判断模型是否真的在学。你可以在训练循环里每50个batch记录一次loss和当前batch的准确率训练结束后画两条曲线。如果训练loss持续下降但验证loss明显回升那就是过拟合优先增加数据增强或加大dropout如果两者同时卡住不动那就是学习率太低或网络容量不够如果训练loss下降慢得像条直线可以考虑换优化器或调整batch size。这套方法不管以后你接触什么框架、什么任务判断思路都不会变。我从这份资源里收获最大的一点不是学会了某个特定网络怎么写而是养成了一套“先小规模验证、再全量训练”的工作习惯。从那以后我每次拿到新项目都强制自己先跑通一个最小可复现的流程确认数据、模型、训练三部分都没问题再回头精调参数。这个习惯帮我避开了无数个深夜调参的坑希望帮到你。本文还有配套的精品资源点击获取
返回列表