简体   繁体   English

Python LMFIT限制适合参数

[英]Python LMFIT restriction fit parameters

I'm trying to fit a function to some data in Python using the LMFIT library for nonlinear functions. 我正在尝试使用针对非线性函数的LMFIT库使函数适合Python中的某些数据。 It's easy enough, but I want to know if there's a way to restrict some properties of the fitted values. 这很容易,但是我想知道是否有办法限制拟合值的某些属性。

For example, in the following code I fit my data to optimize values A, B and C. But I also want the ratio of A to B to be pi/4 times some integer. 例如,在下面的代码中,我适合我的数据以优化值A,B和C。但是我还希望A与B的比率为pi / 4某个整数的倍。 Is there a way to impose this restriction? 有没有办法施加这种限制?

from lmfit import  Model
import numpy
from numpy import cos, sin, pi, linspace

Upload data: 上传数据:

data = numpy.genfromtxt('data')
axis = numpy.genfromtxt('axis')

Define function: 定义功能:

def func(x, A, B, C):
return (A*cos(x)*cos(x) + B*sin(x)*sin(x) + 2*C*sin(x)*cos(x))**2

I must make an initial guess for my parameters: 我必须对我的参数进行初步猜测:

a = 0.009 
b = 0.3 
c = 0.3 

Then create a model to fit my function: 然后创建一个适合我功能的模型:

func_model = Model(func)

Fit the function to input data, with initial guesses (A = a, B = b, C = c): 使用初始猜测值将函数拟合为输入数据(A = a,B = b,C = c):

result = func_model.fit(data, x=axis, A = a, B = b, C = c) 
fitted_vals = result.best_values #dictionary structure
Afit = fitted_vals['A']
Bfit = fitted_vals['B']
Cfit = fitted_vals['C']

How can I make sure that the ratio of Afit to Bfit is pi/4 times some integer? 如何确定Afit与Bfit的比率是某个整数的pi / 4倍?

If it's not possible, is anyone aware of software that has this capability? 如果不可能,是否有人知道具有此功能的软件?

The problem with the standard fit is the estimate of the Jacobian. 标准拟合的问题是雅可比估计。 If a parameter is discrete the derivative is zero almost everywhere. 如果参数是离散的,则几乎在任何地方导数均为零。 A workaround might be that one uses leastsq with a self defined residual function and additionally providing the derivatives. 一种解决方法可能是使用带有自定义残差函数的leastsq并另外提供导数。 One can set the parameter discrete in the residual function but let it be continuous in the derivative. 可以在残差函数中设置参数离散,但在导数中使其连续。 I'm not saying that this is the general solution to this type of problem, but in case of the OP's function, it works quite OK. 我并不是说这是解决此类问题的常规方法,但是在使用OP功能的情况下,它的工作效果还不错。

Edit - Code would be: 编辑-代码为:

# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import leastsq

def f0( x, A, B, C ):
    return ( A * np.cos( x )**2 + B * np.sin( x )**2 + 2 * C * np.sin( x ) * np.cos( x ) )

def func(x, A, B, C):
    return f0( x, A, B, C )**2

a = 0.009
b = 0.3
c = 0.4

xList = np.linspace( -1, 6, 500 )
yList = np.fromiter( ( func( x, a, b, c ) for x in xList ), np.float )


def residuals( p, x, y ):
    return func(x, p[0], int(p[1]) * np.pi / 2. * p[0], p[2] ) - y

def dfunc( p, x, y ):     #Derivative
    return [ 
        f0( x, p[0], int( p[1] ) * np.pi / 2. * p[0] , p[2] ) * ( np.cos( x )**2 + p[1] * np.pi / 2. * np.sin( x )**2 ),
        f0( x, p[0], int( p[1] ) * np.pi / 2. * p[0] , p[2] ) * ( p[0] * np.pi / 2.* np.sin( x )**2 ),
        f0( x, p[0], int( p[1] ) * np.pi / 2. * p[0] , p[2] ) * ( 2 * np.sin( x ) * np.cos( x ) ),
     ]

plsq, cov, infodict, mesg, ier = leastsq( residuals, [ 0.009, .3/.01, .4 ], args=( xList, yList ), Dfun=dfunc, col_deriv=1, full_output=True )

fit = func(xList, plsq[0], int( plsq[1] ) * np.pi / 2. * plsq[0],  plsq[2] )
print plsq
print int( plsq[1] ) 
fig1 = plt.figure( 1, figsize=( 6, 4 ), dpi=80 )
ax = fig1.add_subplot( 1, 1, 1 )
ax.plot( xList, yList )
ax.plot( xList, fit, ls='--')
plt.show()

Providing: 提供:

>>[8.68421935e-03 2.22248626e+01 4.00032135e-01]
>>22

数据和拟合

我认为答案是否定的。scipy.optimize中的求解器优化lmfit换行不支持离散变量,仅支持连续变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM