簡體   English   中英

Python:使用 scipy curve_fit 將曲線擬合到屏蔽數據

[英]Python: fitting curve to masked data with scipy curve_fit

我正在嘗試使用 python/numpy/scipy 編寫一個腳本,用於數據操作、擬合和繪制角度相關磁阻測量。 我是 Python 新手,從我的博士導師那里得到了框架代碼,並設法向框架添加了幾百行代碼。 一段時間后,我注意到一些測量有多個錯誤,並且由於腳本應該自動完成所有操作,因此我嘗試屏蔽這些點並將曲線擬合到未屏蔽的點(曲線是疊加在線性函數上的正弦平方,所以 numpy.ma.polyfit 並不是一個真正的選擇)。 然而,在屏蔽了有問題的點的 x 和 y 坐標之后,擬合仍然會考慮它們,即使它們不會顯示在圖中。 這個例子被簡化了,但同樣的事情正在發生;

import numpy.ma as ma
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit



def Funk(x, k, y0):
 return k*x + y0   

fig,ax= plt.subplots()

x=ma.masked_array([1,2,3,4,5,6,7,8,9,10],mask=[0,0,0,0,0,0,1,1,1,1])
y=ma.masked_array([1,2,3,4,5,30,35,40,45,50], mask=[0,0,0,0,0,1,1,1,1,1])


fitParamsFunk, fitCovariancesFunk = curve_fit(Funk, x, y)

ax.plot(x, Funk(x, fitParamsFunk[0], fitParamsFunk[1]))
ax.errorbar(x, y, yerr = None, ms=3, fmt='-o')
plt.show()

點的后半部分被屏蔽且未顯示在圖中,但仍被考慮在內。

在寫這篇文章時,我發現我可以做到這一點:

def Funk(x, k, y0):
    return k*x + y0   

fig,ax= plt.subplots()

x=np.array([1,2,3,4,5,6,7,8,9,10])
y=np.array([1,2,3,4,5,30,35,40,45,50])
mask=np.array([0,0,0,0,0,1,1,1,1,1])

fitParamsFunk, fitCovariancesFunk = curve_fit(Funk, x[mask], y[mask])

ax.plot(x, Funk(x, fitParamsFunk[0], fitParamsFunk[1]))
ax.errorbar(x, y, yerr = None, ms=3, fmt='-o')
plt.show()

我真正想要的

我猜 scipy curve_fit 並不是為了處理掩碼數組,但我仍然想知道是否有任何解決方法(我需要使用掩碼數組,因為數據點的數量 > 10e6,但我'我一次只繪制 100,所以我需要獲取我想要繪制的數組部分的掩碼並將其分配給另一個數組,同時將數組的值復制到另一個數組或將原始掩碼設置為 False) ? 感謝您的任何建議

如果只想考慮有效條目,可以使用掩碼的倒數作為索引:

x = ma.masked_array([1,2,3,4,5,6,7,8,9,10], mask=[0,0,0,0,0,1,1,1,1,1])  # changed mask
y = ma.masked_array([1,2,3,4,5,30,35,40,45,50], mask=[0,0,0,0,0,1,1,1,1,1])

fitParamsFunk, fitCovariancesFunk = curve_fit(Funk, x[~x.mask], y[~y.mask])

PS:請注意,兩個數組都需要具有相同數量的有效條目。

在數值微積分中使用掩碼相當於在解析微積分中使用 Heaviside 階躍函數。 例如,通過應用分段線性回歸,這變得非常簡單:

在此處輸入圖片說明

他們是論文中分段線性回歸的幾個例子: https : //fr.scribd.com/document/380941024/Regression-par-morceaux-Piecewise-Regression-pdf

使用本文所示的方法,下面非常簡單的演算會導致結果的預期形式:

在此處輸入圖片說明

注意:在大量點的情況下,如果過渡區域中有幾個點的橫坐標略有不同,則應用上述參考論文第 29-31 頁的案例會更准確。

我認為您想要做的是定義一個列出“良好數據點”索引的掩碼,然后將其用作要擬合(和/或繪制)的點。

作為 lmfit 的主要作者,我建議使用該庫進行曲線擬合:它比curve_fit具有許多有用的功能。 有了這個,您的示例可能如下所示:

import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model

def Funk(x, k, y0, good_points=None):  # note: add keyword argument
    f = k*x + y0
    if good_points is not None:
        f = f[good_points]       # apply mask of good data points
    return f

x = np.array([1,2,3,4,5, 6,7,8.,9,10])
y = np.array([1,2,3,4,5,30,35.,40,45,50]) 
y += np.random.normal(size=len(x), scale=0.19) # add some noise to make it fun

# make an array of the indices of the "good data points"
# does not need to be contiguous.
good_points=np.array([0,1,2,3,4])

# turn your model function Funk into an lmfit Model
mymodel = Model(Funk)

# create parameters, giving initial values. Note that parameters are
# named using the names of your function's argument and that keyword 
# arguments with non-numeric defaults like 'good points' are seen to
#  *not* be parameters. Like the independent variable `x`, you'll 
# need to pass that in when you do the fit.
# also: parameters can be fixed, or given `min` and `max` attributes

params = mymodel.make_params(k=1.4,  y0=0.2)
params['k'].min = 0

# do the fit to the 'good data', passing in the parameters, the 
# independent variable `x` and the `good_points` mask.
result  = mymodel.fit(y[good_points], params, x=x, good_points=good_points)

# print out a report of best fit values, uncertainties, correlations, etc.
print(result.fit_report())

# plot the results, again using the good_points array as needed.
plt.plot(x, y, 'o', label='all data')
plt.plot(x[good_points], result.best_fit[good_points], label='fit to good data')
plt.legend()
plt.show()

這將打印出來

[[Model]]
    Model(Funk)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 7
    # data points      = 5
    # variables        = 2
    chi-square         = 0.02302999
    reduced chi-square = 0.00767666
    Akaike info crit   = -22.9019787
    Bayesian info crit = -23.6831029
[[Variables]]
    k:   1.02460577 +/- 0.02770680 (2.70%) (init = 1.4)
    y0: -0.04135096 +/- 0.09189305 (222.23%) (init = 0.2)
[[Correlations]] (unreported correlations are < 0.100)
    C(k, y0) = -0.905

並產生一個情節在此處輸入圖片說明

希望能幫助您入門。

暫無
暫無

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

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