曲线拟合、python和excel之间的幂律回归问题

曲线拟合、python和excel之间的幂律回归问题,python,excel,curve-fitting,Python,Excel,Curve Fitting,对不起,我是python和堆栈流方面的新手。所以我不能发布图片 我想用python中的curve_fit函数进行幂律回归。但结果对我来说很奇怪。我使用excel进一步检查它。这两者看起来有很大区别。黑线是曲线拟合的结果,红线参数来自excel。有人能告诉我区别吗?谢谢大家! x=[164000,400,13000,700,57000,108,12000] y=[0.011970,0.000098,0.066100,0.004300,0.042600,0.000061,0.002858 ] de

对不起,我是python和堆栈流方面的新手。所以我不能发布图片

我想用python中的curve_fit函数进行幂律回归。但结果对我来说很奇怪。我使用excel进一步检查它。这两者看起来有很大区别。黑线是曲线拟合的结果,红线参数来自excel。有人能告诉我区别吗?谢谢大家!

x=[164000,400,13000,700,57000,108,12000]
y=[0.011970,0.000098,0.066100,0.004300,0.042600,0.000061,0.002858 ]

def f(x,a,b):
    return a*x**b

popt,pocv=curve_fit(f,x,y)

ax.set_xscale("log")
ax.set_yscale("log")
ax.set_ylim(0.00001,0.1)
ax.set_xlim(10,1000000)

ax.scatter(x,y)

px=np.linspace(10,1000000,1000)

#parameter form curve_fit
py=a*px**b
[enter image description here][1]
#parameter from excel
pyy=3E-6*px**0.8305

ax.loglog(px,pyy,color="red")
ax.loglog(px,py,color="k")

使用
least_squares
进行对数拟合是有问题的,因为点和拟合线之间的差异随着
x
值的增大而增大。这就是为什么合身不是你所期望的。要更正此问题,可以在参数上添加边界,如下所示:

popt,pcov=curve_fit(f,x,y, bounds=(0, [3*10**(-6), 0.9]))
您可以从
pcov
获得的摘要参数错误

error = np.sum(np.sqrt(np.diag(pcov)))
输出:


或者更改拟合方法。

在日志空间中绘制数据的事实应该给您一个很好的提示,让您在日志空间中进行拟合。也就是说,将
np.log(a*x**b)
拟合到
np.log(y)
。对实际运行并获得良好匹配的脚本的修改如下:

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

x=[164000,400,13000,700,57000,108,12000]
y=[0.011970,0.000098,0.066100,0.004300,0.042600,0.000061,0.002858 ]

def f(x, a, b):
    return np.log(a*x**b)

popt,pcov=curve_fit(f, x, np.log(y), [1.e-6, 0.9])

ax = plt.gca()

ax.set_xscale("log")
ax.set_yscale("log")
ax.set_ylim(0.00001,0.1)
ax.set_xlim(10,1000000)

ax.scatter(x,y)

px = np.linspace(10,1000000,1000)
a, b = popt
print("Parameters: a=%g,  b=%g" % (a, b))

#parameter form curve_fit
py=a*px**b

#parameter from excel
pyy=3e-6*px**0.8305

ax.loglog(px,pyy, color="red")
ax.loglog(px,py,  color="k")
plt.show()
始终确保为参数提供初始值,并确保打印出结果。例如,运行此命令将打印出
参数:a=2.78612e-06,b=0.829763
,并显示两条预测行几乎位于彼此顶部

为了获得更好的曲线拟合体验,您可能会发现
lmfit
()很有用(是的,我是主要作者,而且有偏见)。使用
lmfit
,您的适合度可以是:

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

x=[164000,400,13000,700,57000,108,12000]
y=[0.011970,0.000098,0.066100,0.004300,0.042600,0.000061,0.002858 ]

def f(x, a, b):
    return np.log(a*x**b)

model = Model(f)
params = model.make_params(a=1.e-6, b=0.9)
result = model.fit(np.log(y), params, x=x)

print(result.fit_report())

px = np.linspace(10,1000000,1000)
plt.scatter(x,y)
plt.loglog(px, np.exp(result.eval(x=px)),  color="k")
plt.show()
请注意,使用lmfit,将使用
f()
model函数中的名称命名参数。这将打印一份包含估计不确定性的fit报告:

[[Model]]
    Model(f)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 16
    # data points      = 7
    # variables        = 2
    chi-square         = 14.7591170
    reduced chi-square = 2.95182340
    Akaike info crit   = 9.22165592
    Bayesian info crit = 9.11347621
[[Variables]]
    a:  2.7861e-06 +/- 6.3053e-06 (226.31%) (init = 1e-06)
    b:  0.82976271 +/- 0.25700150 (30.97%) (init = 0.9)
[[Correlations]] (unreported correlations are < 0.100)
    C(a, b) = -0.958
[[Model]]
模型(f)
[[Fit统计数据]]
#拟合方法=最小二乘法
#函数evals=16
#数据点=7
#变量=2
卡方检验=14.7591170
缩减卡方检验=2.95182340
Akaike信息临界值=9.22165592
贝叶斯信息标准=9.11347621
[[变量]]
a:2.7861e-06+/-6.3053e-06(226.31%)(初始值=1e-06)
b:0.82976271+/-0.25700150(30.97%)(初始值=0.9)
[[相关性]](未报告的相关性<0.100)
C(a,b)=-0.958
并制作一个

python没有曲线拟合函数。在优化包中的scipy中有一个-这就是你的意思吗?它使用Levenburg-Marquart算法。我不知道Excel使用什么,但如果你先取对数,然后对这些值进行线性回归,你会给出不同的答案。所以,这意味着我什么时候要进行回归。我总是需要设置边界,对吗?@Jui mingChang不总是这样,但当你只有几个数据点时,你试图拟合的函数不是线性的。