Skip to content

scipy.optimize._optimize.BracketError in some cases of power transformer #30281

Closed as not planned
@mahlzahn

Description

@mahlzahn

Describe the bug

Similar to #27499, in very few cases the power transformation fails.

Edit: Actually, it starts with a RuntimeWarning: overflow encountered in power because at this point the lambda is 292.8… And thus the out becomes [inf, inf, inf].

Steps/Code to Reproduce

from sklearn.preprocessing import PowerTransformer
transformer = PowerTransformer()
transformer.fit([[23.81], [23.98], [23.97]])

Expected Results

No error.

Actual Results

/tmp/test_venv/lib/python3.12/site-packages/sklearn/preprocessing/_data.py:3438: RuntimeWarning: overflow encountered in power
  out[pos] = (np.power(x[pos] + 1, lmbda) - 1) / lmbda
---------------------------------------------------------------------------
BracketError                              Traceback (most recent call last)
Cell In[1], line 3
      1 from sklearn.preprocessing import PowerTransformer
      2 transformer = PowerTransformer()
----> 3 transformer.fit([[23.80762687], [23.97982808], [23.97586205]])

File /tmp/test_venv/lib/python3.12/site-packages/sklearn/base.py:1473, in _fit_context.<locals>.decorator.<locals>.wrapper(estimator, *args, **kwargs)
   1466     estimator._validate_params()
   1468 with config_context(
   1469     skip_parameter_validation=(
   1470         prefer_skip_nested_validation or global_skip_validation
   1471     )
   1472 ):
-> 1473     return fit_method(estimator, *args, **kwargs)

File /tmp/test_venv/lib/python3.12/site-packages/sklearn/preprocessing/_data.py:3251, in PowerTransformer.fit(self, X, y)
   3231 @_fit_context(prefer_skip_nested_validation=True)
   3232 def fit(self, X, y=None):
   3233     """Estimate the optimal parameter lambda for each feature.
   3234 
   3235     The optimal lambda parameter for minimizing skewness is estimated on
   (...)
   3249         Fitted transformer.
   3250     """
-> 3251     self._fit(X, y=y, force_transform=False)
   3252     return self

File /tmp/test_venv/lib/python3.12/site-packages/sklearn/preprocessing/_data.py:3304, in PowerTransformer._fit(self, X, y, force_transform)
   3301     self.lambdas_[i] = 1.0
   3302     continue
-> 3304 self.lambdas_[i] = optim_function(col)
   3306 if self.standardize or force_transform:
   3307     X[:, i] = transform_function(X[:, i], self.lambdas_[i])

File /tmp/test_venv/lib/python3.12/site-packages/sklearn/preprocessing/_data.py:3493, in PowerTransformer._yeo_johnson_optimize(self, x)
   3491 x = x[~np.isnan(x)]
   3492 # choosing bracket -2, 2 like for boxcox
-> 3493 return optimize.brent(_neg_log_likelihood, brack=(-2, 2))

File /tmp/test_venv/lib/python3.12/site-packages/scipy/optimize/_optimize.py:2625, in brent(func, args, brack, tol, full_output, maxiter)
   2553 """
   2554 Given a function of one variable and a possible bracket, return
   2555 a local minimizer of the function isolated to a fractional precision
   (...)
   2621 
   2622 """
   2623 options = {'xtol': tol,
   2624            'maxiter': maxiter}
-> 2625 res = _minimize_scalar_brent(func, brack, args, **options)
   2626 if full_output:
   2627     return res['x'], res['fun'], res['nit'], res['nfev']

File /tmp/test_venv/lib/python3.12/site-packages/scipy/optimize/_optimize.py:2662, in _minimize_scalar_brent(func, brack, args, xtol, maxiter, disp, **unknown_options)
   2659 brent = Brent(func=func, args=args, tol=tol,
   2660               full_output=True, maxiter=maxiter, disp=disp)
   2661 brent.set_bracket(brack)
-> 2662 brent.optimize()
   2663 x, fval, nit, nfev = brent.get_result(full_output=True)
   2665 success = nit < maxiter and not (np.isnan(x) or np.isnan(fval))

File /tmp/test_venv/lib/python3.12/site-packages/scipy/optimize/_optimize.py:2432, in Brent.optimize(self)
   2429 def optimize(self):
   2430     # set up for optimization
   2431     func = self.func
-> 2432     xa, xb, xc, fa, fb, fc, funcalls = self.get_bracket_info()
   2433     _mintol = self._mintol
   2434     _cg = self._cg

File /tmp/test_venv/lib/python3.12/site-packages/scipy/optimize/_optimize.py:2401, in Brent.get_bracket_info(self)
   2399     xa, xb, xc, fa, fb, fc, funcalls = bracket(func, args=args)
   2400 elif len(brack) == 2:
-> 2401     xa, xb, xc, fa, fb, fc, funcalls = bracket(func, xa=brack[0],
   2402                                                xb=brack[1], args=args)
   2403 elif len(brack) == 3:
   2404     xa, xb, xc = brack

File /tmp/test_venv/lib/python3.12/site-packages/scipy/optimize/_optimize.py:3031, in bracket(func, xa, xb, args, grow_limit, maxiter)
   3029     e = BracketError(msg)
   3030     e.data = (xa, xb, xc, fa, fb, fc, funcalls)
-> 3031     raise e
   3033 return xa, xb, xc, fa, fb, fc, funcalls

BracketError: The algorithm terminated without finding a valid bracket. Consider trying different initial points.

Versions

System:
    python: 3.12.6 (main, Sep  8 2024, 13:18:56) [GCC 14.2.1 20240805]
executable: /usr/bin/python
   machine: Linux-6.6.54-2-MANJARO-x86_64-with-glibc2.40

Python dependencies:
      sklearn: 1.5.2
          pip: 24.2
   setuptools: 69.5.1
        numpy: 2.1.3
        scipy: 1.14.1
       Cython: 3.0.11
       pandas: 2.2.2
   matplotlib: 3.9.2
       joblib: 1.4.2
threadpoolctl: 3.5.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 4
         prefix: libscipy_openblas
       filepath: /tmp/test_venv/lib/python3.12/site-packages/numpy.libs/libscipy_openblas64_-ff651d7f.so
        version: 0.3.27
threading_layer: pthreads
   architecture: Haswell

       user_api: blas
   internal_api: openblas
    num_threads: 4
         prefix: libscipy_openblas
       filepath: /tmp/test_venv/lib/python3.12/site-packages/scipy.libs/libscipy_openblas-c128ec02.so
        version: 0.3.27.dev
threading_layer: pthreads
   architecture: Haswell

       user_api: openmp
   internal_api: openmp
    num_threads: 4
         prefix: libgomp
       filepath: /tmp/test_venv/lib/python3.12/site-packages/scikit_learn.libs/libgomp-a34b3233.so.1.0.0
        version: None

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions