matlabcurve-fitting

Matlab fittype of a logged power law, with a y-intercept


In Matlab, I am doing a curve fitting of a set of points, which follow a power law. If I use the 'log(a*x^n)' power law as the main argument of the fittype function, everything works well:

% input
x = [4 9 15 25 35 45 55 65 75 85 95 150 250 350 450 900];
y = [335 28 37 9 4 3.5 2 1 0.7 0.6 0.5 0.3 0.1 0.01 0.005 0.001];
% curve fitting
ft = fittype('log(a*x^n)','independent','x');
[fitresult, gof] = fit(x',log(y)',ft,'Startpoint', [1 -1]);
% plots
hold on
plot(x,y,'o-','Color','b')
plot(x,(fitresult.a .* (x.^fitresult.n)),'-','color','r')
set(gca, 'XScale', 'log', 'YScale', 'log');

enter image description here

However, if I add an additional parameter, b (i.e. the y-intercept), to the previous power law, i.e. now being 'log(a*x^n + b)', in the fittype function...

% input
x = [4 9 15 25 35 45 55 65 75 85 95 150 250 350 450 900];
y = [335 28 37 9 4 3.5 2 1 0.7 0.6 0.5 0.3 0.1 0.01 0.005 0.001];
% curve fitting
ft = fittype('log(a*x^n + b)','independent','x');
[fitresult, gof] = fit(x',log(y)',ft,'Startpoint', [1 -1 1]);
% plots
hold on
plot(x,y,'o-')
plot(x,(fitresult.a .* (x.^fitresult.n)),'-')
set(gca, 'XScale', 'log', 'YScale', 'log');

I get the following error:

Error using fit>iFit
Complex value computed by model function, fitting cannot continue.
Try using or tightening upper and lower bounds on coefficients.

Error in fit (line 117)
[fitobj, goodness, output, convmsg] = iFit( xdatain, ydatain, fittypeobj, ...

Error in untitled6 (line 6)
[fitresult, gof] = fit(x',log(y)',ft,'Startpoint', [1 -1 1]);

How can I solve this error and - in general - make the fittype function work for a logged power law which includes a y-intercept?


Solution

  • It looks like during the fitting process Matlab is trying negative values for b, and that gives a complex result for the logarithm. The error is quite explicit:

    Complex value computed by model function, fitting cannot continue. Try using or tightening upper and lower bounds on coefficients.

    To avoid that, as the error suggests, specify a lower value 0 for b. You do that with the 'lower' optional input of the fit function. This forces you to specify lower values for all coefficients, so for ther others use -inf.

    Added or modified lines are marked with %%:

    % input
    x = [4 9 15 25 35 45 55 65 75 85 95 150 250 350 450 900];
    y = [335 28 37 9 4 3.5 2 1 0.7 0.6 0.5 0.3 0.1 0.01 0.005 0.001];
    % curve fitting
    ft = fittype('log(a*x^n + b)','independent','x');
    ind_b = strcmp(coeffnames(ft), 'b');   %% index of 'b' coefficient
    lower_values = -inf(1, numel(ind_b));  %% lower value -inf for all coefficients...
    lower_values(ind_b) = 0;               %% ...except 0 for b
    [fitresult, gof] = fit(x',log(y)',ft,'Startpoint', [1 -1 1],...
        'lower',lower_values);             %% use 'lower' optional input
    % plots
    hold on
    plot(x,y,'o-')
    plot(x,(fitresult.a .* (x.^fitresult.n)),'-')
    set(gca, 'XScale', 'log', 'YScale', 'log');