如何在Python中进行指数和对数曲线拟合?我发现只有多项式拟合
我有一组数据,我想比较哪一行最能描述它(不同阶的多项式,指数或对数)。
我使用 Python 和 Numpy,对于多项式拟合,有一个函数 polyfit()
。但我没有发现这样的指数和对数拟合函数。
有吗?或者另外如何解决?
I have a set of data and I want to compare which line describes it best (polynomials of different orders, exponential or logarithmic).
I use Python and Numpy and for polynomial fitting there is a function polyfit()
. But I found no such functions for exponential and logarithmic fitting.
Are there any? Or how to solve it otherwise?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
要拟合 y = A + B log x,只需将 y 拟合到 (记录x)。
为了拟合y = AeBx,两边取对数得到logy = log A + Bx。因此适合(log y)与x。
请注意,将 (log y) 拟合为线性将强调 y 的小值,从而导致大 y 出现较大偏差。这是因为
polyfit
(线性回归)的工作原理是最小化 Σi (ΔY)2< /sup> = Σi (Yi − Ŷ< em>i)2。当Yi = log yi时,残基 ΔYi = Δ(log yi< /sub>) ≈ Δyi / |yi |。因此,即使polyfit
对于较大的 y 做出了非常糟糕的决定,“除以-|y|”因子将对其进行补偿,导致polyfit
倾向于较小的值。这可以通过为每个条目赋予与y成比例的“权重”来缓解。
polyfit
通过w
关键字参数支持加权最小二乘。请注意,Excel、LibreOffice 和大多数科学计算器通常使用未加权(有偏差)公式来计算指数回归/趋势线。如果您希望结果与这些平台兼容,甚至不要包含权重如果它能提供更好的结果。
现在,如果您可以使用 scipy,则可以使用
scipy.optimize.curve_fit
无需转换即可拟合任何模型。对于 y = A + B log x 结果与转换方法相同:
对于 y = AeBx,但是,我们可以获得更好的拟合,因为它计算 Δ(log y) 直接。但我们需要提供一个初始化猜测,以便 curve_fit 能够达到所需的局部最小值。
For fitting y = A + B log x, just fit y against (log x).
For fitting y = AeBx, take the logarithm of both side gives log y = log A + Bx. So fit (log y) against x.
Note that fitting (log y) as if it is linear will emphasize small values of y, causing large deviation for large y. This is because
polyfit
(linear regression) works by minimizing ∑i (ΔY)2 = ∑i (Yi − Ŷi)2. When Yi = log yi, the residues ΔYi = Δ(log yi) ≈ Δyi / |yi|. So even ifpolyfit
makes a very bad decision for large y, the "divide-by-|y|" factor will compensate for it, causingpolyfit
favors small values.This could be alleviated by giving each entry a "weight" proportional to y.
polyfit
supports weighted-least-squares via thew
keyword argument.Note that Excel, LibreOffice and most scientific calculators typically use the unweighted (biased) formula for the exponential regression / trend lines. If you want your results to be compatible with these platforms, do not include the weights even if it provides better results.
Now, if you can use scipy, you could use
scipy.optimize.curve_fit
to fit any model without transformations.For y = A + B log x the result is the same as the transformation method:
For y = AeBx, however, we can get a better fit since it computes Δ(log y) directly. But we need to provide an initialize guess so
curve_fit
can reach the desired local minimum.您还可以使用 scipy.optimize 中的 curve_fit 将一组数据拟合到您喜欢的任何函数。例如,如果您想拟合指数函数(来自文档 ):
然后如果你想绘图,你可以这样做:
(注意:绘图时
popt
前面的*
会将术语展开到
、func
所期望的 ab
和c
。)You can also fit a set of a data to whatever function you like using
curve_fit
fromscipy.optimize
. For example if you want to fit an exponential function (from the documentation):And then if you want to plot, you could do:
(Note: the
*
in front ofpopt
when you plot will expand out the terms into thea
,b
, andc
thatfunc
is expecting.)我在这方面遇到了一些麻烦,所以让我非常明确,以便像我这样的菜鸟能够理解。
假设我们有一个数据文件或类似的文件,
结果是:
a = 0.849195983017 , b = -1.18101681765, c = 2.24061176543, d = 0.816643894816
I was having some trouble with this so let me be very explicit so noobs like me can understand.
Lets say that we have a data file or something like that
the result is:
a = 0.849195983017 , b = -1.18101681765, c = 2.24061176543, d = 0.816643894816
这是使用来自 scikit 学习。
给定
代码
拟合指数数据
拟合日志数据
详细信息
常规步骤
x
、y
或两者)np.exp())并拟合原始数据
假设我们的数据遵循指数趋势,一般方程+可能是:
我们可以线性化后一个方程(例如 y = 截距 + 斜率* x) 通过获取日志:
给定线性方程++和回归参数,我们可以
A
(ln(A)
)B
通过斜率 (B
)线性化技术总结
+注意:当噪声为小且C=0。谨慎使用。
++注意:虽然更改 x 数据有助于线性化指数数据,但更改 y 数据有助于线性化对数数据> 数据。
Here's a linearization option on simple data that uses tools from scikit learn.
Given
Code
Fit exponential data
Fit log data
Details
General Steps
x
,y
or both)np.exp()
) and fit to original dataAssuming our data follows an exponential trend, a general equation+ may be:
We can linearize the latter equation (e.g. y = intercept + slope * x) by taking the log:
Given a linearized equation++ and the regression parameters, we could calculate:
A
via intercept (ln(A)
)B
via slope (B
)Summary of Linearization Techniques
+Note: linearizing exponential functions works best when the noise is small and C=0. Use with caution.
++Note: while altering x data helps linearize exponential data, altering y data helps linearize log data.
好吧,我想你总是可以使用:
稍微修改 IanVS 的答案:
这会产生下图:
Well I guess you can always use:
Slightly modifying IanVS's answer:
This results in the following graph:
我们在解决这两个问题的同时演示了
lmfit
的功能。给定
代码
方法 1 -
lmfit
模型拟合指数数据
方法2 - 自定义模型
拟合日志数据
详细信息
您可以从回归器确定推断参数目的。示例:
要进行预测,请使用
ModelResult.eval()方法。
注意:
ExponentialModel()
遵循衰减函数,它接受两个参数,其中一个为负数。另请参阅
ExponentialGaussianModel()
,它接受 更多参数。通过
>安装
库pip 安装 lmfit
。We demonstrate features of
lmfit
while solving both problems.Given
Code
Approach 1 -
lmfit
ModelFit exponential data
Approach 2 - Custom Model
Fit log data
Details
You can determine the inferred parameters from the regressor object. Example:
To make predictions, use the
ModelResult.eval()
method.Note: the
ExponentialModel()
follows a decay function, which accepts two parameters, one of which is negative.See also
ExponentialGaussianModel()
, which accepts more parameters.Install the library via
> pip install lmfit
.Wolfram 有一个用于拟合指数的封闭式解决方案。他们也有类似的解决方案来拟合 对数 和 幂律。
我发现这比 scipy 的 curve_fit 效果更好。特别是当您没有“接近零”的数据时。这是一个示例:
Wolfram has a closed form solution for fitting an exponential. They also have similar solutions for fitting a logarithmic and power law.
I found this to work better than scipy's curve_fit. Especially when you don't have data "near zero". Here is an example: