Extending the Theta forecasting method to GLMs and attention
[This article was first published on T. Moudiki's Webpage - R, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
In the new version (v0.18.0
) of the ahead
package, I have extended the forecast::thetaf
function to support Generalized Linear Models (GLMs) and added an attention mechanism.
Attention is widely used in current neural networks (because they tend to forget; blame it on the gradients 🙂 ) to focus on specific parts of the input data when making predictions.
In this case, it helps the model to learn which parts of the time series are more important for forecasting, by using weighted averages of the past observations.
More on this later in a paper. A link to a notebook containing Python and R examples is provided at the end of this post.
1 – R version
Start with:
options(repos = c( techtonique = "https://r-packages.techtonique.net", CRAN = "https://cloud.r-project.org" )) install.packages("ahead")
1 – 1 – USAccDeaths
library(forecast) library(ahead) # glm.nb par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::glm.nb, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::glm.nb, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # glm par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::glm, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::glm, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # rlm par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::rlm, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::rlm, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # lqs par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::lqs, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::lqs, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # lm par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::lm, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::lm, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # gam par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=gam::gam, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=gam::gam, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # rq par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=quantreg::rq, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=quantreg::rq, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention")
1 - 2 - AirPassengers
# glm.nb par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::glm.nb, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::glm.nb, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # glm par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::glm, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::glm, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # rlm par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::rlm, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::rlm, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # lm par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::lm, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::lm, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # lqs par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::lqs, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::lqs, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # gam par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=gam::gam, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=gam::gam, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention") # rq par(mfrow=c(2,1)) obj1 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=quantreg::rq, attention = TRUE, type_pi = "conformal-split", method = "adj")) plot(obj1, main="With attention") obj2 <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=quantreg::rq, attention = FALSE, type_pi = "conformal-split", method = "adj")) plot(obj2, main="Without attention")
2 - Python version
from rpy2.robjects.packages import importr from rpy2.robjects import r import rpy2.robjects as ro import numpy as np import matplotlib.pyplot as plt from rpy2.robjects import pandas2ri # Import required R packages ahead = importr('ahead') mass = importr('MASS') base = importr('base') stats = importr('stats') # Get the data and fit the model with localconverter(ro.default_converter): # Get AirPassengers data data = r('USAccDeaths') data = np.array(data) # Fit the model fit = r(''' suppressWarnings( ahead::glmthetaf( USAccDeaths, h=25L, fit_func=MASS::glm.nb, attention=TRUE, type_pi="conformal-split", method="adj" ) ) ''') # Extract predictions and intervals forecasts = np.array(fit.rx2('mean')) lower = np.array(fit.rx2('lower')) upper = np.array(fit.rx2('upper')) # Create time indices time_train = np.arange(len(data)) time_test = np.arange(len(data), len(data) + len(forecasts)) # Create the plot plt.figure(figsize=(12, 6)) # Plot training data plt.plot(time_train, data, 'b-', label='Observed', alpha=0.7) # Plot forecasts and prediction intervals plt.plot(time_test, forecasts, 'r--', label='Forecast') plt.fill_between(time_test, lower, upper, color='r', alpha=0.2, label='95% Prediction Interval') # Customize the plot plt.title('USAccDeaths Forecast with Attention') plt.xlabel('Time') plt.ylabel('-') plt.legend() plt.grid(True, alpha=0.3) # Show the plot plt.tight_layout() plt.show()
To leave a comment for the author, please follow the link and comment on their blog: T. Moudiki's Webpage - R.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.