Fix parameters using fit function

Hi all,
This may be a dumb and easy question, but I'm having problems in understanding how to fix parametersin a multiparameter fit function. Going straight to the problem, i have a function which fits a 2D user inputted gaussian as follows:
function [gof,fittato] = fit_gaub(image,error,init)
a = init(1);
b = init(2);
c1 = init(3);
c2 = init(4);
t1 = init(5);
w1 = init(6);
w2 = init(7);
gaub = @(a,b,c1,c2,t1,w1,w2,x,y) a + b.*exp(-(((x-c1).*cosd(t1)+(y-c2).*sind(t1))/w1).^2-((-(x-c1).*sind(t1)+(y-c2).*cosd(t1))/w2).^2)./(pi.*w1.*w2);
lunghezza = numel(image);
z_vect = zeros(lunghezza,1);
k = 1;
for i=1:size(image,2)
for j=1:size(image,1)
r_fit(k) = j;
c_fit(k) = i;
z_vect(k) = image(j,i);
k = k+1;
end
end
weight(1:lunghezza)=error;
% a,b,c1,c2,t1,w1,w2
[fittato, gof] = fit([r_fit', c_fit'], z_vect,gaub,'Robust', 'Bisquare','Algorithm','Trust-Region','weights',weight...
,'StartPoint', init ...
,'Lower', [ -10 0 0 0 0 1 1 ]...
,'Upper', [ 100 10e12 200 50 15 100 100]);
In the framework of this function, how can I tell matlab to fix a parameter without playing with the contranints? I've found something about it only concerning the
lsqcurvefit
function, but I have no idea neither on how to use that function, nor what changes may that bring to my code(get same output from my function).
any help would be much appreciated,
Andrea Calvi

 Accepted Answer

jgg
jgg on 17 Dec 2015
Edited: jgg on 17 Dec 2015
I think I understand what you're trying to do. Your function is this thing:
gaub = @(a,b,c1,c2,t1,w1,w2,x,y) ...%bunch of function stuff
What you'd like to do is, say, fix b to be a particular value, say b = 3 then optimize your function, but you don't want to do this by saying 3< = b <= 3 in the constraints.
The simplest solution is to just refine your function and constaints:
b = 3;
gaub2 = @(a,c1,c2,t1,w1,w2,x,y) gaub(a,b,c1,c2,t1,w1,w2,x,y);
%now gaub2 is gaub, with b fixed at the value set.
Now, you just need to get rid of the b constraint, so in your optimization, set:
'Lower', [ -10 0 0 0 1 1 ]...
'Upper', [ 100 200 50 15 100 100]
by omitting the column of constraints associated with b. You can fiddle with this to be a little more robust, but I think this is the most straightforward way. (For example, to do it for all of your variables, you can set up a switch statement and have seven possible functions).

More Answers (2)

gabodabo
gabodabo on 19 May 2019
Edited: gabodabo on 19 May 2019
I am nearly 4y late for the discussion, but a very simple way of fixing parameters in the 'fit' function is to put your value in the upper and lower limits. For example, for a fit to a function with four parameters, of which two are fixed:
opts.Lower = [ param1_fix param2_fix -Inf -Inf ];
opts.Upper = [ param1_fix param2_fix Inf Inf ];
[fitresult, gof] = fit( xData, yData, myfunc, opts);
Hope this helps!
Gabriel
Andrea Calvi
Andrea Calvi on 18 Dec 2015
Hi,
Thanks for your answer. Indeed that's exactly what I'm trying to do. Your approach is by far the simplest, and I'll apply it for sure, but now I encounter another problem. IS there an intelligent way to do this without taking a switch loop of 20 and more possibilities? I mean, suppose I also want, to fix more than one parameter at a time.
I'll try to sort this thing out and post any progress in that sense.

4 Comments

This is a good question. Since I do this occasionally, I figured out a way to do this relatively nicely.
test = @(x)(normcdf(x(1),x(2),x(3))); %the function (just an example)
k = 3; %number of variables in gaub
places = [2,3];
values = [1.5,2.5];
places_count = 1;
y_str = '';
for i = 1:k %k is number of variables
if ismember(i,places)
y_str = strcat(y_str,num2str(values(places_count)));
places_count = places_count + 1;
else
y_str = strcat(y_str,'y(',num2str(i),')');
end
if i < k
y_str = strcat(y_str,',');
end
end
gaub_str = strcat('@(y)([',y_str,'])');
gaub2 = str2func(gaub_str);
gaub3 = @(x)(test(gaub2(x)));
gaub3(0.21)
normcdf(0.21,1.5,2.5)
Basically, the idea is to create the anonymous function dynamically using string concatenation. The only trick is that we have to get around a restriction on workspace variables, which is why there are now 3 of these functions floating around.
Thanks! This week-end I ended up with something definetly similar. Mine is just a little uglier, but it works just as fine :D
I'll share it too, so if anyone needs something like this he'll have more than one possibility
gaus = {'a','+','b','.*exp(-(((x-','c1',').*cosd(','t1',')+(y-','c2',').*sind(','t1','))/','w1',').^2-((-(x-','c1',').*sind(','t1',')+(y-','c2',').*cosd(','t1','))/','w2',').^2)./(pi.*','w1','.*','w2',')'};
minni = [-10 0 0 0 -15 1 1];
maxxi = [100 10e12 200 50 15 100 100];
funcpar = ['@('];
ll = 0;
for a=1:length(minni)
if strcmp(param(a,4),'Fixed')
for r=1:length(gaus)
if strcmp(gaus{r},param(a,2))
gaus{r} = num2str(cell2mat(param(a,3)));
else
end
end
par(a) = param(a,3);
else
ll = ll + 1;
low(ll) = minni(a);
up(ll) = maxxi(a);
funcpar = strcat(funcpar,param(a,2),',');
par(a) = param(a,2);
inits(ll) = cell2mat(param(a,3));
end
end
gauss = str2func(char(strcat(funcpar,'x,y)',{' '},cell2mat(gaus))));
In my code the basic ingredient is to write the function as a cell array as I did, separating the parameters of fit from all the other elements of the function. maxxi e minni are the lower and upper bonds for the parameters. In my case moreover I'm inputting everything from a table which has an user inputted decision menu for "fixed"/"free" parameters.
Thanks again jgg :D
Andrea Calvi
Andrea Calvi on 21 Dec 2015
Edited: Andrea Calvi on 21 Dec 2015
p.s. is there a way to un-accept the previous answer and highliting your second one?
I don't think so; it's okay though. People should read through if they want to automate it, so it's all good.

Sign in to comment.

Categories

Asked:

on 17 Dec 2015

Edited:

on 19 May 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!