簡體   English   中英

如何在Python curve_fit中返回擬合錯誤

[英]How to return the fit error in Python curve_fit

我正在嘗試使用python使函數適合實驗的數據集。 我可以得到一個非常好的近似值,擬合度看起來也不錯,但是給定的參數誤差非常高,我不確定如何解決。

該函數如下所示: Function

數據由時間數據集和ay數據集組成。 變量“ ve”是線性速度函數,因此在代碼中將其替換為“ a * x + b”。 現在,擬合看起來確實不錯,並且理論上該函數應該可以擬合數據,但是誤差非常高。 代碼如下:

import operator
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from lmfit import Model
from numpy import log, linspace, random
from matplotlib import colors as mcolors
from scipy.optimize import curve_fit

data6 = pd.read_csv('2594.csv')
x=data6.iloc[:18,0]
y=data6.iloc[:18,1]

def func(x, a, b, mo, q):
    return (4.9+a*x+b)*x+(a*x+b)*((mo/q)-x)*log(1-(q*x)/mo)-0.5*9.8*x*x

popt, pcov = curve_fit(func,x,y,bounds=((0, -100, 0, 0), (1000, 1000, 1, 1)))
plt.plot(x, func(x, *popt), 'g--', label='fit: a=%5.3f, b=%5.3f, mo=%5.3f, 
q=%5.3f' % tuple(popt))
plt.plot(x,y,':', label='Daten')
plt.grid(True)
plt.legend(loc='upper left')
plt.xlabel("t [s]")
plt.ylabel("z [m]")
plt.title('Anpassung vor Zeitpunkt T', )
plt.savefig('fit1.pdf')
plt.show()

這是此代碼行的合適位置: Fit1

和協方差矩陣:

[[ 3.66248820e+09  2.88800781e+09 -5.59803683e+06 -4.01121935e+05]
 [ 2.88800781e+09  2.27731332e+09 -4.44058731e+06 -3.17108449e+05]
 [-5.59803683e+06 -4.44058731e+06  2.43805434e+05  7.83731345e+03]
 [-4.01121935e+05 -3.17108449e+05  7.83731345e+03  2.65778118e+02]]

我還嘗試了以下擬合模式,但出現了1400%以上的錯誤:

fmodel = Model(func)
result = fmodel.fit(y, x=x, a=14, b=3.9, mo=0.8, q=0.002)

這是適合的報告:

a:   926.607518 +/- 182751.047 (19722.59%) (init = 14)
b:   737.755741 +/- 143994.520 (19517.91%) (init = 3.9)
mo:  0.27745681 +/- 27.5360933 (9924.46%) (init = 0.8)
q:   0.00447098 +/- 0.60437392 (13517.72%) (init = 0.002)

這就是適合的結果: Fit2非常感謝您的幫助。 如果可能的話,提供有關如何最大程度地減少功能錯誤的簡單指南!

數據如下所示:

x=[0.0333 0.0667 0.1    0.133  0.167  0.2    0.233  0.267  0.3    0.333  
   0.367  0.4    0.433  0.467  0.5    0.533  0.567  0.6   ]
y=[0.104 0.249 0.422 0.6   0.791 1.    1.23  1.47  1.74  2.02  2.33  2.64
   2.99  3.34  3.71  4.08  4.47  4.85 ]

謝謝!

如果您已從lmfit打印出完全擬合報告(或從lmfit正確解開了協方差矩陣的curve_fit ),您會看到參數ab是100%相關的。

基本上,這是一種擬合算法,它告訴您模型無法很好地描述您的數據,並且您不需要那么多參數(或也許這些參數和模型)來描述數據。

確實,如果您繪制數據,則會有輕微的上升。 您的功能是三個不同術語的總和:

   (4.9+a*x+b)*x
 + (a*x+b)*((mo/q)-x)*log(1-x/(mo/q)) 
 - 0.5*9.8*x*x

有幾件事要注意:

  1. moq僅一起出現,並且為mo/q 他們不會獨立。
  2. ab僅一起出現,並且以相同的形式出現在多個位置
  3. x有2個純二次項,其中之一是硬連線的。
  4. 對數項也具有二次因子。 重要的是, x數據的變化幅度不超過1個數量級,因此對數項的變化不會太大, 主要是第三個二次項。 (順便說log(1-x*a) :如果您要記錄日志,則應確保該參數實際上是正log(1-x*a)正在引起麻煩)

總結一下:模型對於數據來說太復雜了。

我非常懷疑您是否需要登錄術語。 事實證明,您可以使用簡單的拋物線模型很好地擬合它:

import numpy as np
import matplotlib.pyplot as plt
from lmfit.models import ParabolicModel

x = np.array([0.0333, 0.0667, 0.1, 0.133, 0.167, 0.2, 0.233 , 0.267, 0.3 ,
          0.333, 0.367, 0.4, 0.433, 0.467, 0.5, 0.533 , 0.567 , 0.6 ])

y = np.array([0.104, 0.249 , 0.422, 0.6, 0.791, 1.0, 1.23, 1.47, 1.74,
          2.02, 2.33, 2.64, 2.99, 3.34, 3.71, 4.08, 4.47, 4.85 ])

qmodel = ParabolicModel()
result = qmodel.fit(y, x=x, a=1, b=2, c=0)
print(result.fit_report())
fitlabel = "fit: a=%5.3f, b=%5.3f, c=%5.3f" % (result.params['a'].value,
                                               result.params['b'].value,
                                               result.params['c'].value)
plt.plot(x, y, label='Daten')
plt.plot(x, result.best_fit, label=fitlabel)
plt.xlabel("t [s]")
plt.ylabel("z [m]")
plt.legend(loc='upper left')
plt.title("Anpassung vor Zeitpunkt T (Model: a*x^2+b*x+c)")
plt.show()

這將給出一個報告

[[Model]]
    Model(parabolic)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 9
    # data points      = 18
    # variables        = 3
    chi-square         = 0.00298906
    reduced chi-square = 1.9927e-04
    Akaike info crit   = -150.657052
    Bayesian info crit = -147.985936
[[Variables]]
    c: -0.02973853 +/- 0.01120090 (37.66%) (init = 0)
    b:  3.67707491 +/- 0.08142567 (2.21%) (init = 2)
    a:  7.51540814 +/- 0.12492370 (1.66%) (init = 1)
[[Correlations]] (unreported correlations are < 0.100)
    C(b, a) = -0.972
    C(c, b) = -0.891
    C(c, a) =  0.785

和一個情節 在此處輸入圖片說明

數據和公式來自物理實驗,因此我不得不使用該函數。 我可以確定mo的實際值,還必須考慮不同變量的含義。 首先,公式“ vo”和“ ve”必須相等,這是因為數據在加速一段時間后“開始”,並且還因為在原始擬合中,“ ve”被假定為線性函數,但實際上應為線性函數。恆定速度。 這就是為什么在下面的代碼vo + ve = ve中。 剩下的擬合函數帶有兩個參數,可以輕松確定並且誤差很小。

def func(x, ve, q):
    return (2*ve*x) + ve*((0.65/q) - x)*log(1 - (q*x)/0.65) - 0.5*9.8*x*x

popt, pcov = curve_fit(func,x,y,bounds=((-100, 0), (1500, 1.5)))
plt.plot(x, func(x, *popt), color='orange', label='Anpassung: $v_e$=%5.3f, q=%5.3f' % 
tuple(popt))
plt.plot(x,y,':', label='Daten')

print(pcov)

plt.grid(True)
plt.legend(loc='upper left')
plt.xlabel("t [s]")
plt.ylabel("z [m]")
plt.title('Anpassung vor Zeitpunkt T', )
plt.savefig('anpass.pdf')
plt.savefig('anpass.png')
plt.show()

給出協方差矩陣:

[[ 0.01807039 -0.00305967]
 [-0.00305967  0.00065509]]

和適合:

擬合功能

該函數的實際值。

感謝您的幫助,我希望這篇文章對某天某人有用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM