Commit | Line | Data |
---|---|---|
8eafefbc | 1 | ----- |
4d376294 | 2 | # Résultats numériques |
b6233fa6 | 3 | |
882ae735 BA |
4 | Cette partie montre les résultats obtenus avec des variantes de l'algorithme décrit à la |
5 | section 4, en utilisant le package présenté au chapitre précédent. Cet algorithme est | |
6 | systématiquement comparé à deux approches naïves : | |
63ff1ecb | 7 | |
b6233fa6 | 8 | * la moyenne des lendemains des jours "similaires" dans tout le passé, c'est-à-dire |
4d376294 | 9 | prédiction = moyenne de tous les mardis passés si le jour courant est un lundi. |
b6233fa6 BA |
10 | * la persistence, reproduisant le jour courant ou allant chercher le lendemain de la |
11 | dernière journée "similaire" (même principe que ci-dessus ; argument "same\_day"). | |
12 | ||
9b9bb2d4 | 13 | Concernant l'algorithme principal à voisins, deux variantes sont comparées dans cette |
b6233fa6 BA |
14 | partie : |
15 | ||
16 | * avec simtype="mix" et raccordement "Neighbors" dans le cas "non local", i.e. on va | |
17 | chercher des voisins n'importe où du moment qu'ils correspondent au premier élément d'un | |
18 | couple de deux jours consécutifs sans valeurs manquantes. | |
9b9bb2d4 BA |
19 | * avec simtype="none" (moyenne simple) et raccordement=NULL (aucun ajustement après |
20 | moyenne des courbes) dans le cas "local" : voisins de même niveau de pollution et même | |
21 | saison. | |
b6233fa6 BA |
22 | |
23 | Pour chaque période retenue $-$ chauffage, épandage, semaine non polluée $-$ les erreurs | |
24 | de prédiction sont d'abord affichées, puis quelques graphes de courbes réalisées/prévues | |
25 | (sur le jour "en moyenne le plus facile" à gauche, et "en moyenne le plus difficile" à | |
26 | droite). Ensuite plusieurs types de graphes apportant des précisions sur la nature et la | |
27 | difficulté du problème viennent compléter ces premières courbes. Concernant les graphes | |
882ae735 BA |
28 | de filaments, la moitié droite du graphe correspond aux jours similaires au jour courant, |
29 | tandis que la moitié gauche affiche les jours précédents : ce sont donc les voisinages | |
30 | tels qu'utilisés dans l'algorithme. | |
63ff1ecb | 31 | <% |
b6233fa6 | 32 | list_titles = ['Pollution par chauffage','Pollution par épandage','Semaine non polluée'] |
63ff1ecb BA |
33 | list_indices = ['indices_ch', 'indices_ep', 'indices_np'] |
34 | %> | |
63ff1ecb | 35 | -----r |
63ff1ecb BA |
36 | library(talweg) |
37 | ||
1e8327df BA |
38 | P = ${P} #première heure de prévision |
39 | H = ${H} #dernière heure de prévision | |
d09b09b0 | 40 | |
b6233fa6 BA |
41 | ts_data = read.csv(system.file("extdata","pm10_mesures_H_loc_report.csv", |
42 | package="talweg")) | |
43 | exo_data = read.csv(system.file("extdata","meteo_extra_noNAs.csv", | |
44 | package="talweg")) | |
45 | # NOTE: 'GMT' because DST gaps are filled and multiple values merged in | |
46 | # above dataset. Prediction from P+1 to P+H included. | |
1e8327df | 47 | data = getData(ts_data, exo_data) |
63ff1ecb | 48 | |
882ae735 BA |
49 | indices_ch = seq(as.Date("2015-01-19"),as.Date("2015-01-25"),"days") |
50 | indices_ep = seq(as.Date("2015-03-16"),as.Date("2015-03-22"),"days") | |
51 | indices_np = seq(as.Date("2015-04-27"),as.Date("2015-05-03"),"days") | |
ff5df8e3 | 52 | % for i in range(3): |
63ff1ecb | 53 | ----- |
8eafefbc BA |
54 | ##<h2 style="color:blue;font-size:2em">${list_titles[i]}</h2> |
55 | ${"##"} ${list_titles[i]} | |
63ff1ecb | 56 | -----r |
1e8327df BA |
57 | p1 = computeForecast(data, ${list_indices[i]}, "Neighbors", "Neighbors", predict_from=P, |
58 | horizon=H, simtype="mix", local=FALSE) | |
882ae735 | 59 | p2 = computeForecast(data, ${list_indices[i]}, "Neighbors", NULL, predict_from=P, |
1e8327df | 60 | horizon=H, simtype="none", local=TRUE) |
9b9bb2d4 | 61 | p3 = computeForecast(data, ${list_indices[i]}, "Average", "Zero", predict_from=P, |
1e8327df | 62 | horizon=H) |
9b9bb2d4 | 63 | p4 = computeForecast(data, ${list_indices[i]}, "Persistence", "Zero", predict_from=P, |
1e8327df | 64 | horizon=H, same_day=${'TRUE' if loop.index < 2 else 'FALSE'}) |
63ff1ecb | 65 | -----r |
1e8327df BA |
66 | e1 = computeError(data, p1, P, H) |
67 | e2 = computeError(data, p2, P, H) | |
68 | e3 = computeError(data, p3, P, H) | |
69 | e4 = computeError(data, p4, P, H) | |
63ff1ecb | 70 | options(repr.plot.width=9, repr.plot.height=7) |
9b9bb2d4 | 71 | plotError(list(e1, e4, e3, e2), cols=c(1,2,colors()[258],4)) |
63ff1ecb | 72 | |
9b9bb2d4 BA |
73 | # noir: Neighbors non-local (p1), bleu: Neighbors local (p2), |
74 | # vert: moyenne (p3), rouge: persistence (p4) | |
63ff1ecb | 75 | |
882ae735 | 76 | sum_p23 = e2$abs$indices + e3$abs$indices |
9b9bb2d4 BA |
77 | i_np = which.min(sum_p23) #indice de jour "facile" |
78 | i_p = which.max(sum_p23) #indice de jour "difficile" | |
b6233fa6 | 79 | ----- |
12119d21 | 80 | % if i == 0: |
9b9bb2d4 BA |
81 | L'erreur absolue -- en haut à gauche -- reste modérée pour les meilleurs modèles |
82 | (variantes à voisins), ne dépassant 10 que deux jours. Les deux modèles naïfs ont des | |
83 | erreurs similaires sauf sur la période "difficile" (jours 4 à 6), sur laquelle on gagne | |
84 | donc à chercher des jours similaires pour effectuer la prévision. | |
85 | Le MAPE reste en général inférieur à 35% pour les meilleurs méthodes. | |
12119d21 | 86 | % elif i == 1: |
9b9bb2d4 BA |
87 | Le modèle à voisins avec contrainte de localité obtient ici les meilleurs résultats, son |
88 | erreur étant clairement en dessous des autres à partir du jour 4 (graphe en haut à | |
89 | droite). Le MAPE jour après jour est du même ordre que précédemment pour cette méthode | |
90 | (35%, graphe en bas à droite) sauf un jour sur lequel le MAPE explose. | |
8eafefbc | 91 | % else: |
b6233fa6 | 92 | Dans ce cas plus favorable les intensité des erreurs absolues ont clairement diminué : |
9b9bb2d4 BA |
93 | elles sont souvent en dessous de 5. En revanche le MAPE moyen reste en général au-delà de |
94 | 20%. Comme dans le cas de l'épandage on constate une croissance globale de la courbe | |
95 | journalière d'erreur absolue moyenne (en haut à gauche) -- sauf pour la méthode à voisins | |
96 | "locale" ; ceci peut être dû au fait que l'on ajuste le niveau du jour à prédire en le | |
97 | recollant sur la dernière valeur observée (sauf pour "Neighbors local"). | |
b6233fa6 | 98 | % endif |
63ff1ecb BA |
99 | -----r |
100 | options(repr.plot.width=9, repr.plot.height=4) | |
101 | par(mfrow=c(1,2)) | |
102 | ||
445e7bbc BA |
103 | plotPredReal(data, p1, i_np); title(paste("PredReal p1 day",i_np)) |
104 | plotPredReal(data, p1, i_p); title(paste("PredReal p1 day",i_p)) | |
63ff1ecb | 105 | |
445e7bbc BA |
106 | plotPredReal(data, p2, i_np); title(paste("PredReal p2 day",i_np)) |
107 | plotPredReal(data, p2, i_p); title(paste("PredReal p2 day",i_p)) | |
63ff1ecb | 108 | |
9b9bb2d4 | 109 | # Bleu : prévue ; noir : réalisée (confondues jusqu'à predict_from-1) |
b6233fa6 | 110 | ----- |
12119d21 | 111 | % if i == 0: |
b6233fa6 BA |
112 | Le jour "facile à prévoir", à gauche, se décompose en deux modes : un léger vers 10h |
113 | (7+3), puis un beaucoup plus marqué vers 19h (7+12). Ces deux modes sont retrouvés par | |
9b9bb2d4 | 114 | les deux variantes de l'algorithme à voisins, bien que l'amplitude soit mal prédite. |
4d376294 BA |
115 | Concernant le jour "difficile à prévoir" (à droite) il y a deux pics en tout début et |
116 | toute fin de journée (à 9h et 23h), qui ne sont pas du tout anticipés par les méthodes ; | |
117 | la grande amplitude de ces pics explique alors l'intensité de l'erreur observée. | |
12119d21 | 118 | % elif i == 1: |
9b9bb2d4 BA |
119 | Dans le cas d'un jour "facile" à prédire $-$ à gauche $-$ la forme est plutôt bien |
120 | retrouvée, ainsi que le niveau moyen pour la méthode sans contrainte de localité | |
121 | (dans l'autre, l'algorithme a probablement écarté trop de voisins potentiels). | |
122 | Concernant le jour "difficile" à droite, non seulement la forme n'est pas anticipée mais | |
123 | surtout le niveau prédit est largement supérieur au niveau de pollution observé -- dans | |
124 | une moindre mesure toutefois pour la variante "locale". | |
8eafefbc | 125 | % else: |
9b9bb2d4 BA |
126 | L'impression visuelle est plutôt mauvaise dans ce cas, mais les écart étant minimes les |
127 | erreurs au final ne sont pas très importantes. De plus deux des quatres graphes sont | |
128 | satisfaisants (en haut à droite et en bas à gauche : forme + niveau acceptables. | |
b6233fa6 | 129 | % endif |
63ff1ecb BA |
130 | -----r |
131 | par(mfrow=c(1,2)) | |
9b9bb2d4 BA |
132 | |
133 | f_np1 = computeFilaments(data, p1, i_np, plot=TRUE) | |
134 | title(paste("Filaments p1 day",i_np)) | |
135 | ||
136 | f_p1 = computeFilaments(data, p1, i_p, plot=TRUE) | |
137 | title(paste("Filaments p1 day",i_p)) | |
138 | ||
139 | f_np2 = computeFilaments(data, p2, i_np, plot=TRUE) | |
140 | title(paste("Filaments p2 day",i_np)) | |
141 | ||
142 | f_p2 = computeFilaments(data, p2, i_p, plot=TRUE) | |
143 | title(paste("Filaments p2 day",i_p)) | |
b6233fa6 | 144 | ----- |
12119d21 | 145 | % if i == 0: |
b6233fa6 BA |
146 | Les voisins du jour courant (période de 24h allant de 8h à 7h le lendemain) sont affichés |
147 | avec un trait d'autant plus sombre qu'ils sont proches. On constate dans le cas non | |
148 | contraint (en haut) une grande variabilité des lendemains, très nette sur le graphe en | |
149 | haut à droite. Ceci indique une faible corrélation entre la forme d'une courbe sur une | |
150 | période de 24h et la forme sur les 24h suivantes ; **cette observation est la source des | |
151 | difficultés rencontrées par l'algorithme sur ce jeu de données.** | |
12119d21 | 152 | % elif i == 1: |
b6233fa6 | 153 | Les observations sont les mêmes qu'au paragraphe précédent : trop de variabilité des |
9b9bb2d4 | 154 | voisins (et ce même le jour précédent). |
8eafefbc | 155 | % else: |
b6233fa6 BA |
156 | Les graphes de filaments ont encore la même allure, avec une assez grande variabilité |
157 | observée. Cette observation est cependant trompeuse, comme l'indique plus bas le graphe | |
158 | de variabilité relative. | |
159 | % endif | |
63ff1ecb BA |
160 | -----r |
161 | par(mfrow=c(1,2)) | |
63ff1ecb | 162 | |
9b9bb2d4 BA |
163 | plotFilamentsBox(data, f_np1, predict_from=P) |
164 | title(paste("FilBox p1 day",i_np)) | |
165 | ||
166 | plotFilamentsBox(data, f_p1, predict_from=P) | |
167 | title(paste("FilBox p1 day",i_p)) | |
168 | ||
169 | # En pointillés la courbe du jour courant (à prédire) + précédent | |
b6233fa6 | 170 | ----- |
12119d21 | 171 | % if i == 0: |
4d376294 | 172 | Sur cette boxplot fonctionnelle (voir la fonction fboxplot() du package R "rainbow") on |
b6233fa6 BA |
173 | constate essentiellement deux choses : le lendemain d'un voisin "normal" peut se révéler |
174 | être une courbe atypique, fort éloignée de ce que l'on souhaite prédire (courbes bleue et | |
175 | rouge à gauche) ; et, dans le cas d'une courbe à prédire atypique (à droite) la plupart | |
176 | des voisins sont trop éloignés de la forme à prédire et forcent ainsi un aplatissement de | |
177 | la prédiction. | |
12119d21 | 178 | % elif i == 1: |
9b9bb2d4 BA |
179 | Concernant le jour "difficile" on constate la présence de voisins au lendemains |
180 | complètement atypiques avec un pic en début de journée (courbes en vert et rouge à | |
181 | droite). Ajouté au fait que le jour à prévoir est lui-même "hors norme", cela montre | |
182 | l'impossibilité de bien prévoir une courbe en utilisant l'algorithme à voisins. | |
8eafefbc | 183 | % else: |
b6233fa6 | 184 | On peut réappliquer les mêmes remarques qu'auparavant sur les boxplots fonctionnels : |
9b9bb2d4 | 185 | voisins atypiques, courbe à prévoir elle-même légèrement "hors norme". |
b6233fa6 | 186 | % endif |
63ff1ecb BA |
187 | -----r |
188 | par(mfrow=c(1,2)) | |
63ff1ecb | 189 | |
9b9bb2d4 BA |
190 | plotRelVar(data, f_np1, predict_from=P) |
191 | title(paste("StdDev p1 day",i_np)) | |
63ff1ecb | 192 | |
9b9bb2d4 BA |
193 | plotRelVar(data, f_p1, predict_from=P) |
194 | title(paste("StdDev p1 day",i_p)) | |
195 | ||
196 | plotRelVar(data, f_np2, predict_from=P) | |
197 | title(paste("StdDev p2 day",i_np)) | |
198 | ||
199 | plotRelVar(data, f_p2, predict_from=P) | |
200 | title(paste("StdDev p2 day",i_p)) | |
201 | ||
202 | # Variabilité globale en rouge ; sur les voisins en noir | |
b6233fa6 | 203 | ----- |
12119d21 | 204 | % if i == 0: |
b6233fa6 BA |
205 | Ces graphes viennent confirmer l'impression visuelle après observation des filaments. En |
206 | effet, la variabilité globale en rouge (écart-type heure par heure sur l'ensemble des | |
9b9bb2d4 | 207 | couples "hier/aujourd'hui" du passé) devrait rester nettement au-dessus de la |
b6233fa6 | 208 | variabilité locale, calculée respectivement sur un voisinage d'une soixantaine de jours |
9b9bb2d4 BA |
209 | (pour p1) et d'une dizaine de jours (pour p2). Or ce n'est pas du tout le cas sur la |
210 | moitié droite, sauf pour le jour "facile" avec l'algorithme "local". | |
12119d21 | 211 | % elif i == 1: |
9b9bb2d4 BA |
212 | Comme précédemment les variabilités locales et globales sont trop proches dans les |
213 | parties droites des graphes pour le jour "difficile". L'allure des graphes est | |
214 | raisonnable ppour l'autre jour, qui est d'ailleurs bien prédit. | |
8eafefbc | 215 | % else: |
b6233fa6 BA |
216 | Cette fois la situation idéale est observée : la variabilité globale est nettement |
217 | au-dessus de la variabilité locale. Bien que cela ne suffise pas à obtenir de bonnes | |
218 | prédictions de forme, on constate au moins l'amélioration dans la prédiction du niveau. | |
219 | % endif | |
63ff1ecb | 220 | -----r |
9b9bb2d4 BA |
221 | plotSimils(p1, i_np) |
222 | title(paste("Weights p1 day",i_np)) | |
63ff1ecb | 223 | |
9b9bb2d4 BA |
224 | plotSimils(p1, i_p) |
225 | title(paste("Weights p1 day",i_p)) | |
226 | ||
227 | # Poids < 1/N à gauche, >= 1/N à droite ; jour facile en haut, difficile en bas | |
b6233fa6 | 228 | ----- |
12119d21 | 229 | % if i == 0: |
9b9bb2d4 BA |
230 | Les poids se concentrent près de 0 : c'est ce que l'on souhaite observer pour éviter |
231 | d'effectuer une simple moyenne. | |
12119d21 | 232 | % elif i == 1: |
9b9bb2d4 BA |
233 | En comparaison avec le paragraphe précédent on retrouve le même (bon) comportement des |
234 | poids pour la version "non locale". | |
8eafefbc | 235 | % else: |
9b9bb2d4 | 236 | Concernant les poids en revanche, deux cas a priori mauvais se cumulent : ... |
b6233fa6 | 237 | % endif |
63ff1ecb | 238 | -----r |
9b9bb2d4 BA |
239 | options(digits=2) |
240 | ||
445e7bbc BA |
241 | p1$getParams(i_np)$window |
242 | p1$getParams(i_p)$window | |
63ff1ecb | 243 | |
9b9bb2d4 | 244 | # Fenêtres sélectionnées dans ]0,7] |
63ff1ecb | 245 | % endfor |
b6233fa6 | 246 | ----- |
8eafefbc | 247 | ${"##"} Bilan |
b6233fa6 | 248 | |
9b9bb2d4 BA |
249 | Nos algorithmes à voisins donnent de meilleurs résultats que les approches naïves |
250 | (persistence, moyenne sur tout le jeu de données). Les erreurs restent cependant assez | |
251 | élevées, notamment en terme de MAPE. Une possible poste d'amélioration consisterait à | |
252 | aggréger les courbes spatialement (sur plusieurs stations situées dans la même | |
4d376294 | 253 | agglomération ou dans une même zone). |