首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用python拟合多个指数曲线

如何使用python拟合多个指数曲线
EN

Stack Overflow用户
提问于 2020-08-25 22:43:07
回答 1查看 436关注 0票数 1

对于像这里的curve_fit for as single exponential curve图像中所示的单个指数曲线,我能够使用scipy.optimize.curve_fit拟合数据。然而,我不确定如何实现对由多个指数曲线组成的类似数据集的拟合,如这里所示的double exponential curves。我使用以下方法实现了对单个曲线的拟合:

代码语言:javascript
复制
def exp_decay(x,a,r):
    return a * ((1-r)**x) 

x = np.linspace(0,50,50)
y = exp_decay(x, 400, 0.06)

y1 = exp_decay(x, 550, 0.06)      # this is to be used to append to y to generate two curves

pars, cov = curve_fit(exp_decay, x, y, p0=[0,0])
plt.scatter(x,y)
plt.plot(x, exp_decay(x, *pars), 'r-')     #this realizes the fit for a single curve

yx = np.append(y,y1)   #this realizes two exponential curves (as shown above - double exponential curves) for which I don't need to fit a model to

有人可以帮助描述如何实现这一点的数据集的两条曲线。我的实际数据集由多条指数曲线组成,但我认为如果我能够实现对两条曲线的拟合,我也许能够对我的数据集复制相同的拟合。这不能用scipy的curve_fit来完成;任何可以工作的实现都可以。

请帮帮我!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-26 17:23:15

您的问题可以通过使用一阶导数估计等简单标准拆分数据集来轻松解决,然后我们可以对每个子数据集应用简单的曲线拟合过程。

试验数据集

首先,让我们导入一些包,并创建一个具有三条曲线的合成数据集来表示您的问题。

我们使用一个双参数指数模型,因为时间原点偏移将由分裂方法处理。我们还添加了噪声,因为现实世界中的数据总是存在噪声:

代码语言:javascript
复制
import numpy as np
import pandas as pd
from scipy import optimize
import matplotlib.pyplot as plt

def func(x, a, b):
    return a*np.exp(b*x)

N = 1001
n1 = N//3
n2 = 2*n1

t = np.linspace(0, 10, N)

x0 = func(t[:n1], 1, -0.2)
x1 = func(t[n1:n2]-t[n1], 5, -0.4)
x2 = func(t[n2:]-t[n2], 2, -1.2)

x = np.hstack([x0, x1, x2])
xr = x + 0.025*np.random.randn(x.size)

它以图形方式呈现如下:

数据集拆分

我们可以将数据集分成三个子数据集,使用一个简单的标准作为一阶导数估计,使用一阶差分来评估它。目标是检测曲线何时急剧上升或下降(数据集应拆分的位置。一阶导数估计如下):

代码语言:javascript
复制
dxrdt = np.abs(np.diff(xr)/np.diff(t))

该标准需要一个额外的参数(阈值),该参数必须根据您的信号规格进行相应的调整。该标准等同于:

代码语言:javascript
复制
xcrit = 20
q = np.where(dxrdt > xcrit) # (array([332, 665], dtype=int64),)

和拆分索引是:

代码语言:javascript
复制
idx = [0] + list(q[0]+1) + [t.size] # [0, 333, 666, 1001]

标准阈值主要受数据上噪声的性质和强度以及两条曲线之间的间隙大小的影响。这种方法的使用取决于在存在噪声的情况下检测曲线间隙的能力。当噪声功率与我们想要检测的间隙的大小相同时,它将断开。如果噪声严重拖尾(很少有强离群值),还可以观察到错误的分裂指数。

在此MCVE中,我们将阈值设置为20 [Signal Units/Time Units]

对于这种手工创建的标准,另一种方法是将标识委托给scipy的优秀find_peaks方法。但它不会避免根据您的信号规格调整检测的要求。

拟合原点偏移数据集

现在我们可以在每个子数据集上应用曲线拟合(具有原点偏移的时间),收集参数和统计数据,并绘制结果:

代码语言:javascript
复制
trials = []
fig, axe = plt.subplots()
for k, (i, j) in enumerate(zip(idx[:-1], idx[1:])):
    p, s = optimize.curve_fit(func, t[i:j]-t[i], xr[i:j])
    axe.plot(t[i:j], xr[i:j], '.', label="Data #{}".format(k+1))
    axe.plot(t[i:j], func(t[i:j]-t[i], *p), label="Data Fit #{}".format(k+1))
    trials.append({"n0": i, "n1": j, "t0": t[i], "a": p[0], "b": p[1],
                   "s_a": s[0,0], "s_b": s[1,1], "s_ab": s[0,1]})
axe.set_title("Curve Fits")
axe.set_xlabel("Time, $t$")
axe.set_ylabel("Signal Estimate, $\hat{g}(t)$")
axe.legend()
axe.grid()
df = pd.DataFrame(trials)

它返回以下拟合结果:

代码语言:javascript
复制
    n0    n1    t0         a         b       s_a           s_b      s_ab
0    0   333  0.00  0.998032 -0.199102  0.000011  4.199937e-06 -0.000005
1  333   666  3.33  5.001710 -0.399537  0.000013  3.072542e-07 -0.000002
2  666  1001  6.66  2.002495 -1.203943  0.000030  2.256274e-05 -0.000018

它符合我们的原始参数(参见试验数据集部分)。

我们可以用图形来检查拟合的好坏:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63581359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档