1. 概述
最小二乘法拟合直线的核心思想是:给定一组数据点 ( x i , y i ) (x_i, y_i) (xi,yi),其中i=1, 2, …, N,我们希望找到一条直线y = kx + b,使得这些点到直线的垂直距离的平方和最小。这里的k是直线的斜率,b是直线的截距。
2. 误差函数
为了找到最佳的k和b,我们需要定义一个误差函数,该函数表示所有数据点到直线的垂直距离的平方和。误差函数e可以表示为:
E
=
∑
i
=
1
n
(
y
i
−
(
k
x
i
+
b
)
)
2
=
0
E= \sum_{i=1}^n (y_i - (kx_i + b))^2= 0
E=i=1∑n(yi−(kxi+b))2=0
3. 求解最优参数
为了找到使误差函数e最小的k和b,我们需要对e分别关于k和b求偏导,并令其为0。
对 k求偏导
∂
E
∂
k
=
2
∑
i
=
1
n
(
y
i
−
(
k
x
i
+
b
)
)
(
−
x
i
)
=
0
\frac{\partial E}{\partial k} = 2 \sum_{i=1}^n (y_i - (kx_i + b)) (-x_i) = 0
∂k∂E=2i=1∑n(yi−(kxi+b))(−xi)=0
化简得:
∑
i
=
1
n
x
i
y
i
−
k
∑
i
=
1
n
x
i
2
−
b
∑
i
=
1
n
x
i
=
0
\sum_{i=1}^n x_i y_i - k \sum_{i=1}^n x_i^2 - b \sum_{i=1}^n x_i = 0
i=1∑nxiyi−ki=1∑nxi2−bi=1∑nxi=0
对 b 求偏导
∂
E
∂
b
=
2
∑
i
=
1
n
(
y
i
−
(
k
x
i
+
b
)
)
=
0
\frac{\partial E}{\partial b} = 2 \sum_{i=1}^n (y_i - (kx_i + b)) = 0
∂b∂E=2i=1∑n(yi−(kxi+b))=0
化简得:
∑
i
=
1
n
y
i
−
k
∑
i
=
1
n
x
i
−
n
b
=
0
\sum_{i=1}^n y_i - k \sum_{i=1}^n x_i - nb =0
i=1∑nyi−ki=1∑nxi−nb=0
联立方程组
将两个方程联立,得到关于 (k) 和 (b) 的线性方程组。令:
A
=
∑
i
=
1
n
x
i
2
,
B
=
∑
i
=
1
n
x
i
,
C
=
∑
i
=
1
n
x
i
y
i
,
D
=
∑
i
=
1
n
y
i
A = \sum_{i=1}^n x_i^2, \quad B = \sum_{i=1}^n x_i, \quad C = \sum_{i=1}^n x_i y_i, \quad D = \sum_{i=1}^n y_i
A=i=1∑nxi2,B=i=1∑nxi,C=i=1∑nxiyi,D=i=1∑nyi
方程组形式为:
{
A
k
+
B
b
=
C
B
k
+
n
b
=
D
\begin{cases} A k + B b = C \\ B k + n b = D \end{cases}
{Ak+Bb=CBk+nb=D
解表达式
解得 (k) 和 (b) 的值为:
k
=
C
⋅
n
−
B
⋅
D
A
⋅
n
−
B
2
k = \frac{C \cdot n - B \cdot D}{A \cdot n - B^2}
k=A⋅n−B2C⋅n−B⋅D
b = A ⋅ D − C ⋅ B A ⋅ n − B 2 b = \frac{A \cdot D - C \cdot B}{A \cdot n - B^2} b=A⋅n−B2A⋅D−C⋅B
说明
- 公式推导基于最小二乘法,通过求偏导并令导数为零得到极值点。
- 最终解的表达式可直接用于线性回归参数 (k)(斜率)和 (b)(截距)的计算。
4. MATLAB实现最小二乘法拟合直线
在代码中,我们给定一组数据点(x, y)模拟离散点,直接根据上面推导的公式计算k和b。
clc;
clear;
close all;
%% 设置直线参数
k = 2;
b = 3;
x = -10:0.5:10;
y = k*x + b;
figure
plot(x, y, 'k')
%% 拟合直线
% 给定数据
y = y + randn(size(y))*0.5;
hold on
plot(x, y, 'or')
% 计算k和b
N = length(x);
k = (sum(y .* x) - N * mean(y) * mean(x)) / (sum(x .^ 2) - N * mean(x) ^ 2);
b = mean(y) - k * mean(x);
% 绘制拟合直线
x_line = linspace(min(x), max(x), 100);
y_line = k * x_line + b;
plot(x_line, y_line, '-r');
legend('原始数据', '噪声数据', '拟合直线');
xlabel('x');
ylabel('y');
title('最小二乘法拟合直线');