一元线性回归分析是处理两个变量之间关系的最简单模型,它所研究的对象是两个变量之间的线性相关关系。通过对这个模型的讨论,我们不仅可以掌握有关一元线性回归的知识,而且可以从中了解回归分析方法的基本思想、方法和应用。
一、问题的提出
例2-1-1 为了研究氮含量对铁合金溶液初生奥氏体析出温度的影响,测定了不同氮含量时铁合金溶液初生奥氏体析出温度,得到表2-1-1给出的5组数据。
表2-1-1 氮含量与灰铸铁初生奥氏体析出温度测试数据
如果把氮含量作为横坐标,把初生奥氏体析出温度作为纵坐标,将这些数据标在平面直角坐标上,则得图2-1-1,这个图称为散点图。
从图2-1-1可以看出,数据点基本落在一条直线附近。这告诉我们,变量X与Y的关系大致可看作是线性关系,即它们之间的相互关系可以用线性关系来描述。但是由于并非所有的数据点完全落在一条直线上,因此X与Y的关系并没有确切到可以唯一地由一个X值确定一个Y值的程度。其它因素,诸如其它微量元素的含量以及测试误差等都会影响Y的测试结果。如果我们要研究X与Y的关系,可以作线性拟合
(2-1-1)
我们称(2-1-1)式为回归方程,a与b是待定常数,称为回归系数。从理论上讲,(2-1-1)式有无穷多组解,回归分析的任务是求出其最佳的线性拟合。
二、最小二乘法原理
如果把用回归方程 计算得到的 i值(i=1,2,…n)称为回归值,那么实际测量值yi与回归值 i之间存在着偏差,我们把这种偏差称为残差,记为ei(i=1,2,3,…,n)。这样,我们就可以用残差平方和来度量测量值与回归直线的接近或偏差程度。残差平方和定义为:
(2-1-2)
所谓最小二乘法,就是选择a和b使Q(a,b)最小,即用最小二乘法得到的回归直线 是在所有直线中与测量值残差平方和Q最小的一条。由(2-1-2)式可知Q是关于a,b的二次函数,所以它的最小值总是存在的。下面讨论的a和b的求法。
三、正规方程组
根据微分中求极值的方法可知,Q(a,b)取得最小值应满足
(2-1-3)
由(2-1-2)式,并考虑上述条件,则
(2-1-4)
(2-1-4)式称为正规方程组。解这一方程组可得
(2-1-5)
其中
(2-1-6)
(2-1-7)
式中,Lxy称为xy的协方差之和,Lxx称为x的平方差之和。
如果改写(2-1-1)式,可得
(2-1-8)
或
(2-1-9)
由此可见,回归直线是通过点 的,即通过由所有实验测量值的平均值组成的点。从力学观点看, 即是N个散点 的重心位置。
现在我们来建立关于例1的回归关系式。将表2-1-1的结果代入(2-1-5)式至(2-1-7)式,得出
a=1231.65
b=-2236.63
因此,在例1中灰铸铁初生奥氏体析出温度(y)与氮含量(x)的回归关系式为
y=1231.65-2236.63x
四、一元线性回归的统计学原理
如果X和Y都是相关的随机变量,在确定x的条件下,对应的y值并不确定,而是形成一个分布。当X取确定的值时,Y的数学期望值也就确定了,因此Y的数学期望是x的函数,即
E(Y|X=x)=f(x) (2-1-10)
这里方程f(x)称为Y对X的回归方程。如果回归方程是线性的,则
E(Y|X=x)=α+βx (2-1-11)
或
Y=α+βx+ε (2-1-12)
其中
ε―随机误差
从样本中我们只能得到关于特征数的估计,并不能精确地求出特征数。因此只能用f(x)的估计式 来取代(2-1-11)式,用参数a和b分别作为α和β的估计量。那么,这两个估计量是否能够满足要求呢?
1. 无偏性
把(x,y)的n组观测值作为一个样本,由样本只能得到总体参数α和β的估计值。可以证明,当满足下列条件:
(1)(xi,yi)是n个相互独立的观测值
(2)εi是服从 分布的随机变量
则由最小二乘法得到的a与b分别是总体参数α和β的无偏估计,即
E(a)= α
E(b)=β
由此可推知
E( )=E(y)
即y是回归值 在某点的数学期望值。
2. a和b的方差
可以证明,当n组观测值(xi,yi)相互独立,并且D(yi)=σ2,时,a和b的方差为
(2-1-13)
(2-1-14)
以上两式表明,a和b的方差均与xi的变动有关,xi分布越宽,则a和b的方差越小。另外a的方差还与观测点的数量有关,数据越多,a的方差越小。因此,为提高估计量的准确性,xi的分布应尽量宽,观测点数量应尽量多。
java实现
1、定义一个DataPoint类,对X和Y坐标点进行封装:
- package com.zyujie.dm;
-
- public class DataPoint {
-
-
- public float x;
-
-
- public float y;
-
-
- public DataPoint(float x, float y) {
- this.x = x;
- this.y = y;
- }
- }
2、下面是算法实现回归线:
- package com.zyujie.dm;
-
- import java.math.BigDecimal;
- import java.util.ArrayList;
-
- public class RegressionLine
- {
-
- private double sumX;
-
-
- private double sumY;
-
-
- private double sumXX;
-
-
- private double sumXY;
-
-
- private double sumYY;
-
-
- private double sumDeltaY;
-
-
- private double sumDeltaY2;
-
-
- private double sse;
-
- private double sst;
-
- private double E;
-
- private String[] xy;
-
- private ArrayList listX;
-
- private ArrayList listY;
-
- private int XMin, XMax, YMin, YMax;
-
-
- private float a0;
-
-
- private float a1;
-
-
- private int pn;
-
-
- private boolean coefsValid;
-
-
- public RegressionLine() {
- XMax = 0;
- YMax = 0;
- pn = 0;
- xy = new String[2];
- listX = new ArrayList();
- listY = new ArrayList();
- }
-
-
- public RegressionLine(DataPoint data[]) {
- pn = 0;
- xy = new String[2];
- listX = new ArrayList();
- listY = new ArrayList();
- for (int i = 0; i < data.length; ++i) {
- addDataPoint(data[i]);
- }
- }
-
-
- public int getDataPointCount() {
- return pn;
- }
-
-
- public float getA0() {
- validateCoefficients();
- return a0;
- }
-
-
- public float getA1() {
- validateCoefficients();
- return a1;
- }
-
-
- public double getSumX() {
- return sumX;
- }
-
-
- public double getSumY() {
- return sumY;
- }
-
-
- public double getSumXX() {
- return sumXX;
- }
-
-
- public double getSumXY() {
- return sumXY;
- }
-
- public double getSumYY() {
- return sumYY;
- }
-
- public int getXMin() {
- return XMin;
- }
-
- public int getXMax() {
- return XMax;
- }
-
- public int getYMin() {
- return YMin;
- }
-
- public int getYMax() {
- return YMax;
- }
-
-
- public void addDataPoint(DataPoint dataPoint) {
- sumX += dataPoint.x;
- sumY += dataPoint.y;
- sumXX += dataPoint.x * dataPoint.x;
- sumXY += dataPoint.x * dataPoint.y;
- sumYY += dataPoint.y * dataPoint.y;
-
- if (dataPoint.x > XMax) {
- XMax = (int) dataPoint.x;
- }
- if (dataPoint.y > YMax) {
- YMax = (int) dataPoint.y;
- }
-
-
-
- xy[0] = (int) dataPoint.x + "";
- xy[1] = (int) dataPoint.y + "";
- if (dataPoint.x != 0 && dataPoint.y != 0) {
- System.out.print(xy[0] + ",");
- System.out.println(xy[1]);
-
- try {
-
- listX.add(pn, xy[0]);
- listY.add(pn, xy[1]);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
-
- }
- ++pn;
- coefsValid = false;
- }
-
-
- public float at(int x) {
- if (pn < 2)
- return Float.NaN;
-
- validateCoefficients();
- return a0 + a1 * x;
- }
-
-
- public void reset() {
- pn = 0;
- sumX = sumY = sumXX = sumXY = 0;
- coefsValid = false;
- }
-
-
- private void validateCoefficients() {
- if (coefsValid)
- return;
-
- if (pn >= 2) {
- float xBar = (float) sumX / pn;
- float yBar = (float) sumY / pn;
-
- a1 = (float) ((pn * sumXY - sumX * sumY) / (pn * sumXX - sumX
- * sumX));
- a0 = (float) (yBar - a1 * xBar);
- } else {
- a0 = a1 = Float.NaN;
- }
-
- coefsValid = true;
- }
-
-
- public double getR() {
-
- for (int i = 0; i < pn - 1; i++) {
- float Yi = (float) Integer.parseInt(listY.get(i).toString());
- float Y = at(Integer.parseInt(listX.get(i).toString()));
- float deltaY = Yi - Y;
- float deltaY2 = deltaY * deltaY;
-
-
- sumDeltaY2 += deltaY2;
-
-
- }
-
- sst = sumYY - (sumY * sumY) / pn;
-
- E = 1 - sumDeltaY2 / sst;
-
- return round(E, 4);
- }
-
-
- public double round(double v, int scale) {
-
- if (scale < 0) {
- throw new IllegalArgumentException(
- "The scale must be a positive integer or zero");
- }
-
- BigDecimal b = new BigDecimal(Double.toString(v));
- BigDecimal one = new BigDecimal("1");
- return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
-
- }
-
- public float round(float v, int scale) {
-
- if (scale < 0) {
- throw new IllegalArgumentException(
- "The scale must be a positive integer or zero");
- }
-
- BigDecimal b = new BigDecimal(Double.toString(v));
- BigDecimal one = new BigDecimal("1");
- return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).floatValue();
-
- }
- }
3、线性回归测试类:
我们运行测试类,得到运行结果:
1,136
2,143
3,132
4,142
5,147
数据点个数 n = 5
Sum x = 15.0
Sum y = 700.0
Sum xx = 55.0
Sum xy = 2121.0
Sum yy = 98142.0
回归线公式: y = 2.1x + 133.7
误差: R^2 = 0.3658
假如某公司:
1月收入,136万元
2月收入,143万元
3月收入,132万元
4月收入,142万元
5月收入,147万元
我们可以根据回归线公式:y = 2.1x + 133.7,预测出6月份收入:
y = 2.1 * 6 + 133.7 = 12.6 + 133.7 = 146.3