ARTICLE DETAIL

资讯详情

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

驾驶员行为检测数据集与YOLO模型训练部署全流程实战

驾驶员行为检测数据集与YOLO模型训练部署全流程实战 1. 驾驶员行为检测数据集到底解决什么问题1.1 从一个真实需求说起去年帮一个做商用车队管理的朋友看项目他们想在营运车辆上装一套驾驶员状态监控核心诉求很朴素司机抽烟、打电话、双手离开方向盘、打哈欠这些动作能不能实时识别出来并报警。他们一开始想找现成的商用方案问了一圈发现要么贵得离谱要么接口封闭没法二次开发最后决定自己搞。自己搞的第一步就卡住了——没有数据。这就是驾驶员行为检测数据集存在的意义。市面上公开的通用目标检测数据集比如COCO、VOC里面根本没有抽烟打电话喝水这些类别你拿它们训练出来的模型遇到驾驶员场景直接抓瞎。而专门针对驾驶舱场景标注的数据集要么规模太小要么类别定义跟实际需求对不上要么标注质量堪忧。22600张这个量级在驾驶员行为检测这个细分领域里已经算是能撑起一个可用模型的规模了。1.2 这个数据集里有什么从标题和常见同类数据集的构成来看这个数据集的核心内容大致是这样的图像来源主要是驾驶舱内固定视角的摄像头拍摄包含白天、夜间、不同光照条件、不同驾驶员性别、衣着、姿态各异的场景。标注格式是YOLO格式也就是每张图片对应一个txt文件每行是类别编号 中心x 中心y 宽度 高度坐标都归一化到0到1之间。类别方面驾驶员行为检测通常覆盖这几类正常驾驶、打电话左手/右手、抽烟、喝水/吃东西、双手离开方向盘、低头看手机或调设备、打哈欠/疲劳、转头张望。具体类别数以数据集实际标注为准但一般不会少于6类。22600张的规模如果按8类算平均每类接近3000张这个分布对于训练一个YOLO模型来说是够用的当然实际分布可能不均衡这个后面会讲怎么处理。1.3 谁适合用这个数据集三类人最适合第一类是做车载DMS驾驶员监控系统产品原型的团队需要快速验证算法可行性第二类是高校做智能驾驶、人机交互方向的研究生需要数据集发论文或做毕业设计第三类是想入门目标检测的开发者拿一个场景明确、类别清晰的数据集练手比在COCO上折腾要容易出成果。如果你属于这三类中的任何一类这个数据集值得花时间研究。注意使用任何数据集之前先确认其授权协议。公开数据集通常有CC、MIT等不同许可商用和非商用限制不一样别等产品上线了才发现授权有问题。2. 数据集结构与YOLO格式深度拆解2.1 目录组织与文件对应关系一个规范的YOLO格式数据集目录结构通常长这样dataset/ ├── images/ │ ├── train/ │ │ ├── 000001.jpg │ │ └── ... │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ │ ├── 000001.txt │ │ └── ... │ ├── val/ │ └── test/ └── data.yamlimages和labels下的文件名必须一一对应只是扩展名不同。这一点看起来简单但实际拿到数据集后第一件事就是检查对应关系我见过太多人因为图片和标签对不上训练了半天loss不降最后发现是文件名差了一个下划线。data.yaml是YOLO训练的核心配置文件内容大致如下path: /path/to/dataset train: images/train val: images/val test: images/test nc: 8 names: [normal, phone, smoke, drink, hands_off, look_down, yawn, turn_head]nc是类别数names是类别名称列表顺序必须和标注文件里的类别编号严格对应。编号0对应names里第一个编号1对应第二个以此类推。这个顺序搞错了模型训练出来会把抽烟识别成打电话而且你从loss曲线上完全看不出来问题。2.2 标注格式的数学含义YOLO的标注格式是归一化的中心点坐标加宽高具体计算方式是中心x (标注框左上角x 标注框右下角x) / 2 / 图片宽度中心y (标注框左上角y 标注框右下角y) / 2 / 图片高度宽度 (右下角x - 左上角x) / 图片宽度高度 (右下角y - 左上角y) / 图片高度举个例子一张1920x1080的图标注框从(960, 540)到(1440, 810)那么中心x (9601440)/2/1920 0.625中心y (540810)/2/1080 0.625宽度 (1440-960)/1920 0.25高度 (810-540)/1080 0.25所以标注文件里这一行就是0 0.625 0.625 0.25 0.25假设类别是0。为什么要归一化因为YOLO训练时会把输入图片统一缩放到固定尺寸比如640x640如果标注用绝对坐标缩放后就得重新计算归一化之后无论怎么缩放相对位置关系不变省去了大量坐标变换的麻烦。这是YOLO设计上很聪明的一个点。2.3 数据分布检查别急着开训拿到数据集后先做三件事顺序不能乱。第一统计每个类别的样本数量。写个简单的Python脚本遍历labels目录下所有txt文件统计每个类别编号出现的次数。如果发现某个类别只有几十张而其他类别有几千张这就是典型的长尾分布直接训练会导致模型对少数类识别极差。第二检查图片尺寸分布。驾驶员行为检测数据集的图片可能来自不同摄像头分辨率不统一。虽然YOLO训练时会统一resize但如果原图长宽比差异太大resize后目标变形严重会影响检测精度。统计一下宽高比如果大部分在1.7到1.8之间16:9说明来源比较统一问题不大。第三可视化抽样检查标注质量。随机抽20到30张图把标注框画出来看一眼。重点看有没有漏标、错标、框得离谱的情况。我遇到过标注框把整个驾驶舱都框进去的这种脏数据不清理模型学出来的东西完全是错的。import os from collections import Counter label_dir dataset/labels/train counter Counter() for f in os.listdir(label_dir): if f.endswith(.txt): with open(os.path.join(label_dir, f)) as file: for line in file: cls int(line.split()[0]) counter[cls] 1 for cls_id, count in sorted(counter.items()): print(f类别 {cls_id}: {count} 个标注框)这段代码跑一遍数据分布一目了然。如果发现严重不均衡后面训练时就要做针对性处理。3. 从零训练一个驾驶员行为检测模型3.1 环境搭建与依赖安装训练YOLO模型环境搭建是第一步也是最容易劝退的一步。我推荐用conda建虚拟环境避免和系统Python打架。conda create -n driver_behavior python3.10 conda activate driver_behavior pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics opencv-python matplotlib pyyaml这里用的是ultralytics这个库它封装了YOLOv8及后续版本的训练、验证、推理全流程API设计得很干净比早期YOLOv5的代码可读性高不少。torch的版本要根据你的CUDA版本选cu118对应CUDA 11.8如果你装的是CUDA 12.x把index-url里的cu118改成cu121。装完之后验证一下import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))如果第一行输出True第二行显示你的显卡型号说明环境没问题。如果输出False检查CUDA驱动和torch版本是否匹配这是新手最常踩的坑。3.2 模型选型n/s/m/l/x怎么选YOLOv8提供了n、s、m、l、x五个规格参数量从300万到6800万不等。选哪个取决于你的硬件和精度要求。模型规格参数量输入640推理速度V100mAPCOCO适用场景YOLOv8n3.2M约1.5ms37.3边缘设备、实时性优先YOLOv8s11.2M约2.5ms44.9平衡型推荐首选YOLOv8m25.9M约5ms50.2精度优先服务器部署YOLOv8l43.7M约8ms52.9高精度场景YOLOv8x68.2M约12ms53.9追求极致精度驾驶员行为检测这个任务目标相对固定驾驶舱内的人体和手部动作背景变化不大不需要特别大的模型。我的经验是YOLOv8s就够用了如果部署在车机端算力有限YOLOv8n也能跑出可接受的效果。先用s跑一版baseline看mAP和实际badcase再决定要不要换更大的模型。3.3 训练参数配置与启动训练脚本本身很简单from ultralytics import YOLO model YOLO(yolov8s.pt) results model.train( datadataset/data.yaml, epochs100, imgsz640, batch16, device0, workers8, patience20, lr00.01, lrf0.01, momentum0.937, weight_decay0.0005, warmup_epochs3, augmentTrue, cacheTrue )参数逐个解释一下。epochs100是训练轮数驾驶员行为检测数据集22600张100轮通常能收敛如果loss还在降可以加到150。imgsz640是输入分辨率YOLOv8默认640如果你的图片里目标很小比如远距离拍摄可以提到1280但显存占用会翻倍。batch16是批大小根据显存调整8G显存用1612G用32不够就往下调。patience20是早停耐心值20轮验证集mAP不提升就停防止过拟合。lr00.01是初始学习率lrf0.01是最终学习率因子实际最终学习率是lr0*lrf0.0001。warmup_epochs3是预热轮数前3轮学习率从很小线性升到lr0避免训练初期震荡。cacheTrue是把图片缓存到内存22600张图如果内存够大概需要20到30G开启后训练速度能提升30%以上。内存不够就别开否则会OOM。3.4 训练过程监控与指标解读训练启动后终端会实时打印每个epoch的loss和mAP。重点看几个指标box_loss是边界框回归损失cls_loss是分类损失dfl_loss是分布焦点损失。三个loss都应该整体下降如果某个loss震荡剧烈或者不降说明对应部分有问题。比如cls_loss不降可能是类别标注有误或者类别不均衡太严重。mAP50是IoU阈值0.5时的平均精度mAP50-95是IoU从0.5到0.95每隔0.05取一个阈值再平均。驾驶员行为检测看mAP50就够了mAP50-95作为参考。一般来说mAP50到0.85以上算可用0.9以上算不错。训练完成后runs/detect/train/目录下会生成权重文件、训练曲线、混淆矩阵等。混淆矩阵特别值得看能直观看出哪些类别容易混。比如抽烟和打电话如果经常混说明手部动作特征区分度不够可能需要增加数据或调整模型。4. 数据不均衡与难例挖掘实战4.1 长尾分布的处理策略驾驶员行为数据集里正常驾驶的样本通常最多可能占40%以上而喝水、转头这类动作样本较少。这种不均衡会导致模型偏向多数类少数类召回率低。处理方式有三种按推荐程度排序第一种是过采样少数类。把少数类的图片复制多份让各类样本数量接近。简单粗暴但有效缺点是容易过拟合少数类。实际操作时不要复制到完全相等复制到多数类的50%到70%就行。第二种是数据增强。对少数类图片做随机翻转、旋转、色彩抖动、马赛克增强生成更多变体。YOLOv8内置了这些增强通过augmentTrue开启但内置增强对所有类别一视同仁不能针对性加强少数类。要针对性增强得自己写数据加载逻辑。第三种是损失函数加权。给少数类的分类损失乘一个大于1的权重让模型更关注少数类。YOLOv8没有直接暴露这个参数需要改源码。如果你不想动源码前两种方法组合使用基本够用。4.2 难例挖掘让模型越训越聪明难例就是模型容易判错的样本。训练完一版模型后用它在验证集上推理把置信度低或者判错的样本挑出来人工检查标注是否正确然后把这些难例加入训练集重新训练。这个过程可以迭代多轮每轮模型都会变强一点。具体操作from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model.val(datadataset/data.yaml, save_jsonTrue)val会输出每个类别的precision、recall、mAP以及混淆矩阵。根据混淆矩阵找到最容易混的类别对然后专门去训练集里找这些类别的边界样本检查标注质量。我做过一轮难例挖掘把打电话和抽烟的混淆率从15%降到了6%效果很明显。4.3 标注质量复查的实操方法标注质量是模型精度的天花板。标注错了模型再强也学不对。复查标注有个高效方法用训练好的模型在训练集上推理把模型预测和原始标注不一致的样本挑出来。这些样本要么是模型错了要么是标注错了人工过一遍修正标注错误。import cv2 from ultralytics import YOLO model YOLO(best.pt) results model(dataset/images/train, streamTrue, conf0.3) for r in results: img cv2.imread(r.path) for box in r.boxes: x1, y1, x2, y2 map(int, box.xyxy[0]) cls int(box.cls[0]) conf float(box.conf[0]) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, f{cls} {conf:.2f}, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) cv2.imwrite(fvis/{r.path.split(/)[-1]}, img)把可视化结果和原始标注对比差异大的重点看。这个工作枯燥但值得做我一般会花半天时间过一遍能发现不少隐藏问题。5. 模型部署与推理性能优化5.1 导出ONNX与TensorRT加速训练完的PyTorch模型推理速度一般生产环境通常要转成ONNX或TensorRT。YOLOv8导出很简单from ultralytics import YOLO model YOLO(best.pt) model.export(formatonnx, imgsz640, simplifyTrue) model.export(formatengine, imgsz640, halfTrue, device0)ONNX是通用格式跨平台兼容性好但推理速度不如TensorRT。TensorRT是NVIDIA的推理加速库在N卡上能比PyTorch快3到5倍。halfTrue开启FP16半精度速度再提升约1.5倍精度损失很小。导出TensorRT engine时要注意engine文件是和显卡型号绑定的在V100上导出的engine不能拿到T4上用得重新导出。这是新手容易忽略的点。5.2 推理速度实测与路数估算标题热词里有个问题很典型T4 1080p25帧每秒用TensorRT YOLO 640分辨率检测可以支持多少路。这个问题我来算一下。T4的FP16算力是65 TFLOPSYOLOv8s在640分辨率下单帧推理大约2到3毫秒TensorRT FP16。1080p25帧每秒意味着每路视频每秒25帧每帧处理时间预算40毫秒。理论上单路占用2.5毫秒40除以2.5等于16路。但实际要考虑视频解码、预处理、后处理、数据传输的开销这些加起来可能占一半时间。所以实际能支持的路数大概是理论值的一半8路左右比较稳妥。如果换成YOLOv8n单帧推理降到1.5毫秒左右理论能支持20路以上实际10到12路。如果分辨率降到320速度还能再快一倍。具体路数要用实际视频流压测不能只看理论值。模型精度单帧推理(ms)理论路数实际路数YOLOv8nFP161.52610-12YOLOv8sFP162.5168-10YOLOv8mFP16584-5YOLOv8sFP324105-65.3 视频流推理的工程细节实际部署时视频流推理和单张图片推理差别很大。几个关键点帧采样策略。25帧每秒的视频不需要每帧都检测隔帧检测每2帧或3帧检测一次能大幅降低算力消耗对行为检测这种动作持续时间较长的任务精度损失很小。多线程流水线。视频解码、推理、后处理分到不同线程用队列串联避免某个环节阻塞整个流程。Python的GIL会限制多线程性能建议用多进程或者C实现。结果平滑。单帧检测结果可能有抖动用滑动窗口对连续多帧的结果做投票比如最近5帧里有3帧检测到抽烟才报警能有效降低误报。from collections import deque class SmoothDetector: def __init__(self, window5, threshold3): self.window deque(maxlenwindow) self.threshold threshold def update(self, detections): self.window.append(set(detections)) counter {} for frame_dets in self.window: for d in frame_dets: counter[d] counter.get(d, 0) 1 return [k for k, v in counter.items() if v self.threshold]这个平滑逻辑简单但实用我在实际项目里用下来误报率能降一半以上。6. 常见问题与排查技巧实录6.1 训练不收敛的排查清单训练不收敛是最高频的问题原因可能有很多按排查优先级列一下现象可能原因排查方法解决方案loss完全不降学习率过大看loss曲线是否震荡降低lr0到0.001loss降了又升过拟合对比训练和验证loss增加数据增强、早停cls_loss不降类别标注错误检查data.yaml的names顺序修正类别映射box_loss不降标注框格式错误可视化标注框修正标注格式训练中途崩溃显存不足看报错信息减小batch或imgszmAP为0验证集路径错误检查data.yaml的val路径修正路径我遇到最多的是data.yaml里names顺序和标注文件类别编号对不上这个错误很隐蔽因为训练能正常跑loss也在降但mAP就是上不去。排查方法是拿一张图手动推理看预测类别和实际是否一致。6.2 过拟合与欠拟合的判断与处理过拟合的表现是训练集mAP很高0.95以上验证集mAP明显低低5个点以上。处理方法是增加数据增强、加dropout、减小模型、早停。YOLOv8内置了mosaic、mixup、随机翻转等增强augmentTrue时自动开启。如果还过拟合可以手动调大mosaic的概率。欠拟合的表现是训练集和验证集mAP都低。处理方法是换更大模型、增加训练轮数、提高学习率、检查数据质量。欠拟合通常不是模型容量不够而是数据有问题或者训练不够充分。6.3 实际部署中的误报与漏报调优部署后最常见的反馈是误报太多或漏报太多。这两个是矛盾的调高置信度阈值减少误报但增加漏报调低则相反。我的经验是分场景设置阈值。抽烟、打电话这类需要报警的行为阈值设高一点0.6到0.7宁可漏报不要误报因为误报多了司机烦会把系统关掉。疲劳检测打哈欠、闭眼阈值设低一点0.4到0.5宁可误报不要漏报因为漏报可能出大事。另外报警逻辑不要只看单帧结合时间维度。比如连续3秒检测到抽烟才报警单帧误报就被过滤掉了。这个逻辑用前面说的滑动窗口就能实现。提示部署前一定要用真实场景的视频流做测试不要只用验证集图片。验证集和真实场景的分布差异可能很大我见过验证集mAP 0.92的模型在真实夜间红外视频上mAP掉到0.6的情况。6.4 数据集扩展与持续迭代22600张不是终点。实际项目里模型上线后会遇到各种验证集里没有的场景比如戴墨镜、戴口罩、特殊车型、极端光照。这些badcase收集起来人工标注后加入训练集重新训练模型会越来越适应实际场景。标注工具推荐labelImg或CVAT。labelImg轻量适合小规模标注CVAT功能强支持多人协作和视频标注适合团队使用。标注格式选YOLO和现有数据集保持一致省去格式转换的麻烦。迭代节奏建议每两周或每月一次取决于badcase积累速度。每次迭代记录mAP变化和badcase解决情况形成闭环。这个习惯坚持下来模型精度会稳步提升。7. 我个人在实际操作中的几点体会做驾驶员行为检测这几年踩过的坑比走过的路还多。最大的体会是数据质量决定上限模型和调参只是逼近这个上限。我见过太多人花大量时间调模型结构、试各种trick但标注数据里的错误一直没清理最后精度卡在某个点怎么都上不去。反过来把标注质量做好用最朴素的YOLOv8s都能跑出不错的效果。另一个体会是不要迷信大模型。驾驶员行为检测这个任务目标特征明显背景相对固定小模型完全够用。YOLOv8n在T4上能跑10路以上精度和s差不了两三个点但速度翻倍。在车载端算力受限的场景n才是最优解。最后说个细节训练时把cacheTrue打开但记得监控内存。我有一次用22600张图开cache内存直接爆了训练进程被系统杀掉白跑了一晚上。后来改成cachedisk速度慢一点但稳定。这种小坑文档里不会写只有自己踩过才知道。
返回列表