slhck
slhck

Reputation: 38740

Using multiple independent variables in Python lmfit

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?

Upvotes: 4

Views: 4595

Answers (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)

Upvotes: 4

slhck
slhck

Reputation: 38740

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().

Upvotes: 3

Related Questions