我使用此代码通过将指数与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


Howewer我想要估计的指数曲线经过第一点。

坏情况:

python - 如何强制scipy.optimize.curve_fit解决第一点?-LMLPHP

好案例:

python - 如何强制scipy.optimize.curve_fit解决第一点?-LMLPHP

我尝试使用第一个点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


Howewer出了点问题,我得到了:

python - 如何强制scipy.optimize.curve_fit解决第一点?-LMLPHP

a参数真的很大
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.]

最佳答案

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))


如您所见,现在的第一个点和最后一个点都接近原始值,但是对于其余的数据点来说,这种“钳位”有时要付出一定的代价。
您可能还注意到,我删除了重新缩放部分。恕我直言,在进行曲线拟合之前,不应该这样做。通常最好使用原始数据。另外,您的数据不能真正用指数函数很好地表示,因此b值很小。

关于python - 如何强制scipy.optimize.curve_fit解决第一点?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49151096/

10-14 08:44