Repository navigation
Conversation
RepresentationSearchCV stratified its folds for a classifier but built every candidate Preprocessor with the default task="regression". Target-aware placement then crashed on string class labels and treated integer labels as a regression target. A classifier now defaults the preprocessors to task="classification"; an explicit task in preprocessor_params still wins. Fixes #77
This was referenced Oct 16, 2026
This branch has not been deployed
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.
Fixes #77.
RepresentationSearchCVaround a classifier built every candidatePreprocessorwith the defaulttask="regression". Target-aware candidates ("ple", and the feature maps and splines thatPreprocessorplaces on the target by default) crashed on string class labels, and they placed bins, centers and knots for integer labels with a regression model.Root cause
RepresentationSearchCValready checksis_classifier(self.estimator)to choose a stratified splitter, but_make_preprocessorforwarded onlyrandom_stateandpreprocessor_params, so it never derivedtaskfrom the estimator.Fix
RepresentationSearchCV._make_preprocessorsetstask="classification"withparams.setdefaultwhen the estimator is a classifier. Ataskgiven inpreprocessor_paramsstill takes precedence.Behaviour changes
task="classification": string labels work, integer labels are placed by a classification model (DecisionTreeClassifierfor"cart", LightGBM's classification objective for"lightgbm"), andbest_preprocessor_.taskis"classification". For binary 0/1 labels with"cart"placement the locations stay the same, as the issue explains. Multiclass labels and"lightgbm"placement can get different locations.taskinpreprocessor_params, are unchanged.Documentation
RepresentationSearchCVdocstring (preprocessor_params): with a classifier asestimator,taskdefaults to"classification". The private_make_preprocessordocstring says the same.docs/core_concepts/target_awareness.md("Searching over representations"): with a classifier, everyPreprocessorusestask="classification", so target-aware methods place against the class labels, and ataskset inpreprocessor_paramstakes precedence.Tests
test_classifier_search_places_against_class_labels: a search aroundLogisticRegressionon string labels with methods["minmax", "ple"]fits,best_preprocessor_.task == "classification", and the predictions are class labels. Fails onmain(could not convert string to float: np.str_('pos')), passes here.test_classifier_search_keeps_an_explicit_task:preprocessor_params={"task": "regression"}overrides the classifier default. Guard test: passes on both by design.test_regressor_search_keeps_the_regression_task: a search around a regressor keepstask="regression". Guard test: passes on both by design.Reproduction
Output of the script from #77 on this branch:
Checks
just test: 1441 passed, 59 skipped, 7 xfailed; coverage 93.65% (gate 90%).scripts/quickstart.pypasses.just docs: strict build succeeds.just check: all pre-commit and pre-push hooks pass (ruff format, ruff lint, prettier, file hygiene, pyright with 0 errors).Merge notes
main.pretab/compose/search.pyanddocs/core_concepts/target_awareness.md. Both files merge cleanly with this branch.tests/compose/test_search.pyhas an append/append conflict at the end of the file: keep both blocks. RepresentationSearchCV lacks predict_proba, classes_ and classifier tags, so nested roc_auc CV returns NaN #92 adds the sameclass_datafixture, which git merges into one definition. Combined with either branch this way, thetests/composesuite passes. After this PR, the explicit{"task": "classification"}in RepresentationSearchCV lacks predict_proba, classes_ and classifier tags, so nested roc_auc CV returns NaN #92's tests is redundant but harmless."classification"is a validtaskthere.preprocessor_params={"placement_strategy": "lightgbm"}, a classifier search on string labels still fails on this branch alone, because LightGBM placement uses the binary objective on the raw labels. It works once the PR for LightGBM placement with task="classification" always uses the binary objective on raw labels #61 (fix(placement): label-encode classification targets for LightGBM #105) is merged too (checked by combining the two branches).This change was previously part of #86, which is closed in favour of one pull request per issue.