refactor reports.gj, prepare also 13h report
[talweg.git] / reports / OLD / report_OLD.gj
1 -----
2 # Résultats numériques
3
4 Cette partie montre les résultats obtenus avec des variantes de l'algorithme décrit au
5 chapitre 5, en utilisant le package présenté au chapitre 6.
6 Les ........... options ...........
7 Cet algorithme est
8 systématiquement comparé à deux approches naïves :
9
10 * la moyenne des lendemains des jours de même type dans tout le passé, c'est-à-dire
11 prédiction = moyenne de tous les mardis passés si le jour courant est un lundi.
12 * la persistence, reproduisant le jour courant ou allant chercher le lendemain de la
13 dernière journée de même type (même principe que ci-dessus ; argument "same\_day").
14
15 Concernant l'algorithme principal à voisins, trois variantes sont étudiées dans cette
16 partie :
17
18 * avec simtype="mix" et raccordement "Neighbors" dans le cas "non local", i.e. on va
19 chercher des voisins n'importe où du moment qu'ils correspondent au premier élément d'un
20 couple de deux jours consécutifs sans valeurs manquantes.
21 * avec simtype="endo" + raccordement "Neighbors" puis simtype="none" + raccordement
22 "Zero" (sans ajustement) dans le cas "local" : voisins de même niveau de pollution et
23 même saison.
24
25 Pour chaque période retenue $-$ chauffage, épandage, semaine non polluée $-$ les erreurs
26 de prédiction sont d'abord affichées, puis quelques graphes de courbes réalisées/prévues
27 (sur le jour "en moyenne le plus facile" à gauche, et "en moyenne le plus difficile" à
28 droite). Ensuite plusieurs types de graphes apportant des précisions sur la nature et la
29 difficulté du problème viennent compléter ces premières courbes. Concernant les graphes
30 de filaments, la moitié gauche du graphe correspond aux jours similaires au jour courant,
31 tandis que la moitié droite affiche les lendemains : ce sont donc les voisinages tels
32 qu'utilisés dans l'algorithme.
33 <%
34 list_titles = ['Pollution par chauffage','Pollution par épandage','Semaine non polluée']
35 list_indices = ['indices_ch', 'indices_ep', 'indices_np']
36 %>
37 -----r
38 library(talweg)
39
40 P = ${P} #instant de prévision
41 H = ${H} #horizon (en heures)
42
43 ts_data = read.csv(system.file("extdata","pm10_mesures_H_loc_report.csv",
44 package="talweg"))
45 exo_data = read.csv(system.file("extdata","meteo_extra_noNAs.csv",
46 package="talweg"))
47 # NOTE: 'GMT' because DST gaps are filled and multiple values merged in
48 # above dataset. Prediction from P+1 to P+H included.
49 data = getData(ts_data, exo_data, input_tz = "GMT", working_tz="GMT",
50 predict_at=P)
51
52 indices_ch = seq(as.Date("2015-01-18"),as.Date("2015-01-24"),"days")
53 indices_ep = seq(as.Date("2015-03-15"),as.Date("2015-03-21"),"days")
54 indices_np = seq(as.Date("2015-04-26"),as.Date("2015-05-02"),"days")
55 % for i in range(3):
56 -----
57 ##<h2 style="color:blue;font-size:2em">${list_titles[i]}</h2>
58 ${"##"} ${list_titles[i]}
59 -----r
60 p1 = computeForecast(data, ${list_indices[i]}, "Neighbors", "Neighbors", horizon=H,
61 simtype="mix", local=FALSE)
62 p2 = computeForecast(data, ${list_indices[i]}, "Neighbors", "Neighbors", horizon=H,
63 simtype="endo", local=TRUE)
64 p3 = computeForecast(data, ${list_indices[i]}, "Neighbors", "Zero", horizon=H,
65 simtype="none", local=TRUE)
66 p4 = computeForecast(data, ${list_indices[i]}, "Average", "Zero", horizon=H)
67 p5 = computeForecast(data, ${list_indices[i]}, "Persistence", "Zero", horizon=H,
68 same_day=${'TRUE' if loop.index < 2 else 'FALSE'})
69 -----r
70 e1 = computeError(data, p1, H)
71 e2 = computeError(data, p2, H)
72 e3 = computeError(data, p3, H)
73 e4 = computeError(data, p4, H)
74 e5 = computeError(data, p5, H)
75 options(repr.plot.width=9, repr.plot.height=7)
76 plotError(list(e1, e5, e4, e2, e3), cols=c(1,2,colors()[258],4,6))
77
78 # noir: Neighbors non-local (p1), bleu: Neighbors local endo (p2),
79 # mauve: Neighbors local none (p3), vert: moyenne (p4),
80 # rouge: persistence (p5)
81
82 ##############TODO: expliquer "endo" "none"......etc
83 ## ajouter fenêtres essais dans rapport. --> dans chapitre actuel.
84 ## re-ajouter annexe sur ancienne méthode exo/endo/mix
85 ## ---------> fenetres comment elles sont optimisées
86 #--------> ajouter à la fin quelques graphes montrant/comparant autres méthodes
87 #chapitre résumé avec différents essais conclusions. ---> synthèse des essais réalisés,
88 #avec sous-paragraphes avec conclusions H3/H17 sans surprises on améliore les choses,
89 #mais il y a des situations où c'est pas mieux.
90 #---------> fichier tex réinsérer synthèse de l'ensemble des essais réalisés.
91 #++++++++ ajouter à 13h
92
93 sum_p123 = e1$abs$indices + e2$abs$indices + e3$abs$indices
94 i_np = which.min(sum_p123) #indice de (veille de) jour "facile"
95 i_p = which.max(sum_p123) #indice de (veille de) jour "difficile"
96 -----
97 % if i == 0:
98 L'erreur absolue dépasse 20 sur 1 à 2 jours suivant les modèles (graphe en haut à
99 droite). ##C'est au-delà de ce que l'on aimerait voir (disons +/- 5 environ).
100 Sur cet
101 exemple le modèle à voisins "contraint" (local=TRUE) utilisant des pondérations basées
102 sur les similarités de forme (simtype="endo") obtient en moyenne les meilleurs résultats,
103 avec un MAPE restant en général inférieur à 30% de 8h à 19h (7+1 à 7+12 : graphe en bas à
104 gauche).
105 % elif i == 1:
106 Il est difficile dans ce cas de déterminer une méthode meilleure que les autres : elles
107 donnent toutes de plutôt mauvais résultats, avec une erreur absolue moyennée sur la
108 journée dépassant presque toujours 15 (graphe en haut à droite).
109 % else:
110 Dans ce cas plus favorable les intensité des erreurs absolues ont clairement diminué :
111 elles restent souvent en dessous de 5. En revanche le MAPE moyen reste au-delà de 20%, et
112 même souvent plus de 30%. Comme dans le cas de l'épandage on constate une croissance
113 globale de la courbe journalière d'erreur absolue moyenne (en haut à gauche) ; ceci peut
114 être dû au fait que l'on ajuste le niveau du jour à prédire en le recollant sur la
115 dernière valeur observée.
116 % endif
117 -----r
118 options(repr.plot.width=9, repr.plot.height=4)
119 par(mfrow=c(1,2))
120
121 plotPredReal(data, p1, i_np); title(paste("PredReal p1 day",i_np))
122 plotPredReal(data, p1, i_p); title(paste("PredReal p1 day",i_p))
123
124 plotPredReal(data, p2, i_np); title(paste("PredReal p2 day",i_np))
125 plotPredReal(data, p2, i_p); title(paste("PredReal p2 day",i_p))
126
127 plotPredReal(data, p3, i_np); title(paste("PredReal p3 day",i_np))
128 plotPredReal(data, p3, i_p); title(paste("PredReal p3 day",i_p))
129
130 # Bleu : prévue ; noir : réalisée
131 -----
132 % if i == 0:
133 La courbe non centrée du jour facile à prévoir (en noir),
134 ##Le jour "facile à prévoir",
135 à gauche, se décompose en deux modes : un léger vers 10h
136 (7+3), puis un beaucoup plus marqué vers 19h (7+12). Ces deux modes sont retrouvés par
137 les trois variantes de l'algorithme à voisins, bien que l'amplitude soit mal prédite.
138 Concernant le jour "difficile à prévoir" (à droite) il y a deux pics en tout début et toute fin de
139 journée (à 9h et 23h), qui ne sont pas du tout anticipés par les méthodes ; la grande
140 amplitude de ces pics explique alors l'intensité de l'erreur observée.
141 % elif i == 1:
142 Dans le cas d'un jour "facile" à prédire $-$ à gauche $-$ la forme est plus ou moins
143 retrouvée, mais le niveau moyen est trop bas (courbe en bleu). Concernant le jour
144 "difficile" à droite, non seulement la forme n'est pas anticipée mais surtout le niveau
145 prédit est très inférieur au niveau de pollution observé. Comme on le voit ci-dessous
146 cela découle d'un manque de voisins au comportement similaire.
147 % else:
148 La forme est raisonnablement retrouvée pour les méthodes "locales", l'autre version
149 lissant trop les prédictions. Le biais reste cependant important, surtout en fin de
150 journée sur le jour "difficile".
151 % endif
152 -----r
153 par(mfrow=c(1,2))
154 f_np1 = computeFilaments(data, p1, i_np, plot=TRUE)
155 title(paste("Filaments p1 day",i_np))
156 f_p1 = computeFilaments(data, p1, i_p, plot=TRUE)
157 title(paste("Filaments p1 day",i_p))
158
159 f_np2 = computeFilaments(data, p2, i_np, plot=TRUE)
160 title(paste("Filaments p2 day",i_np))
161 f_p2 = computeFilaments(data, p2, i_p, plot=TRUE)
162 title(paste("Filaments p2 day",i_p))
163 -----
164 % if i == 0:
165 Les voisins du jour courant (période de 24h allant de 8h à 7h le lendemain) sont affichés
166 avec un trait d'autant plus sombre qu'ils sont proches. On constate dans le cas non
167 contraint (en haut) une grande variabilité des lendemains, très nette sur le graphe en
168 haut à droite. Ceci indique une faible corrélation entre la forme d'une courbe sur une
169 période de 24h et la forme sur les 24h suivantes ; **cette observation est la source des
170 difficultés rencontrées par l'algorithme sur ce jeu de données.**
171 % elif i == 1:
172 Les observations sont les mêmes qu'au paragraphe précédent : trop de variabilité des
173 lendemains (et même des voisins du jour courant).
174 % else:
175 Les graphes de filaments ont encore la même allure, avec une assez grande variabilité
176 observée. Cette observation est cependant trompeuse, comme l'indique plus bas le graphe
177 de variabilité relative.
178 % endif
179 -----r
180 par(mfrow=c(1,2))
181 plotFilamentsBox(data, f_np1); title(paste("FilBox p1 day",i_np))
182 plotFilamentsBox(data, f_p1); title(paste("FilBox p1 day",i_p))
183
184 ## Questions :
185 #7h VS 13h
186 #est-ce que prévoir 24h ou 13 ou 3 facilite.
187 #amplitude erreur raisonnable ? probleme facile difficile ?
188 #place des exogènes ?
189 #H = ?
190 #épandage > chauffage > np
191
192 # En pointillés la courbe du jour courant + lendemain (à prédire)
193 -----
194 % if i == 0:
195 Sur cette boxplot fonctionnelle (voir la fonction fboxplot() du package R "rainbow") on
196 constate essentiellement deux choses : le lendemain d'un voisin "normal" peut se révéler
197 être une courbe atypique, fort éloignée de ce que l'on souhaite prédire (courbes bleue et
198 rouge à gauche) ; et, dans le cas d'une courbe à prédire atypique (à droite) la plupart
199 des voisins sont trop éloignés de la forme à prédire et forcent ainsi un aplatissement de
200 la prédiction.
201 % elif i == 1:
202 On constate la présence d'un voisin au lendemain complètement atypique avec un pic en
203 début de journée (courbe en vert à gauche), et d'un autre phénomène semblable avec la
204 courbe rouge sur le graphe de droite. Ajouté au fait que le lendemain à prévoir est
205 lui-même un jour "hors norme", cela montre l'impossibilité de bien prévoir une courbe en
206 utilisant l'algorithme à voisins.
207 % else:
208 On peut réappliquer les mêmes remarques qu'auparavant sur les boxplots fonctionnels :
209 lendemains de voisins atypiques, courbe à prévoir elle-même légèrement "hors norme".
210 % endif
211 -----r
212 par(mfrow=c(1,2))
213 plotRelVar(data, f_np1); title(paste("StdDev p1 day",i_np))
214 plotRelVar(data, f_p1); title(paste("StdDev p1 day",i_p))
215
216 plotRelVar(data, f_np2); title(paste("StdDev p2 day",i_np))
217 plotRelVar(data, f_p2); title(paste("StdDev p2 day",i_p))
218
219 # Variabilité globale en rouge ; sur les voisins (+ lendemains) en noir
220 -----
221 % if i == 0:
222 Ces graphes viennent confirmer l'impression visuelle après observation des filaments. En
223 effet, la variabilité globale en rouge (écart-type heure par heure sur l'ensemble des
224 couples "aujourd'hui/lendemain"du passé) devrait rester nettement au-dessus de la
225 variabilité locale, calculée respectivement sur un voisinage d'une soixantaine de jours
226 (pour p1) et d'une dizaine de jours (pour p2). Or on constate que ce n'est pas du tout le
227 cas sur la période "lendemain", sauf en partie pour p2 le jour 4 $-$ mais ce n'est pas
228 suffisant.
229 % elif i == 1:
230 Comme précédemment les variabilités locales et globales sont confondues dans les parties
231 droites des graphes $-$ sauf pour la version "locale" sur le jour "facile"; mais cette
232 bonne propriété n'est pas suffisante si l'on ne trouve pas les bons poids à appliquer.
233 % else:
234 Cette fois la situation idéale est observée : la variabilité globale est nettement
235 au-dessus de la variabilité locale. Bien que cela ne suffise pas à obtenir de bonnes
236 prédictions de forme, on constate au moins l'amélioration dans la prédiction du niveau.
237 % endif
238 -----r
239 par(mfrow=c(1,2))
240 plotSimils(p1, i_np); title(paste("Weights p1 day",i_np))
241 plotSimils(p1, i_p); title(paste("Weights p1 day",i_p))
242
243 plotSimils(p2, i_np); title(paste("Weights p2 day",i_np))
244 plotSimils(p2, i_p); title(paste("Weights p2 day",i_p))
245 -----
246 % if i == 0:
247 Les poids se concentrent près de 0 dans le cas "non local" (p1), et se répartissent assez
248 uniformément dans [ 0, 0.2 ] dans le cas "local" (p2). C'est ce que l'on souhaite
249 observer pour éviter d'effectuer une simple moyenne.
250 % elif i == 1:
251 En comparaison avec le pragraphe précédent on retrouve le même (bon) comportement des
252 poids pour la version "non locale". En revanche la fenêtre optimisée est trop grande sur
253 le jour "facile" pour la méthode "locale" (voir affichage ci-dessous) : il en résulte des
254 poids tous semblables autour de 0.084, l'algorithme effectue donc une moyenne simple $-$
255 expliquant pourquoi les courbes mauve et bleue sont très proches sur le graphe d'erreurs.
256 % else:
257 Concernant les poids en revanche, deux cas a priori mauvais se cumulent :
258
259 * les poids dans le cas "non local" ne sont pas assez concentrés autour de 0, menant à
260 un lissage trop fort $-$ comme observé sur les graphes des courbes réalisées/prévues ;
261 * les poids dans le cas "local" sont trop semblables (à cause de la trop grande fenêtre
262 optimisée par validation croisée, cf. ci-dessous), résultant encore en une moyenne simple
263 $-$ mais sur moins de jours, plus proches du jour courant.
264 % endif
265 -----r
266 # Fenêtres sélectionnées dans ]0,7] :
267 # "non-local" 2 premières lignes, "local" ensuite
268 p1$getParams(i_np)$window
269 p1$getParams(i_p)$window
270
271 p2$getParams(i_np)$window
272 p2$getParams(i_p)$window
273 % endfor
274 -----
275 ${"##"} Bilan
276
277 Nos algorithmes à voisins ne sont pas adaptés à ce jeu de données où la forme varie
278 considérablement d'un jour à l'autre.
279 Toutefois, un espoir reste permis par exemple en aggrégeant les courbes spatialement (sur
280 plusieurs stations situées dans la même agglomération ou dans une même zone).
281 ##Plus généralement cette décorrélation de forme rend
282 ##ardue la tâche de prévision pour toute autre méthode $-$ du moins, nous ne savons pas
283 ##comment procéder pour parvenir à une bonne précision.