Viktor Viktor - 8 months ago 41
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