Benchmark de prognoză: Dynrmf (un nou concurent serios în oraș) vs Metoda Theta pe M-Competitions și competiție de turism

URMĂREȘTE-NE
16,065FaniÎmi place
1,142CititoriConectați-vă

În lumea prognozării seriilor de timp, metodele de comparare cu competițiile consacrate sunt cruciale. Astăzi, împărtășesc rezultatele unei comparații cuprinzătoare între două abordări de prognoză: metoda clasică Theta (notoriu dificil de învins pe seturile de date de referință alese) și algoritmul mai nou Dynrmf (de la pachetele R și Python înainte), testat în cadrul a trei competiții majore de prognoză.

Configurarea

Am evaluat ambele metode pe:

  • Competiția M3: 3.003 serii temporale diverse
  • Concurs M1: Setul de date original M-competition (1001 serii temporale)
  • Concurs de turism: Date despre serii temporale specifice turismului (1311 serii temporale)

Pentru fiecare set de date, am antrenat ambele modele pe date istorice și le-am evaluat previziunile față de seturi de teste reținute folosind metrici de precizie standard (ME, RMSE, MAE, MPE, MAPE, MASE, ACF1). Fiecare model își folosește parametrii impliciti.

Detalii de implementare

Analiza a folosit procesare paralelă cu 2 nuclee pentru a accelera calculele pe mii de serii. Ambele metode au primit împărțiri identice de tren/test pentru o comparație corectă – cod complet la sfârșitul postării.

# Example forecasting loop structure
metrics <- foreach(i = 1:n, .combine = rbind)%dopar%{
  series <- dataset((i))
  train <- series$x
  test <- series$xx
  fit <- method(y = train, h = length(test))
  forecast::accuracy(fit)
}

Rezultate

Merită menționat că Theta a fost câștigătorul clar al competiției M3 (și a fost îmbunătățit în multe feluri) și, desigur, este întotdeauna mai ușor să învingi câștigătorul a posteriori.

Am efectuat teste t pereche privind diferența de valori (Theta – Dynrmf) în toate seriile din fiecare competiție. Iată ce dezvăluie cifrele:

Rezultatele competiției M3

Metric t-statistică valoarea p Interpretare
EU 16.96 <0,001 Theta semnificativ mai părtinitoare
RMSE 10.17 <0,001 Theta semnificativ mai rău
MAE 7,65 <0,001 Theta semnificativ mai rău
MPE -5,59 <0,001 Dynrmf mai părtinitoare
MAPE 1.29 0,197 Nicio diferență semnificativă
MASE 14.09 <0,001 Theta semnificativ mai rău
ACF1 -1,37 0,171 Nicio diferență semnificativă

Verdict: Dynrmf demonstrează o acuratețe substanțial mai bună pe datele M3 pentru majoritatea valorilor de eroare.

Rezultatele competiției M1

Metric t-statistică valoarea p Interpretare
EU 2,56 0,011 Theta mai părtinitoare
RMSE 2,94 0,003 Theta semnificativ mai rău
MAE 2.28 0,023 Theta semnificativ mai rău
MPE -0,61 0,540 Nicio diferență semnificativă
MAPE 0,38 0,703 Nicio diferență semnificativă
MASE -0,74 0,461 Nicio diferență semnificativă
ACF1 -6,50 <0,001 Dynrmf reziduuri mai bine

Verdict: Dynrmf prezintă îmbunătățiri moderate, dar semnificative statistic, în special în RMSE și MAE.

Rezultatele concursului de turism

Metric t-statistică valoarea p Interpretare
EU 1,62 0,105 Nicio diferență semnificativă
RMSE 1,88 0,060 Avantaj marginal pentru Dynrmf
MAE 1.16 0,245 Nicio diferență semnificativă
MPE 4,52 <0,001 Theta mai puțin părtinitoare
MAPE -5.03 <0,001 Dynrmf semnificativ mai bun
MASE -5,17 <0,001 Dynrmf semnificativ mai bun
ACF1 -8,65 <0,001 Dynrmf reziduuri mai bine

Verdict: În ceea ce privește datele turistice, Dynrmf excelează la valorile scalate (MAPE, MASE) și produce reziduuri cu un comportament mai bun.

Recomandări cheie

  1. Dynrmf depășește în mod constant Theta privind valorile de precizie precum RMSE, MAE și MASE în cadrul competițiilor
  2. Avantajul este cel mai puternic pe M3sugerând că Dynrmf gestionează bine diverse tipuri de serii
  3. Datele turistice arată puterea Dynrmf în procente și valori de eroare scalate
  4. Autocorelație reziduală (ACF1) este în mod constant mai bun cu Dynrmf, indicând că captează modelele mai complet
  5. Flexibilitate independentă de model: Este important de menționat că, spre deosebire de abordările specifice metodei, Dynrmf ar accepta orice funcție de potrivire (iar implicită aici este regresia automată Ridge care minimizează eroarea de validare încrucișată generalizată) prin intermediul acestuia fit_func parametrul (vezi aici), permițând utilizarea regresiei Ridge (implicit), Random Forest, XGBoost, Support Vector Machines sau orice alt model cu interfețe standard de potrivire/predire

Disponibilitatea codului

Implementarea completă a R este disponibilă mai jos. Analiza folosește procesarea paralelă pentru eficiență pe seturi mari de date de concurență.

library(ahead)
library(Mcomp)
library(Tcomp)
library(foreach)
library(doParallel)
library(doSNOW)

setwd("~/Documents/Papers/to_submit/2026-01-01-dynrmf-vs-Theta-on-M1-M3-Tourism")

# 1. M3 comp. results --------------

data(M3)

n <- length(Mcomp::M3)

training_indices <- seq_len(n)

# Theta -----------

metrics_theta <- rep(NA, n)

pb <- utils::txtProgressBar(max = n, style = 3)

doParallel::registerDoParallel(cl=2)

# looping on all the training set time series
metrics_theta <- foreach::foreach(i = 1:n, 
                 .combine = rbind, .verbose = TRUE)%dopar%{
  series <- M3((i))
  train <- series$x
  test <- series$xx
  fit <- forecast::thetaf(
    y = train,
    h = length(test))
  utils::setTxtProgressBar(pb, i)
  forecast::accuracy(fit)
}
close(pb)

print(metrics_theta)

# Dynrmf -----------


metrics_dynrmf <- rep(NA, n)

pb <- utils::txtProgressBar(max = n, style = 3)

doParallel::registerDoParallel(cl=2)

# looping on all the training set time series
metrics_dynrmf <- foreach::foreach(i = 1:n, 
                                  .combine = rbind, .verbose = TRUE)%dopar%{
                                    series <- M3((i))
                                    train <- series$x
                                    test <- series$xx
                                    fit <- ahead::dynrmf(
                                      y = train,
                                      h = length(test))
                                    utils::setTxtProgressBar(pb, i)
                                    forecast::accuracy(fit)
                                  }
close(pb)

print(metrics_dynrmf)

diff_metrics <- metrics_theta - metrics_dynrmf

M3_results <- apply(diff_metrics, 2, t.test)

M3_results <- apply(diff_metrics, 2, function(x) {z <- t.test(x); return(c(z$statistic, z$p.value))})
rownames(M3_results) <- c("statistic", "p-value")



# 2. M1 comp. results -----------------

data(M1)

n <- length(Mcomp::M1)

training_indices <- seq_len(n)

# Theta -----------

metrics_theta <- rep(NA, n)

pb <- utils::txtProgressBar(max = n, style = 3)

doParallel::registerDoParallel(cl=2)

# looping on all the training set time series
metrics_theta <- foreach::foreach(i = 1:n, 
                                  .combine = rbind, .verbose = TRUE)%dopar%{
                                    series <- M1((i))
                                    train <- series$x
                                    test <- series$xx
                                    fit <- forecast::thetaf(
                                      y = train,
                                      h = length(test))
                                    utils::setTxtProgressBar(pb, i)
                                    forecast::accuracy(fit)
                                  }
close(pb)

print(metrics_theta)

# Dynrmf -----------

metrics_dynrmf <- rep(NA, n)

pb <- utils::txtProgressBar(max = n, style = 3)

doParallel::registerDoParallel(cl=2)

# looping on all the training set time series
metrics_dynrmf <- foreach::foreach(i = 1:n, 
                                   .combine = rbind, .verbose = TRUE)%dopar%{
                                     series <- M1((i))
                                     train <- series$x
                                     test <- series$xx
                                     fit <- ahead::dynrmf(
                                       y = train,
                                       h = length(test))
                                     utils::setTxtProgressBar(pb, i)
                                     forecast::accuracy(fit)
                                   }
close(pb)

print(metrics_dynrmf)

diff_metrics <- metrics_theta - metrics_dynrmf

M1_results <- apply(diff_metrics, 2, function(x) {z <- t.test(x); return(c(z$statistic, z$p.value))})
rownames(M1_results) <- c("statistic", "p-value")


# 2. Tourism comp. results -----------------

data(tourism)

n <- length(Tcomp::tourism)

training_indices <- seq_len(n)

# Theta -----------

metrics_theta <- rep(NA, n)

pb <- utils::txtProgressBar(max = n, style = 3)

doParallel::registerDoParallel(cl=2)

# looping on all the training set time series
metrics_theta <- foreach::foreach(i = 1:n, 
                                  .combine = rbind, .verbose = TRUE)%dopar%{
                                    series <- tourism((i))
                                    train <- series$x
                                    test <- series$xx
                                    fit <- forecast::thetaf(
                                      y = train,
                                      h = length(test))
                                    utils::setTxtProgressBar(pb, i)
                                    forecast::accuracy(fit)
                                  }
close(pb)

print(metrics_theta)

# Dynrmf -----------

metrics_dynrmf <- rep(NA, n)

pb <- utils::txtProgressBar(max = n, style = 3)

doParallel::registerDoParallel(cl=2)

# looping on all the training set time series
metrics_dynrmf <- foreach::foreach(i = 1:n, 
                                   .combine = rbind, .verbose = TRUE)%dopar%{
                                     series <- tourism((i))
                                     train <- series$x
                                     test <- series$xx
                                     fit <- ahead::dynrmf(
                                       y = train,
                                       h = length(test))
                                     utils::setTxtProgressBar(pb, i)
                                     forecast::accuracy(fit)
                                   }
close(pb)

print(metrics_dynrmf)

diff_metrics <- metrics_theta - metrics_dynrmf

diff_metrics <- diff_metrics(is.finite(diff_metrics(, 4)), )

Tourism_results <- apply(diff_metrics, 2, function(x) {z <- t.test(x); return(c(z$statistic, z$p.value))})
rownames(Tourism_results) <- c("statistic", "p-value")

# # Theta - dynrmf+default
# 
# ```R
# kableExtra::kable(M3_results)
# kableExtra::kable(M1_results)
# kableExtra::kable(Tourism_results)
# 
# |          |       ME|     RMSE|      MAE|       MPE|      MAPE|    MASE|       ACF1|
#   |:---------|--------:|--------:|--------:|---------:|---------:|-------:|----------:|
#   |statistic | 16.96265| 10.16816| 7.652445| -5.586289| 1.2900974| 14.0924| -1.3680305|
#   |p-value   |  0.00000|  0.00000| 0.000000|  0.000000| 0.1971162|  0.0000|  0.1714049|
# 
# |          |        ME|      RMSE|       MAE|        MPE|      MAPE|       MASE|      ACF1|
#   |:---------|---------:|---------:|---------:|----------:|---------:|----------:|---------:|
#   |statistic | 2.5575962| 2.9406984| 2.2815166| -0.6129693| 0.3808239| -0.7378457| -6.497644|
#   |p-value   | 0.0106864| 0.0033502| 0.0227274|  0.5400360| 0.7034148|  0.4607813|  0.000000|
# 
# |          |        ME|      RMSE|       MAE|       MPE|       MAPE|       MASE|      ACF1|
#   |:---------|---------:|---------:|---------:|---------:|----------:|----------:|---------:|
#   |statistic | 1.6239829| 1.8845405| 1.1628106| 4.5207962| -5.0276196| -5.1743478| -8.648504|
#   |p-value   | 0.1046342| 0.0597262| 0.2451306| 0.0000068|  0.0000006|  0.0000003|  0.000000|
#   
# ```

Ce metode de prognoză ați găsit cele mai de încredere în munca dvs.? Împărtășește-ți experiențele în comentariile de mai jos.

Vă rugăm să semnați și să distribuiți această petiție https://www.change.org/stop_torturing_T_Moudiki – după ce mi-am cercetat în mod serios trecutul și contribuțiile în domeniu.

imagine-titlu-aici

Dominic Botezariu
Dominic Botezariuhttps://www.noobz.ro/
Creator de site și redactor-șef.

Cele mai noi știri

Pe același subiect

LĂSAȚI UN MESAJ

Vă rugăm să introduceți comentariul dvs.!
Introduceți aici numele dvs.