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

使用scipy.minimize的BFGS算法参数接近最优但未收敛问题

问题

我正在估计区间回归模型,参照STATA的intreg模块编写了对数似然函数,所得参数与STATA结果误差在0.001以内,但使用scipy.minimize的BFGS算法时始终未收敛,收到如下提示信息:

message: Desired error not necessarily achieved due to precision loss.
  success: False
   status: 2
      fun: 26435.40918822449
        x: [ 7.379e+00 -6.967e-02 ...  2.149e-01  4.295e-01]
      nit: 94
      jac: [-4.883e-04  0.000e+00 ... -2.441e-04  4.883e-04]
 hess_inv: [[ 3.566e-04 -7.314e-05 ... -1.261e-04 -1.775e-06]
            [-7.314e-05  5.599e-05 ...  3.216e-05  5.660e-07]
            ...
            [-1.261e-04  3.216e-05 ...  4.981e-04  1.297e-06]
            [-1.775e-06  5.660e-07 ...  1.297e-06  8.380e-06]]
     nfev: 4235
     njev: 121 

对数似然函数代码如下:

def log_likelihood(params, x, y_lower, y_upper):
    beta = params[:-1]
    sigma = np.abs(params[-1])  

    z_upper = (y_upper - np.dot(x, beta)) / sigma
    z_lower = (y_lower - np.dot(x, beta)) / sigma
    
    epsilon = 1e-10
    ll_interval = np.sum(np.log(np.clip(norm.cdf(z_upper) - norm.cdf(z_lower), epsilon, None)))

    log_likelihood = ll_interval
    
    return -log_likelihood  

调用scipy.minimize的代码如下:

initial_params = np.concatenate([np.zeros(X.shape[1]), [1.0]])
result = minimize(log_likelihood, initial_params, args=(X, y_lower, y_upper), method='BFGS', options={'disp':True})

为何参数已接近最优,但算法仍提示未收敛?


分析与解决建议
  • 数值精度限制导致收敛判定不通过
    BFGS默认通过梯度(jac)绝对值是否小于gtol=1e-5来判定收敛。你给出的jac分量有4.88e-04,远高于阈值,但参数已接近STATA结果,说明此时似然函数地形极平缓,梯度的微小波动是数值计算精度上限导致的,并非真的未达最优。

  • sigma的绝对值处理引入不可导点
    用np.abs(params[-1])约束sigma为正,会在params[-1]=0处产生不可导点。迭代中若参数接近0,会引发梯度计算的数值不稳定,干扰收敛判定。建议改用指数化参数化:sigma = np.exp(params[-1]),确保sigma始终为正且全参数空间可导,提升稳定性。

  • 似然函数的数值计算误差
    用np.clip避免log(0)时,epsilon=1e-10过小,可能引发log计算的数值误差。可尝试调大epsilon到1e-8,或用更稳定的对数概率计算方式:

    ll_interval = np.sum(norm.logcdf(z_upper) + np.log1p(-norm.cdf(z_lower)/(norm.cdf(z_upper)+1e-12)))
    

    这种方式避免直接计算概率差值,降低数值噪声。

  • 调整BFGS收敛阈值
    确认参数足够接近最优后,可手动放宽收敛阈值,让算法认可当前状态:

    result = minimize(log_likelihood, initial_params, args=(X, y_lower, y_upper), 
                      method='BFGS', options={'disp':True, 'gtol':1e-3, 'ftol':1e-6})
    
  • 换用更鲁棒的优化算法
    BFGS对数值噪声敏感,可尝试L-BFGS-B(带边界约束)给sigma设下界,避免接近0:

    bounds = [(None, None)]*X.shape[1] + [(1e-3, None)]
    result = minimize(log_likelihood, initial_params, args=(X, y_lower, y_upper), 
                      method='L-BFGS-B', bounds=bounds, options={'disp':True})
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:22:09