You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在scikit-learn LogisticRegression中设置LBFGS求解器的maxfun限制?

问题

使用scikit-learn的LogisticRegression模型搭配LBFGS求解器时出现提前停止,日志如下(数据已标准化):

(...)

At iterate13150    f=  4.05397D+03    |proj g|=  2.41194D+04

At iterate13200    f=  4.05213D+03    |proj g|=  1.36863D+04
.venv/lib/python3.8/site-packages/sklearn/linear_model/_logistic.py:444: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of f AND g EVALUATIONS EXCEEDS LIMIT.

Increase the number of iterations (max_iter) or 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(
[Parallel(n_jobs=-1)]: Done   1 out of   1 | elapsed:    5.5s finished

           * * *

Tit   = total number of iterations
Tnf   = total number of function evaluations
Tnint = total number of segments explored during Cauchy searches
Skip  = number of BFGS updates skipped
Nact  = number of active bounds at final generalized Cauchy point
Projg = norm of the final projected gradient
F     = final function value

           * * *

   N    Tit     Tnf  Tnint  Skip  Nact     Projg        F
   62  13240  15001      1     0     0   4.800D+04   4.051D+03
  F =   4051.0211050375365     

sklearn采用scipy实现的LBFGS求解器,scipy/optimize/_lbfgsb_py.py:_minimize_lbfgsb的提前停止条件如下:

if n_iterations >= maxiter:
                task[:] = 'STOP: TOTAL NO. of ITERATIONS REACHED LIMIT'
            elif sf.nfev > maxfun:
                task[:] = ('STOP: TOTAL NO. of f AND g EVALUATIONS '
                           'EXCEEDS LIMIT')

实际触发了sf.nfev > maxfun的限制,但sklearn在实例化scipy求解器时,将maxfun固定为15000(见sklearn/linear_model/_logistic.py:442)。曾通过修改sklearn源码将maxfun设为100000,求解器成功收敛,但不想维护自定义版本,询问是否有其他设置maxfun参数的方法。

解决方法

1. 手动调用scipy求解器实现逻辑回归

跳过sklearn的封装,直接用scipy.optimize.minimize调用LBFGSB求解器,可自由设置maxfun参数。需要自行构造逻辑回归的损失函数和梯度:

import numpy as np
from scipy.optimize import minimize

def logistic_loss(w, X, y):
    z = X @ w
    # 适配标签为0/1的情况,若标签是-1/1可直接用np.log(1 + np.exp(-y*z))
    loss = np.mean(-y * np.log(1/(1+np.exp(-z))) - (1-y)*np.log(np.exp(-z)/(1+np.exp(-z))))
    return loss

def logistic_gradient(w, X, y):
    z = X @ w
    sigmoid = 1 / (1 + np.exp(-z))
    grad = X.T @ (sigmoid - y) / len(y)
    return grad

# 假设X是标准化特征矩阵,y是0/1标签
initial_w = np.zeros(X.shape[1])
result = minimize(logistic_loss, initial_w, jac=logistic_gradient, args=(X, y),
                  method='L-BFGS-B', options={'maxfun': 100000})
# result.x即为训练后的模型参数

2. 用猴子补丁临时修改sklearn的求解器参数

通过运行时替换sklearn内部调用的scipy求解器,修改maxfun参数,无需修改源码:

from functools import partial
import sklearn.linear_model._logistic
from scipy.optimize import _minimize_lbfgsb

# 保存原始求解器
original_minimize = _minimize_lbfgsb

def custom_minimize(*args, **kwargs):
    # 强制设置maxfun为目标值
    kwargs['options']['maxfun'] = 100000
    return original_minimize(*args, **kwargs)

# 替换sklearn内部使用的求解器
sklearn.linear_model._logistic._minimize_lbfgsb = custom_minimize

# 正常训练模型
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(solver='lbfgs', max_iter=100000)
model.fit(X, y)

注意:该方法依赖sklearn内部实现,版本更新后可能失效,需验证对应版本兼容性。

3. 切换其他求解器

若场景允许,可尝试saga或sag求解器,这类求解器更适合大规模数据,且sklearn对其迭代控制更灵活,无需调整maxfun即可收敛。

内容的提问来源于stack exchange,提问作者VaM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:50:29