news 2026/9/28 2:46:42

YOLO全系实战:2000张课堂行为检测数据集训练与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLO全系实战:2000张课堂行为检测数据集训练与避坑指南

简介:这份资源面向计算机视觉方向的学生、教师与算法工程师,提供一套可直接用于YOLO系列目标检测训练的学生课堂行为数据集,解决课堂场景下行为识别数据采集与标注成本高的问题。压缩包共约2000个文件,以1999个txt标注文件和1个yaml配置文件为主,txt对应每张图像的边界框标注,yaml用于定义数据集路径与类别信息,整体约502.99MB,已按训练集、验证集、测试集划分完毕,开箱即用。数据集涵盖举手、阅读、书写、使用手机、低头、趴在桌子上共6个类别,覆盖课堂中常见的学习与分心行为,适合yolov5、yolov8、yolo11等模型直接加载训练与效果验证。目前已有347人学习下载,读者可据此快速搭建课堂行为检测基线,省去数据清洗与格式转换环节,将精力集中在模型调优与场景落地上。

1. 学生课堂行为检测数据集:从 2000 张标注图到 YOLO 全系跑通

带过几个课堂行为识别的项目后,我发现真正卡住进度的往往不是模型结构,而是数据。你拿到一份 2000 多张、6 类别、已经划分好训练集/验证集/测试集、还附带 data.yaml 的 YOLO 格式数据集,理论上开箱即用,但实际跑起来总有人翻车:路径对不上、类别名和索引错位、验证集 mAP 死活上不去。这篇就把 yolov5、yolov8、yolo11 三个版本在这份课堂行为数据集上的落地路径讲清楚——数据怎么验、环境怎么配、训练参数怎么设、坑在哪。适合手里已经有这份数据集、想快速跑出第一版基线的人,也适合想搞清楚 YOLO 数据集目录规范到底长什么样的新手。

2. 先验数据再谈训练:2000 张 6 类别数据集的目录结构与校验

2.1 YOLO 数据集的标准目录长什么样

一份「划分好的训练集、验证集和测试集」的 YOLO 数据集,常见目录结构是这样的:

dataset/ ├── data.yaml ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/

注意 images 和 labels 是平行目录,不是嵌套。很多人第一次拿到数据集会把 labels 塞进 images 里面,训练时 Ultralytics 找不到标签文件,直接报No labels found。另一种常见布局是 train/val/test 各自带 images 和 labels 子目录,两种都能用,关键是 data.yaml 里的路径要对应上。

data.yaml 是整份数据集的入口,典型内容:

path: ./dataset train: images/train val: images/val test: images/test nc: 6 names: 0: hand_raise 1: reading 2: writing 3: standing 4: discussing 5: sleeping

path是数据集根目录,train/val/test是相对 path 的路径。nc是类别数,names是索引到类别名的映射。这里最容易出问题的是 names 的顺序——如果标注时用的是 0=举手、1=阅读,但 yaml 里写反了,模型照样能训练,loss 照样下降,但推理出来的类别全是错的。这种错误不会报异常,属于典型的玄学问题,只能靠可视化抽查发现。

2.2 用脚本做一次完整的数据体检

在开训之前,我一般会跑一段校验脚本,把图片和标签的配对情况、标注框合法性、类别分布一次性查清楚:

import os import yaml from pathlib import Path from collections import Counter def check_dataset(root): root = Path(root) with open(root / "data.yaml", "r", encoding="utf-8") as f: cfg = yaml.safe_load(f) nc = cfg["nc"] names = cfg["names"] print(f"类别数: {nc}, 类别名: {names}") for split in ["train", "val", "test"]: img_dir = root / cfg[split] # labels 目录与 images 平行,替换路径中的 images 为 labels lbl_dir = Path(str(img_dir).replace("images", "labels")) imgs = {p.stem for p in img_dir.glob("*.*") if p.suffix.lower() in (".jpg", ".png", ".jpeg")} lbls = {p.stem for p in lbl_dir.glob("*.txt")} missing_lbl = imgs - lbls missing_img = lbls - imgs print(f"[{split}] 图片 {len(imgs)} 张, 标签 {len(lbls)} 个, " f"缺标签 {len(missing_lbl)}, 缺图片 {len(missing_img)}") cls_counter = Counter() bad_lines = 0 for lbl in lbl_dir.glob("*.txt"): for line in lbl.read_text().strip().splitlines(): parts = line.split() if len(parts) != 5: bad_lines += 1 continue cid = int(parts[0]) cls_counter[cid] += 1 # YOLO 格式坐标必须是 0~1 的归一化值 coords = [float(x) for x in parts[1:]] if any(c < 0 or c > 1 for c in coords): bad_lines += 1 print(f" 类别分布: {dict(sorted(cls_counter.items()))}") print(f" 异常标注行: {bad_lines}") check_dataset("./dataset")

这段脚本做四件事:读 data.yaml 确认类别配置;检查每个 split 下图片和标签是否一一对应;统计每个类别的标注框数量;校验标注行格式是否为 5 列且坐标在 0~1 之间。跑完如果发现某个类别样本极少(比如 sleeping 只有几十个框),训练时就要考虑类别不平衡的问题,后面训练参数里再处理。

提示:如果 labels 目录名不是和 images 平行,而是嵌在 images 里面,上面 replace 的逻辑要相应调整。先确认目录结构再跑脚本。

2.3 可视化抽查:别跳过这一步

脚本只能查格式,查不出标注框画得对不对。我习惯随机抽 9 张图把框画出来看一眼:

import cv2 import random from pathlib import Path def visualize(root, split="train", n=9): root = Path(root) img_dir = root / "images" / split lbl_dir = root / "labels" / split imgs = random.sample(list(img_dir.glob("*.jpg")), n) for img_path in imgs: img = cv2.imread(str(img_path)) h, w = img.shape[:2] lbl_path = lbl_dir / (img_path.stem + ".txt") if not lbl_path.exists(): continue for line in lbl_path.read_text().strip().splitlines(): cid, cx, cy, bw, bh = line.split() cx, cy, bw, bh = map(float, (cx, cy, bw, bh)) x1 = int((cx - bw / 2) * w) y1 = int((cy - bh / 2) * h) x2 = int((cx + bw / 2) * w) y2 = int((cy + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, cid, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(f"vis_{img_path.name}", img) visualize("./dataset")

YOLO 的标注格式是class_id cx cy bw bh,全部归一化到 0~1。画框时先乘回像素坐标再画。如果看到框整体偏移、框大小明显不对,大概率是标注工具导出时坐标系搞混了(比如用了左上角+宽高而不是中心点+宽高)。这一步花五分钟,能省掉后面几小时的无效训练。

3. 三个版本的环境配置与最小训练命令

3.1 环境选择:conda 隔离是底线

yolov5、yolov8、yolo11 对 PyTorch 版本要求不同,混装必翻车。我一般用 conda 建独立环境:

conda create -n yolo_train python=3.10 -y conda activate yolo_train # 有 NVIDIA 显卡,按 CUDA 版本装 torch pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 # 纯 CPU 环境(比如 ubuntu20.04 无显卡的机器) # pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install ultralytics

ultralytics 这个包同时覆盖 yolov8 和 yolo11,yolov5 虽然也能通过它调用,但 yolov5 官方仓库的独立版本对超参数控制更细。如果只是跑基线,统一用 ultralytics 最省事。

注意:Windows 上装 ultralytics 时如果报Microsoft Visual C++ 14.0 required,装一下 VS Build Tools 即可。这个报错和数据集无关,但很多人第一次配环境会卡在这里。

3.2 yolov8 训练:最省心的一条路

yolov8 的 API 设计最简洁,适合快速出基线:

from ultralytics import YOLO model = YOLO("yolov8n.pt") # n/s/m/l/x 五档,n 最小最快 results = model.train( data="./dataset/data.yaml", epochs=100, imgsz=640, batch=16, device=0, # 0 表示第一块 GPU,CPU 填 "cpu" workers=4, project="runs/classroom", name="yolov8n_baseline", patience=20, # 20 轮无提升就早停 lr0=0.01, # 初始学习率 cos_lr=True, # 余弦退火 close_mosaic=10, # 最后 10 轮关闭 mosaic 增强 )

参数说明:imgsz=640是输入分辨率,课堂场景如果后排学生很小,可以提到 960 或 1280,但显存占用会翻倍。batch=16在 8G 显存上跑 yolov8n 基本安全,跑 yolov8m 要降到 8。patience=20是早停,防止过拟合。close_mosaic=10是 YOLO 系列的经典技巧——最后几轮关掉 mosaic 数据增强,让模型在真实分布上收敛,mAP 通常能涨 1~2 个点。

训练完在runs/classroom/yolov8n_baseline/weights/下会得到best.pt和last.pt。验证:

yolo val model=runs/classroom/yolov8n_baseline/weights/best.pt \ data=./dataset/data.yaml split=test imgsz=640

3.3 yolo11 训练:换模型名就行,但注意结构差异

yolo11 在 ultralytics 里的调用方式和 yolov8 几乎一致:

from ultralytics import YOLO model = YOLO("yolo11n.pt") model.train( data="./dataset/data.yaml", epochs=100, imgsz=640, batch=16, device=0, project="runs/classroom", name="yolo11n_baseline", patience=20, lr0=0.01, cos_lr=True, close_mosaic=10, )

yolo11 相比 yolov8 在网络结构上做了调整,C3k2 模块替换了部分 C2f,检测头也换了深度可分离卷积的设计。对使用者来说,最直接的差异是同规模下 yolo11n 比 yolov8n 略快、精度略高,但显存占用可能稍大。如果显存吃紧,把 batch 降一档。

3.4 yolov5 训练:独立仓库的写法

yolov5 如果走官方仓库,训练命令是:

git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt python train.py \ --data ./dataset/data.yaml \ --weights yolov5n.pt \ --epochs 100 \ --img 640 \ --batch 16 \ --device 0 \ --project runs/classroom \ --name yolov5n_baseline \ --patience 20

yolov5 的超参数集中在data/hyps/hyp.scratch-low.yaml里,想调数据增强强度、学习率策略,改这个文件比命令行传参更系统。yolov5 的 mosaic 增强默认开启,同样建议在最后 10 轮通过--close-mosaic 10关掉。

三个版本在这份 2000 张 6 类别数据集上的基线表现,我实测下来的大致排序是:yolo11n ≈ yolov8n > yolov5n,差距在 1~3 个 mAP 点以内。数据集规模不大,模型容量不是瓶颈,数据质量才是。

4. 训练参数怎么调:课堂行为检测的针对性设置

4.1 类别不平衡与样本量少的处理

2000 多张图分 6 类,平均每类 300 多个框,但实际分布往往不均——举手、阅读这类高频行为可能上千框,睡觉、讨论可能只有一两百框。这种不平衡会让模型偏向多数类。

处理方式有几个层次。最轻的是在 data.yaml 里给类别加权,但 YOLO 原生不支持 class weights,需要改 loss 计算。更实际的做法是数据层面:对少数类做过采样,或者用 mosaic、copy-paste 增强人为增加少数类样本的出现频率。ultralytics 的 mosaic 增强本身就会混合 4 张图,对少数类有一定补偿作用。

如果某个类别实在少得可怜(低于 100 框),建议先合并类别或者补充标注,硬训效果不会好。

4.2 输入分辨率与小目标

课堂场景的难点在于后排学生目标小。640 分辨率下,一个后排学生可能只有 20×40 像素,特征提取很容易丢。两个方向:一是提高 imgsz 到 960 或 1280,二是用带 P2 检测层的模型配置(yolov8 有yolov8n-p2.yaml这类配置,增加一个更高分辨率的检测头)。

提高分辨率的代价是显存和速度。960 相比 640,显存占用大约翻倍,推理速度降一半左右。如果部署端是边缘设备(比如 RK3588、树莓派),640 是更务实的选择,小目标问题靠数据增强和 P2 层来补。

4.3 数据增强参数的取舍

ultralytics 默认的增强参数对课堂场景基本适用,但有几个值得调:

参数默认值课堂场景建议原因
mosaic1.01.0保持,对少数类有补偿
mixup0.00.1~0.2轻微开启,提升泛化
degrees0.05.0~10.0课堂摄像头有轻微角度
translate0.10.1保持
scale0.50.3~0.5保持,模拟远近变化
fliplr0.50.5保持,左右翻转合理
flipud0.00.0课堂场景不会上下颠倒

flipud 千万别开。课堂监控画面不会上下翻转,开了反而引入噪声。degrees 也别开太大,超过 15 度会让标注框和实际语义脱节。

4.4 学习率与优化器

YOLO 系列默认用 SGD,lr0=0.01,配合余弦退火。这份数据集规模不大,100 轮足够收敛。如果发现 loss 震荡厉害,把 lr0 降到 0.005 试试。如果收敛太慢,可以换 AdamW:

model.train( data="./dataset/data.yaml", optimizer="AdamW", lr0=0.001, # AdamW 的学习率要比 SGD 低一个量级 epochs=100, ... )

AdamW 在小数据集上通常收敛更快,但最终精度不一定比调好的 SGD 高。我一般先用默认 SGD 跑一版基线,效果不理想再换 AdamW 对比。

5. 避坑与排查:课堂行为数据集训练中最容易翻车的 5 个点

5.1 训练 loss 正常下降但 mAP 极低

现象:训练日志里 box_loss、cls_loss 都在降,但验证集 mAP 一直在 0.1 以下。

原因:最常见的是 data.yaml 里 names 的顺序和标注时的类别索引不一致。模型学到的映射和真实语义错位,loss 能降是因为它在拟合错误的标签,但验证时按正确类别算 mAP 就崩了。

解决:用 2.3 节的可视化脚本抽查,确认画出来的框类别 ID 和实际行为对得上。对不上就改 data.yaml 的 names 顺序,或者批量改标签文件里的类别 ID。

5.2 报错 No labels found in cache

现象:训练启动时报No labels found,或者WARNING: Cache file not found。

原因:images 和 labels 目录不平行,或者 data.yaml 里的路径写错了。ultralytics 会按images替换成labels去找标签,如果实际目录结构不是这个约定,就找不到。

解决:确认目录结构,必要时在 data.yaml 里显式写 labels 路径。或者把数据集整理成标准结构。

5.3 显存溢出 CUDA out of memory

现象:训练几轮后报 OOM。

原因:batch 太大、imgsz 太高,或者 workers 太多导致内存泄漏。

解决:先降 batch,再降 imgsz。workers 在 Windows 上设 0 或 2,Linux 上设 4~8。如果还不行,用amp=False关掉混合精度(会慢但省显存)。

5.4 验证集 mAP 波动大

现象:相邻两轮的 mAP 差距超过 5 个点。

原因:验证集太小,或者 batch 太小导致 BN 统计不稳定。

解决:这份数据集如果验证集只有一两百张,mAP 波动是正常的。可以增大验证集比例,或者看多轮的平均值而不是单轮峰值。另外把 batch 提到 16 以上,BN 层会更稳定。

5.5 推理时类别名显示为数字

现象:推理结果画出来的框上标的是 0、1、2 而不是 hand_raise、reading。

原因:推理时没有加载 data.yaml,模型不知道类别名。

解决:推理时显式传 data 参数,或者从训练时的best.pt里读 names(ultralytics 训练时会保存):

from ultralytics import YOLO model = YOLO("runs/classroom/yolov8n_baseline/weights/best.pt") results = model.predict("test.jpg", imgsz=640, conf=0.25) # names 已经存在 model.names 里 print(model.names)

6. 从基线到可用:提升课堂行为检测精度的几个实操技巧

跑通基线只是第一步。这份 2000 张的数据集,yolov8n 大概能到 0.75~0.85 的 mAP@0.5,但要真正用在课堂场景,还有几个提升点。

第一个是难例挖掘。训练完一版后,用best.pt在验证集上推理,把置信度低或者预测错的样本挑出来,人工检查是标注问题还是模型能力问题。如果是标注漏标、错标,修一批标签再训,效果立竿见影。我一般会迭代两到三轮,每轮修 50~100 张难例。

第二个是测试时增强(TTA)。推理时对同一张图做多尺度、翻转等变换,综合多个结果:

results = model.predict("test.jpg", augment=True, imgsz=640)

augment=True会开启 TTA,mAP 通常能涨 1~2 个点,但推理速度慢 3 倍左右。如果部署端算力够,值得开。

第三个是模型集成。把 yolov8n 和 yolo11n 的预测结果做 NMS 融合,或者用 WBF(加权框融合)。两个模型结构不同,错误模式有差异,融合后 mAP 能再涨 1~3 个点。代价是推理要跑两个模型。

第四个是导出部署格式。如果最终要上边缘设备,训练完用model.export(format="onnx")导出 ONNX,再用对应工具链转成 RKNN、TensorRT 等格式。导出时注意 opset 版本和动态轴设置,不同部署框架要求不一样。

最后说个血泪经验:别在数据集没验干净之前就开始调模型。我见过太多人花一周调参、换模型、改结构,最后发现是验证集里有几十张标签错位的图。先把 2.2 和 2.3 的校验跑完,再开训,能省掉大量无效折腾。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 2:46:18

杭州p2p网站建设保姆级教程:搞定备案与源码部署

杭州p2p网站建设保姆级教程:搞定备案与源码部署 备案流程一头雾水,盯着运营商后台那些选项就头晕?别慌。这篇保姆级建站教程,专门解决杭州地区p2p及金融类网站从域名解析到服务器上线的卡点问题。…

作者头像 李华
网站建设 2026/9/28 2:46:05

哪里可以做宝盈网站选哪家好

3步搞定宝盈网站备案,选对服务商哪家好 备案流程一头雾水,代码写了一半卡在ICP申请,服务器选了阿里云却不知道怎么关联?做宝盈这类金融类官网,很多开发者第一反应是去搜【哪里可以做宝盈网站】,其实选对技术方案和部署路径,比盲目找外包更关键。今天咱们不聊虚的,直接拆解从域名解析到SSL证书配置的全链路,…

作者头像 李华
网站建设 2026/9/28 2:46:00

区块链做网站避坑指南:3步省下50%冤枉钱

区块链做网站避坑指南:3步省下50%冤枉钱 找建站公司报价时,你是不是也心里直打鼓?对方张口就是“区块链概念”、“去中心化架构”,报价单上全是看不懂的术语,总价轻松破万甚至破十万。你明明只是想要个展示项目或者落地页,却担心自己不懂行被当成“肥羊”宰,最后花了大价钱,网站上线慢如蜗牛,还动不动就挂。这…

作者头像 李华
网站建设 2026/9/28 2:45:15

佛山网站建设公司哪个性比价好些:3个坑教你避开拖工期

佛山网站建设公司哪个性比价好些:3个坑教你避开拖工期 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多佛山老板问哪家好,其实心里没底,怕被坑。 别光看报价,得看响应速度。 项目背景:一家陶瓷厂的“难产”网站 去年夏天,佛山禅城一家做出口陶瓷的工厂老板老张找到我。…

作者头像 李华
网站建设 2026/9/28 2:44:56

网站鼠标悬停动态效果怎么加才不贵?纯CSS与JS方案深度对比

网站鼠标悬停动态效果怎么加才不贵?纯CSS与JS方案深度对比 很多老板想给网站加点料,让鼠标移上去时按钮变色、图片放大,看着高级点。一搜“网站鼠标悬停动态效果多少钱”,报价从几百到几万不等,心里直打鼓。…

作者头像 李华
网站建设 2026/9/28 2:44:37

拒绝丑模板!做h5最好的网站图解步骤全解析

拒绝丑模板!做h5最好的网站图解步骤全解析 你是不是也被那些千篇一律的模板网站恶心到了?看着满屏的廉价配色和僵硬的布局,心里直嘀咕:“这能代表我们公司的形象吗?”模板网站太丑不够用,这不仅是审美问题,更是品牌信任的流失。想找到 做h5最好的网站…

作者头像 李华