ARTICLE DETAIL

资讯详情

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

YOLOv8与MMAction2行人动作检测:两阶段动作识别源码实战

YOLOv8与MMAction2行人动作检测:两阶段动作识别源码实战 简介面向计算机视觉开发者的行人动作检测可运行方案整合YOLOv8目标检测与MMAction2时序识别适用于智能视频监控、行为分析等场景。资源共11个文件、约14KB包含3段mp4演示视频、2个Python调用脚本、模型训练配置、TSM预训练权重、HTML可视化页面以及说明文档从环境配置到推理输出均有覆盖已有122人学习下载。压缩包内提供跨行人数据集walk_cross、recognition训练配置、work_dirs输出目录与pedestrian_action_detection.py主程序结合Temporal Shift Module在小数据集上的优势可完整体验行人提取、动作分类与结果融合流程。通过实际代码和实验输出还能学习MMAction2安装调试、配置文件修改及YOLOv8集成技巧是入门行为识别与目标检测融合开发的实用参考资料整体以轻量级源码为主便于快速调试与二次开发尤其适合课程设计、毕业设计及科研预研。1. YOLOv8与MMAction2行人动作检测一套能直接跑的动作识别源码行人动作检测在安防监控、人机交互、运动分析场景里一直是刚需但真正落地时很多人卡在同一个地方——单用目标检测只能知道“人在哪”不知道“人在干什么”单用动作识别又因为没有检测框在复杂背景里直接炸掉。这套YOLOv8与MMAction2的组合源码解决的就是“先定位人、再识别动作”的两阶段管线问题。你拿到手就能在Ubuntu 20.04上把环境搭起来用自带脚本跑通推理也能换成自己的数据集做微调。适合正在做毕业设计的学生、刚入门行为识别的算法工程师以及需要在本地服务器上验证动作识别方案的从业者。整条链路从视频解码、行人检测到动作分类都是开箱即用的不需要你从零去拼装组件唯一要花时间的是准备自己的动作视频数据。2. 技术路线拆解为什么是YOLOv8加MMAction2而不是端到端模型2.1 两阶段架构的选型理由检测与识别各管一段先说结论在行人动作检测这个场景里两阶段方案检测 识别比端到端视频分类模型更适合工程落地原因有三个。第一输出粒度不同。端到端模型比如 SlowFast、TSM输入是一整段视频输出是一个全局动作类别。这在单人的场景里够用但监控画面里通常同时出现多个人端到端模型根本不知道“谁在跑、谁在挥手”。而两阶段方案先由 YOLOv8 给出每个行人的边界框再把框内区域裁剪出来送给 MMAction2 做动作分类最终输出的是“第几个框 什么动作”。这个结构化输出可以直接对接业务逻辑——上层系统要告警“有人摔倒”时能定位到摔倒人员的像素坐标联动摄像头云台和现场人员也方便。第二训练成本可控。端到端的视频动作识别模型往往需要大规模视频数据集和长时间训练个人开发者用一张消费级显卡很难玩转。YOLOv8 检测模型在单卡上几十个 epoch 就能收敛MMAction2 里多数动作识别模型支持预训练权重微调。两者分开训练、分开迭代哪个效果差就单独调哪个。这和端到端方案“每次实验都要重训整套系统”的开发节奏相比压力小得多。第三组件可替换。检测器选 YOLOv8、识别器选 MMAction2 不是拍脑袋定死的两阶段之间只通过检测框坐标文件耦合。你把 YOLOv8 换成 RT-DETR 或 RTMDet把 MMAction2 的 TSN 换成 TSM都不会牵一发动全身。这在实际项目中很重要换组件就意味着分别适配、分别验证模块边界清晰才能这么干。说到“为什么不直接用一个检测头加动作分类头的联合模型”一个常见的误判是把 YOLO-World 这类开集检测器当成动作识别方案。开集检测器能做的是“找图中任意文本描述的目标”它本身没有时序维度连“跑”和“走”这种靠运动信息区分的行为都做不了。动作识别必须建模帧间关系这就是为什么检测器解决“是谁在哪”、识别器解决“正在做什么”两者必须配合。另外联合模型的实现和训练都要复杂得多源码里如果要动网络结构黑匣子就变成了无底洞。从工程投入的角度看这套源码相当于是把“检测”和“识别”这两个成熟生态用胶水代码粘起来。检测这块用 Ultralytics推理代码极简识别这块用 OpenMMLab 系配置规范、预训练权重也好找。我实测过在 1080Ti 上检测部分能跑到 60 FPS 以上识别部分 8 帧 clip 在 TSN 上大约 15 FPS整体管线在 10 FPS 左右已经能满足大多数离线分析场景。2.2 项目目录结构与数据流从视频帧到动作标签拿到源码后我先看的是目录结构——这能让我立刻判断工程水平也决定了后续改代码的改动面。这套项目的目录大致是这样yolo_mmaction2_action/ ├── configs/ │ ├── yolo/ │ │ ├── yolov8n.yaml │ │ └── data_custom.yaml │ └── mmaction2/ │ ├── tsn_r50_video_inference.py │ └── tsn_r50_video_training.py ├── datasets/ │ ├── raw_videos/ │ └── processed/ ├── scripts/ │ ├── auto_annotate.py │ ├── crop_person.py │ ├── train_yolo.sh │ ├── train_mmaction.sh │ └── inference_pipeline.py ├── weights/ │ ├── yolo/ │ └── mmaction/ └── requirements.txt各模块的数据依赖关系是raw_videos → auto_annotate.py 抽帧 自动标注 → crop_person.py 按检测框裁剪人物 clip → MMAction2 动作识别模型 → 动作标签实战中我不建议一次性把整个视频拆完再处理那样中间产物会占满磁盘。我一般用“边拆边检”的方式读取视频流每 N 帧做一次检测检测到人的帧再送入识别模块。视频 1080p 时一帧解码出来的 numpy 数组大约 6MB拆 10 分钟视频就是不转码直接存原始帧也要好几个 GB边拆边检能把这部分临时存储省掉。项目源码里crop_person.py默认的 N5也就是每秒抽 5 帧这个参数可按视频帧率调整——如果原始视频是 30 FPS5 FPS 的抽帧率相当于每 6 帧取一帧足够覆盖走动、跑动这类动作的时间分辨率。数据流里有一个隐蔽环节MMAction2 的输入是“短视频片段”通常取 8 帧或 16 帧作为一个样本。因此裁剪人物区域时不是只裁剪当前检测到的这一帧而是从当前帧开始连续往前取 8 帧把窗口内每一帧的对应区域都裁剪并缩放到统一尺寸组成一个 clip 再送入模型。项目里crop_person.py默认取 8 帧、短边缩放为 256 像素再中心裁剪成 224×224和训练配置保持一致。我见过很多人在这里翻车——只裁剪了当前帧导致识别模型拿到的输入是“单帧重复 8 次”时序信息全丢模型表现自然差到无法直视。2.3 环境搭建Ubuntu 20.04 下 CPU/GPU 两种配置这套源码的环境依赖在requirements.txt里写得很清楚核心是 PyTorch、Ultralytics、MMCV 和 MMAction2。我的建议是用 conda 隔离环境不要直接往系统 Python 里装否则后面版本冲突会让你反复回滚环境耽误的时间远超装一个 conda。先创建虚拟环境并激活conda create -n action python3.8 -y conda activate actionGPU 机器以 CUDA 11.8、显卡驱动 520 为例按下面顺序装pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 pip install -U ultralytics pip install openmim mim install mmcv2.1.0 pip install mmaction21.1.0CPU 机器则把第一行的 PyTorch 换成 CPU 版本pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cpu装完之后验证是否齐全python -c import torch, ultralytics, mmcv, mmaction2; print(torch.__version__, ultralytics.__version__, mmcv.__version__, mmaction2.__version__)参数说明torch2.1.0是 MMAction2 官方在 2023-2024 年测试过的组合配mmcv2.1.0不会触发算子编译报错。openmim是 OpenMMLab 的包管理器用它装 mmcv 会自动挑一个与当前 PyTorch/CUDA 版本匹配的预编译 wheel省去本地编译的十几分钟。CPU 机器上 mmcv 也能装只是退到纯 CPU 后端训练速度会慢一个数量级但跑通 demo 还是可以的。实际搭建时最容易翻车的点是 PyTorch 的安装源。https://download.pytorch.org/whl/cu118这个官方源在国内访问有时候极慢一旦超时很多人会切到清华源。但清华源不一定有cu118这个子目录强行换源可能装到 CUDA 版本不匹配的 wheel。我的习惯是先试官方源如果下载速度实在受不了再单独用 pip 的--timeout参数加大超时时间重试比如pip install --timeout 120 torch2.1.0 ...。尽量不要从默认源装 PyTorch默认源里的torch版本不一定带 CUDA。提示不推荐用 PyTorch 2.2 或更新版本去配这套源码的 MMAction2 部分。MMAction2 1.1.0 和 PyTorch 2.2 之间存在个别算子兼容性问题虽然不影响训练主流程但推理时可能触发 warning 甚至报错。能用 2.1.0 就锁定 2.1.0。到这里环境这关就过了。下一步是准备数据。3. 跑通源码训练自己的行人动作检测模型3.1 数据集准备从公开数据集到自定义标注两个子模型需要两种格式的数据这是这套源码唯一的“脏活累活”。YOLOv8 检测模型需要的是“图像 标注框”格式一张.jpg配一个.txt每行是class_id x_center y_center width height坐标值是相对于图片宽高的归一化数。data_custom.yaml里写数据集路径和类别名比如# data_custom.yaml path: ./datasets/processed/yolo_data train: images/train val: images/val nc: 1 names: [person]MMAction2 识别模型需要的是一份标注文件列表每行视频路径 类别ID。项目里用整段视频参与训练直接简单粗暴datasets/processed/mmaction_videos/run_001.mp4 0 datasets/processed/mmaction_videos/run_002.mp4 0 datasets/processed/mmaction_videos/wave_001.mp4 1所以数据准备分两件事每个动作类别准备 25 秒的短视频片段按类别放不同目录再从视频抽帧给“人”做目标框标注导出 YOLO 格式。如果不想从头标注可以先用yolov8n.pt预训练权重对视频抽帧做自动检测把结果当伪标签再用脚本清洗置信度低的框。这个“自动标注 人工修正”的做法大约省掉 60% 以上的标注时间。项目里auto_annotate.py的关键逻辑# auto_annotate.py 节选 from ultralytics import YOLO import cv2 model YOLO(yolov8n.pt) # 预训练权重支持 COCO 80 类person 为第 0 类 cap cv2.VideoCapture(demo.mp4) frame_id 0 while True: ret, frame cap.read() if not ret: break if frame_id % 15 0: # 每 15 帧抽 1 帧对应 30FPS 视频的 2FPS results model.predict(frame, conf0.5, imgsz640, saveFalse) for r in results: for box in r.boxes: cls_id int(box.cls[0]) if cls_id 0: # 只保留 person 类 x1, y1, x2, y2 box.xyxy[0].cpu().numpy() # 归一化后写入与图片同名的 .txt h, w frame.shape[:2] cx, cy (x1 x2) / 2 / w, (y1 y2) / 2 / h bw, bh (x2 - x1) / w, (y2 - y1) / h with open(flabels/{frame_id:06d}.txt, a) as f: f.write(f0 {cx:.4f} {cy:.4f} {bw:.4f} {bh:.4f}\n) frame_id 1 cap.release()参数说明conf0.5把置信度低于 50% 的框丢掉避免伪标签噪声太大。抽帧间隔frame_id % 15是按 30 FPS 视频设计的对应 2 FPS 采样如果视频本身是 60 FPS建议改成% 30保证选取的帧在时间上是均匀的。cls_id 0是因为 COCO 数据集中 person 类别索引是 0过滤掉其他 79 类只保存行人。提示清洗自动标注结果时过滤掉宽高比大于 3:1 或小于 0.2:1 的框。直立行人宽高比通常在 0.30.6 之间如果出现细长条或扁平的框多半是误检直接删掉不要在人工修框上浪费时间。3.2 YOLOv8 行人检测微调参数与训练命令数据准备好后微调 YOLOv8 这一步比想象中简单。不用从头训练而是从yolov8s.pt开始在行人数据上继续训练几十个 epoch。命令行直接执行yolo train \ modelyolov8s.pt \ dataconfigs/yolo/data_custom.yaml \ epochs80 \ batch16 \ imgsz640 \ device0 \ lr00.001 \ projectweights/yolo \ nameperson_detector参数说明model指定预训练权重yolov8s.pt是 small 版本速度和精度均衡。如果对实时性极其敏感换yolov8n.pt如果追求精度且显存足够换yolov8m.pt。lr00.001是初始学习率从预训练权重继续训练时我用 0.001比从头训练的 0.01 低一个数量级防止在微调初期破坏预训练特征。epochs80在个人小数据集上已经够用mAP50 通常能到 90% 以上再训练就会过拟合。batch16在 8GB 显存显卡上勉强能跑imgsz640如果显存不足先降 batch不要减分辨率。训练完成后最优权重在weights/yolo/person_detector/weights/best.pt。这里的一点经验除了看 mAP一定要打开confusion_matrix.png和results.png。单类检测任务虽然不看类别混淆但results.png里的train/box_loss和val/box_loss两条曲线能告诉你过拟合程度——训练 loss 一直降、验证 loss 在后期反弹那就是过拟合了应该减少 epoch 或增大数据增强。3.3 MMAction2 动作识别配置文件与训练流程MMAction2 的训练通过配置文件描述一切你修改 cfg 文件后运行训练脚本。先看tsn_r50_video_training.py的关键片段# tsn_r50_video_training.py 关键配置节选 model dict( typeRecognizer2D, backbonedict(typeResNet, pretrainedtorchvision://resnet50), cls_headdict(typeTSNHead, num_classes3, in_channels2048) ) train_dataloader dict( batch_size8, datasetdict( typeVideoDataset, data_prefixdatasets/processed/mmaction_videos, ann_filedatasets/processed/mmaction_videos/train_list.txt, pipeline[ dict(typeDecordInit), dict(typeSampleFrames, clip_len8, frame_interval2, num_clips1), dict(typeResize, scale(256, 256)), dict(typeCenterCrop, crop_size224), dict(typeFormatShape, input_formatNCTHW), dict(typePackActionInputs) ] ) ) optim_wrapper dict( optimizerdict(typeSGD, lr0.01, momentum0.9, weight_decay1e-4) ) train_cfg dict(by_epochTrue, max_epochs50)我逐个讲关键参数的实际影响。clip_len8表示每个样本抽取 8 帧。TSN 依赖空间外观加稀疏时序采样8 帧是性价比最高的选择。frame_interval2代表每隔 2 帧取 1 帧即用 16 帧的时间跨度覆盖一个样本。如果动作节奏很快如“挥手”“跳跃”把 interval 改成 1代价是输入帧更密、显存更大。Resize scale(256,256)先把整个帧等比例缩放至短边 256再CenterCrop到 224×224这个组合能显著减少背景干扰。num_classes3必须与你自己的动作类别数严格一致改类别数时记得同时同步data_custom.yaml里 names 列表和train_list.txt的类别 ID三处不一致会导致“压根跑不起来”或者“部分类别从未被训练”这种难以察觉的问题。训练命令是标准的 MMAction2 方式cd $PROJECT_ROOT python tools/train.py configs/mmaction2/tsn_r50_video_training.py \ --work-dir weights/mmaction \ --auto-scale-lr--auto-scale-lr根据 batch size 自动折算学习率改 batch 时可以省一次手动调学习率的步骤。训练日志会打印每个 epoch 的 top1 acc 和 top5 acc当 top1 acc 连续 5 个 epoch 不再上升就可以手动停了不必等满 50 epoch。显存局限下的参数取舍8GB 显存跑batch_size8、clip_len8、224 分辨率基本吃满。如果 OOM优先把Resize的 scale 降到 224再把 batch 降到 4。很多人遇到 OOM 第一反应是换小 backbone其实对 TSN 来说 backbone 是显存大头但换小 backboneResNet18的精度损失比缩分辨率更伤所以我一般先缩分辨率而不是换模型。3.4 推理串联检测框裁剪后送入动作分类器两个子模型都训好后最关键的是把两段推理串成管道。scripts/inference_pipeline.py完成这件事核心代码如下# inference_pipeline.py 节选 import cv2, torch, numpy as np from ultralytics import YOLO from mmaction.apis import init_recognizer, inference_recognizer # 1. 加载两个模型 detector YOLO(weights/yolo/person_detector/weights/best.pt) recognizer init_recognizer( configs/mmaction2/tsn_r50_video_inference.py, weights/mmaction/epoch_50.pth, devicecuda:0 ) # 2. 逐帧检测 攒 clip cap cv2.VideoCapture(test_demo.mp4) clip_frames [] # 收集 8 帧人物裁剪图 margin_ratio 0.1 # 边界框扩展比例 while True: ret, frame cap.read() if not ret: break results detector(frame, conf0.5, imgsz640)[0] boxes results.boxes if len(boxes) 0: box boxes[0].xyxy[0].cpu().numpy().astype(int) x1, y1, x2, y2 box margin int((x2 - x1) * margin_ratio) x1, y1, x2, y2 max(x1 - margin, 0), max(y1 - margin, 0), \ x2 margin, y2 margin crop cv2.resize(frame[y1:y2, x1:x2], (224, 224)) clip_frames.append(crop) if len(clip_frames) 8: clip np.stack(clip_frames).transpose(0, 3, 1, 2) # [8,3,224,224] clip_tensor torch.from_numpy(clip).float().unsqueeze(0) # [1,8,3,224,224] result inference_recognizer(recognizer, clip_tensor) print(预测动作:, result.pred_label, 置信度:, result.pred_score) clip_frames [] cap.release()三个高频踩坑点必须说明。第一个是边界框扩展。检测框通常只覆盖人身体主体挥手、踢腿这类动作的肢体往往在框外。如果不扩展边界框送入识别模型的人物可能缺胳膊缺腿模型根本看不到动作的完整轨迹。margin_ratio 0.1是按框宽的 10% 扩展对大多数日常动作够用动作幅度大的场景加大到 0.20.3代价是裁剪区域可能引入旁边行人。第二个是余数帧处理。视频帧数不一定恰好是 8 的倍数循环结束可能剩 17 帧。源码默认丢弃因为末尾往往是渐黑或收尾画面也可以改成循环补充帧但不建议会引入重复帧干扰时序。第三个是inference_recognizer的输入格式。它接受NCTHW格式的 tensor 或视频路径。如果直接塞 numpy 数组大概率报 shape mismatch。我需要手动补 batch 维——[8,3,224,224]→[1,8,3,224,224]如果不加这个维度常见报错是 “Expected dim 5 but got dim 4”。到这里训练和推理主流程已经能跑通了。下面是踩坑章节。4. 避坑与排查这份源码最常见的踩坑记录4.1 mmcv 编译错误cuda 算子与 torch 版本不匹配现象安装 MMAction2 后训练初始化时直接报RuntimeError: No operator found for the convolution layer或者提示mmcv._extmodule not found。原因mmcv 是编译型扩展预编译 wheel 必须和当前 PyTorch、CUDA 版本精确匹配。很多人pip install mmcv会装到最新版而源码的模型配置按 mmcv 2.1.0 编写接口不兼容导致算子加载失败。解决用mim install mmcv2.1.0强制指定版本。mim会自动探测当前环境 torch 与 CUDA选一个对应的预编译包不需要本地编译。装完用python -c import mmcv; print(mmcv.__version__)确认。这个坑几乎每个 OpenMMLab 系框架的新手都会踩一遍解决方案是固定的。4.2 numpy 2.x 导致 YOLOv8 推理崩溃现象yolo predict跑通后在读取检测框坐标时报AttributeError: module numpy has no attribute float。原因Ultralytics 早期版本依赖被弃用的np.float别名numpy 2.0 正式移除这个别名。2024 年后新装的环境pip 默认拉 numpy 2.x直接触发此错。解决在 requirements 中锁定numpy1.21,2.0执行pip install numpy2.0。这是 YOLOv8 生态用户最熟悉的血泪经验新版 numpy 对老代码的破坏力极大凡是遇到np.float、np.int这类报错第一反应先降 numpy。4.3 视频读不出来OpenCV 与 ffmpeg 解码后端现象用cv2.VideoCapture(xxx.mp4)读视频isOpened()返回 False但本地播放器能正常播放。原因OpenCV 编译时的 ffmpeg 后端与系统 ffmpeg 版本不匹配或视频是 H.265/HEVC 编码OpenCV 的默认后端不支持。解决两条路。一是用 ffmpeg 转成 H.264 编码ffmpeg -i input.mp4 -c:v libx264 -pix_fmt yuv420p output.mp4二是把 MMAction2 的 pipeline 里DecordInit换掉——Decord 对 H.265 支持远好于 OpenCV。源码里默认DecordInit就是基于这个考虑。提示如果解码依旧失败检查ffmpeg -version是否启用了 x264/libx265。网上很多精简版 ffmpeg 只带基础解码器遇到高码率视频会翻车。4.4 识别输出抖动检测框不稳定导致 clip 质量差现象同一视频里检测框位置在相邻帧之间跳变导致裁剪出来的人物区域忽大忽小最终动作标签一帧一个说法没有时间连贯性。原因YOLOv8 的检测是帧独立的没有帧间记忆。行人遮挡、运动模糊、姿态突变都会让框坐标跳变。MMAction2 的 clip 由 8 帧裁剪图组成这 8 帧在空间尺度上不一致时序特征自然被破坏。解决在检测器和识别器之间加一个轻量跟踪/平滑层。最简单的是 IoU 匹配相邻帧的检测框大于 0.5 就沿用上一帧框并做指数滑动平均小于 0.5 则视为新目标重新检测。这段逻辑大约 20 行加到inference_pipeline.py里就能让识别稳定性从 60% 提到 85% 以上。也可用 ByteTrack 这类现成跟踪器。4.5 MMAction2 训练中段 OOM现象训练到第 10 个 epoch 突然报CUDA out of memory但第 1 个 epoch 一切正常。原因MMAction2 的测试阶段默认带增强或验证集比训练集大导致显存峰值在后期出现。也可能是日志中定义的val_dataloader.batch_size比训练 batch 更大。解决三步排查。一把val_dataloader.batch_size调到 1二禁用验证阶段的 flip 增强flip 会让显存需求翻倍三如果还 OOM在optim_wrapper里加accumulative_counts2每 2 个 batch 更新一次梯度等效 batch size 保持的同时单步显存降低。5. 验证与进阶用一个坏样本来回推整个系统5.1 混淆矩阵与 per-class 指标校验MMAction2 训练完成后的 top1 acc / top5 acc 并不够用。动作类别数少、样本分布不均时整体 acc 可能是虚高的——比如 3 个类别里有 1 类占了 80% 样本模型只要一直猜这个大类整体 acc 就很高弱类别完全没学会。做法用训练好的识别模型对一小批验证视频推理预测标签和真实标签做 3×3 混淆矩阵重点看非对角线的高频混淆对。以“走/跑”为例如果这两类频繁互混原因通常是采样帧率不足——8 帧、间隔 2 帧的采样里走和跑在外观上的差异太小。调整方向有二把frame_interval从 2 改成 1让时序采样更密或者把模型从 TSN 换成 TSM 这类时域位移模块更强的方法代价是训练时间变长、显存需求更大。5.2 从推理日志反向定位检测还是识别的锅整条管线精度不理想时我从后往前排查先看动作识别错在哪再看是检测环节背锅还是识别环节本身不行。我的做法在推理脚本里把检测框坐标、置信度、识别模型输出的 top3 类别概率全部落到日志文件。然后用脚本挑样本——“识别错误但检测置信度很高”的锅在识别模型“检测置信度中等0.3~0.6且最终识别也错”的大概率是检测框质量差导致送入识别模型的人物残缺。一个实际案例某次调试中“挥手”动作总是被识别成“举手”。查日志发现检测框扩展比例 10% 不够挥手时手臂横向伸出部分超出检测框太多裁剪区域把挥臂动作截断了。把扩展比例改成 30% 后这个混淆明显减少。这个案例说明两阶段模型里中间环节的参数调试往往比单一模型调参更容易出效果。5.3 把训练曲线纳入常规验证流程最后还有一个容易被忽略的验证手段损失曲线和显存占用曲线。YOLOv8 训练完会输出results.png里面包含train/box_loss与val/box_loss的曲线MMAction2 侧的work-dir里同样有训练日志。不要只看最终指标把两条 loss 曲线叠在一起看能快速判断过拟合和欠拟合。特别是在使用这套源码做自己的数据集时“loss 曲线先降后升”几乎等于过拟合信号可以直接回退到上一个 checkpoint。使用预训练权重微调时我最常遇到的是val loss刚开始就比train loss高很多这种情况往往是数据划分有问题——比如验证集里混入了和训练集相同来源的视频片段导致模型在验证集上记忆了场景看起来精度虚高一旦部署到真实新场景就崩溃。我一般会确保训练集和验证集来自不同的拍摄时段或不同人物这样才能证明模型学的是动作而非背景。从那以后我每次跑完一批训练数据都强制走一遍“日志回看 → 找失败样本 → 区分检测/识别责任 → 对比 loss 曲线”的流程而不是只看一个 acc。这套方法在 YOLOv8 MMAction2 的框架里尤其好用因为两个模型的优化方向完全不同混在一起看指标问题出在哪根本说不清楚。希望帮到你。本文还有配套的精品资源点击获取
返回列表