Выбор метода интерполяции и экстраполяции

Есть задача выбора аккумуляторной батареи по требуемому времени работы и мощности. Первый шаг — рассчитать мощность по заданному времени исходя из таблицы разрядных характеристик. Для этого нужно интерполировать данные в заданном диапазоне и экстраполировать за пределами имеющихся данных. У меня два вопроса.

  1. Какой из методов интерполяции даст наиболее точный результат?
  2. Как экстраполировать данные? Метод 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 шт):

Автор решения: Pak Uula

Эта задача не решается экстраполяцией. Необходимо сначала из физических соображений подобрать функцию разряда, и только после того, как выбрана физическая модель, аппроксимировать параметры модели.

введите сюда описание изображения

Вот график разряда в зависимости от времени и температуры. Видно невооруженным глазом, что никакие сплайны, интерполяционные полиномы и прочие математические трюки не в состоянии предсказать падение тока вблизи максимального разряда.

Если вы не знаете физическую модель явления, то нужно что-то придумать. Например, ткнуть пальцем в потолок и провозгласить: "Функция разряда от времени должна быть обратной сигмоидной".

Ткнув пальцем второй раз, можно выбрать из всех сигмодных обратную логистическую: 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))

Результат вот такой:

введите сюда описание изображения

Понятное дело, приближение корявое, но ведь и модель взята с потолка. Чем лучше физическая модель, тем лучше результат.

→ Ссылка