parameter control in scipy.optimize.leastsq
![](https://secure.gravatar.com/avatar/979f65d31f6a47df4a2762bfdd04a989.jpg?s=120&d=mm&r=g)
Hello, I have been using scipy for about one and a half years now and have been extremely pleased. In this time I have made extensive use of scipy.optimize.leastsq. While I am generally fairly happy with its performance, I think it does lacks one important feature which I am used to from similar routines in other languages. (Please excuse if I have just missed that feature so far.) I would like to be able to control which parameters actually are fitted. For example I would like to be able to do leastsq( redsiduals, p0, args=(y), fit=([True,True,False,True]) ) where the parameter "fit" would tell leastsq to leave the parameter p0[2] untouched while fitting the others. Right now I have to modify my source code to change the parameters which are actually fit. I'd be happy to participate and start getting my hands dirty if someone would point out where to start. Regards, Maximilian
![](https://secure.gravatar.com/avatar/ac4e2152839c56c5326cd95ae54296e9.jpg?s=120&d=mm&r=g)
On Sun, Oct 19, 2008 at 10:37 AM, Maximilian Fabricius <mxhf@gmx.net> wrote:
Hello,
I have been using scipy for about one and a half years now and have been extremely pleased.
In this time I have made extensive use of scipy.optimize.leastsq. While I am generally fairly happy with its performance, I think it does lacks one important feature which I am used to from similar routines in other languages. (Please excuse if I have just missed that feature so far.)
I would like to be able to control which parameters actually are fitted. For example I would like to be able to do
leastsq( redsiduals, p0, args=(y), fit=([True,True,False,True]) )
where the parameter "fit" would tell leastsq to leave the parameter p0[2] untouched while fitting the others.
I think you can do this by 'wrapping' your existing function: Something like: fit_function = lambda x, fixed: residuals(x[0],x[1],fixed[0],x[2]) Then you can call least squared with the fixed argument specified leastsq( fit_function, p0, args=(y,fixed)) You can either have the fixed parameters passed as a argument to the lambda, or have them defined where the lambda is run (but I find it a bit confusiong becuase the scoping gets funny). I'm sure you could do something to get the [True, False] type notation you want - but since you will have to specify the fixed values as well. Robin
![](https://secure.gravatar.com/avatar/979f65d31f6a47df4a2762bfdd04a989.jpg?s=120&d=mm&r=g)
On Sun, Oct 19, 2008 at 12:06 PM, Robin <robince@gmail.com> wrote:
On Sun, Oct 19, 2008 at 10:37 AM, Maximilian Fabricius <mxhf@gmx.net> wrote:
Hello,
I have been using scipy for about one and a half years now and have been extremely pleased.
In this time I have made extensive use of scipy.optimize.leastsq. While I am generally fairly happy with its performance, I think it does lacks one important feature which I am used to from similar routines in other languages. (Please excuse if I have just missed that feature so far.)
I would like to be able to control which parameters actually are fitted. For example I would like to be able to do
leastsq( redsiduals, p0, args=(y), fit=([True,True,False,True]) )
where the parameter "fit" would tell leastsq to leave the parameter p0[2] untouched while fitting the others.
I think you can do this by 'wrapping' your existing function:
Something like:
fit_function = lambda x, fixed: residuals(x[0],x[1],fixed[0],x[2])
Then you can call least squared with the fixed argument specified leastsq( fit_function, p0, args=(y,fixed))
You can either have the fixed parameters passed as a argument to the lambda, or have them defined where the lambda is run (but I find it a bit confusiong becuase the scoping gets funny). I'm sure you could do something to get the [True, False] type notation you want - but since you will have to specify the fixed values as well.
Robin _______________________________________________ Scipy-dev mailing list Scipy-dev@scipy.org http://projects.scipy.org/mailman/listinfo/scipy-dev
Robin, thank you for the quick reply. Indeed, but this would still involve to swap parameters around between fixed and non-fixed and changing the lambda function manually rather then just switching the fissint on and off with a single variable. But no doubt, a wrapper can be done. Thanks! Maximilian
![](https://secure.gravatar.com/avatar/ac4e2152839c56c5326cd95ae54296e9.jpg?s=120&d=mm&r=g)
On Sun, Oct 19, 2008 at 11:28 AM, Maximilian Fabricius <mxhf@gmx.net> wrote:
Robin,
thank you for the quick reply. Indeed, but this would still involve to swap parameters around between fixed and non-fixed and changing the lambda function manually rather then just switching the fissint on and off with a single variable.
But no doubt, a wrapper can be done.
I couldn't think of a way to squeeze it into a lamdba single statement, but something like this would do: def fit_function(x, fit, y): p0 = zeros(fit.size) p0[fit] = x p0[~fit] = y where fit is a boolean array, x is the ones to optimised and y are the fixed values. You have the extra overhead of the p0 array allocation for every iteration of the function - but perhaps that is worth it for the convenience. Robin
![](https://secure.gravatar.com/avatar/979f65d31f6a47df4a2762bfdd04a989.jpg?s=120&d=mm&r=g)
On Sun, Oct 19, 2008 at 12:52 PM, Robin <robince@gmail.com> wrote:
On Sun, Oct 19, 2008 at 11:28 AM, Maximilian Fabricius <mxhf@gmx.net> wrote:
Robin,
thank you for the quick reply. Indeed, but this would still involve to swap parameters around between fixed and non-fixed and changing the lambda function manually rather then just switching the fissint on and off with a single variable.
But no doubt, a wrapper can be done.
I couldn't think of a way to squeeze it into a lamdba single statement, but something like this would do:
def fit_function(x, fit, y): p0 = zeros(fit.size) p0[fit] = x p0[~fit] = y
where fit is a boolean array, x is the ones to optimised and y are the fixed values. You have the extra overhead of the p0 array allocation for every iteration of the function - but perhaps that is worth it for the convenience.
Robin _______________________________________________ Scipy-dev mailing list Scipy-dev@scipy.org http://projects.scipy.org/mailman/listinfo/scipy-dev
Robin, great, nice idea! As this may be of use to others, my solution now is: def fit_function(p_fit, fit, p_fixed, ... ): # assemble p_fit and p_fixed into a single array # while restoring the correct order of the original p0 array. p = zeros(fit.size) p[ where(fit == True) ] = p_fit p[ where(fit == False) ] = p_fixed # calls the original residuals routine return residuals(p, ... ) main(): # best guesses p0 = zeros(10) p0[0] = vrot_d p0[1] = vsig_d .... # choose which parameters to fit fit = zeros(len(p0)) fit[0:7] = True fit[8] = False fit[9] = False # store parameters which should be fit in p_fit # all the others in p_fixed p_fit = p0[ where(fit == True) ] p_fixed = p0[ where(fit == False) ] plsq = leastsq(fit_function, p_fit, args=(fit, p_fixed, ...) ) Thanks! Cheers, Maximilian
![](https://secure.gravatar.com/avatar/ac4e2152839c56c5326cd95ae54296e9.jpg?s=120&d=mm&r=g)
On Sun, Oct 19, 2008 at 4:28 PM, Maximilian Fabricius <mxhf@gmx.net> wrote:
Robin,
great, nice idea! As this may be of use to others, my solution now is:
def fit_function(p_fit, fit, p_fixed, ... ): # assemble p_fit and p_fixed into a single array # while restoring the correct order of the original p0 array. p = zeros(fit.size) p[ where(fit == True) ] = p_fit p[ where(fit == False) ] = p_fixed # calls the original residuals routine return residuals(p, ... )
main(): # best guesses p0 = zeros(10) p0[0] = vrot_d p0[1] = vsig_d ....
# choose which parameters to fit fit = zeros(len(p0)) fit[0:7] = True fit[8] = False fit[9] = False
# store parameters which should be fit in p_fit # all the others in p_fixed p_fit = p0[ where(fit == True) ] p_fixed = p0[ where(fit == False) ] plsq = leastsq(fit_function, p_fit, args=(fit, p_fixed, ...) )
Thanks!
Just want to point out that if fit is a boolean array (ie fit = array([True,False,False,True]) etc. then you can index with it directly p0[fit] instead of p0[where(fit==True)] and p0[~fit] instead of p0[where(fit==False)] which is likely to be a bit quicker. Doesn't matter outside, but in the fit_function you probably want to save any time you can since it will be run many times. Robin
![](https://secure.gravatar.com/avatar/979f65d31f6a47df4a2762bfdd04a989.jpg?s=120&d=mm&r=g)
On Sun, Oct 19, 2008 at 5:40 PM, Robin <robince@gmail.com> wrote:
On Sun, Oct 19, 2008 at 4:28 PM, Maximilian Fabricius <mxhf@gmx.net> wrote:
Robin,
great, nice idea! As this may be of use to others, my solution now is:
def fit_function(p_fit, fit, p_fixed, ... ): # assemble p_fit and p_fixed into a single array # while restoring the correct order of the original p0 array. p = zeros(fit.size) p[ where(fit == True) ] = p_fit p[ where(fit == False) ] = p_fixed # calls the original residuals routine return residuals(p, ... )
main(): # best guesses p0 = zeros(10) p0[0] = vrot_d p0[1] = vsig_d ....
# choose which parameters to fit fit = zeros(len(p0)) fit[0:7] = True fit[8] = False fit[9] = False
# store parameters which should be fit in p_fit # all the others in p_fixed p_fit = p0[ where(fit == True) ] p_fixed = p0[ where(fit == False) ] plsq = leastsq(fit_function, p_fit, args=(fit, p_fixed, ...) )
Thanks!
Just want to point out that if fit is a boolean array (ie fit = array([True,False,False,True]) etc. then you can index with it directly p0[fit] instead of p0[where(fit==True)] and p0[~fit] instead of p0[where(fit==False)] which is likely to be a bit quicker. Doesn't matter outside, but in the fit_function you probably want to save any time you can since it will be run many times.
Robin
Robin, thank you. Indeed, I should know that. Python sometime is overwhelmingly convenient. Maximilian
![](https://secure.gravatar.com/avatar/8fcc78062e4d78f014ed64d55c8c434e.jpg?s=120&d=mm&r=g)
To avoid array creation overhead, I use objects encapsulating everything, so def fit_function(self, x, ... ): # x is a subset of all the parameters, self.tofit is bool array with those arg to fit self.p[self.tofit ][:] = x[:] self.p[~self.tofit][:] = self.all_arg [~self.tofit][:] # calls the original residuals routine return residuals(self.p, ... ) Then in your loop, you can change the self.tofit array to change what you fit. Obviously, self.all_arg default to something in the __init__() method and self.p is created once there, and things can be changed. If things are slow, the line self.p[~self.tofit][:] = self.all_arg [~self.tofit][:] can be removed and put into it's own method, only to be called if self.tofit changes. Benny 2008/10/19 Maximilian Fabricius <mxhf@gmx.net>
On Sun, Oct 19, 2008 at 12:52 PM, Robin <robince@gmail.com> wrote:
On Sun, Oct 19, 2008 at 11:28 AM, Maximilian Fabricius <mxhf@gmx.net> wrote:
Robin,
thank you for the quick reply. Indeed, but this would still involve to swap parameters around between fixed and non-fixed and changing the lambda function manually rather then just switching the fissint on and off with a single variable.
But no doubt, a wrapper can be done.
I couldn't think of a way to squeeze it into a lamdba single statement, but something like this would do:
def fit_function(x, fit, y): p0 = zeros(fit.size) p0[fit] = x p0[~fit] = y
where fit is a boolean array, x is the ones to optimised and y are the fixed values. You have the extra overhead of the p0 array allocation for every iteration of the function - but perhaps that is worth it for the convenience.
Robin _______________________________________________ Scipy-dev mailing list Scipy-dev@scipy.org http://projects.scipy.org/mailman/listinfo/scipy-dev
Robin,
great, nice idea! As this may be of use to others, my solution now is:
def fit_function(p_fit, fit, p_fixed, ... ): # assemble p_fit and p_fixed into a single array # while restoring the correct order of the original p0 array. p = zeros(fit.size) p[ where(fit == True) ] = p_fit p[ where(fit == False) ] = p_fixed # calls the original residuals routine return residuals(p, ... )
main(): # best guesses p0 = zeros(10) p0[0] = vrot_d p0[1] = vsig_d ....
# choose which parameters to fit fit = zeros(len(p0)) fit[0:7] = True fit[8] = False fit[9] = False
# store parameters which should be fit in p_fit # all the others in p_fixed p_fit = p0[ where(fit == True) ] p_fixed = p0[ where(fit == False) ] plsq = leastsq(fit_function, p_fit, args=(fit, p_fixed, ...) )
Thanks!
Cheers,
Maximilian _______________________________________________ Scipy-dev mailing list Scipy-dev@scipy.org http://projects.scipy.org/mailman/listinfo/scipy-dev
participants (3)
-
Benny Malengier
-
Maximilian Fabricius
-
Robin