Chapitre 3 Collecte de données

## Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3

L’étape initiale de tout projet de modélisation prédictive est la collecte des données. Sans données, le modèle apprendra… rien!

La présente section aura donc pour but de couvrir la collecte de données. Nous décrirons d’abord l’approche générale pour la collecte. Ensuite, nous dresserons une liste potentielle de sources de données pour la tâche à accomplir. Nous terminerons finalement en dressant une liste de considérations, tout en soumettant la liste de sources à ces considérations.

3.1 Description de l’approche

L’étape de collecte peut être subdivisée à son tour en 3 sous-étapes : obtenir les données etiquetées, obtenir les données de jointure et effectuer la jointure. Nous verrons également que la collecte se produit souvent différemment lors de la modélisation et lors de la prédiction en production.

3.1.1 Obtenir les données etiquetées

Dans tout projet de modélisation prédictive, il faut obtenir des données etiquetées, de façon à ce que le modèle puisse apprendre à prédire une étiquette. Ces données etiquetées sont des exemples réels tirés du passé et pour lesquels nous connaissons le résultat, et donc duquel le modèle pourra apprendre. Nous appellerons ces exemples des observations.

Pour chaque observation, les données etiquetées contiennent au minimum l’étiquette, aussi appelée variable réponse. Autrement dit, c’est la valeur que nous voulons prédire. Dans notre cas, une observation sera un trajet. Pour chaque observation, nous aurons 2 étiquettes : la durée du trajet et le statut de membre du client. Sans information supplémentaire pour chacune des observations, nous serions en présence d’un simple échantillon aléatoire grâce auquel nous pourrions simplement prédire un estimateur comme la moyenne ou le mode pour tous les trajets. C’est pourquoi nous nécessiterons également au moins une information supplémentaire nous permettant de segmenter nos prédictions d’une observation à l’autre. Nous appellerons ces informations supplémentaires les prédicteurs. Par exemple, le jour et l’heure de départ pourraient nous donner de l’information prédictive sur la durée du trajet et sur le statut de membre du client. Voici de quoi pourrait avoir l’air notre jeu de données etiquetées :

temps_depart duree_trajet membre
2017-05-07 17:00:02 1505 1
2017-05-29 18:50:11 120 0
2017-10-12 22:56:46 707 0

Ici, une ligne représente une observation ou un trajet, temps_depart est le prédicteur, et duree_trajet et membre sont les étiquettes.

3.1.2 Obtenir les données de jointure

Après avoir trouvé nos données etiquetées contenant les étiquettes et les prédicteurs, nous sommes rarement satisfaits de la quantité de prédicteurs que nous pouvons y trouver. En effet, il arrive souvent dans les premiers instants d’un projet de prononcer une phrase du genre : “Imaginez si nous avions accès à telle ou telle donnée (qui malheureusement est absente des données etiquetées)”. Nous pouvons alors augmenter le jeu de données à l’aide de ce que nous appellerons les données de jointure. Nous les appellerons ainsi car nous devrons effectuer une opération de jointure entre notre jeu de données etiquetées et notre source de données additionnelle. Par exemple, si nous reprenons les données etiquetées précédentes, une source de données de jointure pourrait nous renseigner sur les heures de lever et de coucher du soleil pour chaque journée. En supposant que la noirceur décourage les cyclistes, cela pourrait aider à prédire la durée du trajet :

date heure lever heure coucher
2017-05-07 06:35:00 20:10:00
2017-05-29 06:00:00 20:45:00
2017-10-12 07:30:00 17:55:00

Ici, la variable date nous permettrait d’effectuer une jointure entre ces données et les données etiquetées.

3.1.3 Effectuer la jointure

Maintenant que nous avons les données de jointure et les données etiquetées, nous pouvons effectuer une jointure à partir des informations présentes dans les 2 jeux de données, soit la variable date :

temps_depart duree_trajet membre date heure lever heure coucher
2017-05-07 17:00:02 1505 1 2017-05-07 06:35:00 20:10:00
2017-05-29 18:50:11 120 0 2017-05-29 06:00:00 20:45:00
2017-10-12 22:56:46 707 0 2017-10-12 07:30:00 17:55:00

Le jeu de données serait alors prêt à passer à l’étape de prétraitement 5, où nous pourrions par exemple créer une variable indicatrice noirceur qui indiquerait s’il fait noir ou non au début du trajet.

3.1.4 Collecte historique vs. collecte en production

Dans les projets de modélisation prédictive, il existe généralement un fossé entre la modélisation, qui nécessite une collecte de données historiques, et la prédiction en production, qui nécessite une collecte de données en temps réel. Selon la configuration des systèmes en place et la nature de la problématique, le fossé peut être microscopique, et passer inaperçu, ou astronomique, et poser de sérieux ennuis pouvant même compromettre la faisabilité du projet. En effet, les natures différentes de ces 2 contextes peuvent parfois être irréconciliables : l’entraînement de modèles sur des données historiques exige un entreposage adéquat des données, mais les données historiques ont rarement été collectées dans l’optique de servire à entraîner des modèles. Ainsi, nous pouvons généralement reconnaître 3 situations :

  • une source de données disponible à l’entraînement mais indisponible en production en temps réel est inutile. Par exemple, disposer d’instruments météorologiques qui nécessitent une récolte manuelle mensuelle des données serait bénéfique à l’entraînement, mais inutilisable en production.
  • une source de données disponible en production en temps réel mais indisponible à l’entraînement peut être utile à condition de faire certaines hypothèses au jugement avant, pendant ou après l’entraînement. Par exemple, si nous pouvons effectuer une lecture en temps réel de nos instruments météorologiques mais que ces données ne sont pas déversées dans une base de données, nous devrons poser une hypothèse : introduire l’opinion d’experts ou le résultat d’analyses simplifiées dans le modèle de façon manuelle. Attention toutefois : le modèle devient sensible à notre hypothèse, et nous introduisons potentiellement du biais ou de l’incertitude indésirables dans notre modèle.
  • entre les 2 situations précédentes se trouve le cas où les données d’entraînement sont différentes de celles de production. C’est notamment le cas quand une source de données fournit les données historiques, et une autre fournit les données en temps réel. L’hypothèse par défaut serait que les sources produisent la même distribution de données. Une autre hypothèse pourrait être par exemple que la source de production sous-estime systématiquement de 2 unités, et nous apporterions des corrections manuelles à la source de production. Peu importe la complexité de l’hypothèse, encore une fois le modèle devient sensible à cette hypothèse et nous introduisons potentiellement du biais et de l’incertitude.

Alors que la première situation est difficile à corriger tant que les données en temps réel sont indisponibles, les 2 suivantes permettent de continuer d’avancer, puis de commencer à entreposer les données de la source de production afin de fournir au modèle les données de production historiques lors de son prochain réentrainement.

Également, les données de jointure peuvent représenter des concepts connus d’avance (ex. les heures de lever et coucher du soleil pour une journée donnée), ou d’autres devant être recalculés ou récupérés d’une source externe à chaque prédiction (ex. la température ambiante au moment de la prédiction). Alors que le premier type peut déjà être calculé et entreposé d’avance, puis récupéré rapidement lors de la prédiction, le deuxième doit nécessairement être calculé ou récupéré en temps réel à chaque prédiction, ce qui peut augmenter le temps de réponse.

Pour des raisons de différence entre les sources et de rapidité des calculs, il faudra donc distinguer la collecte des données selon si elle est faite dans l’optique de modélisation, de prédiction, ou des 2.

3.2 Liste des données potentielles

Dans le but d’identifier les données étiquetées et de jointure, dressons d’abord une liste des données disponibles et potentiellement utiles.

Les plus expérimentés auront déjà en tête la majorité des considérations couvertes plus tard dans ce chapitre au moment de dresser leur liste. Dans notre cas, permettons-nous de lister naïvement un grand nombre de sources. Chaque considération à venir nous permettra ensuite d’invalider certaines sources et de distiller notre sélection.

3.2.1 Données étiquetées

Tout d’abord, une simple recherche des mots-clés données historiques BIXI dans votre moteur de recherche favori devrait vous mener à la page du site web de BIXI réservée à l’historique des déplacements.

Un coup d’oeil aux données disponibles permet de constater qu’il y a 2 types de fichiers : des données historiques et de l’information sur les stations.

Concentrons-nous pour commencer avec les données historiques. Pour l’année 2017, nous avons accès, pour chacun des mois d’ouverture du service (avril à novembre), à des données tabulaires sous cette structure :

if(file.exists("data/data_bixi.csv")){
  data_2017_04 <- data.table::fread("data/data_bixi.csv", nrows = 5)
} else {
  data_2017_04 <- data.table::fread("https://s3.ca-central-1.amazonaws.com/jeremiedb/share/dot-layer/R-Quebec/BixiMontrealRentals2017/OD_2017-04.csv", nrows = 5)}

data_2017_04 %>% 
  knitr::kable() %>% 
  kableExtra::kable_styling(full_width = FALSE, position = "left")
start_date start_station_code end_date end_station_code duration_sec is_member
2017-04-15 00:00 7060 2017-04-15 00:31 7060 1841 1
2017-04-15 00:01 6173 2017-04-15 00:10 6173 553 1
2017-04-15 00:01 6203 2017-04-15 00:04 6204 195 1
2017-04-15 00:01 6104 2017-04-15 00:06 6114 285 1
2017-04-15 00:01 6174 2017-04-15 00:11 6174 569 1

Voilà qui devrait nous fournir les éléments les plus précieux : nos 2 étiquettes. En effet, pour chacun des trajets, nous pourrons déterminer la durée avec la colonne duration_sec et le statut de membre du client à l’aide de la colonne is_member. Ces données renferment aussi d’autres éléments intéressants pouvant servir de prédicteurs. Nous pourrons notamment utiliser le jour de la semaine, l’heure et la station de départ pour tenter de prédire les variables réponses.

Dans ce jeu de données, duration_sec et is_member sont les étiquettes. Les prédicteurs sont la station de départ, l’heure de la journée, le jour de la semaine, et le mois, qui peuvent tous fournir davantage de précision à nos prédictions.

3.2.2 Données de jointure

La station de départ est représentée par un code unique représentant une entité unique et identifiable (souvent appelé ID). Cela fait non seulement d’elle un bon prédicteur, mais également une bonne clé pour amener des données de jointures. Par exemple, dans notre cas, le code de station est une porte d’entrée vers l’information spécifique aux stations ou à leur emplacement géographique. Nous pouvons dès lors utiliser n’importe quelle information reliée à la station ou son emplacement et susceptible de raffiner les prédictions. Or, il s’avère que le deuxième type de fichier fourni par BIXI contient la position GPS de chaque station :

code name latitude longitude
7015 LaSalle / 4e avenue 45.43074 -73.59191
6714 LaSalle / Sénécal 45.43443 -73.58669
6712 LaSalle / Crawford 45.43791 -73.58274
6715 Natatorium (LaSalle / Rolland) 45.44441 -73.57557
7048 Métro Angrignon 45.44653 -73.60354

Le jour de la semaine pourrait aussi servir à faire des jointures, par exemple avec une liste des jours fériés ou avec une table des heures de lever et de coucher du soleil. La liste des jointures possibles ne s’arrête pas là; allons passer en revue toutes les données de jointure potentiellement à notre disposition.

Une recherche plus approfondie des mots-clés précédents (données historiques BIXI) devrait vous mener à la page du Portail données ouvertes de la Ville de Montréal réservée elle aussi à l’historique des déplacements. A priori, c’est simplement un lien vers les données précédentes. Un clic sur le bouton Vélo de la section Mots-clés nous ouvre toutefois une boîte de Pandore : L’état en temps réel des stations BIXI, la géolocalisation des arceaux à vélos, la cartographie du réseau cyclable et le nombre de passages quotidiens sur les pistes cyclables sur le territoire de la Ville de Montréal.

À cette liste, nous pourrions ajouter une tonne d’autres sources de données permettant de mieux contextualiser les observations et améliorer nos prédictions. Parmi celles-ci, notons les suivantes :

Tel que mentionné en introduction, notre ouvrage est linéaire, donc le processus de sélection de données se fera d’un seul trait. Bien entendu, dans un projet réel, il est presque certain que certains aspects nous échappent au début, et que nous devions réajuster le tir dans les phases subséquentes.

Comme nous pouvons le constater, la liste de données potentielles est sans limites. Pour les besoins de l’atelier, les sources de données qui seront réellement considérées à partir de maintenant seront les suivantes :

  • la géolocalisation des arceaux
  • la cartographie du réseau cyclable
  • le nombre de passages quotidiens sur les pistes cyclables
  • la disponibilité des vélos aux différentes stations
  • la température historique
  • la température en temps réel
  • le découpage des quartiers
  • l’altitude des stations

3.3 Considérations

La collecte de données est le point de départ de la chaîne. Les données étant quelque peu la matière première du produit que nous nous apprêtons à bâtir, plusieurs considérations influenceront leur collecte.

Les premières considérations qui viennent à l’esprit dans le cas des matières premières sont évidemment le prix, la qualité et la quantité. Toutefois, d’autres facteurs influencent le choix de matière première comme la provenance, le processus de récolte ou de transformation, la constance de l’approvisionnement, l’entreposage et la sécurité. Les mêmes considérations peuvent s’appliquer dans notre contexte et viendront influencer la collecte des données.

La présente section aura pour objectif d’aborder ces considérations, tout en les appliquant sur les sources mentionnées et retenues précédemment.

3.3.1 Accessibilité

Pour une matière première, la première considération principale serait le coût. Dans le cas des données, nous allons plutôt parler d’accessibilité, dont le coût est une des composantes.

3.3.1.1 Coût

Si plusieurs tribunes s’entendent pour dire que le nouvel or noir est les données, cet engouement vient nécessairement avec un coût, dicté par l’offre et la demande. Certaines sources sont gratuites, alors que d’autres sont payantes. Plusieurs approches sont donc possibles pour maximiser les bénéfices d’un projet tout en limitant ses coûts.

3.3.1.1.1 Sources gratuites

Outre l’approche par moteur de recherche effectuée ci-haut, un balayage des différentes sources gratuites peut révéler des trésors cachés. Parmi ces sources gratuites, notons les suivantes :

3.3.1.1.2 Sources payantes

Les sources payantes sont aussi vastes. Parfois elles sont accessibles en ligne, mais bien souvent des tarifs sont offerts à la pièce. Les fournisseurs principaux de ce type de données sont les courtiers, les aggrégateurs, les entreprise technologiques et les entreprises qui ont beaucoup de données.

3.3.1.2 Lecture et écriture

Les sources de données peuvent se présenter sous plusieurs formes : un fichier, une base de données ou un service. Dans tous les cas, R gère facilement la lecture et l’écriture des données.

3.3.1.2.1 Lecture et écriture de fichiers

Les sources de données se présentent parfois sous la forme de fichier. Aussi peu dynamique cela soit-il, il est fréquent d’avoir recours à des fichiers aux premiers stades de développement d’une idée. En effet, un fichier est souvent plus simple à obtenir, et plus rapide à configurer pour des besoins ponctuels qu’une connexion à une base de données ou à une API.

Plusieurs packages R facilitent et accélèrent cette étape du processus. Parmi ceux-ci, notons data.table et ses fonctions fread et fwrite, readr, readxl et xlsx.

3.3.1.2.2 Connexion à une base de données

L’importation de fichiers peut fonctionner à petite échelle. Pour éliminer des étapes manuelles, il convient de configurer l’environnement de modélisation pour qu’il puisse se connecter à des bases de données.

Parmi les types de bases de données, on peut les placer sur un continuum allant de structuré à non-structuré. Certaines définitions considèrent que les données semi-structurées sont une classe à part… nous nous contenterons de dire qu’il existe un continuum de degrés d’organisation des données, avec à un extrême les données structurées, et à l’autre les données non-structurées.

Sans entrer dans les détails, notons que les packages permettant à R de se connecter à des bases de données sont multiples : odbc, DBI, dbplyr, sparklyr, ROracle, RMySQL, RPostgresSQL, RSQLite, sqldf, rio, foreign et haven sont du nombre. Notons également que l’éditeur RStudio facilite l’interaction avec plusieurs de ces packages.

3.3.1.2.2.1 Données structurées

Les données structurées sont caractérisées par un modèle de données qui garanti une uniformité entre toutes les données, de façon à ce que la lecture et l’écriture de ces données soient facilitées et accélérées.

L’implantation la plus connue de données structurées est probablement les bases de données relationnelles constituées de tables disposées en colonnes et en rangées. L’utilisation de jointures est omniprésente et à la base de ce type de bases de données. Le langage par excellence pour ce type de bases de données est le SQL (Structured Query Language).

3.3.1.2.2.2 Données non-structurées

Les données non-structurées sont celles qui ne sont pas organisées à l’aide d’un modèle de données. Une base de données non-structurée peut donc contenir à la fois du texte, des images, du son ou une combinaison (ex. vidéo). R est également équipé pour traiter ce genre de données. Par exemple, pour le traitement d’images, les packages imager, magick et png sont disponibles.

3.3.1.2.3 Service

Outre la collecte par fichiers ou par connexion à des bases de données, il est possible de procéder en faisant appel à un service. Un service est accessible via une adresse précise, faisant référence à un port sur un serveur. On y envoie des instructions, et on reçoit une réponse, souvent en XML ou en JSON.

En fait, le produit fini du présent ouvrage sera un service déployé sur le web. Voyez par vous-même :

r <- httr::GET("35.203.45.227:8080/bixikwargs?start_date=2017-04-15%2000:48&start_station_code=6079&is_member=1")
httr::content(r)
## $duree
## $duree[[1]]
## $duree[[1]][[1]]
## [1] 620.488
## 
## 
## 
## $meme_station
## $meme_station[[1]]
## [1] FALSE

Des APIs du genre sont souvent utilisées pour rendre des données disponibles aux développeurs. C’est de cette façon que des développeurs peuvent créer des applications web ou en connecter entre elles. Avec votre accord si on utilise vos données bien sûr!

Vous êtes-vous déjà demandés comment les développeurs pouvaient bâtir une application aussi facilement par-dessus une autre? Par exemple, comment BIXI peut afficher les disponibilités de ses vélos sur une carte aussi facilement que ça? En suivant ce lien, on apprend que BIXI rend ses données en temps réel sur l’état des stations publiques. La documentation est ici, le statut des stations est ici et les autres endpoints disponibles sont ici. Il suffit alors de connecter ce flux à un autre service ouvert : OpenStreetMap.

D’autres services de vélo-partage à travers le monde rendent leurs données publiques. Puisque chaque service est doté d’un modèle de données, des aggrégateurs comme celui-ci sont possibles.

Pour la suite de l’atelier, nous discarterons ces source de données car, bien que nous ayions accès aux données en temps réel, nous ne disposons pas de l’historique pour entraîner notre modèle.

Bien que la collecte par service soit commode, ce n’est pas la panacée. Les sources sont rarement gratuites, et quand elles le sont elles limitent souvent l’utilisation avec des timeouts ou des limites de requêtes par unité de temps.

Notons pour terminer que les packages suivants facilitent la communication avec des serveurs : curl, httr, jsonlite, xml2, XML, downloader

3.3.1.3 Web Scraping

Le principal obstacle du web scraping est l’aspect légal. Néanmoins, les packages suivants facilitent la collecte d’information par web scraping : rvest, googlesheets.

3.3.1.4 Accès aux données historiques et en temps réel

Nous avons discarté le service de disponibilité des vélos par absence d’historique. Voyons maintenant comment pourrait s’orchestrer l’utilisation de sources différentes en entraînement et en production.

Le site weatherstats.ca permet de télécharger un historique des températures à Montréal.

Le site OpenWeatherMap.org, lui, permet d’obtenir la température en temps réel à l’aide d’une requête à un service :

r <- httr::GET("http://api.openweathermap.org/data/2.5/weather?q=montreal&APPID=06284235673deed0ce24aeaaa1e8f296")

httr::content(r)
## $coord
## $coord$lon
## [1] -73.61
## 
## $coord$lat
## [1] 45.5
## 
## 
## $weather
## $weather[[1]]
## $weather[[1]]$id
## [1] 500
## 
## $weather[[1]]$main
## [1] "Rain"
## 
## $weather[[1]]$description
## [1] "light rain"
## 
## $weather[[1]]$icon
## [1] "10d"
## 
## 
## 
## $base
## [1] "stations"
## 
## $main
## $main$temp
## [1] 278.68
## 
## $main$pressure
## [1] 1012
## 
## $main$humidity
## [1] 87
## 
## $main$temp_min
## [1] 278.15
## 
## $main$temp_max
## [1] 279.26
## 
## 
## $visibility
## [1] 24140
## 
## $wind
## $wind$speed
## [1] 4.1
## 
## $wind$deg
## [1] 70
## 
## 
## $rain
## $rain$`1h`
## [1] 0.25
## 
## 
## $clouds
## $clouds$all
## [1] 90
## 
## 
## $dt
## [1] 1557834722
## 
## $sys
## $sys$type
## [1] 1
## 
## $sys$id
## [1] 943
## 
## $sys$message
## [1] 0.0096
## 
## $sys$country
## [1] "CA"
## 
## $sys$sunrise
## [1] 1557825921
## 
## $sys$sunset
## [1] 1557879381
## 
## 
## $id
## [1] 6077243
## 
## $name
## [1] "Montreal"
## 
## $cod
## [1] 200

Les lectures proviennent-elles des mêmes stations météo? Les distributions ont-elles des biais systématiques, ou des variabilités imprévisibles entre elles? La tâche de réconcilier ces sources de données et de les intégrer au modèle sera laissée en exercice au lecteur.

3.3.1.5 Stabilité

Pour que la stabilité des sources de données soit problématique, deux éléments doivent être réunis : - le format des données change - notre fréquence de collecte est trop élevée pour nous donner le temps de réagir

Alors que nous n’avons que peu de contrôle sur le premier élément, nous pouvons mitiger le deuxième. Nous pouvons travailler avec une copie des données, de sorte que nous ne serons pas affectés par un changement à la source. Évidemment, en contrepartie on sacrifie la réactivité… l’approche à prendre dépendra donc de la valeur ajoutée d’avoir les données les plus à jour dans le modèle, de notre anticipation de la stabilité ainsi que de l’impact d’une panne du service.

Dans notre cas, les limites administratives des quartiers de la Ville de Montréal changent très peu souvent. Nous pouvons donc nous permettre de travailler avec une copie des données figée dans le temps, autant pour l’entraînement que pour la prédiction. Étant donné ces propriétés désirables, nous retenons cette source de données pour la suite.

Voyons maintenant comment nous pouvons déterminer le quartier pour chaque observation, à partir des coordonnées des stations et des limites administratives des arrondissements.

Premièrement, nous chargeons les polygones , aussi connus sous le nom de shapefiles :

extension_list <- c(".shx", ".shp", ".prj", ".dbf")
AWS_path <- "https://s3.ca-central-1.amazonaws.com/jeremiedb/share/dot-layer/R-Quebec/LIMADMIN/LIMADMIN"

if (! all(purrr::map_lgl(extension_list, ~ file.exists(paste0("data/LIMADMIN", .x))))){
  purrr::walk(extension_list,
              ~ download.file(url = paste0(AWS_path, .x),
                              destfile = paste0("data/LIMADMIN", .x),
                              method = "auto",
                              mode = "wb"))
  
}

shape_file <- sf::read_sf(dsn="data/LIMADMIN.shp")

Prenons maintenant la première station, et utilisons le package sf pour déterminer à quel arrondissement elle appartient :

point_station_sf <- sf::st_sfc(sf::st_point(c(data_stations[[1, "longitude"]], data_stations[[1, "latitude"]])), crs = 4326)

pnts_trans <- sf::st_transform(point_station_sf, 2163)
shape_file_trans <- sf::st_transform(shape_file, 2163)
vecteur_intersection <- sf::st_intersects(shape_file_trans, pnts_trans, sparse = FALSE)

shape_file_trans[which(vecteur_intersection), ]$NOM
## [1] "LaSalle"

Nous pourrons ainsi rattacher le prédicteur de l’arrondissement à chacune des observations.

3.3.1.6 sécurité et confidentialité

Simple note : comme dans tout projet informatique, nous devons nous assurer des niveaux de sécurité et de confidentialité appropriés pour l’usage.

3.3.2 Qualité

Plusieurs aspects peuvent influencer notre perception de qualité d’une source de données, tels que sa complexité, son pouvoir prédictif, la capacité de faire des jointures et le biais. Encore une fois, notons que les étapes futures peuvent invalider une source de données. Par exemple, le pouvoir prédictif est difficile à évaluer sans un premier modèle naïf au moins.

3.3.2.1 complexité

Nous pouvons décrire la complexité à utiliser une source de données de 2 façons : - Par la qualité de l’organisation et de la documentation de la source - Par la simplicité à construire une clé de jointure ou des prédicteurs

3.3.2.1.1 organisation et documentation des données

Ces 3 sources de données contiennent la même information. Avec laquelle préfériez-vous travailler a priori?

dt temps
2019-05-14 07:55:28 0.0208333
Date Durée (minutes)
2019-05-14 07:55:28 30
Date début Date fin
2019-05-14 07:55:28 2019-05-14 08:25:28

Évidemment, nous préférerons, dans l’ordre, 3, 2, 1. Bien que cet exemple soit simpliste et fictif, il illustre tout de même que des éléments tels que le nom, la structure ou la documentation des données influenceront notre capacité à maximiser notre utilisation de ces données.

3.3.2.1.2 construire une clé de jointure ou des prédicteurs

Prenons l’exemple des sources contenant la cartographie du réseau cyclable, le nombre de passages quotidiens et la position des arceaux. Dans les 3 cas cela nécessiterait dans un premier temps de sommariser les données géographiques complexes, pour ensuite devoir les rattacher aux données étiquetées par les seules clés de jointure disponibles : les points GPS reliés aux stations. Nous devrions donc grandement compresser de l’information riche à cause de la clé de jointure limitée.

3.3.2.2 pouvoir prédictif

Comme l’énonce le fameux dicton : Garbage In, Garbage Out. Autrement dit, si les données que nous fournissons à notre modèle sont de piètre qualité ou peu corrélées avec les étiquettes à prédire, l’apprentissage machine n’aura jamais l’effet d’une baguette magique.

Également, notons que nous devons considérer le pouvoir prédictif en termes relatif, et non en termes absolu. En effet, si nous avons déjà des bons proxys pour des prédicteurs, il peut s’avérer futile de vouloir amener ces prédicteurs à tout prix dans nos données d’entraînement, au bénéfice de quelques poussières de précision additionnelle. Par exemple, dans le cas des données géographiques mentionnée dans la sous-section précédente, nous considérons que les limites administratives captureront déjà une bonne partie des effets géographiques concentrés autour des stations. Puisque la clé de jointure aurait été la station de toute façon, nous jugeons donc qu’en plus d’être compliqué à joindre à notre jeu de données, le pouvoir prédictif serait limité.

3.3.2.3 complexité-bénéfice

Comme dans n’importe quel projet, nous devrons faire des analyses complexité-bénéfice afin de déterminer à quel point le bénéfice espéré justifie le coût associé à la complexité additionnelle. Revenons aux données géographiques mentionnées aux 2 sous-sections précédentes. Non seulement la complexité nous apparaît élevée, les bénéfices marginaux nous apparaissent également limités. Nous discartons donc ces 3 sources de données.

3.3.2.4 jointure

Dans la section approche @, nous avons grandement simplifié le processus de jointure de sources de données. Or, dans la vraie vie, les opérations de jointure peuvent parfois s’avérer périlleuses. En effet, les informations de part et d’autres peuvent être manquantes ou insuffisantes, de sorte que la jointure produira un prédicteur avec une faible qualité ou un faible niveau de confiance. La quantité de jointures à effectuer peut aussi être supérieure à 1, ce qui augmente l’incertitude par rapport à la qualité des données jointes.

3.3.2.4.1 Faible qualité

À la section 3.1.3, si au lieu d’avoir sous la main l’heure moyenne de lever et de coucher du soleil dans un mois, plutôt que la donnée exacte pour chacune des journées, nos prédicteurs auraient un pouvoir prédictif plus faible étant donné que l’heure moyenne dans un mois est seulement un proxy pour le vrai prédicteur, qui est l’heure exacte :

mois heure lever moy heure coucher moy
2017-05 06:17:00 20:27:00
2017-10 07:25:00 17:50:00

La jointure aurait donné ceci :

start_date start_station_code end_date end_station_code duration_sec is_member mois heure lever moy heure coucher moy
2017-04-15 00:00 7060 2017-04-15 00:31 7060 1841 1 2017-04 NA NA
2017-04-15 00:01 6173 2017-04-15 00:10 6173 553 1 2017-04 NA NA
2017-04-15 00:01 6203 2017-04-15 00:04 6204 195 1 2017-04 NA NA
2017-04-15 00:01 6104 2017-04-15 00:06 6114 285 1 2017-04 NA NA
2017-04-15 00:01 6174 2017-04-15 00:11 6174 569 1 2017-04 NA NA

Nous constatons que les 2 premières observations ont le même prédicteur, alors que dans les faits les heures de lever et de coucher diffèrent à l’intérieur de chaque mois.

Nous utiliserions donc une source de données en jointure, sachant que son pouvoir prédictif n’est pas aussi élevé qu’il pourrait l’être.

3.3.2.4.2 Faible niveau de confiance

Un faible niveau de confiance dans la jointure est présent lorsque la clé de jointure comporte de l’incertitude. Contrairement au cas précédent où nous compressions volontairement l’information de la clé de jointure pour joindre des données aggrégées, ce cas-ci se produit lorsque la clé produit des jointures irrégulières ou imprévisibles. Par exemple, si nous avions accès au nom du client dans les données étiquetées, et que nous avions accès à des données de jointure triées par nom, il y aurait certainement des clients pour lesquels la jointure des 2 sources retournerait la mauvaise personne ou plusieurs personnes.

3.3.2.4.3 Plusieurs jointures

Supposons un instant que nous disposons d’une source de données avec l’altitude pour toute position GPS (nous reviendrons à la connection à des APIs [API]). Supposons également que nous croyons qu’une station de départ plus élevée produit en général des trajets plus longs. Nous pourrions alors joindre successivement plusieurs sources de données jusqu’à temps que le prédicteur (altitude) soit vis-à-vis l’étiquette. En effet, en joignant les données etiquetées, la position GPS de chaque station et l’altitude par position GPS :

start_station_code duration_sec
7060 1841
6173 553
6203 195
6104 285
6174 569
code name latitude longitude
7060 de l’Église / de Verdun 45.463 -73.57157
6203 Hutchison / Sherbrooke 45.507 -73.57208
6104 Wolfe / René-Lévesque 45.516 -73.55419
6174 Roy / St-Denis 45.519 -73.57270
6173 Berri / Cherrier 45.519 -73.56951
longitude latitude elevation
-73.57157 45.463 10
-73.57208 45.507 20
-73.55419 45.516 15
-73.57270 45.519 5
-73.56951 45.519 100

Nous obtiendrions le résultat suivant, avec lequel nous pourrions continuer la modélisation prédictive avec un nouveau prédicteur : l’altitude :

start_station_code elevation duration_sec
7060 10 1841
6173 100 553
6203 20 195
6104 15 285
6174 5 569

En soi, la multitude de jointure n’est pas un problème. Or, elle amplifie les problèmes précédents (perte de confiance ou de qualité) en les multipliant entre eux.

Nous discartons maintenant l’élévation parce que le rapport complexité-bénéfice nous semble très élevé.

3.3.2.5 Biais

Plusieurs biais peuvent se glisser dans la collecte de données. Les plus vicieux sont sans doute les biais socio-démographiques, qui sont présents dès que des données personnelles (ou leurs proxys) sont en jeu, et sont aggravés lorsque les prédictions ont un impact réel sur la vie des gens. Nous devons donc rester vigilents à cette réalité durant la collecte.

3.3.3 Volume

Dans le cas des données, on parlera de volume plutôt que de quantité. Nous définissons le volume comme l’espace occupé par un objet sur disque ou en mémoire. Le volume d’une source de données sera donc le produit du nombre d’observations et de la richesse de chaque observation. Si notre source de données contient beaucoup d’observations ou des observations riches, nous aurons des contraintes de rapidité de calcul, d’espace disque ou de mémoire au moment de l’entraînement, et potentiellement même au moment de la prédiction selon l’algorithme choisi.

Si nous avons le malheur d’être ensevelis sous des observations en trop grand nombre ou d’une trop grande richesse, plusieurs options s’offrent à nous, qu’elles soient informatiques ou mathématiques/statistiques.

Du point de vue informatique, R est parfois réputé lent et capricieux en termes de mémoire vive. Or, il n’en est rien. En effet, il existe plusieurs stratégies simples pour optimiser une expression R : profiler le code, comprendre la gestion de la mémoire ou des interfaces C++ et C.

Du point de vue mathématique, il serait étonnant que la quantité d’observations etiquetées soit trop grande. Comme a déjà admis le Scientifique en Chef de Google : «Nous n’avons pas de meilleurs algorithmes que n’importe qui d’autre; nous avons seulement plus de données». Pour contourner les problèmes de mémoire ou d’espace disque, il existe des algorithmes qui taitent les données par batches, c’est-à-dire par tranches de \(n\) observations à la fois, où \(n\) devra être assez petit pour contourner les contraintes d’espace, mais assez grand pour que l’algorithme puisse généraliser son apprentissage. C’est le cas notamment des algorithmes d’apprentissage profond.

Pour les besoins de l’atelier, nous utiliserons seulement les données de 2017 pour entraîner le modèle, mais vous pouvez vous amuser à modéliser avec autant de données que vous le désirez!

3.3.3.1 Aggrégation

À la section précédente, nous avons pris la peine de préciser que ce sont les données etiquetées qui ne peuvent pas être trop nombreuses. Par contre, pour toutes les données de jointure, il est possible que les clés de jointure ne soient pas tout à fait alignées avec leur correspondance dans les données etiquetées. Par exemple, si le taux d’échantillonnage des données de jointure n’est pas aussi précis que le permet la clé dans les données etiquetées, nous devrons nous contenter d’une valeur aggrégée, par exemple la moyenne sur une plus longue période. D’un point de vue mathématique, nous préférerons une source la plus granulaire possible, car nous aurions toujours la possibilité de faire l’aggrégation nous-même si nécessaire. Nous évitons ainsi la perte potentielle d’information prédictive pour notre modèle. Par contre, des contraintes de coûts ou d’entreposage pourraient nous forcer à entreposer des données aggrégées.

Pour effectuer ces aggrégations, il existe plusieurs écoles de pensées en R. Les packages base, dplyr et data.table sont tous capables d’effectuer la majorité des opérations, mais avec des vitesses et des convivialités variables d’une tâche à l’autre. Plutôt que choisir un camp, nous nous contenterons de vous orienter vers cette discussion, qui dresse les avantages et les désavantages de ces méthodes

3.4 Références

## 
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
## 
##     date
## data.table 1.11.8  Latest news: r-datatable.com
## 
## Attaching package: 'data.table'
## The following objects are masked from 'package:lubridate':
## 
##     hour, isoweek, mday, minute, month, quarter, second, wday,
##     week, yday, year
## Loading required package: sp
## rgdal: version: 1.4-3, (SVN revision 828)
##  Geospatial Data Abstraction Library extensions to R successfully loaded
##  Loaded GDAL runtime: GDAL 2.2.3, released 2017/11/20
##  Path to GDAL shared files: C:/Users/Samuel/Dropbox/Documents/R/win-library/3.5/rgdal/gdal
##  GDAL binary built with GEOS: TRUE 
##  Loaded PROJ.4 runtime: Rel. 4.9.3, 15 August 2016, [PJ_VERSION: 493]
##  Path to PROJ.4 shared files: C:/Users/Samuel/Dropbox/Documents/R/win-library/3.5/rgdal/proj
##  Linking to sp version: 1.3-1