sun0727
sun0727

Reputation: 394

Python LMFIT - Get the wrong result for Minimization, when using bounded parameters

Now, I have trouble using minimize in LMFIT-Module. Please see the case below:

Case 1: Parameter without constraints

import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model, minimize, Parameters, Parameter, report_fit

noise = np.random.randn(100)

def func_model(para, x, data):
    ''' Model: y = a*sin(2*k*pi*x+theta)'''
    a = para['a']
    k = para['k']
    theta = para['theta']
    model= a*np.sin(2*k*np.pi*x+theta)
    return model-data  # thas's what I want to minimize

def func_noise(x, para):
    a, k, theta = para
    return a*np.sin(2*k*np.pi*x+theta) + noise

x_steps = np.linspace(-2*np.pi, 0, 100)
para_true = [10, 0.34, np.pi/6]
datas = func_noise(x_steps, para_true)

params = Parameters()

params.add('a', value=7)
params.add('k', value=0.2)
params.add('theta', value=0)

result = minimize(func_model, params, args=(x_steps, datas))
report_fit(result)

Got the result:

a:      10.0054134 +/- 0.14334401 (1.43%) (init = 7)
k:      0.33954301 +/- 0.00110337 (0.32%) (init = 0.2)
theta:  0.52071533 +/- 0.02546636 (4.89%) (init = 0)

compare to the factual parameters [10, 0.34, pi/6] the results are right.

Case 2: Parameter with constraints

just change to:

params.add('a', value=7, min=5, max=15)    #   should be 10
params.add('k', value=0.2, min=0, max=1)   #   should be 0.34
params.add('theta', value=0)

and keep other code same, then get the wrong result:

a:      14.9999918 +/- 51.0737691 (340.49%) (init = 7)
k:      0.01305462 +/- 0.58283692 (4464.60%) (init = 0.2)
theta: -2.90461833 +/- 10.5723936 (363.99%) (init = 0)

How could it happen?

Upvotes: 0

Views: 475

Answers (1)

M Newville
M Newville

Reputation: 7862

I think the main problem is that k goes to nearly 0 here, which makes it hard for the fitting process to determine the other parameters. When parameters hit their bounds, it can be hard for the algorithm to be able to move away from it. Here it looks like it tries a of ~15, then that pushes k toward zero and it ends up so far away it doesn't know how to get unstuck.

Generally, it's a good idea to set bounds based on physical limitations, or to know how the fit will respond to values near the bounds. That said, I don't really know why this case is so bad.

Upvotes: 1

Related Questions