如何强制scipy.optimize.curve_fit解决第一点? [英] How to force scipy.optimize.curve_fit fix first point?

查看:64
本文介绍了如何强制scipy.optimize.curve_fit解决第一点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用此代码通过将指数与 scipy.optimize.curve_fit 拟合来平滑数据:

I use this code for smoothing data by fitting exponent with 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我希望估计的指数曲线经过第一个点.

Howewer I want estimated exponent curve to go through 1st point.

坏情况:

很好的情况:

我尝试使用第一个点x0,y0删除最后一个参数:

I have tried to remove last parameter using first point 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 something go wrong and I get:

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 ,该参数被设计为加权拟合的标准偏差.但是此数组可以填充任意数据:

Scipy curve_fit allows for passing the parameter sigma, which is designed to be the standard deviation for weighting the fit. But this array can be filled with arbitrary data:

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 值.

As you can see, now the first and last point are close to the original values, but this "clamping of values" comes sometimes at a price for the rest of the data points.
You have probably also noticed, that I removed your rescaling part. Imho, one shouldn't do this before curve fitting procedures. It is usually better to use raw data. Additionally, your data are not really well represented by an exponential function, hence the tiny b value.

这篇关于如何强制scipy.optimize.curve_fit解决第一点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆