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

如何使用python拟合多个指数曲线,python,python-3.x,machine-learning,artificial-intelligence,data-analysis,Python,Python 3.x,Machine Learning,Artificial Intelligence,Data Analysis,对于如图所示的单指数曲线,我可以使用scipy.optimize.curve\u fit拟合数据。然而,我不确定如何实现对由多个指数曲线组成的类似数据集的拟合,如图所示。 我使用以下方法实现了单曲线的拟合: 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 i

对于如图所示的单指数曲线,我可以使用scipy.optimize.curve\u fit拟合数据。然而,我不确定如何实现对由多个指数曲线组成的类似数据集的拟合,如图所示。 我使用以下方法实现了单曲线的拟合:

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的曲线拟合完成;任何有效的实现都可以


请帮忙

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

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

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

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)
它以图形方式呈现如下所示:

dxrdt = np.abs(np.diff(xr)/np.diff(t))

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

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

xcrit = 20
q = np.where(dxrdt > xcrit) # (array([332, 665], dtype=int64),)
和拆分索引为:

idx = [0] + list(q[0]+1) + [t.size] # [0, 333, 666, 1001]
标准阈值主要受数据上噪声的性质和功率以及两条曲线之间的间隙大小的影响。该方法的使用取决于在存在噪声的情况下检测曲线间隙的能力。当噪声功率与我们想要检测的间隙大小相同时,它将中断。如果噪声是重尾的(很少有强异常值),也可以观察假分割指数

在本MCVE中,我们将阈值设置为
20[信号单位/时间单位]

此手工标准的另一种替代方法是将标识委托给优秀的
scipy
。但它无法避免将检测调整到您的信号规格的要求

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

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)
它返回以下拟合结果:

    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
符合我们的原始参数(见试用数据集部分)

我们可以通过图形检查拟合度:


好消息/坏消息。如果可以将一条曲线拟合到类似的数据(似乎可以),则可以拟合N条曲线。您显然需要通过分离数据来分别拟合它们。所以潜在的坏消息。在您的数据集中,来自单独曲线的数据是如何标记或区分的?@AirSquid Yea,我可以为单个曲线标记或区分数据;但是,由于它是一个来自某些观察的连续数据集,所以分离数据不是一个选项。曲线是重复的模式,我需要找到适合的模式。这些曲线具有不同的数据点-不同的周期。感谢您的评论。使用一阶导数标准分割数据集(曲线变化时第一个差值为正),然后通过切换到原点或添加额外的滞后参数应用单曲线拟合。最后汇总结果。很明显,您必须以某种方式分离不同曲线的数据。曲线拟合算法如何知道要拟合哪条曲线?建议你们用数据扩充你们的帖子,或者写一篇新的帖子。如果数据在你的x轴上被隔开,如你的例子中所示,在寻找大跳跃或寻找上面所建议的导数方面有一些希望…所有这些都取决于许多事情!非常感谢。似乎真的是这样。是否有可能获得整个jupyter笔记本文件,用于所有绘图的实现?只是为了更好地了解这项技术(以前从未这样做过)。再次感谢。@Ziggey,不客气。如果您觉得合适,可以将其标记为答案。这是笔记本:我想了解阈值的背景知识在这里非常重要。如果这些知识不方便,怎么能做到呢?“该标准需要一个额外的参数(阈值),必须根据您的信号规格进行相应调整。”您能否描述一下,在没有这些信息的情况下,如何实现这一目标?您是如何得出20个阈值的?我运行了5次绘图,并在本MCVE中直观地选择了它。如果你的噪声可以被认为是正常的,你可以将这个阈值设定在5西格玛左右(适当地调整它以获得正确的单位)。这将是一个良好的开端。您可以根据过去的数据进行评估,并评估它在使用新获取的数据时的性能。只要您的流程保持稳定,它就会工作。但这取决于你的过程和我们可以从中得出的假设。