Summary
WithinSessionSplitter.__init__ (and WithinSubjectSplitter) overwrites an explicitly
passed n_splits (and shuffle / random_state) in cv_kwargs with its own n_folds,
unconditionally:
self._cv_kwargs = dict(**cv_kwargs)
params = inspect.signature(self.cv_class).parameters
for p, v in [("n_splits", n_folds), ("shuffle", shuffle), ("random_state", self._rng)]:
if p in params:
self._cv_kwargs[p] = v # clobbers a value the caller already put in cv_kwargs
So a caller can't ask for a different fold count than n_folds even when the inner CV exposes
n_splits.
Repro
from sklearn.model_selection import StratifiedShuffleSplit
from moabb.evaluations.splitters import WithinSessionSplitter
sp = WithinSessionSplitter(cv_class=StratifiedShuffleSplit, n_splits=1, test_size=0.25,
shuffle=True, random_state=42)
# wanted: a single 75/25 stratified split per session; got: 5 folds (n_splits overwritten by n_folds)
Use case / current workaround
We want a single stratified train/test split at a paper-reported ratio. Because the explicit
n_splits=1 is clobbered, we wrap StratifiedShuffleSplit in a class that simply doesn't expose
n_splits (so the loop above skips it and the inner split count stays 1). A no-op wrapper that only
exists to dodge the overwrite.
Proposed
Only inject the default when the caller hasn't already provided it:
for p, v in [("n_splits", n_folds), ("shuffle", shuffle), ("random_state", self._rng)]:
if p in params and p not in cv_kwargs:
self._cv_kwargs[p] = v
Backward compatible (defaults unchanged when cv_kwargs doesn't set these), and lets a single
holdout split be requested via plain cv_class=StratifiedShuffleSplit, cv_kwargs={n_splits:1, ...}.
Happy to PR.
Summary
WithinSessionSplitter.__init__(andWithinSubjectSplitter) overwrites an explicitlypassed
n_splits(andshuffle/random_state) incv_kwargswith its ownn_folds,unconditionally:
So a caller can't ask for a different fold count than
n_foldseven when the inner CV exposesn_splits.Repro
Use case / current workaround
We want a single stratified train/test split at a paper-reported ratio. Because the explicit
n_splits=1is clobbered, we wrapStratifiedShuffleSplitin a class that simply doesn't exposen_splits(so the loop above skips it and the inner split count stays 1). A no-op wrapper that onlyexists to dodge the overwrite.
Proposed
Only inject the default when the caller hasn't already provided it:
Backward compatible (defaults unchanged when
cv_kwargsdoesn't set these), and lets a singleholdout split be requested via plain
cv_class=StratifiedShuffleSplit, cv_kwargs={n_splits:1, ...}.Happy to PR.