Extending the Theta forecasting method to GLMs and attention
This article was first published on T. Moudiki's Webpage - Python , and kindly contributed to python-bloggers. (You can report issue about the content on this page here)
Want to share your content on python-bloggers? click here.
Want to share your content on python-bloggers? click here.
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 - Python .
Want to share your content on python-bloggers? click here.