Интерполяция данных емкости батареи в логарифмической шкале с использованием Python

Вопрос или проблема

Я работаю над интерполяцией данных емкости батареи на основе взаимосвязей между hour_rates, capacities и currents. Вот образец моих данных:

import numpy as np
import pandas as pd
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

capacity_data = [
    [1, 135, 135], [2, 191, 95.63], [3, 221, 73.75],
    [4, 244, 60.94], [5, 263, 52.5], [6, 278, 46.25],
    [8, 300, 37.5], [10, 319, 31.88], [12, 334, 27.81],
    [15, 352, 23.45], [20, 375, 18.75], [24, 386, 16.9],
    [50, 438, 8.76], [72, 459, 6.38], [100, 486, 4.86]
]
capacity = pd.DataFrame(capacity_data, columns=['hour_rates', 'capacities', 'currents'])

Столбцы соотносятся следующим образом:

  • hour_rates (ч) = capacities (Ah) / currents (A)
  • capacities (Ah) = hour_rates (ч) * currents (A)
  • currents (A) = capacities (Ah) / hour_rates (ч)

Цель: Я хочу интерполировать capacities и hour_rates для диапазона значений currents с использованием логарифмической шкалы для лучшей точности.

Код

Пользовательский класс интерполяции и функция для достижения этой цели. Вот код:

from typing import Union

class interpolate1d(interp1d):
    """Расширение scipy interp1d для интерполяции/экстраполяции по осям в логарифмическом пространстве"""

    def __init__(self, x, y, *args, xspace="linear", yspace="linear", **kwargs):
        self.xspace = xspace
        self.yspace = yspace
        if self.xspace == 'log': x = np.log10(x)
        if self.yspace == 'log': y = np.log10(y)
        super().__init__(x, y, *args, **kwargs)

    def __call__(self, x, *args, **kwargs):
        if self.xspace == 'log': x = np.log10(x)
        if self.yspace == 'log':
            return 10**super().__call__(x, *args, **kwargs)
        else:
            return super().__call__(x, *args, **kwargs)

def interpolate_cap_by_current(df: list,
                               current_values: list,
                               kind: Union[str, int] = 'linear',
                               hr_limit: int = 600
                               ):
    """
    Интерполировать значения емкости батареи из списка значений тока
    """
    result = 0
    if isinstance(np_data, np.ndarray):
        # Создание функций интерполяции для часовых норм и емкостей
        # Установка kind='cubic' для лучшего соответствия нелинейным данным
        hour_rate_interp_func = interpolate1d(
            df['currents'],
            df['hour_rates'],
            xspace="log",
            yspace="log",
            fill_value="extrapolate",
            kind=kind
        )
        capacity_interp_func = interpolate1d(
            df['currents'],
            df['capacities'],
            xspace="log",
            yspace="log",
            fill_value="extrapolate",
            kind=kind
        ) # , kind='cubic'

        # Вычисление интерполированных значений для новых токов
        hour_rate_interpolated = hour_rate_interp_func(current_values)
        capacity_interpolated = capacity_interp_func(current_values)

        # Создание DataFrame для результатов
        real_cap = current_values * hour_rate_interpolated
        real_hr = capacity_interpolated / current_values
        result = pd.DataFrame({
            'currents': current_values,
            'hour_rates': hour_rate_interpolated,
            'capacities': capacity_interpolated,
            'calc_cap': real_cap,
            'diff_cap': capacity_interpolated - real_cap,
            'calc_hr': real_hr,
            'diff_hr': hour_rate_interpolated - real_hr,
        })

        result = result[result['hour_rates'] < hr_limit]
    return result

def plot_grid(major_ticks: list,
              minor_ticks: list,
              ):
    """Установка основных меток сетки по оси X"""
    ax=plt.gca()
    ax.grid(True)
    ax.set_xticks(major_ticks)
    ax.set_xticks(minor_ticks, minor=True)
    ax.grid(which="minor", alpha=0.2)
    ax.grid(which="major", alpha=0.5)

Визуализация:

currents_list = np.array([
            0.1, 0.2, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 1.7, 2, 2.2, 2.5,
            3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 17, 20, 22, 25, 27, 30, 32,
            35, 37, 40, 60, 80, 120, 150, 180, 220, 250
        ])
capacities = interpolate_cap_by_current(
    df=capacity,
    current_values=currents_list,
    kind='quadratic'
)
#  linear, nearest, nearest-up, zero, slinear, quadratic, cubic, previous, or next. zero, slinear, quadratic and cubic
plt.figure(figsize=(18, 15))
plt.subplot(3, 1, 1)
plt.plot(capacities['hour_rates'], capacities['capacities'], label="Интерполированная емкость")
plt.plot(capacities['hour_rates'], capacities['calc_cap'], label="Вычисленная емкость")
plt.plot(capacity['hour_rates'], capacity['capacities'], label="Емкость")
plt.ylabel('Емкость (А/ч)')
plt.xlabel('Часовая норма (ч)')
plt.title('Взаимосвязь часовой нормы/емкости батареи')
plt.legend()
max_tick = capacities['hour_rates'].max() + 10
plot_grid(
    major_ticks=np.arange(0, max_tick, 20),
    minor_ticks=np.arange(0, max_tick, 5)
)
plt.subplot(3, 1, 2)
plt.plot(capacities['hour_rates'], capacities['currents'], label="Интерполированный ток (А)")
plt.plot(capacity['hour_rates'], capacity['currents'], label="Ток (А)")
plt.ylabel('Ток (А)')
plt.xlabel('Часовая норма (ч)')
plt.title('Взаимосвязь часовой нормы/тока батареи')
plt.legend()
plot_grid(
    major_ticks=np.arange(0, max_tick, 20),
    minor_ticks=np.arange(0, max_tick, 5)
)
plt.subplot(3, 1, 3)
plt.plot(capacities['currents'], capacities['capacities'], label="Интерполированная емкость / ток")
plt.plot(capacities['currents'], capacities['calc_cap'], label="Вычисленная емкость / ток")
plt.plot(capacity['currents'], capacity['capacities'], label="емкость / ток")
plt.ylabel('Емкость (А/ч)')
plt.xlabel('Ток (А)')
plt.title('Взаимосвязь тока/емкости батареи')
plt.xscale('linear')
plt.yscale('linear')
plt.legend()
max_tick = capacities['currents'].max() + 10
plot_grid(
    major_ticks=np.arange(0, max_tick, 20),
    minor_ticks=np.arange(0, max_tick, 5)
)

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

Проблема

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

plt.figure(figsize=(18, 15))
plt.subplot(3, 1, 1)
plt.plot(capacities['hour_rates'], capacities['diff_cap'], label="Разница в емкости")
plt.plot(capacities['hour_rates'], capacities['diff_hr'], label="Разница в часовой норме")
plt.ylabel('Разница интерполированного / вычисленного')
plt.xlabel('Часовая норма (ч)')
plt.title('Взаимосвязь данных интерполяции по часовой норме')
plt.legend()
max_tick = capacities['hour_rates'].max() + 10
plot_grid(
    major_ticks=np.arange(0, max_tick, 20),
    minor_ticks=np.arange(0, max_tick, 5)
)
plt.subplot(3, 1, 2)
plt.plot(capacities['capacities'], capacities['diff_cap'], label="Разница в емкости")
plt.plot(capacities['capacities'], capacities['diff_hr'], label="Разница в часовой норме")
plt.ylabel('Разница интерполированного / вычисленного')
plt.xlabel('Емкость (А/ч)')
plt.title('Взаимосвязь данных интерполяции по емкости')
plt.legend()
max_tick = capacities['capacities'].max() + 10
plot_grid(
    major_ticks=np.arange(0, max_tick, 20),
    minor_ticks=np.arange(0, max_tick, 5)
)
plt.subplot(3, 1, 3)
plt.plot(capacities['currents'], capacities['diff_cap'], label="Разница в емкости")
plt.plot(capacities['currents'], capacities['diff_hr'], label="Разница в часовой норме")
plt.ylabel('Разница интерполированного / вычисленного')
plt.xlabel('Ток (А)')
plt.title('Взаимосвязь данных интерполяции по току')
plt.legend()
max_tick = capacities['currents'].max() + 10
plot_grid(
    major_ticks=np.arange(0, max_tick, 20),
    minor_ticks=np.arange(0, max_tick, 5)
)

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

Есть ли способ улучшить точность интерполяции на логарифмической шкале для такого типа взаимосвязей данных? Я понимаю, что значения тока вне диапазона (4.86 А, 135 А) могут привести к неточным результатам из-за экстраполяции. Тем не менее, я замечаю неточности в пределах диапазона, особенно между 5 А и 25 А. Почему интерполированные значения в этом диапазоне могут быть неправильными?

Ответ или решение

Интерполяция данных ёмкости аккумуляторов с использованием логарифмической шкалы в Python

Работа с данными ёмкости аккумуляторов требует точности и аккуратности, особенно при интерполяции значений, основанных на соотношениях между такими переменными, как hour_rates (часы разряда), capacities (ёмкость) и currents (токи). В данном случае возникли проблемы, связанные с тем, что интерполированные значения не совпадают с рассчитанными, даже с использованием логарифмической шкалы. Давайте подробно рассмотрим эту задачу и предложим возможные пути её решения.

Исходные данные

Ваши исходные данные представлены в таком формате:

capacity_data = [
    [1, 135, 135], [2, 191, 95.63], [3, 221, 73.75],
    [4, 244, 60.94], [5, 263, 52.5], [6, 278, 46.25],
    [8, 300, 37.5], [10, 319, 31.88], [12, 334, 27.81],
    [15, 352, 23.45], [20, 375, 18.75], [24, 386, 16.9],
    [50, 438, 8.76], [72, 459, 6.38], [100, 486, 4.86]
]
Переменные данных и их отношения
  • hour_rates (h): показывает, как долго аккумулятор разряжается.
  • capacities (Ah): ёмкость аккумулятора.
  • currents (A): ток, при котором происходит разрядка.

Используя эти данные, можно вывести формулы, которые связывают эти переменные:

  1. hour_rates = capacities / currents
  2. capacities = hour_rates * currents
  3. currents = capacities / hour_rates

Цель

Основная цель заключается в интерполяции значений capacities и hour_rates для заданного диапазона значений currents с использованием логарифмической шкалы для повышения точности.

Код интерполяции

Для выполнения этой задачи вы создали расширенный класс interpolate1d, который помогает интерполировать значения в логарифмическом пространстве, вот как выглядит часть важного кода:

class interpolate1d(interp1d):
    """Расширенный класс interp1d для интерполяции в логарифмическом пространстве"""

    def __init__(self, x, y, *args, xspace="linear", yspace="linear", **kwargs):
        self.xspace = xspace
        self.yspace = yspace
        if self.xspace == 'log': x = np.log10(x)
        if self.yspace == 'log': y = np.log10(y)
        super().__init__(x, y, *args, **kwargs)

    def __call__(self, x, *args, **kwargs):
        if self.xspace == 'log': x = np.log10(x)
        if self.yspace == 'log':
            return 10**super().__call__(x, *args, **kwargs)
        else:
            return super().__call__(x, *args, **kwargs)

Проблема с интерполяцией

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

  1. Неправильный выбор метода интерполяции: Попробуйте использовать другие методы интерполяции, такие как cubic или quadratic, поскольку ваши данные могут быть нелинейными в этом диапазоне.

  2. Проблемы с экстраполяцией: Убедитесь, что значения токов не выходят за пределы диапазона ваших исходных данных. Экстраполяция может привести к несоответствиям.

  3. Неверная логика в расчетах: Проверьте, достаточно ли точно вы рассчитываете capacities и hour_rates из интерполированных значений, используя исходные соотношения.

Рекомендации по улучшению точности интерполяции

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

  2. Проверка диапазона данных: Ограничьте значения токов, которые вы интерполируете, теми, которые находятся в пределах вашего набора данных.

  3. Анализ ошибок: После интерполяции проводите анализ ошибок между интерполированными и рассчитанными значениями. Это поможет вам понять, в каких конкретных областях возникают проблемы.

  4. Графическое представление: Визуализация ваших данных может помочь выявить области слабой точности и улучшить настройки интерполяции.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...