When fits run
- The first run starts within a few minutes of the first outcome you post, or of the judgment’s first outcome rules. A run makes a fit only for an epoch that meets the minimums, so the first run usually makes none.
- Until there is a fit, Brussle runs again every hour, for the current epoch and for a new epoch with no fit yet. The first fit comes within the hour after your outcomes meet the minimums.
- Once there is a fit, Brussle makes a new fit each night, on all the outcomes so far, rule outcomes included. It replaces the current fit only under the rule below.
- When Brussle re-judges answers to correct them, the next run starts within a few minutes after the correction ends. See when answers are corrected.
Fit now
To fit at once, for example right after you post the outcomes that meet the minimums, callPOST /namespaces/{ns}/judgments/{name}/calibration/fit (fitCalibration, fit_calibration), or select Fit now in the judgment’s Calibration section. The run usually ends within a minute or two. Then read the report.
- You can ask once an hour for each judgment. Within that hour, the call returns
rate_limited(429), andRetry-Aftergives the seconds until the next call is accepted. Named runs share this limit. - If a run is already waiting or running, that run serves the call.
- It runs on every plan, and it is never billed.
The rule
The challenger replaces the current fit only when both are true:- It is clearly better on the outcomes that arrived since the current fit was made. The current fit never saw them, so they are a fair test of both. The challenger is scored on each of them without that outcome, and must beat the current fit by more than two standard errors of the mean difference in log loss.
- It moves the number by at least a point: 0.01 on average over all the judgment’s outcomes. For a
choiceorscore, this is the probability that moves between the options.
fit id, and nothing is judged again.
- An outcome arrives when you post it, not when it was observed. An implicit negative arrives when its window closes. After the engine changes, a replayed outcome arrives when it is replayed. An outcome whose answer was judged again with changed inputs counts as new too.
- The current fit is withdrawn when the engine’s raw numbers beat it by the same margin on the outcomes since. Answers then read the night’s fit, or the raw numbers if that did not beat them.
- A new start takes the night’s fit at once: the first fit, a new engine epoch, a new version, and a change from fitting on all outcomes to fitting on labelling-queue labels alone, or back.
- Below 100 outcomes, while the current fit or the night’s rests on fewer than 100, each night’s fit replaces the current one, under the margin below 100 rather than this test.
- When a run cannot fit again, because outcomes were deleted and the epoch fell below the minimums, the current fit stays.
- It applies to every judgment: to
calibratedon abool, achoiceand ascore, topof a judgment with features, and to a template tenant’s own fit and its own weights, on that tenant’s own outcomes. The exception is a choice among candidates with features: each run’s fit replaces the current one, as a first fit does. - On a steady process, the rule changes the fit by chance about once in three to five years for each version and epoch. A real change in your outcomes, such as a new base rate, shows in the outcomes since, and the new fit replaces the current one once it is clearly better.
Read the current fit and the challenger
Each epoch of the report shows both:current: the fit answers read now.fitis its id, ornullwhen it did not beat the raw numbers.runholds it.pinnedistruefor a pinned fit, andpin_suspendedisolder_preprocessingwhen the pin is suspended.fitted_atis when the run that made it ran; a fit kept since an earlier run keeps that date, so it can be weeks older than the newest run.sincemeasures it against the raw numbers on the outcomes that arrived after it was made:outcomes,fallback_log_loss(the raw numbers’),log_loss(the current fit’s) and thestandard_errorof the difference.sinceisnullwhile those outcomes hold fewer than 20 of each kind, and on the night the fit was made.currentisnullwhile the epoch has no fit of its own.challenger: the newest run’s fit when it did not replace the current one;nullwhen it did, and when there was no current fit. It has its ownfit,run,fitted_at,outcomesandheld_out, andversus_current: the challenger against the current fit on the outcomes since.gainis the current fit’s log loss minus the challenger’s, so a positivegainfavours the challenger.shiftis how far the challenger would move the number on average over every outcome.gainandstandard_errorarenullwith fewer than 20 of each kind since. On achoiceorscorewith features,moved_picksis the share of outcomes whose most probable option would change.
tenant.current and tenant.challenger say the same of the tenant’s own fit, against the pool (fallback: pooled). See per-customer corrections.
Why a new fit was held
challenger.held says why the current fit stays:
too_few_outcomes_since: fewer than 20 of each kind arrived since the current fit was made. Post more outcomes, or wait for them.not_clearly_better: on the outcomes since, the new fit did not beat the current one by more than two standard errors (versus_current.gainandstandard_error). The difference is within noise.too_small_a_move: the new fit is better, but would move the number by less than 0.01 on average (versus_current.shift). On a judgment with features, each move re-judges the judgments that readp, billed, so a move this small is not worth it.pinned: a pin holds the fit.
current.since tells whether the current fit still beats the raw numbers on outcomes it never saw; when it stops doing so by the same margin, the next run withdraws it.
Promote the newest fit
To make the newest fit current for every version and epoch now, whether or not it is clearly better, call Fit now withpromote:
- The run makes its own new fit and applies it. It fits all the outcomes so far, as a nightly run does, and that fit becomes current for each version and epoch that is not pinned, tenants included. A promote never moves a pin.
- With readers, confirm first. On a
boolwith features that other judgments read, a new current fit judges their documents again, billed. Withoutconfirm, the call returns thedownstreamestimate (200), made against last night’s fits, and queues nothing. Withconfirm: true, the run is queued, and the answer carries the estimate too. - A confirmed promote is not held by the hourly limit. You accepted its cost, so it is queued even within an hour of Fit now. Without readers, a promote is queued at once and counts as Fit now’s request for the hour.
- Templates. On a namespace that inherits the judgment, a promote is
invalid_request; promote on the template. Fit now without a body still queues the template’s run.
Pin a fit
By default, each answer reads the current fit for its version and epoch (auto). A pin holds one fit you choose for one version and epoch: to hold a fit you checked, or to go back to an earlier one. Name the fit as the list of fits shows it: its run, version, engine and engine_version. fit is optional; when you give it, Brussle checks it is that run’s fit.
- Send
calibrationalone in itsPATCH /namespaces/{ns}/judgments/{name}, without other settings, or the request isinvalid_request. - The list replaces all the pins. Include the pins you want to keep. A pin sent again from the same run stays as it is. Two pins for one version and epoch is
invalid_request. - The pin writes a run (
cause: pin) that holds the pinned fit, and every later run holds it too. The response has the judgment, withcalibration: {"mode": "pinned", "pins": [...]}, and each pin haspinned_at.modeisautowhen no pin applies. - Answers of that version and epoch read the pinned fit, also when a later fit would do better. Every other version and epoch stays
auto. Each run still makes a fit and lists it as the challenger; when it clearly beats the pinned fit on the outcomes since, the report warnspinned_fit_beaten. - A pin is a setting, like thresholds. It makes no version, and a new version starts in
auto. - On any judgment without features, a pin changes only
calibrated. Readers use the raw numbers, so nothing is judged again or billed, and there is nothing to confirm.
bool with features that other judgments read, a pin also stops the nightly re-judging of readers for that version and epoch. A pin of a fit other than the one p reads now changes p once, so Brussle judges again the readers whose view of it changes, billed as any re-judge. Confirm it first, as for a threshold change a reader reads:
confirm, the response is only the downstream estimate, and nothing changes. With confirm: true, the pin applies and a resync job starts; the response has the judgment, job_id and downstream. The dashboard shows the cost first and asks you to confirm.
Brussle refuses a pin with invalid_request when the run is not in the judgment’s list of fits; the run has no fit for that version and epoch, for example because it did not beat the raw numbers; fit is not that run’s fit; the fit uses features and was made before Brussle last changed how it keeps features; or the namespace inherits the judgment from a template (set the pin on the template; see per-customer corrections). If the pins changed between your read and your write, the request is conflict: read the judgment and send the list again.
A pin and a new epoch
A pin never reaches another epoch. After the engine changes by itself, the new epoch starts inauto. Until it has its own fit, its answers read the previous epoch’s fit as usual, which here is the pinned fit, with "from_previous_epoch": true and "pinned": true. The 30-day limit for calibrated applies as for any fit. p of a bool with features keeps the pinned fit until the new epoch has its own.
A suspended pin
Sometimes Brussle changes how it keeps features, and a fit with features made before the change cannot read the features after it. At the next run its version and epoch readauto: the pin shows "suspended": "older_preprocessing", the answer shows "pinned": false, and the report warns pin_suspended. Pin a fit made since, or lift the pin. A pin of a fit without features is never suspended.
Lift a pin
Send the list of pins without it.{"calibration": {"pins": []}} lifts them all:
- The next run comes at once. Brussle brings it forward, usually within a few minutes. It does not count toward Fit now’s limit, and the list of fits shows it as
cause: nightly. - Until that run ends, answers read the pinned fit and still show
"pinned": true.GETon the judgment already showsmode: auto. - A lift keeps the number until a clearly better fit arrives. The formerly pinned fit stays current, now in
auto, and that run’s fit replaces it only when it is clearly better on the outcomes since the pinned fit was made, usually many by then. To take tonight’s fit anyway, promote. On aboolwith features, when the fitpreads changes, readers are re-judged and billed, with no confirm.
bool with features each change re-judges the readers. The report’s replay.status is done when it has ended.
Events when the fit changes
On a judgment with features,p is the corrected number and readers act on it. When the fit that p reads changes (its first fit, a promotion, a withdrawal, a pin or a lift), Brussle brings up to date the judgments that read it: it judges again the documents whose view of it changed, billed like any re-judge. A night that keeps the current fit re-judges nothing. Then:
judgment.fit_appliedreports how many documents crossed each of the judgment’s thresholds. Whenpgoes back to the engine’s, the event isjudgment.fit_withdrawn. Both carryfit,runandpinned.- The event gives each reader’s re-judges:
engine_judgments, which are billed, andreuses, re-judges where only a feature the reader keeps moved, which use their engine answer again at no charge. - The counts come from those re-judges, so the event arrives after they have started.
calibrated, so a new fit judges nothing again.