Python 如何在考虑误差条的情况下进行线性回归?
我正在做一个有限大小的物理系统的计算机模拟,然后我在做无穷大的外推(热力学极限)。一些理论认为数据应该与系统大小成线性关系,所以我在做线性回归 我拥有的数据是有噪声的,但对于每个数据点,我可以估计误差条。例如,数据点如下所示:Python 如何在考虑误差条的情况下进行线性回归?,python,numpy,linear-regression,least-squares,extrapolation,Python,Numpy,Linear Regression,Least Squares,Extrapolation,我正在做一个有限大小的物理系统的计算机模拟,然后我在做无穷大的外推(热力学极限)。一些理论认为数据应该与系统大小成线性关系,所以我在做线性回归 我拥有的数据是有噪声的,但对于每个数据点,我可以估计误差条。例如,数据点如下所示: x_list = [0.3333333333333333, 0.2886751345948129, 0.25, 0.23570226039551587, 0.22360679774997896, 0.20412414523193154, 0.2, 0.1666666666
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实现这一点
m, c, r_value, p_value, std_err = scipy.stats.linregress(x_list, y_list)
我知道这会给我结果的误差条,但这并没有考虑初始数据的误差条m, c = numpy.polynomial.polynomial.polyfit(x_list, y_list, 1, w = [1.0 / ty for ty in y_err], full=False)
我该怎么做?不完全确定这是否是你的意思,但是……使用pandas和patsy,我们可以比较普通最小二乘拟合和加权最小二乘拟合,后者使用你提供的噪声的倒数作为权重矩阵(顺便说一句,statsmodels会抱怨样本大小小于20) WLS残差:
[0.025624005084707302,
0.013611438189866154,
-0.033569595462217161,
0.044110895217014695,
-0.025071632845910546,
-0.036308252199571928,
-0.010335514810672464,
-0.0081511479431851663]
加权拟合(wls\u-fit.mse\u resid
或wls\u-fit.scale
)的残差均方误差为0.22964802498892287,拟合的r平方值为0.754
如果您需要每个可用属性和方法的列表,您可以通过调用其summary()
方法和/或执行dir(wls\u fit)
,获得大量关于fits的数据。我发现该文档有助于理解和设置我自己的加权最小二乘例程(适用于任何编程语言)
通常,学习和使用优化的例程是最好的方法,但有时理解例程的精髓很重要。我编写了一个简明的函数来执行数据集的加权线性回归,这是数据集的直接转换。如果您想确切地知道函数在执行拟合时正在执行的操作,这将非常有用
def wlinear_fit (x,y,w) :
"""
Fit (x,y,w) to a linear function, using exact formulae for weighted linear
regression. This code was translated from the GNU Scientific Library (GSL),
it is an exact copy of the function gsl_fit_wlinear.
"""
# compute the weighted means and weighted deviations from the means
# wm denotes a "weighted mean", wm(f) = (sum_i w_i f_i) / (sum_i w_i)
W = np.sum(w)
wm_x = np.average(x,weights=w)
wm_y = np.average(y,weights=w)
dx = x-wm_x
dy = y-wm_y
wm_dx2 = np.average(dx**2,weights=w)
wm_dxdy = np.average(dx*dy,weights=w)
# In terms of y = a + b x
b = wm_dxdy / wm_dx2
a = wm_y - wm_x*b
cov_00 = (1.0/W) * (1.0 + wm_x**2/wm_dx2)
cov_11 = 1.0 / (W*wm_dx2)
cov_01 = -wm_x / (W*wm_dx2)
# Compute chi^2 = \sum w_i (y_i - (a + b * x_i))^2
chi2 = np.sum (w * (y-(a+b*x))**2)
return a,b,cov_00,cov_11,cov_01,chi2
为了表现你的健康,你会
a,b,cov_00,cov_11,cov_01,chi2 = wlinear_fit(x_list,y_list,1.0/y_err**2)
它将返回线性回归系数a
(截距)和b
(斜率)的最佳估计值,以及协方差矩阵cov_00
、cov_01
和cov_11
的元素。对a
上的误差的最佳估计是cov_00
的平方根,b
上的误差是cov_11
的平方根。残差的加权和在chi2
变量中返回
重要:此函数接受反向方差,而不是反向标准偏差作为数据点的权重。支持在以下情况下指定权重:
此处,样品重量指定为1/y\u err
。可能有不同的版本,如果y_err
变化很大或有小的异常值,通常最好将这些样本权重剪裁为最大值:
sample_weight = 1 / y_err
sample_weight = np.minimum(sample_weight, MAX_WEIGHT)
其中,
MAX_WEIGHT
应根据您的数据确定(通过查看y_err
或1/y_err
分布,例如,如果它们有异常值,则可以对其进行剪裁)。我是否误解了您,或者您正在尝试使用y\u err
系列作为权重矩阵?是否确定参数weights
应设置为1/y\u err?statsmodel页面上的示例使用权重=1/(w**2)。他们写道:“在这个例子中,w是误差的标准偏差。WLS要求权重与误差方差的倒数成比例。”@Jim我不确定!我不能确定7年前statsmodels是否建议WLS中的误差方差,所以我只是用在intro stats中学到的知识来指定模型。您是否尝试过在权重为1/(w**2)的情况下运行该示例?无论哪种方式,我都很乐意更正答案。我还没有试过用1/(w**2)的重量运行它。我觉得应该很相似。我不确定1(w**2)是否正确。我认为在过去的某个时刻,我决定使用1/(w**2)进行分析,但那是很久以前的事了。
x_data = np.array(x_list).reshape(-1, 1) # The model expects shape (n_samples, n_features).
y_data = np.array(y_list)
y_err = np.array(y_err)
model = LinearRegression()
model.fit(x_data, y_data, sample_weight=1/y_err)
sample_weight = 1 / y_err
sample_weight = np.minimum(sample_weight, MAX_WEIGHT)