清风建模第四讲拟合
插值和拟合的区别:
插值得到的函数一定会经过所有的点,这就会导致当多项式次数过高的时候会造成龙格现象。
而拟合得到的函数虽然并不会经过所有的点,但是得到的曲线误差尽可能地小。
例如要拟合的点为:
数据:
用函数y = kx + b来拟合
最小二乘法
当k和b取何值时,得到的拟合曲线最接近呢?
第一种定义:
y
i
∗
=
k
×
x
i
+
b
k
,
b
=
a
r
g
m
i
n
(
∑
n
=
1
n
∣
y
i
−
y
i
∗
∣
)
y^*_i = k \times x_i + b\\ k,b = argmin(\sum_{n=1}^{n}{|y_i - y^*_i|})
yi∗=k×xi+bk,b=argmin(n=1∑n∣yi−yi∗∣)
第二种定义:
y
i
∗
=
k
×
x
i
+
b
k
,
b
=
a
r
g
m
i
n
(
∑
n
=
1
n
(
y
i
−
y
i
∗
)
2
)
y^*_i = k \times x_i + b\\ k,b = argmin(\sum_{n=1}^{n}{(y_i - y^*_i)^2})
yi∗=k×xi+bk,b=argmin(n=1∑n(yi−yi∗)2)
由于第一种定义含有绝对值,不方便求导,所以一般使用第二种定义
于是通过得到拟合曲线
matlab代码如下:
data.mat文件存储的x和y的值
% 加载数据
load data.mat
plot(X,Y,'o')
% 加标签
xlabel('x的值')
ylabel('y的值')
% 拟合函数y=kx+b
n = size(X,1)
k = (n*sum(X.*Y)-sum(X)*sum(Y))/(n*sum(X.*X)-sum(X)*sum(X))
b = (sum(X.*X)*sum(Y)-sum(X)*sum(X.*Y))/(n*sum(X.*X)-sum(X)*sum(X))
hold on % 继续在之前的图形上来画图形
grid on % 显示网格线
% 用匿名函数绘制图像
f = @(x) k * x + b
fplot(f,[2.5,7])
legend("原始数据的值","拟合数据的值","Location","southeast")
% 判断拟合效果
y_hat = k * X + b
SSR = sum((y_hat-mean(Y)).^2) % 回归平方和
SSE = sum((y_hat-Y).^2) % 误差平方和
SST = sum((Y-mean(Y)).^2) % 总体平方和
SST = SSE + SSR
R_2 = SSR / SST
python代码如下
data1.xlsx存储的就是开头图片中的数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据
data = pd.read_excel('./data1.xlsx')
data = pd.DataFrame(data)
x = np.array(data.iloc[:,0])
y = np.array(data.iloc[:,1])
plt.scatter(x,y) #绘制图像
# 拟合y = kx + b
n = np.size(x)
k = (n * np.sum(x * y) - np.sum(x) * np.sum(y)) / (n * np.sum(x * x) - np.sum(x) * np.sum(x))
b = (np.sum(x * x) * np.sum(y) - np.sum(x) * np.sum(x * y)) / (n * np.sum(x * x) - np.sum(x) * np.sum(x))
y_hat = x * k + b
plt.plot(x,y_hat,'r')
# 计算R^2
SSR = np.sum((y_hat - np.mean(y)) ** 2) # 回归平方和
SSE = np.sum((y_hat - y) ** 2) # 误差平方和
SST = np.sum((y - np.mean(y)) ** 2) # 总体平方和
SST = SSE + SSR
R_2 = SSR / SST
print(R_2)
plt.show()
SST = np.sum((y - np.mean(y)) ** 2) # 总体平方和
SST = SSE + SSR
R_2 = SSR / SST
print(R_2)
plt.show()