fit multiple parametric curves with scipy

前端 未结 2 913
春和景丽
春和景丽 2021-01-13 14:07

I have a set (at least 3) of curves (xy-data). For each curve the parameters E and T are constant but different. I\'m searching the coefficients a,n and m for the best fit o

2条回答
  •  醉梦人生
    2021-01-13 14:58

    One way to do this is use scipy.optimize.leastsq instead (curve_fit is a convenience wrapper around leastsq).

    Stack the x data in one dimension; ditto for the y data. The lengths of the 3 individual datasets don't even matter; let's call them n1, n2 and n3, so your new x and y will have a shape (n1+n2+n3,).

    Inside the function to optimize, you can split up the data at your convenience. It will not be the nicest function, but this could work:

    def function(x, E, T, a, n, m):
        return x/E + (a/n+1)*T^(n+1)*x^m
    
    def leastsq_function(params, *args):
        a = params[0]
        n = params[1]
        m = params[2]
        x = args[0]
        y = args[1]
        E = args[2]
        T = args[3]
        n1, n2 = args[2]
    
        yfit = np.empty(x.shape)
        yfit[:n1] = function(x[:n1], E[0], T[0], a, n, m)
        yfit[n1:n2] = function(x[n1:n2], E[1], T[1], a, n, m)
        yfit[n2:] = function(x[n2:], E[2], T[2], a, n, m)
    
        return y - yfit
    
    
    params0 = [a0, n0, m0]
    args = (x, y, (E0, E1, E2), (T0, T1, T2), (n1, n1+n2))
    result = scipy.optimize.leastsq(leastsq_function, params0, args=args)
    

    I have not tested this, but this is the principle. You're now splitting up the data into 3 different calls inside the function that is to be optimized.

    Note that scipy.optimize.leastsq simply requires a function that returns whatever value you'd like to be minized, in this case the difference between your actual y data and the fitted function data. The actual important variables in leastsq are the parameters you want to fit for, not the x and y data. The latter are passed as extra arguments, together with the sizes of three separate datasets (I'm not using n3, and I've done some juggling with the n1+n2 for convenience; keep in mind that the n1 and n2 inside leastsq_function are local variables, not the original ones).

    Since this is an awkward function to fit (it probably won't have a smooth derivative, for example), it is quite essential to

    • provide good starting values (params0, so all the ...0 values).

    • don't have data or parameters which span orders of magnitude. The closer everything is around 1 (a few orders of magnitude is certainly ok), the better.

提交回复
热议问题