使用MATLAB拟合正弦函数遇MaxFunEvals超限及NaN问题求助
MATLAB正弦函数拟合出现NaN及迭代次数超限问题
我尝试用以下MATLAB代码将数据集拟合成正弦函数:
data = importdata('analisipicco.txt') ; x = data(:,1) ; y = data(:,2) ; yu = max(y); yl = min(y); yr = (yu-yl); % Range of ‘y’ yz = y-yu+(yr/2); zx = x(yz .* circshift(yz,[0 1]) <= 0); % Find zero-crossings per = 2*mean(diff(zx)); % Estimate period ym = mean(y); % Estimate offset fit = @(b,x) b(1).*(sin(2*pi*x./b(2) + 2*pi/b(3))) + b(4); % Function to fit fcn = @(b) sum((fit(b,x) - y).^2); % Least-Squares cost function s = fminsearch(fcn, [yr; per; -1; ym]) % Minimise Least-Squares xp = linspace(min(x),max(x)); figure(1) plot(x,y,'b', xp,fit(s,xp), 'r') grid
参数向量s(即函数中的b)各元素含义:
- s(1): 正弦波幅值(单位与y一致)
- s(2): 周期(单位与x一致)
- s(3): 相位(相位为
s(2)/(2*s(3)),单位与x一致) - s(4): 偏移量(单位与y一致)
运行代码后,命令窗口报错:
Maximum number of function evaluations has been exceeded - increase MaxFunEvals option. Current function value: NaN s = 1.0e+05 * 1.0466 NaN -0.0000 2.4885
不确定是数据不适合正弦拟合,还是代码有问题,我的数据集如下:
-200 183966 -192 189734 -184 195724 -176 201663 -168 207557 -160 213278 -152 219000 -144 224677 -136 229500 -128 236024 -120 241968 -112 247787 -104 252963 -96 257491 -88 261967 -80 267373 -72 273494 -64 278599 -56 281476 -48 282610 -40 283097 -32 283839 -24 284971 -16 286169 -8 287164 0 287968 8 288561 16 288626 24 288107 32 286967 40 285132 48 282828 56 279847 64 276296 72 272299 80 268080 88 263564 96 258926 104 254052 112 248894 120 243694 128 238177 136 232665 144 227143 152 221959 160 216874 168 211678 176 206540 184 201537 192 196748 200 192091
我是MATLAB新手,恳请帮忙解答,谢谢!
问题分析与解决方案
- 拟合函数相位项的隐患
原拟合函数中相位部分写为2*pi/b(3),当b(3)趋近于0时会触发无穷大计算,直接导致NaN。建议简化参数定义,把相位作为独立的弧度参数:
fit = @(b,x) b(1).*sin(2*pi*x./b(2) + b(3)) + b(4);
此时s(3)直接代表相位(弧度),避免分母为0的风险,也符合常规正弦拟合的参数逻辑。
- 初始值估计偏差
原代码通过零交叉点计算周期的方式不适用于当前单峰对称数据:你的x范围(-200到200)仅覆盖半个周期,导致per估计错误。手动设置更合理的初始值:
amp_guess = (max(y)-min(y))/2; % 幅值应为峰值到偏移量的差值,而非全范围 period_guess = 800; phase_guess = 0; offset_guess = mean(y); initial_guess = [amp_guess; period_guess; phase_guess; offset_guess];
- 迭代次数限制
默认fminsearch的迭代次数不足以完成拟合,需通过参数设置扩容:
options = optimset('MaxFunEvals', 10000, 'MaxIter', 5000); s = fminsearch(fcn, initial_guess, options);
- 数据适配性验证
你的数据集是对称单峰曲线,完全符合余弦/相位偏移正弦函数的特征,不存在数据不适合拟合的问题。
修改后的完整代码
data = importdata('analisipicco.txt') ; x = data(:,1) ; y = data(:,2) ; % 合理估计初始参数 amp_guess = (max(y)-min(y))/2; period_guess = 800; phase_guess = 0; offset_guess = mean(y); initial_guess = [amp_guess; period_guess; phase_guess; offset_guess]; % 简化拟合函数,避免分母为0 fit = @(b,x) b(1).*sin(2*pi*x./b(2) + b(3)) + b(4); fcn = @(b) sum((fit(b,x) - y).^2); % 设置迭代参数 options = optimset('MaxFunEvals', 10000, 'MaxIter', 5000); s = fminsearch(fcn, initial_guess, options); xp = linspace(min(x),max(x),1000); % 增加点数让拟合曲线更平滑 figure(1) plot(x,y,'b.', xp,fit(s,xp), 'r-','LineWidth',1.5) grid on xlabel('x') ylabel('y') legend('原始数据','拟合曲线') % 输出参数含义 fprintf('幅值: %.2f\n周期: %.2f\n相位(弧度): %.2f\n偏移量: %.2f\n', s(1), s(2), s(3), s(4));
内容的提问来源于stack exchange,提问作者Jack_01
相关产品推荐
相关产品推荐

