cleverly.learners.CrossFitPlan#
- class cleverly.learners.CrossFitPlan(n_folds: int = 10, learner_folds: int = 5, scheme: str = 'stratified', stratify_by: tuple[str, ...] = (), random_state: int | None = None, repeats: int = 1)[source]#
The fold policy a fit declared, as distinct from the split it got.
Every field is a number or a string, so a plan is comparable, hashable and serialisable, and says nothing about any particular dataset. What a plan realises on one is a
Folds, and the two can differ:resolve_n_folds()capsn_foldsat the rarest stratum and again at the cluster count, both with a warning at fit time and no trace afterwards. Recording the plan beside the realised count is what makes “why did my 10-fold fit run 3 folds?” answerable from a saved result.Built from the estimator’s own keyword arguments by
crossfit_plan()and held onTMLEConfig, exactly asTargetingSpecis – so the settings appear once and cannot drift.- Parameters:
- n_folds
int Outer folds, the ones that make the nuisance predictions out of fold.
1meanscross_fit=False.- learner_folds
int Inner folds, which score Super Learner’s candidates inside one outer training fold. A separate declaration rather than the same one: this is model selection, not what makes a prediction out of fold, and its stratum is the learner’s own target – the treatment for the mechanism, the outcome for the regression.
- scheme
str Which family of split the fit used.
"supplied"means a caller handed over exact assignments and nothing was generated."none"means the fit drew no split. The other two are resolved from what the data declared rather than chosen:"grouped"wheneverid=named clusters, and"vfold"otherwise.- stratify_by
tupleofstr What the outer folds were checked against, as user-facing names. Empty on every fit this version runs, because it draws no split that balances the data it then conditions on. A copied or modified estimator can declare names here, and its fit then refuses.
- random_state
intorNone Seed for generated outer splits and repeat-specific learner state. Under
scheme="supplied", the assignments ignore it while learner and collaborative selection folds remain seeded. A seed is not enough to reproduce a generated split on its own; seecleverly.provenance.- repeats
int How many independent draws of the whole split the fit combines by median.
1is an ordinary fit. A count layered over whicheverschemethe data resolved to, not a scheme of its own – repeating a grouped split gives grouped splits.
- n_folds
Methods#
- CrossFitPlan.describe() str[source]#
Return a readable description.
- Returns:
strOne line naming the fold count, the repeats, and the stratification.
- CrossFitPlan.seeds() tuple[int | None, ...][source]#
One seed per repeat, for the fold draws to combine.
Spawned from
random_staterather than derived by addition, so the draws are independent rather than merely different, and a repeated fit stays reproducible under a seed.random_state=NoneyieldsNoneper repeat, because the plan is a declaration and the caller declared no seed. The engine does not draw withNone:_repeat_draws()replaces eachNonewith a fresh seed from operating-system entropy, in the same[0, 2**31 - 2]range, before it draws the folds. That seed reaches the folds, the learners and the C-TMLE selection folds, andseedrecords it on the result. The plan keepsrandom_state=None, so the result still says that the caller fixed no seed.One repeat passes
random_statestraight through rather than spawning from it, which is what makesrepeats=1bit-for-bit an ordinary fit rather than merely an equivalent one.tests/unit/test_repeated_crossfit.pyenforces that.- Returns:
tupleofintorNoneOne seed per repeat, derived from
random_state.
Attributes#
- CrossFitPlan.cross_fit#
Whether the outer nuisance fits are cross-fitted at all.
- CrossFitPlan.repeated#
Whether more than one draw of the split was combined.