MATLAB 中的曲线拟合,对于超过 8 项的正弦函数?

Curve fitting in MATLAB, for a Sinusoidal function with more than 8 terms?

我正在尝试将一些数据拟合到 MATLAB 中的正弦函数和,但是,MATLAB 中正弦函数的项数是有限的,即到 1 ≤ n ≤ 8。但是,我想要在我的拟合函数中有更多的项,即超过 50 个项。有没有办法让 MATLAB 将我的数据拟合为具有超过 8 个正弦项的正弦函数之和?为什么在 MATLAB 中有这样的约束(是技术上的还是任意的)?是否有适合正弦函数的工具箱(尤其是能够支持加权数据的工具箱)?

>f = fit(X,Y, 'sin10')
>Error using fittype>iCreateFromLibrary (line 412)
>Library function sin10 not found.

最多'sin8'或'sin9'个参数是o.k。

感谢您的回答。

我在浏览 MATLAB 帮助时无意中找到了问题的解决方案。我post这个回答希望能帮助到有同样问题的人

作为解决这个问题的第一步,我尝试了 'fit' 指令。出于某些原因,定制的 'fit' 基础拟合代码如下,没有锻炼:

FitOptions = fitoptions('Method','NonlinearLeastSquares', 'Algorithm', 'Trust-Region', 'MaxIter');
FitType = fittype('a*sin(1*f) + b*sin(2*f) + c*sin(3*f) + d*sin(4*f) + e*sin(5*f) + g*sin(6*f) + h*sin(7*f) + k*sin(8*f) + l*sin(9*f) + m*sin(10*f) + n*sin(11*f)', 'independent', 'f');
[FittedModel, GOF] = fit(freq, data, FitType)
% `In above code, phase parameters are not included, they might be added.

我发现使用Optimization Toolbox 中的'lsqcurvefit' 指令,自定义函数拟合比'fit' 函数更可行、更容易。我对其进行了测试,使我的数据适合以下代码中 12 (>8) 个正弦的总和:

clear;clc
xdata=1:0.1:10; % X or Independant Data
ydata=sin(xdata+0.2)+0.5*sin(0.3*xdata+0.3)+ 2*sin( 0.2*xdata+23 )+...
    0.7*sin( 0.34*xdata+12 )+.76*sin( .23*xdata+.3 )+.98*sin(.76 *xdata+.56 )+...
    +.34*sin( .87*xdata+.123 )+.234*sin(.234 *xdata+23 ); % Y or Dependant data 
x0 = randn(36,1);  % Initial Guess
fun = @(x,xdata)x(1)*sin(x(2)*xdata+x(3))+... 
                x(4)*sin(x(5)*xdata+x(6))+...
                x(7)*sin(x(8)*xdata+x(9))+...
              x(10)*sin(x(11)*xdata+x(12))+...
              x(13)*sin(x(14)*xdata+x(15))+...
              x(16)*sin(x(17)*xdata+x(18))+...
              x(19)*sin(x(20)*xdata+x(21))+...
              x(22)*sin(x(23)*xdata+x(24))+...
              x(25)*sin(x(26)*xdata+x(27))+...
              x(28)*sin(x(29)*xdata+x(30))+...
              x(31)*sin(x(32)*xdata+x(33))+...
              x(34)*sin(x(35)*xdata+x(36)); % Goal function which is Sum of 12 sines
options = optimoptions('lsqcurvefit','Algorithm','trust-region-reflective');% Options for fitting 
x=lsqcurvefit(fun,x0,xdata,ydata) % the main instruction
times = linspace(xdata(1),xdata(end));
plot(xdata,ydata,'ko',times,fun(x,times),'r-')
legend('Data','Fitted Sum of 12 Sines')
title('Data and Fitted Curve')

结果还算满意(目前为止),如下图:

上面的问题是,当我使用matlab fit 函数时,为Sum of Sines 拟合指定参数(例如fit(xdata,ydata,'sin6')),它很容易收敛到一个最优解和拟合结果可以接受如下:

但是当我尝试使用自定义函数拟合相同数据时,结果并不令人满意,如下图所示:

fun=@(x,xdata)a1*sin(b1*xdata+c1)+...+a6*sin(b6*xdata+c6); %Sum if Six Sines
f=fit(xdata,ydata,fun);

首先,我觉得它是 fit 指令,所以我尝试了其他指令,例如 lsqcurvefit ,它对某些数据运行良好,但一旦使用其他数据,它就开始表现不佳. 从 Maltab 文档中,我发现 Sum of Sine 拟合和 Fourier 拟合对起点或初始点非常敏感,或者拟合算法在其第一次迭代中为拟合参数(振幅、频率和相位)假设的值.通过检查 Matlab 拟合工具箱 .m 文件,我注意到当您使用预定义函数拟合时,matlab 做了一些巧妙的技巧来获取起点(例如 fit(x,y,'sin1'), or fit(x,y,'sin2'),... 但是当您选择 ti 输入自定义函数时,初始点是随机生成!这就是为什么 Matlab 构建函数起作用而我的自定义函数拟合不起作用(即使我输入相同的函数)。 顺便说一句,Matlab 计算 ydata 的 FFT,并通过一些(看起来很贪婪的)方法提取振幅、频率和相位的初始点(称为 startpt.m 的函数执行此操作)。