人脸识别有个反直觉的地方:它本质上不是一个分类问题。如果你把它当成分类,那么世界上每新增一个人,模型就要多一个输出类别、就要重训——这显然不现实。真正能落地的人脸识别系统解决的是一个开放集(open-set)问题:把任意一张脸映射成一个向量,让"同一个人"的向量靠得近、"不同人"的向量离得远。这套思路叫度量学习(metric learning),核心产物叫特征嵌入(embedding)。
直觉:从识别到比对
完整管线大致是:检测(找到脸在哪)→ 关键点对齐(把脸摆正)→ 嵌入(提特征向量)→ 比对(算相似度)。前两步是预处理,真正的智能在第三步。
对齐这一步常被低估。检测出人脸框后,用 5 个或更多关键点(眼、鼻、嘴角)做仿射变换,把脸归一化到标准姿态和尺度。对齐质量直接决定上限:歪着的脸、侧脸会让同一个人的嵌入漂移,再好的模型也救不回来。
嵌入阶段,一个 CNN(或 ViT)骨干网络把对齐后的人脸图像 映射成向量 , 通常是 128、256 或 512。识别时不再做分类,而是算两张脸嵌入的距离或余弦相似度,跟阈值比:
这种设计的好处是一次训练,永久通用:新来一个人,只需存一张照片的嵌入作为底库,无需重训模型。这就是"1:N 检索"和"1:1 核验"能工作的根基。
机制:怎么学出好的嵌入
关键问题是:用什么损失函数,能逼着网络把同人拉近、异人推远?这条线索的演进非常清晰。
Triplet Loss——直接但难训
最直观的是三元组损失。每次取一个锚点 、一个正样本 (同人)、一个负样本 (异人),要求正样本距离比负样本距离至少近一个 margin :
思路漂亮,但工程上很痛:三元组的组合是 量级,绝大多数三元组都是"轻松满足约束"的简单样本,梯度为零、毫无信息。于是必须做难样本挖掘(hard mining)——专门找那些异人却长得像、同人却差异大的三元组。挖掘做得不好,训练要么不收敛要么塌陷。
从 Softmax 到角度间隔
后来主流转向了改造分类损失。训练时仍然用分类头(每个训练身份是一类),但在 softmax 上动手脚,逼出更好的嵌入几何。
先把权重和特征都做 L2 归一化,此时 logit 变成余弦:(归一化后模长为 1)。然后把特征缩放到半径 ,并在目标类的角度上加一个间隔(margin),让同类必须挤得更紧才能被正确分类。一种广泛使用的形式(加性角度间隔)是:
直觉解释:普通 softmax 只要求"目标类分数最大"就够了,决策边界松。而 相当于人为给目标类"加难度"——必须让真实类的角度比其它类小一个 margin 才算分对。结果是同类样本在超球面上被压成更紧的簇,类间留出更大的角度间隔。这类角度间隔损失训练比 triplet 稳定得多,也不需要复杂的三元组挖掘,成了现代人脸嵌入的主流。
1 | # 角度间隔 softmax 的核心逻辑(示意) |
注意 (尺度)和 (间隔)都是关键超参: 太小梯度饱和学不动, 太大训练不收敛。
推理与检索:嵌入怎么用
训练完成后,分类头被丢弃,只保留骨干网络做嵌入器。
- 1:1 核验(这是不是本人):算两个嵌入的余弦相似度,跟阈值比。刷脸支付、过闸机就是这个模式。
- 1:N 检索(这是谁):把待识别嵌入和底库 个嵌入逐一比对取最相似。底库大时用 ANN 索引(如 HNSW)加速,从 降到约 。
因为嵌入都归一化到单位超球面上,余弦相似度等价于欧氏距离的单调变换,二者择一即可。
工程权衡与边界
- 阈值即策略。同一个模型,调高 会降低误识率(FAR,把陌生人当成本人)但升高拒识率(FRR)。安防场景要极低 FAR,宁可多拒;考勤场景更在意体验,可放宽。ROC 曲线和 FAR@FRR 工作点的选择是产品决策,不是模型决策。
- 类别极度不均衡与长尾。训练身份成千上万,但每个身份样本数差异巨大。长尾身份的类中心学不充分,是精度瓶颈之一。
- 域偏移。训练集多是清晰正脸,线上却有逆光、口罩、低分辨率、跨年龄。嵌入对这些变化不鲁棒就会失效,需要针对性数据增强或专门训练。
- 活体检测是另一个系统。识别只回答"嵌入像不像",但照片、视频、面具能轻易骗过纯识别模型。防攻击靠独立的活体检测(红外、结构光、动作配合),不要把它和识别混为一谈。
小结
人脸识别的精髓是把"识别"转化为"嵌入 + 比对":用度量学习训练一个把人脸映射到超球面的编码器,让几何距离编码身份相似度。损失函数从 triplet 的难样本挖掘演进到角度间隔 softmax,本质都是在做同一件事——压缩类内、扩张类间。理解了这一点,检索、阈值、长尾、域偏移这些工程问题就都能挂在同一根主线上。