Skip to content

Custom sklearn estimators implementing __sklearn_is_fitted__#1119

Merged
BenjaminBossan merged 6 commits intoskorch-dev:masterfrom
divakaivan:master
Aug 15, 2025
Merged

Custom sklearn estimators implementing __sklearn_is_fitted__#1119
BenjaminBossan merged 6 commits intoskorch-dev:masterfrom
divakaivan:master

Conversation

@divakaivan
Copy link
Copy Markdown
Contributor

@divakaivan divakaivan commented Aug 13, 2025

Closes #1118

Things to note:

  • I saw the docstring here so I made this __sklearn_is_fitted__ docstring similar
  • renamed the existing test_not_fitted_raises into test_not_init_raises but looking for advice on your preferences.
  • also not sure if a test_not_fitted_raises test is needed in all 3 of tests/test_net.py, tests/test_regressor.py and tests/test_classifier.py as the one in tests/test_net.py cover it. Again, seeking maintainers' preferences here.

cc @BenjaminBossan

Copy link
Copy Markdown
Collaborator

@BenjaminBossan BenjaminBossan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for creating this PR so quickly. I think it's not quite correct yet, though, so please check my comment.

Comment thread skorch/net.py Outdated
Copy link
Copy Markdown
Collaborator

@BenjaminBossan BenjaminBossan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update. Only a small comment, the rest looks good.

Comment thread skorch/net.py Outdated
@divakaivan
Copy link
Copy Markdown
Contributor Author

divakaivan commented Aug 15, 2025

Hmm ~ not sure this test fail is related to the changes from this PR, is it? 🤔 (it's a flaky test)

failed test
________________________________________ TestNeuralNet.test_fit_lbfgs_optimizer ________________________________________

self = <skorch.tests.test_net.TestNeuralNet object at 0x7f1d6182dea0>
net_cls = <class 'skorch.classifier.NeuralNetClassifier'>
module_cls = functools.partial(<class 'skorch.toy.MLPModule'>, output_nonlin=Softmax(dim=-1), input_units=20, hidden_units=10, num_hidden=2, dropout=0.5)
data = (array([[-0.96[58](https://github.com/skorch-dev/skorch/actions/runs/16988488056/job/48164133761?pr=1119#step:6:59)346 , -2.1890705 ,  0.16985609, ..., -0.89645284,
         0.3759244 , -1.0849651 ],
       [-0.454767..., 0, 1,
       1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0,
       0, 1, 1, 0, 1, 0, 1, 0, 1, 0]))

    @flaky(max_runs=5)
    def test_fit_lbfgs_optimizer(self, net_cls, module_cls, data):
        # need to randomize the seed, otherwise flaky always runs with
        # the exact same seed
        torch.manual_seed(int(time.time()))
        X, y = data
        net = net_cls(
            module_cls,
            optimizer=torch.optim.LBFGS,
            lr=1.0,
            batch_size=-1,
        )
        net.fit(X, y)
    
        last_epoch = net.history[-1]
>       assert last_epoch['train_loss'] < 1.0
E       assert np.float64(7.054504871368408) < 1.0

skorch/tests/test_net.py:2525: AssertionError
@BenjaminBossan
Copy link
Copy Markdown
Collaborator

Hmm ~ not sure this test fail is related to the changes from this PR, is it? 🤔 (investigating)

It's a flaky test, I simply restarted the run.

Copy link
Copy Markdown
Collaborator

@BenjaminBossan BenjaminBossan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing the imports. I only now noticed an issue with the indentation, sorry for not noticing earlier. Please also add a brief entry to the CHANGES.md.

Comment thread skorch/tests/test_classifier.py Outdated
divakaivan and others added 3 commits August 15, 2025 13:49
Two more in next commit

Co-authored-by: Benjamin Bossan <BenjaminBossan@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@BenjaminBossan BenjaminBossan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for implementing __sklearn_is_fitted__, the PR LGTM.

@BenjaminBossan BenjaminBossan merged commit 90add47 into skorch-dev:master Aug 15, 2025
16 checks passed
@divakaivan
Copy link
Copy Markdown
Contributor Author

Thanks for the help 🙏

BenjaminBossan added a commit that referenced this pull request Dec 19, 2025
There were two issues in skorch with sklearn v1.8 that are now fixed:

__sklearn_is_fitted__ should return a bool. Instead, we were just
raising or returning None. Not sure if this was already wrong when
added (#1119) or if the API changed later.

Moreover, sklearn was now raising an error when using the SkorchDoctor
class because of missing __sklearn_tags__. This class now inherits from
BaseEstimator, resolving this issue.

For good measure, I also tested locally with sklearn 1.7 to ensure that
these changes are backwards compatible.

Unrelated changes:

Remove an unnecessary import and trailing whitespace. Added
__sklearn_is_fitted__ to SkorchDoctor too.
BenjaminBossan added a commit that referenced this pull request Dec 22, 2025
There were two issues in skorch with sklearn v1.8 that are now fixed:

__sklearn_is_fitted__ should return a bool. Instead, we were just
raising or returning None. Not sure if this was already wrong when
added (#1119) or if the API changed later.

Moreover, sklearn was now raising an error when using the SkorchDoctor
class because of missing __sklearn_tags__. This class now inherits from
BaseEstimator, resolving this issue.

For good measure, I also tested locally with sklearn 1.7 to ensure that
these changes are backwards compatible.

Unrelated changes:

Remove an unnecessary import and trailing whitespace. Added
__sklearn_is_fitted__ to SkorchDoctor too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants