插值的概念: 数模比赛中,常常需要根据已知的函数点进行数据、模型的处理和分析,而有时候现有的数据是极少的,不足以支撑分析的进行,这时就需要使用一些数学的方法,“模拟产生”一些新的但又比较靠谱的值来满足需求,这就是插值的作用。
插值法的定义:
设函数$y=f(x)$在区间$[a,b]$上有定义,且已知在$a \leq$
上的值分别为:$y_0,y_1,...,y_n$
若存在一简单函数$p(x)$,使
则称$P(x)$为$f(x)$的插值函数,求插值函数$P(x)$的方法称为插值法。
插值法的分类:
1.若$P(x)$是次数不超过n的代数多项式,即
2.若$P(x)$为分段多项式,就称为分段插值
3.若$P(x)$为三角多项式,就称为三角插值
注: 我们一般只讨论多项式插值和分段插值
设有n+1个互不相同的节点$(x_i,y_i) \qquad (i=0,1,2,...,n)$
则存在唯一的多项式:
使得
拉格朗日插值法: 在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫∙路易斯∙拉格朗日命名的一种多项式插值方法。在若干个不同的地方得到相应的观测值, 拉格朗日插值法可以找到一个多项式,其恰好在各个观测的点取到观测到的值。
拉格朗日插值多项式:
其中
其中
龙格现象: 插值多项式并不是次数越高误差越小,高次插值会产生龙格现象,即在两端处波动极大,产生明显的震荡。在不熟悉曲线 运动趋势的前提下,不要轻易使用高次插值。
分段低次插值的思路:插值多项式次数高精度未必显著提高,插值多项式次数越高误差可能显著增大。将插值节点等分为多个部分,在每个部分分别采取低次插值。常用的方法有分段线性插值和分段二次插值。
牛顿插值公式:
$$ f(x)=f(x_0)+fx_0,x_1+fx_0,x_1,x_2(x-x_1)+... +fx_0,x_1,...,x_{n-2},x_{n-1}(x-x_1)...(x-x_{n-3})(x-x_{n-2}) +fx_0,x_1,...,x_{n-1},x_n(x-x_1)...(x-x_{n-2})(x-x_{n-1}) $$
差商的定义:
称$f[x_0,x_k]=\frac{f(x_k)-f(x_0)}{x_k-x_0}$为函数关于点$x_0,x_k$的一阶差商(亦称均差)。
二阶差商:$f[x_0,x_1,x_2]=\frac{f[x_1,x_2]-f[x_0,x_1]}{x_2-x_0}$
K阶差商:
注: 与拉格朗日插值法相比,牛顿插值法的计算过程具有继承性。(牛顿插值法每次插值只和前n项 的值有关,这样每次只要在原来的函数上添加新的项,就能够产生新的函数) 但是牛顿插值也存在龙格现象的问题。
拉格朗日插值和牛顿插值法的缺点:
1.龙格现象;
2.不能全面反映被插值函数的性态。(在许多实际问题中,不仅要求插值函数与被插值函数在所有节 点处有相同的函数值,它也需要在一个或全部节点上插值多项式与被插函数有相同的低阶甚至高阶的导数值。)
设函数$f(x)$在区间$[a,b]$上有n+1个互异节点
定义在$[a,b]$上函数$f(x)$在节点上满足:
可唯一确定一个次数不超过2n+1的多项式
其余项为:
注: 直接使用埃尔米特插值得到的多项式次数较高,也存在着龙格现象,因此在实际应用中,往往使用分段三次埃尔米特插值多项式。
分段三次埃尔米特插值PCHIP的示例代码:
% 分段三次埃尔米特插值
x = -pi:pi; y = sin(x);
new_x = -pi:0.1:pi;
p = pchip(x,y,new_x);
figure(1); % 在同一个脚本文件里面,要想画多个图,需要给每个图编号,否则只会显示最后一个图哦~
plot(x, y, 'o', new_x, p, 'r-')
补充plot函数用法:
% plot函数用法:
% plot(x1,y1,x2,y2)
% 线方式: - 实线 :点线 -. 虚点线 - - 波折线
% 点方式: . 圆点 +加号 * 星号 x x形 o 小圆
% 颜色: y黄; r红; g绿; b蓝; w白; k黑; m紫; c青
设$y=f(x)$在点$x_0,x_1,x_2,...,x_n$的值为$y_0,y_1,y_2,...,y_n$,
若函数$S(x)$满足下列条件
(1)$S(x_i)=f(x_i)=y_i,i=0,1,2,...,n$
(2)在每个子区间 $x_i,x_{i+1}$
(3)$S(x)$在$[a,b]$上二阶连续可微。
则称$S(x)$为函数$f(x)$的三次样条插值函数
三次样条插值函数满足的条件:
并且满足条件:
$$ S_{i-1}(x_i)=S_i(x_i),\ S'_{i-1}(x_i)=S'i(x_i),\ S''{i-1}(x_i)=S''_i(x_i), $$
三次样条插值示例代码:
x = -pi:pi; y = sin(x);
new_x = -pi:0.1:pi;
p = interpn (x, y, new_x, 'spline');
% 等价于 p = spline(x, y, new_x);
figure(3);
plot(x, y, 'o', new_x, p, 'r-')
%插值预测中间周的水体评价指标
load Z.mat
x=Z(1,:); %Z的第一行是星期Z: 1 3 5 7 9 11 13 15
[n,m]=size(Z);%n为Z的行数,m为Z的列数
% 注意Matlab的数组中不能保存字符串,如果要生成字符串数组,就需要使用元胞数组,其用大括号{}定义和引用
ylab={'周数','轮虫','溶氧','COD','水温','PH值','盐度','透明度','总碱度','氯离子','透明度','生物量'}; % 等会要画的图形的标签
disp(['共有' num2str(n-1) '个指标要进行插值。'])
disp('正在对一号池三次埃尔米特插值,请等待')%一号池共有十一组要插值的数据,算上星期所在的第一行,共十二行
P=zeros(11,15);%对要储存数据的矩阵P赋予初值
for i=2:n%从第二行开始都是要进行插值的指标
y=Z(i,:);%将每一行依次赋值给y
new_x=1:15;%要进行插值的x
p1=pchip(x,y,new_x);%调用三次埃尔米特插值函数
subplot(4,3,i-1);%将所有图依次变现在4*3的一幅大图上
plot(x,y,'ro',new_x,p1,'-');%画出每次循环处理后的图像
axis([0 15,-inf,inf]) %设置坐标轴的范围,这里设置横坐标轴0-15,纵坐标不变化
% xlabel('星期')%x轴标题
ylabel(ylab{i})%y轴标题 这里是直接引用元胞数组中的字符串哦
P(i-1,:)=p1;%将每次插值之后的结果保存在P矩阵中
end
legend('原始数据','三次埃尔米特插值数据','Location','SouthEast')%加上标注,注意要手动在图中拖动标注到图片右下角哦
P = [1:15; P] %把P的第一行加上周数
拟合的概念: 与插值问题不同,在拟合问题中不需要曲线一定经过给定的点。拟合问题的目标是寻求一个函数(曲线),使得该曲线在某种准则下与所有的数据点最为接近,即曲线拟合的最好(最小化损失函数)。
插值和拟合的区别:
插值算法中,得到的多项式f(x)要经过所有样本点。但是如果样本点太多,那么这个多项式次数过高,会造成龙格现象。
尽管我们可以选择分段的方法避免这种现象,但是更多时候我们更倾向于得到一个确定的曲线,尽管这条曲线不能经过每一个样本点,但只要保证误差足够小即可,这就是拟合的思想。(拟合的结果是得到一个确定的曲线)
评价拟合的好坏
拟合优度(可决系数)$R^2$
总体平方和SST:$SST=\sum_{i=1}^{n}(y_i-\overline{y})^2$
误差平方和SSE:$SSE=\sum_{i=1}^{n}(y_i-\widehat{y_i})^2$
回归平方和SSR:$SSR=\sum_{i=1}^{n}(\widehat{y_i}-\overline{y_i})^2$
可以证明:$SST=SSE+SSR$
拟合优度:
注意:
线性函数和其他函数(例如复杂的指数函数)比较拟合的好坏,直接看SSE即可
注意:这里的线性函数是指线性于参数的函数。在函数中,参数仅以一次方出现,且不能乘以或除以其他任何的参数,并不能出现参数的复合函数形式。
拟合样例习题:根据给定的x,y值,拟合曲线。并求出SSR、SSE、SST、$R^2$等评价拟合优度的指标
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,'-')
% 匿名函数的基本用法。
% handle = @(arglist) anonymous_function
% 其中handle为调用匿名函数时使用的名字。
% arglist为匿名函数的输入参数,可以是一个,也可以是多个,用逗号分隔。
% anonymous_function为匿名函数的表达式。
% 举个小例子
% z=@(x,y) x^2+y^2;
% z(1,2)
% % ans = 5
% fplot函数可用于画出匿名一元函数的图形。
% fplot(f,xinterval) 将匿名函数f在指定区间xinterval绘图。xinterval = [xmin xmax] 表示定义域的范围
f=@(x) k*x+b;
fplot(f,[2.5,7]);
legend('样本数据','拟合函数','location','SouthEast')
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
clear;clc
year = 1790:10:2000;
population = [3.9,5.3,7.2,9.6,12.9,17.1,23.2,31.4,38.6,50.2,62.9,76.0,92.0,106.5,123.2,131.7,150.7,179.3,204.0,226.5,251.4,281.4];
plot(year,population,'o')
cftool % 拟合工具箱
% (1) X data 选择 year
% (2) Y data 选择 population
% (3) 拟合方式选择:Custom Equation (自定义方程)
% (4) 修改下方的方框为:x = f(t) = xm/(1+(xm/3.9-1)*exp(-r*(t-1790)))
% (5) 左边的result一栏最上面显示:Fit computation did not converge:即没有找到收敛解,右边的拟合图形也表明拟合结果不理想
% (6) 点击Fit Options,修改非线性最小二乘估计法拟合的初始值(StartPoint), r修改为0.02,xm修改为500
% 有很多同学有疑惑,初始值为什么要这样设置?我们在未来学习微分方程模型和智能算法的课程时再来给大家介绍这里面蕴含的技巧。
% (7) 此时左边的result一览得到了拟合结果:r = 0.02735, xm = 342.4
% (8) 依次点击拟合工具箱的菜单栏最左边的文件—Generate Code(导出代码到时候可以放在你的论文附录),可以得到一个未命名的脚本文件
% (9) 在这个打开的脚本中按快捷键Ctrl+S,将这个文件保存到当前文件夹。
% (10) 在现在这个文件中调用这个函数得到参数的拟合值和预测的效果
[fitresult, gof] = createFit(year, population)
t = 2001:2030;
xm = 342.4;
r = 0.02735;
predictions = xm./(1+(xm./3.9-1).*exp(-r.*(t-1790))); % 计算预测值(注意这里要写成点乘和点除,这样可以保证按照对应元素进行计算)
figure(2)
plot(year,population,'o',t,predictions,'.') % 绘制预测结果图