开始学习回归算法,先看下最小乘法在回归算法里面的应用。相关概念理论如下:

最小二乘法

我们在研究两个变量(x, y)之间的相互关系时,通常可以得到一系列成对的数据(x1, y1、x2, y2... xm , ym);将这些数据描绘在x -y直角座标系中(如图1), 若发现这些点在一条直线附近,可以令这条直线方程如(式1-1)。 

Y计= a0 + a1 X                 (式1-1) 
其中:a0、a1 是任意实数 
为建立这直线方程就要确定a0和a1,应用《最小二乘法原理》,将实测值Yi与利用(式1-1)计算值(Y计= a0 + a1 X)的离差(Yi - Y计)的平方和`〔∑(Yi - Y计)2〕最小做为“优化判据”。 
令: φ = ∑(Yi - Y计)2               (式1-2) 
把(式1-1)代入(式1-2)中得: 
φ = ∑(Yi - a0 - a1 Xi)2               (式1-3) 
当∑(Yi-Y计)平方最小时,可用函数 φ 对a0、a1求偏导数,令这两个偏导数等于零。 

            (式1-4) 

         (式1-5)  

亦即: 
m a0 + (∑Xi ) a1 = ∑Yi              (式1-6) 
(∑Xi ) a0 + (∑Xi2 ) a1 = ∑(Xi, Yi)          (式1-7) 
得到的两个关于a0、 a1为未知数的两个方程组,解这两个方程组得出:
a0 = ∑Yi / m - a1 * ∑Xi / m                                 (式1-8)
a1 = [m∑(XiYi) - ∑Xi * ∑Yi] / [m∑(Xi^2) - (∑Xi)^2]  (式1-9) 

其中m为样本容量
这时把a0、a1代入(式1-1)中, 此时的(式1-1)就是我们回归的元线性方程即:数学模型。 
在回归过程中,回归的关联式是不可能全部通过每个回归数据点(x1, y1、 x2, y2...xm,ym),为了判断关联式的好坏,可借助相关系数“R”,统计量“F”,剩余标准偏差“S”进行判断;“R”越趋近于 1 越好;“F”的绝对值越大越好;“S”越趋近于 0 越好。 其中:
R = [∑XiYi - m (∑Xi / m)(∑Yi / m)]/ SQR{[∑Xi2 - m (∑Xi / m)2][∑Yi2 - m (∑Yi / m)2]}        (式1-10) 

最小三乘法

促上述情况之外,我们在研究实际中两个变量(x, y)之间的相互关系时,对一系列成对的数据(x1,y1、x2,y2 ... xm,ym);将这些数据描绘在x - y直角座标系(如图2)中,发现这些点在一条曲线附近,假设这条曲线的一元非线性方程如(式2-1)。

Y计 = a0 + a1 Xk            (式2-1) 
其中:a0、a1、k是任意实数 
为建立曲线方程,就要确定a0 、a1和 k 值,应用《最小二乘法》同样的方法, 将实测值Yi与计算值 Y计(Y计 = a0 + a1 Xik)的离差 (Yi - Y计)的平方和〔∑(Yi - Y计)2〕为依据:
令: φ = ∑(Yi - Y计)2           (式2-2)
把(式2-1)代入(式2-2)中得:
φ = ∑(Yi - a0 - a1 Xik )2       (式2-3) 
用函数 φ 分别对a0、a1 和 k 求偏导数,令这三个偏导数等于零即:
         (式2-4) 

     (式2-5) 

    (式2-6) 

得到三个关于a0、a1 和 k,为未知数的三元方程组,解方程组即可得到数学模型。 这里就不再详细陈述了。有兴趣的小伙伴可以自己算出相应的值。

最小三乘法和最小二乘法比较:

1.“最小三乘法”利用计算幂值,使回归模型函数曲线以不同曲率弯曲,来更好的拟和不同曲率的曲线。它省去了“最小二乘法”中繁琐的建机理模型和线性化处理,使回归模型与数据拟和更好。
2.对多维非线性数据回归,不用“偏最小二乘法”的每个因素逐一与目标函数回归建模,再把所有模型捆绑成最终模型的方法,而是所有因素与目标函数,同时一次回归成数学模型,在回归时,它不但考虑因素对目标函数的贡献,还把因素之间的影响考虑进去,这样的模型要比用“偏最小二乘法”回归的模型准确。
3.“最小二乘法”数据回归一因素数据只有一元 “X”, “最小三乘法” 数据回归一因素数据可有若干个元

“Xk1”、“Xk2” 、… “Xkn” 如(式3-2), 利用这一特性,可使回归模型拟和数据更准确。 

Y计 = a0 + a1 Xk1 + a2 Xk2 +...+ an X kn                   (式3-2)


选择回归参数注意问题 
1、当一因素数据中有 0 值时, 此因素数据不可作除数和取对数;可把此维数据加上一个数,使它大于零。 
2、当一因素数据中有负数都有时,此因素数据不可做回归计算;可把此维数据乘上一个负数,使它大于零。
3、某因素数据取幂时,不可太大和太小,否则回归计算机会中断溢出;有时回归出的模型,不能逆运算。

下面是用Java语言简单实现的最小二乘法算法:

public class LeastSquaresBuilder {
	
	//初始化数据
	private List<Point> initializeData() {
		List<Point> points = new ArrayList<Point>();
		points.add(new Point(1, 110));
		points.add(new Point(2, 120));
		points.add(new Point(3, 130));
		points.add(new Point(4, 140));
		points.add(new Point(5, 150));
		points.add(new Point(6, 160));
		points.add(new Point(7, 170));
		points.add(new Point(8, 180));
		points.add(new Point(9, 190));
		return points;
	}
	
	/**
	 * Y = a0 + a1 * X 
	 * a0 = ∑Yi / m - a1 * ∑Xi / m
	 * a1 = [m∑(XiYi) - ∑Xi * ∑Yi] / [m∑(Xi^2) - (∑Xi)^2]
	 * 计算a0、a1
	 */
	private double[] calculate(List<Point> points) {
		double[] xParameters = extract(points, "X");
		double[] yParameters = extract(points, "Y");
		double m = points.size();
		double xSum = sum(xParameters, false);
		double ySum = sum(yParameters, false);
		double xySum = sum(xParameters, yParameters);
		double xxSum = sum(xParameters, true);
		double p1 = m * xySum - xSum * ySum;
		double p2 = m * xxSum - Math.pow(xSum, 2);
		double a1 =  p1 / p2;
		double a0 = ySum / m - a1 * xSum / m;
		System.out.println("Y = " + a0 + " + " + a1 + " * X");
		return new double[]{a0 , a1};
	}
	
	//预测X的值Y
	private double predict(double[] a0_a1, double x) {
		if (a0_a1.length != 2) {
			throw new RuntimeException("error");
		}
		return a0_a1[0] + a0_a1[1] * x;
	}
	
	//计算∑(Xi) 或则 ∑(Xi^2)
	private double sum(double[] parameters, boolean isSquare) {
		double result = 0.0;
		for (double parameter : parameters) {
			result += isSquare ? Math.pow(parameter, 2) : parameter;
		}
		return result;
	}
	
	//计算∑(XiYi)
	private double sum(double[] xParameters, double[] yParameters) {
		double result = 0.0;
		for (int i = 0, len = xParameters.length; i < len; i++) {
			result += xParameters[i] * yParameters[i];
		}
		return result;
	}
	
	//抽取某一维度点集合
	private double[] extract(List<Point> points, String type) {
		double[] result = new double[points.size()];
		int index = 0;
		for (Point point : points) {
			if ("X".equals(type)) {
				result[index++] = point.getX();
			} else if ("Y".equals(type)) {
				result[index++] = point.getY();
			}
		}
		return result;
	}
	
	public void build() {
		List<Point> points = initializeData();
		double[] a0_a1 = calculate(points);
		double x = 10;
		double result = predict(a0_a1, x);
		System.out.println("predict " + x + " result: " + result);
	}

	public static void main(String[] args) {
		LeastSquaresBuilder builder = new LeastSquaresBuilder();
		builder.build();
	}
}

代码托管:https://github.com/fighting-one-piece/repository-datamining.git

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐