Уменьшение влияния экстремальных точек с повышением

Весь код живет здесь: ThymeBoost Github

Введение

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

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

Пакет находится в постоянном развитии, поэтому даже если он у вас установлен, есть 100% вероятность того, что на pip есть новая версия!

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

С этим, давайте перейдем к примеру…

Простой пример

Мы смоделируем простой ряд, состоящий из тренда, сезонности и небольшого шума:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('darkgrid')
#Here we will just create a random series with seasonality and a slight trend
seasonality = ((np.cos(np.arange(1, 101))*10 + 50))
np.random.seed(100)
true = np.linspace(-1, 1, 100)
noise = np.random.normal(0, 1, 100)
y = true + seasonality + noise
plt.plot(y)
plt.show()

Добавленный шум дает несколько точек немного больше пика, но в целом здесь ничего не выделяется. Давайте передадим эти данные ThymeBoost, чтобы узнать, что он думает о сериале.

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost()
output = boosted_model.detect_outliers(y,
                                       trend_estimator='linear',
                                       seasonal_estimator='fourier',
                                       seasonal_period=25,
                                       global_cost='maicc',
                                       fit_type='global')
boosted_model.plot_results(output)
boosted_model.plot_components(output)

Здесь мы используем метод «detect_outliers», а не стандартную подгонку. Этот метод действует так же, как метод «подгонки», за исключением того, что он проверяет точки, лежащие за пределами ошибок. Эти границы ошибки будут согласованы только для простых оценок линейного тренда. Если бы вы передали более плавное сглаживание, такое как «ses» (простое экспоненциальное сглаживание), в качестве тренда, то эти границы будут довольно шаткими! Поскольку мы используем простой линейный тренд, мы можем безопасно продолжить и взглянуть на столбец «выбросы», который метод добавил в выходной DataFrame:

Похоже, что ThymeBoost согласен с нашим предыдущим наблюдением: серия работает достаточно хорошо и не содержит отклонений. Добавим один!

y[30] = 100
plt.plot(y)
plt.show()

Теперь, когда у нас есть явный выброс, давайте посмотрим, что произойдет, когда мы дадим его ThymeBoost.

boosted_model = tb.ThymeBoost()
output = boosted_model.detect_outliers(y,
                                       trend_estimator='linear',
                                       seasonal_estimator='fourier',
                                       seasonal_period=25,
                                       global_cost='maicc',
                                       fit_type='global')
boosted_model.plot_results(output)
boosted_model.plot_components(output)

Первое, на что следует обратить внимание, это то, что график «plot_results» теперь имеет красный «X» там, где находится выброс. Если ваш вывод содержит столбец выбросов, он будет использоваться при построении графика. Следующее важное наблюдение заключается в том, что наш сезонный компонент значительно изменяется из-за присутствия этого выброса. Вопрос в том:

Что нам теперь делать?

Как упоминалось ранее, существует множество способов продолжить. Вы можете заменить выбросы средним значением ряда или верхней границей подобранных значений или ничего не делать! Давайте посмотрим, как с этим может справиться ThymeBoost.

Обработка выбросов с помощью столбца выбросов

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

weights = np.invert(output['outliers'].values) * 1

Все, что мы делаем здесь, это берем нашу серию и преобразуем ее в массив, переворачиваем логическое значение с помощью «инвертировать» и умножаем на 1, чтобы преобразовать из True/False в 0/1 целые числа. Результатом является массив, в котором точка данных выброса равна 0, а все остальные точки равны 1. Имея это в виду, мы можем выполнить нормальную подгонку, но передать этот массив в качестве аргумента «seasonality_weights», который дает влияние выброса 0 при расчете сезонности. Примечание. Эти веса необходимо передавать в виде массива и использовать с сезонностью Фурье.

output = boosted_model.fit(y,
                           trend_estimator='linear',
                           seasonal_estimator='fourier',
                           seasonal_period=25,
                           global_cost='maicc',
                           fit_type='global',
                           seasonality_weights=weights)
boosted_model.plot_results(output)
boosted_model.plot_components(output)

Обратите внимание, что красный «X» исчез, потому что мы только что использовали стандартный метод подгонки, но теперь наш сезонный компонент кажется фиксированным. Большой всплеск в нашей подобранной сезонности, который был артефактом выброса, был стерт. Это становится еще яснее, если мы посмотрим на эти сезонные компоненты:

Мы передали веса как 0/1, однако мы могли использовать любые веса, какие захотим. Ноэти веса по-прежнему произвольны. Что, если бы нам нужны веса, которые динамически назначаются в зависимости от того, насколько они далеки от «нормального»?

Это возможно?

Да, посмотрим.

Обработка выбросов с использованием аргумента Regularize

Вместо того, чтобы передавать массив весов, мы могли бы передать строку: «regularize». ThymeBoost теперь будет использовать схему взвешивания, которая будет штрафовать точки данных с более высокими ошибками при аппроксимации сезонности. Это взвешивание в сочетании с несколькими раундами бустинга обеспечивает обработку, аналогичную Iтерационно R взвешенному Lвосточному S. > метод квадратов.

output = boosted_model.fit(y,
                           trend_estimator='linear',
                           seasonal_estimator='fourier',
                           seasonal_period=25,
                           global_cost='maicc',
                           fit_type='global',
                           seasonality_weights='regularize')
boosted_model.plot_components(output)

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

Заключение

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

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