Python 使用scipy.optmize.curve_fit拟合测井数据

Python 使用scipy.optmize.curve_fit拟合测井数据,python,scipy,curve-fitting,Python,Scipy,Curve Fitting,我有两个变量x和y,我正试图使用curve\u fit从scipy.optimize进行拟合 拟合数据的方程式是一个简单的幂律,形式为y=a(x^b)。当我将x轴和y轴设置为对数刻度时,数据的拟合似乎很好,即ax.set_xscale('log')和ax.set_yscale('log') 代码如下: def fitfunc(x,p1,p2): y = p1*(x**p2) return y popt_1,pcov_1 = curve_fit(fitfunc,x,y,p0=(1

我有两个变量
x和y
,我正试图使用
curve\u fit
scipy.optimize
进行拟合

拟合数据的方程式是一个简单的幂律,形式为
y=a(x^b)
。当
我将x轴和y轴设置为对数刻度时,数据的拟合似乎很好,即
ax.set_xscale('log')
ax.set_yscale('log')

代码如下:

def fitfunc(x,p1,p2):
    y = p1*(x**p2)
    return y

popt_1,pcov_1 = curve_fit(fitfunc,x,y,p0=(1.0,1.0))
p1_1 = popt_1[0]
p1_2 = popt_1[1]
residuals1 = (ngal_mstar_1) - fitfunc(x,p1_1,p1_2)
xi_sq_1 = sum(residuals1**2) #The chi-square value

curve_y_1 = fitfunc(x,p1_1,p1_2) #This is the fit line seen in the graph

fig = plt.figure(figsize=(14,12))
ax1 = fig.add_subplot(111)
ax1.scatter(x,y,c='r')
ax1.plot(y,curve_y_1,'y.',linewidth=1)
ax1.legend(loc='best',shadow=True,scatterpoints=1)
ax1.set_xscale('log') #Scale is set to log
ax1.set_yscale('log') #SCale is set to log
plt.show()

当我为x和y使用真对数值时,幂律拟合变成
y=10^(a+b*log(x))
,即将右侧的幂提高到10,因为它是logbase 10。现在,by x和y值都是log(x)和log(y)

上述情况的适用性似乎不太好。这是我使用的代码

def fitfunc(x,p1,p2):
    y = 10**(p1+(p2*x))
    return y

popt_1,pcov_1 = curve_fit(fitfunc,np.log10(x),np.log10(y),p0=(1.0,1.0))

p1_1 = popt_1[0]
p1_2 = popt_1[1]
residuals1 = (y) - fitfunc((x),p1_1,p1_2)
xi_sq_1 = sum(residuals1**2)

curve_y_1 = fitfunc(np.log10(x),p1_1,p1_2) #The fit line uses log(x) here itself

fig = plt.figure(figsize=(14,12))
ax1 = fig.add_subplot(111)
ax1.scatter(np.log10(x),np.log10(y),c='r')
ax1.plot(np.log10(y),curve_y_1,'y.',linewidth=1)
plt.show()


两个曲线图之间的唯一区别是拟合方程,对于第二个曲线图,数值已独立记录。我在这里做错了什么,因为我想要对数(x)vs对数(y)图和相应的拟合参数(斜率和截距)

你将幂律模型转换为对数是错误的,即你的第二次拟合实际上适合不同的模型。将原始模型
y=a*(x^b)
应用两侧的对数,您将得到
log(y)=log(a)+b*log(x)
。因此,对数比例中的模型应该简单地读取
y'=a'+b*x'
,其中素数表示对数比例中的变量。该模型现在是一个线性函数,这是一个众所周知的结果,即所有幂律都成为对数中的线性函数


这就是说,您仍然可以期望两种拟合版本之间存在一些小的差异,因为
curve\u fit
将优化最小二乘问题。因此,在对数尺度下,拟合将最小化拟合和数据之间的相对误差,而在线性尺度下,拟合将最小化绝对误差。因此,为了决定哪种方法实际上更适合您的拟合,您必须估计数据中的误差。您显示的数据在对数刻度中肯定没有恒定的不确定性,因此在线性刻度上,您的拟合可能更可靠。如果每个数据点的错误都是已知的,那么你可以考虑使用<代码> sigma < /Cord>参数。如果正确使用这一方法,这两种方法应该没有太大区别。在这种情况下,我更喜欢对数比例拟合,因为模型更简单,因此可能在数值上更稳定。

您将幂律模型转换为对数是错误的,即您的第二次拟合实际上适合不同的模型。将原始模型
y=a*(x^b)
应用两侧的对数,您将得到
log(y)=log(a)+b*log(x)
。因此,对数比例中的模型应该简单地读取
y'=a'+b*x'
,其中素数表示对数比例中的变量。该模型现在是一个线性函数,这是一个众所周知的结果,即所有幂律都成为对数中的线性函数


这就是说,您仍然可以期望两种拟合版本之间存在一些小的差异,因为
curve\u fit
将优化最小二乘问题。因此,在对数尺度下,拟合将最小化拟合和数据之间的相对误差,而在线性尺度下,拟合将最小化绝对误差。因此,为了决定哪种方法实际上更适合您的拟合,您必须估计数据中的误差。您显示的数据在对数刻度中肯定没有恒定的不确定性,因此在线性刻度上,您的拟合可能更可靠。如果每个数据点的错误都是已知的,那么你可以考虑使用<代码> sigma < /Cord>参数。如果正确使用这一方法,这两种方法应该没有太大区别。在这种情况下,我更喜欢对数比例拟合,因为模型更简单,因此可能在数值上更稳定。

您将幂律模型转换为对数是错误的,即您的第二次拟合实际上适合不同的模型。将原始模型
y=a*(x^b)
应用两侧的对数,您将得到
log(y)=log(a)+b*log(x)
。因此,对数比例中的模型应该简单地读取
y'=a'+b*x'
,其中素数表示对数比例中的变量。该模型现在是一个线性函数,这是一个众所周知的结果,即所有幂律都成为对数中的线性函数


这就是说,您仍然可以期望两种拟合版本之间存在一些小的差异,因为
curve\u fit
将优化最小二乘问题。因此,在对数尺度下,拟合将最小化拟合和数据之间的相对误差,而在线性尺度下,拟合将最小化绝对误差。因此,为了决定哪种方法实际上更适合您的拟合,您必须估计数据中的误差。您显示的数据在对数刻度中肯定没有恒定的不确定性,因此在线性刻度上,您的拟合可能更可靠。如果每个数据点的错误都是已知的,那么你可以考虑使用<代码> sigma < /Cord>参数。如果正确使用这一方法,这两种方法应该没有太大区别。在这种情况下,我更喜欢对数比例拟合,因为模型更简单,因此可能在数值上更稳定。

您将幂律模型转换为对数是错误的,即您的第二次拟合实际上适合不同的模型。将原始模型
y=a*(x^b)
应用两侧的对数,您将得到
log(y)=log(a)+b*log(x)
。因此,对数比例中的模型应该简单地读取
y'=a'+b*x'
,其中素数表示对数比例中的变量。该模型现在是一个线性函数,这是一个众所周知的结果,即所有幂律都成为对数中的线性函数

也就是说,你仍然可以期待一些小的差异