返回专辑
·Johan·4 分钟阅读

ArcFace margin 与 deploy 阈值

嵌入空间训好 cosine similarity 仍要选 operating threshold——验证集上按 recall@FP 目标定阈,部署域 drift 时阈值要重标。

ArcFace margin 与 deploy 阈值

1. val AUC 0.99,上线误识率爆

人脸/re-ID 嵌入,ArcFace 训完 val AUC 0.99——上线用固定 cosine threshold 0.45,误识在夜间红外相机上爆。训练优化的是 类间角 margin,不是运营点 FPR;threshold 是部署参数,随传感器、季节 drift,季度重 tune 是常态。模型版本升级后若只换 checkpoint 不重标 threshold,AUC 再高也可能运营失败。安全相关门禁宁可保守 threshold,也要写清 FPR 预算与复核流程。

2. ArcFace 机制

s=64 缩放 logits,m=0.5 常见 margin。推理:L2 normalize 后 cosine similarity = dot product,threshold 在 similarity 上切。scale s 影响训练动态,部署 embedding 已 normalize,threshold 与 s 无直接对应——别把训练 s 抄成部署 threshold。换 ms 重训后必须重画 ROC 选点。

3. triplet mining 与 batch

Triplet semi-hard:选 d(a,n) > d(a,p) 且最小的 negative。batch 内 in-batch negatives 要够大;hard 太狠 early 会炸——curriculum 常见。ArcFace 用大 batch + 多类 ID 更稳;小 batch 考虑 memory bank。mining 策略变更应单变量 ablation,别与换 backbone 同 PR。类数极少时 ArcFace 优势有限,可考虑 proxy-based 或纯 triplet。

4. 部署:ROC 上选 operating point

val 画 ROC/PR,按 TPR@FPR=1e-3 或 recall@固定 precision 选 threshold——不是 train loss 最小点。monitor 部署 positive pair cosine 分布 shift;IR 与 RGB 域 gap 大时分域 threshold。

python
emb = F.normalize(model(x), dim=1)
sim = (emb @ gallery.T).max(dim=1).values
accept = sim > threshold

threshold 写进部署 config 与模型 version 绑定,不是硬编码 magic number。运营变更 threshold 要走评审与灰度,与改模型版本同级。

metric learning 换 gallery(新员工脸库)不需重训 backbone,但 threshold 要在 新 gallery + 新域 val 上重标。open-set 拒识还要 tune unknown 类 score 分布,不能共用一个 training val threshold。gallery 增量更新后,旧 threshold 常偏保守或偏松——应 weekly val 脚本出建议 threshold,人工 approve 后下发。

6. 与分类头、ONNX 导出

分类头是 softmax;metric 是 embedding + 外部分 gallery。export 验 embedding 向量 ORT assert_allclose,再验 threshold 在 ORT 输出上仍有效。L2 normalize 要在 graph 内或部署侧固定一处,别重复 normalize 压扁分布。移动端 int8 量化后 cosine 分布会 shift,threshold 要在量化后 val 上重标。

7. 失败模式

现象原因
训好上线差threshold 未按 FPR 标定
夜间误识高域 drift
triplet 不收敛mining 太 hard
gallery 更新后掉点未重 tune threshold

8. 验收

val ROC/AUC + 业务 operating point(TPR@FPR)。部署 quarterly 抽检 score 分布。train 用 ArcFace margin;deploy 用 cosine threshold——两层参数分开 version。val best → test 一次。上线 A/B 对比旧 threshold 与新 threshold 的 FP 率,再全量切换。

9. 案例:红外域 threshold 未分域

RGB val 上 TPR@FPR=1e-3 对应 threshold 0.45;同一模型红外 val 最优 0.38,仍用 0.45 上线导致 FP 翻倍。分域 threshold + 红外 quarterly _tune 后 FP 回预算内。教训:一个 threshold 走天下 在 multi-sensor 部署必翻车。

10. 与 hard negative 库维护

生产误识样本应回流进 hard negative gallery,定期重训或 fine-tune margin——只调 threshold 有 ceiling。回流要防 duplicate 与 label 噪声;误识图人工复核后再入库。metric 系统 monitor 分域 score 分布,漂移超阈触发 threshold 重标或增量训练,写进运维 playbook。

11. 与法规 / 审计

门禁类场景保留 threshold 变更审计:谁、何时、旧新值、对应 ROC 截图。模型 version 与 threshold version 分开编号,回滚时能指认是模型差还是阈值差。A/B 全量前保留 shadow mode 比对 FP/FN 一周。1:N 检索与 1:1 验证 threshold 不同,不能共用同一 operating point。embedding 维度变更(512→256)后 gallery 要重建,threshold 必须重标——维度压缩常改变 cosine 分布形状。训练集 ID 数与部署 gallery 规模差一个量级时,val 应用 subsampled gallery 模拟线上负载。pairwise 训练与 listwise 检索 metric 不对齐时,deploy threshold 要在 listwise val 上重标。冷启动新用户 gallery 空时,拒识 threshold 应更保守,写进 onboarding 流程。embedding 量化后 cosine 分布压缩,threshold 通常需下调,量化 PR 必须附 threshold 重标结果。1:1 门禁与 1:N 检索的 deploy 文档分开写 threshold 来源,禁止互相复制数值。Face SDK 升级 embedding 维数不变时仍建议 full gallery re-index + threshold 复核,版本号绑定发布。Negative gallery(已知非同一人)应参与 threshold 标定,只用 positive pair 会 optimistic bias。Open-set reject 单独 report TNR@TPR 目标,与 verification threshold 分文档维护。Court/audit 场景保留每次 threshold 变更的 ROC 图与批准人,模型 retrain 不等于 threshold 自动仍有效。Embedding 导出 int8 后必须重画 ROC,禁止沿用 fp32 阈值上线。

Metric learning 训的是空间,运营用的是阈值——threshold 与模型同等重要写进部署 config。

← 全部文章

johan's blog