fix(speaker): cross-condition negative-exemplar veto via condition transport#1497
Merged
Conversation
…ansport The negative-exemplar veto (#1487) was "sound but regime-limited" (eval in #1493): after a correction it removed 46% of repeat wrong-matches in-room (AMI) but only 12% cross-condition (VoxCeleb). Root cause: a single rejected in-room sample and a later telephone/VoIP sample of the same rejected impostor sit too far apart in embedding space for the raw cosine to clear the 0.80 veto floor. The positive side already closed this gap with multi-exemplar voiceprints (#1488); the negative side — one rejected embedding — had no analog. Give the negative side the same multi-condition treatment (eval rec #3): compare the candidate against each rejected sample AND against that sample transported along the profile's own observed condition shifts (unit(exemplar) − average). Channel/condition shifts are largely speaker-independent, so a rejected sample shifted by a condition the profile has actually seen approximates the same rejected voice returning in that other condition. Owner-safe by construction: - transport only along +(exemplar − average) — real, forward, profile-observed conditions; bidirectional/synthetic directions were measured to leak owner-collateral and are not used. - a profile with no positive exemplars derives nothing → reduces exactly to the raw maxNegativeSimilarity → single-condition profiles unchanged. - the 0.80 floor and the ≥positiveSimilarity owner gate are untouched; transport only widens which impostor returns are caught, never lowers the floor. Real qmatrix eval (SpeakerExemplarDeltaEvalTests): AMI cross-condition vetoed-among-re-match 0.350 → 0.374 (+7.0% rel) with owner-collateral flat (2.17% → 2.32%, +9 of 5773 checks). VoxCeleb (single-utterance corpus, no condition structure) byte-identical, incl. owner-collateral — no regression. Pushing VoxCeleb's 12% further was investigated and rejected: every mechanism that moves it trades owner-collateral ~1:1, violating the #1493 guardrail. See docs/speaker-eval-negative-veto-cross-condition-2026-07.md. Refs #1493. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
509a9c7 to
c790cfe
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Strengthens the negative-exemplar veto (#1487) so it fires cross-condition, implementing recommendation #3 of the PR #1493 eval (
docs/speaker-eval-exemplar-delta-2026-07.md): "give a profile's negative exemplars the same multi-condition treatment as its positive ones."Why
PR #1493 measured the veto as "sound but regime-limited": after a correction it removes 46% of repeat wrong-matches in-room (AMI) but only 12% cross-condition (VoxCeleb). A rejected in-room sample and a later telephone/VoIP sample of the same rejected impostor sit too far apart in embedding space for the raw cosine to clear the 0.80 veto floor — so a correction made in one audio condition failed to protect the owner in another. The positive side already closed this exact gap with multi-exemplar voiceprints (#1488); the negative side (a single rejected embedding) had no analog.
How
SpeakerNegativeExemplarPolicygains a condition-transported negative similarity. Beyond raw cosine to each stored rejected sample, the candidate is compared against each rejected sample transported along the profile's own observed condition shifts —unit(exemplar) − average, reusing the positive multi-exemplar voiceprints. Channel/condition shifts (clean → compressed remote → telephone) are largely speaker-independent, so a rejected sample shifted by a condition the profile has actually seen approximates the same rejected voice returning in that condition.Owner-safe by construction (the #1493 guardrail is the priority):
+(exemplar − average)— real, forward, profile-observed conditions. Bidirectional/synthetic directions were measured to leak owner-collateral and are not used.maxNegativeSimilarity→ single-condition profiles (and any store with no negatives) are byte-for-byte unchanged.≥ positiveSimilarityowner gate are untouched. Transport only widens which impostor returns are caught; it never lowers the floor, so a genuine owner — closer to its own fingerprint than to a transported impostor sample — is still protected.Results — real qmatrix corpus (
SpeakerExemplarDeltaEvalTests)Same harness/corpus/operating point as #1493.
RAW= single stored rejected sample (pre-fix);TX= condition-transported (this PR); both use the unchanged 0.80/≥posgate.AMI (in-room, 147 profiles, 535 cross-condition wrong re-matches, 5773 owner checks)
VoxCeleb (single-utterance, 30 profiles) — byte-identical (0.123→0.123; owner-collateral 1.56%→1.56%): no condition structure to transport along, and no regression.
On VoxCeleb's 12%
It doesn't move — and that is correct, not a miss. VoxCeleb is single-short-utterance-per-meeting, so a "cross-condition" replay differs from the rejected sample in content/session as much as in channel; a channel transport can't (and shouldn't) bridge that. Real returning Transcripted users are AMI-like (repeated appearances across conditions → multi-exemplar structure), which is the regime this improves. Pushing VoxCeleb's 12% harder was investigated across floor-lowering, ramped owner-margins, global channel subspaces, and orthogonal-complement distance — every mechanism trades owner-collateral for veto coverage at a ≈1:1-or-worse absolute rate (best case removed +39 wrong re-matches while adding +56 owner false-vetoes), which is net-negative in production and violates the #1493 guardrail. Condition transport is the one lever that gains cross-condition coverage without a net owner cost.
Full write-up:
docs/speaker-eval-negative-veto-cross-condition-2026-07.md.Tests
SpeakerNegativeExemplarPolicyTests12/12 — new fixtures: same-impostor-different-condition (veto now fires), owner-different-condition (no false veto), no-exemplars-equals-raw (byte-identical fallback).SpeakerNegativeExemplarTests7/7,SpeakerNamingSimulationRunnerTests7/7, full Core suite 714 passed / 0 failed (13 corpus-gated skips),SpeakerExemplarDeltaEvalTestspasses on the real corpus.Coordination
Orthogonal to #1496 (average-based auto-accept margin): that PR changes the auto-accept margin computation; this changes the negative-veto representation. They touch
SpeakerMatchingService.swiftandSpeakerExemplarDeltaEvalTests.swiftin different regions. #1496 should land first; I'll rebase this onto it, keeping both changes.Refs #1493, #1487, #1488.
🤖 Generated with Claude Code