Share:

L’apprentissage automatique (ML) est l’art d’utiliser des données historiques pour prédire l’avenir. Mais comment utiliser les données historiques, la « vérité du terrain », lorsque le « terrain » est en mouvement constant ? Dans cet article, Yoyu Li, architecte senior de données Cloud, explique comment elle a utilisé AWS pour créer un modèle d’apprentissage automatique entièrement automatisé à partir de données diffusées en direct.

Si vous lisez cet article, vous êtes probablement déjà familiarisé(e) avec les concepts de base. Un flux de travail ML typique ressemble à ceci :

  1. Tout d’abord, nous définissons un problème
  2. Ensuite, nous collectons certaines données et les étiquetons
  3. À l’aide de ces données de « vérité sur le terrain », les scientifiques des données travaillent pour trouver le meilleur ensemble de fonctionnalités, algorithme et paramètres pour créer un modèle
  4. Enfin, nous déployons le modèle pour la prédiction.

Cependant, un problème que nous pouvons rencontrer lors de l’application de ce flux de travail en production est dans les situations où le « terrain » est en mouvement constant, comme à la bourse par exemple.

Pouvons-nous continuellement mettre à jour le modèle ML basé sur les données les plus récentes en automatisant le processus ?

Dans cet article, nous allons examiner un scénario fictif dans lequel nous construisons un modèle ML pour prédire le meilleur moment pour acheter du Bitcoin (afin de réaliser un profit, bien sûr !). Comme vous le savez probablement, le marché du Bitcoin est extrêmement volatile et apparemment irrationnel. Il est impossible d’utiliser le modèle d’hier pour prédire l’évolution du marché aujourd’hui. Ainsi, pour augmenter la précision de la prédiction, nous voulons que le modèle ML soit le plus « frais » possible. Pour relever ce défi, nous présentons un pipeline de formation de modèles ML entièrement automatisé utilisant des données en continu en direct.

Avant de nous plonger dans l’architecture, gardez à l’esprit qu’il n’y a très probablement pas du tout de modèle gagnant dans le trading de Bitcoins. Le mieux que le modèle puisse faire est de minimiser les pertes. Cette démo est uniquement destinée à des fins expérimentales. N’appliquez pas le modèle dans le cadre de transactions réelles.

Vue d’ensemble de l’architecture

La démo est construite sur AWS et s’appuie largement sur la boîte à outils ML d’AWS, Sagemaker, sur laquelle nous allons nous pencher plus en détail. Le schéma ci-dessous offre une vue d’ensemble de l’architecture :

Vue d’ensemble de l’architecture

  • Client streaming : le client streaming est une application node.js qui s’abonne à la source de données de streaming en temps réel d’ IG pour le prix du Bitcoin. L’application stocke ensuite les données du marché dans une base de données MongoDB et génère des données de transaction fictives, que nous utiliserons ultérieurement à des fins de ML. Avec l’instance MongoDB, l’application est ensuite emballée et déployée en tant que conteneur docker sur Amazon ECS, optimisé par Fargate (qui vous permet d’exécuter des conteneurs sans gérer les ressources informatiques sous-jacentes). Pour des raisons de sécurité, nous utilisons également AWS Secrets Manager pour stocker les informations d’identification de l’utilisateur pour IG.
  • S3 Notification + Object Watcher Lambda Function : chaque fois que le client streaming a accumulé suffisamment de points de données (dans notre démo, soit 10 000 transactions terminées), il exporte deux fichiers CSV vers Amazon S3 – l’un pour les prix historiques, l’autre pour les transactions. Une fois que les objets arrivent dans S3, une fonction Lambda reçoit la notification et déclenche l’exécution d’une fonction Step.
  • Orchestration des fonctions Step : nous utilisons AWS Step Functions pour orchestrer notre ETL, modéliser l’apprentissage, le réglage et le pipeline de déploiement. Lorsqu’une exécution de fonction Step démarre, elle déclenche d’abord une fonction Lambda, le vérificateur de fichiers d’entrée, pour voir si les deux fichiers CSV sont dans S3 et transmet les noms d’objet et d’autres paramètres aux tâches suivantes.
  • Glue ETL Jobs : dans le cadre du pipeline, le job ETL Glue joint les données de transaction aux données de prix, extrait les caractéristiques, remplit les valeurs manquantes et transforme les données dans un format binaire, ce qui est requis par l’algorithme ML que nous avons choisi d’utiliser. Il divise également les données en ensembles de données d’apprentissage, de validation et de test.
  • Sagemaker Model Training and Hyperparameter Tuning : avec les ensembles de données dapprentissage, de validation et de test obtenus à partir de la tâche ETL, nous lançons le service Sagermaker Model Training pour préparer le modèle. Pour cette démo, nous utilisons l’un des algorithmes intégrés de Sagemaker, Linear Learner. Sagemaker Hyperparameter Tuning est un service entièrement géré et automatisé qui nous aide à trouver les meilleurs hyperparamètres pour un algorithme ML donné, en formant, ajustant et recyclant les modèles via plusieurs tâches Model Training. Nous pouvons définir un objectif pour chaque travail de réglage, par exemple, si nous voulons maximiser la précision, le rappel ou le score F1 pour la classification binaire. À la fin du réglage, le service suggérera le meilleur modèle de ce lot, cependant, nous pouvons également accéder aux métriques de l’algorithme à sélectionner en fonction de nos propres critères de sélection de modèle.
  • Sagemaker Model Hosting : une fois que nous avons sélectionné le meilleur modèle (dans la démo, nous utilisons une autre fonction Lambda, la fonction Model Selection), nous pouvons déployer le modèle et exposer un point de terminaison pour l’inférence.

Cette architecture événementielle est capable de convertir des données en continu en petits lots et de lancer un processus de ML dès qu’une quantité suffisante de points de données est collectée. Le pipeline automatise le processus d’apprentissage, de réglage et de déploiement du modèle. À la fin du pipeline, le modèle derrière le point de terminaison d’inférence sera « actualisé » avec les dernières données d’apprentissage. Les applications en aval doivent pouvoir utiliser ce point de terminaison pour des prévisions plus à jour.

Plongée en profondeur

Les données et l’énoncé du problème ML

Comme indiqué précédemment, le but de ce modèle ML est de prédire quel est le meilleur moment pour acheter du Bitcoin. Il y a plusieurs façons de formuler ce problème, par exemple, vous pouvez construire un modèle de prévision pour prédire le prix futur du Bitcoin ou un modèle de régression pour prédire la probabilité de profit d’un ordre donné. Ici, nous avons formulé cette question sous la forme d’un problème de classification binaire – à savoir si l’achat de Bitcoin à un moment donné est susceptible d’entraîner un profit ou une perte – nous étiquetons donc chaque transaction comme un profit (1) ou une perte (0), et nous construisons un modèle pour prédire si la rentabilité d’une commande future est susceptible d’être positive ou négative.

La source de données en continu contient le prix en temps réel du Bitcoin en USD et d’autres informations comme le prix d’ouverture, le plus haut et le plus bas de la journée. Vous trouverez ci-dessous un exemple de données de prix :

Exemple de données de prix

Comme nous ne disposons pas de données de transaction réelles, nous devons simuler les transactions. Chaque seconde, un robot de trading place plusieurs faux ordres dans la base de données. Chaque ordre est assorti d’un seuil inférieur et supérieur à partir desquels une action de vente sera déclenchée. Par exemple, nous avons passé un ordre d’achat de Bitcoin à 6 512,5 $, avec une limite inférieure de -10 $ et une limite supérieure de +10 $. Si le prix monte à 6 522,5 $, un ordre de vente sera déclenché, ce qui entraîne un profit de 10 $ ; et si le prix baisse à 6 502,5 $, un ordre de vente sera également déclenché pour limiter la perte. Bien sûr, dans le monde réel, le comportement des traders est beaucoup plus sophistiqué. Nous avons simplifié le modèle de commande pour cette démo, mais le processus d’apprentissage et de réglage des modèles ML devrait être similaire.

 

Vous trouverez ci-dessous un exemple de données de transaction :

Exemple de données de prix

Dans le cadre de cet article, nous n’approfondirons pas l’application Streaming Client elle-même. Nous pouvons simplement supposer de temps en temps qu’il y aura deux fichiers CSV générés – l’un pour toutes les transactions terminées dans une certaine période et l’autre pour les prix.

Extraction de fonctionnalités

Dans cette démo, nous utilisons Glue ETL Jobs pour le traitement des données. Glue est un outil ETL Big Data entièrement géré sur AWS. Avec Glue, nous pouvons exécuter Spark ou Python ETL Jobs à la demande, sans payer pour l’infrastructure lorsque nous n’en avons pas besoin. Bien que dans notre cas, le volume de données soit suffisamment petit pour être géré par une fonction Lambda, pour le bien de la démo, nous utilisons toujours Glue ETL pour le traitement.

L’analyse exploratoire des données et le prototypage ETL ont été réalisés dans un environnement Jupyter local. Dans le répertoire git, il y a un exemple de notebook glue/glue-etl.ipynb qui donne une idée de ce processus (bien qu’en réalité, les notebooks sont beaucoup plus désordonnés). Après plusieurs expérimentations, l’ensemble final de fonctionnalités utilisé dans la démo est le suivant :

Exemples de données de prix

L’ensemble de fonctionnalités est créé en joignant les données de transaction et les prix. Chaque ligne du tableau contient les informations sur les prix au moment où l’ordre a été donné, les prix des 10 dernières minutes et l’étiquette (si la transaction a été profitable). Il a exclu les colonnes telles que l’horodatage qui peuvent être utilisées à cette fin, et a conservé plusieurs colonnes telles que le prix d’achat et le prix de vente dans la table des prix. Et les colonnes 0 à 599 sont le prix historique à moins x seconde(s) par rapport au moment où l’ordre a été donné. En utilisant les points de prix historiques comme caractéristiques, nous recadrons un problème de prédiction de séries temporelles en un problème conventionnel d’apprentissage automatique supervisé.

Dans la pratique réelle, nous pouvons vouloir inclure les informations sur les prix d’une période plus longue (par exemple, les dernières heures ou les derniers jours), ou à une résolution différente (par exemple, chaque minute ou chaque heure) en fonction de la fréquence de trading que nous avons l’intention de faire. Ici, pour la commodité de la démo, nous supposons une fréquence de trading très élevée, par conséquent, nous utilisons les données de prix par seconde au cours des 10 dernières minutes pour la prédiction.

Enfin, nous convertissons tous les prix absolus en prix relatifs par rapport au cours moyen (la moyenne des cours acheteur et vendeur) à ce moment-là, comme indiqué ci-dessous. L’utilisation de cette technique a permis d’obtenir de meilleurs résultats de prédiction dans les modèles d’entraînement expérimentaux. Plus tard, nous configurerons Sagemaker pour normaliser les données dans les fonctionnalités.

Exemples de données de prix

La tâche ETL Glue divise également les données en ensembles de données d’apprentissage, de validation et de test (70/15/15) et les exporte au format binaire RecordIO-Protobuf, comme l’exige l’algorithme de l’apprenant linéaire.

Le script ETL est ensuite déployé dans Glue ETL sous forme de fichier .py et les dépendances python peuvent être déployées sous forme de fichier egg ou wheel. Une fois la tâche déclenchée, Glue exécute le script ETL sur une base ad hoc.

Un examen plus approfondi du réglage de l’hyperparamètre et de la sélection du modèle

Une fois que nous avons les ensembles de données, nous pouvons commencer à former le modèle en utilisant les tâches Sagemaker Model Training. Cependant, il existe de nombreux hyperparamètres accordables pour chaque algorithme ML. Nous avons déjà présenté que nous pouvons utiliser Sagemaker Hyperparameter Tuning pour trouver la meilleure combinaison pour un algorithme ML donné.

Hyperparameter Tuning est une implémentation Amazon de Bayesian Hyperparameter Optimization. Il commence le processus d’ajustement en utilisant une combinaison de base d’hyperparamètres ; puis, sur la base des résultats de validation des premiers modèles, il exécute une recherche bayésienne pour trouver de nouvelles combinaisons susceptibles de générer de meilleurs résultats et entraîne à nouveau les modèles ; en répétant ce processus d’entraînement, d’ajustement et de réentraînement, l’algorithme peut, en théorie, trouver la combinaison optimale pour l’objectif donné.

Comment cela fonctionne-t-il dans la pratique ? Sagemaker étant un service entièrement géré, il suffit de définir un objectif et les paramètres réglables. Sagemaker exécutera le processus d’optimisation et lancera des tâches d’apprentissage pour nous.

Tout d’abord, nous devons définir un modèle de travail d’apprentissage, dans lequel nous spécifions certains hyperparamètres statiques – ceux qui ne sont pas accordables et seront appliqués à toutes les tâches d’apprentissage – par exemple la dimension de la fonctionnalité et le type de prédicteur.

"StaticHyperParameters": {
       "feature_dim": "605",
       "epochs": "15",
       "normalize_data": "true",
       "normalize_label": "false",
       "predictor_type": "binary_classifier",
       "binary_classifier_model_selection_criteria": "precision_at_target_recall",
       "target_recall": "0.25"
    }

Ici, nous définissons également binary_classifier_model_selection_criteria sur precision_at_target_recall et target_recall sur 25 %. Cela signifie que nous voulons que la précision (combien de commandes que le modèle prédit être rentables rapporte réellement de l’argent) soit aussi élevée que possible, alors que nous ne nous soucions pas trop du rappel (la proportion d’opportunités de profit que le modèle peut identifier). Intuitivement, nous savons que nous n’avons pas besoin que le modèle soit capable d’identifier toutes les opportunités de profit ; mais pour les opportunités qui sont signalées comme positives, il vaut mieux qu’elles soient vraies.

Ensuite, nous définissons un ensemble d’hyperparamètres accordables dans la configuration de la tâche de réglage. Certains de ces paramètres sont catégoriques, par exemple use_bias peut être soit vrai soit faux ; certains d’entre eux peuvent être compris dans un intervalle, par exemple le poids des exemples positifs. Le travail de réglage va essayer différentes combinaisons des hyperparamètres dans ces plages possibles.

"ParameterRanges": {
      "CategoricalParameterRanges": [
        { 
            "Name": "use_bias",
            "Values": [ "true","false" ]
        }
      ],
      "ContinuousParameterRanges": [
        {
          "MaxValue": "1",
          "MinValue": "0.0000001",
          "ScalingType":"Logarithmic",
          "Name": "l1"
        },
        {
          "MaxValue": "1",
          "MinValue": "0.00001",
          "ScalingType":"Logarithmic",
          "Name": "learning_rate"
        },
        {
          "MaxValue": "10000",
          "MinValue": "0.00001",
          "ScalingType":"Logarithmic",
          "Name": "positive_example_weight_mult"
        },
        {
          "MaxValue": "1",
          "MinValue": "0.0000001",
          "ScalingType":"Logarithmic",
          "Name": "wd"
        }
      ],
      "IntegerParameterRanges": [
        {
          "MaxValue": "1000",
          "MinValue": "100",
          "ScalingType":"Logarithmic",
          "Name": "mini_batch_size"
        }
      ]
    }

Enfin, nous définissons un objectif pour l’apprentissage. Comme expliqué précédemment, nous voulons maximiser la précision pour les besoins de la prédiction. De plus, nous voulons avoir un maximum de 10 tâches d’apprentissage, avec 2 tâches fonctionnant en parallèle à chaque étape. En théorie, nous pouvons trouver la combinaison optimale des hyperparamètres si nous exécutons les tâches d’apprentissage un nombre infini de fois. Mais évidemment, le temps et le budget seront les contraintes.

"HyperParameterTuningJobObjective": {     
      "MetricName": "validation:precision",
      "Type": "Maximize"
    },
"Strategy":"Bayesian",
"ResourceLimits": {
      "MaxNumberOfTrainingJobs": 10,
      "MaxParallelTrainingJobs": 2
    }

Pour le volume de données dont nous disposons et le type de machine que nous utilisons, chaque tâche d’apprentissage prend environ 3 minutes, y compris le temps nécessaire à l’approvisionnement des ressources. L’ensemble du processus de réglage prend donc environ 15 minutes.

Une fois le travail de réglage terminé, nous pouvons afficher les métriques de l’algorithme dans CloudWatch. Ici, chacun des points représente une tâche d’apprentissage, et l’axe Y montre la métrique objective -validation:precision. Nous pouvons constater que la précision a augmenté de façon constante au cours du réglage :

Prescision accrue

Sur le graphique, nous pouvons également voir que la 6e tâche d’apprentissage a même atteint une précision de 100 %. Bien que nous sachions par expérience que ce n’est pas nécessairement un bon signe, cela peut soit signifier qu’il y a un surajustement, soit que le rappel est très faible. Et en effet, au fur et à mesure que nous approfondissons les mesures, nous découvrons que le rappel de cette tâche n’est que de 1,7 %.

 

 

 

validation:binary_f_beta 0.033

Validation:precision  1

Validation:recall  0.017

Néanmoins, comme il s’agit du meilleur travail de réglage selon nos critères de sélection de modèles, le pipeline d’automatisation déploiera ce modèle pour la prédiction.

Utilisation des points de terminaison d’inférence

Maintenant, nous pouvons utiliser ce point de terminaison pour produire des résultats de prédiction. Pour cela, nous utilisons le SDK Python Sagemaker dans la démo. Un exemple complet peut être trouvé dans notebooks/linear_learner.ipynb dans le répertoire git.

from sagemaker.predictor import RealTimePredictor
linear_predictor=RealTimePredictor(’endpoint-name’,sagemaker_session)
linear_predictor.predict(input_data)

En réponse, le modèle Linear Learner nous donne un predicted_label et un score.

{’predictions’: [{’score’: 0.1967127025127411, ’predicted_label’: 0.0}]}

Nous pouvons évaluer le modèle en utilisant plus de données que nous avons. Voici la matrice de confusion de toutes les prédictions faites par le modèle :

Matrice de confusion

Pas impressionné ? Cependant, si nous fixons un seuil inférieur au score (de sorte que seules les prédictions les plus certaines comptent), nous pouvons réellement trouver que la prédiction est assez bonne. Voici la matrice de confusion de toutes les prédictions avec un score supérieur à 0,75. Sur les 122 prédictions les plus certaines faites par le modèle, 106 d’entre elles sont de vrais positifs. Pas mal, non ?

 

 

Matrice de confusion

Orchestration

Jusqu’à présent, nous avons parcouru l’ETL des données, la formation des modèles, le processus de réglage et de déploiement. Pour tout relier, il vaut la peine de jeter un coup d’œil à l’outil d’orchestration, Step Functions. Le service Step Functions est le principal outil d’orchestration dans AWS. Il s’intègre à une large gamme de services AWS et peut transmettre des paramètres (l’état) entre les services.

Dans notre cas, nous utilisons certains des types de tâches Step Function intégrés, tels que StartJobRun de Glue, CreateHyperParameterTuningJob de Sagemaker, etc. De cette façon, nous n’avons pas besoin d’écrire du code supplémentaire juste pour soumettre de telles tâches, à la place, nous pouvons simplement utiliser la syntaxe JSON déclarative de Step Functions pour définir le pipeline. L’exécution et la transition d’état seront gérées par le service Step Functions. Il offre également une belle présentation visuelle pour chaque exécution. Vous trouverez ci-dessous une représentation graphique d’une exécution réussie de la fonction d’étape générée par le service.

Sagemaker

Essayez vous-même

Si vous souhaitez jouer avec la démo ou l’utiliser comme base pour votre propre résolution de problèmes de ML, le code complet peut être trouvé à l’adresse suivante : https://github.com/

La démo est construite à l’aide de l’outil d’automatisation de la configuration Terraform et le processus de déploiement est entièrement automatisé. Vous pouvez donc l’essayer vous-même en suivant les instructions du README.md.

Conclusion

Dans cet article, nous avons découvert la puissance de Sagemaker pour l’apprentissage automatisé des modèles et le réglage des hyperparamètres. Nous avons également introduit quelques services pratiques sur AWS pour l’ingénierie des données, tels que Glue ETL et l’orchestration Step Functions. Grâce à ces services entièrement gérés, il est tout à fait possible, même pour une petite équipe, de réaliser des formations et des prédictions automatisées en temps quasi réel.

Cependant, il convient également de souligner ce qui ne peut pas être automatisé. Si l’on considère l’ensemble du processus, nous avons toujours besoin de connaissances adéquates en ML pour traduire un problème du monde réel en un problème de ML, qu’il s’agisse d’un problème de classification ou de régression par exemple. Nous avons encore besoin de l’expertise des scientifiques des données, en particulier lors de l’analyse exploratoire, pour déterminer quel ensemble de fonctionnalités ainsi que le modèle de base utiliser. Enfin, limité à ma propre expérience en ML, j’ai du mal à interpréter certains des résultats du réglage des hyperparamètres, ce qui offre certainement une marge d’amélioration.

Néanmoins, non seulement la démo présente la possibilité d’automatiser le processus d’apprentissage, mais l’architecture a également pris en compte le coût, la sécurité et la complexité opérationnelle de l’exécution d’un système comme celui-ci. Il devrait servir de base satisfaisante pour résoudre des problèmes de ML similaires.

Pour plus d’informations sur la façon dont notre équipe Data Insights pourrait aider votre entreprise, cliquez ici.