| 1 | \documentclass[a4paper,12pt]{article} |
| 2 | \usepackage[utf8]{inputenc} |
| 3 | \usepackage[T1]{fontenc} |
| 4 | |
| 5 | \renewcommand*\familydefault{\sfdefault} |
| 6 | |
| 7 | \marginparwidth 0pt |
| 8 | \oddsidemargin 0pt |
| 9 | \evensidemargin 0pt |
| 10 | \marginparsep 0pt |
| 11 | \topmargin 0pt |
| 12 | \textwidth 16cm |
| 13 | \textheight 23cm |
| 14 | \parindent 5mm |
| 15 | |
| 16 | \begin{document} |
| 17 | |
| 18 | \section{Package R "ppmfun"} |
| 19 | |
| 20 | Le package $-$ Predict PM10 with FUNctional methods $-$ contient le code permettant de (re)lancer |
| 21 | les expériences numériques décrites dans ce document. La fonction principale \emph{predictPM10} |
| 22 | se divise en trois parties, décrites successivement au cours des trois paragraphes suivants.\\ |
| 23 | |
| 24 | <<setup, out.width='7cm', out.height='7cm'>>= |
| 25 | #Chargement de la librairie (après compilation, "R CMD INSTALL ppmfun/") |
| 26 | library(ppmfun) |
| 27 | |
| 28 | #Exemple d'appel principal (détaillé ci-après) |
| 29 | p_mix = predictPM10("GMT", "7h", 400, 30, "Neighbors", NULL, 0, "direct", |
| 30 | simtype="mix") |
| 31 | |
| 32 | #Allure des courbes prédites |
| 33 | yrange = range(p_mix$forecasts[401:430], na.rm=TRUE) |
| 34 | plot(0,xaxt='n',yaxt='n',bty='n',pch='',ylab='Prédictions PM10', |
| 35 | xlab='Temps',ylim=yrange,main="Courbes PM10 prédites") |
| 36 | for (i in 401:430) |
| 37 | { |
| 38 | if (!any(is.na(p_mix$forecasts[[i]]))) |
| 39 | { |
| 40 | par(new=TRUE) |
| 41 | plot(p_mix$forecasts[[i]], type="l", ylim=yrange, xlab="", ylab="") |
| 42 | } |
| 43 | } |
| 44 | @ |
| 45 | |
| 46 | L'appel à \emph{predictPM10()} ci-dessus se traduit par : |
| 47 | \begin{enumerate} |
| 48 | \item charger les données découpées selon le temps universel, en segments de $24h$ de $7h15$ à |
| 49 | $7h$ le lendemain ; |
| 50 | \item commencer la prédiction au jour $400$, terminer au jour $400+30-1 = 429$ ; |
| 51 | \item utiliser la méthode "Neighbors" qui place plus de poids sur les voisins de la courbe de |
| 52 | PM10 du jour courant, en tenant compte de tout l'historique ; |
| 53 | \item raccorder continûment la prévision centrée aux mesures sur le dernier bloc de $24h$. |
| 54 | \end{enumerate} |
| 55 | |
| 56 | \subsection{Acquisition des données} |
| 57 | |
| 58 | Compte-tenu de la nature hétérogène des données utilisées $-$ fonctionnelles pour les PM10, |
| 59 | vectorielles pour les variables exogènes $-$, celles-ci sont organisées sous forme d'une liste |
| 60 | \emph{data}, la $i^{eme}$ cellule correspondant aux données disponibles au $i^{eme}$ jour à |
| 61 | l'heure $H$ de prédiction choisie (0h15, 7h15 ou 13h15) : c'est-à-dire les valeurs des PM10 de |
| 62 | $H-24h$ à $H-15m$, ainsi que les variables météo mesurées du dernier jour complet avant l'heure |
| 63 | $H$, et les variables météo prédites pour la période de $0h15$ à $0h$ du jour courant.\\ |
| 64 | |
| 65 | Exemple :\\ |
| 66 | <<data>>= |
| 67 | #Le premier argument indique la zone horaire souhaitée ; "GMT" ou "local" |
| 68 | #pour l'heure française, ou tout autre fuseau horaire. |
| 69 | data = getData("GMT", "7h") |
| 70 | @ |
| 71 | |
| 72 | \subsection{Prédiction} |
| 73 | |
| 74 | Deux types de prévisions du prochain bloc de $24h$ sont à distinguer : |
| 75 | \begin{itemize} |
| 76 | \item prévision de la forme (centrée) ; |
| 77 | \item prévision du niveau. |
| 78 | \end{itemize} |
| 79 | |
| 80 | \noindent Si l'on choisit de raccorder la prévision de la forme au dernier PM10 mesuré, alors le niveau n'a |
| 81 | pas à être prédit (d'où l'argument \texttt{NULL} dans l'appel principal). Dans le cas contraire il faut |
| 82 | préciser une méthode ; seule la persistance est actuellement implémentée. la méthode de prévision |
| 83 | de forme "Neighbors" est détaillée ci-après (voir aussi le fichier S\_Neighbors.R).\\ |
| 84 | |
| 85 | \begin{enumerate} |
| 86 | \item \textbf{Préparation des données} : calcul des niveaux sur 24h, fenêtrage si demandé |
| 87 | (paramètre "memory"). |
| 88 | \item \textbf{Optimisation des paramètres d'échelle} : via la fonction \emph{optim()} |
| 89 | minimisant la somme des 45 dernières erreurs jounalières L2. |
| 90 | \item \textbf{Prédiction finale} : une fois le (ou les, si "simtype" vaut "mix") paramètre |
| 91 | d'échelle $h$ déterminé, les similarités sont évaluées sur les variables exogènes et/ou |
| 92 | endogènes, sous la forme $s(i,j) = \mbox{exp}\left(-\frac{\mbox{dist}^2(i,j)}{h^2}\right)$. |
| 93 | La formule indiquée plus haut dans le rapport est alors appliquée. |
| 94 | \end{enumerate} |
| 95 | |
| 96 | Exemple :\\ |
| 97 | <<forecasts>>= |
| 98 | forecasts = as.list(rep(NA, length(data))) |
| 99 | for (i in 400:429) |
| 100 | { |
| 101 | #forecast with data up to index i |
| 102 | forecasts[[i+1]] = getForecasts(data[1:i], "Neighbors", NULL, 0, |
| 103 | "direct", simtype="mix") |
| 104 | } |
| 105 | @ |
| 106 | |
| 107 | \subsection{Calcul des erreurs} |
| 108 | |
| 109 | Pour chacun des instants à prévoir jusqu'à minuit du jour courant, on calcule l'erreur moyenne |
| 110 | sur tous les instants similaires du passé (sur la plage prédite, dans l'exemple 401 à 430). Deux |
| 111 | types d'erreurs sont considérées : |
| 112 | \begin{itemize} |
| 113 | \item l'erreur "L1" égale à la valeur absolue entre la mesure et la prédiction ; |
| 114 | \item l'erreur "MAPE" égale à l'erreur L1 normalisée par la mesure. |
| 115 | \end{itemize} |
| 116 | |
| 117 | Code :\\ |
| 118 | <<errors, out.width='7cm', out.height='7cm', fig.show='hold'>>= |
| 119 | e = getErrors(data, forecasts) |
| 120 | #Erreurs absolues, point par point, moyennées sur les 30 jours |
| 121 | plot(e$L1, type="l", xlab="Temps", ylab="Erreur absolue") |
| 122 | #Erreurs relatives, point par point, moyennées sur les 30 jours |
| 123 | plot(e$MAPE, type="l", xlab="Temps", ylab="Erreur relative") |
| 124 | @ |
| 125 | |
| 126 | \subsection{Autres expériences numériques} |
| 127 | |
| 128 | <<others1, out.width='7cm', out.height='7cm', fig.show='hold'>>= |
| 129 | p_endo = predictPM10("GMT", "7h", 400, 30, "Neighbors", NULL, 0, |
| 130 | "direct", simtype="endo") |
| 131 | p_exo = predictPM10("GMT", "7h", 400, 30, "Neighbors", NULL, 0, |
| 132 | "direct", simtype="exo") |
| 133 | yrange_L1 = range(p_mix$errors$L1, p_endo$errors$L1, p_exo$errors$L1) |
| 134 | plot(p_mix$errors$L1, type="l", main="Erreur L1", xlab="Temps", |
| 135 | ylab="Erreur absolue", ylim=yrange_L1) ; par(new=TRUE) |
| 136 | plot(p_endo$errors$L1, type="l", col=2, xlab="", ylab="", |
| 137 | ylim=yrange_L1) ; par(new=TRUE) |
| 138 | plot(p_exo$errors$L1, type="l", col=3, xlab="", ylab="", |
| 139 | ylim=yrange_L1) |
| 140 | yrange_MAPE = |
| 141 | range(p_mix$errors$MAPE, p_endo$errors$MAPE, p_exo$errors$MAPE) |
| 142 | plot(p_mix$errors$MAPE, type="l", main="Erreur MAPE", xlab="Temps", |
| 143 | ylab="Erreur relative", ylim=yrange_MAPE) ; par(new=TRUE) |
| 144 | plot(p_endo$errors$MAPE, type="l", col=2, xlab="", ylab="", |
| 145 | ylim=yrange_MAPE) ; par(new=TRUE) |
| 146 | plot(p_exo$errors$MAPE, type="l", col=3, xlab="", ylab="", |
| 147 | ylim=yrange_MAPE) |
| 148 | |
| 149 | #Ne tenir compte que des similarités sur les variables exogènes semble |
| 150 | #conduire à l'erreur la plus faible. |
| 151 | @ |
| 152 | |
| 153 | <<others2, out.width='7cm', out.height='7cm', fig.show='hold'>>= |
| 154 | p_exo_h = predictPM10("GMT", "7h", 400, 30, "Neighbors", NULL, 0, |
| 155 | "direct", simtype="exo", h_window=0.25) |
| 156 | plot(p_exo_h$errors$L1, type="l", main="Erreur L1", xlab="Temps", |
| 157 | ylab="Erreur absolue") |
| 158 | plot(p_exo_h$errors$MAPE, type="l", main="Erreur MAPE", xlab="Temps", |
| 159 | ylab="Erreur relative") |
| 160 | |
| 161 | #Diminuer la fenêtre n'améliore pas les performances moyennes |
| 162 | #(car les données individuelles sont très variables). |
| 163 | @ |
| 164 | |
| 165 | <<others3, out.width='7cm', out.height='7cm', fig.show='hold'>>= |
| 166 | p_exo_s = predictPM10("GMT", "7h", 400, 30, "Neighbors", "Persistence", |
| 167 | 0, "separate", simtype="exo") |
| 168 | plot(p_exo_s$errors$L1, type="l", main="Erreur L1", xlab="Temps", |
| 169 | ylab="Erreur absolue") |
| 170 | plot(p_exo_s$errors$MAPE, type="l", main="Erreur MAPE", xlab="Temps", |
| 171 | ylab="Erreur relative") |
| 172 | |
| 173 | #Prédire séparément forme et niveau mène à une erreur plus grande ; |
| 174 | #d'autres méthodes de prévision du niveau doivent tout de même être testées. |
| 175 | @ |
| 176 | |
| 177 | \subsection{Suite du travail} |
| 178 | |
| 179 | Le type de jour n'est pas pris en compte dans la recherche de voisins ; cela diminuerait |
| 180 | nettement le nombre de similarités retenues, mais pourrait significativement améliorer les |
| 181 | prévisions.\\ |
| 182 | |
| 183 | \noindent Il serait intéressant également de disposer de plusieurs méthodes de prédiction, pour |
| 184 | par exemple les agréger à l'aide de méthodes similaires à celles du précédent contrat. |
| 185 | |
| 186 | \end{document} |