MATLAB中lsqcurvefit拟合正弦曲线却输出直线问题求助
问题描述
我尝试使用MATLAB的lsqcurvefit函数拟合含干扰的正弦曲线,先生成了如下信号:
A=3.75; omega=2; phi=2; t=1:10000; y=A*sin(omega*t/1000+phi); noise1=(rand(1,10000)-0.5)*0.2; noise2=0.1*sin(2*t); sig_out=A*sin(omega*t/1000+(phi-0.5))+noise1+noise2; figure; plot(t,y); hold on; plot(t,sig_out); grid on;
上述代码生成了含随机噪声、小幅振荡及相位偏移的目标信号。随后使用如下拟合代码:
close all; f=@(x,xdata) x(1)*sin(x(2)*xdata+x(3)); x0=[3.75 2 2]; %definiamo i limiti inferiore e superiore della regressione lob=ones(1,10000)*x0(1)*1.05*-1; upb=ones(1,10000)*x0(1)*1.05; options=optimoptions('lsqcurvefit','Diagnostic','on','MaxIteration',1000000000,'Display','iter-detailed','FunctionTolerance',1e-100,'FiniteDifferenceType','central','StepTolerance',1e-100,'FiniteDifferenceStepSize',100); [reg,EXITFLAG]=lsqcurvefit(f,x0,t,sig_out,lob,upb,options);
但拟合结果仅为一条围绕0的带小幅振荡的直线,尝试过多种参数仍未解决,请问问题出在哪里?
问题分析与解决方法
1. 参数上下限设置完全错误
lsqcurvefit中lob和upb是拟合参数的取值范围,不是拟合输出值的范围。你当前生成了长度为10000的数组,而拟合参数只有3个(振幅、角频率、相位),维度不匹配会直接导致拟合逻辑崩溃,这是核心问题。
正确设置方式是给3个参数分别定范围:
lob = [0, 0, 0]; % 振幅非负,角频率非负,相位可设0到2π区间 upb = [5, 5, 2*pi]; % 根据目标信号的大致范围设定上限
2. 拟合模型与信号生成逻辑不一致
生成信号时,角频率项是omega*t/1000,但拟合模型里写的是x(2)*xdata(即x(2)*t)。实际目标信号的角频率是2/1000=0.002,但你初始值设为x0(2)=2,和真实值差了1000倍,算法根本找不到正确的收敛方向。
修正拟合模型,使其和信号生成逻辑对齐:
f=@(x,xdata) x(1)*sin(x(2)*xdata/1000 + x(3));
初始值x0保持[3.75 2 2]即可,因为x(2)对应原信号的omega,和真实值一致。
3. 优化参数设置过于极端,破坏计算精度
FiniteDifferenceStepSize设为100过大,数值梯度计算会完全失真,改成1e-6这类远小于1的数值才合理;FunctionTolerance和StepTolerance设为1e-100没有意义,MATLAB浮点数精度极限在1e-16左右,设置过小只会增加无意义的计算量;MaxIteration设为1e9完全没必要,默认迭代次数足够完成这类简单拟合。
简化后的options示例:
options=optimoptions('lsqcurvefit',... 'Display','iter-detailed',... 'FiniteDifferenceType','central',... 'FiniteDifferenceStepSize',1e-6);
4. 高频干扰的影响
noise2=0.1*sin(2*t)是高频干扰,频率远高于目标信号。如果需要更精准的拟合,可以先对sig_out做低通滤波,滤除高频成分后再进行拟合。
内容的提问来源于stack exchange,提问作者Alessandro Pani
相关产品推荐
相关产品推荐

