La reconnaissance faciale sur une archive familiale semble être un problème résolu jusqu'à ce qu'on se rappelle que les visages, dans cette archive, changent de forme. Un nouveau-né et l'enfant de dix ans qu'il devient ne se ressemblent pas seulement différemment pour un humain — leurs empreintes de visage, les vecteurs numériques qu'un modèle de reconnaissance produit, dérivent suffisamment loin l'une de l'autre qu'un seuil de similarité unique ne peut pas tenir les deux bouts de ce trajet à la fois. Fais tourner une seule passe de regroupement global sur toute l'archive avec un seuil assez souple pour reconnaître un nouveau-né et un enfant de dix ans comme la même personne, et il commence aussi à confondre des personnes différentes. Resserre-le assez pour garder des inconnus séparés, et chaque enfant se retrouve scindé en plusieurs « personnes » à mesure qu'il grandit.
C'est le problème central de cet article : pas « comment reconnaître un visage », qui est un problème en grande partie résolu grâce à des modèles matures, mais « comment suivre une identité à travers le genre de changement qu'un visage traverse sur deux décennies d'enfance », ce qui est un problème entièrement différent et beaucoup moins documenté.
D'abord des fenêtres, puis on les chaîne
L'approche qui a fonctionné consiste à arrêter de demander à une seule passe de regroupement de couvrir vingt ans, et à demander plutôt à un grand nombre de petites passes de regroupement faciles de couvrir chacune six mois, puis à chaîner les résultats ensemble.
Étape un : un regroupement glouton à l'intérieur de fenêtres de six mois, avec une barre de similarité stricte de 0,50 en cosinus. À l'intérieur d'une fenêtre de six mois, la dérive due à l'âge est vraiment faible — un enfant ne change pas assez la structure de son visage en six mois pour menacer une passe de regroupement bien calibrée, donc une barre stricte peut se permettre d'être stricte, et rester fiable.
L'étape deux est la vraie astuce. Prendre les groupes de chaque fenêtre de six mois et les chaîner à travers jusqu'à quatre fenêtres adjacentes, avec une barre bien plus souple de 0,42 en cosinus, en utilisant un « union-find » pour fusionner les chaînes de façon transitive. La logique : la dérive due à l'âge qui casserait une correspondance directe sur une décennie est assez faible pour être franchie d'un simple saut d'une fenêtre de six mois à la suivante. Donc plutôt que d'avoir un jour besoin d'une seule vérification de similarité pour couvrir « du nouveau-né à dix ans », le système n'a jamais besoin que d'une chaîne de petits sauts, chacun facile en soi, qui finissent par s'additionner jusqu'à la longue distance. Le « union-find » est la bonne structure ici parce que l'identité est transitive — si le groupe de la fenêtre A se relie à celui de la fenêtre B, et que celui de B se relie à celui de C, A et C devraient finir dans le même ensemble même s'ils n'ont jamais été comparés directement.
Limiter la chaîne à quatre fenêtres adjacentes (deux ans, étant donné la taille des fenêtres de six mois) est une limite délibérée, pas un oubli. Laisser la barre souple de 0,42 chaîner indéfiniment, et les erreurs s'accumulent : une fusion légèrement trop généreuse à deux sauts devient le fondement d'une fusion légèrement trop généreuse à quatre sauts, et finalement deux enfants différents finissent par partager une identité parce que la chaîne a dérivé tout le long du trajet, une fusion souple à la fois. Limiter la portée garde borné le pire cas d'erreur de chaque chaîne.
Des groupes de mauvaise qualité sont pires que moins de groupes
Le chaînage génère des groupes-personnes candidats, et ils ne valent pas tous la peine d'être montrés à quelqu'un. Un filtre de pureté s'exécute après le chaînage et rejette les groupes qui ne semblent pas assez cohérents en interne pour qu'on leur fasse confiance, et il est agressif : sur l'archive fondatrice, ça a fait chuter les groupes listés de 545 à 281. Ce n'est pas un petit élagage, c'est jeter plus de la moitié de la sortie brute. L'alternative — montrer à une personne 545 « personnes » candidates, dont un tiers sont en réalité des fragments ou des fausses fusions — est pire que d'en montrer moins, mais plus propres. Personne ne veut nettoyer derrière un algorithme de regroupement ; les gens veulent une liste courte qui est déjà, en grande partie, juste.
Les corrections doivent survivre à un nouveau regroupement
Rien de tout ça n'est un processus à usage unique. Le regroupement se refait à mesure qu'une archive grandit ou qu'un modèle s'améliore, et chaque fois, il serait inacceptable de perdre les corrections humaines déjà apportées par quelqu'un — renommer un groupe, fusionner deux qui étaient en fait la même personne, en scinder un qui ne l'était pas. Alors chaque correction est écrite dans une table de substitution durable, indexée par nom, séparée de la sortie du regroupement elle-même, et réappliquée après chaque nouveau regroupement. L'algorithme de regroupement propose ; la table de substitution a le dernier mot. C'est le même principe que le contrôle de version pour du code généré automatiquement : ne jamais laisser la sortie régénérable écraser silencieusement la partie qu'une personne a modifiée à la main.
La limite honnête : les frères et sœurs
La chose la plus utile que je puisse dire sur ce système, c'est où il n'essaie pas d'être malin. Les frères et sœurs, dans cette archive, affichent une similarité en cosinus d'environ 0,33 entre eux — plus proche que deux inconnus au hasard, mais nettement en dessous des barres de 0,50 ou 0,42 que le regroupement utilise réellement. C'est assez proche pour qu'un système plus agressif puisse se convaincre de les fusionner, et assez loin pour qu'il ait parfois tort. Plutôt que de jouer sur cette limite, le système traite une similarité presque suffisante comme un signal pour demander, pas comme une instruction pour agir : des cas comme celui-ci apparaissent comme une fusion suggérée qu'un humain doit confirmer, jamais une fusion automatique. Une fausse fusion automatique corrompt silencieusement les chronologies de deux personnes à la fois ; une suggestion refusée ne coûte rien.