воскресенье, 31 мая 2020 г.

Временные ряды : подготовка к прогнозированию

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

Как разбить временной ряд на обучающий и тестовый

С помощью функции window

train <- window(ts_month,
                start = time(ts_month)[1],
                end = time(ts_month)[length(ts_month) - 12])

test <- window(ts_month,
               start = time(ts_month)[length(ts_month) - 12 + 1],
               end = time(ts_month)[length(ts_month)])               

ts_info(train)

##  The train series is a ts object with 1 variable and 48 observations
##  Frequency: 12
##  Start time: 2015 1
##  End time: 2018 12

ts_info(test)

##  The test series is a ts object with 1 variable and 12 observations
##  Frequency: 12
##  Start time: 2019 1
##  End time: 2019 12

С помощъю функции ts_split из пакета TSstudio

ts_month_part <- ts_split(ts_month, sample.out = 12)
train <- ts_month_part$train
test <- ts_month_part$test

ts_info(train)

##  The train series is a ts object with 1 variable and 48 observations
##  Frequency: 12
##  Start time: 2015 1
##  End time: 2018 12

ts_info(test)

##  The test series is a ts object with 1 variable and 12 observations
##  Frequency: 12
##  Start time: 2019 1
##  End time: 2019 12

Как сделать диагностику модели по ее остаткам на обучающей выборке

Для того, чтобы изучить остатки, мы будем использовать функцию checkresiduals из пакета forecast, который возвращает следующие четыре вывода :
             график остатков временного ряды
             ACF график остатков
             график распределение остатков
             вывод теста Ljung-Box
Тест Ljung-Box представляет собой статистический метод для тестирования автокорреляции временного ряда (в данном случае, это временной ряд остатков).Он рассматривает следующую гиптезу отличия от нуля

H0: Корреляция между временным рядом и его лагами равна нулю, и поэтому наблюдения независимы 
H1: Корреляция между временным рядом и его лагами отличается от нуля, и, следовательно, наблюдение не является независимым.
С помощью функции auto.arima создадим модель на обучающем временном ряду и продиагностируем полученную модель функцией checkresiduals

md <- auto.arima(train)

checkresiduals(md)


##
##  Ljung-Box test
##
## data:  Residuals from ARIMA(0,0,0)(0,1,0)[12] with drift
## Q* = 12.673, df = 9, p-value = 0.178
##
## Model df: 1.   Total lags used: 10


Анализ по результатам :
             график остатков все же не похож на график белого шума, такое впечатление, что большинство из остатков ниже нулевой линии и это признак того, что модель имеет тенденцию переоценивать фактические значения
             вывод теста Ljung-Box p-значение высокое и это не дает нам право отклонить нулевую гипотезу о независимости наблюдений в остатках, график ACF функции подтверждает это
             гистограмма распределение остатков показывает его скошенность
Вывод - модель требует доработки.

Как оценить прогностическую точность модели

Для оценки точности прогноза используем функцию accuracy из пакета forecast. В начале делаем прогноз на полученной модели на 12 месяцев вперед, а потом оцениваем точность прогноза по тестирующей части временного ряда

fc <- forecast(md, h = 12)

round(accuracy(fc, test),2)


                       ME   RMSE    MAE   MPE MAPE MASE  ACF1 Theil's U
Training set   2.81 307.36  203.25   0.15     1.97    0.36      -0.16        NA
Test set        -82.22 268.14  225.83  -0.85    2.56    0.40      -0.38      0.11


Функция accuracy возвращает несколько метрик ошибок между прогнозом, сделанным на обученной модели и фактическими значениями из тестовой выборки. Так MAPE равен 1.97% на обучающей выборке и 2.56% на тестовой. Близость значений говорит о том, что нет переобучения.
С помощью функции test_forecast из пакета TSstudio можно визуально оценить близость прогноза фактическим значениям.

test_forecast(actual = ts_month,

              forecast.obj = fc,
              test = test)



Анализ такого графика позволит оценить на каких участках временного ряда наблюдаются наибольшие ошибки прогноза.

Опорный прогноз

Для того, чтобы оценить насколько хороша точность полученного прогноза необходимо иметь некоторый опорный прогноз, относительно показателей которого можно провести сравнение полученной точности. Часто для этого используют наивный прогноз.
Простой наивный прогноз, как правило, предполагает, что будущее значение равно текущему. Получить наивный прогноз можно функцией naive from the forecast.

naive_model <- naive(train, h = 12)
test_forecast(actual = ts_month,
              forecast.obj = naive_model,
              test = test)



Оценим точность наивной модели

round(accuracy(naive_model, test),2)

                         ME    RMSE     MAE    MPE  MAPE MASE  ACF1 Theil's U
Training set   -67.21 2436.81 1600.36  -4.33  18.57    2.84   -0.43        NA
Test set        -2469.50 3004.26 2597.17 -33.76 34.86   4.60     0.06      1.52

В случае наивной модели, нет никакого процесса обучения и прогнозные значения равны 
фактическим. Но так как наш временной ряд ts_month является сезонным,  было бы целесообразно использовать сезонную наивные модель, которая принимает во внимание
сезонные колебания. snaive_model из пакета forecast использует последнюю сезонную серию как прогноз всех соответствующих сезонных наблюдений. 

snaive_model <- snaive(train, h = 12)
test_forecast(actual = ts_month,
              forecast.obj = snaive_model,
              test = test)



Оценим точность сезонной наивной модели

round(accuracy(snaive_model, test),2)


                       ME      RMSE    MAE    MPE  MAPE MASE  ACF1 Theil's U
Training set -544.44 649.88    564.06  -5.55   5.71     1.00      -0.16        NA
Test set         -626.67 676.65    626.67  -7.37   7.37     1.11      -0.38       0.3

Сезонная наивная модель выдает лучший вариант для опорного прогноза, поэтому мы будем использовать ее в качестве ориентира для модели ARIMA. Сравнение MAPE и RMSE двух моделей  хорошо показывает, что модель ARIMA дает лучший прогноз с точки зрения  точности по отношению к опорной модели :

ac_arm <- round(accuracy(fc, test),2)
ac_sn <- round(accuracy(snaive_model, test),2)


data.frame(Model=c('ARIMA','snaive'),
                  RMSE=c(ac_arm[2,2],ac_sn[2,2]),
                 MAPE=c(ac_arm[2,5],ac_sn[2,5]))


    Model     RMSE  MAPE
1  ARIMA 268.14    2.56
2  snaive    676.65    7.37

Доработка прогноза

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

md_final <- auto.arima(ts_month)
fc_final <- forecast(md_final, h = 12)

plot_forecast(fc_final,
              title = "Прогноз посетителей в магазине одежды",
              Xtitle = "Год",
              Ytitle = "Посетители")



Доверительный интервал прогноза

Доверительный интервал представляет диапазон возможных значений, которые содержат истинное значение с определенной степенью уверенности (или вероятностью). Широта диапазона доверительного интервала зависит от заданного  уровень доверия или вероятность того, что истинное значение будет в этом диапазоне,  чем выше уровень доверия, тем шире интервал диапазона.
По умолчанию функция forecast генерирует интервал прогнозирования с уровнем доверия
80% и 95%, но  его можно изменить, например сделаем его уже  80% и 85%.

fc_final2 <- forecast(md_final,
                      h = 12,
                      level = c(80, 85))

plot_forecast(fc_final2,
              title = "Прогноз посетителей в магазине одежды",
              Xtitle = "Год",
              Ytitle = "Посетители")


















































Комментариев нет:

Отправить комментарий