十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

极市平台目标检测实训全流程:从数据清洗到云端部署的实战经验

极市平台目标检测实训全流程:从数据清洗到云端部署的实战经验 这次极市平台实训我选了目标检测方向带的任务是一个实际场景下的物体识别项目要求最终交出一个能在云端稳定推理、结果达到指定精度的模型文件。说实话刚开始拿到任务时我是有点懵的因为和平时在本地随便跑跑notebook不一样平台会限时限算力评测端是黑盒提交的方式也有固定规范。整个流程走下来从数据清洗、模型训练到最终交付踩了不少坑也积累了不少可以复用的经验。这篇东西就是给那些准备在极市平台上做实训、打比赛或者第一次接触这种“平台化AI开发”流程的朋友把我实际走过的弯路和验证过的做法一次性讲清楚。特别是如果你已经习惯在自己电脑上用PyTorch或者TensorFlow写Demo一定要看看第3节和第5节——云端训练任务和本地Notebook的思维完全不是一回事很多本地能跑通的代码放到平台评测环境里就是各种离奇报错。1. 立项前我先做了这三件事读题、摸数据、跑通baseline1.1 极市平台实训到底长什么样极市平台本身是一个面向计算机视觉开发者的云端AI平台实训项目通常会给出一套完整的数据集、预置的GPU训练环境和在线评测系统有的还会配套官方baseline。你不需要自己搭建服务器也不需要担心数据集下载慢登录网页就能直接进开发机把数据集挂载进去然后训练、推理、提交评测全流程都在上面完成。但好处背后也有约束。第一算力不是无限的平台对训练时长、GPU实例类型、文件大小都会有具体配额你没法像在公司服务器上那样随意挂着十几个实验第二评测环境是相对固定的提交的模型和推理脚本必须匹配平台指定的依赖版本和接口规范第三数据是受管控的一般不会允许你把训练集下载到本地反复折腾。所以实训的第一步不是打开代码编辑器而是先把平台的文档、任务说明和评测规则从头到尾读一遍。我见过不少同学上来就写模型写到一半才发现任务评测指标是mAP而不是Accuracy损失函数、后处理逻辑全都得换非常浪费时间。1.2 动手写网络之前先学会看评测指标实训任务书里最核心的信息就是评测指标。目标检测类任务通常是mAP分类任务最常见的是Accuracy或F1分割任务则是mIoU。指标不同直接决定了模型设计、训练策略和最后的后处理方式。举个例子如果你做的是目标检测但是评测标准里明确写了“仅在IoU阈值0.5下计算mAP”那你的模型就不需要特别纠结边界框的定位精度更值得把精力放在提高召回率上。反过来如果评测用了0.5:0.95的COCO标准边界框回归质量就非常关键回归损失在整个训练里的权重就得认真调。我的习惯是先把评测指标的计算逻辑用小脚本在本地验证一遍哪怕手头只有一个很笨的模型也要确保提交格式能被评测脚本正确解析。这一步看似简单但能让你在后续所有实验里都有一把准确的“尺子”而不是靠猜。1.3 baseline不是用来刷分的是用来定契约的很多实训项目会提供官方baseline或者至少给一个官方的数据读取示例。拿到之后我的建议是第一件事不是改进它而是原封不动跑通它。跑通baseline意味着你确认了下面这一整串信息训练数据路径怎么挂载标注文件放在哪个目录类别ID与类别名的对应关系图像读入时用OpenCV还是PIL通道顺序是BGR还是RGB模型输出需要什么形式是原始logits、经过softmax的概率还是检测框列表最后提交文件的命名和压缩格式。这些细节我统称为“契约”。baseline就是一个帮你验证契约是否正确的最短路径。如果跳过这一步直接用自己的代码从本地往上传很容易遇到“本地一切正常、评测分数为零”的尴尬情况。2. 数据这一关比模型更早教会我做人2.1 拿到数据后先做结构化体检很多教程都会说数据很重要但极少有教程告诉你拿到数据后具体该看什么。我在实训里总结了一套固定的“数据体检”流程顺序大概是统计图片总数、类别数量、每类样本数可视化随机抽样20-30张图人工确认标注框与物体是否匹配检查图片尺寸分布找出极端长宽比和超小分辨率检查是否有损坏图片、单通道图片、带透明通道的PNG检查标注框是否出现坐标越界、宽度高度为0、类别ID超范围等异常。这些操作听起来琐碎但非常必要。极市平台实训里我给自己的要求是模型可以换数据必须先用脚本彻底摸一遍。我当时写了一个简单的数据统计脚本专门用来检查标注框面积分布。后来发现一个小目标占了很大的召回权重如果不提前发现后面模型再怎么调参都很难让mAP有明显上涨。import json from collections import Counter with open(annotations/instances_train.json) as f: data json.load(f) # 统计每张图的标注数量 img_ann_count Counter() for ann in data[annotations]: img_id ann[image_id] img_ann_count[img_id] 1 # 查看标注框面积分布框面积过小的目标可能需要特殊处理 areas [ann[area] for ann in data[annotations]] small sum(1 for a in areas if a 32 * 32) print(f总标注数: {len(areas)}, 小目标占比: {small / len(areas):.2f})2.2 标注格式不一致是第一个坑极市平台的数据集有时会直接给COCO格式或VOC格式但有的时候给的可能是平台自定义的格式。最稳妥的做法是把所有格式统一成一种内部标准格式再写一个统一的Dataset类去读取。我在一次实训里遇到过标注框坐标是归一化浮点数的情况没有仔细看说明直接用像素坐标去算损失结果模型训练出来预测框全偏到角落。后来一点点排查才发现是坐标系统不一致。这就是为什么我说不要跳过数据体检——很多Bug长得像模型问题实际是数据问题。另外要特别注意类别映射。平台数据集的类别顺序可能和预训练模型的类别顺序不同如果你的模型是迁移学习来的最后分类头的输出维度必须重新初始化不能直接沿用预训练模型的类别参数。2.3 数据增强不是越多越好数据增强是实训涨点的重要工具但它有一个很多人忽略的大前提增强策略必须和评测时的数据分布对齐。比如训练时做了大幅度的随机裁剪和缩放但评测时的图片是等比缩放到固定尺寸再送入模型的两边的目标尺度分布就不一致。这种情况下训练里看到的物体大小五花八门评测时看到的全是某个特定尺度模型在尺度泛化上反而吃亏。我这次的做法是分阶段增强前期用基础增强随机水平翻转、轻微亮度对比度扰动、随机缩放先把模型正常训起来后期如果出现明显的过拟合再逐步引入更激进的增强比如Mosaic、CopyPaste或者AutoAugment。每次增加一个增强操作就做一个消融实验确保它真的带来收益而不是凭感觉全堆上去。3. 平台算力怎么用才不浪费3.1 开发机与训练任务的取舍用极市平台实训最常见的操作误区是把所有代码和训练都跑在“开发机”里像使用本地Jupyter一样开着页面等结果。但平台开发机本质上是给你做代码调试和数据处理用的长时间挂着训练任务会占用GPU资源甚至可能因为达到时限被强制释放。更合理的做法是在开发机上调试小批量数据确认代码没问题后把完整训练提交为独立的训练任务让平台调度GPU去跑。前端和后端分离的思路在这里也同样适用——开发机相当于你的开发环境训练任务才是生产环境。生产环境跑长训练开发环境光做验证、写代码和看日志这种分工能最大化利用配额。我在第一次实训时没意识到这点一直占着开发机训练结果中途进度丢失后面的实验计划全部被打乱非常惨痛。3.2 显存不足时的标准操作流程实训中训练模型最常见的一个问题就是CUDA Out Of Memory。我也是在显存崩溃边缘反复横跳之后才总结出一套固定的处理顺序减小Batch Size最直接有效但如果Batch Size太小会导致BatchNorm统计不稳定降低输入分辨率在目标检测和分割任务里收益非常明显不过要配合调整锚框或评估尺寸开启混合精度PyTorch里用torch.cuda.amp显存能省差不多一半训练速度通常也会提升使用梯度累积模拟更大的Batch Size缓解小batch带来的BN抖动。scaler torch.cuda.amp.GradScaler() for batch_idx, (images, targets) in enumerate(train_loader): with torch.cuda.amp.autocast(): loss_dict model(images, targets) loss sum(loss_dict.values()) scaler.scale(loss).backward() if (batch_idx 1) % accumulation_steps 0: scaler.step(optimizer) scaler.update() optimizer.zero_grad()这个流程能覆盖90%的显存不足场景。如果还是不够那就得考虑是否真的需要这么大的模型或者把输入图改成可变的尺度策略。3.3 训练监控与实验记录在云端训练最怕的就是训练到一半发现Loss曲线异常但日志没打出来之前的算力全白费了。所以我的习惯是每一轮训练都打印完整的关键指标包括当前epoch、Loss、learning rate、显存占用、验证集指标并且定期保存最新的checkpoint。平台一般会提供日志查看功能我倾向于在训练脚本里使用Python标准库logging或者直接print带时间戳的信息方便在任务日志里快速定位问题。实验记录方面我强烈建议在项目目录里建一个experiments.md每次跑实验前先写一行这次改了什么参数、目的是什么、预期结果是什么。跑完之后再写一行实际结果是多少、和预期有什么差异、可能的原因。别高估自己的记性云端任务一多单靠文件名区分实验基本不可能。4. 模型训练环节的关键参数和翻车现场4.1 模型选型应该由数据量决定很多新手会在实训开始就上各种大模型觉得模型越大越准。但在极市平台上算力有限、训练时间有限模型规模必须和数据量匹配。我的经验是拿一个简单的原则来定训练集如果只有几千张图就优先考虑轻量级网络如果数据量达到几万甚至几十万再尝试用更深的backbone。以分类任务为例数据量几千的时候ResNet18或ResNet34已经能交出很不错的结果强行上ResNet152反而容易过拟合训练时间还翻好几倍。目标检测任务里如果项目对推理速度有要求YOLO系列是稳妥的选择如果更看重精度并且能容忍推理时间略长Faster R-CNN系列配合一个性能强一点的backbone会更合适。选好模型后优先加载在ImageNet上预训练好的权重。这个操作在计算机视觉任务里几乎是必做的因为预训练模型已经学到了大量底层视觉特征你只需要微调高层的任务相关部分收敛速度会快非常多。4.2 学习率与优化器最容易被忽视的杠杆实训中最常见的训练问题不是模型结构不对而是学习率策略不合理。学习率设太大Loss曲线直接飞掉设太小模型收敛慢训练时间不够用。我常用的基础配置是这样的参数项我的常用配置理由优化器AdamW或SGDmomentumSGDmomentum泛化往往更好AdamW更适合Transformers类结构初始学习率0.001AdamW或0.01SGD以Batch Size 64为基准Batch增大时学习率线性放大学习率调度Cosine Annealing后期自动降低学习率省去手动调衰减步长Warmup前5个epoch线性warmup避免训练初期Loss剧烈震荡EMA指数移动平均对最终指标有稳定提升尤其是检测和分割任务刚开始的时候如果Loss一直不降先看一眼当前学习率是不是太小以及模型是否加载了预训练权重。很多训练卡住的问题都是出在优化器配置上而不是网络结构上。EMA这个技巧容易被忽略实现起来却很简单在训练过程中维护一份模型参数的滑动平均验证和提交时用滑动平均后的权重。实践下来通常能带来0.5到1个百分点的mAP提升属于性价比极高的操作。4.3 Loss不降或者震荡我的排查顺序训练过程中如果发现Loss不降、震荡或者直接涨上去我有一套固定的排查顺序会省去大量病急乱投医的时间先看数据检查数据加载是否正常标签有没有错位数据增强是否过强导致模型无法学习再看学习率把当前学习率打印出来确认调度器没有把学习率调到过小检查Loss计算不同任务的Loss权重是否失衡比如检测里分类Loss和回归Loss差距过大检查梯度在损失函数之后调用torch.autograd.grad查看梯度是否存在NaN或全部为0用小数据过拟合测试只用16张图跑几十个epoch如果Loss能降到很低、训练acc能到100%说明代码链路没问题问题出在训练策略或数据上。第5步是我最推荐的做法。很多看起来玄乎的训练问题用小数据集一测试就能水落石出如果小数据都不能过拟合那是模型或者数据处理有Bug如果能过拟合但大训练集上效果差那就是正则化、学习率或数据分布的问题。5. 评测通过不等于万无一失部署提交才是真正考验5.1 本地验证结果和平台评测结果对不上先查这些地方在本地验证集上mAP已经很高了提交到平台评测分数却低得离谱这个现象在实训里太常见了。我的排查顺序基本是固定的检查图像缩放方式训练时如果用了letterbox推理时是否用了同一种方式很多评测环境会把图片直接缩放到固定尺寸和训练的等比缩放不一致检查通道顺序OpenCV读入是BGRPyTorch训练时通常转成RGB推理脚本是否漏了这一步检查归一化参数是否使用了和训练一致的mean和std检查前后处理模型输出是原始logits评测脚本可能期望的是概率值或者检测模型需要你提前过滤掉低置信度框。其中图像缩放方式是最隐蔽的坑。很多人在训练时用了自定义的数据预处理但推理脚本里想当然地用了最普通的resize导致目标框全部看起来“差不多但不对”。要验证这个问题最简单的办法是找一张训练集图片把预处理后的结果可视化出来和推理时程序里实际看到的输入图做个对比。5.2 推理脚本的输入输出契约极市平台的评测一般会要求你提交一个推理脚本平台自动对测试集图片逐张调用。这个环节有两个常见翻车点一个是依赖了训练环境里存在的额外库提交后评测环境没装另一个是脚本里留了硬编码路径评测机器上根本没有这个路径。我的做法是尽可能让推理脚本只依赖标准库和明确声明过的第三方库并把所有路径都改成相对路径或环境变量。另外推理脚本不要假设输入图片已经做过和训练一样的预处理。最稳妥的方式是把预处理逻辑完整复制到推理脚本里并在开头用一张已知图片做断言验证输出尺寸和值范围符合预期。还可以准备一个prepare.py脚本把每个环境下的依赖打包成固定版本在README里写清楚。环境一致性在云端实训里同样重要你不是在一台固定的机器上开发评测环境的差异随时可能让你的代码崩掉。5.3 模型融合与TTA的收益评估当单个模型的精度已经稳定想继续涨点我一般会考虑模型融合和测试时增强TTA。但这两种手段都是有代价的实训中尤其要评估清楚。TTA的原理很简单推理时对同一张图做多个变换水平翻转、多尺度缩放把多次预测结果平均后再输出。它的收益通常在小目标检测和分割任务上更明显代价是推理时间成倍增加。如果平台对单个测试图有推理时间限制TTA可能直接让脚本超时。模型融合我这次也试了用不同种子或不同backbone训练两个模型在检测框层面做NMS合并或者对置信度做平均。结果是在验证集上确实涨了大概1个点mAP但训练成本和推理成本都增加了接近一倍。如果离目标分数只差一点点模型融合是合理选择如果分数差距还很大先回去优化单个模型更实在。6. 实训结束后的经验沉淀与迁移6.1 代码组织与实验管理实训结束后我重新整理了一次整个项目代码才意识到一个好用的代码结构能省掉多少重复劳动。现在我一般会按这样的目录组织project/ ├── configs/ # 所有实验对应的配置文件 ├── data/ # 数据处理和Dataset定义 ├── models/ # 网络结构定义 ├── train.py # 训练脚本 ├── infer.py # 推理脚本 ├── tools/ # 数据可视化、格式转换、评测辅助脚本 ├── experiments.md # 实验记录 └── requirements.txt # 依赖列表配置和代码分离是我特别推荐的做法。每次实验只需要改配置文件不用在训练脚本里翻来覆去找参数。实验记录里把每个实验的配置项、Loss曲线和最终指标粘贴进去后续做任何消融对比都能直接翻历史。6.2 这次实训留下的几个习惯在极市平台跑完一个完整实训我养成了几个平时在本地开发时不会刻意坚持的习惯每个实验固定随机种子确保可复现训练脚本里每次保存checkpoint时同时保存优化器状态和当前epoch方便断点续训任何预处理逻辑都抽成函数并且训练和推理共用同一份代码而不是各写一份改动任何数据加载逻辑后先用画图的方式可视化一批样本确保输入没问题评测之前先用一条命令跑通全流程确认从原始图片到最终提交文件一气呵成。这些习惯后来带进了我的日常工作里确实帮我避免了很多莫名其妙的返工。6.3 这些经验在真实项目中的延伸极市平台实训虽然带有任务性质但整个流程其实非常接近真实项目先理解需求再处理数据然后训练模型最后交付一个能在规定环境里稳定运行的推理服务。平台化的训练方式也让我提前适应了代码不在自己电脑上运行、需要依靠日志排查问题的开发模式。如果你之后要去企业中做视觉算法相关的工作大概率也会遇到类似的平台化流程。哪怕不是在极市平台上换成任何私有化AI开发平台底层的思路都是相通的先读文档确认契约再处理好数据接着做训练和评估最后把推理脚本整理成可以交付的状态。我个人的体会是实训过程中真正拉开差距的往往不是谁的模型结构更炫而是谁更早把数据流程捋清楚、谁更早跑通一个可评估的baseline、谁在遇到分数不对时能按逻辑一步步排查。能把这些基本功练扎实哪怕最后的榜单名次不是最靠前从实训里带走的经验也完全值回票价。
返回列表