From: Benjamin Auder Date: Thu, 4 May 2017 18:54:11 +0000 (+0200) Subject: update reports, last fixes, cleanup X-Git-Url: https://git.auder.net/variants/current/doc/css/assets/index.css?a=commitdiff_plain;h=9b9bb2d490e356ff0393aec66b137cff0a64803d;p=talweg.git update reports, last fixes, cleanup --- diff --git a/pkg/R/F_Neighbors.R b/pkg/R/F_Neighbors.R index 9d1e3fb..17fdd58 100644 --- a/pkg/R/F_Neighbors.R +++ b/pkg/R/F_Neighbors.R @@ -128,8 +128,6 @@ NeighborsForecaster = R6::R6Class("NeighborsForecaster", # limit=Inf to not censor any day (TODO: finite limit? 60?) tdays = getSimilarDaysIndices(today, data, limit=Inf, same_season=TRUE, days_in=tdays_cut, operational=opera) -# if (length(tdays) <= 1) -# return (NA) # TODO: 10 == magic number tdays = .getConstrainedNeighbs(today, data, tdays, min_neighbs=10) if (length(tdays) == 1) @@ -142,7 +140,7 @@ NeighborsForecaster = R6::R6Class("NeighborsForecaster", } return ( data$getSerie(tdays[1])[predict_from:horizon] ) } - max_neighbs = 10 #TODO: 12 = arbitrary number + max_neighbs = 10 #TODO: 10 or 12 or... ? if (length(tdays) > max_neighbs) { distances2 <- .computeDistsEndo(data, today, tdays, predict_from) @@ -226,11 +224,7 @@ NeighborsForecaster = R6::R6Class("NeighborsForecaster", .getConstrainedNeighbs = function(today, data, tdays, min_neighbs=10) { levelToday = data$getLevelHat(today) -# levelYersteday = data$getLevel(today-1) - distances = sapply(tdays, function(i) { -# sqrt((data$getLevel(i-1)-levelYersteday)^2 + (data$getLevel(i)-levelToday)^2) - abs(data$getLevel(i)-levelToday) - }) + distances = sapply( tdays, function(i) abs(data$getLevel(i) - levelToday) ) #TODO: 1, +1, +3 : magic numbers dist_thresh = 1 min_neighbs = min(min_neighbs,length(tdays)) @@ -242,14 +236,7 @@ NeighborsForecaster = R6::R6Class("NeighborsForecaster", break dist_thresh = dist_thresh + ifelse(dist_thresh>1,3,1) } - tdays = tdays[same_pollution] -# max_neighbs = 12 -# if (nb_neighbs > max_neighbs) -# { -# # Keep only max_neighbs closest neighbors -# tdays = tdays[ order(distances[same_pollution])[1:max_neighbs] ] -# } - tdays + tdays[same_pollution] } # compute similarities @@ -277,8 +264,7 @@ NeighborsForecaster = R6::R6Class("NeighborsForecaster", sapply(tdays, function(i) { delta = lastSerie - c(data$getSerie(i-1), data$getSerie(i)[if (predict_from>=2) 1:(predict_from-1) else c()]) -# sqrt(mean(delta^2)) - sqrt(sum(delta^2)) + sqrt(mean(delta^2)) }) } diff --git a/pkg/R/plot.R b/pkg/R/plot.R index 2488d81..8675c62 100644 --- a/pkg/R/plot.R +++ b/pkg/R/plot.R @@ -30,40 +30,24 @@ plotError <- function(err, cols=seq_along(err)) { if (!is.null(err$abs)) err = list(err) - par(mfrow=c(2,2), mar=c(4.7,5,1,1), cex.axis=1.5, cex.lab=1.5, lwd=2) + par(mfrow=c(2,2), mar=c(4.7,5,1,1), cex.axis=1.5, cex.lab=1.5, lty=1) L = length(err) + yrange = range( sapply(1:L, function(i) ( err[[i]]$abs$day ) ), na.rm=TRUE ) - for (i in seq_len(L)) - { - plot(err[[i]]$abs$day, type="l", xlab=ifelse(i==1,"Time (hours)",""), - ylab=ifelse(i==1,"Mean |y - y_hat|",""), ylim=yrange, col=cols[i]) - if (i < L) - par(new=TRUE) - } + matplot( sapply( seq_len(L), function(i) err[[i]]$abs$day ), type="l", + xlab="Time (hours)", ylab="Mean |y - y_hat|", ylim=yrange, col=cols, lwd=2 ) + yrange = range( sapply(1:L, function(i) ( err[[i]]$abs$indices ) ), na.rm=TRUE ) - for (i in seq_len(L)) - { - plot(err[[i]]$abs$indices, type="l", xlab=ifelse(i==1,"Time (days)",""), - ylab=ifelse(i==1,"Mean |y - y_hat|",""), ylim=yrange, col=cols[i]) - if (i < L) - par(new=TRUE) - } + matplot( sapply( seq_len(L), function(i) err[[i]]$abs$indices ), type="l", + xlab="Time (days)", ylab="Mean |y - y_hat|", ylim=yrange, col=cols, lwd=2 ) + yrange = range( sapply(1:L, function(i) ( err[[i]]$MAPE$day ) ), na.rm=TRUE ) - for (i in seq_len(L)) - { - plot(err[[i]]$MAPE$day, type="l", xlab=ifelse(i==1,"Time (hours)",""), - ylab=ifelse(i==1,"Mean MAPE",""), ylim=yrange, col=cols[i]) - if (i < L) - par(new=TRUE) - } + matplot( sapply( seq_len(L), function(i) err[[i]]$MAPE$day ), type="l", + xlab="Time (hours)", ylab="Mean MAPE", ylim=yrange, col=cols, lwd=2 ) + yrange = range( sapply(1:L, function(i) ( err[[i]]$MAPE$indices ) ), na.rm=TRUE ) - for (i in seq_len(L)) - { - plot(err[[i]]$MAPE$indices, type="l", xlab=ifelse(i==1,"Time (days)",""), - ylab=ifelse(i==1,"Mean MAPE",""), ylim=yrange, col=cols[i]) - if (i < L) - par(new=TRUE) - } + matplot( sapply( seq_len(L), function(i) err[[i]]$MAPE$indices ), type="l", + xlab="Time (days)", ylab="Mean MAPE", ylim=yrange, col=cols, lwd=2 ) } #' Plot measured / predicted @@ -77,7 +61,13 @@ plotError <- function(err, cols=seq_along(err)) plotPredReal <- function(data, pred, index) { prediction = pred$getForecast(index) - measure = data$getSerie( pred$getIndexInData(index) )[1:length(prediction)] + measure = data$getSerie( pred$getIndexInData(index) )[1:length(pred$getForecast(1))] + + # Remove the common part, where prediction == measure + dot_mark <- ifelse(prediction[1]==measure[1], which.max(prediction==measure), 0) + prediction = prediction[(dot_mark+1):length(prediction)] + measure = measure[(dot_mark+1):length(measure)] + yrange = range(measure, prediction) par(mar=c(4.7,5,1,1), cex.axis=1.5, cex.lab=1.5, lwd=3) plot(measure, type="l", ylim=yrange, xlab="Time (hours)", ylab="PM10") @@ -98,8 +88,11 @@ plotSimils <- function(pred, index) weights = pred$getParams(index)$weights if (is.null(weights)) stop("plotSimils only works on 'Neighbors' forecasts") - par(mar=c(4.7,5,1,1), cex.axis=1.5, cex.lab=1.5) - hist(pred$getParams(index)$weights, nclass=20, main="", xlab="Weight", ylab="Count") + par(mfrow=c(1,2), mar=c(4.7,5,1,1), cex.axis=1.5, cex.lab=1.5) + small_weights = weights[ weights < 1/length(weights) ] + large_weights = weights[ weights >= 1/length(weights) ] + hist(small_weights, nclass=25, main="", xlab="Weight < 1/N", ylab="Count") + hist(large_weights, nclass=25, main="", xlab="Weight >= 1/N", ylab="Count") } #' Functional boxplot @@ -137,7 +130,6 @@ plotFbox <- function(data, indices=seq_len(data$getSize())) #' @param index Index in forecast (integer or date) #' @param limit Number of neighbors to consider #' @param plot Should the result be plotted? -#' @param predict_from First prediction instant #' #' @return A list with #' \itemize{ @@ -147,18 +139,24 @@ plotFbox <- function(data, indices=seq_len(data$getSize())) #' } #' #' @export -computeFilaments <- function(data, pred, index, predict_from, limit=60, plot=TRUE) +computeFilaments <- function(data, pred, index, limit=60, plot=TRUE) { - if (is.null(pred$getParams(index)$weights) || is.na(pred$getParams(index)$weights[1])) + weights <- pred$getParams(index)$weights + if (is.null(weights) || is.na(pred$getParams(index)$weights[1])) stop("computeFilaments requires a serie without NAs") - # Compute colors for each neighbor (from darkest to lightest) - sorted_dists = sort(-log(pred$getParams(index)$weights), index.return=TRUE) - nn = min(limit, length(sorted_dists$x)) - min_dist = min(sorted_dists$x[1:nn]) - max_dist = max(sorted_dists$x[1:nn]) - color_values = floor(19.5*(sorted_dists$x[1:nn]-min_dist)/(max_dist-min_dist)) + 1 - colors = gray.colors(20,0.1,0.9)[color_values] #TODO: 20 == magic number + nn <- min(limit, length(weights)) + sorted_dists = sort(-log(weights), index.return=TRUE) + # Compute colors for each neighbor (from darkest to lightest), if weights differ + if ( any( weights != weights[1] ) ) + { + min_dist = min(sorted_dists$x[1:nn]) + max_dist = max(sorted_dists$x[1:nn]) + color_values = floor(19.5*(sorted_dists$x[1:nn]-min_dist)/(max_dist-min_dist)) + 1 + colors = gray.colors(20,0.1,0.9)[color_values] #TODO: 20 == magic number + } + else + colors <- rep(colors()[17], length(weights)) if (plot) { @@ -179,7 +177,9 @@ computeFilaments <- function(data, pred, index, predict_from, limit=60, plot=TRU } # Also plot ref curve, in red plot(ref_serie, ylim=yrange, type="l", col="#FF0000", xlab="", ylab="") - abline(v=24+predict_from-0.5, lty=2, col=colors()[56], lwd=1) + dot_mark <- 0.5 + which.max( pred$getForecast(1) == + data$getSerie( pred$getIndexInData(1) )[1:length(pred$getForecast(1))] ) + abline(v=24+dot_mark, lty=2, col=colors()[56], lwd=1) } list( @@ -194,6 +194,7 @@ computeFilaments <- function(data, pred, index, predict_from, limit=60, plot=TRU #' #' @inheritParams computeError #' @param fil Output of \code{computeFilaments} +#' @param predict_from First predicted time step #' #' @export plotFilamentsBox = function(data, fil, predict_from) @@ -213,7 +214,7 @@ plotFilamentsBox = function(data, fil, predict_from) usr <- par("usr") yr <- (usr[4] - usr[3]) / 27 par(new=TRUE) - plot(c(data$getSerie(fil$index),data$getSerie(fil$index+1)), type="l", lwd=2, lty=2, + plot(c(data$getSerie(fil$index-1),data$getSerie(fil$index)), type="l", lwd=2, lty=2, ylim=c(usr[3] + yr, usr[4] - yr), xlab="", ylab="") abline(v=24+predict_from-0.5, lty=2, col=colors()[56]) } diff --git a/reports/Experiments.gj b/reports/Experiments.gj index 36ed5c5..55147e9 100644 --- a/reports/Experiments.gj +++ b/reports/Experiments.gj @@ -10,15 +10,15 @@ prédiction = moyenne de tous les mardis passés si le jour courant est un lundi * la persistence, reproduisant le jour courant ou allant chercher le lendemain de la dernière journée "similaire" (même principe que ci-dessus ; argument "same\_day"). -Concernant l'algorithme principal à voisins, trois variantes sont étudiées dans cette +Concernant l'algorithme principal à voisins, deux variantes sont comparées dans cette partie : * avec simtype="mix" et raccordement "Neighbors" dans le cas "non local", i.e. on va chercher des voisins n'importe où du moment qu'ils correspondent au premier élément d'un couple de deux jours consécutifs sans valeurs manquantes. - * avec simtype="endo" puis simtype="none", choisissant dans les deux cas -raccordement==NULL (aucun ajustement après moyenne des courbes) dans le cas "local" : -voisins de même niveau de pollution et même saison. + * avec simtype="none" (moyenne simple) et raccordement=NULL (aucun ajustement après +moyenne des courbes) dans le cas "local" : voisins de même niveau de pollution et même +saison. Pour chaque période retenue $-$ chauffage, épandage, semaine non polluée $-$ les erreurs de prédiction sont d'abord affichées, puis quelques graphes de courbes réalisées/prévues @@ -57,47 +57,44 @@ ${"##"} ${list_titles[i]} p1 = computeForecast(data, ${list_indices[i]}, "Neighbors", "Neighbors", predict_from=P, horizon=H, simtype="mix", local=FALSE) p2 = computeForecast(data, ${list_indices[i]}, "Neighbors", NULL, predict_from=P, - horizon=H, simtype="endo", local=TRUE) -p3 = computeForecast(data, ${list_indices[i]}, "Neighbors", NULL, predict_from=P, horizon=H, simtype="none", local=TRUE) -p4 = computeForecast(data, ${list_indices[i]}, "Average", "Zero", predict_from=P, +p3 = computeForecast(data, ${list_indices[i]}, "Average", "Zero", predict_from=P, horizon=H) -p5 = computeForecast(data, ${list_indices[i]}, "Persistence", "Zero", predict_from=P, +p4 = computeForecast(data, ${list_indices[i]}, "Persistence", "Zero", predict_from=P, horizon=H, same_day=${'TRUE' if loop.index < 2 else 'FALSE'}) -----r e1 = computeError(data, p1, P, H) e2 = computeError(data, p2, P, H) e3 = computeError(data, p3, P, H) e4 = computeError(data, p4, P, H) -e5 = computeError(data, p5, P, H) options(repr.plot.width=9, repr.plot.height=7) -plotError(list(e1, e5, e4, e2, e3), cols=c(1,2,colors()[258],4,6)) +plotError(list(e1, e4, e3, e2), cols=c(1,2,colors()[258],4)) -# noir: Neighbors non-local (p1), bleu: Neighbors local endo (p2), -# mauve: Neighbors local none (p3), vert: moyenne (p4), -# rouge: persistence (p5) +# noir: Neighbors non-local (p1), bleu: Neighbors local (p2), +# vert: moyenne (p3), rouge: persistence (p4) sum_p23 = e2$abs$indices + e3$abs$indices -i_np = which.min(sum_p23) #indice de (veille de) jour "facile" -i_p = which.max(sum_p23) #indice de (veille de) jour "difficile" +i_np = which.min(sum_p23) #indice de jour "facile" +i_p = which.max(sum_p23) #indice de jour "difficile" ----- % if i == 0: -L'erreur absolue dépasse 20 sur 1 à 2 jours suivant les modèles (graphe en haut à -droite). Sur cet exemple le modèle à voisins "contraint" (local=TRUE) utilisant des -pondérations basées sur les similarités de forme (simtype="endo") obtient en moyenne les -meilleurs résultats, avec un MAPE restant en général inférieur à 30% de 8h à 19h (7+1 à -7+12 : graphe en bas à gauche). +L'erreur absolue -- en haut à gauche -- reste modérée pour les meilleurs modèles +(variantes à voisins), ne dépassant 10 que deux jours. Les deux modèles naïfs ont des +erreurs similaires sauf sur la période "difficile" (jours 4 à 6), sur laquelle on gagne +donc à chercher des jours similaires pour effectuer la prévision. +Le MAPE reste en général inférieur à 35% pour les meilleurs méthodes. % elif i == 1: -Il est difficile dans ce cas de déterminer une méthode meilleure que les autres : elles -donnent toutes de plutôt mauvais résultats, avec une erreur absolue moyennée sur la -journée dépassant presque toujours 15 (graphe en haut à droite). +Le modèle à voisins avec contrainte de localité obtient ici les meilleurs résultats, son +erreur étant clairement en dessous des autres à partir du jour 4 (graphe en haut à +droite). Le MAPE jour après jour est du même ordre que précédemment pour cette méthode +(35%, graphe en bas à droite) sauf un jour sur lequel le MAPE explose. % else: Dans ce cas plus favorable les intensité des erreurs absolues ont clairement diminué : -elles restent souvent en dessous de 5. En revanche le MAPE moyen reste au-delà de 20%, et -même souvent plus de 30%. Comme dans le cas de l'épandage on constate une croissance -globale de la courbe journalière d'erreur absolue moyenne (en haut à gauche) ; ceci peut -être dû au fait que l'on ajuste le niveau du jour à prédire en le recollant sur la -dernière valeur observée. +elles sont souvent en dessous de 5. En revanche le MAPE moyen reste en général au-delà de +20%. Comme dans le cas de l'épandage on constate une croissance globale de la courbe +journalière d'erreur absolue moyenne (en haut à gauche) -- sauf pour la méthode à voisins +"locale" ; ceci peut être dû au fait que l'on ajuste le niveau du jour à prédire en le +recollant sur la dernière valeur observée (sauf pour "Neighbors local"). % endif -----r options(repr.plot.width=9, repr.plot.height=4) @@ -109,40 +106,41 @@ plotPredReal(data, p1, i_p); title(paste("PredReal p1 day",i_p)) plotPredReal(data, p2, i_np); title(paste("PredReal p2 day",i_np)) plotPredReal(data, p2, i_p); title(paste("PredReal p2 day",i_p)) -plotPredReal(data, p3, i_np); title(paste("PredReal p3 day",i_np)) -plotPredReal(data, p3, i_p); title(paste("PredReal p3 day",i_p)) - -# Bleu : prévue ; noir : réalisée +# Bleu : prévue ; noir : réalisée (confondues jusqu'à predict_from-1) ----- % if i == 0: Le jour "facile à prévoir", à gauche, se décompose en deux modes : un léger vers 10h (7+3), puis un beaucoup plus marqué vers 19h (7+12). Ces deux modes sont retrouvés par -les trois variantes de l'algorithme à voisins, bien que l'amplitude soit mal prédite. +les deux variantes de l'algorithme à voisins, bien que l'amplitude soit mal prédite. Concernant le jour "difficile à prévoir" (à droite) il y a deux pics en tout début et toute fin de journée (à 9h et 23h), qui ne sont pas du tout anticipés par les méthodes ; la grande amplitude de ces pics explique alors l'intensité de l'erreur observée. % elif i == 1: -Dans le cas d'un jour "facile" à prédire $-$ à gauche $-$ la forme est plus ou moins -retrouvée, mais le niveau moyen est trop bas (courbe en bleu). Concernant le jour -"difficile" à droite, non seulement la forme n'est pas anticipée mais surtout le niveau -prédit est très inférieur au niveau de pollution observé. Comme on le voit ci-dessous -cela découle d'un manque de voisins au comportement similaire. +Dans le cas d'un jour "facile" à prédire $-$ à gauche $-$ la forme est plutôt bien +retrouvée, ainsi que le niveau moyen pour la méthode sans contrainte de localité +(dans l'autre, l'algorithme a probablement écarté trop de voisins potentiels). +Concernant le jour "difficile" à droite, non seulement la forme n'est pas anticipée mais +surtout le niveau prédit est largement supérieur au niveau de pollution observé -- dans +une moindre mesure toutefois pour la variante "locale". % else: -La forme est raisonnablement retrouvée pour les méthodes "locales", l'autre version -lissant trop les prédictions. Le biais reste cependant important, surtout en fin de -journée sur la courbes "difficile à prévoir". +L'impression visuelle est plutôt mauvaise dans ce cas, mais les écart étant minimes les +erreurs au final ne sont pas très importantes. De plus deux des quatres graphes sont +satisfaisants (en haut à droite et en bas à gauche : forme + niveau acceptables. % endif -----r par(mfrow=c(1,2)) -f_np1 = computeFilaments(data, p1, i_np, predict_from=P, plot=TRUE) - title(paste("Filaments p1 day",i_np)) -f_p1 = computeFilaments(data, p1, i_p, predict_from=P, plot=TRUE) - title(paste("Filaments p1 day",i_p)) - -f_np2 = computeFilaments(data, p2, i_np, predict_from=P, plot=TRUE) - title(paste("Filaments p2 day",i_np)) -f_p2 = computeFilaments(data, p2, i_p, predict_from=P, plot=TRUE) - title(paste("Filaments p2 day",i_p)) + +f_np1 = computeFilaments(data, p1, i_np, plot=TRUE) +title(paste("Filaments p1 day",i_np)) + +f_p1 = computeFilaments(data, p1, i_p, plot=TRUE) +title(paste("Filaments p1 day",i_p)) + +f_np2 = computeFilaments(data, p2, i_np, plot=TRUE) +title(paste("Filaments p2 day",i_np)) + +f_p2 = computeFilaments(data, p2, i_p, plot=TRUE) +title(paste("Filaments p2 day",i_p)) ----- % if i == 0: Les voisins du jour courant (période de 24h allant de 8h à 7h le lendemain) sont affichés @@ -153,7 +151,7 @@ période de 24h et la forme sur les 24h suivantes ; **cette observation est la difficultés rencontrées par l'algorithme sur ce jeu de données.** % elif i == 1: Les observations sont les mêmes qu'au paragraphe précédent : trop de variabilité des -lendemains (et même des voisins du jour courant). +voisins (et ce même le jour précédent). % else: Les graphes de filaments ont encore la même allure, avec une assez grande variabilité observée. Cette observation est cependant trompeuse, comme l'indique plus bas le graphe @@ -161,10 +159,14 @@ de variabilité relative. % endif -----r par(mfrow=c(1,2)) -plotFilamentsBox(data, f_np1, predict_from=P); title(paste("FilBox p1 day",i_np)) -plotFilamentsBox(data, f_p1, predict_from=P); title(paste("FilBox p1 day",i_p)) -# En pointillés la courbe du jour courant + lendemain (à prédire) +plotFilamentsBox(data, f_np1, predict_from=P) +title(paste("FilBox p1 day",i_np)) + +plotFilamentsBox(data, f_p1, predict_from=P) +title(paste("FilBox p1 day",i_p)) + +# En pointillés la courbe du jour courant (à prédire) + précédent ----- % if i == 0: Sur cette boxplot fonctionnelle (voir la fonction fboxplot() du package R "rainbow") on @@ -174,82 +176,78 @@ rouge à gauche) ; et, dans le cas d'une courbe à prédire atypique (à dro des voisins sont trop éloignés de la forme à prédire et forcent ainsi un aplatissement de la prédiction. % elif i == 1: -On constate la présence d'un voisin au lendemain complètement atypique avec un pic en -début de journée (courbe en vert à gauche), et d'un autre phénomène semblable avec la -courbe rouge sur le graphe de droite. Ajouté au fait que le lendemain à prévoir est -lui-même un jour "hors norme", cela montre l'impossibilité de bien prévoir une courbe en -utilisant l'algorithme à voisins. +Concernant le jour "difficile" on constate la présence de voisins au lendemains +complètement atypiques avec un pic en début de journée (courbes en vert et rouge à +droite). Ajouté au fait que le jour à prévoir est lui-même "hors norme", cela montre +l'impossibilité de bien prévoir une courbe en utilisant l'algorithme à voisins. % else: On peut réappliquer les mêmes remarques qu'auparavant sur les boxplots fonctionnels : -lendemains de voisins atypiques, courbe à prévoir elle-même légèrement "hors norme". +voisins atypiques, courbe à prévoir elle-même légèrement "hors norme". % endif -----r par(mfrow=c(1,2)) -plotRelVar(data, f_np1, predict_from=P); title(paste("StdDev p1 day",i_np)) -plotRelVar(data, f_p1, predict_from=P); title(paste("StdDev p1 day",i_p)) -plotRelVar(data, f_np2, predict_from=P); title(paste("StdDev p2 day",i_np)) -plotRelVar(data, f_p2, predict_from=P); title(paste("StdDev p2 day",i_p)) +plotRelVar(data, f_np1, predict_from=P) +title(paste("StdDev p1 day",i_np)) -# Variabilité globale en rouge ; sur les voisins (+ lendemains) en noir +plotRelVar(data, f_p1, predict_from=P) +title(paste("StdDev p1 day",i_p)) + +plotRelVar(data, f_np2, predict_from=P) +title(paste("StdDev p2 day",i_np)) + +plotRelVar(data, f_p2, predict_from=P) +title(paste("StdDev p2 day",i_p)) + +# Variabilité globale en rouge ; sur les voisins en noir ----- % if i == 0: Ces graphes viennent confirmer l'impression visuelle après observation des filaments. En effet, la variabilité globale en rouge (écart-type heure par heure sur l'ensemble des -couples "aujourd'hui/lendemain"du passé) devrait rester nettement au-dessus de la +couples "hier/aujourd'hui" du passé) devrait rester nettement au-dessus de la variabilité locale, calculée respectivement sur un voisinage d'une soixantaine de jours -(pour p1) et d'une dizaine de jours (pour p2). Or on constate que ce n'est pas du tout le -cas sur la période "lendemain", sauf en partie pour p2 le jour 4 $-$ mais ce n'est pas -suffisant. +(pour p1) et d'une dizaine de jours (pour p2). Or ce n'est pas du tout le cas sur la +moitié droite, sauf pour le jour "facile" avec l'algorithme "local". % elif i == 1: -Comme précédemment les variabilités locales et globales sont confondues dans les parties -droites des graphes $-$ sauf pour la version "locale" sur le jour "facile"; mais cette -bonne propriété n'est pas suffisante si l'on ne trouve pas les bons poids à appliquer. +Comme précédemment les variabilités locales et globales sont trop proches dans les +parties droites des graphes pour le jour "difficile". L'allure des graphes est +raisonnable ppour l'autre jour, qui est d'ailleurs bien prédit. % else: Cette fois la situation idéale est observée : la variabilité globale est nettement au-dessus de la variabilité locale. Bien que cela ne suffise pas à obtenir de bonnes prédictions de forme, on constate au moins l'amélioration dans la prédiction du niveau. % endif -----r -par(mfrow=c(1,2)) -plotSimils(p1, i_np); title(paste("Weights p1 day",i_np)) -plotSimils(p1, i_p); title(paste("Weights p1 day",i_p)) +plotSimils(p1, i_np) +title(paste("Weights p1 day",i_np)) -plotSimils(p2, i_np); title(paste("Weights p2 day",i_np)) -plotSimils(p2, i_p); title(paste("Weights p2 day",i_p)) +plotSimils(p1, i_p) +title(paste("Weights p1 day",i_p)) + +# Poids < 1/N à gauche, >= 1/N à droite ; jour facile en haut, difficile en bas ----- % if i == 0: -Les poids se concentrent près de 0 dans le cas "non local" (p1), et se répartissent assez -uniformément dans [ 0, 0.2 ] dans le cas "local" (p2). C'est ce que l'on souhaite -observer pour éviter d'effectuer une simple moyenne. +Les poids se concentrent près de 0 : c'est ce que l'on souhaite observer pour éviter +d'effectuer une simple moyenne. % elif i == 1: -En comparaison avec le pragraphe précédent on retrouve le même (bon) comportement des -poids pour la version "non locale". En revanche la fenêtre optimisée est trop grande sur -le jour "facile" pour la méthode "locale" (voir affichage ci-dessous) : il en résulte des -poids tous semblables autour de 0.084, l'algorithme effectue donc une moyenne simple $-$ -expliquant pourquoi les courbes mauve et bleue sont très proches sur le graphe d'erreurs. +En comparaison avec le paragraphe précédent on retrouve le même (bon) comportement des +poids pour la version "non locale". % else: -Concernant les poids en revanche, deux cas a priori mauvais se cumulent : - - * les poids dans le cas "non local" ne sont pas assez concentrés autour de 0, menant à -un lissage trop fort $-$ comme observé sur les graphes des courbes réalisées/prévues ; - * les poids dans le cas "local" sont trop semblables (à cause de la trop grande fenêtre -optimisée par validation croisée, cf. ci-dessous), résultant encore en une moyenne simple -$-$ mais sur moins de jours, plus proches du jour courant. +Concernant les poids en revanche, deux cas a priori mauvais se cumulent : ... % endif -----r -# Fenêtres sélectionnées dans ]0,7] : -# "non-local" 2 premières lignes, "local" ensuite +options(digits=2) + p1$getParams(i_np)$window p1$getParams(i_p)$window -p2$getParams(i_np)$window -p2$getParams(i_p)$window +# Fenêtres sélectionnées dans ]0,7] % endfor ----- ${"##"} Bilan -Nos algorithmes à voisins ne sont pas adaptés à ce jeu de données où la forme varie -considérablement d'un jour à l'autre. Toutefois, un espoir reste permis par exemple en -aggrégeant les courbes spatialement (sur plusieurs stations situées dans la même +Nos algorithmes à voisins donnent de meilleurs résultats que les approches naïves +(persistence, moyenne sur tout le jeu de données). Les erreurs restent cependant assez +élevées, notamment en terme de MAPE. Une possible poste d'amélioration consisterait à +aggréger les courbes spatialement (sur plusieurs stations situées dans la même agglomération ou dans une même zone).