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)