docs: deploy from 0bd2747

This commit is contained in:
2026-07-21 08:56:42 +02:00
parent 36f75ba199
commit 34b1f2c58f
24 changed files with 2066 additions and 1897 deletions
+481 -196
View File
@@ -242,6 +242,25 @@
<li class="md-tabs__item">
<a href="../methodology/" class="md-tabs__link">
How We Score Against X-Ray
</a>
</li>
@@ -272,26 +291,7 @@
Model Bake-off & Re-tune (full log)
</a>
</li>
<li class="md-tabs__item">
<a href="../optimizer-experiments/" class="md-tabs__link">
Optimizer Experiments (prior round)
Full Experiment Log
</a>
</li>
@@ -393,6 +393,33 @@
<li class="md-nav__item">
<a href="../methodology/" class="md-nav__link">
<span class="md-ellipsis">
How We Score Against X-Ray
</span>
</a>
</li>
@@ -414,10 +441,10 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="">
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="">
@@ -435,8 +462,8 @@
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_2">
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
@@ -597,10 +624,10 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#what-good-looks-like" class="md-nav__link">
<a href="#baseline-correctly-scored-seconds" class="md-nav__link">
<span class="md-ellipsis">
What good looks like
Baseline: correctly scored seconds
</span>
</a>
@@ -619,10 +646,10 @@
</li>
<li class="md-nav__item">
<a href="#mechanism-1-extinction-bridging-usually-right-wrong-at-hard-cuts" class="md-nav__link">
<a href="#mechanism-1-extinction-bridging" class="md-nav__link">
<span class="md-ellipsis">
Mechanism 1: extinction bridging — usually right, wrong at hard cuts
Mechanism 1: extinction bridging
</span>
</a>
@@ -638,6 +665,78 @@
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#every-distinct-out-of-cast-name" class="md-nav__link">
<span class="md-ellipsis">
Every distinct out-of-cast name
</span>
</a>
<nav class="md-nav" aria-label="Every distinct out-of-cast name">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#the-many-saints-of-newark-4-names" class="md-nav__link">
<span class="md-ellipsis">
The Many Saints of Newark: 4 names
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lord-of-war-3-names" class="md-nav__link">
<span class="md-ellipsis">
Lord of War: 3 names
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lovelace-1-name" class="md-nav__link">
<span class="md-ellipsis">
Lovelace: 1 name
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scarface-1-name" class="md-nav__link">
<span class="md-ellipsis">
Scarface: 1 name
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#summary-of-the-nine" class="md-nav__link">
<span class="md-ellipsis">
Summary of the nine
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@@ -692,34 +791,7 @@
<span class="md-ellipsis">
Model Bake-off & Re-tune (full log)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../optimizer-experiments/" class="md-nav__link">
<span class="md-ellipsis">
Optimizer Experiments (prior round)
Full Experiment Log
@@ -786,10 +858,10 @@
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#what-good-looks-like" class="md-nav__link">
<a href="#baseline-correctly-scored-seconds" class="md-nav__link">
<span class="md-ellipsis">
What good looks like
Baseline: correctly scored seconds
</span>
</a>
@@ -808,10 +880,10 @@
</li>
<li class="md-nav__item">
<a href="#mechanism-1-extinction-bridging-usually-right-wrong-at-hard-cuts" class="md-nav__link">
<a href="#mechanism-1-extinction-bridging" class="md-nav__link">
<span class="md-ellipsis">
Mechanism 1: extinction bridging — usually right, wrong at hard cuts
Mechanism 1: extinction bridging
</span>
</a>
@@ -827,6 +899,78 @@
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#every-distinct-out-of-cast-name" class="md-nav__link">
<span class="md-ellipsis">
Every distinct out-of-cast name
</span>
</a>
<nav class="md-nav" aria-label="Every distinct out-of-cast name">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#the-many-saints-of-newark-4-names" class="md-nav__link">
<span class="md-ellipsis">
The Many Saints of Newark: 4 names
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lord-of-war-3-names" class="md-nav__link">
<span class="md-ellipsis">
Lord of War: 3 names
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lovelace-1-name" class="md-nav__link">
<span class="md-ellipsis">
Lovelace: 1 name
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scarface-1-name" class="md-nav__link">
<span class="md-ellipsis">
Scarface: 1 name
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#summary-of-the-nine" class="md-nav__link">
<span class="md-ellipsis">
Summary of the nine
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
@@ -869,43 +1013,44 @@
<h1 id="deep-dive-lvface-b-glint360k">Deep dive: LVFace-B Glint360K<a class="headerlink" href="#deep-dive-lvface-b-glint360k" title="Permanent link">&para;</a></h1>
<p>LVFace won the model bake-off (see <a href="../best-model/">Which model is best?</a>) and is
the shipped default embedder. This page is the honest accounting of how it
actually performs — what a good second looks like, where the errors actually
come from, and two cases where the ground truth itself is wrong and LVFace is
right.</p>
<p>LVFace won the model comparison (see <a href="../best-model/">Which model is best?</a>)
and is the shipped default embedder. This page reports how it performs in
detail: a baseline of correct output, the two mechanisms behind its errors,
and every distinct case where it names someone who is not in the film's
credited cast.</p>
<p>Read <a href="../methodology/">How we score against X-Ray</a> first. X-Ray's ground truth
is scene-level, not per-frame. A name marked correct in the Offscreen column
below is the pipeline correctly reporting scene membership, not a workaround.</p>
<div class="admonition note">
<p class="admonition-title">How to read the frames on this page</p>
<p>The top is the film frame, with a box and name on every face the pipeline
identified. The bottom panels are the per-second verdict against X-Ray:
<strong>Onscreen</strong> lists faces named in the frame, <strong>Offscreen</strong> lists cast
X-Ray marks present in the scene without a visible face — presence
carried by the tracker's windows, not by a detection. Colors are the
score: <span style="color:#0ca30c"><strong>green</strong></span> = correct (TPI),
<span style="color:#eb6834"><strong>orange</strong></span> = wrong (FPI),
<span style="color:#3987e5"><strong>blue</strong></span> = missed (FN).</p>
<p>The top of each image is the film frame, with a box and name on every
face the pipeline matched to a real detection. The panels below are the
per-second result against X-Ray. <strong>Onscreen</strong> lists names attached to a
visible face this second. <strong>Offscreen</strong> lists names the pipeline reports
present without a currently visible face. Colors mark the verdict:
<span style="color:#0ca30c"><strong>green</strong></span> correct (TPI),
<span style="color:#eb6834"><strong>orange</strong></span> wrong (FPI),
<span style="color:#3987e5"><strong>blue</strong></span> missed (FN).</p>
</div>
<h2 id="what-good-looks-like">What good looks like<a class="headerlink" href="#what-good-looks-like" title="Permanent link">&para;</a></h2>
<h2 id="baseline-correctly-scored-seconds">Baseline: correctly scored seconds<a class="headerlink" href="#baseline-correctly-scored-seconds" title="Permanent link">&para;</a></h2>
<p><img alt="Wedding couple correctly identified, Downton Abbey: A New Era" src="../assets/images/downton_wedding_couple.jpg" /></p>
<p>Six faces on screen, all six named correctly including Penelope Wilton at the
edge of the pews and a half-occluded Michelle Dockery — while thirteen more
cast members X-Ray marks present in the scene are correctly carried as
"Offscreen" by their presence windows. One miss in the whole frame: Maggie
Smith (blue). Score for this second: 0.86.</p>
<p>Six faces on screen, all six named correctly, including Penelope Wilton at
the edge of the pews and a partly occluded Michelle Dockery. Thirteen more
cast members X-Ray lists as present in the scene are correctly reported
Offscreen. One miss: Maggie Smith (blue). Score for this second: 0.86.</p>
<p><img alt="19 of 20 correct in the funeral crowd" src="../assets/images/downton_funeral_19of20.jpg" /></p>
<p>The same film's funeral gathering: mourning dress, hats, half the faces turned.
<strong>Nineteen of the twenty cast X-Ray lists for this scene are scored correctly</strong>
seven named on screen at up to 100% confidence, twelve more correctly held
as present off-screen.</p>
<p>And the pipeline doesn't need the face to be <em>real</em>:</p>
<p>The same film's funeral scene: dark clothing, hats, half the faces turned
away. Nineteen of the twenty cast members X-Ray lists for this scene score
correct: seven named on screen at up to 100% confidence, twelve more reported
correctly as present but not visible.</p>
<p><img alt="Herbie Hancock identified on an in-fiction video call" src="../assets/images/valerian_screen_call.jpg" /></p>
<p>That's Herbie Hancock at 98% — as a face on a <em>screen inside the movie</em>, over a
sci-fi HUD overlay, during a video call in Valerian. A face is a face, whether
it's in the room or on the bridge's comms display.</p>
<p>The pipeline does not require a live face. This is Herbie Hancock at 98%
confidence, identified from a face displayed on a screen inside the film, on
a video call under a science-fiction HUD overlay.</p>
<h2 id="training-vs-held-out-the-generalization-gap">Training vs. held-out: the generalization gap<a class="headerlink" href="#training-vs-held-out-the-generalization-gap" title="Permanent link">&para;</a></h2>
<p>The shipped config (<code>prob_threshold=0.754, anneal_sec=35.54,
extinction_sec=57.43, expand_gallery=true</code>) was tuned against 4 films. Scored
against the 5 films the optimizer never saw:</p>
<p>The shipped config (<code>prob_threshold=0.754</code>, <code>anneal_sec=35.54</code>,
<code>extinction_sec=57.43</code>, <code>expand_gallery=true</code>) was tuned on 4 films. Scored
on the 5 films the optimizer never saw:</p>
<p><img alt="Held-out per-film F1 vs. the training-set fit" src="../assets/images/holdout_f1_by_film.png" /></p>
<table>
<thead>
@@ -962,18 +1107,18 @@ against the 5 films the optimizer never saw:</p>
<td>80084</td>
</tr>
<tr>
<td><strong>The Many Saints of Newark</strong></td>
<td><strong>46.3%</strong></td>
<td><strong>54.7%</strong></td>
<td>The Many Saints of Newark</td>
<td>46.3%</td>
<td>54.7%</td>
<td>40.1%</td>
<td>15922</td>
<td>4394</td>
<td><strong>974</strong></td>
<td>974</td>
<td>23791</td>
</tr>
<tr>
<td><strong>macro average</strong></td>
<td><strong>67.4%</strong></td>
<td>macro average</td>
<td>67.4%</td>
<td>85.8%</td>
<td>57.0%</td>
<td></td>
@@ -983,112 +1128,252 @@ against the 5 films the optimizer never saw:</p>
</tr>
</tbody>
</table>
<p><strong>67.4% held-out vs. 75.3% on training</strong> — an ~8pp drop, and a <strong>37pp spread
between the best and worst held-out film</strong>. The config does not generalize
uniformly, and the spread traces to two mechanisms, both visible frame by
frame below.</p>
<h2 id="mechanism-1-extinction-bridging-usually-right-wrong-at-hard-cuts">Mechanism 1: extinction bridging — usually right, wrong at hard cuts<a class="headerlink" href="#mechanism-1-extinction-bridging-usually-right-wrong-at-hard-cuts" title="Permanent link">&para;</a></h2>
<p>The extinction window keeps an identity alive through seconds where no face is
detectable. <strong>Most of the time this is exactly what you want</strong>, and it's where
a lot of the TPI count comes from:</p>
<p>The <code>P</code> column is misID-weighted (each out-of-film name counts 10x in the
denominator; see <a href="../methodology/#precision-recall-and-the-misid-weighting">methodology</a>).
That weighting is why Many Saints reads 54.7% here despite naming mostly real,
present faces: its raw (unweighted) precision is <strong>78.4%</strong>, and the gap is
entirely its 974 misIDs paying the 10x penalty. The three zero-misID films
(Benny &amp; Joon, Downton, Valerian) have identical weighted and raw precision;
Lovelace, with 58 misIDs, sits 3pp below its raw 93.3%.</p>
<p>Held-out F1 is 67.4%, against 75.3% on training, an 8pp drop. The spread
between the best and worst held-out film is 37pp. This is not unique to
LVFace: <a href="../model-bakeoff/#held-out-validation-all-3-models">the full experiment log</a>
shows mbf and r18 with the same shape of spread on the same films, at a
uniformly lower level. Two mechanisms explain the spread. Both are shown
below with frame-level evidence.</p>
<h2 id="mechanism-1-extinction-bridging">Mechanism 1: extinction bridging<a class="headerlink" href="#mechanism-1-extinction-bridging" title="Permanent link">&para;</a></h2>
<p>The extinction window keeps a name reported as present for up to
<code>extinction_sec</code> after its last real detection. This is deliberate: most
gaps in face visibility are short (a turned head, an occlusion, a cut to a
reaction shot), and the window bridges them.</p>
<p><img alt="Two faces on screen, six more correctly bridged" src="../assets/images/lovelace_polygraph_bridged.jpg" /></p>
<p>Lovelace's polygraph scene: only Eric Roberts and Amanda Seyfried have visible
faces, but X-Ray lists eight cast present — and all eight score green, the
other six correctly carried by presence windows through a scene where the
camera never shows them. A perfect second, and the extinction/anneal machinery
is <em>why</em>.</p>
<p>The same mechanism has a failure case: a hard cut into long faceless footage.
Both Many Saints of Newark (974 misIDs) and Downton Abbey (FN=80084, the worst
recall of the five) are dominated by it — verified directly against the raw
per-frame stream and the HDF5 dump's own detection counts, not inferred from
the score alone. <strong>This is not a malfunction</strong>: the tracker is doing exactly
what its window is for; the footage just stops cooperating. In the debug
overlay (which draws a bridged identity's last-known bbox, unlike the shipped
output, which emits presence windows and no boxes at all) the bridged state is
visible spatially:</p>
<p><img alt="Debug overlay: bridged identities drawn at their last-known positions" src="../assets/images/many_saints_ghost_fpi.jpg" />
<em>Debug-overlay rendering (<code>dump_error_frames.py --raw</code>): "Jon Bernthal", "Joey
Diaz" and "Billy Magnussen" are extinction-bridged identities from the previous
shot, drawn frozen over the wall and the hanging plates. Frame
<code>many_saints/fpi/fpi_t03543.jpg</code>, <code>montage-frames</code> artifact package.</em></p>
<p>The cost is measurable, not just visible. Downton Abbey's hard cut into its
closing credits, plotting the dump's own per-second <code>face_count</code> (detector
output, independent of the tracker) against what the tracker reports:</p>
<p>Lovelace's polygraph scene: only Eric Roberts and Amanda Seyfried have
visible faces. X-Ray lists eight cast members present. All eight score
correct; the other six are reported Offscreen through a stretch where the
camera never shows them. The extinction window is why.</p>
<p>The same mechanism fails at a hard cut into a long stretch with no faces at
all. Downton Abbey's recall (39.4%, the worst of the five held-out films) is
dominated by this failure. It is verified directly against the raw
per-frame stream and the dump's own detection counts, not inferred from the
score. Plotting the dump's per-second <code>face_count</code> (detector output,
independent of the tracker) against what the tracker reports, through
Downton Abbey's hard cut into its closing credits:</p>
<p><img alt="Detector vs. tracker through Downton Abbey's cut to credits" src="../assets/images/downton_ghost_timeline.png" /></p>
<p>From the cut onward the detector sees <strong>zero faces for nearly a minute</strong> — and
the tracker keeps reporting the last shot's 15 identities the whole time
(verified for Hugh Bonneville: bbox <code>(1743.2, 0.0, 171.3, 317.8)</code>, unchanged to
the pixel, at every sampled second for 57+ seconds). The staircase at the right
edge is the extinction window expiring actor by actor. That plateau is
<code>SceneTrackerFunc::active_[actor_idx].last_bbox</code>
(<a href="https://gitea.tourolle.paris/dtourolle/scene-actor-extraction/raw/commit/4b5557974bef8783bacc375c0869e8f589d1b0a3/src/nodes/scene_tracker_node.hpp"><code>src/nodes/scene_tracker_node.hpp</code></a>)
re-emitted as designed: <code>extinction_sec=57.4</code> was tuned long because bridging
wins on most footage (see the polygraph frame above) — the training films just
never contained a faceless stretch long enough to show the cost side, and the
held-out set did.</p>
<p>The same track-continuation machinery has one milder spatial artifact, worth
knowing when reading these frames:</p>
<p><img alt="Two labels on one face after a shot/reverse-shot cut" src="../assets/images/cafe_society_rapid_cut.jpg" />
<em>Café Society (a training film), a shot/reverse-shot dialog: that is Steve
Carell wearing both his own label and Jesse Eisenberg's.</em></p>
<p>At a rapid cut, the previous shot's track can linger for a beat at nearly the
same screen position the new face occupies — here Jesse Eisenberg's box from
the counter-shot lands on Steve Carell. Note what the score panel says,
though: both actors are green, because both <em>are</em> present in this dialog
scene per X-Ray. The spatial label is briefly wrong; the per-second presence
claim — the thing the pipeline actually ships — is right. It's the same trade
as the extinction window: track continuation smooths over cuts, and 1 fps
sampling occasionally catches the seam.</p>
<p>From the cut onward the detector reports zero faces for close to a minute.
The tracker continues reporting the previous shot's 15 identities for the
same span (verified for Hugh Bonneville: bbox <code>(1743.2, 0.0, 171.3, 317.8)</code>,
unchanged to the pixel, at every sampled second for 57 seconds). The
staircase at the right edge is the extinction window expiring, actor by
actor. This is <code>SceneTrackerFunc::active_[actor_idx].last_bbox</code>
(<a href="https://gitea.tourolle.paris/dtourolle/scene-actor-extraction/raw/commit/0bd27470698c45cab21935d636a04512360e1008/src/nodes/scene_tracker_node.hpp"><code>src/nodes/scene_tracker_node.hpp</code></a>)
re-emitted as designed. <code>extinction_sec=57.4</code> was tuned long because
bridging is correct on most footage, as in the polygraph scene above. The
training films did not contain a faceless stretch long enough to expose the
cost side; the held-out set did.</p>
<p>The extinction window is a scoring concept, not something drawn on screen.
The shipped output is presence windows with no bounding boxes. Even the
debug overlay used for this report never draws a box for a bridged name: a
name inside its extinction window with no current detection appears only as
a name in the Offscreen column, the same as every correctly bridged name
above.</p>
<p>A related, smaller effect shows up at rapid cuts:</p>
<p><img alt="Two labels on one face after a shot/reverse-shot cut" src="../assets/images/cafe_society_rapid_cut.jpg" /></p>
<p>Café Society (a training film), a shot/reverse-shot dialog. The box on Steve
Carell's face carries two labels: his own, and Jesse Eisenberg's, left over
from the counter-shot a moment earlier. Both names score correct, because
both actors are present in this scene per X-Ray. The box position is
briefly wrong; the presence claim, which is what the pipeline ships, is
right.</p>
<h2 id="mechanism-2-the-face-vs-presence-ceiling">Mechanism 2: the face-vs-presence ceiling<a class="headerlink" href="#mechanism-2-the-face-vs-presence-ceiling" title="Permanent link">&para;</a></h2>
<p>Downton Abbey's recall didn't collapse because faces were misread — it
collapsed because for most of its 80084 FN-seconds there was <strong>no face to
read</strong>:</p>
<p>Downton Abbey's recall did not collapse because faces were misread. It
collapsed because for most of its 80084 false-negative seconds there was no
face to read.</p>
<p><img alt="22 cast credited, nobody facing the camera" src="../assets/images/downton_crew_fn.jpg" /></p>
<p>A newsreel crew hauls equipment through the hall: X-Ray credits 22 cast as
present in this scene; not one face looks at the camera. Eight are still
scored green (windows bridging from adjacent shots) — the other fourteen are
blue FNs that no face-recognition pipeline could ever recover. X-Ray encodes
<em>scene membership</em>; the pipeline measures <em>on-screen faces</em>. In ensemble films
those two definitions diverge massively, and that gap — not identification
error — is most of what the FN column counts.</p>
<p><img alt="Presence without a detectable face, The Many Saints of Newark" src="../assets/images/many_saints_outofcast_fpi.jpg" /></p>
<p>Same ceiling from the other side: Michela De Rossi in frame but turned away,
five cast correctly bridged as offscreen (green), four blue FNs — and one
orange we'll come back to below.</p>
<p>A newsreel crew moves equipment through the hall. X-Ray credits 22 cast
members as present in this scene. None face the camera. Eight still score
correct, carried by presence windows from adjacent shots. The other fourteen
are missed, and no face-recognition system can recover them, because there
is no face in the frame. X-Ray records scene membership; the pipeline
measures visible faces. In ensemble scenes these two quantities diverge, and
that gap accounts for most of the false-negative count.</p>
<h2 id="every-distinct-out-of-cast-name">Every distinct out-of-cast name<a class="headerlink" href="#every-distinct-out-of-cast-name" title="Permanent link">&para;</a></h2>
<p>Many Saints of Newark has the largest misID count of any held-out film: 974
seconds, weighted. Rather than characterize this from a single frame, the
raw replay stream was searched directly for every name the pipeline reports
that is not in the film's credited cast. The same search was run on all 9
films in the benchmark, one rule applied uniformly: <strong>find the first second
each distinct out-of-cast name appears, and render that exact second.</strong></p>
<p>Five films produce no such name anywhere in their runtime: Benny &amp; Joon,
Café Society, Downton Abbey, Sound of Metal, Valerian. Zero out-of-cast
names across their entire length. Four films produce nine distinct names
between them, shown below in full, not a sample.</p>
<h3 id="the-many-saints-of-newark-4-names">The Many Saints of Newark: 4 names<a class="headerlink" href="#the-many-saints-of-newark-4-names" title="Permanent link">&para;</a></h3>
<p><img alt="Germar Terrell Gardner, first out-of-cast name in Many Saints" src="../assets/images/many_saints_fpi_gardner.jpg" /></p>
<p>Germar Terrell Gardner, t=848s, 78% confidence. A real, clearly visible
background actor. He is not in X-Ray's cast list for this film, but he is
credited in Jellyfin's independent cast metadata (see
<a href="#where-lvface-beat-x-ray">Where LVFace beat X-Ray</a> below). This is a
ground-truth gap, not a model error.</p>
<p><img alt="Archie Yates, second out-of-cast name in Many Saints" src="../assets/images/many_saints_fpi_yates.jpg" /></p>
<p>Archie Yates, t=2521s, 78% confidence. A real detected face, a genuine
lookalike confusion.</p>
<p><img alt="Zooey Deschanel, third out-of-cast name in Many Saints" src="../assets/images/many_saints_fpi_deschanel.jpg" /></p>
<p>Zooey Deschanel, t=2819s, 99% confidence. A real detected face at a dinner
table, high-confidence lookalike confusion.</p>
<p><img alt="Talia Balsam, fourth out-of-cast name in Many Saints" src="../assets/images/many_saints_fpi_balsam.jpg" /></p>
<p>Talia Balsam, t=4551s, 93% confidence. A real detected face. Talia Balsam
plays Mrs. Jarecki, a guidance counselor, in this film; she is confirmed
on screen by direct inspection of the frame. She does not appear in X-Ray's
<code>people.csv</code> for this title. This is a second ground-truth gap in the same
film, not a model error.</p>
<p>Two of these four names are ground-truth gaps (Gardner, Balsam), not
misidentifications. The other two (Yates, Deschanel) are genuine embedding
errors on real faces.</p>
<h3 id="lord-of-war-3-names">Lord of War: 3 names<a class="headerlink" href="#lord-of-war-3-names" title="Permanent link">&para;</a></h3>
<p><img alt="David Shumbris, first out-of-cast name in Lord of War" src="../assets/images/lord_of_war_fpi_shumbris.jpg" /></p>
<p>David Shumbris, t=418s, 81% confidence. A real face in a dim, low-detail
shot under a train track. A genuine lookalike confusion in poor lighting.</p>
<p><img alt="Ronald Reagan, second out-of-cast name in Lord of War" src="../assets/images/lord_of_war_fpi_reagan_photo.jpg" /></p>
<p>Ronald Reagan, t=1003s, 100% confidence. This is not a lookalike confusion.
The detected face is a photograph of Reagan appearing within the shot, not a
living actor. The detector and matcher both did their job correctly on the
image content in front of them; the error is that a photograph inside the
scene is not the same thing as an actor present in the scene, and the
pipeline has no way to draw that distinction from a face crop alone.</p>
<p><img alt="Lance Reddick, third out-of-cast name in Lord of War" src="../assets/images/lord_of_war_fpi_reddick.jpg" /></p>
<p>Lance Reddick, t=6424s, 78% confidence. A small, distant, low-detail face at
the edge of frame. A marginal, low-confidence lookalike confusion.</p>
<h3 id="lovelace-1-name">Lovelace: 1 name<a class="headerlink" href="#lovelace-1-name" title="Permanent link">&para;</a></h3>
<p><img alt="Chloë Sevigny, out-of-cast name in Lovelace" src="../assets/images/lovelace_fpi_sevigny.jpg" /></p>
<p>Chloë Sevigny, t=2451s, 100% confidence. Two boxes are drawn on the same
face: one correctly labeled Amanda Seyfried, one incorrectly labeled Chloë
Sevigny, both at 100%. A single detection producing two competing high-
confidence identities on the same crop.</p>
<h3 id="scarface-1-name">Scarface: 1 name<a class="headerlink" href="#scarface-1-name" title="Permanent link">&para;</a></h3>
<p><img alt="Kirstie Alley, out-of-cast name in Scarface" src="../assets/images/scarface_fpi_alley.jpg" /></p>
<p>Kirstie Alley, t=2451s, 89% confidence. Al Pacino is correctly identified in
the foreground at 100%; a background face in the same shot is wrongly
labeled Kirstie Alley. (The t=2451s here and the Lovelace Chloë Sevigny case
above landing on the identical second is a genuine coincidence, verified from
each film's raw stream by <a href="https://gitea.tourolle.paris/dtourolle/scene-actor-extraction/raw/commit/0bd27470698c45cab21935d636a04512360e1008/scripts/docs/first_fpi_frames.py"><code>first_fpi_frames.py</code></a>,
not a transcription slip, two unrelated films whose <em>first</em> out-of-cast name
happens to fall at the same timestamp.)</p>
<h3 id="summary-of-the-nine">Summary of the nine<a class="headerlink" href="#summary-of-the-nine" title="Permanent link">&para;</a></h3>
<table>
<thead>
<tr>
<th>film</th>
<th>name</th>
<th>t (s)</th>
<th>confidence</th>
<th>classification</th>
</tr>
</thead>
<tbody>
<tr>
<td>Many Saints of Newark</td>
<td>Germar Terrell Gardner</td>
<td>848</td>
<td>78%</td>
<td>ground-truth gap</td>
</tr>
<tr>
<td>Many Saints of Newark</td>
<td>Archie Yates</td>
<td>2521</td>
<td>78%</td>
<td>lookalike confusion</td>
</tr>
<tr>
<td>Many Saints of Newark</td>
<td>Zooey Deschanel</td>
<td>2819</td>
<td>99%</td>
<td>lookalike confusion</td>
</tr>
<tr>
<td>Many Saints of Newark</td>
<td>Talia Balsam</td>
<td>4551</td>
<td>93%</td>
<td>ground-truth gap</td>
</tr>
<tr>
<td>Lord of War</td>
<td>David Shumbris</td>
<td>418</td>
<td>81%</td>
<td>lookalike confusion</td>
</tr>
<tr>
<td>Lord of War</td>
<td>Ronald Reagan</td>
<td>1003</td>
<td>100%</td>
<td>photo-in-frame</td>
</tr>
<tr>
<td>Lord of War</td>
<td>Lance Reddick</td>
<td>6424</td>
<td>78%</td>
<td>lookalike confusion, marginal</td>
</tr>
<tr>
<td>Lovelace</td>
<td>Chloë Sevigny</td>
<td>2451</td>
<td>100%</td>
<td>lookalike confusion</td>
</tr>
<tr>
<td>Scarface</td>
<td>Kirstie Alley</td>
<td>2451</td>
<td>89%</td>
<td>lookalike confusion</td>
</tr>
</tbody>
</table>
<p>Of nine distinct out-of-cast names across four films, two are ground-truth
gaps, one is a photograph misread as a person, and six are genuine
embedding-space confusions on real detected faces. None trace to extinction
bridging: every one of these nine is a fresh detection on a real face crop
at the second it first appears.</p>
<h2 id="where-lvface-beat-x-ray">Where LVFace beat X-Ray<a class="headerlink" href="#where-lvface-beat-x-ray" title="Permanent link">&para;</a></h2>
<p>Not every orange in these frames is actually wrong.
<a href="https://gitea.tourolle.paris/dtourolle/scene-actor-extraction/raw/commit/4b5557974bef8783bacc375c0869e8f589d1b0a3/scripts/optimizer/second_score.py"><code>scripts/optimizer/second_score.py</code></a>
scores strictly against X-Ray — but X-Ray itself has holes, and the pipeline
found two kinds.</p>
<p>Not every name marked wrong is actually wrong.
<a href="https://gitea.tourolle.paris/dtourolle/scene-actor-extraction/raw/commit/0bd27470698c45cab21935d636a04512360e1008/scripts/optimizer/second_score.py"><code>scripts/optimizer/second_score.py</code></a>
scores strictly against X-Ray, and X-Ray has gaps of its own.</p>
<p><img alt="LVFace correctly identifies Germar Terrell Gardner, uncredited by X-Ray" src="../assets/images/germar_beats_xray.jpg" /></p>
<p>Germar Terrell Gardner — a real, clean, high-confidence detection — is counted
as an out-of-cast misID because he doesn't appear in X-Ray's <code>people.csv</code> for
The Many Saints of Newark at all. But Jellyfin's independent cast metadata
<em>does</em> credit him for this exact film (cross-checked via
<code>experiments/manifests/jellyfin_casts.json</code> from the <code>experiment-data</code> artifact
package, a completely separate data source from X-Ray). That's also him in
orange in the frame above — every one of those "errors" is the pipeline being
right about a person X-Ray forgot.</p>
<p>Germar Terrell Gardner, the same name from the table above, does not appear
in X-Ray's <code>people.csv</code> for The Many Saints of Newark. Jellyfin's
independent cast metadata does credit him for this film (cross-checked
against <code>experiments/manifests/jellyfin_casts.json</code> from the
<code>experiment-data</code> artifact package, a data source entirely separate from
X-Ray). Talia Balsam is the same case: confirmed on screen, absent from
X-Ray's cast list for this title.</p>
<p><img alt="Robert Patrick, clearly on screen, scored wrong by a ground-truth gap" src="../assets/images/lovelace_robert_patrick_fpi.jpg" /></p>
<p>And it isn't only uncredited bit-parts. That is <strong>Robert Patrick</strong> — top-billed
in Lovelace, unmistakably on screen, reading his newspaper, identified at
100% scored orange because X-Ray's people-in-scene list for <em>this scene</em>
doesn't include him. The identification is flawless; the ground truth missed
an actor sitting in the middle of the frame.</p>
<p>This doesn't mean every flagged misID is secretly correct — Many Saints'
974-count total is still overwhelmingly extinction bridging at cuts, not
uncredited cameos. But the X-Ray corpus is a convenient, large-scale ground
truth, not a perfect one, and the misID/FPI numbers in these tables carry an
irreducible noise floor from ground-truth gaps in both directions.</p>
<p>This extends past uncredited background actors. This is Robert Patrick,
top-billed in Lovelace, clearly on screen reading a newspaper, identified at
100%. The frame is scored wrong because X-Ray's people-in-scene list for
this specific scene omits him, despite crediting him elsewhere in the film.
The identification is correct; the ground truth is missing an entry.</p>
<p>X-Ray is a large, convenient ground truth. It is not a complete one. The
misID and FPI counts reported throughout this document include some fixed
amount of noise from gaps in X-Ray itself, in both directions.</p>
<h2 id="summary">Summary<a class="headerlink" href="#summary" title="Permanent link">&para;</a></h2>
<p>LVFace is the right default: it wins the model comparison outright, it names
19 of 20 correctly across a hat-heavy funeral crowd, and it recognises a face
on a screen inside the movie. Its error budget decomposes into two understood
mechanisms extinction bridging at hard cuts (a tunable trade, not a bug) and
the face-vs-presence ceiling baked into X-Ray's semantics — plus a nonzero
slice where the pipeline is right and the ground truth is wrong. The held-out
generalization gap (75.3% → 67.4%) is real and should be treated as the honest
expected performance, not the training-set number.</p>
<p>LVFace wins the model comparison on every held-out film. It correctly names
19 of 20 people in a crowded funeral scene and correctly identifies a face
displayed on a screen inside the film. Its errors resolve into two
mechanisms: extinction bridging, which is correct on most footage and fails
specifically at hard cuts into long faceless stretches, and the
face-versus-presence ceiling, where X-Ray credits scene membership for
people whose faces never appear on screen. Of the nine distinct
out-of-cast identifications found across the benchmark, two trace to gaps in
X-Ray's own cast data, one is a photograph misread as a person, and six are
genuine lookalike confusions on real faces. The held-out generalization gap,
75.3% training to 67.4% held-out, is real and should be treated as the
expected operating point, not the training-set figure.</p>
@@ -1141,13 +1426,13 @@ expected performance, not the training-set number.</p>
<a href="../model-bakeoff/" class="md-footer__link md-footer__link--next" aria-label="Next: Model Bake-off &amp; Re-tune (full log)">
<a href="../model-bakeoff/" class="md-footer__link md-footer__link--next" aria-label="Next: Full Experiment Log">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Model Bake-off & Re-tune (full log)
Full Experiment Log
</div>
</div>
<div class="md-footer__button md-icon">