1. 简单线性回归 y = ax + b
double[] x = {540, 360, 240};
double[] y = {205, 325, 445};
问题
根据double[] x 和 double[] y ,计算y = ax + b中a和b的值
解决方法
最小二乘法:让距离(实验值和理论值的差值)的平方和最小
即:
求 ( 205 − 540 a − b ) 2 + ( 325 − 360 a − b ) 2 + ( 445 − 240 a − b ) 2 (205 - 540a - b)^2 + (325 - 360a -b)^2 + (445 - 240a -b)^2 (205−540a−b)2+(325−360a−b)2+(445−240a−b)2的最小值
如何求解
对a和b求偏导数,取偏导数为0,可以求解得到a和b。
理论推导
输入数据:
x = [ x 1 , x 2 , . . . , x n ] , y = [ y 1 , y 2 , . . . , y n ] x = [ x_1,x_2, ..., x_n], y = [ y_1,y_2, ..., y_n] x=[x1,x2,...,xn],y=[y1,y2,...,yn]
差值的平方:
f ( a , b ) = ( y 1 − a x 1 − b ) 2 + ( y 2 − a x 2 − b ) 2 + . . . + ( y n − a x n − b ) 2 f(a,b) = (y_1-ax_1-b)^2 + (y_2-ax_2-b)^2 + ... + (y_n-ax_n-b)^2 f(a,b)=(y1−ax1−b)2+(y2−ax2−b)2+...+(yn−axn−b)2
求f(a,b)的最小值,即
∂ f ∂ a = 0 \frac{ \partial f }{ \partial a } = 0 ∂a∂f=0
∂ f ∂ b = 0 \frac{ \partial f }{ \partial b } = 0 ∂b∂f=0
(1)---------------------------------------------------------------------------------------------------------------------
∂ f ∂ b = 0 \frac{ \partial f }{ \partial b } = 0 ∂b∂f=0
∂ f ∂ b = − 2 ( y 1 − a x 1 − b ) − 2 ( y 2 − a x 2 − b ) − . . . − 2 ( y n − a x n − b ) = 0 \frac{ \partial f }{ \partial b } = -2(y_1-ax_1-b) - 2(y_2-ax_2-b) - ... - 2(y_n-ax_n-b) = 0 ∂b∂f=−2(y1−ax1−b)−2(y2−ax2−b)−...−2(yn−axn−b)=0
( y 1 − a x 1 − b ) + ( y 2 − a x 2 − b ) + . . . + ( y n − a x n − b ) = 0 (y_1-ax_1-b) + (y_2-ax_2-b) + ... + (y_n-ax_n-b) = 0 (y1−ax1−b)+(y2−ax2−b)+...+(yn−axn−b)=0
( y 1 + y 2 + . . . + y n ) − a ( x 1 + x 2 + . . . + x n ) − n b = 0 (y_1 + y_2 + ... + y_n) - a(x_1 + x_2+ ... + x_n) - nb = 0 (y1+y2+...+yn)−a(x1+x2+...+xn)−nb=0
( y 1 + y 2 + . . . + y n ) = a ( x 1 + x 2 + . . . + x n ) + n b (y_1 + y_2 + ... + y_n) = a(x_1 + x_2+ ... + x_n) + nb (y1+y2+...+yn)=a(x1+x2+...+xn)+nb
令
y ‾ = y 1 + y 2 + . . . + y n n , x ‾ = x 1 + x 2 + . . . + x n n \overline y = \frac{y_1 + y_2 + ... + y_n }{n},\overline x = \frac{x_1 + x_2+ ... + x_n }{n} y=ny1+y2+...+yn,x=nx1+x2+...+xn
则:
y ‾ = a x ‾ + b \overline y = a\overline x + b y=ax+b
b = y ‾ − a x ‾ b = \overline y - a\overline x b=y−ax
(2)---------------------------------------------------------------------------------------------------------------------
∂ f ∂ a = 0 \frac{ \partial f }{ \partial a } = 0 ∂a∂f=0
∂ f ∂ a = − 2 x 1 ( y 1 − a x 1 − b ) − 2 x 2 ( y 2 − a x 2 − b ) − . . . − 2 x n ( y n − a x n − b ) = 0 \frac{ \partial f }{ \partial a } = -2x_1(y_1-ax_1-b) - 2x_2(y_2-ax_2-b) - ... - 2x_n(y_n-ax_n-b) = 0 ∂a∂f=−2x1(y1−ax1−b)−2x2(y2−ax2−b)−...−2xn(yn−axn−b)=0
x 1 ( y 1 − a x 1 − b ) + x 2 ( y 2 − a x 2 − b ) + . . . + x n ( y n − a x n − b ) = 0 x_1(y_1-ax_1-b) + x_2(y_2-ax_2-b) + ... + x_n(y_n-ax_n-b) = 0 x1(y1−ax1−b)+x2(y2−ax2−b)+...+xn(yn−axn−b)=0
( x 1 y 1 + x 2 y 2 + . . . + x n y n ) − a ( x 1 2 + x 2 2 + . . . + x n 2 ) − b ( x 1 + x 2 + . . . + x n ) = 0 (x_1y_1 + x_2y_2 + ... + x_ny_n)-a(x_1^2 +x_2^2 + ... + x_n^2) - b(x_1 + x_2+ ... + x_n)= 0 (x1y1+x2y2+...+xnyn)−a(x12+x22+...+xn2)−b(x1+x2+...+xn)=0
( x 1 y 1 + x 2 y 2 + . . . + x n y n ) − a ( x 1 2 + x 2 2 + . . . + x n 2 ) − n b x ‾ = 0 (x_1y_1 + x_2y_2 + ... + x_ny_n)-a(x_1^2 +x_2^2 + ... + x_n^2) - nb\overline x= 0 (x1y1+x2y2+...+xnyn)−a(x12+x22+...+xn2)−nbx=0
( x 1 y 1 + x 2 y 2 + . . . + x n y n ) − a ( x 1 2 + x 2 2 + . . . + x n 2 ) − ( n y ‾ − n a x ‾ ) x ‾ = 0 (x_1y_1 + x_2y_2 + ... + x_ny_n)-a(x_1^2 +x_2^2 + ... + x_n^2) - (n\overline y - na\overline x)\overline x= 0 (x1y1+x2y2+...+xnyn)−a(x12+x22+...+xn2)−(ny−nax)x=0
a ( x 1 2 + x 2 2 + . . . + x n 2 ) − n a x ‾ 2 = ( x 1 y 1 + x 2 y 2 + . . . + x n y n ) − n y ‾ × x ‾ a(x_1^2 +x_2^2 + ... + x_n^2)-na\overline x^2 = (x_1y_1 + x_2y_2 + ... + x_ny_n) - n\overline y \times \overline x a(x12+x22+...+xn2)−nax2=(x1y1+x2y2+...+xnyn)−ny×x
a = ∑ i = 1 n x i y i − n y ‾ × x ‾ ∑ i = 1 n x i 2 − n x ‾ 2 a= \frac{ \sum_{i=1}^{n} x_iy_i - n\overline y \times \overline x }{ \sum_{i=1}^{n} x_i^2 - n \overline x^2} a=∑i=1nxi2−nx2∑i=1nxiyi−ny×x
代码实现
/*** 普通最小二乘法给出的判断标准是:残差平方和的值达到最小* 计算最小二乘法的斜率a和截距b* @param x: 输入x向量* @param y: 输入y向量* @return 斜率和截距*/public static double[] linearLeastSquares(double[] x, double[] y) {int n = x.length;double sumX = 0.0;double sumY = 0.0;double sumXY = 0.0;double sumX2 = 0.0;for (int i = 0; i < n; i++) {sumX += x[i];sumY += y[i];sumXY += x[i] * y[i];sumX2 += x[i] * x[i];}double a = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);double b = (sumY - a * sumX) / n;return new double[]{a, b}; // 返回斜率a和截距b}public static void main(String[] args) {double[] x = {540, 360, 240, 480, 420};double[] y = {205, 325, 445, 505, 455};double[] result = linearLeastSquares(x, y);System.out.println("斜率a: " + result[0]);System.out.println("截距b: " + result[1]);}