【问题标题】:How to do curve fitting of a curve family with python/scipy如何使用 python/scipy 对曲线族进行曲线拟合
【发布时间】:2020-04-05 15:01:10
【问题描述】:

我有一个要解决的问题:

  • 我想用一个方程拟合一组曲线(参见代码)
  • 拟合参数 (C1-C4) 应该是常量
  • 所以我可以通过更改“Sigma 和 T”来拟合(或描述)该族的一条曲线

我希望我能描述我的问题,希望你们能提供帮助,我将非常感激!

问题已编辑(由于误解 - 2020_04_04)

我现在会尝试更具体一些,因为我附上了一张图片,您可以在其中看到“曲线族”的示例,该示例会随着不同的“西格玛”而变化。我想用一对常数来描述这些曲线族——C1、C2、C3 和 C4,而不改变它们。线索是找到一个常数的最佳值,它可以仅以改变 Sigma 和 T 作为变量来描述这个曲线族。因此,我必须以最小的误差拟合一堆曲线的参数。之后,只需更改“Sigma 和 T”,方程就应该涵盖整个曲线族。

Example of Curves

最好的问候!

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


#Equation --> Eps_Cr = (C1*Sigma**C2*x**(C3+1)*e(-C4/T))/(C3+1)

def func(x, C1, C2, C3,C4):
    Sigma = 20
    T = 1
    return (C1*Sigma**C2*x**(C3+1)*np.exp(-C4*1/T))/(C3+1)

#Example Data 1
xdata = [1, 10, 100, 1000, 10000, 100000]
ydata = [0.000382,0.000407,0.000658,0.001169,0.002205,0.004304]

#Example Data 2
xdata1 = [1, 10, 100, 1000, 10000, 100000]
ydata1 = [0.002164,0.002371,0.004441,0.008571,0.016811,0.033261]

#Example Data 3
xdata2 = [1, 10, 100, 1000, 10000, 100000]
ydata2 = [0.001332,0.001457,0.002707,0.005157,0.010007,0.019597]

plt.plot(xdata, ydata, 'b-', label='data')
plt.plot(xdata1, ydata1, 'g-', label='data')
plt.plot(xdata2, ydata2, 'y-', label='data')

popt, pcov = curve_fit(func, xdata, ydata)

plt.plot(xdata, func(xdata, *popt), 'r--',
         label='fit: C1=%5.2e, C2=%5.3f, C3=%5.3f,C4=%5.3f' % tuple(popt))


plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()

【问题讨论】:

  • 嗨!请让你的问题更具体。你的代码在做什么,你想让它做什么?

标签: python scipy curve-fitting scipy-optimize


【解决方案1】:

从您在“答案”中提供的额外信息来看,您似乎想要拟合分层模型。至少统计学家经常这么称呼他们。一些参数在所有数据点之间共享(参数C1C4,一些参数在数据集组内共享(TSigma)。所有这些参数都需要从数据中估计。

这通常通过为所有数据构建更大的模型来解决,并在模型中选择要使用的分组参数。如果一个数据点属于数据组1,我们选择Sigma1T1等等......

由于您已经在使用curve_fit,因此我制作了您的代码版本来完成这项工作。由于我不是scipy 方面的专家,因此代码风格有点要求,但我认为您至少会理解该方法。

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

def func(x_and_grp, C1, C2, C3, C4, Sigma0, Sigma1, Sigma2, T0, T1, T2):
    # We estimate one sigma and one T per group of data points
    x = x_and_grp[:,0]
    grp_id = x_and_grp[:,1]
    # here we select the appropriate T and Sigma for each data point based on their group id
    T = np.array([[T0, T1, T2][int(gid)] for gid in grp_id])
    Sigma = np.array([[Sigma0, Sigma1, Sigma2][int(gid)] for gid in grp_id])
    return (C1*Sigma**C2*x**(C3+1)*np.exp(-C4*1/T))/(C3+1)

#Example Data in 3 groups
xdata0 = [1, 10, 100, 1000, 10000, 100000]
ydata0 = [0.000382,0.000407,0.000658,0.001169,0.002205,0.004304]
xdata1 = [1, 10, 100, 1000, 10000, 100000]
ydata1 = [0.002164,0.002371,0.004441,0.008571,0.016811,0.033261]
xdata2 = [1, 10, 100, 1000, 10000, 100000]
ydata2 = [0.001332,0.001457,0.002707,0.005157,0.010007,0.019597]

#  merge all the data and add the group id to the x-data vectors
y_all = np.concatenate([ydata0, ydata1, ydata2])
x_and_grp_all = np.zeros(shape=(3 * 6, 2))
x_and_grp_all[:, 0] = np.concatenate([xdata0, xdata1, xdata2])
x_and_grp_all[0:6, 1] = 0
x_and_grp_all[6:12, 1] = 1
x_and_grp_all[12:18, 1] = 2

# fit a model to all the data together
popt, pcov = curve_fit(func, x_and_grp_all, y_all)

xspace = np.logspace(1,5)
plt.plot(xdata0, ydata0, 'b-', label='data')
plt.plot(xdata1, ydata1, 'g-', label='data')
plt.plot(xdata2, ydata2, 'y-', label='data')
for gid,color in zip([0,1,2],['r','k','purple']):
    T = popt[4+gid]
    Sigma = popt[7+gid]
    x_and_grp = np.column_stack([xspace,np.ones_like(xspace)*gid])
    plt.plot(xspace,
             func(x_and_grp, *popt),
             linestyle='dashed', color=color,
             label='fit: T=%5.2e, Sigma=%5.3f' % (T,Sigma))

plt.xlabel('X')
plt.ylabel('Y')
plt.title('fit: C1=%5.2e, C2=%5.3f, C3=%5.3f,C4=%5.3f' % tuple(popt[0:4]))
plt.legend()
plt.show()

输出如下所示:

最后,我想补充一点,如果您有很多不同的组,curve_fit 就不太适合这项任务。考虑一些其他可能相关的库。 Statmodels 是可能的。一种替代方法是转而使用scipy.optimize.minimze,因为它为您提供了更大的灵活性。您需要手动进行置信区间估计...

我还想补充一点,如果您知道每组数据的TSigma,上面的方法过于复杂。在这种情况下,我们将 SigmaT 的相关值添加到 x 向量,而不是组 id。

【讨论】:

  • 哇 LudvigH,感谢您的努力,非常感谢!我会试着理解你在那里做了什么!希望有问题时可以联系您。
  • 没问题。只要记住接受答案并在它回答您的问题时投票。 :)
  • 嗨 LudvigH,我想我明白你在那里做了什么。但我不得不承认我有点困惑,如果我想用确定的参数重建方程(例如在 excel 中),让我们现在通过改变“x”来假设 xdata0/ydata0 - 曲线拟合不会起作用。 .. 我的 Y 值(结果)甚至不完全吻合——这是为什么呢?在代码中,拟合似乎有效。是否可以检查更大范围的参数(应该有多个最佳参数)并且 C1 > 0? P.S.:你有一些我可以检查的 Statmodels / scipy.optimize.minimze 的例子吗(例如分层模型)?
  • 更改了绘图并将回归结果包含在我的分析器中。该方法对我来说看起来不错。既然我已经回答了你原来的问题,请接受我的回答。
  • 在curve_fit 中打开一个关于边界处理的新问题(您也可以阅读文档:docs.scipy.org/doc/scipy/reference/generated/…)。这是一个单独的问题。
【解决方案2】:

根据您的查询,我可以理解您需要分别为三个不同的数据集拟合一个方程。因此,我通过保持 sigma 和 T 相同来更新您的代码。请看一下,让我进一步了解。

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


#Equation --> Eps_Cr = (C1*Sigma**C2*x**(C3+1)*e(-C4/T))/(C3+1)

def func(x, C1, C2, C3,C4):
    Sigma = 20
    T = 1
    return (C1*Sigma**C2*x**(C3+1)*np.exp(-C4*1/T))/(C3+1)

#Example Data 1
xdata = [1, 10, 100, 1000, 10000, 100000]
ydata = [0.000382,0.000407,0.000658,0.001169,0.002205,0.004304]

#Example Data 2
xdata1 = [1, 10, 100, 1000, 10000, 100000]
ydata1 = [0.002164,0.002371,0.004441,0.008571,0.016811,0.033261]

#Example Data 3
xdata2 = [1, 10, 100, 1000, 10000, 100000]
ydata2 = [0.001332,0.001457,0.002707,0.005157,0.010007,0.019597]

plt.plot(xdata, ydata, 'b-', label='data 1')
plt.plot(xdata1, ydata1, 'g-', label='data 2')
plt.plot(xdata2, ydata2, 'y-', label='data 3')

popt, pcov = curve_fit(func, xdata, ydata)
popt1, pcov1 = curve_fit(func, xdata1, ydata1)
popt2, pcov2 = curve_fit(func, xdata2, ydata2)

plt.plot(xdata, func(xdata, *popt), 'r.',
         label='fit for Data 1: C1=%5.2e, C2=%5.3f, C3=%5.3f,C4=%5.3f' % tuple(popt))

plt.plot(xdata1, func(xdata1, *popt1), 'r+',
         label='fit for Data 2: C1=%5.2e, C2=%5.3f, C3=%5.3f,C4=%5.3f' % tuple(popt1))

plt.plot(xdata2, func(xdata2, *popt2), 'r--',
         label='fit for Data 3 : C1=%5.2e, C2=%5.3f, C3=%5.3f,C4=%5.3f' % tuple(popt2))


plt.xlabel('X')
plt.ylabel('Y')
plt.legend(loc='upper left',prop={'size': 8})
plt.show()

【讨论】:

    猜你喜欢
    • 2015-09-14
    • 2020-03-19
    • 2013-10-10
    • 1970-01-01
    • 2017-04-21
    • 2014-09-08
    • 2020-05-05
    • 2012-04-25
    • 2021-11-14
    相关资源
    最近更新 更多