user1975135
user1975135

Reputation: 1

Python fit with normalized parameters

If I define fitting function as:

def func(a1,a2,a3,a4):
    return a1*y1+a2*y2+a3*y3+a4*y4

and when i fit I want to tie my parameters:

a1**2+a2**2+a3**2+a4**2=1

I cannot find the way to do that with scipy.optimize or lmfit module.

Do you have any suggestion?

Thanks!

Upvotes: 0

Views: 429

Answers (1)

M Newville
M Newville

Reputation: 7862

Just to be clear, your func() is not actually how you write a fitting function for scipy optimize or lmfit. You have given very little context for your problem, which limits how much help can be given.

But, for constraining parameter values, the key is to recognize that there are actually three variable parameters and one parameter whose value is derived from the others, say a1, a2, and a3 vary and a4 is defined as

a4 = sqrt(1 - a1**2 - a2**2 - a3**2)

This can be done easily with lmfit (see docs and examples for more details):

from lmfit import Model, Parameters

def func(y1, y2, y3, y4, a1, a2, a3, a4):
    return  y1*a1**2 + y2*a2**2 + y3*a3**2 + y4*a4**2 

model = Model(func, independent_vars=['y1', 'y2', 'y3', 'y4'])

params = Parameters()
params.add('a1', value=0.5, vary=True)
params.add('a2', value=0.5, vary=True)
params.add('a3', value=0.5, vary=True)
params.add('a4', expr='sqrt(1 - (a1**2 + a2**2 + a3**2))')

result = model.fit(params, ydata, y1=y1, y2=y2, y3=y3, y4=y4)

Of course, you may have to look out for (a1**2 + a2**2 + a3**2) exceeding 1.0. You could, for example, place bounds on the values for parameters a1, etc.

Upvotes: 1

Related Questions