1:1 ROC与1:N ROC有什么区别?1:N人脸识别可用哪些评估指标?
1:N人脸识别评估相关问题解答
1:1 ROC与1:N ROC的核心差异
首先明确1:1人脸验证是二分类任务,对应ROC的计算逻辑是遍历相似度阈值,统计所有正样本对(同一人)、负样本对(不同人)在各阈值下的真阳性率(TPR,纵轴)和假阳性率(FPR,横轴)绘制曲线,结果和底库规模无关。
确实存在1:N ROC这类评估指标,它针对1:N人脸识别的检索匹配逻辑设计,和1:1 ROC的核心差异如下:
- 匹配判定逻辑不同:1:N场景下每个待识别样本会输出和底库N个身份的相似度得分,判定正确的标准是「最高得分超过阈值,且对应身份为样本真实身份」,需同时考虑排序结果和阈值,和1:1仅判断单对样本是否匹配的逻辑完全不同
- 关联底库规模:1:N ROC的表现直接和底库大小N强相关,N越大出现随机高分误匹配的概率越高,相同算法在N=100和N=10000的底库上得到的曲线差异极大,而1:1 ROC的表现不受底库规模影响
- 指标定义不同:1:N ROC的横轴一般为误识率(FAR),指真实身份不在底库中的样本被错误判定为在库的比例;纵轴为识别率(TPR),指真实身份在底库中的样本被正确识别的比例,和1:1 ROC的横轴FPR(所有负样本对被误判为正的比例)定义完全不同
1:N人脸识别其他常用评估指标
除1:N ROC外,工业界和学术界常用的评估指标还有这些:
- Top-k准确率:待识别样本的前k个匹配结果中包含真实身份的比例,常用Top-1、Top-5,仅评估排序效果,不涉及阈值判定
- 漏识别率(FNMR):真实身份在底库中的样本未被正确识别的比例,和识别率为互补关系(FNMR = 1 - TPR)
- 固定FAR下的识别率:实际部署最常用的指标,比如FAR=1e-6时的TPR,指控制误识率在百万分之一的安全标准下,算法能正确识别的样本比例
- 库内拒识率:真实身份在底库中,但最高得分低于阈值被判定为不在库的比例
简易代码示例
以下是基于NumPy实现的1:N指标计算代码,可直接用于模拟或实际测试数据的指标统计:
import numpy as np def calculate_1n_metrics(sim_scores: np.ndarray, query_labels: np.ndarray, gallery_labels: np.ndarray, thresholds: np.ndarray): """ 计算1:N人脸识别核心指标 参数: sim_scores: 形状为(查询样本数, 底库样本数),值为查询样本与底库样本的相似度,越高越相似 query_labels: 形状为(查询样本数,),每个查询样本的真实身份标签,-1代表真实身份不在底库中 gallery_labels: 形状为(底库样本数,),底库中每个样本的身份标签 thresholds: 待遍历的相似度阈值列表 返回: far_list: 各阈值对应的误识率列表 tpr_list: 各阈值对应的识别率列表 top1_acc: Top1准确率 """ # 分离在库、不在库查询样本 in_gallery_mask = query_labels != -1 out_gallery_mask = query_labels == -1 in_idx = np.where(in_gallery_mask)[0] out_idx = np.where(out_gallery_mask)[0] # 计算Top1准确率 max_score_idx = np.argmax(sim_scores, axis=1) pred_labels = gallery_labels[max_score_idx] top1_acc = np.mean(pred_labels[in_idx] == query_labels[in_idx]) if len(in_idx) > 0 else 0.0 far_list, tpr_list = [], [] for th in thresholds: # 计算FAR:不在库样本的最高得分超过阈值的比例 if len(out_idx) > 0: out_max_score = np.max(sim_scores[out_idx], axis=1) far = np.mean(out_max_score > th) else: far = 0.0 far_list.append(far) # 计算TPR:在库样本最高得分超过阈值且预测正确的比例 if len(in_idx) > 0: in_max_score = np.max(sim_scores[in_idx], axis=1) pred_correct = pred_labels[in_idx] == query_labels[in_idx] tpr = np.mean((in_max_score > th) & pred_correct) else: tpr = 0.0 tpr_list.append(tpr) return far_list, tpr_list, top1_acc # 测试示例 if __name__ == "__main__": # 模拟参数:1000个查询样本,1000个底库样本,20%查询样本不在底库中 NUM_QUERY = 1000 NUM_GALLERY = 1000 # 生成模拟数据 sim_scores = np.random.rand(NUM_QUERY, NUM_GALLERY) query_labels = np.random.randint(0, NUM_GALLERY, size=NUM_QUERY) query_labels[np.random.choice(NUM_QUERY, size=int(NUM_QUERY*0.2), replace=False)] = -1 gallery_labels = np.arange(NUM_GALLERY) thresholds = np.arange(0.1, 1.0, 0.05) # 计算指标 far_list, tpr_list, top1_acc = calculate_1n_metrics(sim_scores, query_labels, gallery_labels, thresholds) # 输出结果 print(f"Top1准确率: {top1_acc:.4f}") print("阈值对应FAR/TPR:") for th, far, tpr in zip(thresholds, far_list, tpr_list): print(f"阈值{th:.2f} | FAR={far:.4f} | TPR={tpr:.4f}")
内容的提问来源于stack exchange,提问作者Ink
相关产品推荐
相关产品推荐

