Thanks to visit codestin.com
Credit goes to github.com

Skip to content

SelectFromModel's prefit fails unless fit is called when set_output(transform="pandas") #34880

Description

@solegalli

Warning

This issue is not yet ready for a PR. If you are interested in contributing to scikit-learn, please have a look at our contributing guidelines, and in particular the sections for new contributors and the "Needs triage" label.

Introduce yourself

My understanding is that if prefitis true, one could, in principle call transform() without calling fit() first.

While this is true if we don't set the output to pandas, it fails when we do so:

Minimal reproduction:

import pandas as pd
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import SelectFromModel

X, y = load_iris(as_frame=True, return_X_y=True)
clf = LogisticRegression(max_iter=1000).fit(X, y)

# prefit=True -- docs say we don't need to call .fit() on sel
sel = SelectFromModel(clf, prefit=True).set_output(transform="pandas")

sel.transform(X)
NotFittedError: This SelectFromModel instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.

Without .set_output(transform="pandas"), the identical prefit=True selector transforms X just fine with no .fit() call.

The error only appears once pandas output is requested, because set_output internally calls get_feature_names_out(), which checks whether the wrapper itself has been fitted (via check_is_fitted(self), not check_is_fitted(self.estimator)).

According to Claude, that check was intentionally added in #25308 to standardize get_feature_names_out() behavior across SelectorMixin estimators.

So my question is: is this expected behaviour? or is it an unintended bug?

From a user perspective, if I use fitagain, even though prefit is True, I get the impression that my estimator would be re-fitted, so if this is intended, it might be worth adding a line in the docs.

sel.fit(X, y)     # with prefit=True, does NOT retrain clf -- just
                  # deep-copies it and records feature_names_in_
sel.transform(X)  # now works

Describe the issue linked to the documentation

SelectFromModel's prefit parameter is documented as:

prefit : bool, default=False
Whether a prefit model is expected to be passed into the constructor directly or not. If True, estimator must be a fitted estimator. If False, estimator is fitted and updated by calling fit and partial_fit, respectively.

Maybe it's just me, but I sort of read this as, if the estimator is prefit, I could avoid calling fit and it would be just fine.

Suggest a potential alternative/fix

Add a note to the prefit parameter docstring, e.g.:

Note: even with prefit=True, .fit() must still be called before using get_feature_names_out() or set_output(transform="pandas"), since these check whether the selector itself (not the underlying estimator) has been fitted. Calling .fit() in this case does not refit estimator; it only records bookkeeping metadata (estimator_, feature_names_in_).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions