簡體   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