Повышение эффективности ThymeBoost

Фреймворк ThymeBoost, по своей сути, представляет собой просто алгоритм повышения градиента, основанный на стандартных методах временных рядов. Это означает, что инфраструктура в значительной степени зависит от эффективности и скорости базового метода. Повышение и дополнительная логика добавляют, как мы увидим в этой статье, не только точность, но и вычисление. Большая часть этой тяжелой работы ранее выполнялась с помощью StatsModels для таких вещей, как ETS и ARIMA, но использование пакета статистического прогнозирования Nixtla: StatsForecast может повысить и скорость, и точность. Создание ThymeBoost и StatsForecast идеального союза для прогнозирования временных рядов.

Хороший TLDR для этой статьи:

StatsForecast быстрее, чем StatsModels, а ThymeBoost обеспечивает точность увеличения.

Github для ThymeBoost

Введение

Во-первых, если вы еще не слышали о ThymeBoost, я рекомендую вам ознакомиться с моей предыдущей статьей, в которой представлен достойный обзор. В новейшей версии я добавил StatsForecast в качестве дополнительной зависимости. Чтобы запустить эти примеры, вам необходимо установить его:

pip install StatsForecast

И на всякий случай обновите ThymeBoost:

pip install ThymeBoost --upgrade

Теперь, когда мы это убрали, основной мясо и картошка этой статьи будет бенчмаркинг на наборе данных Weekly M4, чтобы увидеть, как все эти модели работают как по точности, так и по скорости. Все наборы данных с открытым исходным кодом и живут на M-соревнованиях github. Он разделен на стандартные поезда и тесты, поэтому мы будем использовать CSV-файл поезда для подбора, а тестовый CSV-файл — только для оценки с помощью SMAPE.

Не стесняйтесь проверить это с другими наборами данных и дайте мне знать, как они работают!

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

Сравнительный анализ методов

Для начала мы попробуем наиболее ресурсоемкий метод в ThymeBoost: AutoArima. Раньше это делалось с PmdArima, теперь мы можем протестировать с помощью StatsForecast, просто передав trend_estimator=‘fast_arima’ при настройке с ThymeBoost. Давайте взглянем на некоторый код, в котором мы сначала создаем наш набор данных, а затем запускаем ThymeBoost:

from tqdm import tqdm
from statsforecast.models import ETS, AutoARIMA
from ThymeBoost import ThymeBoost as tb
tqdm.pandas()
train_df = pd.read_csv(r'm4-weekly-train.csv')
test_df = pd.read_csv(r'm4-weekly-test.csv')
forecast_horizon = len(test_df.columns) - 1
train_df = train_df.rename({'V1': 'ID'}, axis=1)
train_long = pd.wide_to_long(train_df, ['V'], 'ID', 'Date')
test_df = test_df.rename({'V1': 'ID'}, axis=1)
test_df = pd.wide_to_long(test_df, ['V'], 'ID', 'Date')
train_long = train_long.dropna()
train_df = train_long.reset_index()
train_df.index = train_df['ID']
train_df = train_df.drop('ID', axis = 1)
X = train_long
X = X.reset_index()
  • Примечание: этот код, вероятно, очень неэффективен при манипулировании данными, и я уверен, что есть лучшие способы сделать это, это было просто то, что я собрал вместе, и это работает для теста. Время не включает время, необходимое для запуска этого кода.

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

def grouped_forecast(df):
    y = df['V'].values
    boosted_model = tb.ThymeBoost(verbose=0)
    output = boosted_model.fit(y,
                               seasonal_period=None,
                               trend_estimator=['fast_arima'])
    predicted_output = boosted_model.predict(output,
                                              forecast_horizon,
                                              trend_penalty=True)
    predictions = predicted_output['predictions']
    return predictions

Здесь мы просто создаем функцию, которая будет передана, когда мы выполним группировку и применим:

def counter(df):
    df['counter'] = np.arange(2, len(df) + 2)
    return df
predictions = X.groupby('ID').progress_apply(grouped_forecast)
predictions = predictions.reset_index()
predictions = predictions.groupby('ID').apply(counter)
test_df = test_df.reset_index()
benchmark_df = predictions.merge(test_df, left_on=['ID', 'counter'],
                                 right_on=['ID', 'Date'])
def smape(A, F):
    return 100/len(A) * np.sum(2 * np.abs(F - A) / (np.abs(A) + np.abs(F)))
tqdm.pandas()
def grouped_smape(df):
    return smape(df['V'], df['predictions'])
test = benchmark_df.groupby('ID').progress_apply(grouped_smape)
print(np.mean(test))

Затем мы просто получаем среднее значение SMAPE для заданных результатов, здесь все должно быть хорошо, но дайте мне знать, если есть какие-либо ошибки, которые могут исказить тест.

Это даст вам среднее значение SMAPE 8,61 и займет примерно 10 минут.

Далее, давайте просто запустим Auto Arima от Nixtla и посмотрим, как она работает.

Мы просто изменим эту функцию прогноза groupby на:

def grouped_forecast(df):
    y = df['V'].values
    ar_model = AutoARIMA().fit(y)
    predictions = pd.DataFrame(ar_model.predict(forecast_horizon)['mean'],
                                columns=['predictions'])
    return predictions

Повторный запуск приведенного выше фрагмента расчета SMAPE даст вам SMAPE 8,93 и время примерно 4 минуты.

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

Следующий шаг должен быть очевиден. Мы рассмотрели «быстрый» Auto-Arimain ThymeBoost, а также Auto-Arima без бустинга от StatsForecast. Далее мы должны увидеть, как они сочетаются с использованием Auto-Arimain ThymeBoost от PmdArima.

Если вы использовали этот код до сих пор, пристегнитесь.

Этот следующий бит займет некоторое время…

def grouped_forecast(df):
    y = df['V'].values
    boosted_model = tb.ThymeBoost(verbose=0, n_rounds=None)
    output = boosted_model.fit(y,
                               seasonal_period=None,
                               trend_estimator=['arima'],
                               arima_order='auto')
    predicted_output = boosted_model.predict(output,
                                              forecast_horizon,
                                              trend_penalty=True)
    predictions = predicted_output['predictions']
    return predictions

А результаты?

SMAPE 8,78, но это заняло 90 минут. Похоже, что ускорение Pmd Arima превосходит StatsForecast от Nixtla из коробки, но это занимает довольно много времени.

Arima — это не все предложения в StatsForecast, другая реализация — это метод ETS. С этими новыми методами мы действительно можем использовать эти более быстрые реализации в методе autofit ThymeBoost. Для этого нам просто нужно передать fast=True при вызове autofit. Тогда новая функция прогноза будет выглядеть так:

def grouped_forecast(df):
    y = df['V'].values
    boosted_model = tb.ThymeBoost(verbose=0, n_rounds=None)
    output = boosted_model.autofit(y,
                                    seasonal_period=[52],
                                    optimization_type='grid_search',
                                    optimization_strategy='holdout',
                                    lag=26,
                                    optimization_metric='smape',
                                    verbose=False,
                                    fast=False
                                )
    predicted_output = boosted_model.predict(output,
                                              forecast_horizon,
                                              trend_penalty=True)
    predictions = predicted_output['predictions']
    return predictions

Это приводит к SMAPE 7,88 и занимает около 80 минут. Определенно лучшая точность plug-and-play из всех протестированных, но мы немного жульничаем, выбирая модель.

Следует отметить, что передавать сезонную длину 52 в методы StatsForecast — не лучшая идея. Для ETS это ошибки, а для Auto-Arima это занимает слишком много времени. Это одна из областей, в которой использование преимуществ работы ThymeBoost на самом деле увеличивает скорость, поскольку длительные сезонные периоды в настройке ARIMA занимают значительно больше времени.

Были протестированы несколько других методов, и вы можете просмотреть результаты тестов ниже:

Что касается аббревиатур:

  1. ТБ: ThymeBoost
  2. СФ: СтатистикаПрогноз
  3. NS: Несезонный
  4. Mult: Мультипликативная сезонность
  5. Быстро: ThymeBoost использует StatsForecast под капотом

На высоком уровне лучше всего работает метод Fast AutoFit от ThymeBoost. По какой-то странной причине использование ThymeBoost с сезонностью и быстрой Arima работает не слишком хорошо, фактически это значительно хуже, чем использование Auto-Arima PmdArima. Еще одно наблюдение заключается в том, что усиление простых методов ETS из StatsForecast может ухудшить точность по сравнению с обычной подгонкой с помощью методов без повышения. Это может измениться, если мы изменим параметр global_cost в функции подгонки, поскольку значение по умолчанию может не всегда быть оптимальным.

Заключение

В новейшей версии ThymeBoost есть дополнительные возможности для использования методов StatsForecast. Благодаря этому мы можем увидеть повышенную скорость и, возможно, точность по сравнению с предыдущей реализацией.

Как и в случае с хорошим пирогом, в основе ThymeBoost должно быть хорошее тесто. StatsForecast может быть лучшим тестом, чем StatsModels. Повышение градиента — это просто посыпка сверху.

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