跳到正文
DEV Community· yakhyo·· 4 小時前AI 評分55

UniFace 更換人臉識別模型,需重新校準判定閾值

Changing a Face Recognition Model Also Changes Your Threshold

AI 導讀

UniFace 支援的不同人臉識別模型即使沿用幾乎不變的 Python 介面,嵌入向量與相似度分數的含義仍會不同,原有向量和判定閾值不能直接沿用。切換模型時需重新生成向量、重建搜尋索引,並以具代表性的標註資料校準及評估完整流程。原文提及的 10 組配對不足以建立通用準確度排名或部署錯誤匹配率。

正文

Face verification examples using archival portrait pairs

Replacing a face recognition model can leave the Python code almost unchanged while changing the meaning of every stored embedding and similarity score.

UniFace exposes AdaFace, ArcFace, EdgeFace, MobileFace, and SphereFace through a common recognizer interface. That makes it convenient to compare implementations. It does not make their embedding spaces or decision thresholds interchangeable.

This article develops that distinction from my original recognition model comparison. The focus here is what needs to change in a pipeline when the recognizer changes.

The interface stays stable; the representation changes

The recognition path starts with an image and five alignment landmarks. The landmarks define a standardized face crop, and the recognizer maps that crop to an embedding. UniFace can return an L2-normalized vector for cosine similarity.

Two models can both produce 512 values without assigning the same meaning to those coordinates. Comparing an AdaFace vector with an ArcFace vector is not a supported identity comparison. Even switching weights within a model family should be treated as a representation change unless compatibility has been established.

For a stored gallery, replacing the recognizer therefore requires regenerating its embeddings and rebuilding the corresponding search index. A migration that changes only the model constructor can produce plausible-looking scores from incompatible vectors.

Compute a score before assigning a decision

The following example uses an explicit ArcFace variant and requires one face in each input. It prints a similarity score without attaching an uncalibrated match label.

Install the CPU runtime with pip install "uniface[cpu]", then supply two portrait images:

import cv2
from uniface import ArcFace, RetinaFace, compute_similarity
from uniface.constants import ArcFaceWeights

detector = RetinaFace()
recognizer = ArcFace(model_name=ArcFaceWeights.MNET)

def embed(path):
    image = cv2.imread(path)
    if image is None:
        raise FileNotFoundError(f'Could not read {path}')
    faces = detector.detect(image)
    if len(faces) != 1:
        raise ValueError(f'Expected one face in {path}, found {len(faces)}')
    return recognizer.get_normalized_embedding(image, faces[0].landmarks)

score = compute_similarity(
    embed('portrait_a.jpg'),
    embed('portrait_b.jpg'),
    normalized=True,
)
print(f'Cosine similarity: {score:.3f}')

The score is a similarity measurement, not the probability that the images show the same person. A decision threshold is a separate part of the application.

Selecting the highest-confidence detection would not resolve an ambiguous multi-person image: detector confidence measures detection confidence, not which subject the caller intended. Requiring exactly one face makes this example's assumption explicit.

What a small comparison can tell you

The original post compared six model configurations on five archival portraits, producing two same-person pairs and eight different-person pairs. That exercise showed how the scores changed between models while the input images stayed fixed.

It did not establish a general accuracy ranking, a false-match rate for deployment, or a recommendation for a particular device. Ten pairs are too few to characterize errors across lighting, pose, age, camera quality, and population differences. The illustration above comes from a separate demo run and should not be treated as the numerical record of the comparison.

A small test can check that a pipeline runs and reveal obvious score changes. Choosing a deployment threshold requires a larger, representative evaluation.

Calibrate the complete pipeline

Collect labeled same-person and different-person examples that reflect the intended inputs. Separate threshold selection from final evaluation so the reported result is not simply a fit to the calibration examples.

For a rule that accepts a pair when its score is at least a threshold, increasing that threshold generally reduces false matches while increasing missed matches. Evaluate both errors and choose an operating point based on the application's requirements. A value copied from a demo or another model has no such justification.

The detector and preprocessing belong in that evaluation. Different landmarks change alignment; crop geometry, color conventions, and image quality can also affect embeddings. Keep the detector, alignment method, recognizer weights, and preprocessing fixed when comparing scores.

For one-to-many search, evaluate the search workflow with a gallery of representative size as well. A pairwise threshold study alone does not describe the chance of an incorrect identification across many candidates.

Plan model changes as data migrations

Record the recognizer variant, weight checksum, and preprocessing configuration alongside the embedding collection. Build the replacement gallery separately, recalibrate its decision rule, and validate it before switching the application to the new index.

Runtime measurements need the same care. Weight-file size describes storage, not latency. Measure preprocessing, alignment, inference, and search on the intended hardware and execution provider. The laptop timings in the original post are observations from that setup, not performance promises for another device.

A shared API reduces the code needed to compare recognizers. The data migration and evaluation remain part of the change.

See UniFace's recognition documentation, threshold calibration guide, and model licence terms before selecting a configuration for deployment.

來源:DEV Community · dev.to