http://blog.csdn.net/hwwn2009/article/details/38414911

2014-08-07 11:02 1072人阅读 评论(0) 收藏 举报
 分类:
DataMining(17) 

一元线性回归分析是处理两个变量之间关系的最简单模型,它所研究的对象是两个变量之间的线性相关关系。通过对这个模型的讨论,我们不仅可以掌握有关一元线性回归的知识,而且可以从中了解回归分析方法的基本思想、方法和应用。

一、问题的提出

例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坐标点进行封装:

  1. /**
  2. * File        : DataPoint.java
  3. * Author      : zhouyujie
  4. * Date        : 2012-01-11 16:00:00
  5. * Description : Java实现一元线性回归的算法,座标点实体类,(可实现统计指标的预测)
  6. */
  7. package com.zyujie.dm;
  8. public class DataPoint {
  9. /** the x value */
  10. public float x;
  11. /** the y value */
  12. public float y;
  13. /**
  14. * Constructor.
  15. *
  16. * @param x
  17. *            the x value
  18. * @param y
  19. *            the y value
  20. */
  21. public DataPoint(float x, float y) {
  22. this.x = x;
  23. this.y = y;
  24. }
  25. }

2、下面是算法实现回归线:

  1. /**
  2. * File        : DataPoint.java
  3. * Author      : zhouyujie
  4. * Date        : 2012-01-11 16:00:00
  5. * Description : Java实现一元线性回归的算法,回归线实现类,(可实现统计指标的预测)
  6. */
  7. package com.zyujie.dm;
  8. import java.math.BigDecimal;
  9. import java.util.ArrayList;
  10. public class RegressionLine // implements Evaluatable
  11. {
  12. /** sum of x */
  13. private double sumX;
  14. /** sum of y */
  15. private double sumY;
  16. /** sum of x*x */
  17. private double sumXX;
  18. /** sum of x*y */
  19. private double sumXY;
  20. /** sum of y*y */
  21. private double sumYY;
  22. /** sum of yi-y */
  23. private double sumDeltaY;
  24. /** sum of sumDeltaY^2 */
  25. private double sumDeltaY2;
  26. /** 误差 */
  27. private double sse;
  28. private double sst;
  29. private double E;
  30. private String[] xy;
  31. private ArrayList listX;
  32. private ArrayList listY;
  33. private int XMin, XMax, YMin, YMax;
  34. /** line coefficient a0 */
  35. private float a0;
  36. /** line coefficient a1 */
  37. private float a1;
  38. /** number of data points */
  39. private int pn;
  40. /** true if coefficients valid */
  41. private boolean coefsValid;
  42. /**
  43. * Constructor.
  44. */
  45. public RegressionLine() {
  46. XMax = 0;
  47. YMax = 0;
  48. pn = 0;
  49. xy = new String[2];
  50. listX = new ArrayList();
  51. listY = new ArrayList();
  52. }
  53. /**
  54. * Constructor.
  55. *
  56. * @param data
  57. *            the array of data points
  58. */
  59. public RegressionLine(DataPoint data[]) {
  60. pn = 0;
  61. xy = new String[2];
  62. listX = new ArrayList();
  63. listY = new ArrayList();
  64. for (int i = 0; i < data.length; ++i) {
  65. addDataPoint(data[i]);
  66. }
  67. }
  68. /**
  69. * Return the current number of data points.
  70. *
  71. * @return the count
  72. */
  73. public int getDataPointCount() {
  74. return pn;
  75. }
  76. /**
  77. * Return the coefficient a0.
  78. *
  79. * @return the value of a0
  80. */
  81. public float getA0() {
  82. validateCoefficients();
  83. return a0;
  84. }
  85. /**
  86. * Return the coefficient a1.
  87. *
  88. * @return the value of a1
  89. */
  90. public float getA1() {
  91. validateCoefficients();
  92. return a1;
  93. }
  94. /**
  95. * Return the sum of the x values.
  96. *
  97. * @return the sum
  98. */
  99. public double getSumX() {
  100. return sumX;
  101. }
  102. /**
  103. * Return the sum of the y values.
  104. *
  105. * @return the sum
  106. */
  107. public double getSumY() {
  108. return sumY;
  109. }
  110. /**
  111. * Return the sum of the x*x values.
  112. *
  113. * @return the sum
  114. */
  115. public double getSumXX() {
  116. return sumXX;
  117. }
  118. /**
  119. * Return the sum of the x*y values.
  120. *
  121. * @return the sum
  122. */
  123. public double getSumXY() {
  124. return sumXY;
  125. }
  126. public double getSumYY() {
  127. return sumYY;
  128. }
  129. public int getXMin() {
  130. return XMin;
  131. }
  132. public int getXMax() {
  133. return XMax;
  134. }
  135. public int getYMin() {
  136. return YMin;
  137. }
  138. public int getYMax() {
  139. return YMax;
  140. }
  141. /**
  142. * Add a new data point: Update the sums.
  143. *
  144. * @param dataPoint
  145. *            the new data point
  146. */
  147. public void addDataPoint(DataPoint dataPoint) {
  148. sumX += dataPoint.x;
  149. sumY += dataPoint.y;
  150. sumXX += dataPoint.x * dataPoint.x;
  151. sumXY += dataPoint.x * dataPoint.y;
  152. sumYY += dataPoint.y * dataPoint.y;
  153. if (dataPoint.x > XMax) {
  154. XMax = (int) dataPoint.x;
  155. }
  156. if (dataPoint.y > YMax) {
  157. YMax = (int) dataPoint.y;
  158. }
  159. // 把每个点的具体坐标存入ArrayList中,备用
  160. xy[0] = (int) dataPoint.x + "";
  161. xy[1] = (int) dataPoint.y + "";
  162. if (dataPoint.x != 0 && dataPoint.y != 0) {
  163. System.out.print(xy[0] + ",");
  164. System.out.println(xy[1]);
  165. try {
  166. // System.out.println("n:"+n);
  167. listX.add(pn, xy[0]);
  168. listY.add(pn, xy[1]);
  169. } catch (Exception e) {
  170. e.printStackTrace();
  171. }
  172. /*
  173. * System.out.println("N:" + n); System.out.println("ArrayList
  174. * listX:"+ listX.get(n)); System.out.println("ArrayList listY:"+
  175. * listY.get(n));
  176. */
  177. }
  178. ++pn;
  179. coefsValid = false;
  180. }
  181. /**
  182. * Return the value of the regression line function at x. (Implementation of
  183. * Evaluatable.)
  184. *
  185. * @param x
  186. *            the value of x
  187. * @return the value of the function at x
  188. */
  189. public float at(int x) {
  190. if (pn < 2)
  191. return Float.NaN;
  192. validateCoefficients();
  193. return a0 + a1 * x;
  194. }
  195. /**
  196. * Reset.
  197. */
  198. public void reset() {
  199. pn = 0;
  200. sumX = sumY = sumXX = sumXY = 0;
  201. coefsValid = false;
  202. }
  203. /**
  204. * Validate the coefficients. 计算方程系数 y=ax+b 中的a
  205. */
  206. private void validateCoefficients() {
  207. if (coefsValid)
  208. return;
  209. if (pn >= 2) {
  210. float xBar = (float) sumX / pn;
  211. float yBar = (float) sumY / pn;
  212. a1 = (float) ((pn * sumXY - sumX * sumY) / (pn * sumXX - sumX
  213. * sumX));
  214. a0 = (float) (yBar - a1 * xBar);
  215. } else {
  216. a0 = a1 = Float.NaN;
  217. }
  218. coefsValid = true;
  219. }
  220. /**
  221. * 返回误差
  222. */
  223. public double getR() {
  224. // 遍历这个list并计算分母
  225. for (int i = 0; i < pn - 1; i++) {
  226. float Yi = (float) Integer.parseInt(listY.get(i).toString());
  227. float Y = at(Integer.parseInt(listX.get(i).toString()));
  228. float deltaY = Yi - Y;
  229. float deltaY2 = deltaY * deltaY;
  230. /*
  231. * System.out.println("Yi:" + Yi); System.out.println("Y:" + Y);
  232. * System.out.println("deltaY:" + deltaY);
  233. * System.out.println("deltaY2:" + deltaY2);
  234. */
  235. sumDeltaY2 += deltaY2;
  236. // System.out.println("sumDeltaY2:" + sumDeltaY2);
  237. }
  238. sst = sumYY - (sumY * sumY) / pn;
  239. // System.out.println("sst:" + sst);
  240. E = 1 - sumDeltaY2 / sst;
  241. return round(E, 4);
  242. }
  243. // 用于实现精确的四舍五入
  244. public double round(double v, int scale) {
  245. if (scale < 0) {
  246. throw new IllegalArgumentException(
  247. "The scale must be a positive integer or zero");
  248. }
  249. BigDecimal b = new BigDecimal(Double.toString(v));
  250. BigDecimal one = new BigDecimal("1");
  251. return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
  252. }
  253. public float round(float v, int scale) {
  254. if (scale < 0) {
  255. throw new IllegalArgumentException(
  256. "The scale must be a positive integer or zero");
  257. }
  258. BigDecimal b = new BigDecimal(Double.toString(v));
  259. BigDecimal one = new BigDecimal("1");
  260. return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).floatValue();
  261. }
  262. }

3、线性回归测试类:

  1. /**
  2. * File        : DataPoint.java
  3. * Author      : zhouyujie
  4. * Date        : 2012-01-11 16:00:00
  5. * Description : Java实现一元线性回归的算法,线性回归测试类,(可实现统计指标的预测)
  6. */
  7. package com.zyujie.dm;
  8. /**
  9. * <p>
  10. * <b>Linear Regression</b> <br>
  11. * Demonstrate linear regression by constructing the regression line for a set
  12. * of data points.
  13. *
  14. * <p>
  15. * require DataPoint.java,RegressionLine.java
  16. *
  17. * <p>
  18. * 为了计算对于给定数据点的最小方差回线,需要计算SumX,SumY,SumXX,SumXY; (注:SumXX = Sum (X^2))
  19. * <p>
  20. * <b>回归直线方程如下: f(x)=a1x+a0 </b>
  21. * <p>
  22. * <b>斜率和截距的计算公式如下:</b> <br>
  23. * n: 数据点个数
  24. * <p>
  25. * a1=(n(SumXY)-SumX*SumY)/(n*SumXX-(SumX)^2) <br>
  26. * a0=(SumY - SumY * a1)/n <br>
  27. * (也可表达为a0=averageY-a1*averageX)
  28. *
  29. * <p>
  30. * <b>画线的原理:两点成一直线,只要能确定两个点即可</b><br>
  31. * 第一点:(0,a0) 再随意取一个x1值代入方程,取得y1,连结(0,a0)和(x1,y1)两点即可。
  32. * 为了让线穿过整个图,x1可以取横坐标的最大值Xmax,即两点为(0,a0),(Xmax,Y)。如果y=a1*Xmax+a0,y大于
  33. * 纵坐标最大值Ymax,则不用这个点。改用y取最大值Ymax,算得此时x的值,使用(X,Ymax), 即两点为(0,a0),(X,Ymax)
  34. *
  35. * <p>
  36. * <b>拟合度计算:(即Excel中的R^2)</b>
  37. * <p>
  38. * *R2 = 1 - E
  39. * <p>
  40. * 误差E的计算:E = SSE/SST
  41. * <p>
  42. * SSE=sum((Yi-Y)^2) SST=sumYY - (sumY*sumY)/n;
  43. * <p>
  44. */
  45. public class LinearRegression {
  46. private static final int MAX_POINTS = 10;
  47. private double E;
  48. /**
  49. * Main program.
  50. *
  51. * @param args
  52. *            the array of runtime arguments
  53. */
  54. public static void main(String args[]) {
  55. RegressionLine line = new RegressionLine();
  56. line.addDataPoint(new DataPoint(1, 136));
  57. line.addDataPoint(new DataPoint(2, 143));
  58. line.addDataPoint(new DataPoint(3, 132));
  59. line.addDataPoint(new DataPoint(4, 142));
  60. line.addDataPoint(new DataPoint(5, 147));
  61. printSums(line);
  62. printLine(line);
  63. }
  64. /**
  65. * Print the computed sums.
  66. *
  67. * @param line
  68. *            the regression line
  69. */
  70. private static void printSums(RegressionLine line) {
  71. System.out.println("\n数据点个数 n = " + line.getDataPointCount());
  72. System.out.println("\nSum x  = " + line.getSumX());
  73. System.out.println("Sum y  = " + line.getSumY());
  74. System.out.println("Sum xx = " + line.getSumXX());
  75. System.out.println("Sum xy = " + line.getSumXY());
  76. System.out.println("Sum yy = " + line.getSumYY());
  77. }
  78. /**
  79. * Print the regression line function.
  80. *
  81. * @param line
  82. *            the regression line
  83. */
  84. private static void printLine(RegressionLine line) {
  85. System.out.println("\n回归线公式:  y = " + line.getA1() + "x + "
  86. + line.getA0());
  87. System.out.println("误差:     R^2 = " + line.getR());
  88. }
  89. //y = 2.1x + 133.7   2.1 * 6 + 133.7 = 12.6 + 133.7 = 146.3
  90. //y = 2.1x + 133.7   2.1 * 7 + 133.7 = 14.7 + 133.7 = 148.4
  91. }

我们运行测试类,得到运行结果:

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

一元线性回归分析及java实现的更多相关文章

  1. MATLAB一元线性回归分析

    MATLAB一元线性回归分析应用举例 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ huigui.m function [b,bint,r,rint, ...

  2. $用python玩点有趣的数据分析——一元线性回归分析实例

    Refer:http://python.jobbole.com/81215/ 本文参考了博乐在线的这篇文章,在其基础上加了一些自己的理解.其原文是一篇英文的博客,讲的通俗易懂. 本文通过一个简单的例子 ...

  3. R语言 多元线性回归分析

    #线性模型中有关函数#基本函数 a<-lm(模型公式,数据源) #anova(a)计算方差分析表#coef(a)提取模型系数#devinace(a)计算残差平方和#formula(a)提取模型公 ...

  4. POJ 1061 - 青蛙的约会 - [exgcd求解一元线性同余方程]

    先上干货: 定理1: 如果d = gcd(a,b),则必能找到正的或负的整数k和l,使ax + by = d. (参考exgcd:http://www.cnblogs.com/dilthey/p/68 ...

  5. HDU3579:Hello Kiki(解一元线性同余方程组)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3579 题目解析:求一元线性同余方程组的最小解X,需要注意的是如果X等于0,需要加上方程组通解的整数区间lc ...

  6. HDU1573:X问题(解一元线性同余方程组)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1573 题目解析;HDU就是坑,就是因为n,m定义成了__int64就WAY,改成int就A了,无语. 这题 ...

  7. POJ2115:C Looooops(一元线性同余方程)

    题目: http://poj.org/problem?id=2115 要求: 会求最优解,会求这d个解,即(x+(i-1)*b/d)modm;(看最后那个博客的链接地址) 前两天用二元一次线性方程解过 ...

  8. HDU1573 X问题【一元线性同余方程组】

    题目链接: http://acm.hdu.edu.cn/showproblem.php? pid=1573 题目大意: 求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X ...

  9. 100天搞定机器学习|Day2简单线性回归分析

    第一天机器学习100天|Day1数据预处理,我们学习了数据预处理.知道了,数据预处理是机器学习中最基础和最麻烦,未来占用时间最长的一步操作.数据预处理一般有六个步骤,导入库.导入数据集.处理缺失值.分 ...

随机推荐

  1. JS的className,字体放大缩小

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  2. Lucene中的合并因子mergeFactor

    mergeFactor 是用来决定segment该如何被addDocument()方法进行合并的. 当mergeFactor取比较小的值时,索引时所使用的内存较少 而且搜素未优化的速度会比较快.因此, ...

  3. lucene4.7 分页

    转载自http://my.oschina.net/MrMichael/blog/220782 我 们先来看下下面的问题,现在我们的索引里有2亿多的数据,那么现在的需求是,把索引里的全部数据,读取然后写 ...

  4. elasticsearch使用jetty进行简单的权限控制

    默认elasticsearch是使用netty作为http的容器,由于netty并没有权限模块,所以默认es没有任何的权限控制,直接通过http就可以进行任何操作,除非把http禁用.但如果你使用el ...

  5. ubuntu server 11.10 mysql 自动备份脚本

    1.下载最新的备份脚本(AutoMySQLBackup) 点这里下载 2.修改脚本配置部分 vi  /root/automysqlbackup-2.5.1-01.sh USERNAME=root PA ...

  6. bundle export fail

    C:\eclipse\eclipse.exe -vmargs -Dfile.encoding=utf8

  7. 转 Fragment 和 FragmentActivity的使用

    今天学习下 Android中的 Fragment 和 FragmentActivity,因为没有4.0手机,平台是2.3.3 所以我是使用 v4 support 包来进行学习. 要想用Fragment ...

  8. zf-关于荆州图片链接和弹出页面问题

    target="_blank" 属性不能写在div 里 所以我在里面加了个a标签 这个属性的作用就是弹出一个新的页面,不会在原先的页面上换地址 如果 style 的加载图片卸载cs ...

  9. zf-关于分页必写的代码

    1 存储过程 ALTER PROCEDURE [dbo].[getStatForXXGKWeb] ), ), ), @page int, -- 必写的 @pageRows int,-- 必写的 @al ...

  10. 一个基于jQuery的简单树形菜单

    在工作中的项目使用的是一个前端基于 jQuery easyui 的一个系统,其中左侧的主菜单使用的是 easyui 中的 tree 组件,不是太熟悉,不过感觉不是太好用. 比如 easyui 中的 t ...