Make the panel score absolute so two evaluations can be compared - #97
Merged
Conversation
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.
Groundwork for evaluating occasionally during an epoch rather than only at its boundary. That is impossible while the panel's scores only mean something inside one call, which is what they did.
The problem
rank()put every pair to the panel and scored each candidate by how many rivals it beat. That ranks a field correctly and says nothing outside it: the same drawing scores differently depending on who it was ranked against. Its own docstring said "nothing compares them against an absolute threshold."Two consequences. Scores could not be cached — a value from an earlier call was meaningless later. And cross-run comparisons made with these numbers were invalid, including one I reported today: v8 at 0.004392 against v7 at 0.019767 is not a 4.5x improvement, it is two candidates each near the top of a different field.
Calibrated median
Each member's raw cosine distance is divided by that member's distance from the target to a blank canvas, measured once when the reference is prepared. 0 is the target, about 1 is as wrong as an empty drawing — on every member and every target.
Calibration is what makes combining them honest. The members are cosine distances from three different embedding spaces spanning different widths, so an uncalibrated average is decided by whichever member spreads widest: one model steering the run, the thing a panel exists to prevent.
Then the median, which is the panel argument in absolute form. With three members the median is the majority position: for any standard you might hold a candidate to, "the panel says it meets this" is true exactly when the median says so, and a member that is idiosyncratic about this particular drawing cannot move it. The pairwise vote said that about pairs; this says it about candidates, which is what lets two scores be compared at all.
The cache this unlocks
rank_frontnow skips any node that already carriesFRONT_SCOREand recalls the stored value. A run asks about the same pool members repeatedly, and re-rasterising and re-embedding one the evaluator has already seen bought an identical number at full price. A call the cache answers in full no longer loads a model at all.Not here yet
The periodic evaluation itself.
rank_frontis a closure insiderun_vector_search, so the caching path above has no unit test — extracting it to a module-level function is the next step and makes both testable.