3

I am trying to fit a model to some data. The independent variables are called A and B, and they are columns in a Pandas DataFrame. I am trying to fit with two parameters against y in the data frame.

Previously, with curve_fit from Scipy, I could do:

def fun(X, p1, p2):
  A, B = X
  return np.exp(p1*A) + p2*B

X = (df['A'].tolist(), df['B'].tolist())
popt, pcov = curve_fit(fun, X, df['y'].tolist())

But now, I'm using lmfit, where I cannot simply "pack" the independent variables like with curve_fit:

def fun(A, B, p1 = 1, p2 = 1):
  return np.exp(p1*A) + p2*B

model = Model(fun, independent_vars=['A', 'B'])

How do I run model.fit() here? The FAQ is not really helpful—what do I have to flatten in the first place?

slhck
  • 36,575
  • 28
  • 148
  • 201

2 Answers2

2

I created a complete, working example with two independent variables:

import pandas as pd
import numpy as np
from lmfit import Model

df = pd.DataFrame({
  'A'      : pd.Series([1, 1, 1, 2, 2, 2, 2]),
  'B'      : pd.Series([5, 4, 6, 6, 5, 6, 5]),
  'target' : pd.Series([87.79, 40.89, 215.30, 238.65, 111.15, 238.65, 111.15])
})

def fun(A, B, p1 = 1, p2 = 1):
  return p1 * np.exp(A) + p2 * np.exp(B)

model = Model(fun, independent_vars=['A', 'B'])
fit = model.fit(df['target'], A = df['A'], B = df['B'])

The trick is to specify all variables as keyword arguments in fit().

slhck
  • 36,575
  • 28
  • 148
  • 201
2

Firstly, creat a model with this function of multiple independent variables. for example,

def random_func(x,y,a,b,c):
    return a*x**3+b*y**2+c

Secondly, specify which ones are the independent variables in the formula. for example,

from lmfit import Model

model = Model(random_func,independent_vars=['x','y'])

Thirdly, set params for the model

for example,

model.set_param_hint('a',value=2)
model.set_param_hint('b',value=3)
model.set_param_hint('c',value=4)

finally, set your x-axis values, as well as y-axis. And do the fit Like this,

x = np.arange(0,2,0.1)
y = np.arange(0,2,0.1)
z = np.loadtxt('filename')

A direct fit actually does not work well. The 2D data array has to be flattened into 1D array, as well as the coordinates. For example, let's leave the model as it is. We need to create new 1D coordinates arrays.

x1d = []
y1d = []
for i in x:
    for j in y:
        x1d = x1d.append(i)
        y1d = y1d.append(j)
z1d = z.flatten_data()
result = model.fit(z1d, x = x1d, y = y1d)
  • That's more or less the same as my answer, but yes, that works. – slhck Jan 31 '19 at 21:00
  • 1
    sorry I am new to python and got lost at your 'panda' package, that I did not read through your code carefully. but with two independent variables, the fitting does not run properly actually... I am trying to narrow down the ranges of all parameters now, hopefully could have a good fitting. – Echt-Drei-sonne-person Feb 02 '19 at 14:48
  • What is the size (or shape) of your z? What if z is already 1D, for example, i have data as in surface z=f(x,y), so my z will have the same size as either x or y. Another comment: seems now is `numpy.ndarray.flatten` , it returns error when i use `flatten_data()`. – tetukowski Jul 05 '23 at 13:19