【问题标题】:Calculate confidence band of least-square fit计算最小二乘拟合的置信带
【发布时间】:2025-11-29 13:50:01
【问题描述】:

我有一个问题困扰了我好几天。

如何计算拟合的 (95%) 置信带?

为数据拟合曲线是每个物理学家的日常工作——所以我认为这应该在某个地方实现——但我找不到实现这一点的方法,我也不知道如何在数学上做到这一点。

我发现的唯一东西是seaborn,它对线性最小二乘做得很好。

import numpy as np                                                                                                                                                                                                                         
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd

x = np.linspace(0,10)
y = 3*np.random.randn(50) + x

data = {'x':x, 'y':y}
frame = pd.DataFrame(data, columns=['x', 'y'])
sns.lmplot('x', 'y', frame, ci=95)

plt.savefig("confidence_band.pdf")

但这只是线性最小二乘法。当我想适合时,例如像 这样的饱和曲线,我完蛋了。

当然,我可以根据scipy.optimize.curve_fit 等最小二乘法的标准误差计算 t 分布,但这不是我要寻找的。​​p>

感谢您的帮助!!

【问题讨论】:

标签: python statistics regression confidence-interval


【解决方案1】:

kmpfitconfidence_band() 计算非线性最小二乘的置信区间。这里是你的饱和曲线:

from pylab import *
from kapteyn import kmpfit

def model(p, x):
  a, b = p
  return a*(1-np.exp(b*x))

x = np.linspace(0, 10, 100)
y = .1*np.random.randn(x.size) + model([1, -.4], x)

fit = kmpfit.simplefit(model, [.1, -.1], x, y)
a, b = fit.params
dfdp = [1-np.exp(b*x), -a*x*np.exp(b*x)]
yhat, upper, lower = fit.confidence_band(x, dfdp, 0.95, model)

scatter(x, y, marker='.', color='#0000ba')
for i, l in enumerate((upper, lower, yhat)):
  plot(x, l, c='g' if i == 2 else 'r', lw=2)
savefig('kmpfit confidence bands.png', bbox_inches='tight')

dfdp 是模型 f = a*(1-e^(b*x)) 对每个参数 p(即 a 和 b)的偏导数 ∂f/∂p,见我的answer 对背景链接的类似问题。这里是输出:

【讨论】:

    【解决方案2】:

    您可以使用StatsModels 模块轻松实现此目的。

    另见this examplethis answer

    以下是您问题的答案:

    import numpy as np
    from matplotlib import pyplot as plt
    
    import statsmodels.api as sm
    from statsmodels.stats.outliers_influence import summary_table
    
    x = np.linspace(0,10)
    y = 3*np.random.randn(50) + x
    X = sm.add_constant(x)
    res = sm.OLS(y, X).fit()
    
    st, data, ss2 = summary_table(res, alpha=0.05)
    fittedvalues = data[:,2]
    predict_mean_se  = data[:,3]
    predict_mean_ci_low, predict_mean_ci_upp = data[:,4:6].T
    predict_ci_low, predict_ci_upp = data[:,6:8].T
    
    fig, ax = plt.subplots(figsize=(8,6))
    ax.plot(x, y, 'o', label="data")
    ax.plot(X, fittedvalues, 'r-', label='OLS')
    ax.plot(X, predict_ci_low, 'b--')
    ax.plot(X, predict_ci_upp, 'b--')
    ax.plot(X, predict_mean_ci_low, 'g--')
    ax.plot(X, predict_mean_ci_upp, 'g--')
    ax.legend(loc='best');
    plt.show()
    

    【讨论】:

    • 很遗憾,这目前仅适用于线性函数的 statsmodels,并且将在下一版本中适用于广义线性模型,但不适用于一般非线性函数。