I have an initial parameters for lsqcurvefit like
a0 = [value1, value2, value3];
and then
curvefitoptions = optimset('Display','final','MaxFunEvals',10000,'MaxIter',5000);
[a] = lsqcurvefit(@myfun,a0,x,y,lb,ub,curvefitoptions);
I want to be able to fix any of the initial parameters, f.ex. I'm fixing a0(1) and a0(3) at given value and optimizing only a0(2). How to do it? I was trying fixing it in ub and lb, but the same values are not allowed. Of course I can add a bit for ub, but it's not a nice way of doing it :)
Any suggestions? Thanks!
You can create an anonymous function that fixes the value of the first and third elements. You also need to tweak the start points (2nd argument) and the upper & lower bounds so that they only apply to the 2nd element, e.g.,
a = lsqcurvefit( @(x, xdata) myfun([a0(1); x; a0(3)], xdata), a0(2), x, y, ...
lb(2), ub(2), curvefitoptions );
You can easily change this to fix the 2nd and 3rd elements, e.g.,
a = lsqcurvefit( @(x, xdata) myfun([x; a0(2); a0(3)], xdata), a0(1), x, y, ...
lb(1), ub(1), curvefitoptions );
Or to fix just the 2nd element
a = lsqcurvefit( @(x, xdata) myfun([x(1); a0(2); x(2)], xdata), a0([1,3]), x, y, ...
lb([1,3]), ub([1,3]), curvefitoptions );
To do this in general, start by defining the following (or similar) function
function a = interlace( a, x, fix )
a(~fix) = x;
end
You can then replace code like [a0(1); x; a0(3)]
in the examples above with a call to interlace()
. For example,
fix = [1; 0; 1];
a_free = lsqcurvefit( @(x, xdata) myfun( interlace( a0, x, fix ), xdata), ...
a0(~fix), x, y, lb(~fix), ub(~fix), curvefitoptions );
a = interlace( a0, a_free, fix );
My testing of this is limited to the following code:
%% A function
myfun = @(x, xdata) x(1) + x(2)*xdata + x(3)./xdata;
%% Some Data
x = [0.036;0.14;0.42;0.49;0.66;0.68;0.76;0.79;0.8;0.85;0.92;0.93;0.96];
y = [0.83;1;0.66;0.53;0.58;0.6;0.64;0.62;0.62;0.55;0.41;0.39;0.33];
%% Initial conditions
a0 = [1; 2; 3];
%% Bounds
lb = [-1; -2; -3];
ub = [0.1; 0.2; 0.3];
%% Fitting options
curvefitoptions = optimset( 'Display', 'iter' );
%% Fit all three parameters
a = lsqcurvefit( myfun, a0, x, y, lb, ub, curvefitoptions )
%% Fix some parameters
fix = [1; 0; 1];
a_free = lsqcurvefit( @(x, xdata) myfun( interlace( a0, x, fix ), xdata), ...
a0(~fix), x, y, lb(~fix), ub(~fix), curvefitoptions );
a = interlace( a0, a_free, fix );