[求助]:利用非线性最小二乘法来优化参数的问题?
各位高手,我修改了一下我的程序,可以运行,但是拟合出来的数据不对,不知道是何缘故?可运行的程序如下:
首先编制非线性模型m文件(sta67_2m.m:
function dd1=model(beta0,dd2)
a=beta0(1);
b=beta0(2);
c=beta0(3);
d=beta0(4);
e=beta0(5);
f=beta0(6);
g=beta0(7);
h=beta0(8);
k=beta0(9);
l=beta0(10);
dd1=a*sin(2*pi*0.97656*dd2+b)+c*sin(2*pi*1.9531*dd2+d)+e*sin(2*pi*2.9297*dd2+f)+g*sin(2*pi*3.9063*dd2+h)+k*sin(2*pi*4.8828*dd2+l);
然后在命令栏里面输入:
yy=Data(2100*500:2103*500);dd1=yy';
x=0:0.002:3;dd2=x;
beta0=;
nlintool(dd2,dd1,'sta67_2m',beta0);
betafit=nlinfit(dd2,dd1,'sta67_2m',beta0);
betafit=0.039909 -35.47
-0.044785 0.075721
-0.13027 0.8733
0.32827 11.404
0.40317 -4.0571
然后我将实际dd1值的图形和拟合出来的dd1的图形进行对比(见附图1和附图2),从两图可以看出可以看出图形形状不一样且大小也差的很远,不知道这是怎么回事?
回复
拟合不同于插值, 有一定偏差一般是很正常的.另:你也可以试试lsqcurvefit函数.
[ 本帖最后由 xjzuo 于 2006-11-16 14:52 编辑 ] lsqcurvefit函数如何使用呀?能否告知?我这里有10个参数要识别,lsqcurvefit命令能否识别的出来? 原帖由 kingsword1979 于 2006-11-16 15:00 发表
lsqcurvefit函数如何使用呀?能否告知?我这里有10个参数要识别,lsqcurvefit命令能否识别的出来?
doc lsqcurvefit看一下帮助吧,里边有详细的说明
还有例子 谢谢楼上的高手 楼上的高手,我借了本书看到这样一个例子,很符合我的需要,但是我原搬不动的把书上的例子抄下来,在MATLAB里面运行,还是出错,请帮我看看,谢谢。
例子如下:函数为:y=c(1)*exp(-d(1)*x)+c(2)*exp(-d(2)*x)
function F=myfun(d,Data)
%假设y=c(1)*exp(-d(1)*x)+...+c(n))*exp(-d(n)*x)
%带有n个线性参数,n个非线性参数
x=Data(:,1);y=Data(:,2);
A=zeros(length(x),length(d));
for i=1:length(d)
A(:,i)=exp(-d(i)*x);
end
c=A\y; %通过A*c=y求解线性参数c;
z=A*c;
f=z-y;
Data=';
options=optimset('LargeScale','off');
options=optimset(options,'MaxFunEvals',300);
options=optimset(options,'LevenbergMarquardt','off');
options=optimset(options,'LineSearch','cubicpoly');
d0=;
d=lsqnonlin('myfun2',d0,[],[],options,Data);
【结果输出】
c=2.8898
3.0061
d=1.4006 10.5891
我运行了上面的例子,怎么老是出错,不知道能不能告诉我问题出在哪里?谢谢! function F=myfun(d,Data)
%假设y=c(1)*exp(-d(1)*x)+...+c(n))*exp(-d(n)*x)
%带有n个线性参数,n个非线性参数
x=Data(:,1);y=Data(:,2);
A=zeros(length(x),length(d));
for i=1:length(d)
A(:,i)=exp(-d(i)*x);
end
c=A\y; %通过A*c=y求解线性参数c;
z=A*c;
F=z-y;
上面部分存成myfun.m,你的代码中F写成了f,matlab是区分大小写的
Data=';
options=optimset('LargeScale','off');
options=optimset(options,'MaxFunEvals',300);
options=optimset(options,'LevenbergMarquardt','off');
options=optimset(options,'LineSearch','cubicpoly');
d0=;
d=lsqnonlin('myfun',d0,[],[],options,Data)
注意函数名 非常感谢楼上的高手帮我指出错误,谢谢!更正程序后,出现这样的提示:
Optimization terminated: directional derivative along
search direction less than TolFun and infinity-norm of
gradient less than 10*(TolFun+TolX).
这怎么解决呢? d是非线性项的参数,可以正确识别出来,但是c是线性项的参数,程序没有计算出来,是不是跟上面的提示有关,如何更正呢?
回复
你把你原来的数据文件传上来吧.这样我们可以试试哪个函数能拟合的好一些. y的文件数据在附件1,另外x的文件数据就是时间x=0:0.002:3,谢谢帮我分析一下。 上面的例子我已经可以正确求出参数c和d了,现在我根据上面的例子来模仿编程,程序如下:首先编制m.文件(文件名为myfun.m)
function F=myfun(d,Data)
%假设y=c(1)*sin(2*pi*0.97656*t+d(1))+c(2)*sin(2*pi*1.9531*t+d(2))+c(3)*sin(2*pi*2.9297*t+d(3))+c(4)*sin(2*pi*3.9063*t+d(4))+c(5)*sin(2*pi*4.8828*t+d(5))
%带有5个线性参数c,5个非线性参数d
t=0:0.002:3;x=t';
y=Data(2100*500:2103*500);
A=zeros(length(x),length(d));
for i=1:length(d))
A(:,i)=sin(2*pi*i*0.97656*x+d(i));
end
c=A\y;
z=A*c;
F=z-y;
然后输入上面附件里面的数据Data文件
options=optimset('LargeScale','off');
options=optimset(options,'MaxFunEvals',300);
options=optimset(options,'LevenbergMarquardt','off');
%options=optimset(options,'LineSearch','cubicpoly');
d0=;
d=lsqnonlin('myfun',d0,[],[],options,Data);
结果Matlab提示:
??? Error using ==> optim\private\lsqncommon
User supplied function failed with the following error:
Error: File: d:\MATLAB7\work\myfun.m Line: 7 Column: 18
Unbalanced or misused parentheses or brackets.
Error in ==> lsqnonlin at 147
= ...
这是什么原因呢?哪位高手能帮我改通顺吗?
[ 本帖最后由 kingsword1979 于 2006-11-19 10:51 编辑 ] 怎么数据好象不可用? 我用的是Matlab7
回复
先写成.xls或.txt,再传一下吧.我一直用的是6.5。但数据可能已经corrupt. 应该不是版本的问题.
另:我认为你也许把问题复杂化了,参数不必象你那样进行区分.
[ 本帖最后由 xjzuo 于 2006-11-19 23:24 编辑 ]