笔记整理来自《清风数学建模系列课程》
目录
一、插值和拟合的区别
与插值问题不同,在拟合问题中不需要曲线一定经过给定的点。拟问题的目标是寻求一个函数(曲线),使得该曲线在某种准则下与所有的数据点最为接近,即曲线拟合的最好(最小化损失函数)。
插值算法中,得到的多项式f(x)要经过所有样本点。但是如果样本点太多,那么这个多项式次数过高,会造成龙格现象。
尽管我们可以选择分段的方法避免这种现象,但是更多时候我们更倾向于得到一个确定的曲线,尽管这条曲线不能经过每一个样本点,但只要保证误差足够小即可,这就是拟合的思想。(拟合的结果是得到一个确定的曲线)
二、拟合——找到y和x之间的拟合曲线
数据:
x | 4.2 | 5.9 | 2.7 | 3.8 | 3.8 | 5.6 | 6.9 | 3.5 | 3.6 | 2.9 | 4.2 | 6.1 | 5.5 | 6.6 | 2.9 | 3.3 | 5.9 | 6 | 5.6 |
y | 8.4 | 11.7 | 4.2 | 6.1 | 7.9 | 10.2 | 13.2 | 6.6 | 6 | 4.6 | 8.4 | 12 | 10.3 | 13.3 | 4.6 | 6.7 | 10.8 | 11.5 | 9.9 |
1. 导入数据到matlab
matlab中如何导入数据:
现在数据窗口新建两个变量x和y,把变量的数据从excel中粘贴进去。然后右击鼠标选择“save”,将数据保存为.mat格式即可,这里命名为data1.mat.
易错的细节:load data1.mat时导入出错是因为当前文件夹里面找不到data1.mat,所以需要把当前文件夹切换到有data1.mat的文件夹中。
2. 散点图分析
clear;clc
load data1
plot(x,y,'o')
% 给x和y轴加上标签
xlabel('x的值')
ylabel('y的值')
通过散点图可以发现,数据变化的趋势有点像一次函数,所以我们可以定义y=f(x)的函数图像为y=kx+b,接下来只需要算出k和b的值即可。
3. 确定拟合曲线的函数关系式
如何让样本点和拟合曲线最为接近呢?——最小二乘法。
(1)最小二乘法的几何解释
argmin表示使得|真实值与拟合值之差|的和最小的k和b的值。
第一种定义有绝对值,不容易求导,因此计算比较复杂。所以我们往往使用第二种定义,这也正是最小二乘的思想。最小二乘法的“二”其实指的就是平方的意思。
为什么不用四次方?
(1)避免极端数据对拟合曲线的影响。比如有一个异常值,如果用它的值减去拟合值再求四次方,会对结果有很大的影响。
(2)最小二乘法得到的结果和MLE极大似然估计一致。
不用奇数次方的原因:误差会正负相抵。
(2)求解最小二乘法
matlab求解:
size()函数的用法:
size():获取矩阵的行数和列数
1、s=size(A),当只有一个输出参数时,返回一个行向量,该行向量的第一个元素是矩阵的行数,第二个元素是矩阵的列数。
2、[r,c]=size(A),当有两个输出参数时,size函数将矩阵的行数返回到第一个输出变量r,将矩阵的列数返回到第二个输出变量c。
3、size(A,n)如果在size函数的输入参数中再添加一项n,并用1或2为n赋值,则 size将返回矩阵的行数或列数。其中r=size(A,1)该语句返回的时矩阵A的行数, c=size(A,2) 该语句返回的时矩阵A的列数。
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))
matlab计算得到:k = 2.0948,b =-1.0548
(3)将散点图和拟合函数图像画在一起
在指导拟合函数y=kx+b的函数关系式为y=2.0948x-1.0548,那么怎么画函数图像呢?
方法1:我们可以自己生成x的值,再根据y=2.0948x-1.0548的值画图
clear;clc
load data1
plot(x,y,'o')
% 给x和y轴加上标签
xlabel('x的值')
ylabel('y的值')
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 % 显示网格线
% % 画出y=kx+b的函数图像 plot(x,y)
% % 传统的画法:模拟生成x和y的序列,比如要画出[0,5]上的图形
xx = 2.5: 0.1 :7 % 间隔设置的越小画出来的图形越准确
yy = k * xx + b % k和b都是已知值
plot(xx,yy,'-')
clear;clc
load data1
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))
grid on % 显示网格线
% % 画出y=kx+b的函数图像 plot(x,y)
xx = 2.5: 0.1 :7 % 间隔设置的越小画出来的图形越准确
yy = k * xx + b % k和b都是已知值
plot(x,y,'o',xx,yy,'r-')
legend('真实值','拟合值(拟合函数)')
% 给x和y轴加上标签
xlabel('x的值')
ylabel('y的值')
方法2: 使用匿名函数
% 匿名函数的基本用法。
handle = @(arglist) anonymous_function
% 其中handle为调用匿名函数时使用的名字。
% arglist为匿名函数的输入参数(自变量),可以是一个,也可以是多个,用逗号分隔。
% anonymous_function为匿名函数的表达式。
举例:如要表示z=x^2+y^2
z=@(x,y) x^2+y^2;
z(1,2)
% % ans = 5
% fplot函数可用于画出匿名一元函数的图形。
fplot(f,xinterval)
% fplot(f,xinterval) 将匿名函数f在指定区间xinterval绘图。xinterval = [xmin xmax] 表示定义域的范围
clear;clc
load data1
plot(x,y,'o')
% 给x和y轴加上标签
xlabel('x的值')
ylabel('y的值')
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')
(4) 评价拟合的好坏
证明SST = SSE + SSR
这里的“线性”指的是“对参数为线性”。y=a+bx^2有两个参数a和b,并没有出现a*b,a^2等参数非线性的情况,所以这个函数为线性函数。
如何判断线性于参数的函数?
在函数中,参数仅以一次方出现,且不能乘以或除以其他任何的参数,并不能出现参数的复合函数形式。
神经网络可以用拟合优度。
(5)拟合优度的matlab求解
y_hat = k*x+b; % y的拟合值
SSR = sum((y_hat-mean(y)).^2) % 回归平方和
SSE = sum((y_hat-y).^2) % 误差平方和
SST = sum((y-mean(y)).^2) % 总体平方和
SST-SSE-SSR % 5.6843e-14 = 5.6843*10^-14 matlab浮点数计算的一个误差
R_2 = SSR / SST
计算得到R^2=0.9635