[英]Confidence interval for exponential curve fit
我試圖獲得一些x,y
數據的指數擬合的置信區間( 此處可用)。 這是MWE我必須找到最適合數據的指數:
from pylab import *
from scipy.optimize import curve_fit
# Read data.
x, y = np.loadtxt('exponential_data.dat', unpack=True)
def func(x, a, b, c):
'''Exponential 3-param function.'''
return a * np.exp(b * x) + c
# Find best fit.
popt, pcov = curve_fit(func, x, y)
print popt
# Plot data and best fit curve.
scatter(x, y)
x = linspace(11, 23, 100)
plot(x, func(x, *popt), c='r')
show()
產生:
如何使用純python
, numpy
或scipy
(我已安裝的軟件包)獲得95%(或其他值)置信區間?
您可以使用不確定性模塊進行不確定性計算。 uncertainties
跟蹤不確定性和相關性。 您可以直接從curve_fit
的輸出創建相關的uncertainties.ufloat
curve_fit
。
為了能夠對諸如exp
類的非內置操作進行計算,您需要使用uncertainties.unumpy
函數exp
的函數。
您還應該避免from pylab import *
import。 這甚至會覆蓋諸如sum
類的python內置函數。
一個完整的例子:
import numpy as np
from scipy.optimize import curve_fit
import uncertainties as unc
import matplotlib.pyplot as plt
import uncertainties.unumpy as unp
def func(x, a, b, c):
'''Exponential 3-param function.'''
return a * np.exp(b * x) + c
x, y = np.genfromtxt('data.txt', unpack=True)
popt, pcov = curve_fit(func, x, y)
a, b, c = unc.correlated_values(popt, pcov)
# Plot data and best fit curve.
plt.scatter(x, y, s=3, linewidth=0, alpha=0.3)
px = np.linspace(11, 23, 100)
# use unumpy.exp
py = a * unp.exp(b * px) + c
nom = unp.nominal_values(py)
std = unp.std_devs(py)
# plot the nominal value
plt.plot(px, nom, c='r')
# And the 2sigma uncertaintie lines
plt.plot(px, nom - 2 * std, c='c')
plt.plot(px, nom + 2 * std, c='c')
plt.savefig('fit.png', dpi=300)
注意 :獲得擬合曲線置信區間的實際答案由Ulrich 在此給出。
經過一些研究(見這里 , 這里和1.96 ),我想出了自己的解決方案。
它接受任意X%置信區間並繪制上下曲線。
這是MWE:
from pylab import *
from scipy.optimize import curve_fit
from scipy import stats
def func(x, a, b, c):
'''Exponential 3-param function.'''
return a * np.exp(b * x) + c
# Read data.
x, y = np.loadtxt('exponential_data.dat', unpack=True)
# Define confidence interval.
ci = 0.95
# Convert to percentile point of the normal distribution.
# See: https://en.wikipedia.org/wiki/Standard_score
pp = (1. + ci) / 2.
# Convert to number of standard deviations.
nstd = stats.norm.ppf(pp)
print nstd
# Find best fit.
popt, pcov = curve_fit(func, x, y)
# Standard deviation errors on the parameters.
perr = np.sqrt(np.diag(pcov))
# Add nstd standard deviations to parameters to obtain the upper confidence
# interval.
popt_up = popt + nstd * perr
popt_dw = popt - nstd * perr
# Plot data and best fit curve.
scatter(x, y)
x = linspace(11, 23, 100)
plot(x, func(x, *popt), c='g', lw=2.)
plot(x, func(x, *popt_up), c='r', lw=2.)
plot(x, func(x, *popt_dw), c='r', lw=2.)
text(12, 0.5, '{}% confidence interval'.format(ci * 100.))
show()
加布里埃爾的回答是不正確的。 在這里用紅色顯示他的數據的95%置信區間,由GraphPad Prism計算:
背景:“擬合曲線的置信區間”通常稱為置信帶 。 對於95%置信區間,可以95%確信它包含真實曲線。 (這與預測頻段不同,如上所示為灰色。預測頻段與未來數據點有關。有關詳細信息,請參閱,例如,GraphPad曲線擬合指南的此頁面 。)
在Python中, kmpfit可以計算非線性最小二乘的置信帶。 這里是加布里埃爾的例子:
from pylab import *
from kapteyn import kmpfit
x, y = np.loadtxt('_exp_fit.txt', unpack=True)
def model(p, x):
a, b, c = p
return a*np.exp(b*x)+c
f = kmpfit.simplefit(model, [.1, .1, .1], x, y)
print f.params
# confidence band
a, b, c = f.params
dfdp = [np.exp(b*x), a*x*np.exp(b*x), 1]
yhat, upper, lower = f.confidence_band(x, dfdp, 0.95, model)
scatter(x, y, marker='.', s=10, color='#0000ba')
ix = np.argsort(x)
for i, l in enumerate((upper, lower, yhat)):
plot(x[ix], l[ix], c='g' if i == 2 else 'r', lw=2)
show()
dfdp
是關於每個參數p(即a,b和c)的模型f = a * e ^(b * x)+ c的偏導數∂f/ dfdp
。 有關背景信息,請參閱“GraphPad曲線擬合指南”的kmpfit教程或此頁面 。 (與我的示例代碼不同,kmpfit教程不使用庫中的confidence_band()
,而是使用它自己的略有不同的實現。)
最后,Python圖與Prism圖匹配:
curve_fit()
返回協方差矩陣 - pcov - 它保存估計的不確定性(1 sigma)。 這假設錯誤是正常分布的,這有時是有問題的。
你也可以考慮使用lmfit包(純python,建立在scipy之上),它提供了一個圍繞scipy.optimize擬合例程的包裝器(包括leastsq(),這是curve_fit()使用的),並且可以,除其他外,明確計算置信區間。
我一直是簡單引導的粉絲,以獲得置信區間。 如果你有n
數據點,那么使用random
軟件包從你的數據中選擇n
個點進行重新映射(即允許你的程序多次獲得相同的點,如果這是它想做的 - 非常重要)。 完成后,繪制重新采樣點並獲得最佳擬合。 這樣做10,000次,每次都有新的生產線。 然后你的95%置信區間是包含95%最佳擬合線的一對線。
在Python中編程是一種非常簡單的方法,但從統計的角度來看,這有點不清楚。 有關您為什么要這樣做的更多信息可能會為您的任務帶來更合適的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.