函数功能:高斯牛顿法实现非线性数据拟合。
- 代码
clear;clc;
M=1000;
Te=20;
% 模型
t=Te*(1:M)';
load noise; % 噪音可自己添加
Et1=0.4*exp(-t/50)+0.6*exp(-t/200);
Et2=0.4*exp(-(t/50).^2)+0.6*exp(-t/200);
Et3=0.3*exp(-t/50)+0.4*exp(-t/200)+0.3*exp(-t/800);
Et4=0.3*exp(-(t/50).^2)+0.4*exp(-t/200)+0.3*exp(-t/800);
Et = Et4 + noise;
%%
% 选择合适的初始值很重要
% p0=[0.5,10,0.5,100];
p0=[0.5,50,0.5,100,0.5,500]';
% 迭代过程
for i=1:M
[J,dF] = GNA(p0,t,Et);
p = p0+(J'*J)\J'*dF;
if norm(p-p0)/norm(p0)<1e-6
break;
end
p0 = p;
end
disp(p);
fit = p(1)*exp(-(t/p(2)).^2) + p(3)*exp(-t/p(4)) + p(5)*exp(-t/p(6));
plot(t,Et,t,fit)
xlabel('Measured time(\mus)');
ylabel('Amplitude');
title('Models VS Fitting');
legend('Model','Fitting')
function [J,dE]=GNA(p,t,Et)
% 计算Jacobi矩阵和拟合误差
% p为未知参数
p1 = p(1);
p2 = p(2);
p3 = p(3);
p4 = p(4);
p5 = p(5);
p6 = p(6);
f = p1*exp(-(t/p2).^2) + p3*exp(-t/p4) + p5*exp(-t/p6); % 拟合函数表达式
fp1 = exp(-t.^2/p2^2);
fp2 = (2*p1*t.^2.*exp(-t.^2/p2^2))/p2^3;
fp3 = exp(-t/p4);
fp4 = (p3*t.*exp(-t/p4))/p4^2;
fp5 = exp(-t/p6);
fp6 = (p5*t.*exp(-t/p6))/p6^2;
J = [fp1,fp2,fp3,fp4,fp5,fp6];
dE = Et - f;
计算结果如下:0.3030 48.8801 0.3971 198.6767 0.3057 791.1436;
仅七次迭代就得到了结果,速度快,精度高。
对比Matlab自带函数nlinfit和lsqcurvefit的计算结果:
Nlinfit:0.3030 48.8801 0.3971 198.6768 0.3057 791.1437
Lsqcurvefit:0.3030 48.8795 0.3970 198.6615 0.3057 791.1156