Адаптивная модель экспоненциального сглаживания

Введение

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

Теоретическая часть.

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

Модель вычисляется рекурентной формулой:

$$S_t = \alpha x_t + \beta S_{t-1}$$

где

$S_t$ - значение экспоненциальной средней в момент t

$\alpha$ - параметр сглаживания

$\beta = 1 - \alpha$

Исходя из вышеописанного можно переписать $S_t$, следующим образом:

$$S_t = S_{t-1} + \alpha (x_t - S_{t-1})$$

После рекурсивного применения формулы для $S_t$, её можно выразаить через значения временного ряда $x$:

$$S_t = \alpha \sum_{i=0}^{N-1}\beta^{i} x_{t-i} + \beta^{N} S_0$$

где:

$N$ - кол-во членов ряда

$S_0$ - некоторая величина, характерезующая начальные условия, первого применения формулы.

По сути $S_t$ является средневзвешанной суммой всех членов ряда и соответственно чем старше компонента, т.е. находится ближе к началу ряда, тем меньший вес будет иметь она. Кроме того слагаемое $x_t - S_{t-1}$ по сути является погрешностью прогноза, соответственно каждое последующее значение и является корректировкой предыдущего.

Поэтому рекурентная для прогнозирования:

$$S_{t+d} = \alpha x_t + (1 - \alpha)\widehat{x_t}$$,

где

$x_t$ - фактическое значение на момент $t$,

$\widehat{x_t}$ - прогнозное значение на момент $t$,

Надо пояснить, что для применения данного сглаживание всегда необходимо иметь какое-то значение $S_0$, для расчета первого сглаженного значения, и в большинстве случаев это может быть обычная срденяя N-го количества начальных элементов.

Важным моментом в поиске наилучшей модели является подбор коэффициента $\alpha$. Как показывает практика данный коэффициент зависит от срока на который требуется получить прогноз. Для небольшого срока $\alpha$ должен быть ближе к 1, т. к. таким образом последним элементам последовательности будет придаваться больший вес. Для получения среднесрочных прогнозов начальные элементы последовательности должны иметь больший вес и, соответственно, $\alpha$ должен быть ближе 0.

Однако необходимо помнить что, чем $\alpha$ ближе к 1, тем более вероятно что временной ряд имеет тренд(тенденцию) или сезонные колебания, а при таких условиях от модели экспоненциального сглаживая будет сложно ждать хороших результатов и надо будет подобрать более подходящую модель.

Также не мало важно знать как реагирует модель на типичные нарушения стационарности типа импульсов или сутпенчатого изменения. Импульс - это однократное событие вызванное внешним факторам. Например яркий пример имульса это нелицеприятный ответ Элона Маска анлитикам, на предмет анализа отчетночти Tesla Motors, когда акции одномоментно просели на 5%. Ступенчатые изменения - долговременное изменение структуры ряда. Например изменение уровня производства из-за появления какой-либо технологии.

Из описания импульсов и ступенчатых изменений следует, что хорошая модель должна хорошо сглаживать импульсы и быстро реагировать на изменения. Из выше описанного можно сделать вывод для адекватной реакции на импульсы первые члены последовательности должны иметь вес выше последних, а для это лучше использовать малое значение коэффициента сглаживания $\alpha$. Для сглаживаний ступенчатых изменений наборот большее $\alpha$ предпочтительнее, так как больший вес должны иметь последние элементы

При этом необхлдимо еще раз отметить, что если ряд имеет тенденцую роста (линейную или праболическую) от данной модели нельзя ожидать хороших прогнозов и лучше использовать другую модель.

Практика.

Для практической иллюстрации применения данной модели будет использоваться цена закрытия Bitcoin за последние 2 месяца (01.03.2018-13.05.2018).

В качестве значения $S_0$ будет использоваться среднее арифметическое первых 10 членов последовательности (с 01.03.2018 по 10.03.2018)

$S_0 = \frac{10951,00+11086,40+11489,70+11512,60+11573,30+10779,90+9965,57+9395,01+9337,55+8866,00}{10} = 10495,7$

На основе фактических данных эмпирическим путем был подобран коэффициент $\alpha = 0,43$

На основе полученной информации получился следующий прогноз:

Дата Цена Прогноз
01.03.2018 10 951,00 10 495,70
02.03.2018 11 086,40 10 691,48
03.03.2018 11 489,70 10 861,30
04.03.2018 11 512,60 11 131,51
05.03.2018 11 573,30 11 295,38
06.03.2018 10 779,90 11 414,88
08.05.2018 9 234,82 9 552,29
09.05.2018 9 325,18 9 415,78
10.05.2018 9 043,94 9 376,82
11.05.2018 8 441,49 9 233,68
12.05.2018 8 504,89 8 893,04
13.05.2018 8 726,14

график соотношения фактических и прогнозных данных

Реализация на С++

Реализация функции данной модели выглядит следующим образом:

const float ErrIncorrectAlpha = -1.0;

/*
Реализация молели экспоненциального сглаживания.

@param[in] time_series Временной ряд.
@param[in] alpha Коэффициент сглаживания между 0 и 1.
@param[in] s0 инициализированное первое значение S.

@return Прогнозное значение.
*/
float exponential_smoothing(std::list<float> time_series, float alpha, float s0) {
  if (alpha > 1 || alpha < 0) {
	// если параметр alpha задан не корректно, возвращается ошибка
	  return ErrIncorrectAlpha;
	}

  float predict_value = s0;
  float fact_value;
  
  for(std::list<float>::iterator r = time_series.begin(); r != time_series.end(); r++){
	fact_value = *r;
	predict_value = alpha * fact_value + (1 - alpha) * predict_value;
  }
  
  return predict_value;
}

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

Код тестовой программы:

#include <iostream>
#include <list>

const float ErrIncorrectAlpha = -1.0;

/*
Реализация молели экспоненциального сглаживания.

@param[in] time_series Временной ряд.
@param[in] alpha Коэффициент сглаживания между 0 и 1.
@param[in] s0 инициализированное первое значение S.

@return Прогнозное значение.
*/
float exponential_smoothing(std::list<float> time_series, float alpha, float s0) {
  if (alpha > 1 || alpha < 0) {
	// если параметр alpha задан не корректно, возвращается ошибка
	  return ErrIncorrectAlpha;
	}

  float predict_value = s0;
  float fact_value;
  
  for(std::list<float>::iterator r = time_series.begin(); r != time_series.end(); r++){
	fact_value = *r;
	predict_value = alpha * fact_value + (1 - alpha) * predict_value;
  }
  
  return predict_value;
}

int main() 
{
  // тестовые значения
  std::list<float> ts = {9325.18, 9043.94, 8441.49, 8504.89};
  float predict_value;
  
  // строим модель с alpha=0.43 и s0 = 9552.29
  predict_value = exponential_smoothing(ts, 0.43, 9552.29);

  if (predict_value == ErrIncorrectAlpha) {
	  std::cout << "Alpha must be between 0 and 1" << std::endl;
  } else {
	std::cout << "Predict value: " << predict_value << std::endl;
  }
  
	
  return 0; 
}

Вывод

Была построена и разобрана адаптивная модель экспоненциального сглаживания для прогнозирования цены Bitcoin. В итоге средняя ошибка прогноза получившийся модели находится в районе 4% что является хорошим результатом.

В последующих статьях я буду рассматривать другие адаптивные модели для рядов с трендом и сезонностью.

Ссылки

  1. Экспоненциальное сглаживание
  2. Лукашин Ю. П. - Адаптивные методы краткосрочного прогнозирования временных рядов.
  3. Bitcoin - CoinMarketCap
  4. Gist Exponential smoothing
 
comments powered by Disqus