#Artificial Intelligence (AI)

0 Abonnés · 41 Publications

L'intelligence artificielle (IA) est la simulation des processus d'intelligence humaine par des machines, notamment des systèmes informatiques. Ces processus comprennent l'apprentissage (l'acquisition d'informations et de règles pour utiliser ces informations), le raisonnement (l'utilisation de règles pour parvenir à des conclusions approximatives ou définitives) et l'autocorrection.

En savoir plus.

Article Irène Mykhailova · Juil 14, 2023 1m read

Titre: Microsoft présente PHI-1, un modèle de génération de code plus léger et plus performant que GPT-3.5, attribuant cette performance à la puissance des données de haute qualité

Résumé: Microsoft a récemment dévoilé PHI-1, un modèle de génération de code révolutionnaire qui surpasse les performances de GPT-3.5 tout en étant plus léger. La clé de cette performance réside dans l'utilisation de données de haute qualité, qui alimentent l'algorithme avec des informations précieuses et pertinentes. Microsoft affirme que PHI-1 représente une avancée significative dans le domaine de l'intelligence artificielle, offrant des résultats impressionnants en termes de génération de code. Cette nouvelle percée promet de faciliter le développement logiciel et d'améliorer l'efficacité des tâches de programmation.

0
0 102
Article Lorenzo Scalese · Avr 21, 2023 5m read

picture

Créer un Chatbot avec IRIS et Python

Dans cet article, je vais montrer comment intégrer la base de données IRIS d'InterSystems avec Python pour servir un Modèle d'apprentissage automatique du traitement du langage naturel (NLP).

Pourquoi Python ?

Avec une large adoption et utilisation dans le monde, Python a une grande communauté et un grand nombre d'accélérateurs et de bibliothèques pour déployer n'importe quel type d'application. Vous pouvez également consulter : https://www.python.org/about/apps/ pour en savoir plus.

Globales Iris

Lorsque j'ai commencé à me familiariser avec les globales (^globals), leur utilisation m'est devenue familière en tant que moyen rapide d'ingérer des données dans un modèle de données prêt à l'emploi. Dans un premier temps, je vais donc utiliser les globales (^globals) pour stocker les données d'entraînement et les conversations pour enregistrer le comportement du chatbot.

Traitement du langage naturel

Le traitement du langage naturel ou NLP (Natural Language Processing) est un domaine de l'IA qui crée la capacité de lire et de comprendre le sens de nos langues pour les machines. Comme vous pouvez l'imaginer, ce n'est pas très simple, mais je vais vous montrer comment faire vos premiers pas dans ce vaste et beau domaine.

Démo - Essayez-le vous-même

J'ai déployé l'application Chatbot en tant que démonstration ici : http://iris-python-suite.eastus.cloudapp.azure.com:8080

Comment ça marche?

Apprentissage automatique

Il est tout d'abord bon de savoir que l'apprentissage automatique a un paradigme différent de celui du développement de logiciels courants. Le point principal qui est difficile à comprendre est le cycle de développement des modèles d'apprentissage automatique.

Alerte aux explications superficielles

Le cycle de développement d'une application standard est le suivant :

Développer le code->Tester (avec des données de développement)->Déployer (en utilisant des données réelles)

L'apprentissage automatique du code en lui-même n'a pas la même valeur. La responsabilité est partagée avec les données ! Et pas n'importe quelles données, mais de vraies données ! Car le code final à exécuter est généré par une fusion entre les concepts de développement et les données utilisées. Un cycle d'application de l'apprentissage automatique devrait donc se dérouler de la manière suivante :

Développer (Former) Modèle+Données réelles->Valider->Déployer le résultat de ceci (un Modèle)

Comment former le modèle?

Il existe de nombreuses techniques pour entraîner les modèles et chaque cas et objectif nécessite une courbe d'apprentissage importante. Dans ce cas, j'utilise la bibliothèque ChatterBot qui encapsule certaines techniques et fournit des méthodes d'entraînement et des données d'entraînement prétraitées pour nous aider à nous concentrer sur les résultats.

Langages de modèles pré-entraînés et modèles personnalisés

Vous pouvez commencer par cela pour avoir un chatbot conversationnel de base. Vous pouvez également créer toutes les données nécessaires à l'entraînement de votre chatbot, et cela peut être parfait pour vos besoins, mais terriblement difficile à réaliser en un temps limité. Dans ce projet, j'utilise en_core_web_sm comme base de conversation et je la fusionne avec des données d'entraînement personnalisées que vous pouvez créer à l'aide d'un formulaire

Architecture de base

image

Qu'ai-je utilisé en Python ?

Dans cet environnement d'application, j'utilise Python 3.7 avec les modules suivants :

  • PyYAML<=5.0.0
  • dash==1.12.0
  • dash-bootstrap-components==0.10.1
  • dash-core-components==1.10.0
  • dash-html-components==1.0.3
  • dash-renderer==1.4.1
  • dash-table==4.7.0
  • plotly==4.7.1
  • numpy==1.18.4
  • networkx==2.4
  • Flask>=1.0.0
  • chatterbot>=1.0.0
  • chatterbot-corpus>=1.2.0
  • SQLAlchemy>=1.2
  • ./nativeAPI_wheel/irisnative-1.0.0-cp34-abi3-linux_x86_64.whl

Structure de projet

Ce projet a une structure simple et facile à comprendre. Dans le dossier principal, nous avons trois sous-dossiers importants :

  • ./app: avec tout le code d'application et la configuration d'installation.
  • ./iris: avec InterSystems IRIS dockerfile préparant à servir l'application.
  • ./data: Pour relier l'hôte à l'environnement du conteneur par un volume

Structure de l'application

À l'intérieur du répertoire ./app, nous trouvons quelques fichiers :

  • chatbot.py : avec la mise en œuvre de l'application web
  • iris_python_suite.py : une classe avec quelques accélérateurs à utiliser avec IRIS Database et Python par l'API native d'IRIS.

Structure de la base de données

Cette application utilise Intersystems IRIS comme référentiel, les globales utilisées sont :

  • ^chatbot.training.data : stocke toutes les données d'entraînement personnalisées sous forme de questions et de réponses.
  • ^chatbot.conversation : stocke toutes les données de conversation.
  • ^chatbot.training.isupdated : contrôle le pipeline de formation.

Produits de mon autre solution

Je n'ai pas créé de rapport pour toutes les conversations mais ce n'est pas un problème, grâce à mon visualiseur de graphes globaux je peux suivre les conversations. image

Exécution de l'application par vous-même

Conditions préalables

  • git
  • docker et docker-compose (et plus de paramètres de mémoire dans docker au moins 4 Go)
  • accès à un terminal dans votre environnement

Étapes

Avec docker-compose, vous pouvez facilement mettre en place un environnement avec toutes les pièces et configurations. Allez dans le dossier iris-python-covid19 et tapez ce texte :

$ docker compose build
$ docker compose up

Durée estimée de mise en place des conteneurs

La première exécution dépendra de votre lien internet pour télécharger les images et les dépendances. Si la durée est supérieure à 15 minutes, il est probable que quelque chose ne fonctionne pas, n'hésitez pas à nous en faire part ici. Après la première exécution, les exécutions suivantes seront plus performantes et prendront moins de 2 minutes.

Si tout est correct

Après un certain temps, vous pouvez ouvrir votre navigateur et aller à l'adresse :

La forme des données d'apprentissage

http://localhost:8050/chatbot-training-data

Le chatbot

http://localhost:8080

Vous devriez consulter le portail d'administration d'IRIS

Pour le moment, j'utilise l'espace de noms USER.

http://localhost:9092
user: _SYSTEM
pass: theansweris42

Si cet article vous est utile ou si vous en aimez le contenu, votez :

Cette application est au concours actuel sur open exchange, vous pouvez voter pour mon application iris-python-suite ici (https://openexchange.intersystems.com/contest/current)

0
0 330
Article Irène Mykhailova · Avr 14, 2023 7m read

This is the third post of a series explaining how to create an end-to-end Machine Learning system.Cet article est le troisième article d'une série expliquant comment créer un système d'apprentissage automatique de bout en bout.

Formation d'un modèle d'apprentissage automatique

Lorsque vous travaillez avec l'apprentissage automatique, il est fréquent d'entendre ce terme : formation. Que signifie la formation dans un pipeline ML ? La formation peut désigner l'ensemble du processus de développement d'un modèle d'apprentissage automatique OU le point spécifique du processus de développement qui utilise les données de formation et aboutit à un modèle d'apprentissage automatique.

imageSource

Les modèles d'apprentissage automatique ne sont donc pas équivalents aux applications communes ?

Le dernier point ressemble à une application normale. Mais le concept est très différent, car dans une application courante, nous n'utilisons pas les données de la même manière. Tout d'abord, pour créer des modèles de ML, vous aurez besoin de données réelles (de production) dans tout le processus de développement. Une autre différence est que si vous utilisez des données différentes, vous aurez un modèle différent... toujours...

Pouvez-vous donner quelques exemples ?

Bien sûr ! Imaginez que vous êtes un développeur de systèmes et que vous créez un système qui contrôle les services dans un PetShop. La façon la plus simple de ce type de système est de créer une base de données pour stocker les données et de créer une application pour interagir avec l'utilisateur. Lorsque vous développez, vous n'avez pas besoin de données réelles. Vous pouvez créer tout le système avec de fausses données. C'est impossible avec les modèles d'apprentissage automatique Ils ont besoin de données réelles au début du développement et elles seront utilisées jusqu'à la fin du développement.
Lorsque vous créez un modèle d'apprentissage automatique, vous fournissez des données à un algorithme et l'algorithme produit une application adaptée à ces données. Si vous utilisez de fausses données, vous obtiendrez un faux modèle.

Qu'en est-il de l'initiative d'organisation de la communauté avec le ML ?

Revenons au sujet principal. Avec tous les articles que je possède, j'ai commencé à explorer un échantillon et j'ai trouvé le suivant :

  1. La plupart des articles n'ont pas été balisés.
  2. Certains articles étaient mal balisés
  3. Certains articles (de l'échantillon) avec des balises étaient balisés correctement.

Comment utiliser ces données ?

J'ai décidé de créer un sac de mots (BoW) à partir des données et d'utiliser les algorithmes de classification les plus courants.
Comment puis-je caractériser ces données ? Ma brève tentative ici :

1ère tentative - Formation avec uniquement des données de publication

Prenez toutes les données avec les balises, séparez 80 % pour la formation et 20 % pour la validation du modèle. Le modèle obtenu n'est pas très performant. La plupart du temps, il prédisait que tous les textes étaient à propos de Caché... (le BoW comportait environ 15000 caractéristiques).

2ème tentative - Formation avec les données de publication uniquement, en supprimant les mots vides.

La plupart des messages contiennent les mêmes mots : hi, for, to, why, in, on, the, do, don't... Le modèle a probablement pris une mauvaise direction pour prédire les balises. J'ai donc supprimé tous les mots vides et vectorisé les données, ce qui a permis d'obtenir environ 9000 caractéristiques. Mais le modèle n'est toujours pas performant.

image

3ème tentative - Entraînement à la description des balises

En regardant le tableau des balises, je vois une courte description de chaque balise. J'ai donc donné la chance à ces petites phrases d'être mon guide sur la bonne façon de baliser comme dans la vie réelle. J'ai obtenu environ 1500 caractéristiques et en les utilisant, le modèle commence à être suffisamment performant pour être montré à d'autres personnes =)

4ème tentative - Entraînement avec description des balises

Après toutes ces recherches, j'ai décidé de tester si IntegratedML pouvait être plus performant que mon modèle. J'ai donc converti le dernier sac de mots en tableau, mais j'ai été confronté à un problème : un sac de mots avec 1500 caractéristiques signifie que j'ai besoin d'un tableau avec 1500 colonnes.
Et en lisant la documentation d'IRIS, la limite de colonnes était de 1000. J'ai donc modifié mon vectoriseur pour n'utiliser que 900 caractéristiques. C'est moins, mais c'est la seule solution que j'ai trouvée.

Les algorithmes de classification

J'ai essayé 3 algorithmes avec des paramètres différents :

  1. SVM
  2. Forêt aléatoire
  3. Régression logistique

La meilleure performance (du moins ces derniers jours) a été la régression logistique dans une stratégie Un contre le Reste (One vs Rest).
One vs Rest considère que vous avez 1 classe à prédire contre plus ou moins 1 classe restante.

Article suivant : Application de bout en bout

J'espère que vous appréciez. Si vous aimez le texte et mon application, votez sur https://openexchange.intersystems.com/contest/current dans mon application iris-ml-suite

Training a Machine Learning Model

When you work with machine learning is common to hear this work: training. Do you what training mean in a ML Pipeline? Training could mean all the development process of a machine learning model OR the specific point in all development process that uses training data and results in a machine learning model.

pictureSource

So Machine Learning Models are not equal Common Applications?

In the very last point it looks like a normal application. But the concept is pretty different, because in a common application we don't use data in the same way. First of all, to create ML Models you will need real (production) data at all development process another difference is if you use different data you will have a different model..always...

Can you give some examples?

Sure! Imagine you are a system developer and create a system that controls services in a PetShop. The most simple way to do this kind of system is create a DataBase do store data and create an application to interact with the user. When you start develop it you don't need real data. You can create all system with fake data. This is impossible with machine learning models they need real data at the starting point of development and it will be used until the last point of development. When you create a machine learning model you provide data to an algorithm and the algorithm results in an application fitted to those data, so if you use fake data, you will have a fake model.

What about Organize the Community with ML?

Getting back to the main subject. With all posts that I have I started exploring a sample and realize:

  1. Most post were without any tag
  2. Some posts were with wrong tags
  3. Some posts (from sample) with tags were right tagged

How use this data?

I take the option of create a BoW (Bag of Words) of the data and use the most popular classification algorithms with. How do I featurize those data? My brief of attempts here:

1st Attempt - Training with only post data

Take all the data with tags, separate 80% for training and 20% to validate the model. The resulting model didn't perform well. Most of time it was predicting all text were about Caché... (the BoW was with aroun 15000 features)

2nd Attempt - Training with only post data removing stop words

Thinking of most posts has the same words like: hi, for, to, why, in, on, the, do, don't... the model probably was taking the wrong way to predict the tags. So I removed all stop words and vectorized the data, resulting in around 9000 features. But the model continues to not perform well.

picture

3rd Attempt - Training with Tags Description

Looking at tags table, I see a short description of each tag. So I give the chance to that small phrases be my guide to the right way to tagging like in real life. It resulted in about 1500 features and using it the model starts performing well enough to show to other people =)

4th Attempt - Training with Tags Description

After all this quest I decide to test if IntegratedML could perform better than my model. So I converted the last Bag of Words into a Table but I faced a problem: a bag of words with 1500 features means that I need a table with 1500 columns. And reading the IRIS docs the limit of columns was 1000. So I changed my vectorizer to use only 900 features. It would less but was the only way that I could think.

Classification Algorithms

I tried 3 algorithms with different params:

  1. SVM
  2. Random Forest
  3. Logistic Regression

The best performer (at least in last days) was Logistic Regression in a strategy One vs Rest. One vs Rest consider that you have 1 class to predict versus a more than 1 other classes.

Next article: End-to-End Application

I hope you are enjoying. If you like the text and my application, please vote on https://openexchange.intersystems.com/contest/current in my application iris-ml-suite

0
0 50
Article Irène Mykhailova · Avr 10, 2023 6m read

Voici mon introduction à une série d'articles expliquant comment créer un système d'apprentissage automatique de bout en bout.

Un seul problème pour commencer

Notre communauté de développement d'IRIS a plusieurs messages sans balise ou mal balisés. Au fur et à mesure que le nombre de messages augmente, l'organisation de chaque balise et l'expérience d'un membre de la communauté qui parcourt les sujets tendent à diminuer.

Les premières solutions envisagées

Nous pouvons envisager quelques solutions habituelles pour ce scénario, comme par exemple :

  • Prendre un volontaire pour lire tous les messages et corriger les erreurs.
  • Payer un entrepreneur pour corriger toutes les erreurs.
  • Envoyez un courriel à chaque auteur de message pour qu'il revoie les textes du passé.

Ma solution

image

Et si nous pouvions apprendre à une machine à faire ce travail ?

image Nous avons beaucoup d'exemples de dessins animés, d'anime ou de films pour nous rappeler ce qui peut se passer lorsqu'on enseigne à une machine...

Apprentissage automatique

L'apprentissage automatique est un sujet très vaste et je vais faire de mon mieux pour expliquer ma vision du sujet. Revenons au problème que nous devons encore résoudre : Si l'on examine les solutions habituelles, elles prennent toutes en compte l'interprétation d'un texte. Comment apprendre à une machine à lire un texte, à comprendre la corrélation entre un texte et une balise ? Tout d'abord, nous devons explorer les données et en tirer des conclusions.

Classification ? Régression ?

Lorsque vous commencez à étudier l'apprentissage automatique, les deux termes ci-dessus sont toujours utilisés. Mais comment savoir ce qu'il faut approfondir ? -Classification : Un algorithme d'apprentissage automatique de classification prédit des valeurs discrètes.
-Régression : Un algorithme d'apprentissage automatique de régression prédit des valeurs continues. Si l'on considère notre problème, nous devons prédire des valeurs discrètes (toutes les baises existent).

C'est une question de données !

Toutes les données relatives aux articles ont été fournies ici.

Article

SELECT
 id, Name, Tags, Text
FROM Community.Post
Where  
not text is null              
order by id
idNomBalisesTexte
1946Introduction aux services webWeb Development,Web ServicesCette vidéo est une introduction aux services web. Elle explique ce que sont les services web, leur utilisation et comment les administrer. Les services web sont également connus sous le nom de "SOAP". Cette session comprend des informations sur la sécurité et la politique de sécurité.
1951Les outils pour CachéCachéCette astuce technique (Tech Tip) passe en revue les différents outils disponibles à partir du Caché dans la barre d'état système de Windows. Vous verrez comment accéder à Studio IDE, au terminal, au portail de gestion du système, à SQL, aux globales, à la documentation, à la référence de classe et à l'accès au système à distance.
1956Démarrage avec CachéCachéDémarrage avec Caché présentera Caché et son architecture. Nous examinerons également les outils de développement, la documentation et les exemples disponibles.

Balises

IDDescription
.NETNET Framework (prononcé dot net) est un cadre logiciel développé par Microsoft qui fonctionne principalement sur Microsoft Windows. Site officiel. Support .NET dans InterSystems Data Platform.
.NET ExperienceInterSystems .NET Experience révèle les possibilités d'interopérabilité entre .NET et InterSystems IRIS Data Platform. Pour plus de détails, cliquez ici. Site officiel de .NET
IAL'intelligence artificielle (IA) est la simulation des processus de l'intelligence humaine par des machines, en particulier par des systèmes informatiques. Ces processus comprennent l'apprentissage (l'acquisition d'informations et de règles d'utilisation de ces informations), le raisonnement (l'utilisation de règles pour parvenir à des conclusions approximatives ou définitives) et l'autocorrection. Apprenez-en plus.
APIL'interface de programmation d'applications (API) est un ensemble de définitions de sous-programmes, de protocoles et d'outils permettant de créer des logiciels d'application. En termes généraux, il s'agit d'un ensemble de méthodes de communication clairement définies entre divers composants logiciels. Apprenez-en plus.

Nous savons maintenant à quoi ressemblent les données. Mais il ne suffit pas de connaître la conception des données pour créer un modèle d'apprentissage automatique.

Qu'est-ce qu'un modèle d'apprentissage automatique ?

Un modèle d'apprentissage automatique est une combinaison d'un algorithme d'apprentissage automatique et de données. Après avoir combiné une technique avec des données un modèle peut commencer à prédire.

Exactitude

Si vous pensez que les modèles ML ne font jamais d'erreurs, vous devriez mieux comprendre la précision du modèle. En quelques mots, la précision correspond aux performances du modèle en matière de prédiction. En général, la précision est exprimée en pourcentage, sous forme de chiffres. Ainsi, quelqu'un dira : "J'ai créé un modèle dont la précision est de 70 %". Cela signifie que pour 70 % des prédictions, le modèle prédit correctement. Les 30 % restants seront des prédictions erronées.

NLP - Traitement du langage naturel

Le NLP est un domaine de l'apprentissage automatique qui travaille sur la capacité d'un ordinateur à comprendre et à analyser le langage humain. Et oui, notre problème peut être résolu grâce au NLP.

Utilisation d'algorithmes d'apprentissage automatique

La plupart des algorithmes d'apprentissage automatique ont une chose en commun : ils utilisent en entrée des NOMBRES. Oui, je sais... c'est le point le plus difficile à comprendre pour créer des modèles d'apprentissage automatique.

Si tous les messages et les balises sont du texte, comment le modèle peut-il fonctionner ?

Une bonne partie du travail dans une solution de ML consiste à transformer les données en quelque chose qui peut être utilisé dans un algorithme. Ce travail est appelé "ingénierie des fonctionnalités" (Feature Engineering). Dans ce cas, c'est plus compliqué car les données ne sont pas structurées. Mais voici une brève explication*: J'ai transformé chaque mot du texte en un identifiant unique représenté par un nombre. SKLearn et d'autres librairies python devraient vous aider
de le faire facilement.

Démonstration

J'ai déployé le modèle formé en tant que démonstration ici : http://iris-ml-suite.eastus.cloudapp.azure.com/

Quelle est la suite ?

Dans mon prochain article, je montrerai le code et les moyens de faire toute la modélisation. A ne pas manquer !

Si cet article vous a aidé ou si vous avez aimé son contenu, votez :

Cette application est au concours actuel sur l'échange ouvert, vous pouvez voter ici: https://openexchange.intersystems.com/contest/current ou dans mon application iris-ml-suite

0
0 65
Article Guillaume Rongier · Avr 7, 2023 9m read

Suite à la partie précédente, il est temps de tirer parti de l'instruction de VALIDATION DU MODÈLE IntegratedML, qui fournit des informations permettant de surveiller vos modèles ML. Vous pouvez la voir en action ici

Le code présenté ici est dérivé d'exemples fournis par le modèle InterSystems IntegratedML ou la documentation IRIS, documentation

Remarque: Le code présenté ici n'a qu'une valeur explicative. Si vous souhaitez l'essayer, j'ai développé une application modèle - iris-integratedml-monitor-example, qui participe au concours IA d'InterSystems IRIS (InterSystems IRIS AI Contest). S'il vous plaît, après avoir lu cet article, vous pouvez le consulter et, si vous l'aimez, votez pour moi! :)

Contenu

Partie I:

Partie II:

Surveillance des performances du ML

Pour surveiller votre modèle ML, vous aurez besoin d'au moins deux fonctions :

  1. Fournisseur de mesures de performance
  2. Service de surveillance et de notification

Heureusement, IRIS nous fournit ces deux caractéristiques nécessaires.

Obtenir des mesures de performance des modèles ML

Comme nous l'avons vu dans la partie précédente, IntegratedML fournit l'instruction VALIDER LE MODÈLE pour calculer les paramètres de performance suivants :

  • Exactitude : la qualité de votre modèle (des valeurs proches de 1 signifient des taux élevés de réponses correctes).
  • Précision : dans quelle mesure votre modèle traite les faux positifs (des valeurs proches de 1 signifient un taux élevé de non faux positifs).
  • Rappel : dans quelle mesure votre modèle traite les faux négatifs (des valeurs proches de 1 signifient un taux élevé de non faux négatifs).
  • Mesure F : une autre façon de mesurer la précision, utilisée lorsque la précision n'est pas satisfaisante (des valeurs proches de 1 signifient un taux élevé de réponses correctes).

Remarque: ces définitions ne sont pas formelles, elles sont même assez superficielles ! Je vous encourage à prendre le temps de les interpréter.

Ce qui est intéressant, c'est qu'à chaque fois que vous appelez VALIDER LE MODÈLE (VALIDATE MODEL), IntegrateML enregistre sa mesure de performance, et nous pouvons tirer parti de cette fonctionnalité pour la surveiller.

Moteur de surveillance

InterSystems IRIS fournit le framework du Moniteur de Système pour traiter les tâches de surveillance. Il vous permet également de définir des règles personnalisées afin de déclencher des notifications basées sur des prédicats appliqués à ces mesures.

Par défaut, un ensemble de mesures est fourni pour le disque, la mémoire, les processus, le réseau, etc. En outre, le Moniteur de Système vous permet également d'étendre les moniteurs pour couvrir une infinité de possibilités. De tels moniteurs personnalisés sont appelés une application de moniteur (Application Monitor) dans la terminologie de moniteur de système (System Monitor).

Vous pouvez obtenir plus d'informations sur le Moniteur de Système ici.

La mise en place de l'ensemble

Jusqu'à présent, nous avons un moyen d'obtenir les valeurs des métriques de performance de chaque validation du modèle et, un outil qui pourrait déclencher des alertes basées sur des règles personnalisées appliquées à des sources de métriques personnalisées... Bien, il est temps de les combiner.

Tout d'abord, nous devons créer une classe de moniteur d'application personnalisée, en étendant la classe %Monitor.Abstract et en implémentant les méthodes Initialize et GetSample.

Class MyMetric.IntegratedMLModelsValidation Extends %Monitor.Adaptor
{

/// Initialiser la liste des métriques de validation des modèles.
Method Initialize() As %Status
{
    Return $$$OK
}

/// Obtenir un échantillon métrique de routine.
/// Un code de retour de $$$OK indique qu'il y a une nouvelle instance d'échantillon.
/// Tout autre code de retour indique qu'il n'y a pas d'échantillon.
Method GetSample() As %Status
{
    Return $$$OK
}

}

Les moniteurs système émettent des appels réguliers aux classes de moniteurs afin d'obtenir un ensemble de mesures appelées échantillons. Ces échantillons peuvent être simplement surveillés ou utilisés pour vérifier si des règles d'alerte doivent être levées. Vous définissez la structure de ces échantillons en définissant des propriétés standard non internes dans la classe monitior. Il est important de souligner ici que vous devez spécifier, dans le paramètre INDEX, l'une de ces propriétés comme clé primaire de chaque échantillon - sinon une erreur de clé dupliquée sera générée.

Class MyMetric.IntegratedMLModelsValidation1 Extends %Monitor.Adaptor
{

Parameter INDEX = "ModelTrainedName";

/// Nom de la définition du modèle
Property ModelName As %Monitor.String;

/// Nom du modèle formé en cours de validation
Property ModelTrainedName As %Monitor.String;

/// Erreur de validation (le cas échéant)
Property StatusCode As %Monitor.String;

/// Précision
Property ModelMetricPrecision As %Monitor.Numeric;

/// Rappel
Property ModelMetricRecall As %Monitor.Numeric;

/// Mesure F
Property ModelMetricFMeasure As %Monitor.Numeric;

/// Exactitude
Property ModelMetricAccuracy As %Monitor.Numeric;

...

}

La méthode Initialize est appelée une fois pour chaque appel de moniteur et la méthode GetSample est appelée jusqu'à ce qu'elle renvoie 0.

Ainsi, nous pourrions mettre en place un SQL sur l'historique de validation d'IntegrateML pour fournir des informations de métriques au moniteur, en implémentant les méthodes Initialize et GetSample :

/// Initialiser la liste des métriques de validation des modèles.
Method Initialize() As %Status
{
	// Obtenir la dernière validation pour chaque modèle validé par l'instruction VALIDATION DU MODÈLE
	Set sql =
	"SELECT MODEL_NAME, TRAINED_MODEL_NAME, STATUS_CODE, %DLIST(pair) AS METRICS_LIST FROM ("_
		"SELECT m.*, $LISTBUILD(m.METRIC_NAME, m.METRIC_VALUE) pair, r.STATUS_CODE "_
		"FROM INFORMATION_SCHEMA.ML_VALIDATION_RUNS r "_
		"JOIN INFORMATION_SCHEMA.ML_VALIDATION_METRICS m "_
		"ON m.MODEL_NAME = r.MODEL_NAME "_
			"AND m.TRAINED_MODEL_NAME = r.TRAINED_MODEL_NAME "_
			"AND m.VALIDATION_RUN_NAME = r.VALIDATION_RUN_NAME "_
		"GROUP BY m.MODEL_NAME, m.METRIC_NAME "_
		"HAVING r.COMPLETED_TIMESTAMP = MAX(r.COMPLETED_TIMESTAMP)"_
	") "_
	"GROUP BY MODEL_NAME"
    Set stmt = ##class(%SQL.Statement).%New()
    $$$THROWONERROR(status, stmt.%Prepare(sql))
    Set ..Rspec = stmt.%Execute()
    Return $$$OK
}

/// Obtenir un échantillon métrique de routine.
/// Un code de retour de $$$OK indique qu'il y a une nouvelle instance d'échantillon.
/// Tout autre code de retour indique qu'il n'y a pas d'échantillon.
Method GetSample() As %Status
{
    Set stat = ..Rspec.%Next(.sc)
    $$$THROWONERROR(sc, sc)

    // Quitter si nous avons fait tous les jeux de données
    If 'stat {
        Quit 0
    }

    // remplir cette instance
    Set ..ModelName = ..Rspec.%Get("MODEL_NAME")
    Set ..ModelTrainedName = ..Rspec.%Get("TRAINED_MODEL_NAME")_" ["_$zdt($zts,3)_"]"
    Set ..StatusCode = ..Rspec.%Get("STATUS_CODE")
    Set metricsList = ..Rspec.%Get("METRICS_LIST")
    Set len = $LL(metricsList)
    For iMetric = 1:1:len {
	    Set metric = $LG(metricsList, iMetric)
	    Set metricName = $LG(metric, 1)
	    Set metricValue = $LG(metric, 2)
	    Set:(metricName = "PRECISION") ..ModelMetricPrecision = metricValue
	    Set:(metricName = "RECALL") ..ModelMetricRecall = metricValue
	    Set:(metricName = "F-MEASURE") ..ModelMetricFMeasure = metricValue
	    Set:(metricName = "ACCURACY") ..ModelMetricAccuracy = metricValue
    }

    // quitter avec une valeur de retour indiquant que les données de l'échantillon sont prêtes
    Return $$$OK
}

Après avoir compilé la classe de moniteur, vous devez redémarrer le moniteur de système System Monitor afin que le système comprenne qu'un nouveau moniteur a été créé et qu'il est prêt à être utilisé. Pour ce faire, vous pouvez utiliser la routine ^%SYSMONMGR ou la classe %SYS.Monitor.

Un cas d'utilisation simple

Jusqu'à présent, nous disposons des outils nécessaires pour collecter, surveiller et émettre des alertes sur les mesures de performance du ML. Il est maintenant temps de définir une règle d'alerte personnalisée et de simuler un scénario dans lequel un modèle ML déployé commence à affecter négativement vos performances.

Tout d'abord, nous devons configurer une alerte par courriel et sa règle de déclenchement. Cela peut être fait à l'aide de la routine ^%SYSMONMGR. Cependant, afin de rendre les choses plus faciles, j'ai créé une méthode d'installation qui définit toute la configuration de l'e-mail et de la règle d'alerte. Vous devez remplacer les valeurs entre <&gt ; par les paramètres de votre serveur de messagerie et de votre compte.

ClassMethod NotificationSetup()
{
	// Régler les paramètres de l'e-mail
	Set sender = "<your e-mail address>"
	Set password = "<your e-mail password>"
	Set server = "<SMTP server>"
	Set port = "<SMTP server port>"
	Set sslConfig = "default"
	Set useTLS = 1
	Set recipients = $LB("<comma-separated receivers for alerts>")
	Do ##class(%Monitor.Manager).AppEmailSender(sender)
	Do ##class(%Monitor.Manager).AppSmtpServer(server, port, sslConfig, useTLS)
	Do ##class(%Monitor.Manager).AppSmtpUserName(sender)
	Do ##class(%Monitor.Manager).AppSmtpPassword(password)
	Do ##class(%Monitor.Manager).AppRecipients(recipients)

	// La messagerie électronique comme méthode de notification par défaut
	Do ##class(%Monitor.Manager).AppNotify(1)

	// Activer les notifications par messagerie électronique
	Do ##class(%Monitor.Manager).AppEnableEmail(1)

	Set name  = "perf-model-appointments-prediction"
	Set appname = $namespace
	Set action = 1
	Set nmethod = ""
	Set nclass = ""
	Set mclass = "MyMetric.IntegratedMLModelsValidation"
	Set prop = "ModelMetricAccuracy"
	Set expr = "%1 < .8"
	Set once = 0
	Set evalmethod = ""
	// Créer une alerte
	Set st = ##class(%Monitor.Alert).Create(name, appname, action, nmethod, nclass, mclass, prop, expr, once, evalmethod)
	$$$THROWONERROR(st, st)

	// Relancer le moniteur
	Do ##class(MyMetric.Install).RestartMonitor()
}

Dans la méthode précédente, une alerte sera émise si le moniteur obtient des valeurs de précision inférieures à 90 %.

Maintenant que notre règle d'alerte est configurée, créons, formons et validons un modèle de prédiction show/no-show avec les 500 premiers enregistrements et validons-le avec les 600 premiers enregistrements.

Remarque : Le paramètre seed sert uniquement à garantir la reproductibilité (c.-à-d. pas de valeurs aléatoires) et doit normalement être évité en production.

-- Création du modèle
CREATE MODEL AppointmentsPredection PREDICTING (Show) FROM MedicalAppointments USING {\"seed\": 3}
-- Formation à l'aide des 500 premiers enregistrements du jeu de données
TRAIN MODEL AppointmentsPredection FROM MedicalAppointments WHERE ID <= 500 USING {\"seed\": 3}
-- Affichage des informations sur le modèle
SELECT * FROM INFORMATION_SCHEMA.ML_TRAINED_MODELS
|   | NOM_DU_MODÈLE             | NOM_DU_MODÈLE_FORMÉ      | FOURNISSEUR | HORODATAGE_FORMÉ       | TYPE_DU_MODÈLE     | INFOS_MODÈLE                                        |
|---|------------------------|-------------------------|----------|-------------------------|----------------|---------------------------------------------------|
| 0 | AppointmentsPredection | AppointmentsPredection2 | AutoML   | 2020-07-12 04:46:00.615 | classification | ModelType:Logistic Regression, Package:sklearn... |

Notez que IntegrateML, en utilisant AutoML comme fournisseur (colonne FOURNISSEUR), déduit du jeu de données fourni, un modèle de classification (colonne TYPE_DU_MODÈLE), avec l'algorithme de régression logistique, à partir de la bibliothèque scikit-learn (colonne INFOS_MODÈLE). Il est important de souligner ici la règle "Garbage In, Garbage Out" ("à données inexactes, résultats erronés") - c'est-à-dire que la qualité du modèle est directement liée à la qualité des données.

Poursuivons maintenant avec la validation du modèle.

-- CCalculer les performances du modèle en utilisant les 600 premiers enregistrements (500 de l'ensemble formé + 100 pour le test).
VALIDATE MODEL AppointmentsPredection FROM MedicalAppointments WHERE ID < 600 USING {\"seed\": 3}
-- Afficher les mesures de validation
SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS WHERE MODEL_NAME = '%s'
| NOM_MÉTRIQUE              | Exactitude | Mesure F | Précision | Rappel |
|--------------------------|----------|-------------|-----------|--------|
| AppointmentsPredection21 | 0.9      | 0.94        | 0.98      | 0.91   |

Le modèle peut être utilisé pour effectuer des prédictions à l'aide de l'instruction PREDICT :

SELECT PREDICT(AppointmentsPredection) As Predicted, Show FROM MedicalAppointments  WHERE ID <= 500
|     | Prédit    | Affiché|
|-----|-----------|-------|
| 0   | 0         | Faux |
| 1   | 0         | Faux |
| 2   | 0         | Faux |
| 3   | 0         | Faux |
| 4   | 0         | Faux |
| ... | ...       | ...   |
| 495 | 1         | Vrai  |
| 496 | 0         | Vrai  |
| 497 | 1         | Vrai  |
| 498 | 1         | Vrai  |
| 499 | 1         | Vrai  |

Ensuite, simulons l'ajout de 200 nouveaux enregistrements (pour un total de 800 enregistrements) au modèle de manière à ce que sa précision soit ramenée à 87 %.

-- Calculer les performances du modèle en utilisant les 800 premiers enregistrements.
VALIDATE MODEL AppointmentsPredection FROM MedicalAppointments WHERE ID < **800** USING {\"seed\": 3}
-- Afficher les mesures de validation
SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS WHERE MODEL_NAME = '%s'
| NOM_MÉTRIQUE              | Exactitude | Mesure F | Précision | Rappel |
|--------------------------|----------|-----------|-----------|--------|
| AppointmentsPredection21 | 0.9      | 0.94      | 0.98      | 0.91   |
| AppointmentsPredection22 | 0.87     | 0.93      | 0.98      | 0.88   |

Comme nous avons mis en place une règle pour envoyer une notification par messagerie électronique si la précision est inférieure à 90%, le moniteur de système System Monitor comprend qu'il est temps de déclencher une telle alerte vers le(s) compte(s) de messagerie électronique concerné(s).

Dans le corps du message, vous pouvez trouver des informations sur l'alerte, telles que son nom, le moniteur d'application et ses valeurs métriques qui ont déclenché l'alerte.

Ainsi, une telle situation sera notifiée aux personnes qui pourront prendre des mesures pour y remédier. Par exemple, une action pourrait consister simplement à réentraîner le modèle, mais dans certains cas, une approche plus élaborée peut s'avérer nécessaire.

Il est certainement possible d'approfondir les mesures de surveillance et de créer de meilleures alertes. Par exemple, imaginez que vous ayez plusieurs modèles ML en cours d'exécution et que différentes personnes soient responsables de chacun d'entre eux. Vous pourriez utiliser la métrique du nom du modèle et définir des règles d'alerte spécifiques, pour des destinataires d'e-mails spécifiques.

Le moniteur System Monitor vous permet également de déclencher une ClassMethod au lieu d'envoyer un courriel. Ainsi, vous pouvez exécuter une logique complexe lorsqu'une alerte est déclenchée, comme entraîner automatiquement le modèle, par exemple.

Notez que, comme System Monitor exécutera régulièrement les méthodes "Initialize" et "GetSample", ces méthodes doivent être soigneusement conçues afin de ne pas demander trop de ressources au système.

Travaux futurs

Comme le souligne Benjamin De BoeIRIS introduit une nouvelle façon de personnaliser votre tâche de surveillance - l' outil SAM. Ma première impression a été très positive, SAM est intégré avec les technologies de surveillance des standards du marché comme Grafana et Prometheus. Alors, pourquoi ne pas aller de l'avant et tester comment améliorer ce travail avec de telles nouvelles fonctionnalités ? Mais il s'agit là d'une matière pour un futur travail.... :)

Voilà, c'est fait ! J'espère que cela pourra vous être utile d'une manière ou d'une autre. A bientôt !

0
0 60
Article Guillaume Rongier · Avr 5, 2023 6m read

Il y a quelques mois, j'ai lu cet article intéressant de la MIT Technology Review, qui explique comment la pandémie de COVID-19 pose des défis aux équipes informatiques du monde entier en ce qui concerne leurs systèmes d'apprentissage automatique (ML).

Cet article m'a incité à réfléchir à la manière de traiter les problèmes de performance après le déploiement d'un modèle de ML.

J'ai simulé un simple scénario de problème de performance dans une application modèle de la technologie Open Exchange - iris-integratedml-monitor-example, qui participe au concours IA d'InterSystems IRIS (InterSystems IRIS AI Contest). S'il vous plaît, après avoir lu cet article, vous pouvez le consulter et, si vous l'aimez, votez pour moi! :)

Contenu

Partie I:

Partie II:

Les systèmes IRIS IntegratedML et ML

Avant de parler de COVID-19 et de son impact sur les systèmes ML dans le monde entier, parlons rapidement d'InterSystems IRIS IntegratedML.

En automatisant des tâches telles que la sélection des caractéristiques et en s'intégrant au langage de manipulation de données SQL standard, IntegratedML pourrait nous aider à développer et à déployer une solution de ML.

Par exemple, après avoir manipulé et analysé correctement des données provenant de rendez-vous médicaux, vous pouvez configurer un modèle de ML pour prédire la présence ou l'absence des patients à l'aide de ces instructions SQL :

CREATE MODEL AppointmentsPredection PREDICTING (Show) FROM MedicalAppointments
TRAIN MODEL AppointmentsPredection FROM MedicalAppointments
VALIDATE MODEL AppointmentsPredection FROM MedicalAppointments

Le fournisseur AutoML choisira l'ensemble de caractéristiques et l'algorithme ML le plus performant. Dans ce cas, le fournisseur AutoML a sélectionné le modèle de régression logistique utilisant la bibliothèque scikit-learn, obtenant ainsi une exactitude de 90 %.

|   | NOM_DU_MODÈLE             | NOM_DU_MODÈLE_FORMÉ      | FOURNISSEUR | HORODATAGE_FORMÉ       | TYPE_DU_MODÈLE     | INFOS_MODÈLE                                        |
|---|------------------------|-------------------------|----------|-------------------------|----------------|---------------------------------------------------|
| 0 | AppointmentsPredection | AppointmentsPredection2 | AutoML   | 2020-07-12 04:46:00.615 | classification | ModelType:Logistic Regression, Package:sklearn... |
| NOM_MÉTRIQUE              | Exactitude | Mesure F | Précision | Rappel |
|--------------------------|----------|-----------|-----------|--------|
| AppointmentsPredection21 | 0.9      | 0.94      | 0.98      | 0.91   |

Une fois que votre modèle de ML est déjà intégré à SQL, vous pouvez l'intégrer de manière transparente à votre système de réservation existant afin d'améliorer ses performances, en utilisant des estimations sur les patients qui seront présents et ceux qui ne le seront pas :

SELECT PREDICT(AppointmentsPredection) As Predicted FROM MedicalAppointments WHERE ID = ?

Vous pouvez en savoir plus sur IntegrateML ici. Si vous souhaitez obtenir un peu plus de détails sur ce modèle de prédiction simple, vous pouvez vous référer à.

Toutefois, comme les modèles d'IA/ML sont conçus pour s'adapter au comportement de la société, directement ou non, ils seront probablement très affectés lorsque ce comportement changera rapidement. Récemment, nous avons (malheureusement) pu expérimenter un tel scénario en raison de la pandémie de COVID-19.

Entre les anciennes et les nouvelles normalités

Comme l'explique l'article de MIT Technology Review, la pandémie de COVID-19 a modifié remarquablement et rapidement le comportement de la société. J'ai effectué des recherches dans Google Trends pour des termes cités dans l'article, tels que masque N95, papier toilette et désinfectant pour les mains, afin de confirmer l'augmentation de leur popularité, à mesure que la pandémie se propageait dans le monde :

Tel que cité dans l'article :

"Mais ils [les changements apportés par COVID-19] ont également affecté l'intelligence artificielle, causant des problèmes aux algorithmes qui fonctionnent dans les coulisses de la gestion des stocks, de la détection des fraudes, du marketing, et bien d'autres choses encore. Les modèles d'apprentissage automatique formés sur la base du comportement humain normal découvrent aujourd'hui que la normalité elle-même a changé, et certains d'entre eux ne fonctionnent plus comme ils le devraient."

En d'autres termes, entre l'"ancienne normalité" et la "nouvelle normalité", nous vivons une "nouvelle anormalité".
Une autre citation intéressante, également tirée de l'article :

"Les modèles d'apprentissage automatique sont conçus pour s'adapter aux changements. Mais la plupart d'entre eux sont également fragiles ; ils donnent de mauvais résultats lorsque les données d'entrée diffèrent trop de celles sur lesquelles ils ont été formés. (...) L'IA est un moteur vivant, qui respire."

Cet article présente ensuite des exemples de modèles d'IA/ML dont les performances commencent soudainement à être affectées négativement, ou qui doivent être modifiés de toute urgence. Quelques exemples :

  • Les entreprises de vente au détail qui se sont retrouvées en rupture de stock après avoir passé des commandes en masse pour des produits inadaptés ;
  • Des conseils biaisés de la part de services de recommandation d'investissements basés sur l'analyse du sentiment des messages médiatiques, en raison de leur contenu pessimiste ;
  • Générateurs automatiques de phrases pour les conseils qui commencent à générer un contenu inadapté, en raison d'un nouveau contexte ;
  • Amazon a modifié son système de recommandation des vendeurs pour choisir ceux qui effectuent leurs propres livraisons, afin d'éviter que la logistique de ses entrepôts ne soit trop sollicitée.

Nous devons donc surveiller nos modèles d'IA/ML afin de garantir leur fiabilité et de continuer à aider nos clients.

Jusqu'à présent, j'espère vous avoir montré que la création, la formation et le déploiement de votre modèle de ML ne sont pas tout - vous devez en assurer le suivi. Dans le prochain article, je vous montrerai comment utiliser le framework %Monitor.Abstract d'IRIS pour surveiller les performances de votre système de ML et définir des alertes basées sur les métriques du moniteur.

En attendant, j'aimerais savoir si vous avez été confronté à l'un ou l'autre des problèmes soulevés par ces périodes de pandémie, et comment vous y faites face dans la section des commentaires !

Restez à l'écoute (et en sécurité 😊)!

0
0 53
Article Lucas Enard · Avr 3, 2023 10m read

Sur GitHub, vous trouverez toutes les informations sur l'utilisation d'un modèle d'apprentissage automatique "HuggingFace" / modèle d'IA sur le cadre IRIS à l'aide de Python.

1. iris-huggingface

Utilisation de modèles d'apprentissage automatique dans IRIS à l'aide de Python ; pour les modèles texte-texte, texte-image ou image-image.

Les modèles suivants servent d'exemple :

2. Installation

2.1. Lancement de la production

Dans le dossier iris-local-ml, ouvrez un terminal et saisisse :

docker-compose up

La première fois, cela peut prendre quelques minutes pour construire l'image de manière correcte et installer tous les modules nécessaires à Python.

2.2. Accès à la production

En suivant ce lien, vous accédez à la production : Access the Production

2.3. Clôture de la production

docker-compose down

Comment ça marche

Pour l'instant, certains modèles peuvent ne pas fonctionner avec cette implémentation car tout est fait automatiquement, ce qui veut dire que, quel que soit le modèle que vous saisissez, nous essaierons de le faire fonctionner grâce à la bibliothèque transformerspipeline.

Pipeline est un outil puissant de l'équipe HuggingFace qui va scanner le dossier dans lequel nous avons téléchargé le modèle, puis il va déterminer quelle bibliothèque il doit utiliser entre PyTorch, Keras, Tensorflow ou JAX pour ensuite charger ce modèle en utilisant AutoModel.
À partir de ce point, en saisissant la tâche, le pipeline sait ce qu'il doit faire avec le modèle, l'analyseur lexical ou même l'extracteur de caractéristiques dans ce dossier, et gère automatiquement votre entrée, l'analyse et la traite, la transmet au modèle, puis restitue la sortie sous une forme décodée directement utilisable par nous.

3. API HuggingFace

Vous devez d'abord démarrer la démo, en utilisant le bouton vert Start ou Stop et Start à nouveau pour appliquer vos changements de configuration.

Ensuite, en cliquant sur l'opération Python.HFOperation de votre choix, et en sélectionnant dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname vous devez saisir :

msg.HFRequest

Et pour le json, voici un exemple d'appel à GPT2 :

{
    "api_url":"https://api-inference.huggingface.co/models/gpt2",
    "payload":"Veuillez nous donner plus de détails sur votre ",
    "api_key":"----------------------"
}

Vous pouvez maintenant cliquer sur le bouton Visual Trace (Trace visuelle) pour voir en détail ce qui s'est passé et consulter les journaux.

REMARQUE : vous devez avoir une clé API de HuggingFace avant d'utiliser cette opération (les clés API sont gratuites, il suffit de s'enregistrer auprès de HF).

REMARQUE : vous pouvez changer l'url pour essayer n'importe quel autre modèle de HuggingFace, mais vous devrez peut-être changer le payload.

Par exemple :
sending hf reqhf reqhf resp

4. Utilisation de n'importe quel modèle sur le web

Dans cette section, nous vous apprendrons à utiliser presque tous les modèles disponibles sur l'internet, qu'il s'agisse de HuggingFace ou non.

4.1. PREMIER CAS : VOUS AVEZ VOTRE PROPRE MODÈLE

Dans ce cas, vous devez copier-coller votre modèle, avec la configuration, l'outil tokenizer.json etc. dans un dossier à l'intérieur du dossier model.
Chemin d'accès : src/model/yourmodelname/

A partir de là, vous devez aller dans les paramètres de Python.MLOperation.
Cliquez sur Python.MLOperation puis rendez-vous dans settings dans l'onglet de droite, puis dans la partie Python, puis dans la partie %settings. Ici, vous pouvez saisir ou modifier n'importe quel paramètre (n'oubliez pas d'appuyer sur apply une fois que vous avez terminé).
Voici la configuration par défaut pour ce cas :
%settings

name=yourmodelname
task=text-generation

REMARQUE : tous les paramètres qui ne sont pas name ou model_url sont placés dans les paramètres de PIPELINE.

NMaintenant vous pouvez double-cliquer sur l'opération Python.MLOperation et la démarrer. Vous devez voir dans la partie Log le démarrage de votre modèle.

A partir de là, nous créons une PIPELINE en utilisant des transformateurs qui utilisent votre fichier de configuration situé dans le dossier comme nous l'avons vu précédemment.

Pour appeler ce pipeline, cliquez sur l'opération Python.MLOperation , et sélectionnez dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname (nom de classe), vous devez saisir :

msg.MLRequest

Et pour le json, vous devez saisissez tous les arguments nécessaires à votre modèle. Voici un exemple d'appel à GPT2 :

{
    "text_inputs":"Malheureusement, le résultat",
    "max_length":100,
    "num_return_sequences":3
}

Cliquez sur Invoke Testing Service (Invoquer le service de test) et attendez que le modèle fonctionne.

Voir par exemple :
sending ml req

Vous pouvez maintenant cliquer sur Visual Trace (Trace visuelle) pour voir en détail ce qui s'est passé et consulter les journaux.

Voir par exemple :
ml req

ml resp

4.2. DEUXIÈME CAS : VOUS VOULEZ TÉLÉCHARGER UN MODÈLE À PARTIR DE HUGGINGFACE

Dans ce cas, vous devez trouver l'URL du modèle sur HuggingFace ;

4.2.1. Paramètres

À partir de là, vous devez accéder aux paramètres de la Python.MLOperation.
Cliquez sur Python.MLOperation puis allez dans des paramètres settings dans l'onglet de droite, puis dans la partie Python, puis dans la partie %settings. Ici, vous pouvez saisir ou modifier n'importe quel paramètre (n'oubliez pas d'appuyer sur apply (appliquer) une fois que vous avez terminé).
Voici quelques exemples de configuration pour certains modèles que nous avons trouvés sur HuggingFace :

%settings pour gpt2

model_url=https://huggingface.co/gpt2
name=gpt2
task=text-generation

%settings pour camembert-ner

name=camembert-ner
model_url=https://huggingface.co/Jean-Baptiste/camembert-ner
task=ner
aggregation_strategy=simple

%settings pour bert-base-uncased

name=bert-base-uncased
model_url=https://huggingface.co/bert-base-uncased
task=fill-mask

%settings pour detr-resnet-50

name=detr-resnet-50
model_url=https://huggingface.co/facebook/detr-resnet-50
task=object-detection

%settings pour detr-resnet-50-protnic

name=detr-resnet-50-panoptic
model_url=https://huggingface.co/facebook/detr-resnet-50-panoptic
task=image-segmentation

REMARQUE : tous les paramètres qui ne sont pas name ou model_url iront dans les paramètres du PIPELINE, donc dans notre second exemple, le pipeline camembert-ner requiert une stratégie aggregation_strategy et une tâche task qui sont spécifiées ici alors que le pipeline gpt2 ne requiert qu'une tâche task.

Voir par exemple :
settings ml ope2

Vous pouvez maintenant double-cliquer sur l'opération Python.MLOperation et la démarrer.
Vous devez voir dans la partie Log le démarrage de votre modèle et le téléchargement.
REMARQUE : Vous pouvez actualiser ces journaux toutes les x secondes pour voir l'évolution des téléchargements. dl en temps réel

A partir de là, nous créons une PIPELINE en utilisant des transformateurs qui utilisent votre fichier de configuration qui se trouve dans le dossier comme nous l'avons vu précédemment.

4.2.2. Tests

Pour appeler ce pipeline, cliquez sur l'opération Python.MLOperation , et sélectionnez dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname (nom de classe), vous devez saisir :

msg.MLRequest

Et pour le json, vous devez saisir tous les arguments nécessaires à votre modèle. Voici un exemple d'appel à GPT2 ( Python.MLOperation ) :

{
    "text_inputs":"George Washington a vécu",
    "max_length":30,
    "num_return_sequences":3
}

Voici un exemple d'appel à Camembert-ner ( Python.MLOperation2 ) :

{
    "inputs":"George Washington a vécu à Washington"
}

Voici un exemple d'appel à bert-base-uncased ( Python.MLOperation3 ) :

{
    "inputs":"George Washington a vécu à [MASQUE]."
}

Voici un exemple d'appel à detr-resnet-50 à l'aide d'une url en ligne ( Python.MLOperationDETRRESNET ) :

{
    "url":"http://images.cocodataset.org/val2017/000000039769.jpg"
}

Voici un exemple d'appel à detr-resnet-50-panoptic utilisant l'url comme chemin d'accès( Python.MLOperationDetrPanoptic ) :

{
    "url":"/irisdev/app/misc/000000039769.jpg"
}

Cliquez sur Invoke Testing Service et attendez que le modèle fonctionne.
Vous pouvez maintenant cliquer sur Visual Trace pour voir en détail ce qui s'est passé et consulter les journaux.

REMARQUE : Lorsque le modèle a été téléchargé pour la première fois, la production ne le téléchargera pas à nouveau mais récupérera les fichiers mis en cache dans src/model/TheModelName/.
Si certains fichiers sont manquants, la production les téléchargera à nouveau.

Voir par exemple :
sending ml reqml reqml resp

Voir par exemple :
sending ml reqml resp

5. Dépannage

Si vous avez des problèmes, la lecture est le premier conseil que nous pouvons vous donner, la plupart des erreurs sont facilement compréhensibles simplement en lisant les journaux car presque toutes les erreurs seront capturées par un try / catch et enregistrées.

Si vous avez besoin d'installer un nouveau module, ou une dépendance Python, ouvrez un terminal à l'intérieur du conteneur et saisissez par exemple : "pip install new-module"
Il y a plusieurs façons d'ouvrir un terminal,

  • Si vous utilisez les plugins InterSystems, vous pouvez cliquer sur la barre ci-dessous dans VSCode, celle qui ressemble à docker:iris:52795[IRISAPP] et sélectionner Open Shell in Docker (Ouvrir l'enveloppe dans Docker).
  • Dans n'importe quel terminal local, saisissez : docker-compose exec -it iris bash
  • Depuis Docker-Desktop, trouvez le conteneur IRIS et cliquez sur Open in terminal (Ouvrir dans le terminal).

Certains modèles peuvent nécessiter des modifications au niveau de leur pipeline ou de leurs paramètres, par exemple, et c'est à vous qu'il incombe d'ajouter les informations adéquates dans les paramètres et dans la demande.

6. Conclusion

À partir de là, vous devriez pouvoir utiliser n'importe quel modèle dont vous avez besoin ou que vous possédez sur IRIS.
REMARQUE : vous pouvez créer une Python.MLOperation pour chacun de vos modèles et les activer en même temps.

0
0 189
Article Sylvain Guilbaud · Mars 29, 2023 31m read

Keywords:  IRIS, IntegratedML, apprentissage automatique, Covid-19, Kaggle 

Objectif

J'ai récemment remarqué un jeu de données Kaggle permettant de prédire si un patient Covid-19 sera admis en soins intensifs. Il s'agit d'un tableur de 1925 enregistrements comprenant 231 colonnes de signes vitaux et d'observations, la dernière colonne " USI " valant 1 pour Oui ou 0 pour Non.

Ce jeu de données représente un bon exemple de ce que l'on appelle une tâche "traditionnelle de ML". Les données semblent avoir une quantité suffisante et une qualité relativement bonne. Il pourrait avoir de meilleures chances d'être appliqué directement sur le kit IntegratedML demo. Quelle serait donc l'approche la plus simple pour un test rapide basé sur les pipelines ML normaux par rapport à l'approche possible avec IntegratedML ?

Champ d'application

Nous examinerons brièvement quelques étapes normales de ML, telles que :

  • Analyse des données (EDA)
  • Sélection des caractéristiques
  • Sélection du modèle
  • Ajustement des paramètres du modèle via le quadrillage

Vs. 

  • Approches ML intégrées via SQL.

Il est exécuté sur un serveur AWS Ubuntu 16.04 avec Docker-compose, etc.  

Environnement

Nous allons réutiliser l'environnement Docker de integredML-demo-template:

Le fichier de bloc-notes suivant est exécuté sur "tf2jupyter", et IRIS avec IntegratedML sur "irismlsrv". Docker-compose fonctionne sur un AWS Ubuntu 16.04.

Données et tâches

Le jeu de données contient 1925 enregistrements collectés auprès de 385 patients, chacun comportant exactement 5 enregistrements de rendez-vous. Sur ses 231 colonnes, une seule, "USI", constitue notre cible d'apprentissage et de prédiction, et les 230 autres colonnes pourraient toutes être utilisées comme entrées de quelque manière que ce soit. L'unité de soins intensifs a une valeur binaire de 1 ou 0. À l'exception de deux colonnes qui semblent être des chaînes catégorielles (présentées comme "objet" dans le cadre de données), toutes les autres sont numériques.

import numpy as np
import pandas as pd
from sklearn.impute import SimpleImputer
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, roc_auc_score, roc_curve
import seaborn as sns
sns.set(style="whitegrid")

import os
for dirname, _, filenames in os.walk('./input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))
./input/datasets_605991_1272346_Kaggle_Sirio_Libanes_ICU_Prediction.xlsx

 

df = pd.read_excel("./input/datasets_605991_1272346_Kaggle_Sirio_Libanes_ICU_Prediction.xlsx")
df
<th>
  IDENTIFIANT_DE_VISITE_DU_PATIENT
</th>

<th>
  ÂGE_AU-DESSUS65
</th>

<th>
  ÂGE_POURCENTAGE
</th>

<th>
  GENRE
</th>

<th>
  GROUPE DE MALADIES 1
</th>

<th>
  GROUPE DE MALADIES 2
</th>

<th>
  GROUPE DE MALADIES 3
</th>

<th>
  GROUPE DE MALADIES 4
</th>

<th>
  GROUPE DE MALADIES 5
</th>

<th>
  GROUPE DE MALADIES 6
</th>

<th>
  ...
</th>

<th>
  DIFFÉRENCE_DE_TEMPÉRATURE
</th>

<th>
  DIFFÉRENCE_DE SATURATION_D'OXYGÈNE
</th>

<th>
  DIFFÉRENCE_DE_TENSION_DIASTOLIQUE_REL
</th>

<th>
  DIFFÉRENCE_DE_TENSION_SISTOLIQUE_REL
</th>

<th>
  DIFFÉRENCE_DU_RYTHME_CARDIAQUE_REL
</th>

<th>
  DIFFÉRENCE_DE_TAUX_RESPIRATOIRE_REL
</th>

<th>
  DIFFÉRENCE_DE_TEMPÉRATURE_REL
</th>

<th>
  DIFFÉRENCE_DE_SATURATION_D'OXYGÈNE_REL
</th>

<th>
  FENÊTRE
</th>

<th>
  ICU
</th>
<td>
</td>

<td>
  1
</td>

<td>
  âge de 60-69 ans
</td>

<td>
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  1.0
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  0-2
</td>

<td>
</td>
<td>
</td>

<td>
  1
</td>

<td>
  âge de 60-69 ans
</td>

<td>
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  1.0
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  2-4
</td>

<td>
</td>
<td>
</td>

<td>
  1
</td>

<td>
  âge de 60-69 ans
</td>

<td>
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  1.0
</td>

<td>
  ...
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  4-6
</td>

<td>
</td>
<td>
</td>

<td>
  1
</td>

<td>
  âge de 60-69 ans
</td>

<td>
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  1.0
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  NaN
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  6-12
</td>

<td>
</td>
<td>
</td>

<td>
  1
</td>

<td>
  âge de 60-69 ans
</td>

<td>
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  1.0
</td>

<td>
  ...
</td>

<td>
  -0.238095
</td>

<td>
  -0.818182
</td>

<td>
  -0.389967
</td>

<td>
  0.407558
</td>

<td>
  -0.230462
</td>

<td>
  0.096774
</td>

<td>
  -0.242282
</td>

<td>
  -0.814433
</td>

<td>
  AU-DESSUS_12
</td>

<td>
  1
</td>
<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>
<td>
  384
</td>

<td>
</td>

<td>
  âge de 50-59 ans
</td>

<td>
  1
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  0-2
</td>

<td>
</td>
<td>
  384
</td>

<td>
</td>

<td>
  âge de 50-59 ans
</td>

<td>
  1
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  2-4
</td>

<td>
</td>
<td>
  384
</td>

<td>
</td>

<td>
  âge de 50-59 ans
</td>

<td>
  1
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  4-6
</td>

<td>
</td>
<td>
  384
</td>

<td>
</td>

<td>
  âge de 50-59 ans
</td>

<td>
  1
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  6-12
</td>

<td>
</td>
<td>
  384
</td>

<td>
</td>

<td>
  âge de 50-59 ans
</td>

<td>
  1
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  ...
</td>

<td>
  -0.547619
</td>

<td>
  -0.838384
</td>

<td>
  -0.701863
</td>

<td>
  -0.585967
</td>

<td>
  -0.763868
</td>

<td>
  -0.612903
</td>

<td>
  -0.551337
</td>

<td>
  -0.835052
</td>

<td>
  AU-DESSUS_12
</td>

<td>
</td>
 
1
2
3
4
...
1920
1921
1922
1923
1924

1925 lignes × 231 colonnes

df.dtypes
IDENTIFIANT_DE_VISITE_DU_PATIENT        int64
ÂGE_AU-DESSUS65                     int64
ÂGE_POURCENTAGE                  object
GENRE                          int64
GROUPE DE MALADIES 1            float64
                               ...   
DIFFÉRENCE_DE_TAUX_RESPIRATOIRE_REL     float64
DIFFÉRENCE_DE_TEMPÉRATURE_REL          float64
DIFFÉRENCE_DE SATURATION_D'OXYGÈNE_REL    float64
FENÊTRE                         object
USI                             int64
Longeur: 231, dtype: object

Il existe certainement plusieurs options pour définir ce problème et ses approches. La première option qui nous vient à l'esprit est qu'il peut s'agir d'un problème fondamental de "classification binaire". Nous pouvons traiter les 1925 enregistrements comme des enregistrements individuels "apatrides", qu'ils proviennent ou non du même patient. Bien sûr, il pourrait également s'agir d'un problème de "régression" si nous traitions les valeurs de l'unité de soins intensifs et d'autres valeurs comme étant toutes numériques.

Il existe certainement d'autres approches possibles. Par exemple, nous pouvons considérer que l'ensemble de données comporte 385 jeux distincts de courtes "séries temporelles", chacun pour un patient. Nous pourrions dissoudre le jeu entier en 385 jeux distincts pour Train/Val/Test, et pourrions-nous essayer des modèles d'apprentissage profond tels que CNN ou LSTM pour capturer la "phase ou le modèle de développement des symptômes" caché dans chaque jeu pour chaque patient individuel ? C'est possible. Ce faisant, nous pourrions également appliquer une augmentation des données pour enrichir les données de test par divers moyens. Il s'agit là d'un sujet qui dépasse le cadre de cet article.

Dans cet article, nous nous contenterons de tester rapidement l'approche ML dite "traditionnelle" par rapport à l'approche IntegratedML (une approche AutoML)..  

Approche ML "traditionnelle" ?

Il s'agit d'un jeu de données relativement normalisé par rapport à la plupart des cas réels, à l'exception de quelques valeurs manquantes, de sorte que nous pourrions sauter la partie relative à l'ingénierie des caractéristiques et utiliser directement les colonnes comme caractéristiques. Passons donc directement à la sélection des caractéristiques.

Imputation des données manquantes

Il faut d'abord s'assurer que toutes les valeurs manquantes sont remplies au moyen d'une imputation simple :

df_cat = df.select_dtypes(include=['object'])
df_numeric = df.select_dtypes(exclude=['object'])
imp = SimpleImputer(missing_values=np.nan, strategy='mean')
idf = pd.DataFrame(imp.fit_transform(df_numeric))
idf.columns = df_numeric.columns
idf.index = df_numeric.index
idf.isnull().sum()

 

Sélection sur les caractéristiques

Nous pouvons certainement utiliser la fonction de corrélation normale intégrée dans la base de données pour calculer la corrélation entre les valeurs de chaque colonne et les unités de soins intensifs.

l'ingénierie des caractéristiques - corrélation {#featuring-engineering---correlation}

idf.drop(["PATIENT_VISIT_IDENTIFIER"],1)
idf = pd.concat([idf,df_cat ], axis=1)
cor = idf.corr()
cor_target = abs(cor["ICU"])
relevant_features = cor_target[cor_target>0.1]   # correlation above 0.1
print(cor.shape, cor_target.shape, relevant_features.shape)
#relevant_features.index
#relevant_features.index.shape

Il répertorie 88 caractéristiques présentant une corrélation >0,1 avec la valeur cible de l'unité de soins intensifs. Ces colonnes peuvent être directement utilisées comme entrée de notre modèle

J'ai également exécuté quelques autres "méthodes de sélection de caractéristiques" qui sont normalement utilisées dans les tâches traditionnelles de ML :

Sélection des caractéristiques - Chi carré {#feature-selection---Chi-squared}

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
from sklearn.preprocessing import MinMaxScaler
X_norm = MinMaxScaler().fit_transform(X)
chi_selector = SelectKBest(chi2, k=88)
chi_selector.fit(X_norm, y)
chi_support = chi_selector.get_support()
chi_feature = X.loc[:,chi_support].columns.tolist()
print(str(len(chi_feature)), 'selected features', chi_feature)
88 caractéristiques sélectionnées ['ÂGE_AU-DESSUS65', 'GENRE', 'GROUPE DE MALADIES 1', ... ... 'P02_VENEUS_MIN', 'P02_VENEUS_MAX', ... ... RATURE_MAX', 'DIFFÉRENCE_DE_TENSION_ARTÉRIELLE_DIASTOLIQUE', ... ... 'DIFFÉRENCE_DE_TEMPÉRATURE_REL', 'DIFFÉRENCE_DE SATURATION_D'OXYGÈNE_REL']

Sélection des caractéristiques - Corrélation de Pearson 

def cor_selector(X, y,num_feats):
    cor_list = []
    feature_name = X.columns.tolist()
    # calculate the correlation with y for each feature
    for i in X.columns.tolist():
        cor = np.corrcoef(X[i], y)[0, 1]
        cor_list.append(cor)
    # replace NaN with 0
    cor_list = [0 if np.isnan(i) else i for i in cor_list]
    # feature name
    cor_feature = X.iloc[:,np.argsort(np.abs(cor_list))[-num_feats:]].columns.tolist()
    # Sélection des caractéristiques? 0 for not select, 1 for select
    cor_support = [Vrai if i in cor_feature else False for i in feature_name]
    return cor_support, cor_featurecor_support, cor_feature = cor_selector(X, y, 88)
print(str(len(cor_feature)), 'selected features:  ', cor_feature)
88 caractéristiques sélectionnées:   ['TEMPÉRATURE_MOYENNE', 'TENSION_DIASTOLIQUE_MAX', ... ... 'DIFFÉRENCE_DE_TAUX_ RESPIRATOIRE', 'AUX_ RESPIRATOIRE_MAX']

Sélection des caractéristiques - élimination de caractéristiques récursives (RFE) {#feature-selection---Recursive-Feature-Elimination-(RFE)}

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
rfe_selector = RFE(estimator=LogisticRegression(), n_features_to_select=88, step=100, verbose=5)
rfe_selector.fit(X_norm, y)
rfe_support = rfe_selector.get_support()
rfe_feature = X.loc[:,rfe_support].columns.tolist()
print(str(len(rfe_feature)), 'selected features: ', rfe_feature)
Estimateur d'ajustement avec 127 caractéristiques.
88 caractéristiques sélectionnées:  ['ÂGE_AU-DESSUS65', 'GENRE', ... ... 'DIFFÉRENCE_DE_TAUX_ RESPIRATOIRE_REL', 'DIFFÉRENCE_DE_TEMPÉRATURE_REL']

Sélection des caractéristiques - Lasso

ffrom sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import MinMaxScaler
X_norm = MinMaxScaler().fit_transform(X)
embeded_lr_selector = SelectFromModel(LogisticRegression(penalty="l2"), max_features=88)
embeded_lr_selector.fit(X_norm, y)
embeded_lr_support = embeded_lr_selector.get_support()
embeded_lr_feature = X.loc[:,embeded_lr_support].columns.tolist()
print(str(len(embeded_lr_feature)), 'selected features', embeded_lr_feature)
65 caractéristiques sélectionnées ['ÂGE_AU-DESSUS65', 'GENRE', ... ... 'DIFFÉRENCE_DE_TAUX_ RESPIRATOIRE_REL', 'DIFFÉRENCE_DE_TEMPÉRATURE_REL']

Sélection des caractéristiques - RF Tree-based: SelectFromModel

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
embeded_rf_selector = SelectFromModel(RandomForestClassifier(n_estimators=100), max_features=227)
embeded_rf_selector.fit(X, y)
embeded_rf_support = embeded_rf_selector.get_support()
embeded_rf_feature = X.loc[:,embeded_rf_support].columns.tolist()
print(str(len(embeded_rf_feature)), 'selected features', embeded_rf_feature)
48 selected features ['ÂGE_AU-DESSUS65', 'GENRE', ... ... 'DIFFÉRENCE_DE_TEMPÉRATURE_REL', 'DIFFÉRENCE_DE SATURATION_D'OXYGÈNE_REL']

Sélection des caractéristiques - LightGBM or XGBoost {#feature-selection---LightGBM-or-XGBoost}

from sklearn.feature_selection import SelectFromModel
from lightgbm import LGBMClassifierlgbc=LGBMClassifier(n_estimators=500, learning_rate=0.05, num_leaves=32, colsample_bytree=0.2,
            reg_alpha=3, reg_lambda=1, min_split_gain=0.01, min_child_weight=40)embeded_lgb_selector = SelectFromModel(lgbc, max_features=128)
embeded_lgb_selector.fit(X, y)embeded_lgb_support = embeded_lgb_selector.get_support()
embeded_lgb_feature = X.loc[:,embeded_lgb_support].columns.tolist()
print(str(len(embeded_lgb_feature)), 'selected features:  ', embeded_lgb_feature)
embeded_lgb_feature.index
56 selected features:   ['ÂGE_AU-DESSUS65', 'GENRE', 'HTN', ... ... 'DIFFÉRENCE_DE_TEMPÉRATURE_REL', 'DIFFÉRENCE_DE SATURATION_D'OXYGÈNE_REL']

Sélection des caractéristiques - Les regrouper tous {#feature-selection---Ensemble-them-all}

feature_name = X.columns.tolist()
# regrouper toute la sélection
feature_selection_df = pd.DataFrame({'Feature':feature_name, 'Pearson':cor_support, 'Chi-2':chi_support, 'RFE':rfe_support, 'Logistics':embeded_lr_support, 'Random Forest':embeded_rf_support, 'LightGBM':embeded_lgb_support})
# compter les temps sélectionnés pour chaque caractéristique
feature_selection_df['Total'] = np.sum(feature_selection_df, axis=1)
# afficher les 100 premières
num_feats = 227
feature_selection_df = feature_selection_df.sort_values(['Total','Feature'] , ascending=False)
feature_selection_df.index = range(1, len(feature_selection_df)+1)
feature_selection_df.head(num_feats)
df_selected_columns = feature_selection_df.loc[(feature_selection_df['Total'] > 3)]
df_selected_columns

Nous pouvons dresser la liste des caractéristiques qui ont été sélectionnées dans le cadre d'au moins quatre méthodes :

... ...

Nous pouvons certainement choisir ces 58 caractéristiques. Entre-temps, l'expérience nous a appris que la sélection des caractéristiques n'est pas nécessairement toujours un vote démocratique ; le plus souvent, elle peut être spécifique au problème du domaine, aux données spécifiques et parfois au modèle ou à l'approche ML spécifique que nous allons adopter plus tard.

Sélection des caractéristiques - Outils tiers 

Il existe des outils industriels et des outils AutoML largement utilisés, par exemple DataRobot qui peut fournir une bonne sélection automatique des caractéristiques :  

Le graphe DataRobot ci-dessus montre, sans surprise, que les valeurs de fréquence respiratoire et de tension artérielle sont les caractéristiques les plus pertinentes pour l'admission en soins intensifs.    

Sélection des caractéristiques - Sélection finale
Dans ce cas, j'ai fait quelques expériences rapides et j'ai remarqué que la sélection des caractéristiques par LightGBM donnait un résultat un peu meilleur, c'est pourquoi nous n'utiliserons que cette méthode de sélection.   

df_selected_columns = embeded_lgb_feature  # mieux que la sélection ensemblistedataS = pd.concat([idf[df_selected_columns],idf['ICU'], df_cat['FENÊTRE']],1)
dataS.ICU.value_counts()
print(dataS.shape)
(1925, 58)

Nous pouvons voir que 58 caractéristiques sont sélectionnées, c'est-à-dire ni trop peu, ni trop beaucoup, ce qui semble être la bonne quantité pour ce problème spécifique de classification binaire à cible unique. 

Déséquilibre des données

plt.figure(figsize=(10,5))
count = sns.countplot(x = "USI",data=data)
count.set_xticklabels(["Non admis", "Admis"])
plt.xlabel("Admission à l'USI")
plt.ylabel("Nombre de patients")
plt.show()

Cela indique que les données sont déséquilibrées, seuls 26 % des enregistrements étant admis en USI. Cela aura un impact sur les résultats et nous pouvons donc envisager des approches normales d'équilibrage des données telles que SMOTE, etc.

Nous pouvons essayer toutes sortes d'autres AED pour analyser les différentes distributions de données en conséquence. 

Exécuter une formation de base en LR

Le site Kaggle propose de jolis carnets d'entraînement rapide que nous pouvons exécuter rapidement en fonction de notre propre sélection de colonnes de caractéristiques. Commençons par une exécution rapide du classificateur LR pour le pipeline de formation :

data2 = pd.concat([idf[df_selected_columns],idf['USI'], df_cat['FENÊTRE']],1)   
data2.AGE_ABOVE65 = data2.AGE_ABOVE65.astype(int)
data2.ICU = data2.ICU.astype(int)
X2 = data2.drop("USI",1)
y2 = data2.ICU

from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
X2.WINDOW = label_encoder.fit_transform(np.array(X2["FENÊTRE"].astype(str)).reshape((-1,)))

confusion_matrix2 = pd.crosstab(y2_test, y2_hat, rownames=['Réel'], colnames=['Prédit'])
sns.heatmap(confusion_matrix2, annot=Vrai, fmt = 'g', cmap = 'Reds') print("ORIGINAL")
print(classification_report(y_test, y_hat))
print("USI = ",roc_auc_score(y_test, y_hat),'\n\n')
print("ENCODAGE D'ÉTIQUETTE")
print(classification_report(y2_test, y2_hat))
print("ASC = ",roc_auc_score(y2_test, y2_hat))
y2hat_probs = LR.predict_proba(X2_test)
y2hat_probs = y2hat_probs[:, 1] fpr2, tpr2, _ = roc_curve(y2_test, y2hat_probs) plt.figure(figsize=(10,7))
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr, tpr, label="Base")
plt.plot(fpr2,tpr2,label="Étiquette encodée")
plt.xlabel('Taux de faux positifs')
plt.ylabel('Taux de vrais positifs')
plt.title('Courbe ROC')
plt.legend(loc="meilleur")
plt.show()

ORIGINAL
              précision    rappel  score f1   support
           0       0.88      0.94      0.91       171
           1       0.76      0.57      0.65        54
    exactitude                           0.85       225
   moyenne macro       0.82      0.76      0.78       225
moyenne pondérée       0.85      0.85      0.85       225
ASC=  0.7577972709551657
LABEL ENCODING
              précision    rappel  score f1   support
           0       0.88      0.93      0.90       171
           1       0.73      0.59      0.65        54
    accuracy                           0.85       225
   moyenne macro       0.80      0.76      0.78       225
moyenne pondérée       0.84      0.85      0.84       225
ASC =  0.7612085769980507

        

Il semble qu'il atteigne une AUC de 76 %, avec une précision de 85 %, mais le rappel pour les patients admis en réanimation n'est que de 59 % - il semble y avoir trop de faux négatifs. Ce n'est certainement pas l'idéal - nous ne voulons pas passer à côté des risques réels de l'USI pour le dossier d'un patient. Toutes les tâches suivantes seront donc axées sur l'objectif sur la manière d'augmenter le taux de rappel, en réduisant le FN, avec une précision globale quelque peu équilibrée, nous l'espérons.

Dans les sections précédentes, nous avons mentionné des données déséquilibrées, de sorte que notre premier réflexe serait de stratifier l'ensemble de test et de le MODIFIER pour obtenir un ensemble de données plus équilibré.

#stratifier les données de test, afin de s'assurer que les données de train et de test ont le même ratio de 1:0
X3_train,X3_test,y3_train,y3_test = train_test_split(X2,y2,test_size=225/1925,random_state=42, stratify = y2, shuffle = Vrai) &lt;span> &lt;/span>
# former et prédire
LR.fit(X3_train,y3_train)
y3_hat = LR.predict(X3_test)

#MODIFIER les données pour faire de l'UCI 1:0 une distribution équilibrée
from imblearn.over_sampling import SMOTE sm = SMOTE(random_state = 42)
X_train_res, y_train_res = sm.fit_sample(X3_train,y3_train.ravel())
LR.fit(X_train_res, y_train_res)
y_res_hat = LR.predict(X3_test)

#recréer la matrice de confusion, etc.
confusion_matrix3 = pd.crosstab(y3_test, y_res_hat, rownames=['Actual'], colnames=['Predicted'])
sns.heatmap(confusion_matrix3, annot=Vrai, fmt = 'g', cmap="YlOrBr")
print("LABEL ENCODING + STRATIFY")
print(classification_report(y3_test, y3_hat))
print("ASC = ",roc_auc_score(y3_test, y3_hat),'\n\n')
print("SMOTE")
print(classification_report(y3_test, y_res_hat))
print("ASC = ",roc_auc_score(y3_test, y_res_hat))
y_res_hat_probs = LR.predict_proba(X3_test)
y_res_hat_probs = y_res_hat_probs[:, 1]
fpr_res, tpr_res, _ = roc_curve(y3_test, y_res_hat_probs) plt.figure(figsize=(10,10))

#Et tracez la courbe ROC comme précédemment.

 

LABEL ENCODING + STRATIFY (CODAGE D'ÉTIQUETTES + STRATIFICATION)
              précision    rappel  f1 score   support
           0       0.87      0.99      0.92       165
           1       0.95      0.58      0.72        60
    exactitude                           0.88       225
   moyenne macro       0.91      0.79      0.82       225
moyenne pondérée       0.89      0.88      0.87       225
ASC =  0.7856060606060606
SMOTE
              précision    rappel  f1 score   support
           0       0.91      0.88      0.89       165
           1       0.69      0.75      0.72        60
    exactitude                           0.84       225
   moyenne macro       0.80      0.81      0.81       225
moyenne pondérée       0.85      0.84      0.85       225
ASC =  0.8143939393939393

            

Les traitements des données par STRATIFY (stratification) et SMOT (optimisation) semblent donc améliorer le rappel, qui passe de 0,59 à 0,75, avec une précision globale de 0,84. 

Maintenant que le traitement des données est largement effectué comme d'habitude pour le ML traditionnel, nous voulons savoir quel pourrait être le(s) meilleur(s) modèle(s) dans ce cas ; peuvent-ils faire mieux, et pouvons-nous alors essayer une comparaison globale relative ?

Comparaison de l'entraînement à la course de différents modèles

Poursuivons l'évaluation de quelques algorithmes de ML couramment utilisés, et générons un tableau de bord de résultats à comparer à l'aide de diagrammes en boîte à moustaches :

# comparer les algorithmes
from matplotlib import pyplot
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
#Importer un modèle arborescent aléatoire
from sklearn.ensemble import RandomForestClassifier
from xgboost import XGBClassifier# Répertorier les algorithmes ensemble
models = []
models.append(('LR', &lt;strong>LogisticRegression&lt;/strong>(solver='liblinear', multi_class='ovr')))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', &lt;strong>KNeighborsClassifier&lt;/strong>()))
models.append(('CART', &lt;strong>DecisionTreeClassifier&lt;/strong>()))
models.append(('NB', &lt;strong>GaussianNB&lt;/strong>()))
models.append(('SVM', &lt;strong>SVC&lt;/strong>(gamma='auto')))
models.append(('RF', &lt;strong>RandomForestClassifier&lt;/strong>(n_estimators=100)))
models.append(('XGB', &lt;strong>XGBClassifier&lt;/strong>())) #clf = XGBClassifier()
# évaluer chaque modèle à tour de rôle
résultats = []
noms = []
pour nom, modèler dans modèles :
    kfold = StratifiedKFold(n_splits=10, random_state=1)
    cv_results = cross_val_score(model, X_train_res, y_train_res, cv=kfold, scoring='f1')  ## exactitude, précision, rappel
    results.append(cv_results)
    names.append(name)
    print('%s: %f (%f)' % (name, cv_results.mean(), cv_results.std()))# Comparer les performances de tous les modèles. Question - Souhaitez-vous voir un article intégré sur le site ?
pyplot.figure(4, figsize=(12, 8))
pyplot.boxplot(résultats, étiquettes=noms)
pyplot.title('Comparaison des algorithmes')
pyplot.show()
LR: 0.805390 (0.021905) LDA: 0.803804 (0.027671) KNN: 0.841824 (0.032945) CART: 0.845596 (0.053828)
NB: 0.622540 (0.060390) SVM: 0.793754 (0.023050) RF: 0.896222 (0.033732) XGB: 0.907529 (0.040693)

Ce qui précède semble montrer que le classificateur XGB et le classificateur de la forêt aléatoire "Random Forest" obtiendraient un meilleur score F1 que les autres modèles.

Comparons leurs résultats réels sur le même ensemble de données de test normalisées :

Temps d'importation
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.svm import SVCpour nom, modèler dans modèles :
    print(name + ':\n\r')
    start = time.clock()
    model.fit(X_train_res, y_train_res)
    print("Temps de formation pour ", model, " ", time.clock() - start)
    predictions = model.predict(X3_test) #(X_validation)
    # Evaluate predictions
    print(accuracy_score(y3_test, predictions))  # Y_validation
    print(confusion_matrix(y3_test, predictions))
    print(classification_report(y3_test, predictions))
LR:
Temps de formation pour  LogisticRegression(multi_class='ovr', solver='liblinear')   0.02814499999999498
0.8444444444444444
[[145  20]
 [ 15  45]]
              précision    rappel  f1 score   support
           0       0.91      0.88      0.89       165
           1       0.69      0.75      0.72        60
    exactitude                           0.84       225
   moyenne macro       0.80      0.81      0.81       225
moyenne pondérée       0.85      0.84      0.85       225

LDA:
Temps de formation pour  LinearDiscriminantAnalysis()   0.2280070000000194
0.8488888888888889
[[147  18]
 [ 16  44]]
              précision    rappel  f1 score   support
           0       0.90      0.89      0.90       165
           1       0.71      0.73      0.72        60
    exactitude                           0.85       225
   moyenne macro       0.81      0.81      0.81       225
moyenne pondérée       0.85      0.85      0.85       225

KNN:
Temps de formation pour  KNeighborsClassifier()   0.13023699999999394
0.8355555555555556
[[145  20]
 [ 17  43]]
              précision    rappel  f1 score   support
           0       0.90      0.88      0.89       165
           1       0.68      0.72      0.70        60
    exactitude                           0.84       225
   moyenne macro       0.79      0.80      0.79       225
moyenne pondérée       0.84      0.84      0.84       225

CART:
Temps de formation pour  DecisionTreeClassifier()   0.32616000000001577
0.8266666666666667
[[147  18]
 [ 21  39]]
              précision    rappel  f1 score   support
           0       0.88      0.89      0.88       165
           1       0.68      0.65      0.67        60
    exactitude                           0.83       225
   moyenne macro       0.78      0.77      0.77       225
moyenne pondérée       0.82      0.83      0.83       225

NB:
Temps de formation pour  GaussianNB()   0.0034229999999979555
0.8355555555555556
[[154  11]
 [ 26  34]]
              précision    rappel  f1 score   support
           0       0.86      0.93      0.89       165
           1       0.76      0.57      0.65        60
    exactitude                           0.84       225
   moyenne macro       0.81      0.75      0.77       225
moyenne pondérée       0.83      0.84      0.83       225

SVM:
Temps de formation pour  SVC(gamma='auto')   0.3596520000000112
0.8977777777777778
[[157   8]
 [ 15  45]]
              précision    rappel  f1 score   support
           0       0.91      0.95      0.93       165
           1       0.85      0.75      0.80        60
    exactitude                           0.90       225
   moyenne macro       0.88      0.85      0.86       225
moyenne pondérée       0.90      0.90      0.90       225

RF:
Temps de formation pour  RandomForestClassifier()   0.50123099999999
0.9066666666666666
[[158   7]
 [ 14  46]]
              précision    rappel  f1 score   support
           0       0.92      0.96      0.94       165
           1       0.87      0.77      0.81        60
    exactitude                           0.91       225
   moyenne macro       0.89      0.86      0.88       225
moyenne pondérée       0.91      0.91      0.90       225

XGB:
Temps de formation pour  XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
              colsample_bynode=1, colsample_bytree=1, gamma=0, gpu_id=-1,
              importance_type='gain', interaction_constraints='',
              learning_rate=0.300000012, max_delta_step=0, max_depth=6,
              min_child_weight=1, missing=nan, monotone_constraints='()',
              n_estimators=100, n_jobs=0, num_parallel_tree=1, random_state=0,
              reg_alpha=0, reg_lambda=1, scale_pos_weight=1, subsample=1,
              tree_method='exact', validate_parameters=1, verbosity=Aucun)   1.649520999999993
0.8844444444444445
[[155  10]
 [ 16  44]]
              précision    rappel  f1 score   support
           0       0.91      0.94      0.92       165
           1       0.81      0.73      0.77        60
    exactitude                           0.88       225
   moyenne macro       0.86      0.84      0.85       225
moyenne pondérée       0.88      0.88      0.88       225

Le résultat semble être que RF est en fait meilleur que XGB. Cela pourrait signifier que XGB est peut-être un peu plus surajouté d'une manière ou d'une autre. Le résultat de RFC est également légèrement meilleur que celui de LR.

Exécuter le modèle sélectionné en poursuivant "Ajustement des paramètres via la recherche par quadrillage"

Supposons maintenant que nous ayons choisi le modèle de classificateur de la forêt aléatoire "Random Forest Classifier". Nous pouvons effectuer une nouvelle recherche sur la grille de ce modèle pour voir s'il est possible d'obtenir des résultats un peu plus performants. 

Rappelez-vous que notre objectif est toujours d'optimiser le rappel dans ce cas, en minimisant le nombre de faux négatifs concernant les risques possibles pour l'USI lors de la rencontre avec le patient, nous utiliserons donc 'recall_score' pour réajuster le quadrillage ci-dessous. Une fois de plus, la validation croisée 10 fois sera utilisée comme d'habitude, étant donné que notre ensemble de test ci-dessus a toujours été fixé à environ 12 % de ces 2915 enregistrements.

from sklearn.model_selection import GridSearchCV
# Créer la grille de paramètres sur la base des résultats de la recherche aléatoire

param_grid = {'bootstrap': [Vrai],
 'ccp_alpha': [0.0],
 'class_weight': [Aucun],
 'criterion': ['gini', 'entropy'],
 'max_depth': [Aucun],
 'max_features': ['auto', 'log2'],             
 'max_leaf_nodes': [Aucun],
 'max_samples': [Aucun],
 'min_impurity_decrease': [0.0],
 'min_impurity_split': [Aucun],
 'min_samples_leaf': [1, 2, 4],
 'min_samples_split': [2, 4],
 'min_weight_fraction_leaf': [0.0],
 'n_estimators': [100, 125],
 #'n_jobs': [Aucun],
 'oob_score': [False],
 'random_state': [Aucun],
 #'verbose': 0,
 'warm_start': [False]
}#Ajuster par matrice de confusion
from sklearn.metrics import roc_curve, précision_recall_curve, auc, make_scorer, recall_score, accuracy_score, précision_score, confusion_matrix
scorers = {
    'recall_score': make_scorer(recall_score),
    'précision_score': make_scorer(précision_score),
    'accuracy_score': make_scorer(accuracy_score)
}# Créer un modèle de base
rfc = RandomForestClassifier()
# Instancier le modèle de quadrillage
grid_search = GridSearchCV(estimator = rfc, param_grid = param_grid,
                           scoring=scorers, refit='recall_score',
                           cv = 10, n_jobs = -1, verbose = 2)train_features = X_train_resgrid_search.fit(train_features, train_labels)
rf_best_grid = grid_search.best_estimator_rf_best_grid.fit(train_features, train_labels)
rf_predictions = rf_best_grid.predict(X3_test)
print(accuracy_score(y3_test, rf_predictions))  
print(confusion_matrix(y3_test, rf_predictions))
print(classification_report(y3_test, rf_predictions))
0.92
[[ 46  14]
 [  4 161]]
              précision    rappel f1 score   support
           0       0.92      0.77      0.84        60
           1       0.92      0.98      0.95       165
    exactitude                           0.92       225
   moyenne macro       0.92      0.87      0.89       225
moyenne pondérée       0.92      0.92      0.92       225

Le résultat a montré qu'un quadrillage a permis d'augmenter légèrement la précision globale, tout en maintenant le FN au même niveau. 

Traçons également les comparaisons avec l'ASC :

confusion_matrix4 = pd.crosstab(y3_test, rf_predictions, rownames=['Actual'], colnames=['Predicted'])
sns.heatmap(confusion_matrix4, annot=Vrai, fmt = 'g', cmap="YlOrBr")print("LABEL ENCODING + STRATIFY")
print(classification_report(y3_test, 1-y3_hat))
print("ASC = ",roc_auc_score(y3_test, 1-y3_hat),'\n\n')print("SMOTE")
print(classification_report(y3_test, 1-y_res_hat))
print("ASC = ",roc_auc_score(y3_test, 1-y_res_hat), '\n\n')print("SMOTE + LBG Selected Weights + RF Grid Search")
print(classification_report(y3_test, rf_predictions))
print("ASC = ",roc_auc_score(y3_test, rf_predictions), '\n\n\n')y_res_hat_probs = LR.predict_proba(X3_test)
y_res_hat_probs = y_res_hat_probs[:, 1]predictions_rf_probs = rf_best_grid.predict_proba(X3_test) #(X_validation)
predictions_rf_probs = predictions_rf_probs[:, 1]fpr_res, tpr_res, _ = roc_curve(y3_test, 1-y_res_hat_probs)
fpr_rf_res, tpr_rf_res, _ = roc_curve(y3_test, predictions_rf_probs)plt.figure(figsize=(10,10))
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr, tpr, label="Base")
plt.plot(fpr2,tpr2,label="Label Encoded")
plt.plot(fpr3,tpr3,label="Stratify")
plt.plot(fpr_res,tpr_res,label="SMOTE")
plt.plot(fpr_rf_res,tpr_rf_res,label="SMOTE + RF GRID")
plt.xlabel('False positive rate')
plt.ylabel('Vrai positive rate')
plt.title('ROC curve')
plt.legend(loc="best")
plt.show()
CODAGE D'ÉTIQUETTES + STRATIFICATION
              précision    rappel  f1 score   support
           0       0.95      0.58      0.72        60
           1       0.87      0.99      0.92       165
    exactitude                           0.88       225
   moyenne macro       0.91      0.79      0.82       225
moyenne pondérée       0.89      0.88      0.87       225
ASC =  0.7856060606060606

MODIFICATION
              précision    rappel  f1 score   support
           0       0.69      0.75      0.72        60
           1       0.91      0.88      0.89       165
    exactitude                           0.84       225
   moyenne macro       0.80      0.81      0.81       225
moyenne pondérée       0.85      0.84      0.85       225
ASC =  0.8143939393939394

MODIFICATION + LBG Pondérations sélectionnées + Quadrillage RF
              précision    rappel  f1 score   support
           0       0.92      0.77      0.84        60
           1       0.92      0.98      0.95       165
    exactitude                           0.92       225
   moyenne macro       0.92      0.87      0.89       225
moyenne pondérée       0.92      0.92      0.92       225
ASC =  0.8712121212121211

     

Le résultat a montré qu'après des comparaisons d'algorithmes et un quadrillage suivant, nous avons réussi à faire passer l'ASC de 78 % à 87 %, avec une précision globale de 92 % et un rappel de 77 %.

Récapitulatif de l'approche "ML traditionnelle"

Qu'en est-il réellement de ce résultat ? Il est correct pour un processus manuel de base avec des algorithmes ML traditionnels. Comment ce résultat apparaît-il dans les tableaux de compétition Kaggle ? Eh bien, il ne figurerait pas dans le tableau de classement. J'ai passé le jeu de données brutes par le service AutoML actuel de DataRobot, le meilleur résultat serait un ASC équivalent de ~90+% (à confirmer avec des données similaires) avec le modèle " Classificateur arborescent XGB avec fonctions d'apprentissage non supervisé " (XGB Trees Classifier with Unsupervised Learning Features), sur une comparaison des 43 meilleurs modèles. C'est peut-être le genre de modèle de base que nous devrions utiliser si nous voulons vraiment être compétitifs sur Kaggle. Je joindrai également la liste des meilleurs résultats par rapport aux modèles dans le github. Finalement, pour les cas réels spécifiques aux sites de soins, j'ai le sentiment que nous devons également intégrer un certain degré d'approches d'apprentissage profond personnalisées, comme mentionné dans la section "Données et tâches" de ce billet. Bien sûr, dans les cas réels, l'endroit où collecter des colonnes de données de qualité pourrait également être une question initiale.

L'approche IntegratedML?

Ce qui précède est un processus de ML dit traditionnel, qui comprend normalement l'EDA des données, l'ingénierie des caractéristiques, la sélection des caractéristiques, la sélection des modèles, et l'optimisation des performances par la quadrillage, etc. C'est l'approche la plus simple à laquelle j'ai pu penser jusqu'à présent pour cette tâche, et nous n'avons même pas encore abordé le déploiement du modèle et les cycles de vie de la gestion des services - nous le ferons dans le prochain article, en examinant comment nous pourrions tirer parti de Flask/FastAPI/IRIS et déployer ce modèle de ML de base dans une pile de services de démonstration de la radiographie de Covid-19.

IRIS dispose désormais d'IntegratedML, qui est une enveloppe SQL élégante d'options puissantes d'AutoMLs. Dans la deuxième partie, nous verrons comment accomplir la tâche susmentionnée dans le cadre d'un processus simplifié, de sorte que nous n'aurons plus à nous préoccuper de la sélection des caractéristiques, de la sélection des modèles, de l'optimisation des performances, etc.

Jusqu'ici, cet article pourrait être trop long pour une note de 10 minutes visant à intégrer rapidement les mêmes données, c'est pourquoi je le déplace vers l'article suivant, partie II

0
0 74
Annonce Irène Mykhailova · Mars 24, 2023

Salut les développeurs,

Nous aimerions vous inviter à participer à notre prochain concours dédié à la création des solutions d'IA/ML qui utilisent Cloud SQL pour travailler avec les données :

🏆 Concours InterSystems IRIS Cloud SQL et IntegratedML 🏆

Durée: du 3 avril au 23 avril 2023

Prix: $13,500!

0
0 98
Article Guillaume Rongier · Fév 17, 2023 18m read

Keywords:  IRIS, IntegratedML, Flask, FastAPI, Tensorflow servant, HAProxy, Docker, Covid-19

Objective:

Nous avons abordé quelques démonstrations rapides d'apprentissage profond et d'apprentissage automatique au cours des derniers mois, notamment un simple classificateur d'images radiographiques Covid-19 et un classificateur de résultats de laboratoire Covid-19 pour les admissions possibles en soins intensifs. Nous avons également évoqué une implémentation de démonstration IntegratedML du classificateur ICU. Alors que la randonnée de la "science des données" se poursuit, le moment est peut-être venu d'essayer de déployer des services d'IA du point de vue de "l'ingénierie des données" - pourrions-nous regrouper tout ce que nous avons abordé jusqu'à présent dans un ensemble d'API de services ? Quels sont les outils, les composants et l'infrastructure communs que nous pourrions exploiter pour réaliser une telle pile de services dans son approche la plus simple possible ?

 

Cadre

Dans le cadre de ce qui suit:

Pour commencer, nous pouvons simplement utiliser docker-compose pour déployer les composants dockerisés suivants dans un serveur AWS Ubuntu

  • HAProxy - équilibreur de charge
  • Gunicorn vs. Univorn ** - passerelle web **serveurs
  • Flask vs. FastAPI - serveurs d'application pour l'interface utilisateur des applications Web, les définitions des API de service, la génération des cartes thermiques, etc.
  • Tensorflow Model Serving vs. Tensorflow-GPU Model Serving - serveurs d'applications pour les classifications d'images, etc.
  • IRIS IntegratedML - AutoML consolidé App+DB avec interface SQL.
  • Python3 dans Jupyter Notebook pour émuler un client pour le benchmarking.
  • Docker et docker-compose.
  • AWS Ubuntu 16.04 avec un GPU Tesla T4  

Remarque:   Tensorflow Serving avec GPU n'est utilisé qu'à des fins de démonstration - vous pouvez simplement désactiver l'image liée au GPU (dans un fichier docker) et la configuration (dans le fichier docker-compose.yml).

Out of scope (Hors de portée) ou sur la prochaine liste de souhaits :

  • **Les serveurs web Nginx ou Apache etc. sont omis dans la démo pour le moment.
  • RabbitMQ et Redis - courtier de file d'attente pour une messagerie fiable qui peut être remplacé par IRIS ou Ensemble.
    IAM (Intersystems API Manger) ou Kong est sur la liste des souhaits.
  • SAM(Intersystems System Alert & Monitoring)
  • ICM (Intersystems Cloud Manager) avec l'opérateur Kubernetes - toujours l'un de mes préférés depuis sa naissance
  • FHIR (serveur FHIR R4 basé sur Intesystems IRIS et FHIR Sandbox pour les applications SMART sur FHIR)
  • Outils de développement CI/CD ou Github Actions.

De toute façon, un "ingénieur en apprentissage automatique" ("Machine Learning Engineer") mettra inévitablement la main sur ces composants pour fournir des environnements de production tout au long des cycles de vie des services. Nous pourrons en savoir plus au fil du temps.

Dépôt Github

Le code source complet se trouve à l'adresse suivante : https://github.com/zhongli1990/covid-ai-demo-deployment

Le référentiel integratedML-demo-template est également réutilisé avec le nouveau référentiel. 
 

Modèle de déploiement

Le schéma de déploiement logique de ce cadre de test "Démonstration de l'IA dans les Dockers" est présenté ci-dessous.

Pour la démonstration, j'ai délibérément créé deux piles distinctes pour la classification de l'apprentissage profond et le rendu web, puis j'ai utilisé un HAProxy comme équilibreur de charge pour distribuer les requêtes API entrantes entre ces deux piles de manière indépendante.

  • Guniorn + Flask + Tensorflow Serving
  • Univcorn + FaskAPI + Tensorflow Serving GPU

IRIS avec IntegratedML est utilisé pour les échantillons de démonstration d'apprentissage automatique, comme dans l'article précédent de prédiction de l'ICU.

J'ai omis certains composants communs dans la démo actuelle qui seraient nécessaires ou envisagés pour les services de production :

  • Serveurs Web : Nginx ou Apache, etc. Ils seront nécessaires entre HAProxy et Gunicorn/Uvicorn, pour une gestion correcte des sessions HTTP, c'est-à-dire pour éviter les attaques DoS, etc.
  • Gestionnaire de file d'attente et bases de données : RabbitMQ et/ou Redis, etc., entre Flask/FastAPI et le serveur backend, pour un service asynchrone fiable et la persistance des données/configurations, etc.
  • Passerelle API : IAM ou Kong clusters, entre l'équilibreur de charge HAProxy et le serveur web pour la gestion des API sans créer de point singulier de défaillance.
  • Surveillance et alerte : SAM serait bien.
  • Provisionnement pour CI/CD devops : ICM avec K8s serait nécessaire pour le déploiement et la gestion neutre en nuage, et pour CI/CD avec d'autres outils devops communs.

En fait,  IRIS lui-même peut certainement être utilisé comme gestionnaire de file d'attente de niveau entreprise ainsi que comme base de données performante pour une messagerie fiable. Dans l'analyse des modèles, il apparaît qu'IRIS peut remplacer les courtiers de file d'attente et les bases de données RabbitMQ/Redis/MongoDB, etc., et qu'il serait donc mieux consolidé avec une latence bien moindre et de meilleures performances globales. Et plus encore, IRIS Web Gateway (anciennement CSP Gateway) peut certainement être positionné à la place de Gunicorn ou Unicorn, etc, n'est-ce pas ?  

Topologie de l'environnement

Il existe quelques options courantes pour mettre en œuvre le modèle logique ci-dessus dans tous les composants Docker. Les plus courantes sont les suivantes :  

  • docker-compose
  • docker swarm etc
  • Kubernetes etc 
  • ICM avec K8s Operation

Cette démonstration commence avec "docker-compose" pour un PoC fonctionnel et un certain benchmarking. Nous aimerions certainement utiliser K8s et peut-être aussi ICM au fil du temps. 

Comme décrit dans son fichier docker-compose.yml, une implémentation physique de sa topologie d'environnement sur un serveur AWS Ubuntu ressemblerait à ceci :  

Le diagramme ci-dessus montre comment ces ports de service de toutes les instances Docker sont mappés et exposés directement sur le serveur Ubuntu à des fins de démonstration. En production, la sécurité devrait être renforcée. Et pour les besoins de la démonstration, tous les conteneurs sont connectés au même réseau Docker, alors qu'en production, il serait séparé en routable externe et non-routable interne.

Composants "Dockerisés" 

Le tableau ci-dessous montre comment les volumes de stockage de la machine hôte sont montés sur chaque instance de conteneur comme spécifié dans ce fichier docker-compose.yml

ubuntu@ip-172-31-35-104:/zhong/flask-xray$ tree ./ -L 2

./├── covid19                             (Les conteneurs Flask+Gunicorn et Tensorflow Serving seront montés ici)├── app.py                                (Flask main app:  Les interfaces de l'application web et du service API sont définies et mises en œuvre ici)├── covid19_models               (Les modèles Tensorflow sont publiés et versionnés ici pour la classification des images Le conteneur Tensorflow Serving avec CPU)├── Dockerfile                          (Le serveur Flask avec Gunicorn:      CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:5000", "--workers", "4", "--threads", "2"])├── models                               (Modèles au format .h5 pour l'application Flask et démonstration API de la génération de heatmaps par grad-cam sur des radiographies.)├── __pycache__├── README.md├── requirements.txt             (Paquets Python nécessaires pour les applications complètes de Flask+Gunicorn) ├── scripts├── static                                  (Fichiers statiques Web)├── templates                         (Modèles de rendu Web)├── tensorflow_serving        (Fichier de configuration pour le service de tensorflow)└── test_images├── covid-fastapi                   (Les conteneurs FastAPI+Uvicorn et Tensorflow Serving avec GPU seront définis ici)├── covid19_models            (Les modèles Tensorflow au service des GPU sont publiés et versionnés ici pour la classification des images)├── Dockerfile                       (Le serveur Uvicorn+FastAPI sera lancé ici: CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4" ])├── main.py                           (FastAPI app: les interfaces de l'application web et du service API sont définies et mises en œuvre ici)├── models                            (Modèles au format .h5 pour l'application FastAPI et démonstration API de la génération de heatmaps par grad-cam sur des radiographies)├── __pycache__├── README.md├── requirements.txt├── scripts├── static├── templates├── tensorflow_serving└── test_images├── docker-compose.yml      (Full stack Docker definition file.  La version 2.3 est utilisée pour tenir compte du GPU Docker "nvidia runtime", sinon la version 3.x peut être utilisée)├── haproxy                             (Le service docker HAProxy est défini ici.  Note : une session collante peut être définie pour le backend LB. )                             ├── Dockerfile└── haproxy.cfg└── notebooks                       (Le service conteneur Jupyter Notebook avec Tensorflow 2.2 et Tensorboard etc)├── Dockerfile├── notebooks                  (Exemples de fichiers notebook pour émuler des applications API Client externes pour les tests fonctionnels et les tests de référence API en Python sur l'équilibreur de charge, etc)└── requirements.txt

Remarque: Le docker-compose.yml ci-dessus est destiné à la démonstration d'apprentissage profond de Convid X-Rays. Il est utilisé avec le docker-compose.yml d'un autre integratedML-demo-template pour former la pile de services complète, comme indiqué dans la topologie de l'environnement.  

Démarrage des services 

Un simple docker-compose up -d permettrait de démarrer tous les services de conteneurs :

ubuntu@ip-172-31-35-104:~$ docker ps
ID DE CONTENEUR        IMAGE                                 COMMANDE                  STATUT CRÉÉ                PORTS                                                                              NOMS
31b682b6961d        iris-aa-server:2020.3AA               "/iris-main"             Il y a 7 semaines         Jusqu'à 2 jours (en bonne santé)   2188/tcp, 53773/tcp, 54773/tcp, 0.0.0.0:8091->51773/tcp, 0.0.0.0:8092->52773/tcp   iml-template-master_irisimlsvr_1
6a0f22ad3ffc        haproxy:0.0.1                         "/docker-entrypoint.…"   Il y a 8 semaines         Jusqu'à 2 jours             0.0.0.0:8088->8088/tcp                                                             flask-xray_lb_1
71b5163d8960        ai-service-fastapi:0.2.0              "uvicorn main:app --…"   Il y a 8 semaines         Jusqu'à 2 jours             0.0.0.0:8056->8000/tcp                                                             flask-xray_fastapi_1
400e1d6c0f69        tensorflow/serving:latest-gpu         "/usr/bin/tf_serving…"   Il y a 8 semaines         Jusqu'à 2 jours             0.0.0.0:8520->8500/tcp, 0.0.0.0:8521->8501/tcp                                     flask-xray_tf2svg2_1
eaac88e9b1a7        ai-service-flask:0.1.0                "gunicorn app:app --…"   Шl y a 8 semaines         Jusqu'à 2 jours             0.0.0.0:8051->5000/tcp                                                             flask-xray_flask_1
e07ccd30a32b        tensorflow/serving                    "/usr/bin/tf_serving…"   Il y a 8 semaines         Jusqu'à 2 jours             0.0.0.0:8510->8500/tcp, 0.0.0.0:8511->8501/tcp                                     flask-xray_tf2svg1_1
390dc13023f2        tf2-jupyter:0.1.0                     "/bin/sh -c '/bin/ba…"   Il y a 8 semaines         Jusqu'à 2 jours             0.0.0.0:8506->6006/tcp, 0.0.0.0:8586->8888/tcp                                     flask-xray_tf2jpt_1
88e8709404ac        tf2-jupyter-jdbc:1.0.0-iml-template   "/bin/sh -c '/bin/ba…"   Il y a 2 $ois         Jusqu'à 2 jours             0.0.0.0:6026->6006/tcp, 0.0.0.0:8896->8888/tcp                                     iml-template-master_tf2jupyter_1

docker-compose up --scale fastapi=2 --scale flask=2 -d   par exemple, sera mis à l'échelle horizontalement jusqu'à 2 conteneurs Gunicorn+Flask et 2 conteneurs Univcorn+FastAPI :

ubuntu@ip-172-31-35-104:/zhong/flask-xray$ docker ps
ID DE CONTENEUR        IMAGE                                 COMMANDE                  STATUT CRÉÉ                PORTS                                                                              NOMS
dbee3c20ea95        ai-service-fastapi:0.2.0              "uvicorn main:app --…"   Il y a 4 minutes Jusqu'à 4 minutes          0.0.0.0:8057->8000/tcp                                                             flask-xray_fastapi_2
95bcd8535aa6        ai-service-flask:0.1.0                "gunicorn app:app --…"   Il y a 4 minutes Jusqu'à 4 minutes          0.0.0.0:8052->5000/tcp                                                             flask-xray_flask_2

... ...

L'exécution d'un autre "docker-compose up -d" dans le répertoire de travail de "integrtedML-demo-template" a fait apparaître le conteneur irisimlsvr et tf2jupyter dans la liste ci-dessus.

Tests

1. Application web de démonstration de l'IA avec une interface utilisateur simple

Après avoir démarré les services docker ci-dessus, nous pouvons visiter une application web de démonstration pour X-Ray Covid-19 lung detection hébergée dans une instance AWS EC2 à une adresse temporaire à http://ec2-18-134-16-118.eu-west-2.compute.amazonaws.com:8056/

Voici ci-dessous quelques écrans capturés depuis mon mobile. L'interface utilisateur de démonstration est très simple : en gros, je clique sur "Choose File" puis sur le bouton "Submit" pour télécharger une image radiographique, puis l'application affiche un rapport de classification. S'il s'agit d'une radiographie Covid-19, une [carte thermique sera affichée] (https://community.intersystems.com/post/explainability-and-visibility-covid-19-x-ray-classifiers-deep-learning) pour reproduire la zone de lésion "détectée" par DL ; sinon, le rapport de classification ne montrera que l'image radiographique téléchargée.

        

L'application web est une page serveur Python dont la logique est principalement codée dans le fichier main.py de FastAPI, ainsi que dans le fichier app.py de Flask.

Quand j'aurai un peu plus de temps libre, je pourrais documenter en détail les différences de codage et de convention entre Flask et FastAPI. En fait, j'espère pouvoir faire un hébergement de démonstration Flask vs FastAPI vs IRIS pour l'IA. 

2. Test des API de démonstration      

FastAPI (exposé au port 8056) a intégré des documents Swagger API, comme indiqué ci-dessous. C'est très pratique. Tout ce que j'ai à faire est d'utiliser "/docs" dans son URL, par exemple : 

J'ai intégré quelques paramètres (tels que /hello et /items) et quelques interfaces API de démonstration (telles que /healthcheck, /predict, et predict/heatmap).

Testons rapidement ces API, en exécutant quelques lignes Python (en tant qu'émulateur d'application client API) dans l'un des [fichiers d'échantillons de Jupyter Notebook que j'ai créés] (https://github.com/zhongli1990/covid-ai-demo-deployment/tree/master/notebooks/notebooks) pour ce service de démonstration de l'IA.  

Ci-dessous, j'exécute ce fichier à titre d'exemple : https://github.com/zhongli1990/covid-ai-demo-deployment/blob/master/notebooks/notebooks/Covid19-3class-Heatmap-Flask-FastAPI-TF-serving-all-in-one-HAProxy2.ipynb

Tout d'abord pour tester que le backend TF-Serving (port 8511) et TF-Serving-GPU (port 8521) sont en place et fonctionnent : 

!curl http://172.17.0.1:8511/v1/models/covid19  # servant tensorflow
!curl http://172.17.0.1:8521/v1/models/covid19  # servant tensorflow-gpu
{
 "model_version_status": [
  {
   "version": "2",
   "state": "AVAILABLE",
   "status": {
    "error_code": "OK",
    "error_message": ""
   }
  }
 ]
}
{
 "model_version_status": [
  {
   "version": "2",
   "state": "AVAILABLE",
   "status": {
    "error_code": "OK",
    "error_message": ""
   }
  }
 ]
}

 

Ensuite, vérifiez que les services API suivants sont en place et fonctionnent :

  • Gunicorn+Flask+TF-Serving
  • Unicorn+FastAPI+TF-Serving-GPU
  • Equilibreur de charge HAProxy en face des services gênants ci-dessus
  • r = requests.get('http://172.17.0.1:8051/covid19/api/v1/healthcheck')  # tf servant le docker avec le cpu
    print(r.status_code, r.text)
    r = requests.get('http://172.17.0.1:8056/covid19/api/v1/healthcheck')  # tf-servant le docker avec le gpu
    print(r.status_code, r.text)
    r = requests.get('http://172.17.0.1:8088/covid19/api/v1/healthcheck')  # tf-servant le docker avec le HAproxy
    print(r.status_code, r.text)

    Et les résultats attendus seraient :

    200 L'API du détecteur Covid19 est en ligne !
    200 "L'API du détecteur Covid19 est en ligne !\n\n"
    200 "L'API du détecteur Covid19 est en ligne !\n\n"

     

    Tester une interface API fonctionnelle, telle que **/predict/heatmap ** pour renvoyer le résultat de la classification et de la heatmap d'une image radiographique d'entrée. L'image entrante est codée en based64 avant d'être envoyée via HTTP POST conformément aux définitions de l'API :

    %%time# Importation de la bibliothèque des requêtes
    import argparse
    import base64import requests# définition d'un point d'entrée ap pour api
    API_ENDPOINT = "http://172.17.0.1:8051/covid19/api/v1/predict/heatmap"image_path = './Covid_M/all/test/covid/nejmoa2001191_f3-PA.jpeg'
    #image_path = './Covid_M/all/test/normal/NORMAL2-IM-1400-0001.jpeg'
    #image_path = './Covid_M/all/test/pneumonia_bac/person1940_bacteria_4859.jpeg'
    b64_image = ""
    # Encoding the JPG,PNG,etc. image to base64 format
    with open(image_path, "rb") as imageFile:
        b64_image = base64.b64encode(imageFile.read())# données à envoyer à l'api
    data = {'b64': b64_image}# envoi d'une requête post et enregistrement de la réponse en tant qu'objet réponse
    r = requests.post(url=API_ENDPOINT, data=data)print(r.status_code, r.text)# extraction de la réponse
    print("{}".format(r.text))

    Toutes ces [images de test ont également été téléchargées sur GitHub] (https://github.com/zhongli1990/Covid19-X-Rays/tree/master/all/test). Le résultat du code ci-dessus sera comme ça:

    200 {"Input_Image":"http://localhost:8051/static/source/0198f0ae-85a0-470b-bc31-dc1918c15b9620200906-170443.png","Output_Heatmap":"http://localhost:8051/static/result/Covid19_98_0198f0ae-85a0-470b-bc31-dc1918c15b9620200906-170443.png.png","X-Ray_Classfication_Raw_Result":[[0.805902302,0.15601939,0.038078323]],"X-Ray_Classification_Covid19_Probability":0.98,"X-Ray_Classification_Result":"Covid-19 POSITIVE","model_name":"Customised Incpetion V3"}
    
    {"Input_Image":"http://localhost:8051/static/source/0198f0ae-85a0-470b-bc31-dc1918c15b9620200906-170443.png","Output_Heatmap":"http://localhost:8051/static/result/Covid19_98_0198f0ae-85a0-470b-bc31-dc1918c15b9620200906-170443.png.png","X-Ray_Classfication_Raw_Result":[[0.805902302,0.15601939,0.038078323]],"X-Ray_Classification_Covid19_Probability":0.98,"X-Ray_Classification_Result":"Covid-19 POSITIVE","model_name":"Customised Incpetion V3"}
    
    CPU times: user 16 ms, sys: 0 ns, total: 16 ms
    Wall time: 946 ms

     

    3. Les applications de démonstration de services pour les tests benchmarkés

    Nous avons mis en place une instance d'équilibreur de charge HAProxy. Nous avons également démarré un service Flask avec 4 travailleurs, et un service FastAPI avec 4 travailleurs également.

    Pourquoi ne pas créer 8x processus Pyhon directement dans le fichier Notebook, pour émuler 8x clients API simultanés envoyant des requêtes dans les API du service de démonstration, pour voir ce qui se passe ? 

    #from concurrent.futures import ThreadPoolExecutor as PoolExecutor
    from concurrent.futures import ProcessPoolExecutor as PoolExecutor
    import http.client
    import socket
    import timestart = time.time()#laodbalancer:
    API_ENDPOINT_LB = "http://172.17.0.1:8088/covid19/api/v1/predict/heatmap"
    API_ENDPOINT_FLASK = "http://172.17.0.1:8052/covid19/api/v1/predict/heatmap"
    API_ENDPOINT_FastAPI = "http://172.17.0.1:8057/covid19/api/v1/predict/heatmap"
    def get_it(url):
        try:
            # boucle sur les images
            for imagePathTest in imagePathsTest:
                b64_image = ""
                with open(imagePathTest, "rb") as imageFile:
                    b64_image = base64.b64encode(imageFile.read())
    
                data = {'b64': b64_image}
                r = requests.post(url, data=data)
                #print(imagePathTest, r.status_code, r.text)
            return r
        except socket.timeout:
            # dans un scénario du monde réel, vous feriez probablement quelque chose si le
            # socket passe en timeout
            passurls = [API_ENDPOINT_LB, API_ENDPOINT_LB,
            API_ENDPOINT_LB, API_ENDPOINT_LB,
            API_ENDPOINT_LB, API_ENDPOINT_LB,
            API_ENDPOINT_LB, API_ENDPOINT_LB]with PoolExecutor(max_workers=16) as executor:
        for _ in executor.map(get_it, urls):
            pass
    
    print("--- %s seconds ---" % (time.time() - start))

    Il a donc fallu 74 secondes pour traiter 8x27 = 216 images de test. Cette pile de démonstration à charge équilibrée était capable de traiter 3 images par seconde (en renvoyant les résultats de la classification et de la heatmap aux clients) :

    --- 74.37691688537598 seconds ---

    À partir de la commande Top de la session Putty, nous pouvons voir que 8x processus de serveur (4x gunicorn + 4 unicorn/python) ont commencé à monter en puissance dès que les scripts de référence ci-dessus ont commencé à être exécutés.

    Suivant

    Cet article n'est qu'un point de départ pour mettre en place une pile de déploiement "All-in-Docker AI demo" comme cadre de test. J'espère ensuite ajouter d'autres interfaces de démonstration API, telles que l'interface de prédiction des soins intensifs Covid-19, idéalement conforme à la norme FHIR R4, etc. Cela pourrait également être un banc d'essai pour explorer une intégration plus étroite avec les capacités ML hébergées par IRIS. Au fil du temps, il peut être utilisé comme un cadre de test (et un cadre assez simple) pour intercepter de plus en plus de modèles ML ou DL spécialisés au fur et à mesure que nous avançons sur divers aspects de l'IA, notamment l'imagerie médicale, la santé de la population ou la prédiction personnalisée, le traitement automatique des langues, etc. J'ai également dressé une liste de souhaits à la toute fin de l'article précédent (dans sa section "Next" (Suivant))

    0
    0 314
    Article Guillaume Rongier · Mai 27, 2022 5m read

    La semaine dernière, nous avons annoncé la Plate-forme de données InterSystems IRIS, notre nouvelle plate-forme complète pour toutes vos activités liées aux données, qu'elles soient transactionnelles, analytiques ou les deux. Nous avons inclus un grand nombre des fonctionnalités que nos clients connaissent et apprécient de Caché et Ensemble, mais dans cet article, nous allons mettre un peu plus en lumière l'une des nouvelles capacités de la plate-forme : SQL Sharding, une nouvelle fonctionnalité puissante dans notre histoire de scalability.

    Si vous avez exactement 4 minutes et 41 secondes, jetez un coup d'œil à cette vidéo astucieuse sur le scalability. Si vous ne trouvez pas vos écouteurs et ne croyez pas que notre voix apaisante plaira à vos collègues, continuez à lire !

    Changement d'échelle

    Qu'il s'agisse de traiter des millions d'opérations boursières par jour ou de soigner des dizaines de milliers de patients par jour, une plateforme de données prenant en charge ces activités doit être capable de faire face à ces grandes échelles de manière transparente. La manière transparente signifie que les développeurs et les utilisateurs ne doivent pas se préoccuper de ces chiffres et qu'ils peuvent se concentrer sur leurs activités et applications principales, la plate-forme se chargeant de l'aspect de l'échelle.

    Depuis des années, Caché prend en charge le vertical scalability, où les progrès du matériel sont exploités de manière transparente par le logiciel, en exploitant efficacement un nombre très élevé de cœurs et de grandes quantités de RAM. C'est ce qu'on appelle la mise à l'échelle vers le haut, et bien qu'un bon effort de dimensionnement initial puisse vous permettre d'obtenir un système parfaitement équilibré, il y a une limite inhérente à ce que vous pouvez réaliser sur un seul système de manière rentable.

    C'est là qu'intervient le horizontal scalability, qui consiste à répartir la charge de travail sur un certain nombre de serveurs distincts travaillant en cluster, plutôt que sur un seul. Caché prend en charge les serveurs d'application ECP comme moyen de horizontal scalability depuis un certain temps déjà, mais InterSystems IRIS ajoute désormais le sharding SQL.

    Quelles sont les nouveautés ?

    Quelle est donc la différence entre les serveurs d'application ECP et la nouvelle fonctionnalité de sharding ? Pour comprendre cette différence, examinons de plus près les charges de travail. Une charge de travail peut consister en des dizaines de milliers de petits dispositifs écrivant continuellement de petits lots de données dans la base de données, ou juste une poignée d'analystes émettant des requêtes analytiques couvrant chacune des Go de données à la fois. Lequel des deux a la plus grande échelle ? Difficile à dire, tout comme il est difficile de dire si une canne à pêche ou un tonneau de bière est le plus grand. Les charges de travail ont plus d'une dimension et, par conséquent, la mise à l'échelle pour les prendre en charge nécessite également un peu plus de subtilité.

    En simplifiant grossièrement, considérons les composants suivants dans une charge de travail d'application : N représente la charge de travail de l'utilisateur et Q représente la taille de la requête. Dans nos exemples précédents, la première charge de travail a un N élevé mais un Q faible et la seconde est caractérisée par un N faible mais un Q élevé. Les serveurs d'application ECP sont très efficaces pour aider à supporter un grand N, car ils permettent de répartir les utilisateurs de l'application sur différents serveurs. Cependant, ils ne sont pas nécessairement aussi utiles si l'ensemble de données devient très grand et que l'ensemble de travail ne tient pas dans la mémoire d'une seule machine. Le sharding s'occupe des grands Q, en vous permettant de partitionner l'ensemble de données entre les serveurs, le travail étant également poussé vers ces serveurs shard autant que possible.

     

    Sharding SQL

    Alors, à quoi sert réellement le sharding ? Il s'agit d'une fonctionnalité SQL qui divise les données d'une table partagée en ensembles disjoints de lignes qui sont stockés sur les serveurs shard. Lorsque vous vous connectez au maître du shard, vous voyez toujours cette table comme s'il s'agissait d'une table unique contenant toutes les données, mais les requêtes sont divisées en requêtes locales au shard qui sont envoyées à tous les serveurs shard. Là, les serveurs shard calculent les résultats en fonction des données qu'ils ont stockées localement et renvoient leurs résultats au shard master. Ce dernier agrège ces résultats, exécute toute combinaison logique pertinente et renvoie les résultats à l'application. 

     

    Bien que ce système soit trivial pour un simple SELECT * FROM table, il y a beaucoup de logique intelligente au niveau de l'interface qui garantit que vous pouvez utiliser (presque) n'importe quelle requête SQL et qu'un maximum de travail est poussé vers les shards pour maximiser le parallélisme. La "clé du shard", qui définit quelles lignes vont où, est l'endroit où vous anticipez les modèles de requête typiques. Plus important encore, si vous pouvez vous assurer que les tables souvent reliés entre eux sont répartis selon les mêmes clés, les jointures peuvent être entièrement résolues au niveau du shard, ce qui vous donne les hautes performances que vous recherchez.

    Bien sûr, ce n'est qu'un avant-goût et il y a beaucoup plus à explorer, mais l'essentiel est ce qui est illustré ci-dessus : Le sharding SQL est une nouvelle recette dans le livre des plats hautement évolutifs que vous pouvez concocter avec InterSystems IRIS. Il s'agit d'un complément aux serveurs d'applications ECP, qui se concentre sur les ensembles de données de taille importante, ce qui en fait une solution idéale pour de nombreux cas d'utilisation analytique. Comme les serveurs d'applications ECP, il est entièrement transparent pour l'application et présente quelques variations architecturales plus créatives pour des scénarios très spécifiques. 

    Où puis-je en savoir plus ?

    Les enregistrements des sessions suivantes du Global Summit 2017 sur le sujet sont disponibles ici : http://learning.intersystems.com:

    Consultez également le présent guide de ressources sur InterSystems IRIS sur learning.intersystems.com pour en savoir plus sur les autres capacités de la nouvelle plate-forme. Si vous souhaitez essayer le sharding sur votre cas d'utilisation particulier, consultez http://www.intersystems.com/iris et remplissez le formulaire en bas de page pour vous inscrire à notre programme d'adoption initiale, ou surveillez la version de test sur le terrain prévue plus tard cette année.

    0
    0 77