нелинейная подгонка кривой в питоне с двумя переменными - PullRequest
0 голосов
/ 03 декабря 2018

Я пытаюсь определить функцию, которая подходит для входных данных x и y в форме:

def nlvh(x,y, xi, yi, H,C):

    return ((H-xi*C)/8.314)*((1/xi) - x) + (C/8.314)*np.log((1/x)/xi) + np.log(yi)

Данные x и y являются одномерными массивами одинаковой длины.Я хотел бы нарезать данные так, чтобы я мог выбрать первые 5 точек x и y, подогнать их, оптимизировав C и H в модели, а затем переместиться на одну точку вперед и повторить.У меня есть некоторый код, который делает это для линейного подбора по одним и тем же данным:

for i in np.arange(len(x)):
    xdata = x[i:i + window]
    ydata = y[i:i+window]
    a[i], b[i] = np.polyfit(xdata, ydata,1)
    xdata_avg[i] = np.mean(xdata)
    if i == (lenx - window):
        break

, но делать то же самое с уравнением, определенным выше, кажется немного сложнее.x и y отображаются как независимые и зависимые переменные, но есть также параметры xo и yo, которые являются первыми значениями x и y в каждом окне.

Конечный результат, который я хотел бы получить, - это два новых массива с H [i] и C [i], где i обозначает каждое последующее окно.Кто-нибудь знает, как мне начать?

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

После вашего комментария к моему предыдущему ответу (где вы предположили, что вам нужно, чтобы xi и yi были начальными значениями в каждом "нарезанном" x и y массивах), я добавляю еще один ответ,Этот ответ вводит изменение в функцию nlvh и достигает именно того, что вы хотите.Как и мой предыдущий ответ, мы будем использовать curve_fit из scipy.optimize .

В приведенном ниже коде я использую globals () Функция из Python для определения xi и yi.Для каждого нарезанного массива x и y, xi и yi сохраняют первое значение соответствующих нарезанных массивов.Это обновленный код:

from __future__ import division #For decimal division.
import numpy as np
from scipy.optimize import curve_fit

def nlvh(x, H, C):
    return ((H-xi*C)/8.314)*((1/xi) - x) + (C/8.314)*np.log((1/x)/xi) + np.log(yi)

xdata = np.arange(1,21) #Choose an array for x.

#Choose an array for y.
ydata = np.array([-0.1404996,  -0.04353953,  0.35002257,  0.12939468, -0.34259184, -0.2906065,
     -0.37508709, -0.41583238, -0.511851,   -0.39465581, -0.32631751, -0.34403938,
     -0.592997,   -0.34312689, -0.4838437,  -0.19311436, -0.20962735, -0.31134191, 
     -0.09487793, -0.55578775])


H_lst, C_lst = [], []
for i in range( len(xdata)-5 ):
    #Select 5 consecutive points of xdata (from index i to i+4).
    xnew = xdata[i: i+5]
    globals()['xi'] = xnew[0]

    #Select 5 consecutive points of ydata (from index i to i+4).
    ynew = ydata[i: i+5]
    globals()['yi'] = ynew[0]  

    #Fit function nlvh to data using scipy.optimize.curve_fit
    popt, pcov = curve_fit(nlvh, xnew, ynew, maxfev=100000)

    #Optimal values for H from minimization of sum of the squared residuals.
    H_lst += [popt[0]] 

    #Optimal values for C from minimization of sum of the squared residuals.
    C_lst += [popt[1]] 

H_arr, C_arr = np.asarray(H_lst), np.asarray(C_lst) #Convert list to numpy arrays.

Ваш вывод для H_arr и C_arr теперь будет следующим:

print H_arr 
>>>[1.0, 1.0, -23.041138662879327, -34.58915200575536, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

print C_arr
>>>[1.0, 1.0, -8.795855063863234, -9.271561975595562, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

Ниже приведены графики, которые вы получаете для данныхвыбранное выше (xdata, ydata).

Plot of parameter H Plot of parameter C

0 голосов
/ 03 декабря 2018

Вы можете использовать curve_fit из scipy.optimize .Он будет использовать нелинейные наименьшие квадраты для подгонки параметров (H, C, xi, yi) вашей функции nlvh к заданным входным данным для x и y.

Попробуйте следующий код.В приведенном ниже коде H_arr и C_arr являются массивами-пустышками, которые содержат параметры подгонки H и C соответственно, когда функция nlvh установлена ​​на окнах из 5 последовательных точек xdata и ydata (xdata и ydata - это массивы, которые я выбрал для x и y. Здесь вы можете выбрать различные массивы.)

from __future__ import division #For decimal division.
import numpy as np
from scipy.optimize import curve_fit

def nlvh(x, H, C, xi, yi):
    return ((H-xi*C)/8.314)*((1/xi) - x) + (C/8.314)*np.log((1/x)/xi) + np.log(yi)

xdata = np.arange(1,21) #Choose an array for x

#Find an array yy for chosen values of parameters (H, C, xi, yi)
yy = nlvh(xdata, H=1.0, C=1.0, xi=1.0, yi=1.0)  

print yy
>>>[ 0. -0.08337108 -0.13214004 -0.16674217 -0.19358166 -0.21551112 -0.23405222 -0.25011325 -0.26428008 -0.27695274 -0.28841656 -0.2988822 -0.30850967 -0.3174233  -0.3257217  -0.33348433 -0.3407762 -0.34765116 -0.35415432 -0.36032382]

#Add noise to the initally chosen array yy.
y_noise = 0.2 * np.random.normal(size=xdata.size)
ydata = yy + y_noise    

print ydata

>>>[-0.1404996  -0.04353953  0.35002257  0.12939468 -0.34259184 -0.2906065 -0.37508709 -0.41583238 -0.511851   -0.39465581 -0.32631751 -0.34403938 -0.592997   -0.34312689 -0.4838437  -0.19311436 -0.20962735 -0.31134191-0.09487793 -0.55578775]

H_lst, C_lst = [], []
for i in range( len(xdata)-5 ):
    #Select 5 consecutive points of xdata (from index i to i+4).
    xnew = xdata[i: i+5]

    #Select 5 consecutive points of ydata (from index i to i+4).
    ynew = ydata[i: i+5]

    #Fit function nlvh to data using scipy.optimize.curve_fit
    popt, pcov = curve_fit(nlvh, xnew, ynew, maxfev=100000)

    #Optimal values for H from minimization of sum of the squared residuals.
    H_lst += [popt[0]] 

    #Optimal values for C from minimization of sum of the squared residuals.
    C_lst += [popt[1]]   

H_arr, C_arr = np.asarray(H_lst), np.asarray(C_lst) #Convert list to numpy arrays.

Ниже будет ваш вывод H_arrи C_arr для выбранных значений xdata и ydata.

print H_arr

>>>[ -11.5317468   -18.44101926   20.30837781   31.47360697  -14.45018355 24.17226837   39.96761325   15.28776756 -113.15255865   15.71324201 51.56631241  159.38292301  -28.2429133   -60.97509922  -89.48216973]

print C_arr

>>>[0.70339652 0.34734507 0.2664654  0.2062776  0.30740565 0.19066498 0.1812445  0.30169133 0.11654544 0.21882872 0.11852967 0.09968506 0.2288574  0.128909   0.11658227]
...