sklearn ConvergenceWarning: lbfgs failed to converge (tested)

ConvergenceWarning: lbfgs failed to converge after 100 iteration(s) means LogisticRegression hit max_iter before the optimizer converged, usually because features are not scaled. In our test, scaling fixed it in 19 iterations; max_iter=10000 also worked but took 2338. Tested on scikit-learn 1.9.1.

1. The warning

import warnings
warnings.simplefilter("always")
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression

X, y = load_breast_cancer(return_X_y=True)
clf = LogisticRegression().fit(X, y)
print("n_iter_:", clf.n_iter_, "max_iter:", clf.max_iter)

Output:

/usr/local/lib/python3.15/site-packages/sklearn/linear_model/_logistic.py:599: ConvergenceWarning: lbfgs failed to converge after 100 iteration(s) (status=1):
STOP: TOTAL NO. OF ITERATIONS REACHED LIMIT

Increase the number of iterations to improve the convergence (max_iter=100).
You might also want to scale the data as shown in:
    https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
    https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
  n_iter_i = _check_optimize_result(
n_iter_: [100] max_iter: 100

LogisticRegression uses the lbfgs solver with max_iter=100 by default. On unscaled data (the breast-cancer features are on very different scales) the optimizer hits the limit before converging, so n_iter_ equals max_iter and you get ConvergenceWarning. The model is still returned, but its coefficients are not the optimum.

2. Fix: scale the features (or raise max_iter)

import warnings
warnings.simplefilter("always")
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

X, y = load_breast_cancer(return_X_y=True)
pipe = make_pipeline(StandardScaler(), LogisticRegression()).fit(X, y)
print("scaled n_iter_:", pipe[-1].n_iter_)
clf = LogisticRegression(max_iter=10000).fit(X, y)
print("max_iter=10000 n_iter_:", clf.n_iter_)

Output:

scaled n_iter_: [19]
max_iter=10000 n_iter_: [2338]

With StandardScaler in a pipeline the same model converges in 19 iterations, no warning. Raising max_iter also removes the warning, but needed 2338 iterations here: about 120× the work. Scale first; raise max_iter only if a scaled model still warns.

3. Suppress it (when you accept the result)

import warnings
from sklearn.datasets import load_breast_cancer
from sklearn.exceptions import ConvergenceWarning
from sklearn.linear_model import LogisticRegression

X, y = load_breast_cancer(return_X_y=True)
with warnings.catch_warnings():
    warnings.simplefilter("ignore", category=ConvergenceWarning)
    clf = LogisticRegression().fit(X, y)
print("silenced; n_iter_:", clf.n_iter_)
warnings.filterwarnings("ignore", module="sklearn")
LogisticRegression().fit(X, y)
print("after module='sklearn' filter")

Output:

silenced; n_iter_: [100]
after module='sklearn' filter

Import ConvergenceWarning from sklearn.exceptions and ignore that category inside warnings.catch_warnings(), which keeps other warnings visible. Unlike matplotlib and pandas, scikit-learn attributes this warning to its own module, so module="sklearn" filters do match it (the last fit printed nothing). Note that silencing does not change the result: n_iter_ is still 100.

Related: NumPy RuntimeWarning · suppress matplotlib warnings · suppress pandas warnings.

Frequently asked questions

How do I fix 'lbfgs failed to converge'?

Scale your features (StandardScaler in a Pipeline). If it still warns, raise max_iter, e.g. LogisticRegression(max_iter=1000).

Is the model still usable after a ConvergenceWarning?

It is returned and can predict, but the coefficients are not fully optimized. Fix the convergence before trusting them.

How do I suppress ConvergenceWarning in sklearn?

from sklearn.exceptions import ConvergenceWarning, then warnings.simplefilter('ignore', category=ConvergenceWarning) inside warnings.catch_warnings().

Written with AI assistance. Measured on 2026-10-23 in Docker: python:3-slim (Python 3.15.1) with scikit-learn 1.9.1. Each block was run verbatim and the output pasted unedited. PlainTables is our extension; Python and scikit-learn are free.