使用 Numpy Polyfit 进行曲线拟合,使用平方根估计函数常数
Curve Fitting using Numpy Polyfit, estimate constant on function with Square Root
首先,抱歉我的英语不好,感谢您点击这个问题。
我已经有 x 和 y 数据集,所以我想用我的数据集做曲线拟合。
估计模型是
那么我如何通过 polyfit 估计这个模型的常量?
我知道
np.polyfit(x,y,1)
表示线性方程估计。 (1 表示线性)
但是我如何使用另一个等式(例如具有三个或更多常量的平方根)对我的数据集进行估算。
你想做的是
a*np.sqrt(x-b) + c ~ y
<=> np.sqrt(x-b) ~ (y-c)/a # not entirely true, but close
<=> x - b ~ (y/a - c/a)**2
<=> x ~ (y/a - c/a)** 2 + b
最后一行表示将x
近似为y
中的二次多项式。所以
np.polyfit(y,x, 2)
您可以使用 scipy.optimize.curve_fit
,这里是一个如何执行此操作的示例
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x,a,b,c):
return a * np.sqrt(x - b) + c
x = np.linspace(2,20,100)
y = func(x,2,-2,3)
y_true = y + 0.1*np.random.normal(size=len(x))
popt, pcov = curve_fit(func,x,y_true)
y_pred = func(x,*popt)
fig,ax = plt.subplots(figsize=(8,6))
ax.scatter(x,y_true,c='r',label='true',s=6)
ax.plot(x,y_pred,c='g',label='pred')
ax.legend(loc='best')
这会给你
数组 popt
是 (a,b,c)
个值的列表。
更新
在使用 reaver lover 提供的真实数据集测试 curve_fit
后,我惊讶地发现 curve_fit
可以在这个相对简单的回归任务上失败。
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x,a,b,c):
print('%.3f, %.3f, %.3f' % (a,b,c))
return a * np.sqrt(x - b) + c
x = np.array([5, 11, 15, 44, 60, 70, 75, 100, 120, 200])
y_true = np.array([2.492, 8.330, 11.000, 19.394, 24.466, 27.777, 29.878, 26.952, 35.607, 46.966])
popt, pcov = curve_fit(func,x,y_true)
popt = [2.252, 5.000, 6.908]
y_pred = func(x,*popt)
fig,ax = plt.subplots(figsize=(8,6))
ax.scatter(x,y_true,c='r',label='true',s=6)
ax.plot(x,y_pred,c='g',label='pred')
ax.legend(loc='best')
运行 这个脚本,你会发现系数列表 (a,b,c)
不知何故在优化接近尾声时变成了 (nan,nan,nan)
。然而,curve_fit
找到的最后一个 (a,b,c)
不是 (nan,nan,nan)
已经足够好了,正如你在图中看到的
我真的不知道为什么 curve_fit
会失败。
首先,抱歉我的英语不好,感谢您点击这个问题。
我已经有 x 和 y 数据集,所以我想用我的数据集做曲线拟合。
估计模型是
那么我如何通过 polyfit 估计这个模型的常量?
我知道
np.polyfit(x,y,1)
表示线性方程估计。 (1 表示线性)
但是我如何使用另一个等式(例如具有三个或更多常量的平方根)对我的数据集进行估算。
你想做的是
a*np.sqrt(x-b) + c ~ y
<=> np.sqrt(x-b) ~ (y-c)/a # not entirely true, but close
<=> x - b ~ (y/a - c/a)**2
<=> x ~ (y/a - c/a)** 2 + b
最后一行表示将x
近似为y
中的二次多项式。所以
np.polyfit(y,x, 2)
您可以使用 scipy.optimize.curve_fit
,这里是一个如何执行此操作的示例
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x,a,b,c):
return a * np.sqrt(x - b) + c
x = np.linspace(2,20,100)
y = func(x,2,-2,3)
y_true = y + 0.1*np.random.normal(size=len(x))
popt, pcov = curve_fit(func,x,y_true)
y_pred = func(x,*popt)
fig,ax = plt.subplots(figsize=(8,6))
ax.scatter(x,y_true,c='r',label='true',s=6)
ax.plot(x,y_pred,c='g',label='pred')
ax.legend(loc='best')
这会给你
数组 popt
是 (a,b,c)
个值的列表。
更新
在使用 reaver lover 提供的真实数据集测试 curve_fit
后,我惊讶地发现 curve_fit
可以在这个相对简单的回归任务上失败。
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x,a,b,c):
print('%.3f, %.3f, %.3f' % (a,b,c))
return a * np.sqrt(x - b) + c
x = np.array([5, 11, 15, 44, 60, 70, 75, 100, 120, 200])
y_true = np.array([2.492, 8.330, 11.000, 19.394, 24.466, 27.777, 29.878, 26.952, 35.607, 46.966])
popt, pcov = curve_fit(func,x,y_true)
popt = [2.252, 5.000, 6.908]
y_pred = func(x,*popt)
fig,ax = plt.subplots(figsize=(8,6))
ax.scatter(x,y_true,c='r',label='true',s=6)
ax.plot(x,y_pred,c='g',label='pred')
ax.legend(loc='best')
运行 这个脚本,你会发现系数列表 (a,b,c)
不知何故在优化接近尾声时变成了 (nan,nan,nan)
。然而,curve_fit
找到的最后一个 (a,b,c)
不是 (nan,nan,nan)
已经足够好了,正如你在图中看到的
我真的不知道为什么 curve_fit
会失败。