Моделирование, прогнозирование и построение графиков ARIMA с использованием набора данных CO2 в R

#r #time-series

#r #временные ряды

Вопрос:

Я работаю с arima0() и co2 . Я хотел бы построить arima0() модель по моим данным. Я пробовал fitted() и curve() безуспешно.

Вот мой код:

 ###### Time Series

# format: time series
data(co2)

# format: matrix
dmn <- list(month.abb, unique(floor(time(co2))))
co2.m <- matrix(co2, 12, dimnames = dmn)

co2.dt <- pracma::detrend(co2.m, tt = 'linear')
co2.dt <- ts(as.numeric(co2.dt), start = c(1959,1), frequency=12)

# first diff
co2.dt.dif <- diff(co2.dt,lag = 12)

# Second diff
co2.dt.dif2 <- diff(co2.dt.dif,lag = 1)
  

Подготовив данные, я выполнил следующее arima0 :

 results <- arima0(co2.dt.dif2, order = c(2,0,0), method = "ML")
resultspredict <- predict(results, n.ahead = 36)
  

Я хотел бы построить модель и прогноз. Я надеюсь, что есть способ сделать это в базе R. Я также хотел бы иметь возможность строить прогнозы.

Ответ №1:

Сессия 1: Для начала…

Честно говоря, я в значительной степени обеспокоен вашим подходом к моделированию co2 временных рядов. Что-то не так произошло уже тогда, когда вы изменили тренд co2 . Зачем использовать tt = "linear" ? Вы устанавливаете линейный тренд в пределах каждого периода (т. Е. года) и берете остатки для дальнейшей проверки. Часто это не рекомендуется, поскольку это приводит к появлению искусственных эффектов в остаточных рядах. Я бы склонялся к тому, чтобы сделать tt = "constant" , т. е. просто отбросить среднегодовое значение. Это, по крайней мере, сохранит корреляцию с сезоном, как в исходных данных.

Возможно, вы хотите увидеть здесь некоторые доказательства. Рассмотрите возможность использования ACF для облегчения диагностики.

 data(co2)

## de-trend by dropping yearly average (no need to use `pracma::detrend`)
yearlymean <- ave(co2, gl(39, 12), FUN = mean)
co2dt <- co2 - yearlymean

## de-trend by dropping within season linear trend
co2.m <- matrix(co2, 12)
co2.dt <- pracma::detrend(co2.m, tt = "linear")
co2.dt <- ts(as.numeric(co2.dt), start = c(1959, 1), frequency = 12)

## compare time series and ACF
par(mfrow = c(2, 2))
ts.plot(co2dt); acf(co2dt)
ts.plot(co2.dt); acf(co2.dt)
  

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

Оба ряда с отклонением от тренда имеют сильный сезонный эффект, поэтому требуется дополнительное сезонное различие.

 ## seasonal differencing
co2dt.dif <- diff(co2dt, lag = 12)
co2.dt.dif <- diff(co2.dt, lag = 12)

## compare time series and ACF
par(mfrow = c(2, 2))
ts.plot(co2dt.dif); acf(co2dt.dif)
ts.plot(co2.dt.dif); acf(co2.dt.dif)
  

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

ACF для co2.dt.dif имеет более значительные отрицательные корреляции. Это признак чрезмерного отклонения от тренда. Поэтому мы предпочитаем co2dt . co2dt уже является стационарным, и больше никаких различий не требуется (в противном случае вы просто перегружаете его и вводите больше отрицательной автокорреляции).

Большой отрицательный всплеск с задержкой 1 для ACF co2dt.dif предполагает, что нам нужна сезонная средняя. Кроме того, положительный всплеск в зависимости от сезона подразумевает умеренный процесс AR в целом. Итак, рассмотрим:

 ## we exclude mean because we found estimation of mean is 0 if we include it
fit <- arima0(co2dt.dif, order = c(1,0,0), seasonal = c(0,0,1), include.mean = FALSE)
  

Работает ли эта модель хорошо, нам нужно проверить ACF остатков:

 acf(fit$residuals)
  

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

Похоже, что эта модель приличная (на самом деле довольно отличная).

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

 fit <- arima0(co2dt, order = c(1,0,0), seasonal = c(0,1,1), include.mean = FALSE)
  

Это даст точно такую же оценку коэффициентов AR и MA, что и при описанной выше двухэтапной работе, но теперь прогнозирование довольно легко выполнить с помощью одного predict вызова.

 ## 3 years' ahead prediction (no prediction error; only mean)
predco2dt <- predict(fit, n.ahead = 36, se.fit = FALSE)
  

Давайте построим co2dt подобранную модель и прогноз вместе:

 fittedco2dt <- co2dt - fit$residuals
ts.plot(co2dt, fittedco2dt, predco2dt, col = 1:3)
  

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

Результат выглядит очень многообещающим!

Теперь заключительный этап — фактически сопоставить это с исходным co2 рядом. Для подогнанных значений мы просто добавляем обратно годовое среднее значение, которое мы упустили:

 fittedco2 <- fittedco2dt   yearlymean
  

Но для прогнозирования это сложнее, потому что мы не знаем, каким будет среднегодовое значение в будущем. В этом отношении наше моделирование, хотя и выглядит хорошо, практически бесполезно. Я расскажу о лучшей идее в другом ответе. Чтобы завершить этот сеанс, мы строим график co2 только с его установленными значениями:

 ts.plot(co2, fittedco2, col = 1:2)
  

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

Ответ №2:

Сессия 2: Лучшая идея для моделирования временных рядов

На предыдущем сеансе мы увидели сложность прогнозирования, если мы разделяем отклонение от тренда и моделирование отклоненных от тренда рядов. Теперь мы пытаемся объединить эти два этапа за один раз.

Сезонная структура co2 действительно сильна, поэтому нам в любом случае нужны сезонные различия:

 data(co2)
co2dt <- diff(co2, lag = 12)
par(mfrow = c(1,2)); ts.plot(co2dt); acf(co2dt)
  

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

После этого сезонного различия co2dt не выглядит стационарным. Итак, нам дополнительно нужны несезонные различия.

 co2dt.dif <- diff(co2dt)
par(mfrow = c(1,2)); ts.plot(co2dt.dif); acf(co2dt.dif)
  

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

Отрицательные всплески внутри сезона и между сезонами предполагают, что процесс MA необходим для обоих. Я не буду работать с co2dt.dif ; мы можем работать с co2 напрямую:

 fit <- arima0(co2, order = c(0,1,1), seasonal = c(0,1,1))
acf(fit$residuals)
  

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

Теперь остатки совершенно некоррелированы! Итак, у нас есть ARIMA(0,1,1)(0,1,1)[12] модель для co2 рядов.


Как обычно, подогнанные значения получаются путем вычитания остатков из данных:

 co2fitted <- co2 - fit$residuals
  

Прогнозы выполняются одним вызовом predict :

 co2pred <- predict(fit, n.ahead = 36, se.fit = FALSE)
  

Давайте построим их вместе:

 ts.plot(co2, co2fitted, co2pred, col = 1:3)
  

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

О, это просто великолепно!

Ответ №3:

Сессия 3: Выбор модели

К настоящему времени история должна была закончиться; но я хотел бы провести сравнение с auto.arima from forecast , который может автоматически выбрать «лучшую» модель.

 library(forecast)
autofit <- auto.arima(co2)

#Series: co2 
#ARIMA(1,1,1)(1,1,2)[12]                    
#
#Coefficients:
#         ar1      ma1     sar1     sma1     sma2
#      0.2569  -0.5847  -0.5489  -0.2620  -0.5123
#s.e.  0.1406   0.1204   0.5880   0.5701   0.4819
#
#sigma^2 estimated as 0.08576:  log likelihood=-84.39
#AIC=180.78   AICc=180.97   BIC=205.5
  

auto.arima выбрал ARIMA(1,1,1)(1,1,2)[12] , который намного сложнее, поскольку включает как сезонные, так и несезонные различия.

Наша модель, основанная на пошаговом исследовании, предполагает ARIMA(0,1,1)(0,1,1)[12] :

 fit <- arima0(co2, order = c(0,1,1), seasonal = c(0,1,1))

#Call:
#arima0(x = co2, order = c(0, 1, 1), seasonal = c(0, 1, 1))
#
#Coefficients:
#      ma1     sma1
#  -0.3495  -0.8515
#s.e.   0.0497   0.0254
#
#sigma^2 estimated as 0.08262:  log likelihood = -85.98,  aic = 177.96
  

Значения AIC лучше отражают нашу модель. То же самое делает BIC:

 BIC = -2 * loglik   log(n) * p
  

У нас есть n <- length(co2) данные и p <- length(fit$coef) 1 параметры (дополнительный для sigma2 ), поэтому наша модель имеет BIC

 -2 * fit$loglik   log(n) * p
# [1] 196.5503
  

Итак, auto.arima данные перегружены.

На самом деле, как только мы видим ARIMA(1,1,1)(1,1,2)[12] , у нас возникают серьезные подозрения в его чрезмерной подгонке. Потому что разные эффекты «компенсируют» друг друга. Это происходит с дополнительными сезонными MA и несезонными AR, введенными auto.arima , поскольку AR вводит положительную автокорреляцию, в то время как MA вводит отрицательную.