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');
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?
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');