python - 如何进行线性回归,考虑误差线?

标签 python numpy linear-regression least-squares extrapolation

我正在对一些有限大小的物理系统进行计算机模拟,然后我正在外推到无穷大(热力学极限)。一些理论认为数据应该与系统规模成线性比例关系,所以我正在做线性回归。

我拥有的数据很嘈杂,但对于每个数据点,我都可以估计误差线。因此,例如数据点如下所示:

x_list = [0.3333333333333333, 0.2886751345948129, 0.25, 0.23570226039551587, 0.22360679774997896, 0.20412414523193154, 0.2, 0.16666666666666666]
y_list = [0.13250359351851854, 0.12098339583333334, 0.12398501145833334, 0.09152715, 0.11167239583333334, 0.10876248333333333, 0.09814170444444444, 0.08560799305555555]
y_err = [0.003306749165349316, 0.003818446389148108, 0.0056036878203831785, 0.0036635292592592595, 0.0037034897788415424, 0.007576672222222223, 0.002981084130692832, 0.0034913019065973983]

假设我正尝试在 Python 中执行此操作。

  1. 我知道的第一种方式是:

    m, c, r_value, p_value, std_err = scipy.stats.linregress(x_list, y_list)
    

    我知道这会给我结果的误差线,但这没有考虑初始数据的误差线。

  2. 我知道的第二种方式是:

    m, c = numpy.polynomial.polynomial.polyfit(x_list, y_list, 1, w = [1.0 / ty for ty in y_err], full=False)
    

这里我们使用每个点的误差条的倒数作为在最小二乘近似中使用的权重。所以如果一个点不是真的那么可靠,它不会对结果产生太大影响,这是合理的。

但我不知道如何获得结合这两种方法的东西。

我真正想要的是second 方法的作用,意思是当每个点以不同的权重影响结果时使用回归。但与此同时,我想知道我的结果有多准确,也就是说,我想知道结果系数的误差线是什么。

我该怎么做?

最佳答案

不完全确定这是否是您的意思,但是......使用 Pandas ,statsmodels和 patsy,我们可以比较普通的最小二乘拟合和加权最小二乘拟合,后者使用您提供的噪声的倒数作为权重矩阵(顺便说一下,statsmodels 会提示样本大小 < 20)。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['figure.dpi'] = 300

import statsmodels.formula.api as sm

x_list = [0.3333333333333333, 0.2886751345948129, 0.25, 0.23570226039551587, 0.22360679774997896, 0.20412414523193154, 0.2, 0.16666666666666666]
y_list = [0.13250359351851854, 0.12098339583333334, 0.12398501145833334, 0.09152715, 0.11167239583333334, 0.10876248333333333, 0.09814170444444444, 0.08560799305555555]
y_err = [0.003306749165349316, 0.003818446389148108, 0.0056036878203831785, 0.0036635292592592595, 0.0037034897788415424, 0.007576672222222223, 0.002981084130692832, 0.0034913019065973983]

# put x and y into a pandas DataFrame, and the weights into a Series
ws = pd.DataFrame({
    'x': x_list,
    'y': y_list
})
weights = pd.Series(y_err)

wls_fit = sm.wls('x ~ y', data=ws, weights=1 / weights).fit()
ols_fit = sm.ols('x ~ y', data=ws).fit()

# show the fit summary by calling wls_fit.summary()
# wls fit r-squared is 0.754
# ols fit r-squared is 0.701

# let's plot our data
plt.clf()
fig = plt.figure()
ax = fig.add_subplot(111, facecolor='w')
ws.plot(
    kind='scatter',
    x='x',
    y='y',
    style='o',
    alpha=1.,
    ax=ax,
    title='x vs y scatter',
    edgecolor='#ff8300',
    s=40
)

# weighted prediction
wp, = ax.plot(
    wls_fit.predict(),
    ws['y'],
    color='#e55ea2',
    lw=1.,
    alpha=1.0,
)
# unweighted prediction
op, = ax.plot(  
    ols_fit.predict(),
    ws['y'],
    color='k',
    ls='solid',
    lw=1,
    alpha=1.0,
)
leg = plt.legend(
    (op, wp),
    ('Ordinary Least Squares', 'Weighted Least Squares'),
    loc='upper left',
    fontsize=8)

plt.tight_layout()
fig.set_size_inches(6.40, 5.12)
plt.show()

OLS vs WLS

WLS 残差:

[0.025624005084707302,
 0.013611438189866154,
 -0.033569595462217161,
 0.044110895217014695,
 -0.025071632845910546,
 -0.036308252199571928,
 -0.010335514810672464,
 -0.0081511479431851663]

加权拟合(wls_fit.mse_residwls_fit.scale)的残差均方误差为 0.22964802498892287,并且 r -拟合的平方值为 0.754

如果您需要一个列表,您可以通过调用它们的 summary() 方法和/或执行 dir(wls_fit) 来获取有关拟合的大量数据每个可用的属性和方法。

关于python - 如何进行线性回归,考虑误差线?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21469620/

相关文章:

python - 更新键而不影响嵌套字典中键的值

python - 如何转换相同长度的数组列表

python - numpy 奇特的广播用于特殊情况谜语

python - numpy 对角线函数很慢

python - 我们如何计算 statsmodels OLS 中的截距和斜率?

r - 如何使用预测()

python - 如何将列表转换为 ASCII

python - 创建新行并根据时间间隔重复这些值(如果它们属于)

python - 在 python 中延迟抽取随机结果

matlab - 梯度下降和闭合形式解 - MATLAB 中的不同假设线