Artificial Intelligence (AI)

Fabric Madness. Predicting basketball games with… | by Roger Noble | Apr, 2024

Written by smirow

Prédire les matchs de basket avec Microsoft Fabric

Roger Noble
Vers la science des données
Image de l'auteur et ChatGPT. « Concevoir une illustration, en se concentrant sur un joueur de basket-ball en action, la conception intègre des thèmes de sport et d'analyse de données dans un style de roman graphique ». ChatGPT, 4, OpenAI, 28 mars. 2024. https://chat.openai.com.

Un immense merci à Martin Chaves qui a co-écrit cet article et développé les exemples de scripts.

Au moment d'écrire ces lignes, c'est la saison de basket-ball aux États-Unis, et les tournois de basket-ball universitaire masculin et féminin suscitent beaucoup d'enthousiasme. Le format est à élimination simple, donc au cours de plusieurs tours, les équipes sont éliminées jusqu'à ce que nous obtenions finalement un champion. Ce tournoi n’est pas seulement une vitrine des futurs talents du basket-ball, mais, plus important encore, un terrain fertile pour les passionnés de données comme nous qui souhaitent analyser les tendances et prédire les résultats.

L'un des avantages du sport est qu'il existe de nombreuses données disponibles, et chez Noble Dynamic, nous voulions nous y essayer 🤓.

Dans cette série d'articles intitulée La folie des tissusnous allons approfondir certaines des fonctionnalités les plus intéressantes de Microsoft Fabric, pour une démonstration de bout en bout de la façon de former et d'utiliser un modèle d'apprentissage automatique.

Dans ce premier article de blog, nous aborderons :

  • Un premier aperçu des données à l'aide de Data Wrangler.
  • Analyse exploratoire des données (EDA) et ingénierie des fonctionnalités
  • Suivi des performances de différents modèles d'apprentissage automatique (ML) à l'aide d'expériences
  • Sélection du modèle le plus performant à l'aide de la fonctionnalité ML Model

Les données utilisées ont été obtenues lors du concours Kaggle en cours, dont les détails peuvent être trouvés ici, sous licence CC BY 4.0. [1]

Parmi toutes les données intéressantes disponibles, nous nous sommes concentrés pour cette étude de cas sur les statistiques match par match. Ces données étaient disponibles aussi bien pour les saisons régulières que pour les tournois, depuis 2003. Pour chaque match, outre la date, les équipes qui jouaient et leurs scores, d'autres caractéristiques pertinentes étaient disponibles, telles que les buts sur le terrain. commises et fautes personnelles de chaque équipe.

Chargement des données

La première étape consistait à créer un tissu Espace de travail. Les espaces de travail dans Fabric sont l’un des éléments fondamentaux de la plate-forme et sont utilisés pour regrouper des éléments associés et pour la collaboration.

Après avoir téléchargé tous les fichiers CSV disponibles, un Maison au bord du lac a été créé. En termes simples, un Lakehouse est un mélange entre un Base de données de tableaux (structurés) et un Lac de données de fichiers (non structurés). Le grand avantage d'un Lakehouse est que les données sont disponibles pour chaque outil de l'espace de travail.

Le téléchargement des fichiers a été effectué à l'aide de l'interface utilisateur :

Fig. 1 — Téléchargement de fichiers. Image de Martim Chaves

Maintenant que nous avons un Lakehouse avec les fichiers CSV, il était temps de creuser et d'avoir un premier aperçu des données. Pour ce faire, nous avons créé un bloc-notes, à l'aide de l'interface utilisateur, et joint le Lakehouse précédemment créé.

Fig. 2 — Ajout de Lakehouse au bloc-notes. Image de Martim Chaves

Premier coup d'oeil

Après une rapide analyse des données, il a été constaté que, comme prévu avec les données de Kaggle, la qualité était excellente. Sans doublons ni valeurs manquantes.

Pour cette tâche, nous avons utilisé Data Wrangler, un outil intégré aux notebooks Microsoft Fabric. Une fois qu'un DataFrame initial a été créé (Spark ou Pandas pris en charge), Data Wrangler devient disponible et peut être attaché à n'importe quel DataFrame du Notebook. Ce qui est génial, c'est qu'il permet une analyse facile des DataFrames chargés.

Dans un bloc-notes, après avoir lu les fichiers dans PySpark DataFrames, dans la section « Données », le « Transform DataFrame in Data Wrangler » a été sélectionné, et à partir de là, les différents DataFrames ont été explorés. Des DataFrames spécifiques peuvent être choisis, en effectuant une inspection minutieuse.

Fig. 3 — Ouverture de Data Wrangler. Image de Martim Chaves
Fig. 4 — Analyse du DataFrame avec Data Wrangler. Image de Martim Chaves

Au centre, on a accès à toutes les lignes du DataFrame chargé. A droite, un Résumé onglet, montrant qu'en effet il n'y a pas de doublons ou de valeurs manquantes. En cliquant dans une certaine colonne, les statistiques récapitulatives de cette colonne seront affichées.

A gauche, dans le Opérations , plusieurs opérations prédéfinies peuvent être appliquées au DataFrame. Les opérations comportent bon nombre des tâches de gestion des données les plus courantes, telles que le filtrage, le tri et le regroupement, et constituent un moyen rapide de générer du code passe-partout pour ces tâches.

Dans notre cas, les données étaient déjà en bon état, nous sommes donc passés à l’étape EDA.

L'analyse exploratoire des données

Une brève analyse exploratoire des données (EDA) a suivi, dans le but d'avoir une idée générale des données. Des graphiques ont été tracés pour avoir une idée de la distribution des données et déterminer s'il existait des statistiques qui pourraient poser problème en raison, par exemple, de très longues traînes.

Fig. 5 — Histogramme des buts sur le terrain réalisés. Image de Martim Chaves

D'un simple coup d'œil, il a été constaté que les données disponibles pour la saison régulière avaient des distributions normales, adaptées à la création de fonctionnalités. Connaissant l’importance des bonnes fonctionnalités dans la création de systèmes prédictifs solides, l’étape suivante judicieuse consistait à réaliser une ingénierie des fonctionnalités pour extraire des informations pertinentes des données.

L'objectif était de créer un ensemble de données dans lequel l'entrée de chaque échantillon serait un ensemble de fonctionnalités pour un jeu, contenant des informations sur les deux équipes. Par exemple, les deux équipes font la moyenne des buts sur le terrain réalisés pour la saison régulière. La cible pour chaque échantillon, le résultat souhaité, serait 1 si l'équipe 1 gagnait la partie, ou 0 si l'équipe 2 gagnait la partie (ce qui a été fait en soustrayant les scores). Voici une représentation de l'ensemble de données :

Ingénierie des fonctionnalités

La première fonctionnalité que nous avons décidé d’explorer était le taux de victoire. Non seulement ce serait une fonctionnalité intéressante à explorer, mais cela fournirait également un score de référence. Cette approche initiale utilisait une règle simple : l’équipe ayant le taux de victoire le plus élevé serait prédite comme gagnante. Cette méthode fournit une référence fondamentale à laquelle les performances de systèmes prédictifs plus sophistiqués peuvent être comparées.

Pour évaluer l'exactitude de nos prédictions sur différents modèles, nous avons adopté le score de Brier. Le score Brier est la moyenne du carré de la différence entre la probabilité prédite (p) et le résultat réel (o) pour chaque échantillon, et peut être décrit par la formule suivante :

Image de l'auteur

La probabilité prédite variera entre 0 et 1, et le résultat réel sera soit 0, soit 1. Ainsi, le score Brier sera toujours compris entre 0 et 1. Comme nous voulons que la probabilité prédite soit aussi proche que possible du résultat réel. , plus le score du Brier est bas, mieux c'est, 0 étant le score parfait et 1 le pire.

Pour la référence, la structure de l'ensemble de données mentionnée précédemment a été suivie. Chaque échantillon de l'ensemble de données était un match contenant les taux de victoire pour la saison régulière pour l'équipe 1 et l'équipe 2. Le résultat réel était considéré comme 1 si l'équipe 1 gagnait, ou 0 si l'équipe 2 gagnait. Pour simuler une probabilité, la prédiction était une différence normalisée entre le taux de victoire de T1 et le taux de victoire de T2. Pour la valeur maximale de la différence entre les taux de victoire, la prédiction serait 1. Pour la valeur minimale, la prédiction serait 0.

Après avoir calculé le taux de victoire, puis l'avoir utilisé pour prédire les résultats, nous avons obtenu un score au Brier de 0,23. Considérant que deviner au hasard conduit à un score Brier de 0,25force est de constater que cette fonctionnalité à elle seule n'est pas très bonne 😬.

En partant d’une base de référence simple, il a clairement mis en évidence que des modèles plus complexes étaient en jeu. Nous avons développé 42 fonctionnalités supplémentaires, en préparation à l'utilisation d'algorithmes plus complexes et de modèles d'apprentissage automatique, qui pourraient avoir de meilleures chances.

Il était alors temps de créer des modèles de machine learning !

Pour les modèles, nous avons opté pour de simples réseaux de neurones (NN). Pour déterminer quel niveau de complexité serait le meilleur, nous avons créé trois NN différents, avec un nombre croissant de couches et d'hyper-paramètres. Voici un exemple de petit NN, celui qui a été utilisé :

Fig. 6 — Schéma d'un réseau neuronal. Image de Martim Chaves utilisant draw.io

Si vous êtes familier avec les NN, n'hésitez pas à passer directement aux expériences ! Si vous n'êtes pas familier avec les NN, considérez-les comme un ensemble de couches, où chaque couche agit comme un filtre pour les informations pertinentes. Les données traversent des couches successives, étape par étape, où chaque couche possède des entrées et des sorties. Les données se déplacent à travers le réseau dans une direction, de la première couche (l'entrée du modèle) à la dernière couche (la sortie du modèle), sans rebouclage, d'où le Séquentiel fonction.

Chaque couche est composée de plusieurs neurones, que l’on peut qualifier de nœuds. L'entrée du modèle, la première couche, contiendra autant de neurones qu'il y a de fonctionnalités disponibles, et chaque neurone contiendra la valeur d'une fonctionnalité. La sortie du modèle, la dernière couche, dans les problèmes binaires tels que celui que nous abordons, n'aura qu'un seul neurone. La valeur détenue par ce neurone doit être 1 si le modèle traite un match où l'équipe 1 a gagné, ou 0 si l'équipe 2 a gagné. Les couches intermédiaires ont un ad hoc nombre de neurones. Dans l’exemple de l’extrait de code, 64 neurones ont été choisis.

Dans un Dense couche, comme c'est le cas ici, chaque neurone de la couche est connecté à chaque neurone de la couche précédente. Fondamentalement, chaque neurone processus les informations fournies par les neurones de la couche précédente.

Le traitement des informations de la couche précédente nécessite un fonction d'activation. Il existe de nombreux types de fonctions d'activation : RéLU, signifiant Rectified Linear Unit, en fait partie. Il laisse passer uniquement les valeurs positives et met les valeurs négatives à zéro, ce qui le rend efficace pour de nombreux types de données.

Notez que la fonction d'activation finale est un sigmoïde fonction – cela convertit la sortie en un nombre compris entre 0 et 1. Ceci est crucial pour les tâches de classification binaire, où vous avez besoin que le modèle exprime sa sortie sous forme de probabilité.

A côté de ces petits modèles, des modèles moyens et grands ont été créés, avec un nombre croissant de couches et de paramètres. La taille d'un modèle affecte sa capacité à capturer des modèles complexes dans les données, les modèles plus grands étant généralement plus performants à cet égard. Cependant, les modèles plus grands nécessitent également plus de données pour apprendre efficacement : s'il n'y a pas suffisamment de données, des problèmes peuvent survenir. Trouver la bonne taille n'est parfois possible que par l'expérimentation, en entraînant différents modèles et en comparant leurs performances pour identifier la configuration la plus efficace.

La prochaine étape consistait à mener les expériences ⚗️ !

Qu'est-ce qu'une expérience ?

Dans Fabric, une expérience peut être considérée comme un groupe d'exécutions liées, où une exécution est une exécution d'un extrait de code. Dans ce contexte, une exécution est une formation d'un modèle. Pour chaque exécution, un modèle sera formé avec un ensemble différent d'hyper-paramètres. L'ensemble des hyper-paramètres, ainsi que le score final du modèle, sont enregistrés et ces informations sont disponibles pour chaque exécution. Une fois qu'un nombre suffisant d'exécutions ont été réalisées, les scores finaux du modèle peuvent être comparés, afin que la meilleure version de chaque modèle puisse être sélectionnée.

La création d'une expérience dans Fabric peut être effectuée via l'interface utilisateur ou directement à partir d'un bloc-notes. L'expérience est essentiellement un wrapper pour les expériences MLFlow. L’un des avantages de l’utilisation d’Experiments in Fabric est que les résultats peuvent être partagés avec d’autres. Cela permet de collaborer et de permettre à d'autres de participer à des expériences, soit en écrivant du code pour exécuter des expériences, soit en analysant les résultats.

Créer une expérience

En utilisant l'interface utilisateur pour créer une expérience, sélectionnez simplement Expérience dans le menu + Nouveau et choisissez un nom.

Fig. 7 — Création d'une expérience à l'aide de l'interface utilisateur. Image de Martim Chaves

Lors de la formation de chacun des modèles, les hyper-paramètres sont enregistrés avec l'expérience, ainsi que le score final. Une fois terminé, nous pouvons voir les résultats dans l'interface utilisateur et comparer les différentes exécutions pour voir quel modèle a le mieux fonctionné.

Fig. 8 — Comparaison de différentes analyses. Image de Martim Chaves

Après cela, nous pouvons sélectionner le meilleur modèle et l’utiliser pour faire la prédiction finale. En comparant les trois modèles, le meilleur score Brier était 0,20une légère amélioration 🎉 !

Après avoir chargé et analysé les données du tournoi majeur de basket-ball universitaire américain de cette année et créé un ensemble de données doté de fonctionnalités pertinentes, nous avons pu prédire le résultat des matchs à l'aide d'un simple réseau neuronal. Des expériences ont été utilisées pour comparer les performances de différents modèles. Enfin, le modèle le plus performant a été sélectionné pour réaliser la prédiction finale.

Dans le prochain article, nous expliquerons en détail comment nous avons créé les fonctionnalités à l'aide de pyspark. Restez à l'écoute pour plus! 👋

Le code source complet de cet article peut être trouvé ici.

About the author

smirow

Leave a Comment