Skip to content

Commit a3b35f3

Browse files
committed
GH-16147: Detect classifier/regressor via MRO in __sklearn_tags__ on sklearn 1.8
On sklearn 1.8, ClassifierMixin/RegressorMixin no longer carry `_estimator_type` — the type is exposed only via __sklearn_tags__. Wrappers built by make_classifier / make_regressor add the matching mixin to bases but use is_generic=False, so the dynamic __init__ doesn't take an `estimator_type` argument and the base wrapper never records `_estimator_type` on the instance. Result on sklearn 1.8: getattr(self, '_estimator_type', None) returns None, super().__sklearn_tags__() returns BaseEstimator's defaults (estimator_type=None), and the type-specific branches in our __sklearn_tags__ override never fire. is_classifier(self) then returns False, the params_as_h2o_frames decorator skips asfactor() on y, and algorithms that only support binomial classification (e.g. AdaBoost) end up training as regression and crashing in predict. Add a final MRO-based fallback: if neither _estimator_type nor the upstream tags expose the type, look for ClassifierMixin / RegressorMixin in type(self).__mro__.
1 parent 066cc0b commit a3b35f3

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

h2o-py/h2o/sklearn/wrapper.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,18 @@ def __sklearn_tags__(self):
596596
# NOT inherit ClassifierMixin (see h2o.sklearn._order_estimator_mixins
597597
# for type='estimator'), so an isinstance() check misses them.
598598
est_type = getattr(self, "_estimator_type", None) or getattr(tags, "estimator_type", None)
599+
if est_type is None:
600+
# sklearn 1.8 removed `_estimator_type = "classifier"` from ClassifierMixin
601+
# and the same for RegressorMixin. Wrappers built via make_classifier /
602+
# make_regressor add the respective mixin to bases but rely on the mixin
603+
# for the type tag (is_generic=False, so __init__ doesn't take an
604+
# estimator_type arg). Detect the mixin in the class MRO as the final
605+
# fallback so is_classifier(self) returns the right answer on sklearn 1.8.
606+
mro = type(self).__mro__
607+
if ClassifierMixin in mro:
608+
est_type = "classifier"
609+
elif RegressorMixin in mro:
610+
est_type = "regressor"
599611
if est_type == "classifier":
600612
tags.estimator_type = "classifier"
601613
try:

0 commit comments

Comments
 (0)