Suavizado exponencial en programación R

El suavizado exponencial es una técnica para suavizar datos de series de tiempo utilizando una función de ventana exponencial. Es un método de la regla del pulgar. A diferencia del promedio móvil simple, con el tiempo las funciones exponenciales asignan pesos exponencialmente decrecientes. Aquí, los pesos mayores se asignan a los valores u observaciones recientes, mientras que los pesos menores se asignan a los valores u observaciones más antiguos. Entre muchas funciones de ventana, en el procesamiento de señales, la función de suavizado exponencial generalmente se aplica para suavizar datos donde actúa como un filtro de paso bajo para eliminar el ruido de alta frecuencia. Este método es bastante intuitivo, por lo general se puede aplicar en un rango amplio o enorme de series de tiempo y también es computacionalmente eficiente. En este artículo, analicemos el suavizado exponencial en la programación R.. Existen muchos tipos de técnicas de suavizado exponencial basadas en las tendencias y la estacionalidad, que son las siguientes:

  • Suavizado exponencial simple
  • método de holt
  • Método estacional de Holt-Winter
  • Método de tendencia amortiguada

Antes de continuar, es necesario ver los requisitos de replicación.

Requisitos de replicación del análisis en R

En R, los requisitos previos de este análisis serán la instalación de los paquetes necesarios. Necesitamos instalar los siguientes dos paquetes usando el comando install.packages() desde la consola R:

  • fpp2 (con el que se cargará automáticamente el paquete de pronóstico)
  • ordenado

Bajo el paquete de pronóstico, obtendremos muchas funciones que mejorarán y ayudarán en nuestro pronóstico. En este análisis, trabajaremos con dos conjuntos de datos bajo el paquete fpp2 . Estos son el conjunto de datos «goog» y el conjunto de datos «qcement» . Ahora necesitamos cargar los paquetes requeridos en nuestro R Script usando la función library() . Después de cargar ambos paquetes, prepararemos nuestro conjunto de datos. Para ambos conjuntos de datos, dividiremos los datos en dos conjuntos: conjunto de entrenamiento y conjunto de prueba.

R

# loading the required packages
library(tidyverse)
library(fpp2)
 
# create training and testing set
# of the Google stock data
goog.train <- window(goog,
                     end = 900)
goog.test <- window(goog,
                    start = 901)
 
# create training and testing
# set of the AirPassengers data
qcement.train <- window(qcement,
                        end = c(2012, 4))
qcement.test <- window(qcement,
                       start = c(2013, 1))

Ahora estamos listos para continuar con nuestro análisis.

Suavizado exponencial simple (SES)

La técnica de suavizado exponencial simple se utiliza para datos que no tienen tendencia o patrón estacional. El SES es el más simple entre todas las técnicas de suavizado exponencial. Sabemos que en cualquier tipo de suavizado exponencial ponderamos más los valores u observaciones recientes que los valores u observaciones antiguos. El peso de todos y cada uno de los parámetros siempre está determinado por un parámetro de suavizado o alfa. El valor de alfa está entre 0 y 1. En la práctica, si alfa está entre 0,1 y 0,2, SES funcionará bastante bien. Cuando alfa está más cerca de 0, se considera un aprendizaje lento, ya que el algoritmo le da más peso a los datos históricos. Si el valor de alfa está más cerca de 1, se denomina aprendizaje rápido, ya que el algoritmo otorga más peso a las observaciones o datos recientes. Por lo tanto, podemos decir que los cambios recientes en los datos dejarán un mayor impacto en el pronóstico.

En R, para realizar el análisis de suavizado exponencial simple, necesitamos usar la función ses() . Para entender la técnica vamos a ver algunos ejemplos. Usaremos el conjunto de datos de goog para SES.

Ejemplo 1:

En este ejemplo, estamos configurando alfa = 0.2 y también los pasos hacia adelante del pronóstico h = 100 para nuestro modelo inicial.

R

# SES in R
# loading the required packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the Google stock data
goog.train <- window(goog, end = 900)
goog.test <- window(goog, start = 901)
 
# Performing SES on  the
# Google stock data
ses.goog <- ses(goog.train,
                alpha = .2,
                h = 100)
autoplot(ses.goog)

Producción:

output-graph

En el gráfico de salida anterior, podemos notar que nuestro modelo de pronóstico proyecta una estimación plana hacia el futuro. Por lo tanto, podemos decir que a partir de los datos no está capturando la tendencia actual. Por lo tanto, para corregir esto, usaremos la función diff() para eliminar la tendencia de los datos.

Ejemplo 2:

R

# SES in R
# loading the required packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the Google stock data
goog.train <- window(goog,
                     end = 900)
goog.test <- window(goog,
                    start = 901)
 
# removing the trend
goog.dif <- diff(goog.train)
autoplot(goog.dif)
 
# reapplying SES on the filtered data
ses.goog.dif <- ses(goog.dif,
                    alpha = .2,
                    h = 100)
autoplot(ses.goog.dif)

Producción:

output-graphouput-graph

Para comprender el rendimiento de nuestro modelo, debemos comparar nuestro pronóstico con nuestro conjunto de datos de validación o prueba. Dado que nuestro conjunto de datos de tren fue diferenciado, también debemos formar o crear una validación diferenciada o un conjunto de prueba. 

Ejemplo 3:

Aquí vamos a crear un conjunto de validación diferenciado y luego compararemos nuestro pronóstico con el conjunto de validación. Aquí estamos configurando el valor de alfa de 0.01-0.99 usando el bucle. Estamos tratando de entender qué nivel minimizará la prueba RMSE. Veremos que 0.05 será el que más se minimice.

R

# SES in R
# loading the required packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the Google stock data
goog.train <- window(goog,
                     end = 900)
goog.test <- window(goog,
                    start = 901)
 
# removing trend from test set
goog.dif.test <- diff(goog.test)
accuracy(ses.goog.dif, goog.dif.test)
 
# comparing our model
alpha <- seq(.01, .99, by = .01)
RMSE <- NA
for(i in seq_along(alpha)) {
  fit <- ses(goog.dif, alpha = alpha[i],
             h = 100)
  RMSE[i] <- accuracy(fit,
                      goog.dif.test)[2,2]
}
 
# convert to a data frame and
# identify min alpha value
alpha.fit <- data_frame(alpha, RMSE)
alpha.min <- filter(alpha.fit,
                    RMSE == min(RMSE))
 
# plot RMSE vs. alpha
ggplot(alpha.fit, aes(alpha, RMSE)) +
  geom_line() +
  geom_point(data = alpha.min,
             aes(alpha, RMSE),
             size = 2, color = "red")

Producción:

                      ME     RMSE      MAE       MPE     MAPE      MASE        ACF1 Theil's U
Training set -0.01368221 9.317223 6.398819  99.97907 253.7069 0.7572009 -0.05440377        NA
Test set      0.97219517 8.141450 6.117483 109.93320 177.9684 0.7239091  0.12278141 0.9900678

output-graph

Ahora, intentaremos reajustar nuestro modelo de pronóstico para SES con alfa = 0.05. Notaremos la diferencia significativa entre alfa 0.02 y alfa=0.05.

Ejemplo 4:

R

# SES in R
# loading packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the Google stock data
goog.train <- window(goog,
                     end = 900)
goog.test <- window(goog,
                    start = 901)
 
# removing trend
goog.dif <- diff(goog.train)
 
# refit model with alpha = .05
ses.goog.opt <- ses(goog.dif,
                    alpha = .05,
                    h = 100)
 
# performance eval
accuracy(ses.goog.opt, goog.dif.test)
 
# plotting results
p1 <- autoplot(ses.goog.opt) +
  theme(legend.position = "bottom")
p2 <- autoplot(goog.dif.test) +
  autolayer(ses.goog.opt, alpha = .5) +
  ggtitle("Predicted vs. actuals for
                 the test data set")
 
gridExtra::grid.arrange(p1, p2,
                        nrow = 1)

Producción:

> accuracy(ses.goog.opt, goog.dif.test)
                      ME     RMSE      MAE       MPE     MAPE      MASE       ACF1 Theil's U
Training set -0.01188991 8.939340 6.030873 109.97354 155.7700 0.7136602 0.01387261        NA
Test set      0.30483955 8.088941 6.028383  97.77722 112.2178 0.7133655 0.12278141 0.9998811

output-graph

Veremos que ahora el intervalo de confianza predicho de nuestro modelo es mucho más estrecho.

Método de Holt

Hemos visto que en SES tuvimos que eliminar las tendencias a largo plazo para mejorar el modelo. Pero en el método de Holt , podemos aplicar suavizado exponencial mientras capturamos tendencias en los datos. Esta es una técnica que trabaja con datos que tienen tendencia pero no estacionalidad. Para hacer predicciones sobre los datos, el método de Holt utiliza dos parámetros de suavizado , alfa y beta , que corresponden a los componentes de nivel y los componentes de tendencia. 

En R, para aplicar el Método de Holt vamos a utilizar la función holt() . De nuevo entenderemos el principio de funcionamiento de esta técnica utilizando algunos ejemplos. Vamos a usar el conjunto de datos de goog nuevamente.

Ejemplo 1:

R

# holt's method in R
 
# loading packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the Google stock data
goog.train <- window(goog,
                     end = 900)
goog.test <- window(goog,
                    start = 901)
 
# applying holt's method on
# Google stock Data
holt.goog <- holt(goog.train,
                  h = 100)
autoplot(holt.goog)

Producción:

output-graph

En el ejemplo anterior, no configuramos el valor de alfa y beta manualmente. Pero podemos hacerlo. Sin embargo, si mencionamos algún valor para alfa y beta, automáticamente la función holt() identificará el valor óptimo. En este caso, si el valor de alfa es 0,9967, indica un aprendizaje rápido y si el valor de beta es 0,0001, indica un aprendizaje lento de la tendencia.

Ejemplo 2:

En este ejemplo, vamos a establecer el valor de alfa y beta. Además, vamos a ver la precisión del modelo.

R

# holt's method in R
 
# loading the packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the Google stock data
goog.train <- window(goog,
                     end = 900)
goog.test <- window(goog,
                    start = 901)
 
# holt's method
holt.goog$model
 
# accuracy of the model
accuracy(holt.goog, goog.test)

Producción:

Holt's method 

Call:
 holt(y = goog.train, h = 100) 

  Smoothing parameters:
    alpha = 0.9999 
    beta  = 1e-04 

  Initial states:
    l = 401.1276 
    b = 0.4091 

  sigma:  8.8149

     AIC     AICc      BIC 
10045.74 10045.81 10069.75 

> accuracy(holt.goog, goog.test)
                       ME      RMSE       MAE         MPE     MAPE     MASE       ACF1 Theil's U
Training set -0.003332796  8.795267  5.821057 -0.01211821 1.000720 1.002452 0.03100836        NA
Test set      0.545744415 16.328680 12.876836  0.03013427 1.646261 2.217538 0.87733298  2.024518

El valor óptimo, es decir, beta = 0,0001, se utiliza para eliminar errores del conjunto de entrenamiento. Podemos ajustar nuestra versión beta a este valor óptimo. 

Ejemplo 3:

Tratemos de encontrar el valor óptimo de beta a través de un ciclo que va desde 0.0001 a 0.5 que minimizará la prueba RMSE. Veremos que 0.0601 será el valor de beta que sumergirá RMSE.

R

# holts method in R
# loading the package
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the Google stock data
goog.train <- window(goog,
                     end = 900)
goog.test <- window(goog,
                    start = 901)
 
# identify optimal alpha parameter
beta <- seq(.0001, .5, by = .001)
RMSE <- NA
for(i in seq_along(beta)) {
  fit <- holt(goog.train,
              beta = beta[i],
              h = 100)
  RMSE[i] <- accuracy(fit,
                      goog.test)[2,2]
}
 
# convert to a data frame and
# identify min alpha value
beta.fit <- data_frame(beta, RMSE)
beta.min <- filter(beta.fit,
                   RMSE == min(RMSE))
 
# plot RMSE vs. alpha
ggplot(beta.fit, aes(beta, RMSE)) +
  geom_line() +
  geom_point(data = beta.min,
             aes(beta, RMSE),
             size = 2, color = "red")

Producción:

output-graph

Ahora ajustemos el modelo con el valor óptimo obtenido de beta. 

Ejemplo 4:

Vamos a establecer el valor óptimo de beta y también compararemos la precisión predictiva con nuestro modelo original.

R

# loading the package
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the Google stock data
goog.train <- window(goog,
                     end = 900)
goog.test <- window(goog,
                    start = 901)
 
holt.goog <- holt(goog.train,
                  h = 100)
 
# new model with optimal beta
holt.goog.opt <- holt(goog.train,
                      h = 100,
                      beta = 0.0601)
 
# accuracy of first model
accuracy(holt.goog, goog.test)
 
# accuracy of new optimal model
accuracy(holt.goog.opt, goog.test)
 
p1 <- autoplot(holt.goog) +
  ggtitle("Original Holt's Model") +
  coord_cartesian(ylim = c(400, 1000))
 
p2 <- autoplot(holt.goog.opt) +
  ggtitle("Optimal Holt's Model") +
  coord_cartesian(ylim = c(400, 1000))
 
gridExtra::grid.arrange(p1, p2,
                        nrow = 1)

Producción:

> accuracy(holt.goog, goog.test)
                       ME      RMSE       MAE         MPE     MAPE     MASE       ACF1 Theil's U
Training set -0.003332796  8.795267  5.821057 -0.01211821 1.000720 1.002452 0.03100836        NA
Test set      0.545744415 16.328680 12.876836  0.03013427 1.646261 2.217538 0.87733298  2.024518

> accuracy(holt.goog.opt, goog.test)
                      ME      RMSE       MAE          MPE     MAPE     MASE        ACF1 Theil's U
Training set -0.01493114  8.960214  6.058869 -0.005524151 1.039572 1.043406 0.009696325        NA
Test set     21.41138275 28.549029 23.841097  2.665066997 2.988712 4.105709 0.895371665  3.435763

output-graph

Notaremos que el modelo óptimo comparado con el modelo original es mucho más conservador. Además, el intervalo de confianza del modelo óptimo es mucho más extremo. 

Método estacional de Holt-Winter

El método estacional de Holt-Winter se utiliza para datos con patrones y tendencias estacionales. Este método se puede implementar mediante el uso de la estructura aditiva o mediante el uso de la estructura multiplicativa según el conjunto de datos. La estructura o modelo aditivo se usa cuando el patrón estacional de los datos tiene la misma magnitud o es consistente en todo momento, mientras que la estructura o modelo multiplicativo se usa si la magnitud del patrón estacional de los datos aumenta con el tiempo. Utiliza tres parámetros de suavizado: alfa, beta y gamma .

En R, usamos la función decompose() para realizar este tipo de suavizado exponencial. Usaremos el conjunto de datos de qcement para estudiar el funcionamiento de esta técnica.

Ejemplo 1:

R

# Holt-Winter's method in R
# loading packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the AirPassengers data
qcement.train <- window(qcement,
                        end = c(2012, 4))
qcement.test <- window(qcement,
                       start = c(2013, 1))
 
# applying holt-winters
# method on qcement
autoplot(decompose(qcement))

Producción:

Para crear un modelo aditivo que se ocupe del error, la tendencia y la estacionalidad, vamos a utilizar la función ets() . De los 36 modelos, ets() elige el mejor modelo aditivo. Para el modelo aditivo, el parámetro del modelo de ets() será ‘AAA’.

Ejemplo 2:

R

# loading package
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the AirPassengers data
qcement.train <- window(qcement,
                        end = c(2012, 4))
qcement.test <- window(qcement,
                       start = c(2013, 1))
 
# applying ets
qcement.hw <- ets(qcement.train,
                  model = "AAA")
autoplot(forecast(qcement.hw))

Producción:

Ahora evaluaremos nuestro modelo y resumiremos los parámetros de suavizado. También comprobaremos los residuos y averiguaremos la precisión de nuestro modelo.

Ejemplo 3:

R

# additive model
# loading packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the AirPassengers data
qcement.train <- window(qcement,
                        end = c(2012, 4))
qcement.test <- window(qcement,
                       start = c(2013, 1))
 
qcement.hw <- ets(qcement.train, model = "AAA")
 
# assessing our model
summary(qcement.hw)
checkresiduals(qcement.hw)
 
# forecast the next 5 quarters
qcement.f1 <- forecast(qcement.hw,
                       h = 5)
 
# check accuracy
accuracy(qcement.f1, qcement.test)

Producción: 

> summary(qcement.hw)
ETS(A,A,A) 

Call:
 ets(y = qcement.train, model = "AAA") 

  Smoothing parameters:
    alpha = 0.6418 
    beta  = 1e-04 
    gamma = 0.1988 

  Initial states:
    l = 0.4511 
    b = 0.0075 
    s = 0.0049 0.0307 9e-04 -0.0365

  sigma:  0.0854

     AIC     AICc      BIC 
126.0419 126.8676 156.9060 

Training set error measures:
                      ME       RMSE       MAE          MPE     MAPE      MASE       ACF1
Training set 0.001463693 0.08393279 0.0597683 -0.003454533 3.922727 0.5912949 0.02150539

> checkresiduals(qcement.hw)

    Ljung-Box test

data:  Residuals from ETS(A,A,A)
Q* = 20.288, df = 3, p-value = 0.0001479

Model df: 8.   Total lags used: 11

> accuracy(qcement.f1, qcement.test)
                      ME       RMSE        MAE          MPE     MAPE      MASE        ACF1 Theil's U
Training set 0.001463693 0.08393279 0.05976830 -0.003454533 3.922727 0.5912949  0.02150539        NA
Test set     0.031362775 0.07144211 0.06791904  1.115342984 2.899446 0.6719311 -0.31290496 0.2112428

output-graph

Ahora vamos a ver cómo funciona el modelo multiplicativo usando ets() . Para ello, el parámetro del modelo de ets() será ‘MAM’.

Ejemplo 4:

R

# multiplicative model in R
# loading package
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the AirPassengers data
qcement.train <- window(qcement,
                        end = c(2012, 4))
qcement.test <- window(qcement,
                       start = c(2013, 1))
 
# applying ets
qcement.hw2 <- ets(qcement.train,
                   model = "MAM")
checkresiduals(qcement.hw2)

Producción:

> checkresiduals(qcement.hw2)

    Ljung-Box test

data:  Residuals from ETS(M,A,M)
Q* = 23.433, df = 3, p-value = 3.281e-05

Model df: 8.   Total lags used: 11

output-graph

Aquí optimizaremos el parámetro gamma para minimizar la tasa de error. El valor de gamma será 0,21. Junto con eso, vamos a averiguar la precisión y también trazar los valores predictivos. 

Ejemplo 5:

R

# Holt winters model in R
# loading packages
library(tidyverse)
library(fpp2)
 
# create training and validation
# of the AirPassengers data
qcement.train <- window(qcement,
                        end = c(2012, 4))
qcement.test <- window(qcement,
                       start = c(2013, 1))
 
qcement.hw <- ets(qcement.train,
                  model = "AAA")
 
# forecast the next 5 quarters
qcement.f1 <- forecast(qcement.hw,
                       h = 5)
 
# check accuracy
accuracy(qcement.f1, qcement.test)
 
gamma <- seq(0.01, 0.85, 0.01)
RMSE <- NA
 
for(i in seq_along(gamma)) {
  hw.expo <- ets(qcement.train,
                 "AAA",
                 gamma = gamma[i])
  future <- forecast(hw.expo,
                     h = 5)
  RMSE[i] = accuracy(future,
                     qcement.test)[2,2]
}
 
error <- data_frame(gamma, RMSE)
minimum <- filter(error,
                  RMSE == min(RMSE))
ggplot(error, aes(gamma, RMSE)) +
  geom_line() +
  geom_point(data = minimum,
             color = "blue", size = 2) +
  ggtitle("gamma's impact on
            forecast errors",
  subtitle = "gamma = 0.21 minimizes RMSE")
 
# previous model with additive
# error, trend and seasonality
accuracy(qcement.f1, qcement.test)
 
 
# new model with
# optimal gamma parameter
qcement.hw6 <- ets(qcement.train,
                   model = "AAA",
                   gamma = 0.21)
qcement.f6 <- forecast(qcement.hw6,
                       h = 5)
accuracy(qcement.f6, qcement.test)
 
# predicted values
qcement.f6
autoplot(qcement.f6)

Producción:

> accuracy(qcement.f1, qcement.test)
                      ME       RMSE        MAE          MPE     MAPE      MASE        ACF1 Theil's U
Training set 0.001463693 0.08393279 0.05976830 -0.003454533 3.922727 0.5912949  0.02150539        NA
Test set     0.031362775 0.07144211 0.06791904  1.115342984 2.899446 0.6719311 -0.31290496 0.2112428

> accuracy(qcement.f6, qcement.test)
                       ME       RMSE        MAE        MPE     MAPE      MASE        ACF1 Theil's U
Training set -0.001312025 0.08377557 0.05905971 -0.2684606 3.834134 0.5842847  0.04832198        NA
Test set      0.033492771 0.07148708 0.06775269  1.2096488 2.881680 0.6702854 -0.35877010 0.2202448

> qcement.f6
        Point Forecast    Lo 80    Hi 80    Lo 95    Hi 95
2013 Q1       2.134650 2.025352 2.243947 1.967494 2.301806
2013 Q2       2.427828 2.299602 2.556055 2.231723 2.623934
2013 Q3       2.601989 2.457284 2.746694 2.380681 2.823296
2013 Q4       2.505001 2.345506 2.664496 2.261075 2.748927
2014 Q1       2.171068 1.987914 2.354223 1.890958 2.451179

output-graph

Método de amortiguamiento en R

El método de amortiguamiento utiliza el coeficiente de amortiguamiento phi para estimar de forma más conservadora las tendencias previstas. El valor de phi se encuentra entre 0 y 1. Si creemos que nuestro modelo aditivo y multiplicativo va a ser una línea plana, es probable que esté amortiguado. Para comprender el principio de funcionamiento del pronóstico de amortiguamiento, utilizaremos el conjunto de datos fpp2::ausair donde crearemos muchos modelos e intentaremos tener líneas de tendencia mucho más conservadoras.

Ejemplo:

R

# Damping model in R
 
# loading the packages
library(tidyverse)
library(fpp2)
 
# holt's linear (additive) model
fit1 <- ets(ausair, model = "ZAN",
            alpha = 0.8, beta = 0.2)
pred1 <- forecast(fit1, h = 5)
 
# holt's linear (additive) model
fit2 <- ets(ausair, model = "ZAN",
            damped = TRUE, alpha = 0.8,
            beta = 0.2, phi = 0.85)
pred2 <- forecast(fit2, h = 5)
 
# holt's exponential
# (multiplicative) model
fit3 <- ets(ausair, model = "ZMN",
            alpha = 0.8, beta = 0.2)
pred3 <- forecast(fit3, h = 5)
 
# holt's exponential
# (multiplicative) model damped
fit4 <- ets(ausair, model = "ZMN",
            damped = TRUE,
            alpha = 0.8, beta = 0.2,
            phi = 0.85)
pred4 <- forecast(fit4, h = 5)
 
autoplot(ausair) +
  autolayer(pred1$mean,
            color = "blue") +
  autolayer(pred2$mean,
            color = "blue",
            linetype = "dashed") +
  autolayer(pred3$mean,
            color = "red") +
  autolayer(pred4$mean,
            color = "red",
            linetype = "dashed")

Producción:

output-graph

Publicación traducida automáticamente

Artículo escrito por shaonim8 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *