搞深度学习的人应该都有同感跑通别人的开源项目很容易但从零开始准备数据、训练一个自己的模型每一步都可能踩坑。这篇文章是“零基础入门人脸识别”系列的第二篇继续用 YOLOv11 这条主线在一张 RTX 5060 显卡上把配置、训练、验证、测试、预测这五步全流程代码完整跑一遍每条命令都给可复制的版本并解释为什么这样写。适合刚装好显卡驱动、还没正经训过模型的新手也适合被各种版本问题折磨过、想系统捋一遍流程的老玩家。1. 开始之前YOLOv11 做的是“人脸检测”不是完整意义的“人脸识别”先把这个概念掰清楚不然后面的代码你可能会理解偏。YOLOv11 输出的是边界框和类别置信度它解决的是“图片里哪里有脸”这个问题属于检测任务。而真正的“人脸识别”还包含“这张脸是谁”——那需要提取人脸特征向量再做比对通常由 ArcFace 这类专用模型完成。所以严格来说本文标题里的“人脸识别”指的是识别系统的第一步人脸检测。几乎所有成熟的识别系统都是“先检测、后识别”检测框不准后面提特征、比对全部白搭。把这一步做扎实第三篇再讲特征提取和检索比对就顺理成章了。顺带说一个命名细节Ultralytics 官方把这代模型叫 YOLO11没有 “v”社区里写 YOLOv11 也很常见两者指的是同一个东西不用纠结。再明确一下硬件预期。RTX 5060 属于“入门很舒服、重活不太行”的定位跑 YOLOv11 的人脸检测训练完全够用yolo11n/s/m 都能顺利训完但显存只有 8GBbatch 和输入分辨率不能像顶级卡那样放开。本文的所有参数都按 8GB 显存来设定换卡以后你可以在这个基础上等比调整。2. 环境配置RTX 5060 的新架构逼着我们把版本选对2.1 为什么“能跑起来”和“能用上显卡”是两回事很多新手拿到新显卡第一件事是装最新驱动然后开箱即用旧版 PyTorch。结果torch.cuda.is_available()返回 True一跑训练却报错或者干脆返回 False。原因出在架构上RTX 50 系列桌面卡的计算能力是 12.0架构代号 sm_120而 PyTorch 2.6 及更早的官方预编译包主要覆盖到 sm_90 之前的架构不认识新卡的指令集。解决办法是选择 PyTorch 2.7 及以上、基于 CUDA 12.8cu128构建的 wheel 版本。这类 wheel 自带 CUDA 运行库不需要你再单独安装完整的 CUDA Toolkit对新手省了很多事。2.2 环境创建与安装命令我用 Miniconda 管理的环境命令如下conda create -n yolo11 python3.11 -y conda activate yolo11 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128 pip install ultralyticsPython 3.11 目前是兼容性最稳的选择别在 conda 默认的 3.13 上折腾。顺序也有讲究先装 torch 再装 ultralytics否则 Ultralytics 可能会把你刚装好的 GPU 版 torch 覆盖成 CPU 版这是新人最容易踩的暗坑。国内网络环境如果觉得官方源慢可以把 pip 换成常见的镜像源效果一样。2.3 装完必须做的三个验证python -c import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))正常输出会看到类似2.7.0cu128、True、NVIDIA GeForce RTX 5060。如果is_available()是 False先运行nvidia-smi确认驱动能看到显卡再确认你安装的 torch 是不是 cu128 版本这两个检查能解决八成环境问题。再验证一下模型能正常加载python -c from ultralytics import YOLO; YOLO(yolo11n.pt)第一次运行会自动下载权重文件网络慢就手动下载放到当前目录文件名对得上即可。最后可以跑一下yolo checks它会汇总输出 Python、GPU、依赖库版本一眼看清环境全貌。3. 数据准备从零到一份能训练的 YOLO 人脸数据集3.1 先理解 YOLO 格式的标签到底长什么样YOLO 的标签不是单独一个 json 文件而是每张图片对应一个同名 txt 文件。每行描述一个目标格式是五个数字类别ID 中心点x 中心点y 框宽 框高注意 x、y、w、h 全部是归一化到 0~1 的相对值也就是除以图片的宽高。比如一张 1920x1080 的图人脸框左上角在 (810, 560)右下角在 (1110, 960)那么中心点是 (960, 760)宽 300、高 400。归一化后就是0 0.5 0.70556 0.15625 0.37037人脸检测一般就一个类别记为 0名字叫 face。如果你想区分戴没戴口罩再定义 1: no_mask 之类但入门阶段先只做一个类别把流程跑通。3.2 目录结构直接复制这份模板my_face_data/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── face.yaml图片放在 images 下标签放在 labels 下两个目录的子目录结构必须一致。图片和标签靠文件名关联所以000001.jpg必须对应000001.txt后缀可以不同主名必须相同。强烈建议整个项目路径用纯英文不要出现“人脸数据”这种中文目录Windows 下编码问题会让你报出完全看不懂的错误。3.3 标注工具与数据划分小数据量用 LabelImg 最直接打开图片画框保存格式选 YOLO 就可以生成的 txt 能直接被训练代码使用。追求效率的话用 X-AnyLabeling它支持模型辅助预标注标了一半框就能帮你猜剩下的人工只需要修正边界几百张图也不会太累。标注人脸有个细节框要尽量贴合人脸包含下巴但不留大块背景宽度正好卡住两侧脸颊。侧脸、低头、戴帽子都要标这些难例决定了你模型的上限。数据划分原则是“按场景和人物去分”不是随机分。比如你拍了 10 段视频按 7:2:1 应该切 7 段进 train、2 段进 val、1 段进 test而不是把所有视频的每一帧混在一起随机分——否则同一段视频的连续帧同时出现在训练集和验证集mAP 虚高一换真实场景就现原形。如果暂时没数据可以先拿公开的人脸检测数据集练手比如 WIDER FACE 这类常见基准数据网上有现成整理好的 YOLO 格式版本可以下载。3.4 data.yaml 写法path: F:/datasets/my_face_data # 数据集的绝对路径 train: images/train val: images/val test: images/test names: 0: facepath建议写绝对路径Ultralytics 虽然支持相对路径但新手在项目目录上反复切换很容易搞混。train/val/test是相对于path的路径。names里 0 对应 face类别顺序必须和标签 txt 里的类别 ID 一致。4. 训练环节一条命令的事但参数决定了你能不能跑到 best.pt4.1 训练命令环境配好、数据就位之后训练本身只有一条命令yolo detect train dataface.yaml modelyolo11s.pt epochs120 imgsz640 batch16 device0 workers4 patience20 cacheTrue projectruns/face_detect nametrain_v1用 Python API 写也是一样的意思from ultralytics import YOLO model YOLO(yolo11s.pt) # 自动加载 COCO 预训练权重 model.train( dataface.yaml, epochs120, imgsz640, batch16, device0, workers4, patience20, cacheTrue, optimizerSGD, cos_lrTrue, projectruns/face_detect, nametrain_v1, )modelyolo11s.pt这行很关键它加载的是在 COCO 数据集上预训练过的权重。虽然 COCO 里没有专门的人脸这个类但预训练学到的低层特征边缘、纹理、轮廓对任何检测任务都有用这就是迁移学习。我测试过从预训练权重开始训五百张人脸图就能收敛到能用的程度从零开始训数据量没有两三千张很难看。4.2 参数逐条拆解以 RTX 5060 的 8GB 显存为基准参数含义我的建议model用什么规模的模型入门选 yolo11s速度和精度平衡yolo11n 更快但精度一般yolo11m 在 8GB 显存也能跑但要把 batch 调小epochs训练轮数120 起步多数数据集在 60~100 轮时 mAP 就不再明显提升imgsz输入分辨率640 默认够用小脸多可以试 960但显存占用随分辨率平方增长batch 要减半batch每批图片数8GB 显存下 yolo11s 640 建议 16报 OOM 就先 8 或 4workers数据加载线程数Windows 上 4 比较稳设 8 有时会卡死patience早停耐心值20 表示 val 指标连续 20 轮不提升就自动停止省电省时间device用哪块 GPU单卡写 0没 GPU 写 cpu会很慢不推荐cache是否缓存数据True 会把图片缓存到内存第二次训练明显变快内存小于 16GB 建议 Falsebatch 是最容易劝退新人的参数。显存不够报CUDA out of memory时第一反应应该是降 batch而不是降模型。yolo11s 在 640 分辨率下一张图大概要占 350MB 左右显存加上中间激活值16 的 batch 在 8GB 上是安全线。想开更大 batch 但显存不够可以研究梯度累积不过新手阶段没必要。4.3 训练过程中看什么训练开始后终端会不断打印box_loss、cls_loss、dfl_loss、Time、GPU这些字段。loss 总体应该在波动中下降不用管每一轮的小抖动看趋势就行。同时在runs/face_detect/train_v1/目录下会生成results.csv里面有每个 epoch 的精确率、召回率、mAP50、mAP50-95 和各类 loss这才是你判断训练是否健康的核心依据。训练结束后目录里会出现best.pt和last.pt。best.pt是验证集上 mAP 最高的那个模型last.pt是最后一个 epoch 的模型一般选 best。两个常见判断loss 还在降但 val 的 mAP 不再涨说明模型过拟合要么加数据、要么调低 epochsmAP50 很高但 mAP50-95 偏低说明框位置不够准可以适当提高输入分辨率。速度方面可以给个参考五千张人脸图yolo11sRTX 5060640 分辨率batch 16一个 epoch 大概 2~4 分钟100 轮半天内跑完。要是你发现一个 epoch 要十几分钟先检查是不是 batch 太小或者 workers 没设置好。5. 验证与测试指标怎么读测试集为什么必须单独留5.1 验证命令与输出文件训练完先用验证集做一次评估yolo detect val modelruns/face_detect/train_v1/weights/best.pt dataface.yaml splitval batch16 device0Python 写法model YOLO(runs/face_detect/train_v1/weights/best.pt) metrics model.val(dataface.yaml, splitval, device0, batch16) print(metrics.box.map50, metrics.box.map)验证跑完会在runs/detect/val下生成一堆图混淆矩阵、P-R 曲线、F1 曲线还有每张验证图上预测结果的可视化。先用眼睛过一遍可视化结果再去看数值指标两者结合才完整。5.2 指标表看懂这四个数就够入门了指标含义人脸检测的参考值Precision 精确率预测为“人脸”的框里真正是脸的比例 0.9Recall 召回率所有真实人脸中被找到的比例 0.85mAP50IoU 阈值 0.5 时的平均精度 0.9mAP50-95多个 IoU 阈值的综合平均 0.6人脸检测的特点是“框偏一点问题不大”——后续识别阶段通常会把检测结果裁剪出来再缩放所以 mAP50 是主要参考指标mAP50-95 是更严格的综合参考。如果 mAP50 高但 mAP50-95 低说明你的框经常不够贴合人脸在密集场景里容易互相遮挡。5.3 测试集单独评估这是很多人漏掉的一步训练过程中你一直在用 val 集选模型相当于已经“看过” val 上的表现再用 val 报最终成绩是不公平的。正确做法是留出一部分从训练到选模型全程没碰过的数据等一切定稿后最后跑一次 test 集得到的结果才是这个模型的真实水平。命令和验 val 一样把splitval换成splittest即可。如果 test 的 mAP50 比 val 掉 5 个点以上基本可以断定数据划分出了问题——要么是泄漏要么是 val 规模太小不能代表真实分布。还有一个我每次必做的检查把测试集中最难的那几张图单独拿出来——密集人群、逆光、侧脸、模糊——跑预测看结果。指标是数字面对真实场景的感受是另一回事两者都要过关。5.4 置信度阈值怎么定验证报告里的 Precision 和 Recall 是某个阈值下的值mAP 则是把所有阈值下的表现积分得到的。实际预测时你要通过conf参数选择阈值。阈值高漏检会变多阈值低误检会变多。人脸业务一般取 0.25~0.4。做安防监控宁可多框几个背景也不能漏掉人脸阈值调低做考勤闸机误检一次就开一次门阈值就得调高。这个选择没有绝对的标准全看你的业务容忍度。6. 预测环节命令行、Python API 与摄像头实时检测一次讲清6.1 命令行预测训练一切顺利看一下新图片上的效果yolo detect predict modelruns/face_detect/train_v1/weights/best.pt sourcetest.jpg conf0.35 iou0.45 imgsz640 saveTruesource参数非常灵活可以传单张图片、整个文件夹、视频文件路径也可以传0表示调用第一个摄像头。saveTrue会把标注框的图片保存到runs/detect/predict目录showTrue是实时弹窗显示注意服务器没有桌面环境时不要开 show。6.2 Python API拿到坐标才算真正开始命令行适合快速看效果实际项目里还是要用 Python API 操作结果from ultralytics import YOLO model YOLO(runs/face_detect/train_v1/weights/best.pt) results model.predict(sourcetest.jpg, conf0.35, iou0.45, saveTrue, imgsz640, device0) r results[0] for box in r.boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf round(float(box.conf[0]), 3) cls int(box.cls[0]) print(fface {conf:.3f} ({x1:.0f},{y1:.0f},{x2:.0f},{y2:.0f}))box.xyxy返回的是像素坐标左上角 (x1,y1) 到右下角 (x2,y2)方便直接在图片上画框或裁剪。box.xywhn才是归一化的中心点格式别混淆。如果要为后续的人脸识别准备数据可以直接裁剪出人脸区域import cv2 img cv2.imread(test.jpg) for i, box in enumerate(r.boxes): x1, y1, x2, y2 map(int, box.xyxy[0].tolist()) face img[y1:y2, x1:x2] cv2.imwrite(fface_{i}.jpg, face)这几行代码就是整套识别系统里“检测”模块的标准输出形式后续接特征提取模型完全够用。6.3 摄像头实时检测yolo detect predict modelruns/face_detect/train_v1/weights/best.pt source0 showTrue conf0.35RTX 5060 跑 yolo11s 的摄像头实时检测帧率非常宽裕完全感受不到卡顿。如果觉得框线太粗影响观感加一个line_width2参数。6.4 导出与加速ONNX 和 TensorRT模型训好只是第一步落地部署通常要导出成其他格式yolo export modelruns/face_detect/train_v1/weights/best.pt formatonnx opset12 yolo export modelruns/face_detect/train_v1/weights/best.pt formatengine device0ONNX 是通用格式跨平台、跨代码框架后续可以接 ONNX RuntimeCPU 都能跑新手首选。TensorRTengine 格式是英伟达专属的高性能推理引擎在 50 系列显卡上能进一步压榨性能但要在 NVIDIA 环境下使用。先学会 ONNX再考虑 TensorRT别一上来就搞最复杂的。7. 训练人脸检测模型最容易踩的坑以及我现在的默认参数7.1 六个高频坑问题原因解决办法torch.cuda.is_available()为 FalsePyTorch 版本太老不支持 RTX 50 系列安装 2.7 的 cu128 版本训练报CUDA out of memorybatch 或 imgsz 太大先降 batch 到 8 或 4再考虑降 imgszmAP 始终为 0标签 txt 里坐标可能超出 0~1 范围抽样检查 labels 目录下的文件确认归一化正确val 指标虚高新场景一塌糊涂同段视频的连续帧被分到了 train 和 val按场景而不是按帧切分数据训练时报无法读取图片路径里有中文或特殊字符数据集路径全部用英文小脸密集场景 mAP 上不去分辨率不够特征太小imgsz 提到 960 或 1280batch 减半7.2 我现在的默认训练习惯先小规模试跑再全量跑这是最重要的习惯。不管是新数据集还是新环境先用 30 个 epoch、batch 8确认没有任何报错、loss 能正常下降再放开了跑完整训练。一上来直接跑 300 个 epoch结果 20 分钟后才发现数据路径配错了时间和电费都浪费了。我最近几次人脸检测项目默认参数基本就是 yolo11s、120 epochs、SGD cos_lr、patience20imgsz 根据场景选 640 或 960。先以 val 的 mAP50 过 0.9 作为基线达不到就检查数据而不是盲目换大模型。在 8GB 显存上yolo11m 训练体验明显比 s 难受精度提升却很有限数据质量的收益永远比模型规模的收益来得快。最后分享一个文档习惯每次实验把命令连同 data.yaml 一起记录到项目笔记里命名用train_v1、train_v2这种清晰递增的编号。你永远不知道自己会在哪一天需要回滚到三周前的某个配置到时候没有记录就只能从头再跑一遍。折腾几次之后你就明白训练人脸检测模型真正难的从来不是敲命令而是管理好你的数据和实验痕迹。