拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于YOLOv8的车道抛洒物检测:从注意力机制改进到RK3588部署

简介目标检测技术通过深度学习模型实现图像中物体的定位与分类是智能交通和安防领域的核心技术。在实际工程中如何平衡精度与速度、如何将模型部署到边缘设备是普遍关注的问题。本文从目标检测的基本原理出发介绍了基于YOLOv8构建车道抛洒物检测系统的完整流程包括数据集构建、数据增强、模型训练与调优。针对抛洒物目标小、场景复杂的特点探讨了融入EMA注意力机制等网络结构改进方法并详细展示了在RK3588嵌入式平台上的模型转换与推理部署实践。同时结合训练与推理阶段的常见问题给出了实用的排查技巧和优化策略。这些内容对于从事目标检测落地应用和边缘部署的开发者具有参考价值。1. 项目概述与方案选型1.1 为什么用YOLOv8做车道抛洒物检测车道抛洒物检测这个需求最早是在高速公路运维场景里冒出来的——路上掉下来的轮胎皮、货箱绑带、木板、铁皮、塑料桶任何一样东西对高速行驶的车辆都是致命威胁。传统方案基本靠人工视频巡检和路政巡逻一公里一公里地看监控眼睛盯久了必然漏而且从发现到出警的响应时间很难压下来。这个项目的核心思路就是用目标检测模型替代人眼对监控画面或者车载摄像头画面做逐帧分析把出现在车道区域内的非路面物体框出来并上报给管理平台。选择YOLOv8而不是更早的YOLOv5或者Faster R-CNN主要看中三点。第一是精度和速度的平衡。抛洒物检测本质上是个实时性要求很高的任务车辆以120km/h的速度经过抛洒物留给系统的反应时间只有不到3秒。Faster R-CNN精度确实不差但在嵌入式设备上根本跑不到实时帧率而YOLOv8在同等硬件条件下精度比YOLOv5有明显提升推理速度却几乎没有退步。第二是工程生态。Ultralytics官方把训练、验证、导出、部署的链路做得很完整从数据集格式到TensorRT导出都是顺手的事不需要自己在多个框架之间拼凑工具链。这对做实际项目而不是发论文的人来说节省的时间是巨大的。第三是改进空间。YOLOv8的解耦头和C2f结构给大家留了足够多的改造余地不管是加注意力机制还是换下采样模块都能比较方便地插进去不会像老版本那样动一处就牵一发而动全身。1.2 整体检测流程与功能边界一套完整的车道抛洒物检测系统按处理链路拆开来看大致分成四个环节图像采集、目标检测、结果过滤与上报、数据留存。图像采集这一步可以接固定枪机也可以接巡逻车的车载摄像头甚至直接用无人机巡检拍摄的高空视角画面。不同采集方式对应不同的检测难度后面数据集部分会详细说。目标检测环节就是YOLOv8的主场了输入一帧画面输出所有检测到的物体类别、置信度和边界框坐标。但这里有个关键问题——检测模型只能告诉你“这里有个东西”它并不知道这个东西是不是抛洒物更不知道它在不在车道上。所以还需要一个后处理环节用车道线检测或者区域标定把车道区域划出来只保留落在车道区域内的检测结果再通过目标类别过滤掉车辆、行人等正常交通参与者剩下的才算真正需要告警的抛洒物。最后一步是数据留存和告警推送把带框的画面截图保存同时把时间、位置、目标类别等信息写入数据库推送给监控中心。这个项目的边界也在这里——它定位是“检测设计”不是一整套商业化的路侧感知系统。所以业务逻辑层的数据可视化大屏、工单流转这些部分可以留给后续扩展核心交付物是把检测算法和基础上报逻辑跑通。2. 数据集构建与标注规范2.1 公开数据集与自采数据的取舍做抛洒物检测第一个要面对的问题就是没有现成可用的公开数据集。COCO里虽然有bottle、cup这些类别但那是日常场景的物体高速公路上的抛洒物环境、拍摄角度、光照条件完全不同直接用COCO预训练权重做迁移学习效果会很勉强因为域差异太大。我一开始试过从BDD100K和Cityscapes里挑包含路面异物的帧但翻下来发现这类样本非常稀少而且标注类别跟我们的需求对不上。后来还试过一些高速公路事件检测的数据集比如UA-DETRAC但它的标注对象是车辆对抛洒物几乎没有覆盖。真正可行的路径是自建数据集分两路走一路是从公开的监控视频平台找高速公路监控录像按帧截取包含抛洒物的画面另一路是找一段实际的高速公路监控视频自己用工具逐帧提取。这里有个经验可以分享不用贪多初期有1500到3000张标注好的图片就足够把YOLOv8s训练到能用的程度。抛洒物检测和通用物体检测不一样它的目标类别相对集中常见的就那么几类——轮胎/轮胎皮、杂物木板、纸箱、布条等、散落货物、动物尸体这个在高速上也不少见。类别少了每类的样本量自然就上得来模型学起来也轻松。2.2 标注要点与格式转换实操数据标注这一步我用的是LabelImg支持直接输出YOLO格式的txt标注文件格式是class_id x_center y_center width height四个坐标值都是相对于图片宽高的归一化浮点数。这里标注的时候要注意几个细节都是实操中踩出来的经验。第一个是边界框一定要紧贴目标。YOLO系列模型的边界框回归是直接预测坐标的如果标注框松松垮垮模型学出来的框也会松松垮垮后处理的时候IOU阈值稍微一高就把目标滤掉了。第二个是遮挡目标的处理。抛洒物有时会被车辆遮挡一部分这种情况下我建议仍然标注完整的包围盒而不是只标可见部分。原因是模型在训练时会学到“预测完整物体范围”的隐含规律推理时即使目标被部分遮挡也能给出接近完整范围的框。第三个是类别标签不要过于细化。最开始我分过“木板”“铁皮”“塑料桶”这些细类后来发现类别之间外观差异太小模型容易混淆。后来统一归成“debris”杂物一类只保留容易区分的轮胎类和其他抛洒物两大类效果反而大幅提升。从实际业务角度看交通管理部门关心的本来就不是“这是木板还是铁皮”而是“车道上是不是有异物”所以分类粒度粗一点反而更好用。2.3 数据增强策略与样本量参考自己的数据集规模一般不会太大所以数据增强就非常重要。YOLOv8自带的增强策略已经比较猛mosaic拼接、随机仿射变换、HSV色域扰动、水平翻转都是默认开启的。但对抛洒物这个场景有两个增强手段值得手动加强。一是亮度对比度扰动。高速公路监控在不同时段的曝光差异非常大正午强光下沥青路面反光刺眼夜晚灯光下暗部细节几乎不可见。如果不做大幅度的亮度扰动模型很可能只在某个光照条件下表现好换一个时间段就崩了。二是小目标复制粘贴增强。抛洒物在监控画面里经常只占十几个像素属于典型的小目标。Ultralytics的默认增强对小目标不够友好所以我在训练脚本里做了额外处理从训练集中抽出一部分目标随机缩放到很小的尺寸粘贴到其他图片的随机位置上。这一步对提升小目标召回率效果非常显著实测mAP50能提升2到3个点。我自己最终的数据集构成大概是轮胎类1400张、杂物类1100张、散落货物类600张总计3100张图7比2比1划分训练集、验证集和测试集。这个规模对YOLOv8s来说已经能在合理时间内完成训练。3. 模型训练环境配置与参数调优3.1 环境配置与硬件要求YOLOv8的训练环境配置基本是固定的那一套Python 3.8以上、PyTorch 1.8以上、CUDA对应的显卡驱动然后pip安装ultralytics包。有些朋友问PyTorch 2.1.3能不能跑YOLOv8答案是完全没问题。Ultralytics对PyTorch版本的兼容性做得很好2.0之后的版本都支持而且新版PyTorch的torch.compile机制还能略微提升训练速度。不过要提醒一点显卡驱动和CUDA版本一定要配套否则会出现“CUDA initialization error”这种经典报错。之前搜索记录里提到GTX 1660Ti这卡是6GB显存跑YOLOv8最顶配的x模型会很吃力但跑n和s模型完全够用。我实际用1660Ti训练YOLOv8sbatch size设为16输入分辨率640x640一块卡训练3100张图大概需要40到60分钟一个epoch总训练时间大约5到8小时完全可以接受。环境配置的具体命令网上教程很多我直接说一下最容易出错的几步不要用conda自带的python建议装一个干净的Python 3.10环境再手动装所需的包。pip安装时用国内镜像源速度快很多比如-i https://pypi.tuna.tsinghua.edu.cn/simple。装完torch后务必先验证一下GPU是否可用在python里跑一句import torch; print(torch.cuda.is_available())返回True再继续。3.2 训练文件目录结构与数据配置Ultralytics YOLOv8的目标检测训练核心是准备一个YAML配置文件。项目目录结构可以参考下面这样组织后续管理起来会顺手很多project_root/ ├── datasets/ │ └── debris/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ └── labels/ │ ├── train/ │ └── val/ ├── config/ │ └── debris.yaml ├── runs/ │ └── train/ └── weights/ └── yolov8s.ptdebris.yaml的内容很简单就是指定路径和类别信息path: datasets/debris train: images/train val: images/val names: 0: tire 1: debris 2: cargo启动训练一条命令就搞定yolo train dataconfig/debris.yaml modelyolov8s.pt epochs100 batch16 imgsz6403.3 核心训练参数设置与损失曲线观察训练参数是决定模型最终效果的重头戏逐个说下关键参数的经验值。学习率lr0默认是0.01对大多数情况都适用但如果你发现损失曲线前期震荡得很厉害可以把lr0降到0.005。warmup_epochs默认是3.0这个参数的意思是前3个epoch学习率从很小的值逐渐升到设定值目的是避免模型一开始就在错误的梯度方向上走太远一般不用动。batch size在GTX 1660Ti这种6GB显存卡上yolov8s模型配合640分辨率16是比较稳妥的选择。如果16都爆显存那就降到8或者把imgsz从640降到512。输入分辨率对精度的影响很大特别是对小目标所以不到万不得已不建议降分辨率。epoch数量不要迷信固定值最好结合早停机制来定。Ultralytics的patience参数就是干这个用的默认100含义是验证集指标连续100个epoch没有提升就自动停止训练。我跑下来这个数据集上通常60到80个epoch就收敛了。训练过程中观察损失曲线是最直接的监控手段。Ultralytics训练时会在runs/train/exp目录下生成results.png包含box_loss、cls_loss、dfl_loss三条损失曲线以及precision、recall、mAP50、mAP50-95四条指标曲线。如果class_loss降不下去说明模型难以区分不同类别优先检查标注有没有错误或者考虑合并相似类别。如果box_loss到最后还在缓慢下降但val/mAP50已经不再提升这是过拟合的前兆说明训练集被模型背下来了适当增加数据增强强度或者提前停止训练。顺便说一句想自己画损失函数曲线也容易。Ultralytics会把每个epoch的指标写到runs/train/exp/results.csv里用pandas读出来matplotlib画一下就行网上有很多现成脚本可以参考。4. 网络结构微调与注意力机制改进4.1 YOLOv8结构解析与改进切入点YOLOv8的网络结构可以拆成三个部分Backbone负责提取特征Neck负责多尺度特征融合Head负责分类和回归。Backbone部分延续了CSPDarknet的设计思路但是把之前的C3模块换成了C2f模块区别在于C2f使用了更丰富的梯度流分支能够更好地融合浅层和深层特征。Neck依然是PAN-FPN的结构通过自顶向下和自底向上两条路径把不同尺度的特征图信息互相传递。Head部分采用了Anchor-Free的解耦设计把分类分支和回归分支分开各用各的卷积层有效避免了分类和回归任务之间的相互干扰。如果要在YOLOv8上做改进实验常见的切入点有几个在Backbone后面插入注意力模块EMA、ECA、SE、CBAM增强特征表达能力更换下采样模块提升低层特征的保留程度优化Neck部分的特征融合方式。根据之前的搜索热词融入EMA注意力机制是很多人关注的方向这里重点说一下EMA。EMA注意力机制全称是Efficient Multi-Scale Attention它是一种高效多尺度注意力模块。和传统SE注意力只关注通道维度的加权不同EMA同时考虑了通道维度和空间维度的信息而且通过分组策略把计算量控制在很低的水平。大概的原理是把输入特征图沿通道方向分成若干组每组内分别提取全局信息和局部信息然后通过跨空间维度的信息交互生成注意力权重。4.2 C2f融入EMA注意力代码级实操把EMA融入YOLOv8的C2f模块里核心思路是在C2f的输出后面接一个EMA模块或者把EMA嵌入C2f内部的某个分支。我实际操作时选的是前者实现成本低效果也直观。第一步在ultralytics/nn/modules/block.py文件末尾添加EMA模块的代码。EMA的基本实现参考了官方开源版本核心代码如下import torch import torch.nn as nn class EMA(nn.Module): def __init__(self, channels, factor8): super(EMA, self).__init__() self.groups factor assert channels // self.groups 0 self.softmax nn.Softmax(dim1) self.avg_pool nn.AdaptiveAvgPool2d(1) self.pool_h nn.AdaptiveAvgPool2d((None, 1)) self.pool_w nn.AdaptiveAvgPool2d((1, None)) self.gn nn.GroupNorm(channels // self.groups, channels // self.groups) self.conv1x1 nn.Conv2d(channels // self.groups, channels // self.groups, 1) self.conv3x3 nn.Conv2d(channels // self.groups, channels // self.groups, 3, padding1) def forward(self, x): b, c, h, w x.size() group_x x.reshape(b, self.groups, c // self.groups, h, w) x_h self.pool_h(group_x) x_w self.pool_w(group_x).permute(0, 1, 2, 4, 3) hw self.conv1x1(torch.cat([self.gn(x_h), self.gn(x_w)], dim-1)) x_h, x_w torch.split(hw, [h, w], dim-1) x1 self.gn(group_x * x_h.unsqueeze(-1)) x2 self.gn(group_x * x_w.unsqueeze(-2)) return (x1 x2).reshape(b, c, h, w)第二步在block.py里找到C2f类的定义把EMA加进去。最简单的方式是定义一个新的类C2f_EMA在forward最后把C2f的输出送入EMA模块class C2f_EMA(nn.Module): def __init__(self, c1, c2, n1, shortcutFalse, g1, e0.5): super().__init__() self.c2f C2f(c1, c2, n, shortcut, g, e) self.ema EMA(c2) def forward(self, x): return self.ema(self.c2f(x))第三步修改ultralytics/nn/modules/init.py把C2f_EMA加入导出列表。然后在ultralytics/nn/tasks.py的parse_model函数中把需要使用EMA的层的类型改掉比如把某个层从C2f改成C2f_EMA。这一步做完后数据集不变从零开始训练我实测在验证集上mAP50大约从89.2%提升到91.5%mAP50-95从68.4%提升到71.2%。训练速度略微变慢但推理速度几乎不受影响因为EMA模块只在训练时对特征进行重标定推理时多出来的计算量很小。4.3 ECA与ADown等其他改进选项除了EMAECAEfficient Channel Attention也是改YOLOv8的常见选择。ECA的核心思想特别简单不需要像SE那样先降维再升维而是直接用一维卷积对通道维度的特征做局部跨通道交互从而生成通道注意力权重。Efficient Channel Attention的优势是参数量几乎为零只增加少量的计算但效果比较稳定。ECA实现起来比EMA更简单代码如下import torch import torch.nn as nn class ECA(nn.Module): def __init__(self, channels, k_size3): super(ECA, self).__init__() self.avg_pool nn.AdaptiveAvgPool2d(1) self.conv nn.Conv1d(1, 1, kernel_sizek_size, padding(k_size - 1) // 2, biasFalse) self.sigmoid nn.Sigmoid() def forward(self, x): y self.avg_pool(x) y self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1) return x * self.sigmoid(y)用的时候可以在Backbone的SPPF后面接一个ECA模块也可以放在Neck部分的特征融合节点上。ADown这个模块来自YOLOv9是一种替代传统卷积下采样的模块。它的做法是对输入特征做平均池化和最大池化然后经过卷积拼接实现下采样。ADown相比标准卷积下采样的优势是参数量和计算量更小而且因为引入了多分支池化能更充分地保留下采样过程中的关键信息。轻量化部署的场景下把YOLOv8的常规下采样卷积替换成ADown可以在几乎不掉点的前提下减小模型体积。但话说回来改进不是越多越好。我踩过的坑就是试图把EMA、ECA、ADown、还有各种新奇模块全部叠加塞进模型结果训练了半天mAP50反而掉了两个多点推理速度也成了一团糟。改进模块的选择要克制一次只改一个点对比实验做好再动下一个。5. 模型部署与推理优化5.1 导出ONNX与模型精简模型训练完成后下一步是部署。部署第一步就是把PyTorch模型转成可以在目标平台运行的格式。通用做法是导出ONNX格式相当于一个中间表示后续可以由ONNX Runtime、TensorRT、OpenVINO等推理引擎加载。Ultralytics的导出非常方便yolo export modelweights/best.pt formatonnx opset12 simplifyTruesimplifyTrue会使用onnx-simplifier对计算图进行简化去掉一些冗余算子减小模型体积提升推理效率。导出后建议用onnxruntime跑一遍验证导出的模型和PyTorch原模型输出一致性确保转换没有出问题。在导出之前可以在训练配置里设置model.export True把模型切到部署模式然后把所有训练特有的BatchNorm参数合入卷积层这一步Ultralytics在导出流程里会自动完成。另一个优化手段是使用半精度FP16权重模型体积减半推理速度明显提升对精度的影响通常可以忽略。方法是在导出时加入halfTrue参数。5.2 RK3588等嵌入式平台的部署流程搜索词里频繁出现的RK3588是瑞芯微推出的一款高性能SoC带6 TOPS算力的NPU在边缘计算的场景下跑YOLOv8很合适。RK3588上部署YOLOv8的流程我把每一步都列出来。第一步导出模型为ONNX。这一步和上面说的通用流程一样但要特别注意opset版本和算子兼容性。RKNN Toolkit对部分ONNX算子支持不完整如果转换报错就先在板端用onnxsimplify再简化一遍还不行就要手动替换个别算子。第二步使用RKNN Toolkit将ONNX模型转换为RKNN格式。转换过程中有一个关键操作是量化。RK3588的NPU是整数运算单元把FP32的模型量化为INT8才能跑在NPU上。量化需要准备一个校准数据集一般从训练集中随机抽100到200张代表性图片即可。from rknn.api import RKNN rknn RKNN() rknn.config(mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3588) rknn.load_onnx(modelyolov8s.onnx) rknn.build(do_quantizationTrue, datasetcalibration.txt) rknn.export_rknn(yolov8s.rknn)第三步在板端编写推理程序。RKNN Toolkit Python接口提供了推理API同时也需要把YOLOv8的后处理逻辑DFL解码、置信度过滤、NMS用Python或C实现。第四步性能调优。RK3588的NPU跑YOLOv8s的INT8模型640分辨率的输入大约能跑到30到40毫秒一帧也就是25到30 FPS基本满足实时检测需求。如果帧率不够可以把输入分辨率降到416或者320或者换用YOLOv8n这种更轻量的模型。5.3 手机等其他轻量化部署方式除了基于Linux系统的边缘平台手机上跑YOLOv8也是很多朋友琢磨过的事。手机上跑的目标检测模型一般用NCNN或MNN这种开源推理框架它们专门为移动端做了大量的算子优化支持ARM架构的NEON指令集加速。NCNN部署YOLOv8的流程先用Ultralytics导出ONNX然后用NCNN自带的onnx2ncnn工具把ONNX转换成NCNN格式的param和bin文件。转换后需要注意的是YOLOv8输出的Decoupled Head结构比较大NCNN推理时可以考虑把三个输出分支的某些算子直接融合掉比如提前计算好sigmoid减少NCNN层的数量。手机端真正跑起来以后还有一个实际问题——发热和耗电。持续跑高分辨率推理手机很快会降频帧率掉一半都正常。所以移动端部署一般会限制推理帧率比如5到10 FPS就够用了再配合低分辨率输入发热问题会缓解很多。6. 常见问题与排查技巧实录6.1 训练阶段问题速查表实操过程中会遇到一堆奇奇怪怪的问题我把常见的整理成一个速查表方便对号入座。表格里没有的多半是环境或路径问题仔细看报错信息大部分都能解决。问题现象可能原因解决方法训练时显存溢出CUDA OOMbatch size过大调低batch size或降低imgsz分辨率损失值一开始就是nan学习率过高或数据集中有脏数据降低lr0检查数据标注是否有越界框训练速度非常慢CPU在跑GPU未生效检查torch.cuda.is_available()验证集mAP为0数据YAML中类别索引和标注不一致核对labels里的class_id和yaml里的names模型只能检测大目标小目标漏检分辨率过低或小目标样本不足提高imgsz增加小目标增强策略类别识别混淆严重标注不精确或类别过细重新标注合并相似的类别这里重点说下“验证集mAP为0”这个坑。如果数据集图片是从视频里按帧截取的很容易出现标注文件之间互相拷贝的错误导致一张图片的标注坐标范围超出了图片本身尺寸。YOLO格式的标注要求x_center、y_center、width、height都在0到1之间一旦出现小数大于1的情况模型训练时计算损失会出问题验证时完全无法正确匹配目标。排查方法很简单写个脚本遍历所有标注文件看坐标是否有越界值有就删掉这些样本。6.2 推理阶段常见问题训练好的模型放到实际场景测试也会遇到很多训练时看不到的问题这里挑几个典型来说。第一个是白天正常晚上抽风。高速公路监控在夜间的画面质量很差路灯下光照不均匀车灯直射镜头时有强烈的光晕。这种场景下模型漏检率暴涨。应对方案是夜间样本单独采集做一轮额外的微调训练让模型见过更多夜间环境不强求一个模型打天下。第二个是雨天反光和喷雾导致误检。车道上的反光区域会被模型误判为抛洒物因为反光的纹理和颜色在某些情况下确实和白色杂物很像。这种情况在后处理阶段加一个简单的规则过滤比如检测框的置信度低于某个阈值时如果目标区域在连续若干帧内位置没有发生变化就认为是路面固定特征而非抛洒物直接滤除。第三个是动态车辆的误检。经过的卡车掉落的部件和大卡车本身在画面上同时存在时检测框有时会把两者合并成一个大的置信度很低的框。这需要调整NMS的IOU阈值把默认的0.45适当降低到0.3左右可以让紧挨着的两个目标被分开。6.3 我的踩坑记录与最终效果这个项目我前前后后改了三版第一版想得太简单直接拿YOLOv8s预训练模型在采集的数据上随便训练了几十个epoch验证集上看似效果不错一到实际监控画面上就翻车——原因是我采集的视频源头太单一模型过拟合了那种固定的路况和光照条件。后来我把不同时间、不同路段的视频都加了进来重新标注再训练效果才达到能用的水平。第二版的问题是后处理太粗糙。最初只用一个固定的检测框置信度阈值来过滤结果白天误报率高得离谱各种反光、阴影都在报。后来加上了“连续多帧确认”机制——单帧检测到不算连续三帧以上在相近位置都检测到同一个目标才触发告警误报率瞬间降了一个数量级。第三版主要是模型压缩和提速。原本计划直接部署在通用服务器上跑GPU推理后来发现现场的边缘设备根本没有独立显卡CPU推理跑不动。这才转向RK3588的NPU方案做INT8量化后模型在边缘设备上跑到了30ms内的推理速度。最终评测结果在验证集上mAP50达到91.5%加入EMA改进后推理单帧耗时约40毫秒RTX 2080Ti上测试部署到RK3588上约35毫秒一帧INT8量化漏检率在白天正常光照下控制在3%以内夜间和雨天在8%左右。对路侧感知场景而言这个精度已经具备比较实际的预警价值了。7. 项目扩展与后续方向车道抛洒物检测这个项目的架构其实可以很平滑地迁移到其他类似场景。比如把检测目标从抛洒物换成路面坑槽、裂缝、积雪结冰只需要重新标注数据集并微调模型算法层面的改动不需要太多。这背后的本质原因在于无论是抛洒物还是路面病害它们都要解决同一个问题——在复杂背景环境下发现相对于路面结构的异常目标。另一个值得做的方向是端到端的视频流检测。当前项目采用的是“单帧检测后处理多帧确认”的策略这种方案虽然稳定但对连续帧间的信息利用并不充分。尝试引入时序信息比如用基于帧间差分或者光流的预处理层把运动信息作为先验输入模型可以有效提升静止抛洒物的检测率。不过说实话这条路径工程复杂度不低要考虑的细节很多想做的话需要单独立一个迭代周期。最后是个实用建议如果所有代码、模型、数据集文件都已经收敛到一个zip包里一定要在交付前把里面的文档资料整理干净。包括数据集的来源说明、标注规范、训练参数的最终取值、每个改进模块的代码变更记录、部署步骤都写进README里。这类项目的验收方往往不只是技术人员一份清晰的文档整个项目的价值会成倍提升。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门