这篇零基础入门人脸识别的实战教程继续往前走。上一篇讲清楚了环境安装和显卡驱动准备,这一篇直接进入正题:用YOLOv11把“人脸检测”这件事从零跑通,覆盖数据集准备、训练参数配置、训练、验证、测试和预测的完整代码流程,所有内容都在 RTX 5060 上实测过,遇到什么坑、怎么调参、哪些代码可以直接抄,我都写在下面了。适合刚接触目标检测、想用人脸检测做一个实际项目但还没理清流程的人,也适合已经跑通YOLOv8/v10、想快速迁移到YOLOv11的读者。
1. 环境底子先打牢:RTX 5060 下的版本组合
1.1 为什么RTX 5060对CUDA版本特别挑剔
这一节我必须放在最前面说,因为版本不对,后面所有代码都会崩在import那一行。
RTX 5060是Blackwell架构的新卡,它和上一代Ampere、Ada架构对软件版本的要求完全不一样。老架构用CUDA 11.x、PyTorch 1.x都能跑,但5060必须满足两个硬性条件:显卡驱动要新(建议直接装官网最新版),CUDA版本要支持12.8及以上。很多人第一次跑YOLO,装完PyTorch之后训练时报错提示没有可用的内核镜像,就是这个原因——驱动和PyTorch内置的CUDA版本配不上新显卡。
判断显卡驱动是否支持很简单,在终端输入:
nvidia-smi看右上角的CUDA Version,如果显示12.8或更高,驱动这关就过了。这里有个常见误区:nvidia-smi显示的CUDA Version表示这个驱动最多支持到哪个CUDA版本,并不代表系统里已经装了对应的CUDA工具包。做YOLO训练其实不需要单独安装完整CUDA工具包,PyTorch自带的CUDA运行库就够了。
1.2 安装PyTorch和YOLOv11的正确顺序
PyTorch必须装支持cu128的版本,命令如下:
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128装完之后先验证GPU能不能被PyTorch识别:
import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))第一行返回True,第二行能打印出RTX 5060之类的显卡名称,说明PyTorch和显卡已经通了。注意安装顺序很重要:一定要先装torch/torchvision,再装ultralytics库。如果顺序反了,pip会根据系统环境自动给你装一个CPU版本的torch,训练的时候根本没走显卡,速度慢得离谱。
接下来安装官方YOLO库:
pip install ultralytics安装完可以用一行代码快速验证环境是否完整:
from ultralytics import YOLO model = YOLO("yolo11n.pt")这里说明一下,有些教程里写作YOLOv11、yolov11n.pt,其实官方权重文件名目前是yolo11n.pt,代码里面少一个v不影响流程,大家不用纠结这个名字。如果能正常加载模型,说明环境已经全部就绪,可以进入数据准备环节了。
2. 数据是第一个分水岭:人脸数据集准备与YOLO格式
2.1 目录结构和标注文件到底长什么样
很多零基础同学卡在训练之前,不是因为代码不会写,而是数据集格式搞不清。YOLO训练需要的数据集不是简单扔一堆图片进去就行,它有固定的目录结构:
face_data/ images/ train/ # 训练图片,比如 face_001.jpg、face_002.jpg val/ # 验证图片 labels/ train/ # 训练标注,face_001.txt、face_002.txt val/ # 验证标注 face.yaml # 数据配置文件图片和标注文件名要严格一一对应,比如images/train/face_001.jpg对应的标注文件就是labels/train/face_001.txt,后缀从.jpg换成.txt,主文件名不能有任何差别。
每个txt标注文件里的每一行代表一个目标框,格式是五个值:
类别ID 中心点x坐标 中心点y坐标 框宽度 框高度比如:
0 0.514843 0.456944 0.324219 0.472222说明这张图里有一个人脸框,类别ID是0,框的中心点在图片的相对位置x=0.5148、y=0.4569,宽度占整张图宽度的32.4%,高度占整张图高度的47.2%。
所有坐标必须归一化到0~1之间,也就是用像素坐标除以图片的宽或高。这样做的好处是模型不关心图片原始尺寸,640x640的图和1920x1080的图可以用同一套标注逻辑。如果从公开数据集下载的标注是XML或JSON格式,需要写个脚本转成这种txt格式,转换公式是:
x_center = (x_min + x_max) / 2 / image_width y_center = (y_min + y_max) / 2 / image_height box_width = (x_max - x_min) / image_width box_height = (y_max - y_min) / image_height很多人转格式的时候容易犯一个错:左上角坐标(x_min, y_min)用的是VOC格式,但YOLO格式里的中心点坐标不是框的左上角加上半宽半高算出来的,而是直接用(x_min+x_max)/2,别搞混了。
2.2 face.yaml配置文件逐个字段讲清楚
数据准备好了,还需要告诉YOLO模型“你的训练数据在哪、一共有几个类别”。新建face.yaml文件,内容如下:
path: D:/yolo_face/face_data # 数据集根目录,建议写绝对路径 train: images/train # 训练图片目录,相对于path val: images/val # 验证图片目录,相对于path nc: 1 # 类别数量,人脸检测只有1个类别 names: ["face"] # 类别名称列表有几个细节值得注意。path字段可以写绝对路径也可以写相对路径,但零基础阶段我建议直接写绝对路径,比如D:/yolo_face/face_data,避免运行时因为当前目录不对找不到数据。train和val字段是相对于path的路径,不要写完整路径,否则容易重复拼接。nc和names必须对应,nc是数字1,names列表里只有一个元素"face"。
顺便说一下为什么要单独训练一个人脸类别,而不是直接用官方YOLO模型里的person类。COCO数据集里的person类检测的是整个人体,画出来的人脸框要么太小要么框不准,而且person类包含各种姿态,人脸检测任务的特征分布差异很大。单独训练一个face类,检测头只负责学习人脸这一类特征,模型更专注,推理结果也更干净。
3. 训练前的代码准备与超参解析
3.1 预训练权重怎么选
YOLO官方提供了不同尺寸的预训练权重,nano、small、medium、large、xlarge,尺寸越大精度越高,但显存占用和训练时间也越大。RTX 5060这种8GB左右的显存,零基础入门阶段我强烈建议先用nano版本,也就是yolo11n.pt。
为什么第一个项目不要追求大模型?因为人脸检测任务本身相对简单,类别少、目标特征明显,nano模型完全能跑出不错的效果。更重要的是,用nano模型把全流程跑通之后,你对训练、验证、预测的代码逻辑和数据格式都有了直观理解,后续再换s、m版本的模型其实是改一行代码的事。如果一上来就用最大模型,显存溢出、训练时间过长、参数调试难度增加,很容易把信心磨没了。
加载预训练权重的代码:
from ultralytics import YOLO # 加载nano版本预训练权重 model = YOLO("yolo11n.pt")预训练权重是基于大规模通用数据集训练过的,虽然它的类别列表里没有face,但底层卷积已经学会了边缘、纹理、形状这些通用特征,这些特征对人脸检测非常有帮助。你在这基础上微调,比从零开始随机初始化权重训练快得多,小数据集也不容易过拟合。
3.2 train()参数逐项拆解
训练代码的核心就一个train方法:
model.train( data="face.yaml", epochs=100, batch=8, imgsz=640, device=0, workers=4, patience=20, optimizer="auto", lr0=0.01, amp=True, cache=True, seed=42, project="runs/face_train", name="exp1", )每个参数我都说明一下,方便你按自己的情况调整:
| 参数名 | 含义 | 建议与说明 |
|---|---|---|
| data | 数据配置文件路径 | 直接写face.yaml的路径 |
| epochs | 训练轮数 | 第一次跑可以先设30,流程通了再加大 |
| batch | 每次迭代喂给显卡的图片数 | 显存不够就降到4或2,或者用batch=-1自动检测 |
| imgsz | 输入图片分辨率 | 默认640,不要轻易调大,越大的分辨率越吃显存 |
| device | 使用的计算设备 | 0表示第一张GPU,CPU训练设置为cpu |
| workers | 数据加载线程数 | Windows系统如果卡住,调成0 |
| patience | 早停耐心值 | 连续多少轮验证指标没提升就停止训练 |
| optimizer | 优化器选择 | auto会自动选,新手不用管 |
| lr0 | 初始学习率 | 默认0.01,如果loss不下降可以降到0.001 |
| amp | 混合精度训练 | 默认开启,能省显存、加快速度 |
| cache | 是否缓存图片到内存 | 数据集不大可以开True,太大就关掉 |
| seed | 随机种子 | 固定42保证每次结果可复现 |
| project/name | 训练输出目录 | 生成的权重和图表都保存在这里 |
重点说说batch和amp。RTX 5060玩yolo11n,640分辨率下batch=8很稳,如果用的是s版本可能要降到4。拿不准的时候先试batch=-1,框架会自动用二分法探测当前显卡能承受的最大batch值,这比自己瞎猜靠谱。
amp混合精度在50系显卡上是默认开启的,它能让一半的计算用FP16跑,训练速度提升明显且显存占用降低。如果训练过程中出现loss变成nan的情况,可以先关闭amp试试,不过对大多数人来说保持默认就对了。
4. 训练代码实操与过程解读
4.1 完整训练代码和训练过程中的关键输出
环境没问题、数据格式正确、配置文件写好了,训练就是一段完整但很简单的代码:
from ultralytics import YOLO model = YOLO("yolo11n.pt") model.train( data="face.yaml", epochs=100, batch=8, imgsz=640, device=0, workers=4, patience=20, optimizer="auto", lr0=0.01, amp=True, cache=True, seed=42, )跑起来之后终端会打印每一轮的训练情况,包括box_loss、cls_loss、dfl_loss这些损失值,以及precision、recall、mAP50、mAP50-95这些验证指标。零基础同学不需要每个数值都吃透,重点看两个东西:loss是不是在整体下降,mAP50是不是在整体上升。如果看到loss一轮比一轮低,mAP50从0.2慢慢涨到0.7以上,说明模型正在正常收敛。
训练结束后,输出目录下会生成几个关键文件。runs/face_train/exp1/weights/里有两个权重文件:best.pt是验证集上表现最好的权重,last.pt是最后一轮的权重。以后做预测、做验证都用best.pt,last.pt只在你想接着断点续训时用。同目录下还有results.png,这个图把整个训练过程的loss曲线和指标曲线都画出来了,判断训练状态非常直观。
4.2 训练过程中的几个注意点
第一次跑训练建议加一行设置,把epochs改成30甚至20。因为你要验证的是整个流程是否通畅,而不是立刻训练出成品模型。如果一口气设100个epoch,跑了半小时才发现数据集路径有问题或者显卡配置不对劲,时间全浪费了。小epoch数快速跑两三轮,然后中断看输出目录里是否生成文件,再放心跑正式训练。
中断后想接着训练,一行代码搞定:
model = YOLO("runs/face_train/exp1/weights/last.pt") model.train(resume=True)Ultralytics框架会自动读取上次训练的参数继续跑,不需要重新写配置。
还有一点关于数据增强。官方YOLO库默认开启了马赛克增强、随机翻转、色彩扰动等,这些对提升人脸检测的泛化能力很有帮助。初学者不要一上来就关掉数据增强,也不要去改那些复杂的增强参数,默认方案在大多数场景下就是最优解。人脸检测最怕的就是过拟合——训练集上的框画得准,一到新照片就漏检,默认的数据增强能明显缓解这个问题。
5. 验证指标与模型评估
5.1 val()代码及指标提取
训练完不等于结束,你需要客观评估模型到底行不行。验证代码非常简洁:
from ultralytics import YOLO model = YOLO("runs/face_train/exp1/weights/best.pt") metrics = model.val( data="face.yaml", split="val", imgsz=640, batch=8, device=0, )跑完以后,框架会打印出验证集上的各项指标,同时把这些指标对应的图表保存到输出目录。如果你想在代码里拿到这些指标做下一步处理,可以这样取:
# 所有指标都在 metrics.box 里 mAP50_95 = metrics.box.map # mAP@50-95 mAP50 = metrics.box.map50 # mAP@50 precision = metrics.box.mp # 精确率 recall = metrics.box.mr # 召回率5.2 怎么判断验证结果是好是坏
先解释两个最关键的概念。精确率precision表示模型检测出来的框里,有多少是真正的人脸,精确率低说明模型一直在乱框。召回率recall表示图片里真正的人脸,模型成功找出了多少,召回率低说明模型漏检严重,人脸在眼前却框不出来。
目标检测任务通常用mAP指标综合衡量这两个维度,其中mAP50是IoU阈值设为0.5时的平均精度,mAP50-95是IoU从0.5到0.95取多个阈值算出来的平均精度。对人脸检测来说,我的经验是:mAP50超过0.9基本达到可用水平,mAP50-95超过0.7说明模型定位很准。如果各项指标普遍偏低,先检查标注文件有没有问题,再看epochs是不是太少、学习率是不是不合适,而不是急着换更大的模型。
验证过程的输出目录里有两个值得看的图。混淆矩阵图能看出模型在哪些类别上互相搞混,但对于单类别检测,重点看对角线上的数值大不大。PR曲线图能帮助你理解精确率和召回率的权衡,曲线越靠近右上角说明模型越强。如果曲线下降很快,说明高置信度阈值下精确率还行,但阈值一低就误检,这时候需要在预测阶段适当提高置信度阈值。
6. 测试与预测:模型真正用起来
6.1 图片预测完整代码
训练和验证都通过了,接下来就是把模型用在没见过的图片上。测试和预测其实是一回事,就是用训练好的权重文件对新的图片输出检测结果。代码很简单:
from ultralytics import YOLO model = YOLO("runs/face_train/exp1/weights/best.pt") results = model.predict( source="test_images/", # 可以是单张图片路径,也可以是一个文件夹 conf=0.25, # 置信度阈值 iou=0.5, # NMS的IoU阈值 imgsz=640, # 推理分辨率 device=0, save=True, # 保存画好框的图片 save_txt=True, # 保存检测结果的txt文件 save_conf=True, # 在txt里同时保存置信度 line_width=2, )参数解释一下。conf置信度阈值控制在0到1之间,只有置信度大于这个值的框才会输出。阈值调低,检出的框变多但有误检;阈值调高,漏检变多但框更可信。iou参数是NMS去重阈值,同一个目标可能被生成多个重叠框,IoU超过这个值的框会被合并。默认0.5够用,如果觉得重叠框去不干净可以调到0.6。
save=True会把标注好的人脸框图片保存到runs/detect/predict目录下,save_txt=True会在同一个目录的labels文件夹里生成每个检测框的坐标信息。
预测结果返回后,如何在代码里拿到每个框的坐标?这是做后续业务开发最常用的操作:
for r in results: boxes = r.boxes for box in boxes: x1, y1, x2, y2 = box.xyxy[0].cpu().numpy() # 左上角和右下角坐标 conf = box.conf[0].item() # 置信度 cls = int(box.cls[0].item()) # 类别ID,人脸就是0这里有个经验之谈:box.xyxy默认存放在GPU上,直接使用需要先调用.cpu()转出来。如果你要做实时人脸计数或者配合其他业务逻辑,每秒处理多少帧、置信度阈值怎么权衡,都要从这些基础数据开始做。
6.2 视频和摄像头场景的坑
处理视频文件和摄像头时,编码逻辑几乎一样:
# 视频文件 results = model.predict(source="test.mp4", conf=0.25, save=True) # 摄像头实时检测,0代表默认摄像头 results = model.predict(source=0, conf=0.25, show=True, stream=True)摄像头那一段,可以在弹出的窗口里实时看到检测框,按q键退出。视频文件用save=True,处理结果会保存成带标注框的视频文件。
个人强烈建议视频和摄像头预测一定要加stream=True。如果不加stream=True,框架会把整个视频所有帧一次性读入内存再逐帧推理,一个几分钟的视频可能直接占掉几个GB内存。加上stream=True之后变成边读边处理,内存占用非常稳定,实测下来差别巨大。
摄像头场景默认的推理帧率在RTX 5060上用nano模型是相当流畅的,人脸检测这么轻量的任务,这卡完全能胜任。如果发现画面卡顿,优先检查是不是没加stream=True,其次把imgsz降到480也能明显提速。
7. 常见问题与排查实录
这一节把我实测过程中遇到的、以及身边人经常问的问题整理成速查表,新手遇到报错直接对着查。
| 现象 | 原因 | 解决办法 |
|---|---|---|
| torch.cuda.is_available()返回False | PyTorch装成了CPU版本 | 重新按cu128源安装torch/torchvision |
| 训练报错no kernel image | CUDA版本太旧,不支持Blackwell架构 | 更新显卡驱动,确保PyTorch是cu128版本 |
| 训练刚开始就OOM | batch太大或模型太大 | 调小batch,换成nano模型,开启amp |
| 数据加载一直卡住不动 | workers多进程在Windows下兼容问题 | 把workers设为0 |
| 验证提示no labels found | labels目录下txt文件缺失或路径不对 | 检查txt文件名和图片名是否完全一致,检查yaml路径 |
| 图片路径报错或无法读取 | 数据集路径包含中文或空格 | 把数据集放全英文路径下 |
| loss变成nan | 学习率过高或amp不稳定 | 降低lr0到0.001,关闭amp |
| 训练loss降了但val指标不涨 | 过拟合了 | 增大数据量、加大数据增强、减少epochs |
除了表格里的问题,有一个Windows用户特别容易踩的坑:数据集路径里绝对不能有中文。YOLO底层图像读取对中文路径支持很烂,报错信息往往还特别隐晦。任何跟数据读取有关的稀奇古怪问题,先检查项目路径是否是纯英文。
还有一个关于显存的问题。RTX 5060如果跑yolo11n还是OOM,先别急着怀疑显卡不行,很可能是电脑里其他程序把显存占了,比如浏览器、直播软件。训练前用nvidia-smi看一眼显存占用情况,干净显存比盲目降batch更有效。
关于模型训练时间,给一个大概的参考。用yolo11n,640分辨率,约5000张训练图片,batch=8,在RTX 5060上跑100轮通常几个小时能完成。如果只跑30轮摸流程,数据集一两千张的情况下,基本半小到一个小时就能看到完整的loss曲线和验证指标。
8. 实操心得与避坑经验
这一节是我从头到尾跑完这个项目之后最想对新同学说的话。
第一,不要迷信“必须用大模型”。我见过很多同学一上来就跑yolo11l或者yolo11x,结果RTX 5060的8GB显存连batch=2都吃紧,训练动辄十几个小时,最后效果还没nano好。人脸检测的任务复杂度在那儿摆着,先把nano模型的精度调到满意再说,换模型真的只是改一个文件名的事。
第二,数据质量决定性能上限。模型算法能做的优化始终有限,训练集里如果大量图片标注框偏离实际人脸位置,或者图片模糊、光照极端,再强的模型也没用。我调过的模型里,最明显的效果提升往往不是来自换骨干网络,而是重新清理了一遍标注数据。
第三,第一次跑通全流程比追求精度重要得多。环境问题、格式问题、代码问题,这些比调参更折磨人。先用少量数据集、较小epoch数把训练、验证、预测整条链跑通,看到框画在脸上了,再回头细调参数,心态完全不同。
第四,预测阶段的参数一定要动手调。很多同学觉得模型训练完就万事大吉,其实在conf阈值上做点微调往往效果立竿见影。我自己的习惯是把conf设为0.25,然后用测试图片集跑一遍,看看误检和漏检情况,再根据结果是偏多还是偏少适当上调或下调。
最后留一个真实体会:用人脸检测模型做自己的小项目,遇到的绝大多数问题都出在数据准备和版本兼容上,而不是模型结构本身。把这篇里的目录结构、yaml配置、版本要求这三样东西吃透,之后换数据集、换模型、换部署方式的成本都会很低。下一篇可以聊聊把best.pt导出成ONNX或者TensorRT格式,在CPU或者边缘设备上做推理加速的路子,这个方向对实际落地帮助很大。