Gesichtserkennung in einem Familienarchiv klingt nach einem gelösten Problem, bis man sich erinnert, dass sich die Gesichter in diesem Archiv verändern. Ein Neugeborenes und das zehnjährige Kind, das daraus wird, sehen für einen Menschen nicht nur anders aus, auch ihre Gesichts-Embeddings, die numerischen Vektoren, die ein Erkennungsmodell erzeugt, driften weit genug voneinander weg, dass eine einzelne Ähnlichkeitsschwelle nicht beide Enden dieser Reise halten kann. Lässt man einen einzigen globalen Clustering-Durchlauf über das gesamte Archiv laufen, mit einer Schwelle locker genug, um ein Neugeborenes und ein Zehnjähriges als dieselbe Person zu erfassen, fängt sie auch verschiedene Personen. Zieht man sie eng genug an, um Fremde auseinanderzuhalten, wird jedes Kind, während es älter wird, in mehrere „Personen" aufgespalten.
Um dieses Problem geht es in diesem Beitrag. Ein Gesicht zu erkennen, ist mit ausgereiften Modellen größtenteils gelöst. Identität durch die Veränderung zu verfolgen, die ein Gesicht über zwei Jahrzehnte Kindheit durchläuft, ist ein anderes Problem, über das viel weniger geschrieben wurde.
Erst Fenster, dann verketten
Der Ansatz, der funktionierte, ist, aufzuhören, einen einzigen Clustering-Durchlauf zu bitten, zwanzig Jahre zu überspannen, und statt dessen viele kleine, einfache Clustering-Durchläufe zu bitten, jeweils ein halbes Jahr zu überspannen, und die Ergebnisse dann zu verketten.
Schritt eins: gieriges Clustering innerhalb von Halbjahresfenstern, bei einer strengen Ähnlichkeitsschwelle von 0,50 Cosinus. Innerhalb eines Sechsmonatsfensters ist die Altersdrift klein. Ein Kind verändert seine Gesichtsstruktur in sechs Monaten nicht genug, um einen gut kalibrierten Clustering-Durchlauf zu gefährden, sodass eine strenge Schwelle verlässlich bleibt.
Schritt zwei ist der eigentliche Trick. Nimm die Cluster aus jedem Halbjahresfenster und verkette sie über bis zu vier benachbarte Fenster, bei einer viel lockereren Schwelle von 0,42 Cosinus, wobei Union-Find genutzt wird, um Ketten transitiv zusammenzuführen. Die Logik: Altersdrift, die eine direkte Übereinstimmung über ein Jahrzehnt hinweg brechen würde, ist klein genug, um in einem einzelnen Halbjahressprung überbrückt zu werden. Das System braucht nie einen einzigen Ähnlichkeitsvergleich, der „Neugeborenes bis Alter zehn" überspannt. Es braucht eine Kette kurzer Sprünge, jeder für sich einfach, die sich zur langen Distanz aufsummieren. Union-Find passt, weil Identität transitiv ist: Wenn der Cluster von Fenster A mit dem von B verknüpft ist und der von B mit dem von C, landen A und C in derselben Gruppe, obwohl sie nie direkt verglichen wurden.
Die Kette bei vier benachbarten Fenstern zu kappen (zwei Jahre, bei der Größe des Halbjahresfensters) ist eine bewusste Grenze. Würde die lockere 0,42-Schwelle unbegrenzt verketten, summierten sich Fehler auf: Eine leicht zu großzügige Zusammenführung zwei Sprünge tief wird zur Grundlage für die nächste vier Sprünge tief, und irgendwann teilen sich zwei verschiedene Kinder eine Identität. Die Spannweite zu kappen hält den Worst-Case-Fehler jeder Kette begrenzt.
Müllcluster sind schlimmer als weniger Cluster
Die Verkettung erzeugt Kandidaten-Personen-Cluster, und nicht alle davon sind es wert, jemandem gezeigt zu werden. Ein Reinheits-Filter läuft nach der Verkettung und verwirft Cluster, die nicht intern konsistent genug aussehen, um vertrauenswürdig zu sein, und er ist aggressiv: Im Gründungsarchiv hat das die aufgeführten Cluster von 545 auf 281 reduziert und damit mehr als die Hälfte der Rohausgabe verworfen. Jemandem 545 Kandidaten-„Personen" zu zeigen, von denen ein Drittel Fragmente oder Fehl-Zusammenführungen sind, ist schlechter, als ihm weniger, sauberere zu zeigen. Niemand will nach einem Clustering-Algorithmus aufräumen; man will eine Kurzliste, die größtenteils stimmt.
Korrekturen müssen ein erneutes Clustering überleben
Das Clustering läuft erneut, während ein Archiv wächst oder sich ein Modell verbessert, und dabei dürfen die Korrekturen nicht verloren gehen, die schon jemand vorgenommen hat: einen Cluster umbenennen, zwei zusammenführen, die dieselbe Person waren, einen aufteilen, der es nicht war. Also wird jede Korrektur in eine dauerhafte Override-Tabelle geschrieben, nach Namen indiziert, getrennt von der Clustering-Ausgabe selbst, und nach jedem erneuten Clustering wieder angewendet. Der Clustering-Algorithmus schlägt vor; die Override-Tabelle hat das letzte Wort. Das Prinzip ist dasselbe wie bei generiertem Code: Nie zulassen, dass regenerierbare Ausgabe überschreibt, was ein Mensch von Hand bearbeitet hat.
Die Grenze: Geschwister
Hier versucht das System nicht, clever zu sein. Geschwister messen in diesem Archiv etwa 0,33 Cosinus-Ähnlichkeit zueinander, näher als zwei zufällige Fremde, aber deutlich unter den 0,50- und 0,42-Schwellen, die das Clustering verwendet. Das ist nah genug, dass ein aggressiveres System sie zusammenführen könnte, und weit genug, dass es dabei manchmal falsch läge. Eine knapp verfehlte Ähnlichkeit wird deshalb als Anlass zu fragen behandelt: Solche Fälle tauchen als vorgeschlagene Zusammenführung auf, die ein Mensch bestätigen muss, nie als automatische. Eine falsche automatische Zusammenführung verfälscht still die Zeitleisten zweier Personen gleichzeitig; ein abgelehnter Vorschlag kostet nichts.