Search code examples
matlableast-squaresnonlinear-optimizationnon-linear-regression

Maximum number of function evaluations has been exceeded - increase MaxFunEvals option


I was trying to fit a data set into a sinusoidal function with the code below:

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

Where the elements of output parameter vector, s ( b in the function ) are:

s(1): sine wave amplitude (in units of y)

s(2): period (in units of x)

s(3): phase (phase is s(2)/(2*s(3)) in units of x)

s(4): offset (in units of y)

But when I run the code with my set of data the command window show this:

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

I don't understand if my data are not fitting for a sinusoidal function or just the code is wrong for the sinusoidal fit.

For acknowledge this is my data set:

-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

I'm sorry but I'm new to Matlab. Thank you in advance


Solution

  • Your code goes wrong on the line

    zx = x(yz .* circshift(yz,[0 1]) <= 0);
    

    yz is a column vector, so circshifting it by 1 in the horizontal direction doesn't do anything at all.

    Changing the [0 1] into [1 0] makes your code run correctly:

    s =
    
       1.0e+05 *
    
        0.6986
        0.0061
       -0.0000
        2.1975
    

    To make your code more robust against changes in the input data orientation, you can use circshift(yz,1) instead. Assuming that y is always a vector, this will be correct no matter if it's a column or row vector.