简单线性回归是最基础的一种回归模型,自变量只有一个,函数曲线为直线,因变量为连续型,自变量可以是连续的或者是离散的。函数表示如下:

其中 y 是因变量, x是自变量, β0 和 β1 属于起始值和系数,ε 为偏移量,为了使得到的函数模型更加准确,最后会加上偏移量。

figure 1.8

线性回归一般使用最小二乘法来求解函数模型级求解 β0 和 β1 。 方法如下:最小二乘法

figure 1.8

如图中四个点为数据(x,y):(1,6)(2,5)(3,7)(4,10)。我们需要根据红色的数据来求蓝色的曲线。目前我们已知这四个点匹配直线y= β1 + β2x 。所以我们要找到符合这条直线的最佳情况,即最合适的β0 和 β1。

figure 1.8

最小二乘法就是尽量取两边方差的最小值,这样可以找到最拟合的曲线。

figure 1.8

然后我们我们同时对β0和β1求其偏导数

figure 1.8

这样我们很容易就解除方程组的解

figure 1.8

所以我们就得到了直线 y=3.5 + 1.4x

用Python和Java代码表示如下:

# -*- coding: utf-8 -*-
"""
Created on Thu Dec 01 00:02:49 2016

@author: steve
"""

def SLR(x,y):
    intercept = 0.0
    slope = 0.0
    n = len(x)

    sumx = 0.0
    sumy = 0.0
    sumx2 = 0.0
    
# 第一次循环,得到平均值
    for i in range(n):
        sumx += x[i]
        sumy += y[i]
        sumx2 += x[i]*x[i]

    xbar = sumx/n
    ybar = sumy/n

    xxbar = 0.0
    yybar = 0.0
    xybar = 0.0
    
# 第二次循环,得到方差
    for i in range(n):
        xxbar += (x[i] - xbar) * (x[i] - xbar);
        yybar += (y[i] - ybar) * (y[i] - ybar);
        xybar += (x[i] - xbar) * (y[i] - ybar);

# 计算斜率和intercept
    slope  = xybar / xxbar
    intercept = ybar - slope * xbar

    print "slope is {}, intercept is {}".format(slope, intercept)
## 其他统计变量我就不写了。
    
x=[1,2,3,4]
y=[6,5,7,10]
SLR(x,y)

package regression;

public class SLR {
    
    // 这是用二分法做的简单线性回归
    
    private final double intercept, slope;
    private final double r2;
    private final double svar0, svar1;
    
    public SLR(double[] x, double[] y) {
        
        if (x.length != y.length) {
            throw new IllegalArgumentException("lengths doesn't match!!!");
        }
        
        int n = x.length;
        
        // 第一次循环,找到 所有x和y的平均值
        
        double sumx = 0.0;
        double sumy = 0.0;
        double sumx2 = 0.0;
        
        for (int i=0; i<n; i++) {
            sumx += x[i];
            sumy += y[i];
            sumx2 += x[i]*x[i];
        }
        
        double xbar = sumx / n;
        double ybar = sumy / n;
        
        // 第二次计算,求出方差
        double xxbar = 0.0;
        double yybar = 0.0;
        double xybar = 0.0;
        for (int i = 0; i < n; i++) {
            xxbar += (x[i] - xbar) * (x[i] - xbar);
            yybar += (y[i] - ybar) * (y[i] - ybar);
            xybar += (x[i] - xbar) * (y[i] - ybar);
        }
        System.out.println(xxbar);
        System.out.println(yybar);
        System.out.println(xybar);
        slope  = xybar / xxbar;  //求偏导数的过程
        intercept = ybar - slope * xbar;

        // 其他的统计数据
        double rss = 0.0;      // residual sum of squares
        double ssr = 0.0;      // regression sum of squares
        for (int i = 0; i < n; i++) {
            double fit = slope*x[i] + intercept;
            rss += (fit - y[i]) * (fit - y[i]);
            ssr += (fit - ybar) * (fit - ybar);
        }

        int degreesOfFreedom = n-2;
        r2    = ssr / yybar;
        double svar  = rss / degreesOfFreedom;
        svar1 = svar / xxbar;
        svar0 = svar/n + xbar*xbar*svar1;        
        
    }
    
    public double intercept() {
        return intercept;
        
    }
    
    public double slope() {
        return slope;
        
    }
    
    public double R2() {
        return r2;
    }
    
    public double slopeStdErr() {
        return Math.sqrt(svar1);
    }
    
    public double interceptStdErr() {
        return Math.sqrt(svar0);
    }
    
    //这是预测方法,在机器学习中的函数
    public double predict(double x) {
        return slope*x + intercept;
    }
    
    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append(String.format("%.2f n + %.2f", slope(), intercept()));
        s.append("  (R^2 = " + String.format("%.3f", R2()) + ")");
        return s.toString();
    }
    
}

这是一个回归总结的系列,每一篇我都会加上代码。参考了几篇论文,先开个头,后面我会一点点完善。我这渣渣编程水平也太差了~~Python给我写成这个鬼样子····人老了果然不适合写代码了~


dykin
109 声望28 粉丝

我是一只小蜜蜂,咿呀咿呀哟


引用和评论

0 条评论