Выбор метода интерполяции и экстраполяции
Есть задача выбора аккумуляторной батареи по требуемому времени работы и мощности. Первый шаг — рассчитать мощность по заданному времени исходя из таблицы разрядных характеристик. Для этого нужно интерполировать данные в заданном диапазоне и экстраполировать за пределами имеющихся данных. У меня два вопроса.
- Какой из методов интерполяции даст наиболее точный результат?
- Как экстраполировать данные? Метод UnivariateSpline дает неадекватные результаты. При k=1 линейно уходит в отрицательные значения, чего не может быть. При k>=2 круто улетает вверх.
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy
from scipy import interpolate
from scipy.interpolate import UnivariateSpline
values = [
[5, 5016],
[8, 4452.6],
[10, 3600.0],
[15, 3018.0],
[20, 2424.0],
[30, 1914.0],
[60, 1080.0],
[90, 742.2]
]
data = pd.DataFrame(values, columns=['time','power'])
xp = data.loc[:, 'time']
yp = data.loc[:, 'power']
#display(xp)
# 1 способ интерполяции (кусочно-линейная)
x1 = 45
t1 = np.interp(x1, xp, yp)
print(t1)
# 2 способ интерполяции (kind=2 - параболическая)
f = interpolate.interp1d(xp, yp, kind=2)
t2 = f(x1)
print(t2)
xr = np.linspace(5,90,25)
# Экстраполяция
extrapolator = UnivariateSpline(xp, yp, k=2)
print(extrapolator(180))
# plt.axes(ylim=(t1-800,t1+500),xlim=(x1-10,x1+30))
plt.plot(xp,yp, 'p')
plt.plot(xp,yp, 'r')
plt.plot(x1,t1, 'x')
plt.plot(x1,t2, 'rx')
plt.plot(xr,f(xr))
xs = np.linspace(5,180,25)
plt.plot(xs, extrapolator(xs), '-')
UPD.
Тут скорее всего будет экспоненциальная зависимость. Попробовал такой вариант:
def func(x, a, b, c):
return a * np.exp(-b * x) + c
popt, pcov = curve_fit(func, xp, yp)
plt.plot(xs, func(xs, *popt), 'r-')
Это больше похоже на правду, но получается слишком медленное затухание функции. Что касается физической модели. То тут вряд ли будет сигмоида, скорее экспоненциальная зависимость.
Семейство кривых при разряде постоянной мощностью.

Ответы (1 шт):
Эта задача не решается экстраполяцией. Необходимо сначала из физических соображений подобрать функцию разряда, и только после того, как выбрана физическая модель, аппроксимировать параметры модели.
Вот график разряда в зависимости от времени и температуры. Видно невооруженным глазом, что никакие сплайны, интерполяционные полиномы и прочие математические трюки не в состоянии предсказать падение тока вблизи максимального разряда.
Если вы не знаете физическую модель явления, то нужно что-то придумать. Например, ткнуть пальцем в потолок и провозгласить: "Функция разряда от времени должна быть обратной сигмоидной".
Ткнув пальцем второй раз, можно выбрать из всех сигмодных обратную логистическую: p = pwr_avg + theta*np.log(t_max/t - 1)
У неё вот такой график:
Для подбора параметров есть функция scipy.optimize.curve_fit
import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as spo
values = np.array([
[5, 5016],
[8, 4452.6],
[10, 3600.0],
[15, 3018.0],
[20, 2424.0],
[30, 1914.0],
[60, 1080.0],
[90, 742.2]
])
def model2(t, theta, t_max, pwr_avg, dt=0):
tau = t+dt
return pwr_avg + theta*np.log(t_max/tau-1)
params, pcov = spo.curve_fit(model2, values[:,0], values[:,1],
p0=(1000, 200, 600, 10), maxfev=10000,
bounds=((800,200,400,0), (2000,2000,1000, 100)))
p = np.linspace(0,2000, 1000)
plt.plot(values[:,0], values[:,1])
plt.plot(p, model2(p, *params))
Результат вот такой:
Понятное дело, приближение корявое, но ведь и модель взята с потолка. Чем лучше физическая модель, тем лучше результат.




