Поскольку ваши данные показывают разное поведение в разных регионах, вам также необходимо подогнать данные по этим различным регионам.То есть вместо того, чтобы суммировать две модели (функции), вы должны поместить одну левую область с y = m*x + c
и отдельно в правую область с y = d*exp(-k*x)
.Если у вас возникли проблемы с поиском границы двух областей, вы можете оценить это, сравнив добротность соответствия .
popt_1, pcov_1 = curve_fit(lambda x, m, c: m*x + c, t[t < 0.8], y[t < 0.8], p0=(1, 0))
popt_2, pcov_2 = curve_fit(lambda x, d, k: d*exp(-k*x), t[t >= 0.8], y[t >= 0.8], p0=(400, 1))
Редактировать
Пример кода:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy.optimize import curve_fit
df = pd.read_csv('test.csv', index_col=None)
t = df.t.values
y = df.Y.values
boundary = t[y.argmax()]
t1 = t[t < boundary]
y1 = y[t < boundary]
t2 = t[t >= boundary]
y2 = y[t >= boundary]
f1 = lambda x, m, c: m*x + c
f2 = lambda x, d, k: d*np.exp(-k*x)
popt_1 ,pcov_1 = curve_fit(f1, t1, y1, p0=((y1[-1] - y1[0]) / (t1[-1] - t1[0]), y1[0]))
popt_2 ,pcov_2 = curve_fit(f2, t2, y2, p0=(y2[0], 1))
plt.title('Fitted data on two different domains')
plt.xlabel('t [a.u.]')
plt.ylabel('y [a.u.]')
plt.plot(t, y, '-o', label='Data')
plt.plot(t1, f1(t1, *popt_1), '--', color='#ff7f0e', lw=3, label='Fit')
plt.plot(t2, f2(t2, *popt_2), '--', color='#ff7f0e', lw=3, label='_nolegend_')
plt.grid()
plt.legend()
plt.show()
, который дает следующий график:
Обратите внимание, что результирующая «составная» функция не является непрерывной на границе.Если это нежелательно, вы можете разрешить его, установив один из подходящих параметров (например, k
), прежде чем подгонять другой домен (так или иначе).В качестве альтернативы вы можете подогнать обе области по отдельности, а затем определить значение на границе как среднее значение двух отдельных функций (т. Е. y_b = (f1(t1[-1], *popt_1) + f2(t2[0], *popt_2)) / 2
), а затем повторить подгонку, ограничив параметры так, чтобы это граничное условие выполнялось.
Например, сначала подгонка линейной функции, а затем фиксация параметра d
экспоненты для непрерывного перехода на границе (обратите внимание, что линейная функция f1
является экстраполированной вне ее областина t2[0]
для обеспечения непрерывности):
f1 = lambda x, m, c: m*x + c
popt_1, pcov_1 = curve_fit(f1, t1, y1, p0=((y1[-1] - y1[0]) / (t1[-1] - t1[0]), y1[0]))
d = f1(t2[0], *popt_1)
f2 = lambda x, k: d*np.exp(-k*(x - boundary))
popt_2, pcov_2 = curve_fit(f2, t2, y2, p0=(1,))
, что дает следующий график: