diff --git a/sklearn/ensemble/_gb.py b/sklearn/ensemble/_gb.py index 73bb9e08ae619..e198babdb28d7 100644 --- a/sklearn/ensemble/_gb.py +++ b/sklearn/ensemble/_gb.py @@ -20,6 +20,7 @@ # Arnaud Joly, Jacob Schreiber # License: BSD 3 clause +import math import warnings from abc import ABCMeta, abstractmethod from numbers import Integral, Real @@ -64,11 +65,16 @@ def _safe_divide(numerator, denominator): """Prevents overflow and division by zero.""" - with np.errstate(divide="raise"): - try: - return numerator / denominator - except FloatingPointError: - return 0.0 + try: + # Cast to Python float to trigger a ZeroDivisionError without relying + # on `np.errstate` that is not supported by Pyodide. + result = float(numerator) / float(denominator) + if math.isinf(result): + warnings.warn("overflow encountered in _safe_divide", RuntimeWarning) + return result + except ZeroDivisionError: + warnings.warn("divide by zero encountered in _safe_divide", RuntimeWarning) + return 0.0 def _init_raw_predictions(X, estimator, loss, use_predict_proba): @@ -235,7 +241,9 @@ def compute_update(y_, indices, neg_gradient, raw_prediction, k): # update each leaf (= perform line search) for leaf in np.nonzero(tree.children_left == TREE_LEAF)[0]: - indices = np.nonzero(terminal_regions == leaf)[0] # of terminal regions + indices = np.nonzero(masked_terminal_regions == leaf)[ + 0 + ] # of terminal regions y_ = y.take(indices, axis=0) sw = None if sample_weight is None else sample_weight[indices] update = compute_update(y_, indices, neg_gradient, raw_prediction, k) diff --git a/sklearn/ensemble/tests/test_gradient_boosting.py b/sklearn/ensemble/tests/test_gradient_boosting.py index 6671936d2eaae..9d61464d063f0 100644 --- a/sklearn/ensemble/tests/test_gradient_boosting.py +++ b/sklearn/ensemble/tests/test_gradient_boosting.py @@ -1445,11 +1445,13 @@ def test_huber_vs_mean_and_median(): def test_safe_divide(): """Test that _safe_divide handles division by zero.""" - assert _safe_divide(np.array([1e300]), 0) == 0 - + with pytest.warns(RuntimeWarning, match="divide"): + assert _safe_divide(np.float64(1e300), 0) == 0 + with pytest.warns(RuntimeWarning, match="divide"): + assert _safe_divide(np.float64(0.0), np.float64(0.0)) == 0 with pytest.warns(RuntimeWarning, match="overflow"): # np.finfo(float).max = 1.7976931348623157e+308 - _safe_divide(np.array([1e300]), 1e-10) + _safe_divide(np.float64(1e300), 1e-10) def test_squared_error_exact_backward_compat():