插值算法存在的意义和概念
数模比赛中,常常需要根据已知的函数点进行数据、模型的处理和分析,而有时候现有的数据是极少的,不足以支撑分析的进行,这时就需要使用一些数学的方法,“模拟产生”一些新的但又比较靠谱的值来满足需求,这就是插值的作用。
朗格朗日插值算法
分段二次插值算法
由于拉格朗日插值法在高次时会存在较大误插,所以我们使用较少(三个)相邻的样本点进行二次插值运算
牛顿插值法
与拉格朗日插值法相比,牛顿插值法的计算过程具有继承性。(牛顿插值法每次插值只和前n项的值有关,这样每次只要在原来的函数上添加新的项,就能够产生新的函数)但是牛顿插值也存在龙格现象的问题。
埃尔米特(Hermite)插值
埃尔米特(Hermite)插值算法的改进主要是在导数方面进行了改进,这样就能控制函数的增长下降速度保持和原始数据的变化率相似,但是可能存在数据的稀疏在一定程度还是存在龙格现象。所以最常见的还是埃尔米特三次插值和下面的三次样条插值。
三次样条插值
埃尔米特三次插值和三次样条插值MATLAB库
p1 = pchip(x,y,new_x);%埃尔米特三次
p2 = spline(x,y,new_x);%三次样条插值
%生成初始化样本点
x=-4:4;
y = sin(x);
%插值的横坐标
new_x =-4:0.1:4;
p1 = pchip(x,y,new_x); %根据原始样本点使用分段三次埃尔米特插值
p2 = spline(x,y,new_x); %根据原始样本点使用三次样条插值
plot(x,y,'o',new_x,p1,'r--',new_x,p2,'b-',new_x,sin(new_x),'black--')
legend('样本点','三次埃尔米特插值','三次样条插值','sin图像','Location','SouthEast') %标注显示在东南方向
观察结果:
三次样条插值几乎和sin函数完全重合并且更平滑,三次埃尔米特插值则略逊与三次样条
N维数据的插值函数
p = interpn(x1,x2,...,xn, y, new_x1,new_x2,...,new_xn, method)
method是要插值的方法:
‘linear’:线性插值(默认算法);
‘cubic’:三次插值;
‘spline’:三次样条插值法;(最为精准)
‘nearest’:最邻近插值算法。
使用一维示例:
x=-4:4;
y = sin(x);
new_x =-4:0.1:4;
p = interpn(x,y, new_x,'spline' );
plot(x,y,'o',new_x,p,'r-',new_x,sin(new_x),'black--')
legend('样本点','三次样条插值','sin图像','Location','SouthEast')
插值案例
共12行,每一行就是一个数据特征,
特征名分别为:{‘周数’,‘轮虫’,‘溶氧’,‘COD’,‘水温’,‘PH值’,‘盐度’,‘透明度’,‘总碱度’,‘氯离子’,‘透明度’,‘生物量’}
我们发现只有单数周的数据,所以我们需要用插值法填补双数周的数据。
x=Z(1,:); %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) '个指标要进行插值。']);
P=zeros(11,15);%对要储存数据的矩阵P赋予初值
for i=2:n%从第二行开始都是要进行插值的指标
y=Z(i,:);%将每一行依次赋值给y
new_x=1:15;%要进行插值的新x
p1=spline(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','best')%加上标注,注意要手动在图中拖动标注到图片右下角哦
P = [1:15; P] %把P的第一行加上周数
P数据结果就是: