尧图精选

基于YOLOv5的异常行为检测实践:从环境搭建到部署避坑指南

🕒 发布时间:2026/9/28 1:09:11 📁 来源:尧图网络
简介这是一份面向本科计算机专业毕业设计的基于YOLOv5的异常行为检测完整实战资料适合毕业设计参考、课程设计和技能学习。它围绕目标检测模型从环境配置、数据处理到训练推理的全流程展开帮助读者快速上手并形成可复现的项目方案文档详细适合初学者按步骤推进也适合有基础者快速复用。压缩包共212个文件约2.81MB核心以105个yaml配置文件和45个Python脚本为主配合测试图片、Docker部署文件、Jupyter教程等内容构成完整的项目代码框架。目前已有637人学习下载。资料是作者整理的毕业设计真实成果内含模型配置、数据集标注组织、训练与推理脚本及常见排错思路并附有测试样例图片可验证模型效果既能作为毕业设计完整参考也可作为课程设计或YOLOv5工程化入门的学习素材。1. 基于YOLOv5的异常行为检测一份能直接跑通的毕业设计工程包异常行为检测是目标检测在安防、校园监控、养老院场景里最常见的毕业设计选题但真正动手才知道坑比想象中多——环境装到一半就劝退数据集标注到崩溃训练出来的模型不是漏检就是误检。这个资源包我拆完的感受是它把从零到一的过程收敛成了一整套可以直接跑的工程Dockerfile、教程、测试图片、配置项全部齐备不是那种只丢几个py文件的半成品。里面带tutorial.ipynb跟着走一遍就能把模型训练和推理串起来bus.jpg和Mosaic示例图用来验证预处理和标签格式对不对省掉排查数据管线的时间。适合三类人本科毕设选了这个题目的、想系统学YOLOv5源码的、工作中要在监控项目里叠加行为识别能力的。接下来按环境、数据、训练、避坑、部署五条线把要点和踩坑记录都讲清楚。2. 环境搭建与项目结构conda和Docker两条路都要会2.1 为什么选YOLOv5而不是更新版本的模型YOLOv5虽然名字里带v5但到现在依然是工程落地最稳的选择。YOLOv8、YOLOv9的检测精度确实更高但社区沉淀的教程、issue讨论、部署方案都远不如v5丰富。做毕业设计答辩老师大概率也最熟悉YOLOv5的内部结构你讲backbone、neck、head的改动时对方能从源码层面和你对话换成YOLOv8那个C2f模块反而增加沟通成本。另一个务实的理由是改造成本。YOLOv5的模型结构把backbone、neck、head拆分得很清楚自定义检测头或者改PANet都容易下手。这个资源包里的文件结构我看了一下就是标准的YOLOv5官方布局Dockerfile负责容器化环境setup.cfg管理包的metadatatutorial.ipynb把训练到推理的流程做成可执行文档。拿到手你不需要重新组织代码直接在这个骨架上做二次开发。从工程角度讲YOLOv5的issue几乎你能踩的坑都有人踩过搜个报错马上能找到解决方案这一点在答辩前一周救过不少人的命。2.2 conda方式安装CPU机也能跑GPU机要核对版本资源包里虽然带了Dockerfile但日常开发调试我更习惯先用conda把环境拉起来改代码迭代的速度比容器里快。YOLOv5的依赖项不算多核心就是torch、torchvision、opencv、numpy、pandas、matplotlib、seaborn外加一个pyyaml读配置。setup.cfg里列的就是这些基础依赖不需要额外装奇怪的东西。conda create -n yolo5 python3.9 -y conda activate yolo5 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118 pip install -r requirements.txt第一行创建Python 3.9的独立环境命名为yolo5。Python版本不要选3.11以上有些旧版本依赖包编译会出问题。第二行激活环境。第三行指定CUDA 11.8对应的PyTorch版本如果你的显卡驱动只支持CUDA 12.x把路径换成cu121或cu124。最后一行安装requirements.txt里的包这个文件在YOLOv5仓库根目录下资源包里也应该有没有的话手动装上面列的那几个也行。逻辑说明YU在YOLOv5的官方代码里仍在使用所以PyTorch的匹配版本要在2.0到2.2之间太新或太旧都可能出现算子不支持的情况。参数说明--index-url指定了PyTorch官方预编译包的下载源CPU用户把这段去掉直接pip install torch就行。装完后验证一下python -c import torch; print(torch.cuda.is_available())输出True说明GPU可用False就回到CPU模式跑速度慢点但能出结果。这一步很多人忽略训练到一半报CUDA out of memory才发现装的CPU版浪费半天时间。我一般装机后的第一件事就是跑这条验证命令顺手再nvidia-smi看一眼驱动支持的CUDA版本确保和PyTorch编译版本匹配。2.3 Docker方式答辩演示不翻车的关键资源包里带了Dockerfile这对毕设演示来说是个大杀器。答辩现场用自己笔记本跑环境最怕的是前一天还好好的第二天开机驱动失效或者conda环境被不小心动过。Docker把整个环境连同依赖一起打包在哪个机器上跑行为都一样。# 基于CUDA 11.8基础镜像构建带cuDNN加速 FROM nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04 ENV DEBIAN_FRONTENDnoninteractive # 安装Python 3.9和系统依赖 RUN apt-get update apt-get install -y python3.9 python3.9-dev python3-pip wget git libgl1 libglib2.0-0 # 复制项目代码到容器 WORKDIR /app COPY . /app # 安装Python依赖 RUN pip install --no-cache-dir -r requirements.txt # 暴露Jupyter端口 EXPOSE 8888 CMD [jupyter, notebook, --ip0.0.0.0, --port8888, --allow-root]这个Dockerfile的做法是先把系统依赖装好注意libgl1和libglib2.0-0这两个包OpenCV在容器里跑必须要它们缺了会报libGL.so.1找不到的错误。然后复制项目代码、安装Python依赖、暴露Jupyter端口。构建命令和启动命令如下docker build -t yolo5-anomaly . docker run -it --gpus all -p 8888:8888 -v /home/user/datasets:/app/datasets yolo5-anomaly--gpus all参数把宿主机GPU透传给容器这一步依赖NVIDIA Container Toolkit没装的话在宿主机执行sudo apt-get install nvidia-container-toolkit后重启Docker。-v把宿主机的数据集目录挂载进容器这样容器销毁后训练结果还在。启动后浏览器访问8888端口就能打开tutorial.ipynb跟着教程一步步跑。小提示如果Docker里跑训练显存不够多半是基础镜像使用的CUDA版本和驱动不匹配。先nvidia-smi看驱动支持的CUDA版本再选对应的镜像tag这步省不掉。3. 数据准备与标注异常行为检测的核心工作量3.1 行为类别怎么定从场景反推标签体系异常行为检测的目标是识别出不符合场景常规的行为模式在毕设里最常见的三个类别是打架斗殴、跌倒、翻越围栏。但这里有个区别需要讲清楚YOLOv5是单帧检测模型它看到的是一张静态图片而行为和动作天然是时序概念。这个矛盾决定了你的标注策略——要么把动作拆成关键姿态帧比如跌倒就取倒地瞬间的帧作为正样本要么用多帧投票的方式做后处理连续5帧里有3帧检测到跌倒才触发告警。资源里的bus.jpg和Mosaic示例图恰好帮你理解这个场景。bus.jpg是典型的人群密集场景异常行为很少发生在空地上所以数据集里要包含大量拥挤场景的负样本。Mosaic_without_label和Mosaic_with_label两张图则是训练数据增强的直观展示四张图拼接后通过放缩减小了目标尺寸让模型不得不学习更鲁棒的特征。我在这类项目里通常把类别数控制在4个以内样本数最少的类别也要有800张以上低于这个数模型很难收敛出稳定特征。标注环节我推荐用LabelImg界面简单且直接输出YOLO格式。每个类别有一个索引编号编号从0开始打架斗殴是0、跌倒是1、翻越是2、闯入禁区是3。这个顺序在训练配置文件和标注工具里必须严格一致否则模型学到的和你想表达的类别对不上。第一次做标注容易漏掉密集人群里的小目标我在标注时会强制要求自己把图片放大到200%逐块扫一遍虽然慢但样本质量直接决定模型上限。3.2 数据目录组织和标签格式校验YOLOv5训练时要求数据目录结构固定images放原图labels放标签文件图片和标签同名。数据集还要按train和val划分两个集合不能有重叠。下面的命令创建标准目录结构并完成初步划分mkdir -p dataset/images/train dataset/images/val mkdir -p dataset/labels/train dataset/labels/val # 按8:2比例随机划分图片 ls dataset/all_images | sort -R | head -n 800 train_list.txt ls dataset/all_images | sort -R | tail -n 200 val_list.txt while read img; do mv dataset/all_images/$img dataset/images/train/ mv dataset/all_labels/${img%.jpg}.txt dataset/labels/train/ done train_list.txt先创建训练集和验证集的图片目录、标签目录。然后用sort -R打乱图片列表head -n 800取前800张作为训练集tail -n 200取后200张作为验证集。最后循环把对应图片和标签分别移动到目标目录。这里有个关键点图片和标签文件的匹配靠的是同名不同后缀比如frame_001.jpg对应frame_001.txt。移动时用${img%.jpg}.txt把后缀替换掉这行逻辑如果写粗心很容易造成标签缺失。目录结构搭好后还要校验一下标签内容是否合法。YOLO格式的标签每行是五个数字类别索引加四个归一化坐标。第一个数必须是整数后四个数必须在0到1之间。下面这段Python脚本能快速排查标签问题import os label_dir dataset/labels/train for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname)) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: print(f{fname}:{i} 列数不对, got {len(parts)}) continue cls int(parts[0]) x, y, w, h map(float, parts[1:]) if x 0 or x 1 or y 0 or y 1: print(f{fname}:{i} 中心点越界, x{x}, y{y}) if w 0 or h 0: print(f{fname}:{i} 宽高异常, w{w}, h{h})这个脚本遍历标签目录下每个txt文件对每行做三项检查是否是五个字段、中心点x和y是否在[0,1]范围内、宽高是否为正数。逻辑说明YOLO格式的坐标是相对图片尺寸归一化后的值如果中心点越界或宽高为负训练时损失计算会出现NaN或者目标框飞出图片边界的情形。这些肉眼看不出来的脏数据会在训练到一半的时候以loss爆炸的形式突然冒出来提前查一遍等于给自己省一次重训的折腾。3.3 Mosaic增强原理与验证资源包里的mosaic_with_label.jpg和mosaic_without_label.jpg两张图是非常重要的教学参考。Mosaic是YOLOv5的核心数据增强策略之一把四张训练图片随机缩放裁剪后拼接成一张新图每张子图保留自己的标注框这就是mosaic_with_label的含义。不带标签的那张图是没勾选Label边界框时的可视化效果用来对比标注框在拼接后的变化。Mosaic能显著提升模型对遮挡和小目标的检测能力因为拼接操作模拟了一个画面里同时出现多个不同尺度的目标。但Mosaic不是一直开启就好。训练后期如果mosaic_prob还保持1.0模型会在拼接图的分布上过拟合导致真实场景里表现下降。YOLOv5在训练最后10个epoch会自动关闭Mosaic这个设计是官方内置的你在日志里会看到Closing mosaic的提示属于正常现象。还有一类翻车案例是自定义数据加载器时没实现Mosaic或误改了概率参数导致训练日志正常但精度始终上不去。建议用资源里这两张图做个快速自检把自己的训练数据跑一次数据加载器把输出的batch保存成图片对比Mosaic开启前后的差异。如果拼接图里标注框位置明显错位就要检查标签格式或随机拼接的逻辑了。验证脚本很短import cv2 from yolov5.models.experimental import attempt_load # 读取本地图片验证数据加载器输出 img cv2.imread(mosaic_with_label.jpg) print(Image shape:, img.shape)4. 训练自己的数据集超参数与调优实践4.1 模型选型与配置文件修改YOLOv5提供了n/s/m/l/x五个不同尺度的模型从轻量到高精度。异常行为检测的场景通常在固定摄像头下目标尺寸中等偏大不需要追求极致精度而牺牲速度。我一般推荐从yolov5s开始调跑通整个流程后再视精度需求升级到m。没必要一上来就练l或x训练时间成倍增加不说小数据集上还可能过拟合。模型配置文件是yolov5s.yaml训练前必须改两个地方nc改成你的类别数然后确认depth_multiple和width_multiple保持默认。对异常行为检测来说类别数一般不超过4所以模型的head部分和COCO的80类差别很大改动后模型参数的运算量明显下降。改完后的yaml文件类似这样# yolov5s_anomaly.yaml nc: 4 # 类别数打架、跌倒、翻越、闯入 depth_multiple: 0.33 width_multiple: 0.50 anchors: - [10,13, 16,30, 33,23] - [30,61, 62,45, 59,119] - [116,90, 156,198, 373,326]改动集中在第一行ncanchors保留官方值即可。anchors是根据COCO数据集聚类得到的如果你的目标尺寸分布差异特别大比如全是小目标可以通过python utils/autoanchor.py重新聚类。但异常行为的检测目标通常是完整的人体或半身尺寸分布接近COCO的行人类别用默认anchor就够了强行重算还可能在答辩时被追问合理性。训练数据配置在data.yaml里这个文件指定训练集和验证集路径、类别数、类别名。路径建议写绝对路径写相对路径容易因为工作目录切换导致FileNotFoundError。类名顺序要和标注时的编号一致我从0开始数。# anomaly_data.yaml train: /home/user/dataset/images/train val: /home/user/dataset/images/val nc: 4 names: [fight, fall, climb, intrusion]train和val指向图片目录YOLOv5会自动找到对应的labels目录。names的排列顺序决定了模型输出的类别含义在后续推理和可视化里要反复用到建议现在就用全小写单词命名别用缩写。推理时显示类别名答辩演示数据集的类别名清晰会让整个项目显得更专业。4.2 训练命令与超参数调节训练入口是train.py最小可用参数集合是这样的python train.py \ --weights yolov5s.pt \ --data anomaly_data.yaml \ --hyp hyp.scratch-low.yaml \ --epochs 100 \ --batch-size 16 \ --img 640 \ --device 0 \ --name anomaly_exp1逐行说下参数含义。--weights指定预训练权重从官方仓库下载的yolov5s.pt是在COCO上训好的迁移到你的数据集上能省大量训练时间。--data就是刚才写的数据集配置文件。--hyp指定超参数文件hyp.scratch-low.yaml是官方给的低配置超参显存小的机器用它更稳妥。--epochs是训练轮数100轮在大约1000张训练图上差不多能收敛数据量更少可以减到60轮。--batch-size受显存制约16GB显存跑yolov5s配16的batch没问题显存不够就降到8或4。--img是训练输入尺寸640是精度和速度的平衡点。--device 0指定第0块GPUCPU训练改成cpu。--name是实验名输出会保存在runs/train/anomaly_exp1目录下。训练过程中重点关注两个信息loss曲线和mAP指标。YOLOv5在训练日志里会每100轮输出一次验证集的mAP50和mAP50-95前者表示预测框和真实框的IoU超过0.5时算作正确的精度后者是对IoU阈值从0.5到0.95取平均更严格。如果看到mAP50在最后10轮还在明显上升说明还没收敛完需要增加epochs如果mAP50已经很高而mAP50-95很低说明预测框的定位精度不够可以调整NMS的iou阈值或者换大模型。超参数的调节要克制我见过很多人在训练阶段陷入调参深渊。出现loss震荡时优先减小学习率动lr0和lrf# hyp.scratch-low.yaml 中动态调整 lr0: 0.003 # 初始学习率震荡时降到0.001 lrf: 0.12 # 最终学习率 lr0 * lrf warmup_epochs: 2.0 # 预热轮数帮助收敛稳定lrf表示学习率衰减到初始值的比例warmup_epochs让模型在头两个epoch用较小的学习率做预热之后再按余弦退火衰减。这组参数是官方推荐的基础配置在没有明显依据的情况下不要大改。改了超参数后训练日志里会有对比你是基于实验结果做调整这句话在答辩时比任何理论推演都有说服力。4.3 训练结果验证不只是看mAP训练结束后runs/train/anomaly_exp1目录下会生成weights/best.pt和weights/last.pt两个权重文件。best.pt是验证集表现最好的模型last.pt是最后一批epoch的模型。部署和测试一律用best.pt这个习惯要养成。目录下的confusion_matrix.png给你的是每个类别的误检和漏检情况异常行为检测最怕的是跌倒被检测成打架这种混淆在图中一眼可见发现混淆后去检查是不是标注时把两种动作的边界帧归类错了。results.png把六条曲线画在一张图上包括box_loss、cls_loss、obj_loss和mAP曲线。判断模型是否健康的经验是三行loss曲线都应该单调下降然后趋于平稳如果有任何一条突然上翘再下降属于局部波动不需要管如果尾部持续上行那就要检查是不是学习率没降到位或者数据里有异常标签。最后我习惯跑一次验证脚本在验证集上得到可视化的检测结果确认预测框的置信度数值落在合理区间python val.py \ --weights runs/train/anomaly_exp1/weights/best.pt \ --data anomaly_data.yaml \ --img 640 \ --conf-thres 0.25 \ --iou-thres 0.45--conf-thres 0.25意思是预测框的置信度超过0.25才保留低于这个值的都视为背景--iou-thres 0.45是NMS的IoU阈值两个框重叠超过45%时只保留置信度更高的那个。这两个值会影响最终mAP数字验证时用的阈值要和预测推理时保持一致否则报出来的指标没有参考价值。输出里会有一个表列出每个类别的精度、召回率、mAP50想上桌面演示前先确认每个类别的mAP50都在0.8以上。5. 避坑YOLOv5异常行为检测的五个常见问题5.1 loss直接变成NaN训练崩溃训练到几十个epoch突然看到loss: nan然后模型权重导出后完全不能推理。原因是学习率太高导致梯度爆掉或者数据里有坐标异常的目标框比如宽高为0的标签。还有一种是数据集里存在完全空白的图片网络前向传播计算出NaN。我一般先停止训练检查标签里是否有非法值用前面那个校验脚本扫一遍。确认没问题后把learning率从默认值降到0.001再调小batch-size重训。还不行就检查图片本身YOLOv5有缓存机制把--cache参数去掉重新跑。5.2 检测框每帧乱跳置信度忽高忽低单帧检测正常但连续视频帧里同一个目标框的位置和类别频繁变化跌倒检测到一半框消失又出现。原因在于NMS的iou阈值设得太低而置信度阈值设得太高相邻帧的检测结果不稳定。另外模型在小目标上的定位精度不够目标轻微移动就让检测框大幅漂移。把--iou-thres从0.45降到0.3--conf-thres从0.25降到0.15框会变多但稳定性改善。更根本的解法是在推理端做时序平滑连续三帧同一个位置都检出同一类别才输出告警单帧的偶发结果直接丢弃。5.3 Docker里训练报CUDA error宿主机GPU用不了在容器内跑训练nvidia-smi能看到GPU但PyTorch报CUDA error: no kernel image is available。这是因为Docker镜像里的CUDA版本和宿主机的NVIDIA驱动不兼容镜像是CUDA 11.8的但宿主机驱动只支持到CUDA 11.4PyTorch的算子编译时用的版本高于驱动能支持的版本于是运行时崩溃。解决办法是换镜像tag把基础镜像的版本降下来匹配驱动。执行nvidia-smi看右上角的CUDA Version比这个版本低一档的镜像基本安全。如果项目已经构建了不想重来也可以把PyTorch版本换成CPU版凑合跑速度慢但结果等价。5.4 数据集带中文路径训练时读取不到图片Windows下做标注时用了中文目录Linux下训练报FileNotFoundError但路径看起来完全正确。原因是YOLOv5读路径时用的字符编码默认是utf-8Windows中文环境可能是gbk两种编码对同一个路径字符串的字节表示不同Linux端解码就失败了。一个是把数据集整个移到纯英文路径一劳永逸另一个是在代码里强制指定编码用open(path, encodingutf-8)替换默认的读取方式。我建议直接改路径数据集命名规范用英文和数字所有项目通用这个习惯。5.5 Mosaic增强导致小目标漏检验证集上精度低于训练集训练时mAP50一直是0.9但验证集只有0.7看起来像过拟合但减少epochs后反而更差。Mosaic增强拼接了四张图模型的输入分布和真实单图场景差异较大。训练时大量使用Mosaic的图片模型学会了在拼接图的特征模式上做检测遇到真实场景的单图反而不适应。训练后期手动调低mosaic概率在hyp配置里把mosaic: 1.0改成mosaic: 0.5让模型在最后的epoch接触更多真实场景的样本分布。也可以多训练10个epoch给模型更多时间去适应关闭Mosaic后的数据分布。6. 模型导出与实测把权重用起来6.1 单图和视频实测训练出的best.pt要走到推理这一步才算是完整闭环。detect.py是官方推理脚本输入可以是图片、视频或摄像头流python detect.py \ --weights runs/train/anomaly_exp1/weights/best.pt \ --source test_video.mp4 \ --img 640 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --save-txt \ --save-conf--source指定输入文件视频会逐帧处理后生成标注过的视频。--save-txt把检测结果保存为txt每一行是类别索引加归一化坐标方便后续做行为判定的后处理。--save-conf把置信度也写进txt。输出文件在runs/detect/exp目录下。先拿test_video.mp4跑一遍观察检测框是否有剧烈抖动再拿一张静图跑一下确认类别名输出正确。6.2 导出ONNX做轻量部署YOLOv5的pt权重依赖PyTorch环境部署到边缘设备或嵌入到其他系统时更常见的是导出为ONNX格式。导出命令python export.py \ --weights runs/train/anomaly_exp1/weights/best.pt \ --include onnx \ --img 640 \ --batch 1导出时会打印动态轴信息输出一个best.onnx文件。之后用onnxruntime加载这个文件做推理不再需要PyTorch环境部署体积大幅缩小。导出后一定要验证输出的一致性和原pt模型是否相同找一个测试图分别用两种方式跑对比检测框坐标和置信度的差异。6.3 一个教训验证集和超参数必须认真对待做这类型毕设那会儿我赶时间跳过了超参数验证用默认配置直接练完100个epochmAP50看着不错就把权重部署到演示视频里。结果现场演示拍到跌倒场景时模型没反应换成测试图片又能检出来台上答辩很被动。后来检查发现演示视频的帧率是25fps目标在画面里停留时间短默认阈值0.25在快速运动场景下置信度不够被过滤掉了。从那以后我每次训练完都强制走一遍完整验证流程在多个不同场景的视频上测试确认每个类别的置信度分布然后针对典型的误检漏检场景微调阈值。这一步不做完绝不上线。这个习惯帮我避开了不少演示翻车的局面希望也能帮到你省下临场补救的时间。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →