Viktor Viktor - 2 months ago 12
Python Question

Fitting only 2 paramter of a function with many parameters in python

I know there is a question

Fitting only one paramter of a function with many parameters in python

but I have a little bit different situation. Problem with parameters of lambda function.

I am trying to fit Lorentz func

def lorentz(ph, A, xc, w, f0):
return f0 + A * w**2 / (w**2 + (ph - xc)**2)


if I am fitting only one parameter (xc) its working good.

p1, p2, p3, p4 = params
popt, pcov = curve_fit(lambda x, xc: lorentz(x, p1, xc, p3, p4), abjd, adata, bounds=param_bounds)


But if I try to fit only 2 parameters (a, xc) it fails

p1, p2, p3, p4 = params
popt, pcov = curve_fit(lambda x, a, xc: lorentz(x, a, xc, p3, p4), abjd, adata, bounds=param_bounds)


Error message is

Traceback (most recent call last):
File "template.py", line 294, in <module>
popt, pcov = curve_fit(lambda x, a, xc: lorentz(x, a, xc, p3, p4), abjd, adata, bounds=param_bounds)
File "/usr/local/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 683, in curve_fit
**kwargs)
File "/usr/local/lib/python2.7/dist-packages/scipy/optimize/_lsq/least_squares.py", line 769, in least_squares
f0 = fun_wrapped(x0)
File "/usr/local/lib/python2.7/dist-packages/scipy/optimize/_lsq/least_squares.py", line 764, in fun_wrapped
return np.atleast_1d(fun(x, *args, **kwargs))
File "/usr/local/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 455, in func_wrapped
return func(xdata, *params) - ydata
TypeError: <lambda>() takes exactly 3 arguments (2 given)

Answer

Here is the solution for all 4 parameters of Lorentz function

import numpy as np
from scipy.optimize import curve_fit

def lorentz(ph, A, xc, w, f0):
    return f0 + A * w**2 / (w**2 + (ph - xc)**2)

A, xc, w, f0 = 2,2,2,2  # true values
ph = np.linspace(-5, 10, 100)
y = lorentz(ph, A, xc, w, f0)    
ydata = y + 0.15 * np.random.normal(size=len(ph)) # sample data
popt, pcov = curve_fit(lambda x, _A, _xc: lorentz(x, _A, _xc, w, f0), ph, ydata,bounds=([1,1], [3, 3]))
A, xc = popt # fitted values (only two)

You can easily add or remove parameters by putting them under the function lorentz() or with lambda

The result looks like this enter image description here

Comments