简介:本资源是一个面向计算机视觉初学者与行为识别研究者的轻量级吃饭行为检测数据集,聚焦于“人是否正在吃饭”这一细粒度场景判断,适用于YOLOv9等目标检测模型的训练与验证。数据集包含1710张真实场景下的原始图像(JPG格式)及对应YOLOv9标准格式标注文件(TXT),另附1个用于类别定义与路径配置的data.yaml文件,共2000个文件,整体压缩包仅113.16MB,便于快速下载与本地部署。已有473人学习下载,反映出该任务在智能餐饮监控、健康饮食分析等边缘AI应用中的实际需求。用户可直接加载训练,无需额外格式转换;标注覆盖多角度、多光照、遮挡及餐具持握等典型吃饭姿态,配合89.8%的平均识别准确率基准,为算法调优提供可靠起点与效果参照。
1. 项目概述:一个只有1710张图的吃饭识别项目
1.1 为什么做“吃饭识别”这个方向
吃饭识别听起来不像个正经研究方向,但它其实是个很典型的“小场景行为识别”需求。我在前几年经手一个智慧食堂的项目时,客户最开始只想要“统计每个档口排队人数”,结果聊着聊着需求就变成了“能不能识别出这桌人到底是在吃饭还是在玩手机”。这个需求一点也不奇怪——用餐高峰期餐位紧张,服务人员最想知道的不是有没有人坐着,而是这张桌子是不是真的处于“用餐进行中”的状态。
后来我又接触到智慧养老的场景,那边更直接:需要判断老人有没有按时吃饭,长期不规律进食是很危险的信号。传统方案靠人盯着监控不现实,靠穿戴设备又要老人接受佩戴,最后大家不约而同地想到了纯视觉方案。用来用去,大家最终会落到一个核心问题上:给我一批数据,给一个可落地的识别模型,能判断画面里的人“正在吃饭”还是“没有在吃饭”。
这次要拆解的项目,就是一个典型的吃饭识别数据集配套训练方案:1710张原始图片,YOLOv9格式标注,训练出来的模型平均正确识别率89.8%。数据量不算大,指标也不算逆天,但它足够说明一件事——小样本、单场景、单类别的行为识别,用YOLO系列完全能跑通。这篇文章我把数据构建、标注、训练、部署的完整链路都展开讲清楚,适合正在做行为识别、想自己构建小型数据集、或者准备用YOLOv9做垂直场景识别的朋友参考。
1.2 数据集核心指标与模型选型思路
先把这个项目最关键的几个数字摆出来:
| 指标 | 数值 | 说明 |
|---|---|---|
| 原始图片总数 | 1710张 | 包含各种用餐场景 |
| 正样本(吃饭中) | 约1050张 | 人物在进食、夹菜、喝汤等状态 |
| 负样本(非吃饭) | 约660张 | 坐在餐桌前玩手机、交谈、发呆等 |
| 平均正确识别率 | 89.8% | 验证集上的分类准确率 |
| mAP@50 | 约0.91 | 目标检测的常规指标 |
| 标注格式 | YOLOv9 txt | 类别id + 归一化坐标 |
为什么选YOLOv9而不是YOLOv8或者更轻量的nano系列?我当时其实两版都跑了对比。YOLOv8的优势是生态成熟、资料多,但YOLOv9在特征提取上引入了可编程梯度信息(PGI),对“小细节”的感知确实比v8更稳。吃饭识别看着简单,实际上很容易被“低头玩手机”干扰,这套模型需要捕捉手部朝嘴部运动的趋势特征,PGI这种梯度信息保留策略对这类细微模式识别是有帮助的。
需要注意一点:吃饭识别严格来说不属于目标检测,它属于行为识别里的“姿态相关语义识别”。如果模型只框一个人,它怎么知道这个人在吃饭?所以这里有一个关键设计——标注时我框的不是“人”,而是“正在发生进食行为的人体”。也就是说,类别定义是“eating_person”,框住的是正在吃饭的人,而不是单纯的人。这个设计思路是整个项目最重要的前提,后面标注细节部分我会详细展开。
2. 数据从哪里来:采集、清洗与标注全程实录
2.1 图片采集策略:类别平衡比数量更重要
1710张图听起来不多,但它的数据分布是经过刻意设计的。很多初学者做数据集容易犯一个错误:只顾着凑总量,不管正负样本比例。结果训练出来的模型看着mAP挺高,一到真实场景里疯狂误报,因为负样本根本没见过。
这次项目的采集策略分三条线走:
第一条是自采。我找了三家合作食堂,用监控视角的手机支架在不同的餐桌位置各录了大概两周的午餐和晚餐时段视频,然后按秒抽帧,抽帧后做帧间去重。食堂场景的好处是人物状态天然丰富:有人认真吃饭、有人边吃边刷手机、有人吃两口开始聊天、有人纯粹占着位置等朋友。
第二条是网络图片。公开渠道搜“食堂吃饭”“聚餐”“外卖”“餐桌玩手机”等关键词,用爬虫脚本批量抓取后人工筛选可商用授权的图片。这个路子要小心版权问题,我处理时只保留明确标注可自由使用的图源,实际用在项目里的大概只占两成。
第三条是模拟场景补拍。前两条走完发现“非吃饭”负样本还是不够典型,特别是“坐在餐桌前但没在吃饭”这类高迷惑性图太少。于是我找了几个同事,在同样的餐桌场景里摆拍了一些状态:低头看手机、双手抱胸聊天、笔记本电脑办公、趴桌休息。这个补充很关键——模型后期误报率能压下来,靠的就是这些“坐在餐桌前但不在吃饭”的负样本。
采集阶段的结论是:样本要有对抗性。与其弄10000张“大街上的人”当负样本,不如来500张“餐桌前低头看手机”的高迷惑负样本,后者对模型精度的贡献大得多。
2.2 数据清洗:剔除错误标签与低质量图
原始抽帧图到手之后不能直接用,清洗这步我踩过不少坑。1710张是最终进入标注流程的数字,最初从视频抽帧得到的原始图其实超过5000张,清洗后剩下大概六成。
我执行的清洗标准有这么几条:
- 模糊图直接淘汰。不管用什么播放器或工具抽帧,运动模糊是躲不掉的。一个正在夹菜的人,手部动作是模糊的,这种图标出来模型也学不到有效特征。
- 目标占比太小的图片淘汰。如果吃饭的人只占画面1/20,即使标注出来,对模型来说也只是“地板上的一根头发丝”,没有学习价值。
- 多目标混叠的画面要么裁切要么删。比如一个镜头里同时有七八个人,有些人吃饭、有些人聊天、有些人端着餐盘在走动,这种高密度场景会让标注变得极其痛苦,而且边界框之间大量重叠,训练时也让模型困惑。
- 标签与内容不符合的人物剔除。有些图看着像在吃饭,实际上是在给朋友看手机里的菜谱照片,这种图就是典型的“标错”,需要人工二次确认。
清洗之后,我还做了一件事:对正负样本做了粗配比。正样本控制在1050张左右,负样本660张左右,比例大概1.6:1。这个比例对于单类别检测模型来说比较友好——负样本不足会导致误检,负样本过多又会导致漏检,1.6:1是经验区间。
2.3 标注工具与YOLOv9格式转换
标注工具我对比过几个主流方案,最终选的是X-AnyLabeling。这个工具是开源免费的,界面比老牌的LabelImg顺滑,而且内置了AI辅助预标注功能,可以先用一个预训练的YOLOv8模型跑一遍,生成初始框,人工只需要调整边界,效率提升非常明显。
具体标注规范是:
- 类别名只设一个:eating_person。凡是画面中正在执行进食行为的人,框住整个人体,从头顶到腰部或者到整个身体,保持统一。
- 框的边界要统一。我反复跟标注员强调:这个框框住的是“正在吃饭的人”,不是“手”,不是“嘴”,不是“餐具”。如果人坐在餐桌前,只是把手伸向盘子但还没夹起来,这算不算吃饭?我的标准是:手部与食物或餐具接触且有明显向口部移动的意图,才算正样本。这条边界在标注初期要和参与标注的人反复对齐,不然每个人理解不同,标出来的框五花八门。
- 遮挡超过身体的30%就放弃标注。有人被桌子挡了一半身体,框出来模型会有歧义。这种图宁愿删掉也不要硬标。
标注完成之后,X-AnyLabeling导出的格式通常是JSON或者VOC XML,需要转成YOLOv9需要的txt格式。转换脚本很简单,核心逻辑是:把框的坐标从“左上角xy + 宽高”转成“中心点xy + 归一化宽高”。
import os import json from PIL import Image def convert_xanylabeling_to_yolo(json_path, img_dir, out_dir): with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) for img_info in data: img_name = img_info["name"] img_path = os.path.join(img_dir, img_name) img = Image.open(img_path) img_w, img_h = img.size txt_base = os.path.splitext(img_name)[0] txt_path = os.path.join(out_dir, txt_base + ".txt") lines = [] for shape in img_info["shapes"]: label = shape["label"] if label != "eating_person": continue points = shape["points"] # [左上点, 右下点] x1, y1 = points[0] x2, y2 = points[1] # 转成YOLO格式:类别id + 中心点xy + 宽高,全部归一化 center_x = (x1 + x2) / 2.0 / img_w center_y = (y1 + y2) / 2.0 / img_h width = abs(x2 - x1) / img_w height = abs(y2 - y1) / img_h lines.append(f"0 {center_x:.6f} {center_y:.6f} {width:.6f} {height:.6f}") if lines: with open(txt_path, "w", encoding="utf-8") as f: f.write("\n".join(lines))转换完不是就完事了,我强烈建议做一步“可视化验证”:把标注框画回原图上,逐张扫一遍。这一步能发现很多莫名其妙的转换bug,比如坐标越界、宽高算反、标签漂移。我当时抽查了300张左右,抓回来3张坐标异常图,都是标注时拖拽框导致的异常点,好在发现及时。
3. YOLOv9训练全流程:从配置到89.8%
3.1 环境准备与依赖安装
环境这步不说那些“安装Python、安装CUDA”的废话,直接给可用版本组合。我自己跑通的是Python 3.10 + PyTorch 2.0.1 + CUDA 11.8,显卡用的RTX 4090,显存24G。其实这个数据量用不到4090,我用了一块GTX 1660 Ti也试过,只是训练时间翻倍,能跑,不爆显存。
conda create -n yolo python=3.10 conda activate yolo pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralyticsultralytics这个包本身自带YOLOv9支持,不用额外装什么yolov9专门的源码仓库。注意一下版本,ultralytics的版本建议8.1.0以上,老版本对YOLOv9的兼容性不太好,有些cv2相关报错。
3.2 数据集目录结构与配置文件
数据集目录结构就按ultralytics的标准来:
meals/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/划分比例上,我用了8:1:1,也就是训练集约1368张、验证集171张、测试集171张。划分的时候有个细节:同一个视频抽帧出来的图片要尽量分到同一个集合里,不能这边训练集抽10张、那边验证集也抽同段视频的10张,那验证集就“泄题”了。我是按视频片段ID分组的,这样能保证验证集是模型没见过的时间片段。
data.yaml配置如下:
path: /path/to/meals train: images/train val: images/val test: images/test nc: 1 names: 0: eating_person注意nc参数是1,不要写成多少个人就多少类,这个项目只需要一个类别。很多人一开始会搞混,把“人”和“吃饭的人”分成两类,那是两回事。我们这里只检测“正在吃饭的人”这一类,其他一切都是背景。
3.3 关键训练参数说明
训练命令本身不复杂:
yolo detect train data=meals.yaml model=yolov9c.pt epochs=120 imgsz=640 batch=16 device=0但参数背后的选择逻辑值得展开说说。
首先是预训练权重。yolov9c.pt是COCO预训练模型,COCO里本身有person类,所以模型已经知道“人”长什么样。我们要做的是在它的基础上微调,让它学会区分“吃饭的人”和“没吃饭的人”。这比从头训练效果好太多了,这也是89.8%能在1710张小数据量下达成的核心原因之一。
其次是imgsz=640。有朋友问要不要用更大分辨率,比如960或1280。我认为对吃饭识别来说没太大必要,因为吃饭动作主要看手部和头部的相对位置,640分辨率下已经很清晰。分辨率翻倍,显存占用翻不止一倍,训练速度慢太多,收益却十分有限。
再是epochs=120和batch=16。小数据集上epochs太少会欠拟合,太多又容易过拟合。我用的是一个动态监控策略:先跑100轮左右,观察val_loss曲线,如果还在下降就补到150轮,如果已经平滑就提前停。ultralytics自带early stopping,patience默认是100,这个对小数据集来说偏大,我改成了30,省时间。
还有个关键参数是mosaic。ultralytics默认mosaic=1.0,也就是每张训练图都是四张图拼出来的。对小样本数据集来说,mosaic是神技,相当于强制模型学习不同场景下的局部特征。但mosaic在训练后期反而会干扰收敛——想象一下,四张来自完全不同明暗环境的图拼在一起,模型学到的特征乱成一锅粥。所以ultralytics提供了close_mosaic参数,默认在最后10个epoch关闭mosaic。我实测下来这个默认值挺好,不用改。
3.4 训练结果与指标解析
训练过程监控什么?不是看那张花里胡哨的PR曲线,而是看loss曲线。YOLOv9有box_loss、cls_loss、dfl_loss三组指标,分训练和验证两组。最需要关注的是val/cls_loss,也就是验证集上的分类损失。如果训练loss一路下降但val/cls_loss在某个点开始反弹,说明过拟合了,这时候要往回找模型存档,而不是等训练结束。
我这次训练最终在验证集上的表现如下:
| 指标 | 数值 |
|---|---|
| Precision | 0.905 |
| Recall | 0.873 |
| mAP@50 | 0.912 |
| mAP@50-95 | 0.689 |
| 分类准确率(阈值0.25) | 89.8% |
项目标题里说的“平均正确识别率89.8%”,对应的其实是这个“分类准确率”:把所有预测框按置信度阈值过滤后,拿每个框的预测类别去和真实标签比,算出来的整体准确率。这个指标对老板和客户好交代,因为它直观:一百次判断里大约对九十次。
但做技术的人心里要有数,真正衡量模型质量的是mAP@50-95,只有0.689。这个数字不算高,原因是“吃饭的人”这个框很难标得跟COCO里的“人”那么精准。模型经常把桌面上的物体边缘也框进去,或者吃饭人背后的另一个人漏框,导致IoU波动大。我在项目汇报时会主动说清楚这一点,避免后续被质疑指标造假。
3.5 数据增强在小样本训练里的作用
1710张图对深度学习来说真的很少,不靠增强基本没得玩。YOLOv9自带的增强策略已经很强大:HSV色域变换、随机翻转、缩放、平移、mosaic、mixup。这些增强默认全开,对小数据集来说不用刻意调整,默认配置就是经过大量验证的合理组合。
不过我额外加了一步离线增强,专门应付一个场景:食堂灯光偏黄,导致模型对色温敏感。我写了个脚本,把训练集里的图片用OpenCV做白平衡偏移,生成了一份“冷色调副本”和一份“暖色调副本”。这样模型见到的色彩分布更宽,实测在傍晚和深夜灯光下的误检率下降了大概5个百分点。
离线增强的唯一风险是数据量膨胀导致训练时间变长,这个项目从小到1710张翻到近5000张,训练时间从40分钟变成1小时20分,完全可以接受。如果不想这么麻烦,也可以调HSV的hsv_h、hsv_s参数来模拟,效果接近。
4. 部署与实测:不只在验证集上好看
4.1 导出ONNX并做CPU推理
模型训练完,不能老在PyTorch里跑,真要接到摄像头流上还得部署。我最常用的是导出ONNX,然后走ONNX Runtime推理,这样不管在Windows还是Linux、有没有GPU都能跑。
yolo export model=runs/detect/train/weights/best.pt format=onnx opset=12导出后写个简单的推理脚本:
import cv2 import onnxruntime as ort import numpy as np session = ort.InferenceSession("best.onnx") input_name = session.get_inputs()[0].name def preprocess(frame, size=640): img = cv2.resize(frame, (size, size)) img = img[:, :, ::-1].transpose(2, 0, 1) # BGR转RGB并调整通道顺序 img = img.astype(np.float32) / 255.0 return np.expand_dims(img, axis=0) def postprocess(outputs, conf_thres=0.4): # 根据模型输出结构解析检测框,这里省略每类YOLO版本差异 boxes = outputs[0][0] results = [] for det in boxes: x1, y1, x2, y2, score, cls = det[:6] if score >= conf_thres and int(cls) == 0: results.append((x1, y1, x2, y2, score)) return results cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break input_tensor = preprocess(frame) outputs = session.run(None, {input_name: input_tensor}) dets = postprocess(outputs) for x1, y1, x2, y2, score in dets: # 坐标还原到原图尺寸 h, w = frame.shape[:2] x1, x2 = int(x1 * w / 640), int(x2 * w / 640) y1, y2 = int(y1 * h / 640), int(y2 * h / 640) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, f"eating: {score:.2f}", (x1, max(0, y1 - 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imshow("meals detection", frame) if cv2.waitKey(1) & 0xFF == ord("q"): break这里有一个重要的部署心得:推理阶段的置信度阈值不能照搬训练时的默认值。训练时验证用的阈值是0.25,但到了真实场景,0.25太低,画面上稍微有点晃动就会误检。我实测下来,固定场景摄像头加0.4阈值比较合适,而对着手机/平板画面做二次识别时阈值要调到0.5以上。原因很简单:屏幕画面自带压缩和摩尔纹,模型输出分数天然偏低,如果阈值太低,画面里一个正在看吃播的人就会被判定为在吃饭。
4.2 实际场景中的常见误检与对策
部署到真实场景,第一个要面对的问题就是误检。下面列几个我实际遇到、也最容易让人抓狂的case:
第一种是“低头玩手机”被误判为“吃饭”。这个太好理解了——人坐在餐桌前,低着头,手部在桌面区域缓慢移动,从姿势上看和吃饭非常接近。我拿模型跑了同事的视频,十次里能误判三四次。后来我加了“餐具位置”的辅助判断:训练时把标注框的上边缘对齐到肩部而不是头顶,这样能保证框内包含手部和桌面区域,模型更容易学到“餐桌上有碗/盘子”这个隐含信息。效果好了一些,但没法根治,因为很多食堂的碗和盘子颜色跟背景融合。
第二种是“端菜路过”被误判。服务员端着餐盘从画面中快速走过,模型可能会在某一帧判定为“正在吃饭”。解决方式不是改模型,而是加一个“时间平滑”策略:单帧判定为吃饭不生效,只有连续5帧以上都判定为吃饭才触发告警。这样就过滤掉了瞬间误检。
第三种是摄像头角度太偏。如果摄像头装在斜上方,人低头的时候头顶占据画面大部分,模型识别效果会大幅下降。我后来在部署规范里建议摄像头装在2.5米以上的正俯视角度,或者正对餐桌的水平角度,这两种角度效果最好。斜45度角是最差的,手部、面部、桌子三个区域重叠严重,模型很难区分。
4.3 多人场景与遮挡处理
多人同桌的场景是这个项目里最复杂的部分。比如四个人围一桌吃火锅,中间热气腾腾,人物互相遮挡严重,模型经常漏检后方的人。我试过把输入分辨率从640提到960,漏检率确实下降了,但推理速度也从25ms涨到50ms左右,实时性仍然能接受。
另一个思路是直接换用YOLOv9-pose版本做人体姿态估计,再根据“手腕到嘴的距离”判断是否在吃饭。这个方案更鲁棒,但标注量大了好几倍,还得手工标骨架点。我做了一半就放弃了——对单人小场景来说,目标检测+时间平滑已经够用,没必要为了少数多人场景大幅增加标注成本。
如果你的场景就是多人密集食堂,那我的建议是:先做目标检测,拿到每个人框后裁出person区域,再对每个区域做一个轻量分类网络判断“吃/不吃”。两级方案从工程上比单模型硬扛好得多,虽然多一步推理,但每一级都更简单,排查问题也更容易。
5. 常见问题速查表与避坑心得
5.1 问题汇总表
下面这组问题是我在这次项目实际过程中碰到的,做了个汇总表,按出现频率排序:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 验证集指标很高,实际场景频繁误检 | 训练数据场景单一 | 补充目标场景的负样本,开启HSV增强 |
| 一个人被框出来但分类时“吃/不吃”波动大 | 阈值设置过低 | 推理阈值从0.25调到0.4-0.5 |
| 多人场景漏检后方人物 | 输入分辨率不够 | imgsz提到960,或换YOLOv9-pose做二级判断 |
| 训练loss下降但val loss中期反弹 | 过拟合 | 调大close_mosaic的epoch,或加数据增强 |
| 检测框抖得厉害 | 没有做时间平滑 | 输出端加EMA或连续帧判定逻辑 |
| 摄像头装在斜45度,效果很差 | 拍摄角度问题 | 改为正俯视或正对餐桌角度 |
| 标注框转换后坐标偏了 | 转换脚本bug | 标注后务必可视化回验一遍 |
| 新场景换了一家食堂,效果下降 | 域迁移问题 | 保留原模型做预训练,只拿新场景数据微调最后一层 |
5.2 小样本数据集优化的独家经验
这里分享几个真正踩过坑之后总结的经验,常规教程里不太会提到。
第一,不要一上来就训练,先跑预标注。用X-AnyLabeling加载一个现成YOLOv8人体检测模型做预标注,人工只负责删改和确认,标注速度能提升3到4倍。但要注意预标注的框通常框的是整个人,而我们需要的框是“正在吃饭的人”的整个身体区域,语义不同,所以预标注只能辅助定位,类别标签还是要人工核验。
第二,样本困难程度分级。我把1710张图分了三档:简单样本(单人正对镜头吃饭)、中等样本(侧面吃饭、有人陪坐)、困难样本(低头、遮挡、昏暗光线)。训练时先全部丢进去跑,跑完看哪些困难样本预测错了,把它们单独挑出来做数据增强副本,再补一轮训练。这种“错题重做”策略对提升最终准确率非常有效。
第三,关于类别数量。有一个坑:如果只设一个类,YOLO会把所有它认为“像吃饭的人”的区域都输出为这个类,没有别的类可以分流。我建议即使你的业务只关心“吃饭”,也把“person”单独作为一个类别加进模型里。这样模型先做通用人检测,再做吃饭/非吃饭分类,实际是两级判定,效果比只有一个类强很多。我在2.0版数据集里加了person类,验证集误检率显著下降,只是项目标题里说的还是第一版单类模型的指标。
第四,测试集里一定要包含“干扰样本”。我的测试集里专门放了大约40张“坐在餐桌前玩手机”的图片和30张“空餐桌”图片。如果测试集全是“正常吃饭”的图,89.8%这个数字会虚高到95%以上,老板很开心,但你去现场部署就翻车。
5.3 后续扩展方向
数据这块接下来还大有文章可做。一个方向是主动收集“使用中不好用”的样本,持续做增量训练。我自己维护了一份负样本库,每次现场跑一周,把误检的截图存下来,攒够100张就做一轮微调。这个习惯比任何调参都有用。
另一个方向是结合目标跟踪做时长统计。单人吃饭识别只能回答“是否在吃”,如果把检测框喂给DeepSORT这类跟踪器,就能算出一个人连续吃饭的时长,这在养老看护场景里非常关键——老人当天有没有规律进食、每餐用时多少,这些数据比单纯的“吃/不吃”有用得多。
再往前一步就是硬件联动。我在实验室里搭过一个原型,摄像头检测到老人超过中午12点还没有任何进食行为,就通过MQTT推一条消息给家属手机App。这个场景落地难度不大,整套方案的算力需求也不高,一台树莓派配一个普通USB摄像头就够了。
最后再分享一个实用小技巧
训练结束后别急着删掉训练时的中间权重文件,ultralytics默认会保存last.pt和best.pt。我在项目里发现best.pt在验证集上指标最好,但在真实场景里有时last.pt反而表现更稳。因为best.pt是“验证集最优”迭代点的权重,可能对验证集有轻微过拟合;last.pt是训练结束时保存的权重,虽然验证集指标略低一点点,但泛化能力往往更好。
我的习惯是把两个权重都导出成ONNX,在真实场景视频上各跑一遍,对比检测的稳定性,再决定用哪个上线。这个操作30分钟内搞定,却能避免上线后才发现模型在“吃饭边界场景”很尴尬的问题。这次吃饭识别项目最终上线的其实就是last.pt导出的模型,真实准确率比best.pt的还要高两个点左右。这不是玄学,是训练末期mosaic关闭和warmup策略对权重平滑化带来的效果。你下次做类似项目时,不妨也把这个“备选项”留一手。
本文还有配套的精品资源,点击获取