繁体   English   中英

在scipy函数curve_fit中使用未确定数量的参数

[英]using undetermined number of parameters in scipy function curve_fit

第一个问题:我正在尝试使用以下形式的函数来拟合实验数据:

f(x) = m_o*(1-exp(-t_o*x)) + ... + m_j*(1-exp(-t_j*x))

目前,我没有找到一种方法来获得不确定数量的参数m_j,t_j,我被迫做这样的事情:

def fitting_function(x, m_1, t_1, m_2, t_2):
    return m_1*(1.-numpy.exp(-t_1*x)) + m_2*(1.-numpy.exp(-t_2*x)) 

parameters, covariance = curve_fit(fitting_function, xExp, yExp, maxfev = 100000)

(xExp和yExp是我的实验点)

有没有办法写这样的拟合函数:

def fitting_function(x, li):
    res = 0.
    for el in range(len(li) / 2):
        res += li[2*idx]*(1-numpy.exp(-li[2*idx+1]*x))
    return res

其中li是拟合参数列表,然后执行curve_fitting? 我不知道怎么告诉curve_fitting什么是拟合参数的数量。 当我为fitting_function尝试这种形式时,我遇到了类似“ValueError:无法确定拟合参数的数量”的错误。

第二个问题:有没有办法强制我的拟合参数是积极的?

任何帮助赞赏:)

在这里查看我的问题和答案。 我还做了一个最小的工作示例,演示了如何为您的应用程序完成它。 我没有声称这是最好的方式 - 我自己也在混淆所有这些,所以任何批评或简化都会受到赞赏。

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as pl

def wrapper(x, *args): #take a list of arguments and break it down into two lists for the fit function to understand
    N = len(args)/2
    amplitudes = list(args[0:N])
    timeconstants = list(args[N:2*N])
    return fit_func(x, amplitudes, timeconstants)


def fit_func(x, amplitudes, timeconstants): #the actual fit function
    fit = np.zeros(len(x))
    for m,t in zip(amplitudes, timeconstants):
        fit += m*(1.0-np.exp(-t*x))
    return fit

def gen_data(x, amplitudes, timeconstants, noise=0.1): #generate some fake data
    y = np.zeros(len(x))
    for m,t in zip(amplitudes, timeconstants):
        y += m*(1.0-np.exp(-t*x))
    if noise:
        y += np.random.normal(0, noise, size=len(x))
    return y


def main():
    x = np.arange(0,100)
    amplitudes = [1, 2, 3]
    timeconstants = [0.5, 0.2, 0.1]
    y = gen_data(x, amplitudes, timeconstants, noise=0.01)

    p0 = [1, 2, 3, 0.5, 0.2, 0.1]
    popt, pcov = curve_fit(lambda x, *p0: wrapper(x, *p0), x, y, p0=p0) #call with lambda function
    yfit = gen_data(x, popt[0:3], popt[3:6], noise=0)
    pl.plot(x,y,x,yfit)
    pl.show()
    print popt
    print pcov

if __name__=="__main__":
    main()

但是有一个警告的话。 指数的线性和将使得拟合对任何噪声都非常敏感,特别是对于大量参数。 您可以通过向脚本中生成的数据添加甚至少量的噪声来测试 - 即使是小的偏差也会导致它完全得到错误的答案,而拟合仍然看起来完全有效(通过噪声= 0,0.01和0.1)。 即使合身看起来很好,也要非常小心地解释你的结果。 它也是一个允许变量交换的形式:即使你将任何一对(m_i,t_i)与(m_j,t_j)交换,最合适的解决方案也是一样的,这意味着你的卡方有多个相同的局部最小值可能意味着你的在拟合期间,变量会被交换,具体取决于您的初始条件。 这不太可能是提取这些参数的一种非常可靠的方法。

对于你的第二个问题,是的,你可以通过定义你的指数来这样:

m_0**2*(1.0-np.exp(-t_0**2*x)+...

基本上,将它们全部放在您的实际拟合函数中,使它们适合它们,然后将结果平方(可能是负数或正数)以获得实际参数。 您还可以使用不同的代理表单将变量定义在特定范围之间。

暂无
暂无

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

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