数据插值、数据拟合、最小二乘拟合、方程组解析解&迭代解法

本文探讨了数值计算中的多项式插值问题,包括拉格朗日插值、线性插值、立方插值以及最近邻插值、样条插值等方法。通过实例展示了不同插值方法在数据拟合上的表现,分析了它们的平滑度和计算复杂度。此外,还涉及到了最小二乘法在数据拟合中的应用,以及分段三次样条函数和B样条函数的使用。这些方法在解决实际问题中具有广泛的应用价值。

在这里插入图片描述
(欠定方程)

%解析解:
A = [2 -9 3 -2 -1; 10 -1 10 5 0; 8 -2 -4 -6 3; -5 -6 -6 -8 -4];
B = [-1 -4 0; -3 -8 -4; 0 3 3; 9 -5 3];
[rank(A), rank([A B])]
x0 = null(sym(A)); % 求AX=0的基础解
x_analytical = sym(A)\B; syms a;
x = a*[x0 x0 x0]+x_analytical
A*x - B

输出:

x =
 
[  - (127*a)/170 - 18/17,     193/170 - (127*a)/170,      5/34 - (127*a)/170]
[  (307*a)/408 + 347/204,     (307*a)/408 - 719/408,   (307*a)/408 - 103/408]
[(3659*a)/2040 + 587/204, (3659*a)/2040 - 8911/2040, (3659*a)/2040 - 283/408]
[- (1321*a)/680 - 265/68,   3069/680 - (1321*a)/680,   33/136 - (1321*a)/680]
[                      a,                         a,                       a]

ans =
 
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
%数值解:
x0=null(A); x_numerical=A\B; syms a;
x=a*[x0 x0 x0]+x_numerical; vpa(x,10)
A*x-B
ans =
 
[0.2474402553*a + 0.1396556436,  0.2474402553*a - 0.6840666849,  0.2474402553*a - 0.1418420333]
[0.4938507789 - 0.2492262414*a, 0.07023776988 - 0.2492262414*a, 0.03853511888 - 0.2492262414*a]
[              -0.5940839201*a,                -0.5940839201*a,                -0.5940839201*a]
[0.6434420813*a - 0.7805411315,  0.6434420813*a - 0.2178190763,  0.6434420813*a - 0.5086089095]
[- 0.3312192394*a - 1.60426346,   2.435364854 - 0.3312192394*a,  0.3867176824 - 0.3312192394*a]
 
ans =
 
[      a/36028797018963968,       a/36028797018963968,       a/36028797018963968]
[-(99*a)/36028797018963968, -(99*a)/36028797018963968, -(99*a)/36028797018963968]
[  (5*a)/18014398509481984,   (5*a)/18014398509481984,   (5*a)/18014398509481984]
[        a/562949953421312,         a/562949953421312,         a/562949953421312]

在这里插入图片描述

syms x1 x2
eqns = [x1^2 - x2 - 1 == 0, (x1-2)^2+(x2-0.5)^2 - 1== 0];
[x1,x2] = solve(eqns,[x1 x2]);
norm(double([x1.^2-x2-1 (x1-2).^2+(x2-0.5).^2-1]))
format long;
syms x1 x2
eqns = [x1^2 - x2 - 1 == 0, (x1-2)^2+(x2-0.5)^2 - 1== 0];
S = solve(eqns,[x1 x2]);
x1 = double(vpa(S.x1)) %将sym类型转换为double类型
x2 = double(vpa(S.x2)) %将sym类型转换为double类型
[res1,res2] = deal(zeros(length(x1),1),zeros(length(x2),1)); %建立残差矩阵
for i = 1:length(x(1))
res1(i) = x1(i)^2 - x2(i) - 1;
res2(i) = (x1(i)-2)^2+(x2(i)-0.5)^2 - 1;
end
res1,res2

输出

x1 =

  1.067346085806690 + 0.000000000000000i
  1.546342883319945 + 0.000000000000000i
 -1.306844484563317 + 1.213690445160591i
 -1.306844484563317 - 1.213690445160591i


x2 =

  0.139227666886861 + 0.000000000000000i
  1.391176312794241 + 0.000000000000000i
 -0.765201989840551 - 3.172209328450632i
 -0.765201989840551 + 3.172209328450632i


res1 =

   1.0e-15 *

  -0.222044604925031
                   0
                   0
                   0


res2 =

     0
     0
     0
     0

在这里插入图片描述

a = [10 -1 -2; -1 10 -2; -1 -1 5];
b = [72; 83; 42];
jacobi(a,b,[0;0;0])
seidel(a,b,[0;0;0])

function y=jacobi(a,b,x0)
D = diag(diag(a)); U=-triu(a,1); L=-tril(a,-1);
B=D\(L+U); f=D\b;
y = B*x0+f;
n = 1;
while norm(y-x0)>=1.0e-6
x0 = y;
y = B*x0+f;
n = n+1;
end
N

function y=seidel(a,b,x0)
D = diag(diag(a)); U = -triu(a,1); L = -tril(a,-1);
G = (D-L)\U; f = (D-L)\b;
y = G*x0+f; 
n = 1;
while norm(y-x0)>=1.0e-6
x0 = y;
y = G*x0+f;
n = n+1;
end
n

(jacobi)输出:

n =
    17
ans =
   11.0000
   12.0000
   13.0000

n =
10

(seidel)输出:

ans =

   11.0000
   12.0000
   13.0000

在这里插入图片描述

x=[-2,-1.7,-1.4,-1.1,-0.8,-0.5,-0.2,0.1,0.4,0.7,1,1.3,...
1.6,1.9,2.2,2.5,2.8,3.1,3.4,3.7,4,4.3,4.6,4.9];
y=[0.10289,0.11741,0.13158,0.14483,0.15656,0.16622,0.17332,...
0.1775,0.17853,0.17635,0.17109,0.16302,0.15255,0.1402,...
0.12655,0.11219,0.09768,0.08353,0.07019,0.05786,0.04687,...
0.03729,0.02914,0.02236];
x1 = [-2:0.1:4.9];
subplot(1,2,1)
y1 = lagrange(x,y,x1);
y2 = interp1(x,y,x1,'linear');
y3 = interp1(x,y,x1,'cubic');
plot(x1,[y1',y2',y3'],':',x,y,'*');
title('拉格朗日、线性插值与立方插值'),legend('lagrange插值曲线','线性插值曲线','立方插值曲线','原始数据点')
subplot(1,2,2)
y4 = interp1(x,y,x1,'nearest');
y5 = interp1(x,y,x1,'spline'); 
y6 = interp1(x,y,x1,'pchip');
plot(x1,[y4',y5',y6'],':',x,y,'*');
title('nearest、spline、pchip插值'),legend('nearest插值曲线','spline插值曲线','pchip插值曲线','原始数据点')

在这里插入图片描述
优劣:拉格朗日插值曲线没有线性插值、立方插值曲线那么平滑,但计算复杂度低;nearest插值曲线没有spline插值、pchip插值曲线那么平滑,但计算简单,其中spline插值曲线效果最佳。

在这里插入图片描述

[x,y]=meshgrid(0.1:0.1:1.1);
z=[0.83041,0.82727,0.82406,0.82098,0.81824,0.8161,0.81481,0.81463,0.81579,0.81853,0.82304;
0.83172,0.83249,0.83584,0.84201,0.85125,0.86376,0.87975,0.89935,0.92263,0.94959,0.9801;
0.83587,0.84345,0.85631,0.87466,0.89867,0.9284,0.96377,1.0045,1.0502,1.1,1.1529;
0.84286,0.86013,0.88537,0.91865,0.95985,1.0086,1.0642,1.1253,1.1904,1.257,1.3222;
0.85268,0.88251,0.92286,0.97346,1.0336,1.1019,1.1764,1.254,1.3308,1.4017,1.4605;
0.86532,0.91049,0.96847,1.0383,1.118,1.2046,1.2937,1.3793,1.4539,1.5086,1.5335;
0.88078,0.94396,1.0217,1.1118,1.2102,1.311,1.4063,1.4859,1.5377,1.5484,1.5052;
0.89904,0.98276,1.082,1.1922,1.3061,1.4138,1.5021,1.5555,1.5573,1.4915,1.346;
0.92006,1.0266,1.1482,1.2768,1.4005,1.5034,1.5661,1.5678,1.4889,1.3156,1.0454;
0.94381,1.0752,1.2191,1.3624,1.4866,1.5684,1.5821,1.5032,1.315,1.0155,0.62477;
0.97023,1.1279,1.2929,1.4448,1.5564,1.5964,1.5341,1.3473,1.0321,0.61268,0.14763];
[x1,y1]=meshgrid(0.1:0.02:1.1);
z1 = interp2(x,y,z,x1,y1);  % z1=interp2(x,y,z,x1,y1,'spline');
figure,surf(x1,y1,z1),axis([0.1,1.1,0.1,1.1,0,1.8])
% axis([0.1,1.1,0.1,1.1,min(z1(:)),max(z1(:))])

在这里插入图片描述
前面给出的数据分别为一元数据和二元数据,试用分段三次样条函数和B样条函数对其进行拟合。

x=[-2,-1.7,-1.4,-1.1,-0.8,-0.5,-0.2,0.1,0.4,0.7,1,1.3,...
1.6,1.9,2.2,2.5,2.8,3.1,3.4,3.7,4,4.3,4.6,4.9];
y=[0.10289,0.11741,0.13158,0.14483,0.15656,0.16622,0.17332,...
0.1775,0.17853,0.17635,0.17109,0.16302,0.15255,0.1402,...
0.12655,0.11219,0.09768,0.08353,0.07019,0.05786,0.04687,...
0.03729,0.02914,0.02236];
figure, plot(x,y,'k*'), hold on;
sp1 = csapi(x,y); fnplt(sp1,'--'), hold on;
sp2 = spapi(5,x,y); fnplt(sp2,':')
title('一元数据拟合'),legend('原始数据','三次样条函数','5次B样条函数')

在这里插入图片描述

x1 = 0.1:0.1:1.1; y1 = 0.1:0.1:1.1;
subplot(121), sp1 = csapi({x1,y1},z); fnplt(sp1);axis([0.1,1.1,0.1,1.1,0,1.8])
subplot(122), sp2 = spapi({5,5},{x1,y1},z); fnplt(sp2);axis([0.1,1.1,0.1,1.1,0,1.8])

在这里插入图片描述
上面给出的数据,试考虑用多项式插值的方法对其数据进行逼近,并选择一个能较好拟合原数据的多项式阶次。

x=[-2,-1.7,-1.4,-1.1,-0.8,-0.5,-0.2,0.1,0.4,0.7,1,1.3,...
1.6,1.9,2.2,2.5,2.8,3.1,3.4,3.7,4,4.3,4.6,4.9];
y=[0.10289,0.11741,0.13158,0.14483,0.15656,0.16622,0.17332,...
0.1775,0.17853,0.17635,0.17109,0.16302,0.15255,0.1402,...
0.12655,0.11219,0.09768,0.08353,0.07019,0.05786,0.04687,...
0.03729,0.02914,0.02236];
x0=-2:0.02:4.9;
p3=polyfit(x,y,3); y3=polyval(p3,x0);
p5=polyfit(x,y,5); y5=polyval(p5,x0);
p7=polyfit(x,y,7); y7=polyval(p7,x0);
p9=polyfit(x,y,9); y9=polyval(p9,x0);
p11=polyfit(x,y,11); y11=polyval(p11,x0);
plot(x0,[y3; y5; y7; y9; y11])

从拟合的结果可以发现,选择5 次多项式就能较好地拟合原始数据。

x=[-2,-1.7,-1.4,-1.1,-0.8,-0.5,-0.2,0.1,0.4,0.7,1,1.3,...
1.6,1.9,2.2,2.5,2.8,3.1,3.4,3.7,4,4.3,4.6,4.9];
y=[0.10289,0.11741,0.13158,0.14483,0.15656,0.16622,0.17332,...
0.1775,0.17853,0.17635,0.17109,0.16302,0.15255,0.1402,...
0.12655,0.11219,0.09768,0.08353,0.07019,0.05786,0.04687,...
0.03729,0.02914,0.02236];

figure, plot(x,y,'k*'),hold on;
p2 = polyfit(x,y,2); y2 = polyval(p2,x);
p3 = polyfit(x,y,3); y3 = polyval(p3,x);
p4 = polyfit(x,y,4); y4 = polyval(p4,x);
p5 = polyfit(x,y,5); y5 = polyval(p5,x);
p6 = polyfit(x,y,6); y6 = polyval(p6,x);
plot(x,[y2',y3',y4',y5',y6']), title('多项式拟合'), legend('原始数据','2次拟合','3次拟合','4次拟合','5次拟合','6次拟合');
if(sum((y2-y).^2)>sum((y3-y).^2)>sum((y4-y).^2)>sum((y5-y).^2)>sum((y6-y).^2))
vpa(poly2sym(p6),4)
end

输出

ans =
 
- 6.457e-6*x^6 - 2.477e-5*x^5 + 0.0007888*x^4 - 0.0007826*x^3 - 0.01729*x^2 + 0.01175*x + 0.1765

在这里插入图片描述
在这里插入图片描述

x=[-2,-1.7,-1.4,-1.1,-0.8,-0.5,-0.2,0.1,0.4,0.7,1,1.3,...
1.6,1.9,2.2,2.5,2.8,3.1,3.4,3.7,4,4.3,4.6,4.9];
y=[0.10289,0.11741,0.13158,0.14483,0.15656,0.16622,0.17332,...
0.1775,0.17853,0.17635,0.17109,0.16302,0.15255,0.1402,...
0.12655,0.11219,0.09768,0.08353,0.07019,0.05786,0.04687,...
0.03729,0.02914,0.02236];

f = inline('exp(-(x-u(1)).^2/2/u(2).^2)/sqrt(2*pi)./u(2)','u','x')
[uu,res] = lsqcurvefit(f,[1,1],x,y)
figure, plot(x,y,'k*'); hold on;
y1 = f(uu,x); plot(x,y1), title('数据最小二乘法拟合'),legend('原始数据','最小二乘法拟合');

输出:

uu =

    0.3461    2.2340


res =

   1.8117e-09

在这里插入图片描述
在这里插入图片描述

[x,y]=meshgrid(0.1:0.1:1.1);
z=[0.83041,0.82727,0.82406,0.82098,0.81824,0.8161,0.81481,0.81463,0.81579,0.81853,0.82304;
0.83172,0.83249,0.83584,0.84201,0.85125,0.86376,0.87975,0.89935,0.92263,0.94959,0.9801;
0.83587,0.84345,0.85631,0.87466,0.89867,0.9284,0.96377,1.0045,1.0502,1.1,1.1529;
0.84286,0.86013,0.88537,0.91865,0.95985,1.0086,1.0642,1.1253,1.1904,1.257,1.3222;
0.85268,0.88251,0.92286,0.97346,1.0336,1.1019,1.1764,1.254,1.3308,1.4017,1.4605;
0.86532,0.91049,0.96847,1.0383,1.118,1.2046,1.2937,1.3793,1.4539,1.5086,1.5335;
0.88078,0.94396,1.0217,1.1118,1.2102,1.311,1.4063,1.4859,1.5377,1.5484,1.5052;
0.89904,0.98276,1.082,1.1922,1.3061,1.4138,1.5021,1.5555,1.5573,1.4915,1.346;
0.92006,1.0266,1.1482,1.2768,1.4005,1.5034,1.5661,1.5678,1.4889,1.3156,1.0454;
0.94381,1.0752,1.2191,1.3624,1.4866,1.5684,1.5821,1.5032,1.315,1.0155,0.62477;
0.97023,1.1279,1.2929,1.4448,1.5564,1.5964,1.5341,1.3473,1.0321,0.61268,0.14763];

figure, plot3(x,y,z,'k*'); hold on;

[x1,y1,z1] = deal(x(:),y(:),z(:));
A = [sin(x1.^2.*y1), cos(y1.^2.*x1), x1.^2, x1.*y1, ones(size(x1))];
uu = A\z1
[x,y] = meshgrid(0.1:0.02:1.1);
zz = uu(1)*sin(x.^2.*y) + uu(2)*cos(y.^2.*x) + uu(3)*x.^2 + uu(4)*x.*y + uu(5);
surf(x,y,zz), title('数据最小二乘法拟合');

或者

figure, plot3(x,y,z,'k*'); hold on;
[x,y] = meshgrid(0.1:0.02:1.1);
zz = A*uu;
zz = reshape(zz,size(x));
surf(x,y,zz), title('数据最小二乘法拟合');

输出:

uu =
  -0.892046932516342
   3.093786470903605
  -0.122032779311857
   2.708280894352104
  -2.425070282206750

在这里插入图片描述
假设已知一组实测数据在文件c8pdat.dat中给出,试通过插值的方法绘制出三维曲面。

c8pdata = load('c8pdat.dat');
[x, y, z] = deal(c8pdata(:,1), c8pdata(:,2), c8pdata(:,3));
[max(x), min(x) max(y), min(y) max(z),min(z)] % 找出插值区域
[x1,y1] = meshgrid(0:0.02:1,0:0.02:1);
z1 = griddata(x,y,z,x1,y1,'v4');
figure, plot3(x,y,z,'k*'); hold on;
surf(x1,y1,z1), axis([0,1,0,1,0,2])
title('插值三维曲面');legend('原始数据','插值曲面')

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq-120

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值