-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdataset.tex
308 lines (260 loc) · 24.1 KB
/
dataset.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
Cette section est consacrée à l'étude des données disponibles sur les courses de Formule 1 et à la création d'un dataset adapté
à l'entrainement d'un modèle de Machine Learning.
\section{Données existantes}
Il existe 2 principales sources de données disponibles sur les courses de Formule 1.
La première est le dataset Ergast, qui est un projet open source qui répertorie des données sur les résultats des Grand Prix.
La seconde est la Formule 1 elle-même qui diffuse publiquement une certaine partie des données, dites "Live Timing",
qui correspondent aux données des capteurs des voitures.
Les données ont donc plusieurs temporalités :
\begin{itemize}
\item les informations sur un weekend de courses (circuit, saison, etc.)
\item les données pour un tour de course (temps au tour, gomme de pneu, etc.)
\item les données des capteurs (vitesse, distance avec les autres voitures, etc.)
\end{itemize}
FastF1 est une librairie Python qui permet facilement d'accéder aux données de l'API Ergast et aux données officielle de la Formule 1 depuis 2018.
\fig[H, width=0.9\textwidth]{Diagramme en couches des données}{data_layers.svg}
La quantité entre les catégories de données que nous avons surnommés respectivement données de courses, données de tour et données de télémétrie
sont très différentes.
\fig[H, width=0.9\textwidth]{Nombre de données par courses, pour chaque catégorie de données}{nbSamples.svg}
\subsection{Données de courses}
Ces données donnent des informations sur le weekend de course et ne changent pas au cours de ce dernier.
La majorité des features de cette catégorie sont connues pendant la course et donc au moment de l'inférence.
\begin{table}[h]
\begin{center}
\caption{Liste d'exemple de features 'données de courses'}
\begin{tabular}{l|l}
Nom de la feature & Exemple de valeur \\ \hline
season & 2021 \\
circuit & Monaco \\
number of laps & 78
\end{tabular}
\end{center}
\end{table}
Les autres features sont liées au résultat de la course et ne serais pas disponibles pendant la prédiction.
Mais elles pourraient être utilisées pendant l'entrainement pour par exemple pondérer plus fortement
les stratégies de voitures qui ont de meilleurs résultats.
\subsection{Données de tour}
L'API de la Formule 1 permet d'écouter un flux de données dit "Live Timing".
Ce flux contient différents canaux :
\begin{table}[H]
\begin{center}
\caption{Liste des différents canaux fournis dans le flux de données "Live Timing" \cite{fastf1documentation}}
\begin{tabular}{l|l}
Canal & Description \\ \hline
LapNumber & Numéro du tour en cours \\
Driver & Numéro identifiant du pilote \\
LapTime & Temps du tour précédent \\
Stint & Nombre de relais effectués \\
TotalLaps & Nombre total de tours effectués avec ce set de pneus \\
Compound & Type de pneus utilisé \\
New & Indique si le pneu a été neuf au moment de son montage \\
TyresNotChanged & Signale les arrêts aux stands sans changement de pneus \\
Time & Temps écoulé depuis le début de la session \\
LapFlags & Drapeaux survenus pendant le tour
\end{tabular}
\end{center}
\end{table}
À chaque instant, seulement certains canaux sont actifs. La librairie FastF1 effectue le travail de les agréger sur le parcours d'un tour. Et permet de récupérer ses informations pour tous les tours effectués.
Il serait donc possible de s'abonner à ce flux de donner et d'envoyer directement les informations
émises en entrée du système de prédiction. Un exemple du flux est présenté dans la Table \ref{Live Timing} en annexe.
\subsection{Données de télémétrie}
L'API de la Formule 1 émet également un flux de données pour les données des capteurs des voitures et des capteurs météorologiques.
Les données des capteurs sont envoyés a travers 2 différents flux "Car data" et "Position data" avec des mesures qui sont envoyées environ toutes les 240 millisecondes.
\begin{table}[H]
\begin{center}
\caption{Liste des différents canaux fournis dans le flux de données "Car data" \cite{fastf1documentation}}
\begin{tabular}{l|l}
Canal & Description \\ \hline
Time & Temps écoulé depuis le début de la session \\
Date & Date exacte de la prise de l'échantillon \\
Speed & Vitesse de la voiture en Km/h \\
RPM & Régime moteur \\
Gear & Rapport de vitesse \\
Throttle & Pression sur l'accélérateur, exprimé en pourcentage de 0 à 100 \\
Brake & Indicateur de freinage, Vrai si les freins sont enclenchés, faux sinon \\
DRS & Système de réduction de traînée (Drag Reduction System) \\
& Il comporte plusieurs valeurs possibles codifiées : \\
& 0-1 = désactivé, 8 = éligible, 10-14 = activé
\end{tabular}
\end{center}
\end{table}
\begin{table}[H]
\begin{center}
\caption{Liste des différents canaux fournis dans le flux de données "Position data" \cite{fastf1documentation}}
\begin{tabular}{l|l}
Canal & Description \\ \hline
Time & Temps écoulé depuis le début de la session \\
Date & Date exacte de la prise de l'échantillon \\
Status & 'OnTrack' ou 'OffTrack' (en dehors des limites du circuit) \\
X, Y, Z & Coordonnées de position relative en mètre
\end{tabular}
\end{center}
\end{table}
Pour chaque tour de course d'une voiture, il y a alors entre ~300 et 1'000 échantillons de données télémétriques en fonction de la longueur du circuit.
Ces données offrent un aperçu de la performance de la voiture et permettrait d'estimer la performance du pneumatique.
Un exemple de données télémétriques échantillonnées sur un tour de course est donné en figure \ref{telemetry_example}.
\fig[H, width=0.9\textwidth]{\label{telemetry_example} Exemple de données de télémétrie d'un tour de Carlos Sainz au Grand Prix de Grande-Bretagne 2021}{telemetry_example.svg}
\section{Création d'un dataset}
Les modélisations explorées dans ce travail prennent en entrée les informations d'un ou plusieurs tours de course.
Dans ce contexte, nous avons décidé de discrétiser chaque course en tour pour chaque voiture.
À titre d'exemple, une course de 50 tours engendre alors 50 x 20 entrées dans la base de données si les 20 voitures terminent la course.
Le sous-ensemble des champs considérés est présentée en table \ref{dataset_features}. Ces variables retenues résultent d'une phase de sélection dans laquelle
les variables non pertinentes, redondantes ou non prédictive ont été éliminées.
\begin{table}[H]
\begin{center}
\caption{\label{dataset_features}Champs retenus dans le dataset}
\begin{tabular}{ll}
Champ & Description \\ \hline
LapNumber & Numéro du tour en cours \\
LapTime & Temps du tour en secondes \\
DriverNumber & Numéro unique du pilote \\
Team & Nom de l'écurie \\
Compound & Composé de pneu utilisé (soft, medium ou hard) \\
TyreLife & Âge des pneus en nombre de tours \\
TotalLaps & Nombre de tours totaux de la course \\
Track & Nom du circuit \\
TrackStatus & Drapeaux de course apparaissant pendant le tour \\
Stint & Nombre de relais effectués \\
DistanceToDriverAhead & Distance en mètre avec la voiture devant \\
DriverAhead & Numéro unique du pilote devant \\
Position & Position dans la course \\
GapToLeader & Distance en secondes avec le pilote en tête \\
IntervalToPositionAhead & Distance en secondes avec le pilote devant \\
LapsToLeader & Nombre de tours de retard avec le pilote en tête \\
PitStatus & In Lap / Out Lap / No Pit \\
\end{tabular}
\end{center}
\end{table}
Pour simplifier les opérations de regroupement des tours, 2 colonnes ont étées ajoutées "RoundNumber" et "Year", respectivement le numéro de la course dans la saison et l'année de la course.
Pour les données télémétriques qui sont échantillonnées plus d'une fois par tour,
on prend la dernière mesure au moment où la voiture franchit la ligne d'arrivée.
Les tours avec des informations manquantes ont été exclus.
Les saisons 2019 à 2022 compris ont étés considérés, l'année 2023 étant en cours au moment de la rédaction de ce projet
est réservée comme données de test. La base de données contient 87'845 tours de 80 courses et est disponible ici. % TODO link
\section{Traitement des données}
Les données doivent être préparées pour être utilisées dans le modèle. Les données inutilisable doivent être éliminées
et certaines colonnes doivent être transformées.
L'objectif étant de prédire si un pilote va s'arrêter au stand ou non, la colonne PitStatus est utilisée pour créer la variable binaire cible is\_pitting qui vaut 1 si le pilote s'arrête au stand et 0 sinon.
"PitStatus" est une colonne catégorielle qui prend 3 valeurs possibles : "In Lap", "Out Lap" et "No Pit".
"In Lap" signifie que le pilote est entré dans la voie des stands, "Out Lap" signifie qu'il en est sorti et "No Pit" signifie qu'il n'est pas entré dans la voie des stands.
Pour créer la variable cible, les valeurs "In Lap" sont considérées comme 1 et les autres comme 0.
Les données étant échantillonnées à chaque passage de la ligne d'arrivée, les informations relatives à un tour "In Lap" sont impactées par le temps passé dans la voie des stands.
En d'autres termes, les tours "In Lap" et "Out Lap" sont plus longs que les autres tours. Il est impératif donc de décaler la valeur de la variable cible d'un tour vers le haut.
Ainsi, la valeur de "PitStatus" au tour $n$ correspond au tour d'entrée au stand du tour $n+1$.
De cette manière quand le modèle effectue une prédiction avec les données du tour $n$, il prédit si le pilote entrera au stand au tour $n+1$.
Pour ce faire, les tours ont étés regroupés par course en utilisant les champs "DriverNumber", "RoundNumber" et "Year".
Dans chacun de ces groupes, les tours sont ordonnés par "LapNumber" et les valeurs de "PitStatus" sont décalées d'un tour vers le haut. Pour le dernier tour de course on considère que la voiture n'entrera pas au stand.
Les tours "In Lap" et "Out Lap" sont ensuite exclus du dataset car ils ne sont pas représentatifs.
On peut observer en figure \ref{LapTime_distribution_pitStatus} l'impact de la transformation de la variable cible sur le temps des tours.
\fig[H, width=0.7\textwidth]{
\label{LapTime_distribution_pitStatus}Distribution de la différence de temps entre les tours et la médiane des tours de la course en fonction de la variable cible.
}{LapTime_distribution_pitStatus.svg}
Le deuxième problème est le choix des pneumatiques à utiliser.
Les données contiennent le composé de pneu utilisé pour chaque tour via la variable catégorielle "Compound".
Elle est décalée de 2 tours vers le haut et copiée dans la colonne "NextCompound". Ainsi, la valeur de "NextCompound" au tour $n$ correspond au composé de pneu utilisé au tour $n+2$.
La raison de ce décalage est que l'on veut décider du composé de pneu à utiliser au moment ou l'on prend la décision d'entrer au stand.
Étant donnée que les informations du tour sont capturées quand la voiture franchit la ligne d'arrivée,
le nouveau composé de pneu est connu au moment où la voiture franchit la ligne d'arrivée lors de son tour de sortie des stands.
La gestion de conditions météorologiques changeantent est un problème complexe qui n'est pas abordé dans ce travail.
Les courses sous la pluie sont donc exclues du dataset. Pour ce faire, les tours ont étés regroupés par course en utilisant les champs "DriverNumber", "RoundNumber" et "Year".
Un groupe représente alors l'intégralité des tours d'une course pour un pilote donné. Les courses qui contiennent des tours avec des pneumatiques pluie sont exclues.
Dans certains cas, les pilotes ne terminent pas la course pour des raisons diverses (accident, problème mécanique, etc.).
Ces tours doivent également être exclus du dataset. Pour ce faire, les tours ont encore étés regroupés par course de la même manière.
Un groupe est alors considéré comme valide si le nombre de tours dans le groupe est supérieur au nombre de tours total de la course moins 3.
Cette marge de 3 tours est ajoutée pour considérer les voitures qui abandonnent dans les derniers tours de la course et les voitures ayant des tours de retards car leur stratégie est quand même pertinente.
Dans d'autres cas, différentes situations peuvent amener des voitures à effectuer des arrêts au stands supplémentaires (pénalité, dégâts, etc.).
Ces arrêts supplémentaires peuvent fausser la prédiction de la stratégie. Nous avons donc décidé de ne pas les considérer.
Les tours ont étés regroupés par course comme précédemment et les courses avec plus de 3 arrêts ont étés exclues.
Pour éviter de biaiser le modèle avec des informations comme l'identité du pilote ou de l'écurie, les tours ont étés anonymisés en supprimant les colonnes "DriverNumber" et "Team".
En effet, les performances des pilotes et des écuries varient d'une saison à l'autre et il ne faut pas que le modèle apprenne à prédire la stratégie en fonction de ces informations.
La feature TrackStatus communiquée dans l'api officielle contient un ensemble d'entier concaténé dans une chaine de caractères où chaque entier représente un drapeau de course agité au cours du tour.
Les différents status et leur entier correspondant sont détaillé dans la table \ref{track_status_table}.
\begin{table}[H]
\begin{center}
\caption{\label{track_status_table}Correspondance des status de piste}
\begin{tabular}{r|l|l}
Entier & Correspondance & Description \\ \hline
1 & Drapeau vert & La piste est libre \\
2 & Drapeau jaune & La piste est partiellement bloquée, la course \\
& & continue, mais les dépassements sont interdit \\
& & dans un ou plusieurs secteurs \\
4 & Voiture de sécurité & La course est neutralisée, les voitures ne \\
& & peuvent pas dépasser, réduisent leur vitesse \\
& & et font la queue derrière la voiture de \\
& & sécurité \\
5 & Drapeau rouge & La course est interrompue, toutes les voitures \\
& & rentrent au stand \\
6 & Voiture de sécurité & La course est neutralisée, les voitures ne \\
& virtuelle & peuvent pas dépasser et réduisent leur \\
& & vitesse \\
7 & Fin de la voiture de & La voiture de sécurité rentre à la fin de ce \\
& sécurité & tour
\end{tabular}
\end{center}
\end{table}
Pour l'utiliser, elle a été transformée en 6 features binaires où chaque feature représente la présence d'un statut.
Les distributions de la variable avant et après la transformation est observable en figure \ref{track_status_plot}.
\fig[H, width=0.9\textwidth]{\label{track_status_plot}Distribution de la feature TrackStatus avant et après la discrétisation}{track_status_binarized.svg}
6'455 observations avait des valeurs manquantes pour les colonnes DriverAhead et DistanceToDriverAhead.
Il est logique que ces valeurs soient manquantes pour les tours de la voiture en tête de course.
Cependant, en étudiant la distribution des numéros de tour de ces observations,
présentés en figure \ref{hist_missing_driver_ahead}, on remarque que la plupart des tours sont les premiers de la course.
Il n'est pas clair pourquoi ces valeurs sont manquantes, mais il est possible que ce soit un problème de la capture des données.
Les premiers tours de la course sont donc exclus du dataset, ce qui ne pose pas de problème car il est très rare d'avoir des arrêts au stand dans les premiers tours.
Le reste de la distribution est assez uniforme avec une légère diminution de la fréquence après 55 tours, car la majorité des courses durent entre 50 et 60 tours.
\fig[H, width=0.9\textwidth]{\label{hist_missing_driver_ahead}Distribution de la feature LapNumber pour les tours avec des valeurs manquantes}{lap_number_without_driver_ahead.svg}
En figure \ref{gap_leader_missing}, on voit que beaucoup d'échantillons n'ont pas de valeurs pour la colonne GapToLeader et en observants la figure \ref{gap_leader_laps}, on remarque que ce sont tous des voitures qui ont au moins un tour de retard.
Il est difficile et peut intéressant de déterminer l'écart entre une voiture retardataire et le leader, les valeurs manquantes ont donc été remplacées par -1.
\fig[H, width=0.9\textwidth]{\label{gap_leader_missing}Valeurs manquantes de chaque colonne, les observations d'IntervalToPositionAhead nulles sont celles de voiture avec un tour de retard sur tout le peloton, celles avec des valeurs manquantes de DistanceToDriverAhead et DriverAhead sont ceux du pilote en tête.}{null_values_per_column_after_cleaning.svg}
\fig[H, width=0.9\textwidth]{\label{gap_leader_laps}Histogramme de la caractéristique LapsToLeader lorsque GapToLeader est nul}{gap_to_leader_when_laps_to_leader_is_null.svg}
Les features Track et Compound de notre dataset nécessitent un prétraitement avant d'être utilisées dans notre modèle. Nous avons utilisé l'encodage one-hot de la bibliothèque scikit-learn pour effectuer cette transformation.
L'encodage one-hot est une technique couramment utilisée pour représenter des variables catégorielles sous forme de vecteurs binaires.
Par exemple pour la feature Track, en utilisant l'encodage one-hot, on crée des variables binaires pour chaque piste, où une variable est définie à 1 si la course a eu lieu sur cette piste et 0 sinon.
L'utilisation de l'encodage one-hot nous permet de représenter ces caractéristiques catégorielles en évitant d'introduire un ordre ou une relation numérique entre les catégories.
Pour gérer de manière robuste les nouveaux circuits, le OneHotEncoder à été initialisé avec le paramètre handle unknown='ignore'.
De cette manière, le OneHotEncoder ignore simplement les catégories inconnues et génère un vecteur de zéros correspondant à cette catégorie.
L'intégralité des étapes de prétraitement sont résumées dans la figure \ref{preprocessing_pipeline}.
%TODO modifier le graphique pour qu'il soit joli
\fig[H, width=0.5\textwidth]{\label{preprocessing_pipeline}
Pipelines de prétraitement des données, le pipeline de gauche est utilisé pour le modèle de prediction des gommes et celui de droite pour le modèle de prédiction de l'arrêt au stand.
}{preprocessing_pipeline.svg}
\section{Exploration des données}
%TODO modifier le nombre de colonnes
En faisant analyse de forme, le set de données final possède 84'630 lignes et 22 colonnes dont 11 variables quantitatives et 11 qualitatives, la distribution des types de données est en figure \ref{data_types_distribution}.
1'600 lignes ont été supprimées, car elles possédaient des valeurs manquantes, soit environ 2\% du dataset.
\fig[H, width=0.7\textwidth]{\label{data_types_distribution}Distribution des types des features du dataset}{data_types_distribution.svg}
La première variable cible étudiée est is\_pitting. Les voitures ne rentrant en moyenne qu'une à trois fois au stand par course, la distribution de cette variable est très déséquilibrée.
Seulement 3\% de cas positifs, une attention particulière doit donc être accordée à la gestion de ce déséquilibre
lors de la phase de modélisation afin d'éviter tout biais potentiel.
\begin{table}[H]
\begin{center}
\caption{Proportion des valeurs de la target is pitting}
\begin{tabular}{r|l}
Négatif & 0.970318 \\
Positif & 0.029682
\end{tabular}
\end{center}
\end{table}
La distribution de la variable Compound est en figure \ref{compound_distribution}.
On remarque que les pneumatiques les plus utilisés sont les pneumatiques durs et mediums.
Les pneumatiques tendres sont moins représentés, étant moins durable les voitures effectuent moins de tours avec.
Les intermédiaires et les wets sont utilisés beaucoup moins souvent, car ils ne sont utilisés que dans des conditions météorologiques particulières.
Ils ne seront pas présent dans le dataset final, car les courses avec des conditions météorologiques particulières ont été supprimées.
\fig[H, width=0.9\textwidth]{\label{compound_distribution}
Distribution de la colonne Compound
}{Compound_distribution.svg}
Dans la section suivante, nous examinons la distribution des features du jeu de données.
Seules les plus intéressantes sont présentées ici, les autres seront fournies en annexe \ref{sec:features}.
La distribution en figure \ref{tyreLife_distribution} est unimodal et asymetrique, cela est dû à la nature de l'évolution de l'age des pneumatiques lors de la course.
Supposons que dans une course de 60 tours on effectue des arrêts tous les 20 tours, on a trois périodes distinctes pour les âges des pneumatiques : 1-20 tours, 21-40 tours et 41-60 tours.
Chaque valeur de 1 à 20 apparaîtra trois fois dans la colonne TyreLife.
En revanche, si une voiture ne fait aucun arrêt et parcourt les 60 tours sans changer les pneumatiques, chaque valeur entre 1 et 60 aura seulement un échantillon.
\fig[H, width=0.9\textwidth]{\label{tyreLife_distribution}
Distribution de la colonne TyreLife
}{TyreLife_distribution.svg}
La figure \ref{track_distribution}, présente la distribution de la variable Track.
Track représente le circuit sur lequel la course a lieu, la distribution est assez déséquilibrée, car certains circuits sont plus courts que d'autres se qu'il fait que les pilotes effectuent moins de tours sur ces circuits.
Et d'autre ne sont pas utilisés tous les ans comme le Mugello qui a été utilisé qu'une fois en 2020.
\fig[H, width=0.9\textwidth]{\label{track_distribution}
Distribution de la colonne Track
}{Track_distribution.svg}