☰
YOLOv5人脸表情识别毕设源码实战:训练调参、推理导出与避坑指南
2026/10/7 1:24:01 网站建设 项目流程

简介:这份资源是面向高校学生与Python初学者的计算机视觉实战项目包,聚焦Yolov5目标检测框架下的人脸识别与人脸表情识别两大任务,可直接用于毕业设计、课程设计或技能进阶练习。压缩包共收录2000个文件,以1929个txt标注与说明文件、39个Python源码、20个yaml配置、6个sh脚本及若干md、json文件为主,整体约167.89MB,涵盖数据配置、模型训练、推理导出等完整流程。项目源码经过严格测试,可一键运行,省去环境搭建与调试的重复劳动。目前已有372人学习关注,说明其在同类毕设选题中具备一定参考价值。读者可从中获得Yolov5训练与推理脚本、人脸检测与表情分类的工程化实现思路、配置文件与依赖说明,以及可复用的目录组织方式,便于快速理解项目结构并在此基础上完成二次开发或论文撰写。

1. 从一份能跑通的 YOLOv5 人脸表情识别源码说起

毕业设计选题里,人脸识别和人脸表情识别几乎是每年都被抢的方向,但真正让人头疼的不是选题,而是从零搭一套能跑通、能写进论文、还能应付答辩演示的代码。这份基于 YOLOv5 + Python 的人脸识别、人脸表情识别项目源码,解决的就是这个落地问题:它把数据加载、模型训练、推理导出这几条链路都串好了,目录里能看到train.py、export.py、dataloaders.py、general.py这些核心文件,还有optimizer_config.json这种训练配置。适合谁?正在做毕业设计、课程设计,需要一份结构完整、能直接跑起来再改的工程的同学。下面我按自己拆包复现的顺序,把这份源码怎么用、参数怎么调、哪里容易翻车讲清楚。

2. YOLOv5 做表情识别的选型逻辑与工程结构

2.1 为什么用 YOLOv5 而不是纯分类网络

人脸表情识别本质上是分类任务,很多人第一反应是 ResNet、VGG 这类分类骨干。但这份源码选了 YOLOv5,原因在于它把检测和分类合在一条链路里:先用检测头框出人脸区域,再对框内区域做表情类别判断。这样做的好处是,当一张图里有多张人脸时,不需要额外写人脸检测逻辑,YOLOv5 的检测输出直接就是后续分类的输入。

从工程角度看,YOLOv5 的仓库结构成熟,dataloaders.py负责数据加载和增强,general.py放通用工具函数,train.py是训练入口,export.py负责导出部署格式。这套结构对毕业设计很友好,因为论文里要写的「数据集构建」「模型训练」「结果分析」三块,都能在代码里找到对应位置,不用自己从零设计模块划分。

常见做法是:把表情类别当成 YOLO 的类别标签,比如 angry、happy、sad、neutral 等,每张人脸框对应一个类别。这样训练时 YOLO 的损失函数会同时优化框的位置和类别概率。需要注意的是,表情识别的类间差异比通用目标检测小得多,所以数据增强策略和超参数要针对性调整,不能直接套 COCO 那套配置。

2.2 源码目录里每个文件的实际作用

拆包后先别急着跑,花十分钟把文件职责理清楚,后面改代码会省很多事。下面这张表是我按实际调用关系整理的:

文件作用改动频率
train.py训练主入口,解析参数、构建模型、启动训练循环低,主要改命令行参数
dataloaders.py数据集加载、图像增强、batch 组装中,换数据集时要改
general.py通用工具,含 NMS、坐标转换、日志等低,一般不动
export.py模型导出为 ONNX、TorchScript 等格式低,部署时才用
optimizer_config.json优化器超参数配置中,调参时改
README.md项目说明和基础用法低

train.py里通常会暴露--data、--weights、--epochs、--batch-size、--img-size这些参数。--data指向数据集配置文件,里面写清楚训练集、验证集路径和类别名。--weights可以加载预训练权重,这对小数据集表情识别很关键,因为从零训练容易过拟合。

dataloaders.py是换数据集时最需要关注的文件。它里面定义了数据读取方式、标签格式解析、以及 mosaic、mixup 这类增强。表情识别的人脸区域通常比较规整,mosaic 增强可能会把不同表情的人脸拼在一起,导致标签语义混乱,所以实际训练时我一般会把 mosaic 概率调低或者关掉。

2.3 环境准备与依赖安装

跑之前先把 Python 环境弄干净。建议用 conda 建独立环境,避免和系统里的包冲突。Python 版本选 3.8 或 3.9,太新的版本有些依赖轮子还没跟上。

# 创建独立环境,Python 3.8 兼容性最稳 conda create -n face_yolo python=3.8 -y conda activate face_yolo # 安装 PyTorch,根据自己 CUDA 版本选对应命令 # 这里以 CUDA 11.3 为例,没有 GPU 就用 cpu 版本 pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 -f https://download.pytorch.org/whl/torch_stable.html # 安装项目其余依赖 pip install -r requirements.txt

这段命令的逻辑是:先隔离环境,再装深度学习框架,最后补项目依赖。torch和torchvision版本要匹配,否则会出现ImportError或者算子不兼容。没有 GPU 的话把+cu113换成+cpu,训练会慢很多,但跑通流程没问题。

装完用下面这行验证:

python -c "import torch; print(torch.__version__, torch.cuda.is_available())"

输出里第二个值是True说明 GPU 可用。如果是False但你有显卡,大概率是 CUDA 版本和驱动不匹配,这时候别硬扛,先换成 CPU 版本把流程跑通,再回头解决 GPU 问题。

提示:requirements.txt里如果有版本号写死的包,装不上时先看报错信息里的版本冲突,不要盲目升级所有包。

3. 数据集准备与训练参数配置

3.1 表情数据集的目录结构与标签格式

YOLOv5 要求的数据集格式是每张图对应一个.txt标签文件,每行写类别索引 x_center y_center width height,坐标都是归一化到 0 到 1 之间的值。表情识别的人脸框通常由人脸检测器先跑一遍得到,再人工或自动标注表情类别。

目录结构一般长这样:

datasets/ face_expression/ images/ train/ 0001.jpg 0002.jpg val/ 0100.jpg labels/ train/ 0001.txt 0002.txt val/ 0100.txt

然后写一个数据集配置文件,比如face_expression.yaml:

# 数据集根路径,train.py 会基于这个路径拼接 path: ./datasets/face_expression train: images/train val: images/val # 类别数量和类别名,顺序要和标签里的索引一致 nc: 5 names: ['angry', 'happy', 'sad', 'neutral', 'surprise']

这里nc是类别数,names的顺序必须和标签文件里写的索引严格对应。我见过有人把happy写成索引 0,但标签里 0 对应的是angry,训练 loss 能降但预测全乱,这种坑排查起来很费时间。

标签生成可以用脚本批量处理,核心逻辑是读人脸检测结果,再按表情分类模型或人工标注给类别。如果数据集本身已经带了表情标签,直接转换格式就行。

3.2 训练命令与关键参数含义

数据准备好之后,训练命令本身不复杂,但每个参数都影响结果。下面是一条我常用的训练命令:

python train.py \ --data face_expression.yaml \ --weights yolov5s.pt \ --epochs 100 \ --batch-size 16 \ --img-size 640 \ --optimizer Adam \ --lr0 0.001 \ --mosaic 0.0 \ --project runs/train \ --name exp_face

逐项说明:--data指向数据集配置;--weights加载预训练权重,表情识别数据量通常不大,从预训练开始比从零训练收敛快很多;--epochs 100是训练轮数,小数据集 50 到 100 轮一般够用;--batch-size 16受显存限制,显存不够就降到 8;--img-size 640是输入分辨率,人脸区域小的话可以适当调大,但显存占用也会涨。

--optimizer Adam和--lr0 0.001是优化器和初始学习率。YOLOv5 默认用 SGD,但表情识别这种细粒度分类任务,Adam 收敛更稳。--mosaic 0.0是关掉 mosaic 增强,前面说过,表情识别里 mosaic 容易把不同表情的人脸拼一起,标签语义会乱。

训练过程中重点看两个指标:box_loss和cls_loss。box_loss下降说明人脸框定位在变好,cls_loss下降说明表情分类在变好。如果cls_loss震荡不降,先检查标签类别是否和names对应,再考虑调低学习率。

3.3 优化器配置文件怎么改

optimizer_config.json里通常放的是优化器的细粒度参数,比如权重衰减、动量、学习率调度策略。不同版本的 YOLOv5 这个文件内容不一样,打开后先看结构,别直接覆盖。

常见做法是只改自己需要的字段,比如把weight_decay从默认值调小一点,防止小数据集过拟合:

{ "weight_decay": 0.0005, "momentum": 0.937, "lr0": 0.001, "lrf": 0.01 }

weight_decay是 L2 正则强度,越大正则越强;momentum影响优化器更新方向;lr0是初始学习率;lrf是最终学习率相对于初始学习率的比例,用来做余弦退火。改完保存,重新跑train.py就会生效。如果训练时发现 loss 突然变成 NaN,先把学习率调小一个数量级再试。

注意:改配置文件前先备份一份原始文件,调参调崩了能快速回退。

4. 推理、导出与常见翻车点排查

4.1 用训练好的权重做推理

训练完成后权重默认存在runs/train/exp_face/weights/best.pt。推理可以用 YOLOv5 自带的detect.py,也可以自己写脚本调用。自己写的好处是能把表情识别结果和业务逻辑接起来。

import torch from models.common import DetectMultiBackend from utils.general import non_max_suppression, scale_boxes from utils.augmentations import letterbox import cv2 import numpy as np # 加载训练好的权重 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') model = DetectMultiBackend('runs/train/exp_face/weights/best.pt', device=device) model.eval() # 读取图片并做预处理 img = cv2.imread('test.jpg') img_resized = letterbox(img, 640, stride=32, auto=True)[0] img_resized = img_resized.transpose((2, 0, 1))[::-1] # BGR 转 RGB img_tensor = torch.from_numpy(np.ascontiguousarray(img_resized)).float().to(device) / 255.0 img_tensor = img_tensor.unsqueeze(0) # 前向推理 + NMS 后处理 pred = model(img_tensor) pred = non_max_suppression(pred, conf_thres=0.25, iou_thres=0.45) # 解析结果 for det in pred: if det is not None and len(det): det[:, :4] = scale_boxes(img_tensor.shape[2:], det[:, :4], img.shape).round() for *xyxy, conf, cls in det: label = f'{model.names[int(cls)]} {conf:.2f}' print(label, xyxy)

这段代码的逻辑是:加载权重、预处理图片、前向推理、NMS 去重、坐标还原到原图尺寸。conf_thres=0.25是置信度阈值,低于这个值的框会被丢掉;iou_thres=0.45是 NMS 的 IoU 阈值,控制重叠框的合并程度。表情识别里如果发现同一张脸被框了多次,把iou_thres调低一点。

letterbox做的是保持长宽比的缩放加填充,这样不会让人脸变形。scale_boxes把归一化坐标还原回原图尺寸,方便后续画框或裁剪。

4.2 模型导出为 ONNX 的注意事项

如果毕设要求部署演示,或者要在没有 PyTorch 的环境里跑,导出 ONNX 是常见选择。export.py就是干这个的:

python export.py \ --weights runs/train/exp_face/weights/best.pt \ --include onnx \ --img-size 640 640 \ --batch-size 1 \ --opset 12

--include onnx指定导出格式;--img-size要和训练时一致,否则推理结果会偏;--opset 12是 ONNX 算子集版本,太低有些算子不支持,太高某些推理引擎不兼容,12 是比较稳的选择。

导出后建议用onnxruntime跑一遍验证输出是否和 PyTorch 一致:

import onnxruntime as ort import numpy as np sess = ort.InferenceSession('best.onnx') input_name = sess.get_inputs()[0].name dummy = np.random.randn(1, 3, 640, 640).astype(np.float32) out = sess.run(None, {input_name: dummy}) print(out[0].shape)

如果输出 shape 和预期不符,先检查导出时的--img-size和--batch-size是否和推理时一致。

4.3 避坑与常见问题排查

现象一:训练 loss 一直不降,cls_loss 在某个值附近震荡。原因通常是标签类别索引和names顺序不一致,或者标签文件里有空行、格式错误。解决方法是写个小脚本遍历标签文件,统计每个类别索引出现的次数,和names对照。另外检查标签坐标是否归一化,有人直接把像素坐标写进去,模型根本学不到东西。

现象二:推理时检测框位置整体偏移。原因是预处理和坐标还原不匹配。letterbox缩放后,scale_boxes要用同样的缩放比例还原。如果自己改了预处理逻辑但没改还原逻辑,框就会偏。解决方法是统一用 YOLOv5 自带的letterbox和scale_boxes,不要自己手写缩放。

现象三:GPU 显存够但训练报 CUDA out of memory。不一定是显存真不够,可能是--img-size或--batch-size设太大,也可能是 dataloader 的 worker 数太多导致内存泄漏。先把--batch-size减半试,再检查--workers参数,设成 0 或 2 试试。如果还不行,用nvidia-smi看是不是有其他进程占着显存。

现象四:导出 ONNX 后推理结果和 PyTorch 差很多。常见原因是导出时没设--dynamic,或者 opset 版本和推理引擎不匹配。另外 YOLOv5 的 NMS 后处理如果没一起导出,ONNX 输出的是原始预测,需要自己写后处理。解决方法是先用固定输入尺寸导出,验证一致后再考虑动态轴。

现象五:换了自己的数据集后,验证集指标正常但实际图片预测很差。大概率是训练集和实际场景分布不一致,比如训练集都是正面清晰人脸,实际图片有侧脸、遮挡、光照变化。解决办法是在数据增强里加随机裁剪、亮度对比度扰动,或者补充实际场景的样本。表情识别对光照和姿态很敏感,这一点比通用目标检测更明显。

5. 把这份源码改成能写进论文的进阶技巧

5.1 用混淆矩阵和 PR 曲线补论文实验章节

毕业设计论文里,光有准确率不够,答辩老师通常会问类别不平衡和误判分布。YOLOv5 训练完会在runs/train/exp_face/下生成混淆矩阵和 PR 曲线,直接拿来用就行。如果找不到,可以在验证脚本里手动调val.py,加上--plots参数。

混淆矩阵能看出哪些表情容易被混,比如sad和neutral经常互相误判,这本身就是论文里可以展开分析的点。PR 曲线则能说明在不同置信度阈值下各类别的查准率和查全率,比单一准确率更有说服力。

5.2 调整超参数提升小数据集表现

表情识别公开数据集通常不大,过拟合是常态。除了前面说的关掉 mosaic,还可以做这几件事:把--label-smoothing开到 0.1,让模型不要对某一类过度自信;把--dropout设成 0.2 左右,在全连接层前加随机失活;用--freeze冻结骨干网络前几层,只训练检测头和分类头。

我一般会先跑一组基线,记录mAP@0.5和各类别precision/recall,然后每次只改一个参数,对比指标变化。这样调参有据可查,写论文时也能说清楚每个参数的作用。别一次改好几个参数,不然指标涨了也不知道是谁的功劳,跌了更不知道回退哪个。

5.3 一个我踩过的坑:验证集划分

有次我图省事,直接把训练集随机切了 20% 当验证集,结果验证指标很高,但答辩演示时换了几张新图就翻车。后来才发现,同一个人的多张照片被分到了训练集和验证集,模型其实是在「认人」而不是「认表情」。从那以后我每次划分数据集都强制按人物 ID 分组,同一个人只出现在训练集或验证集其中一边。这个习惯让我后面几次实验的指标都更可信,答辩时被问到泛化能力也能答得上来。

如果你拿到的源码里已经分好了训练集和验证集,先检查一下有没有同人跨集的情况。没有人物 ID 信息的话,至少按图片拍摄时间或来源分组,别用纯随机划分。希望这份拆解能帮你把这份源码真正跑起来、改明白,顺利把毕业设计落地。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询