指数曲线拟合的置信区间

Gab*_*iel 11 python numpy scipy confidence-interval

我试图获得一些指数适合某些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()
Run Code Online (Sandbox Code Playgroud)

产生:

在此输入图像描述

如何在这个拟合上获得95%(或其他一些值)的置信区间,最好使用pure python,numpy或者scipy(我已经安装过的软件包)?

Ulr*_*ern 6

加百列的答案不正确。在这里用红色表示GraphPad Prism计算出的他的数据的95%置信带: 棱镜置信度和预测带

背景:“拟合曲线的置信区间”通常称为置信带。对于95%的置信带,可以95%的置信度包含真实曲线。(这与上面以灰色显示的预测带不同。预测带与将来的数据点有关。有关更多详细信息,请参见例如GraphPad Curve Fitting Guide的本页。)

在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()
Run Code Online (Sandbox Code Playgroud)

dfdp是偏导数?F /?模型的F P = A * E 1(B * X)+ C相对于每个参数p(即,A,B,和C)。有关背景,请参见kmpfit教程或GraphPad曲线拟合指南的本页。(与我的示例代码不同,kmpfit教程不使用confidence_band()库中的内容,而是使用其自己的实现,但略有不同)。

最后,Python图与Prism匹配:

kmpfit置信带

  • 我只是在棱镜图中添加了预测波段。因此,您的旧答案不会计算预测范围。GraphPad Curve Fitting Guide的[page](http://www.graphpad.com/guides/prism/7/curve-fitting/index.htm?reg_how_confidence_and_prediction_.htm)说明了如何在Prism中计算它们。 (2认同)

Max*_*Noe 6

您可以使用不确定性模块进行不确定性计算. uncertainties跟踪不确定性和相关性.您可以uncertainties.ufloat直接从输出创建相关curve_fit.

能够对非内置操作进行计算,例如exp需要使用函数uncertainties.unumpy.

您还应该避免from pylab import *导入.这甚至会覆盖python内置函数,例如sum.

一个完整的例子:

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)
Run Code Online (Sandbox Code Playgroud)

结果如下: 结果


Gab*_*iel 5

注意:获得拟合曲线置信区间的实际答案由 Ulrich here给出。


经过一些研究(请参阅此处此处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()
Run Code Online (Sandbox Code Playgroud)