我使用此代码通过使用scipy.optimize.curve_fit
:
def smooth_data_v1(x_arr,y_arr):
def func(x, a, b, c):
return a*np.exp(-b*x)+c
#Scale data
y = y_orig / 10000.0
x = 500.0 * x_orig
popt, pcov = curve_fit(func, x, y, p0=(1, 0.01, 1))
y_smooth = func(x, *popt) # Calcaulate smoothed values for same points
#Undo scaling
y_final = y_smooth * 10000.0
return y_final
我想要估计的指数曲线要经过第一点。
不好的情况:
好案例:
我尝试使用第一个点x0,y0:
删除最后一个参数def smooth_data_v2(x_orig,y_orig):
x0 = x_orig[0]
y0 = y_orig[0]
def func(x, a, b):
return a*np.exp(-b*x)+y0-a*np.exp(-b*x0)
#Scale data
y = y_orig / 10000.0
x = 500.0 * x_orig
popt, pcov = curve_fit(func, x, y, p0=(1, 0.01))
y_smooth = func(x, *popt) # Calcaulate smoothed values for same points
#Undo scaling
y_final = y_smooth * 10000.0
return y_final
如果出了问题我得到了:
a
param真的很大
popt [ 4.45028144e+05 2.74698863e+01]
有什么想法吗?
更新
数据示例
x_orig [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.]
y_orig [ 445057. 447635. 450213. 425089. 391746. 350725. 285433. 269027.
243835. 230587. 216757. 202927. 189097. 175267. 161437.]
答案 0 :(得分:2)
Scipy curve_fit
允许传递参数sigma
,该参数被设计为加权拟合的标准偏差。但是这个数组可以填充任意数据:
from scipy.optimize import curve_fit
def smooth_data_v1(x_arr,y_arr):
def func(x, a, b, c):
return a*np.exp(-b*x)+c
#create the weighting array
y_weight = np.empty(len(y_arr))
#high pseudo-sd values, meaning less weighting in the fit
y_weight.fill(10)
#low values for point 0 and the last points, meaning more weighting during the fit procedure
y_weight[0] = y_weight[-5:-1] = 0.1
popt, pcov = curve_fit(func, x_arr, y_arr, p0=(y_arr[0], 1, 1), sigma = y_weight, absolute_sigma = True)
print("a, b, c:", *popt)
y_smooth = func(x_arr, *popt)
return y_smooth
x_orig = np.asarray([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
y_orig = np.asarray([ 445057, 447635, 450213, 425089, 391746, 350725, 285433, 269027,
243835, 230587, 216757, 202927, 189097, 175267, 161437])
print(smooth_data_v1(x_orig, y_orig))
正如您所看到的,现在第一个和最后一个点接近原始值,但这个"值的钳位"有时会为其余的数据点付出代价
您可能还注意到,我删除了您的重新缩放部分。 Imho,在曲线拟合程序之前不应该这样做。通常最好使用原始数据。此外,您的数据并非由指数函数很好地表示,因此微小的b
值。
答案 1 :(得分:0)
如何更改您尝试适合的功能的定义?
def func(x, a, b, c):
return (y_arr[0] - c)*np.exp(-b*(x - x_arr[0]))+c
根据定义,此函数始终完美地符合第一点,但除此之外可以执行当前函数所做的任何操作。