#Machine Learning (ML)

0 Abonnés · 22 Publications

L'apprentissage automatique (ML) est un sous-ensemble de l'intelligence artificielle dans le domaine de l'informatique qui utilise souvent des techniques statistiques pour donner aux ordinateurs la capacité d'« apprendre » avec des données, sans être explicitement programmés.

En savoir plus.

Article Lorenzo Scalese · Mai 28, 2025 6m read

Cet article présente une analyse du cycle de solution pour l'application Open Exchange TOOT ( application Open Exchange)

L'hypothèse

Un bouton sur une page Web permet de capturer la voix de l'utilisateur. L'intégration IRIS permet de manipuler les enregistrements afin d' extraire la signification sémantique que la recherche vectorielle d'IRIS peut ensuite proposer pour de nouveaux types de solutions d'IA.

La signification sémantique amusante choisie concernait la recherche vectorielle musicale, afin d'acquérir de nouvelles compétences et connaissances en cours de route.

À la recherche de motifs simples

La voix humaine qui parle, siffle ou fredonne a des contraintes qui se sont exprimées à travers de nombreux encodages de données historiques à faible bande passante et de supports d'enregistrement.

Quelle quantité minimale d'informations est nécessaire pour distinguer un son musical d'un autre en relation avec une entrée vocale musicale?

Considérez la séquence des lettres de l'alphabet musical:

   A, B, C, E, A

Like in programming with ASCII values of the characters:
* B est supérieur d'une unité à A
* C est supérieur d'une unité à B
* E est supérieur de deux unités à C
* A est inférieur de quatre unités à E
Représenté sous forme de progression numérique entre deux nombres:

 +1, +1, +2, -4

On a besoin d'une information de moins que le nombre initial de notes.
Si l'on teste logiquement après le premier café du matin, le fredonnement devient:

  B, C, D, F, B

Notez que la séquence numérique correspond toujours à cette hauteur élevée.
Cela démontre qu'une progression numérique de la différence de hauteur semble plus flexible pour correspondre à l'entrée utilisateur que des notes réelles.

Durée des notes

Le sifflement a une résolution inférieure à celle représentée par les manuscrits musicaux traditionnels.
Une décision a été prise de ne résoudre que DEUX types de durée de note musicale:

  • Une note longue qui dure 0,7 seconde ou plus
  • Une note courte qui dure moins de 0,7 seconde.

Vides entre les notes

Les vides ont une résolution assez faible, nous n'utilisons donc qu'un seul point d'information.
Il a été décidé de définir un vide entre deux notes comme suit:

une pause de plus d'une demi-seconde entre deux notes distinctes.

Plage de changement des notes

Une décision a été prise afin de limiter la transition maximale enregistrable entre deux notes de 45 hauteurs différentes.
Tout changement de note saisi par l'utilisateur qui dépasse cette limite est tronqué à +45 ou -45, selon que la hauteur augmente ou diminue. Contrairement aux notes réelles, cela affecte en rien l'utilité d'une séquence de recherche de mélodie continue.

   +1 0 +2 -4 +2 +1 -3

Possibilité d'entraînement pour obtenir une correspondance sémantique proche de la séquence de changements indiquée en rouge.

+1 1 +2 -4 +2 +1 -3

Saisie monocanal

Une voix ou un sifflement est un instrument simple qui ne produit qu'une seule note à la fois.
Cependant, cela doit correspondre à une musique composée généralement de:
* Plusieurs instruments qui jouent simultanément
* Des instruments qui jouent des accords (plusieurs notes à la fois)
En général, un sifflement tend à suivre UNE voix ou un instrument spécifique pour représenter une musique de référence.
Lors d'enregistrements physiques, les voix et les instruments individuels peuvent être pistes distinctes qui sont ensuite "mixés" ensemble.
De même, les utilitaires d'encodage/décodage et les formats de données peuvent également préserver et utiliser des "pistes" par voix/instrument.

Il en résulte que les entrées fredonnées/sifflées doivent être recherchées en fonction de l'impression laissée par chaque piste vocale et instrumentale.

Plusieurs modèles d'encodage "musicaux" / formats linguistiques ont été envisagés.
L'option la plus simple et la plus aboutie consistait à utiliser le traitement au format MIDI pour déterminer les encodages de référence pour la correspondance et la recherche de sifflements.

Récapitulatif du vocabulaire

Outre les séquences habituelles de symboles de début, de fin et de remplissage, les points d'information sont les suivants

  • 45 notes longues dont la durée diminue selon une amplitude spécifique
  • 45 notes courtes dont la durée diminue selon une amplitude spécifique
  • Répétition de la même note d'une durée courte
  • Répétition de la même note d'une durée longue
  • 45 notes longues dont la durée augmente selon une amplitude spécifique
  • 45 notes courtes dont la durée augmente selon une amplitude spécifique
  • Un vide entre les notes

Données synthétiques

Les globales IRIS sont très rapides et efficaces pour identifier les combinaisons et leur fréquence dans un grand ensemble de données.

Le point de départ des données synthétiques était des séquences valides.

Celles-ci ont été modifiées de différentes manières et classées en fonction de leur écart:

  • SplitLongNote - Une note longue est divisée en deux notes courtes, dont la seconde est une répétition
  • JoinLongNote - Deux notes courtes, dont la seconde est une répétition, sont fusionnées en une seule note longue.
  • VaryOneNote ( +2, +1, -1 or -2 )
  • DropSpace - Suppression de l'espace entre les notes
  • AddSpace - Ajout d'un espace entre les notes

Ensuite, ces scores sont superposés de manière efficace dans une globale pour chaque résultat.

Cela signifie que lorsqu'une autre zone de séquence de changement de note dans un flux de piste est plus proche d'une valeur mutée, le score le plus élevé est toujours sélectionné.

Flux de travail Dev

Flux de travail de recherche

Flux de travail DataLoad

Des intégrations vectorielles ont été générées pour plusieurs pistes d'instruments (22 935 enregistrements) et pour des échantillons mélodiques (6 762 enregistrements)

Flux de travail d'entraînement

Deux essais d'entraînement:

Sans supervision - 110 000 enregistrements maximum (7 heures de traitement)

Score de similarité sous supervision - 960 000 enregistrements maximum (1,3 jour de traitement)

Autres exigences à explorer

Meilleure mesure de la similarité

La version actuelle de l'implémentation trie les résultats en fonction des scores de manière trop stricte.

Il convient de réexaminer le seuil d'inclusion des séquences à faible et à forte occurrence dans l'ensemble de données.

Filtrage du bruit de fond

Au format MIDI, le volume des voix ou des instruments est important en termes d'utilisation réelle et de bruit de fond. Cela pourrait permettre de nettoyer/filtrer une source de données. On pourrait peut-être exclure les pistes qui ne seraient jamais référencées par une entrée humaine. Actuellement, la solution exclut les « percussions » par piste instrumentale, par titre et par analyse de certaines répétitions de progression.

Instruments MIDI synthétiques

L'approche actuelle pour faire correspondre la voix aux instruments consistait à essayer de contourner les incompatibilités entre les caractéristiques des instruments, afin de voir si cela donnait un résultat satisfaisant.

Une expérience intéressante serait d'ajouter certaines caractéristiques à partir des données fournies par l'utilisateur, tout en modifiant les données d'apprentissage synthétiques afin d'obtenir des caractéristiques plus humaines.

Le MIDI encode des informations supplémentaires avec des variations de hauteur afin d'obtenir une progression plus fluide entre les notes.

Ce serait une piste à explorer pour étendre et affiner la manière dont la conversion WAV vers MIDI est effectuée.

Conclusion

J'espère que vous avez trouvé cet article intéressant et que vous apprécierez l'application. Peut-être vous inspirera-t-elle de nouvelles idées.

0
0 30
Article Iryna Mykhailova · Avr 3, 2025 3m read

Introduction

Dans InterSystems IRIS 2024.3 et les versions ultérieures d'IRIS, le composant AutoML est désormais fourni sous forme de package Python distinct, installé après l'installation. Malheureusement, certaines versions récentes des packages Python sur lesquels AutoML s'appuie ont introduit des incompatibilités et peuvent entraîner des échecs lors de l'entraînement des modèles (instruction TRAIN MODEL). Si vous rencontrez une erreur mentionnant « TypeError » et l'argument de mot-clé « fit_params » ou « sklearn_tags », lisez la suite pour une solution rapide.

Cause principale

0
0 28
Article Iryna Mykhailova · Mars 13, 2025 3m read

Présentation

Grâce à SQL, vous pouvez créer, entraîner et gérer des modèles de machine learning directement dans la base de données grâce à l'outil robuste IntegratedML d'InterSystems IRIS. À l'aide d'exemples SQL représentant vos données, nous aborderons dans cet article la configuration d'IntegratedML et son utilisation pratique.

Configuration d'IntegratedML

0
0 36
Article Sylvain Guilbaud · Oct 25, 2024 7m read

Dans le paysage actuel des données, les activités commerciales sont confrontées à différents défis. L'un d'entre eux consiste à réaliser des analyses à partir d'une couche de données unifiée et harmonisée, accessible à tous les utilisateurs. Une couche capable de fournir les mêmes réponses aux mêmes questions, indépendamment du dialecte ou de l'outil utilisé. La plate-forme de données InterSystems IRIS répond à cette question en ajoutant la solution 'Adaptive Analytics' (Analyse adaptative) qui peut fournir cette couche sémantique unifiée. Il y a beaucoup d'articles dans DevCommunity sur l'utilisation de cette couche sémantique via des outils décisionnels. Cet article couvrira la partie concernant la façon de l'utiliser avec l'IA et également la façon d'obtenir des informations en retour. Allons-y étape par étape...

Qu'est-ce que la solution 'Adaptive Analytics'?

Vous pouvez facilement trouver une définition sur le site web de la Communauté de développeurs. En quelques mots, elle peut fournir des données sous une forme structurée et harmonisée à divers outils de votre choix pour une utilisation et une analyse ultérieures. Elle fournit les mêmes structures de données à différents outils décisionnels. Mais... elle peut également fournir les mêmes structures de données à vos outils IA/ML!

Adaptive Analytics a un composant supplémentaire appelé AI-Link qui construit ce pont entre l'IA et d'informatique décisionnelle.

Qu'est-ce que AI-Link exactement?

Il s'agit d'un composant Python conçu pour permettre une interaction programmatique avec la couche sémantique dans le but de rationaliser les étapes clés du flux de travail de l'apprentissage automatique (ML) (par exemple, l'ingénierie des fonctionnalités).

Avec AI-Link, vous pouvez:

  • accéder de manière programmatique aux fonctionnalités de votre modèle de données analytiques;
  • faire des requêtes, explorer les dimensions et les mesures;
  • alimenter des pipelines de ML; ... et renvoyer les résultats vers votre couche sémantique pour qu'ils soient à nouveau utilisés par d'autres (par exemple, par le biais de Tableau ou d'Excel).

Comme il s'agit d'une bibliothèque Python, elle peut être utilisée dans n'importe quel environnement Python. Y compris les Notebooks. Dans cet article, je vais donner un exemple simple pour atteindre une solution d'analyse adaptative à partir d'un Notebook Jupyter avec l'aide d'AI-Link.

Voici le référentiel git qui aura le Notebook complet à titre d'exemple : https://github.com/v23ent/aa-hands-on

**Conditions préalables **

Les étapes suivantes supposent que vous ayez rempli les conditions préalables ci-dessous:

  1. La solution 'Adaptive Analytics' est en place et fonctionne (avec IRIS Data Platform en tant qu'entrepôt de données).
  2. Jupyter Notebook est opérationnel
  3. La connexion entre 1. et 2. peut être établie

Étape 1: Configuration

Tout d'abord, installons les composants nécessaires dans notre environnement. Ainsi, nous téléchargerons quelques paquets nécessaires au bon déroulement des étapes suivantes. 'atscale' - c'est notre paquetage principal pour se connecter 'prophet' - c'est le paquet dont nous aurons besoin pour faire des prédictions.

pip install atscale prophet

Ensuite, nous devons importer des classes clés représentant certains concepts clés de notre couche sémantique. Client - c'est la classe que nous utiliserons pour établir une connexion avec Adaptive Analytics; Project - c'est la classe qui représente les projets à l'intérieur d'Adaptive Analytics; DataModel - c'est la classe qui représentera notre cube virtuel;

from atscale.client import Client
from atscale.data_model import DataModel
from atscale.project import Project
from prophet import Prophet
import pandas as pd

Étape 2: Connexion

Maintenant, nous devrions être prêts à établir une connexion avec notre source de données.

client = Client(server='http://adaptive.analytics.server', username='sample')
client.connect()

Continuez et spécifiez les détails de connexion de votre instance d'Adaptive Analytics. Lorsque l'on vous demande l'organisation, répondez dans la boîte de dialogue et entrez votre mot de passe de l'instance AtScale.

Une fois la connexion établie, vous devrez sélectionner votre projet dans la liste des projets publiés au serveur. Vous obtiendrez la liste des projets sous la forme d'une invite interactive et la réponse devrait être l'identifiant entier du projet. Le modèle de données est ensuite sélectionné automatiquement s'il est le seul.

project = client.select_project()   
data_model = project.select_data_model()

Étape 3: Explorez votre jeu de données

Il existe un certain nombre de méthodes préparées par AtScale dans la bibliothèque de composants AI-Link. Elles permettent d'explorer votre catalogue de données, d'interroger les données et même d'ingérer des données en retour. La documentation d'AtScale a une référence API complète décrivant tout ce qui est disponible. Voyons d'abord quel est notre jeu de données en appelant quelques méthodes de data_model :

data_model.get_features()
data_model.get_all_categorical_feature_names()
data_model.get_all_numeric_feature_names()

Le résultat devrait ressembler à ceci image

Après avoir examiné un peu la situation, nous pouvons interroger les données qui nous intéressent à l'aide de la méthode 'get_data'. Elle renverra un pandas DataFrame contenant les résultats de la requête.

df = data_model.get_data(feature_list = ['Country','Region','m_AmountOfSale_sum'])
df = df.sort_values(by='m_AmountOfSale_sum')
df.head()

Ce qui affichera votre trame de données: image

Préparons un ensemble de données et affichons-le rapidement sur le graphique

import matplotlib.pyplot as plt

# Nous enregistrons des ventes pour chaque date
dataframe = data_model.get_data(feature_list = ['Date','m_AmountOfSale_sum'])

#  Création d'un graphique linéaire
plt.plot(dataframe['Date'], dataframe['m_AmountOfSale_sum'])

# Ajout des étiquettes et d'un titre
plt.xlabel('Days')
plt.ylabel('Sales')
plt.title('Daily Sales Data')

# Affichage du graphique
plt.show()

Résultat: image

Étape 4: Prédiction

La prochaine étape consistera à tirer profit du pont AI-Link - faisons quelques prédictions simples!

# Chargement des données historiques pour l'entraînement du modèle
data_train = data_model.get_data(
    feature_list = ['Date','m_AmountOfSale_sum'],
    filter_less = {'Date':'2021-01-01'}
    )
data_test = data_model.get_data(
    feature_list = ['Date','m_AmountOfSale_sum'],
    filter_greater = {'Date':'2021-01-01'}
    )

Nous disposons ici de 2 jeux de données différents: pour entraîner notre modèle et pour le tester.

# Pour l'outil que nous avons choisi pour faire la prédiction 'Prophète' ,nous devrons spécifier 2 colonnes: 'ds' et 'y'
data_train['ds'] = pd.to_datetime(data_train['Date'])
data_train.rename(columns={'m_AmountOfSale_sum': 'y'}, inplace=True)
data_test['ds'] = pd.to_datetime(data_test['Date'])
data_test.rename(columns={'m_AmountOfSale_sum': 'y'}, inplace=True)

# Initialisation et ajustement du modèle Prophet
model = Prophet()
model.fit(data_train)

Et puis nous créons une autre trame de données pour accueillir notre prédiction et l'afficher sur le graphique

# Création d'une trame de données prochaine pour la prévision
future = pd.DataFrame()
future['ds'] = pd.date_range(start='2021-01-01', end='2021-12-31', freq='D')

# Prédictions
forecast = model.predict(future)
fig = model.plot(forecast)
fig.show()

Résultat: image

Étape 5: Réécriture

Une fois notre prédiction en place, nous pouvons la renvoyer à l'entrepôt de données et ajouter un agrégat à notre modèle sémantique afin de la refléter pour d'autres utilisateurs. La prédiction serait disponible via n'importe quel autre outil décisionnel pour les analystes décisionnels et les utilisateurs commerciaux. La prédiction elle-même sera placée dans notre entrepôt de données et y sera stockée.

from atscale.db.connections import Iris
db = Iris(
    username,
    host,
    namespace,
    driver,
    schema, 
    port=1972,
    password=None, 
    warehouse_id=None
    )

data_model.writeback(dbconn=db,
                    table_name= 'SalesPrediction',
                    DataFrame = forecast)

data_model.create_aggregate_feature(dataset_name='SalesPrediction',
                                    column_name='SalesForecasted',
                                    name='sum_sales_forecasted',
                                    aggregation_type='SUM')

Fin

C'est ça! Bonne chance avec vos prédictions!

0
0 86
Article Lorenzo Scalese · Avr 25, 2024 7m read

En tant que modèle linguistique d'IA, ChatGPT est capable d'effectuer une variété de tâches telles que traduire, écrire des chansons, répondre à des questions de recherche et même générer du code informatique. Avec ses capacités impressionnantes, ChatGPT est rapidement devenu un outil populaire pour diverses applications, des chatbots à la création de contenu.
Mais malgré ses capacités avancées, ChatGPT n'est pas en mesure d'accéder à vos données personnelles. Mais malgré ses capacités avancées, ChatGPT n'est pas en mesure d'accéder à vos données personnelles. Ainsi, dans cet article, je vais démontrer les étapes suivantes pour construire une IA ChatGPT personnalisée en utilisant le LangChain Framework:

  • Étape 1: Chargement du document 

  • Étape 2: Division du document en blocs

  • Étape 3: Utilisation de l'incorporation pour des blocs de données et leur conversion en vecteurs

  • Étape 4: Enregistrement des données dans la base de données de vecteurs

  • Étape 5: Obtention des données (question) de l'utilisateur et leur the intégration

  • Étape 6: Connexion à VectorDB et recherche sémantique

  • Étape 7: Récupération des réponses pertinentes basées sur les requêtes de l'utilisateur et leur envoi au LLM(ChatGPT)

  • Étape 8: Obtention d'une réponse de la part de LLM et renvoi de celle-ci à l'utilisateur

  REMARQUE : Veuillez lire mon article précédent LangChain – Unleashing the full potential of LLMs (LangChain - Libération du plein potentiel des LLM) pour obtenir plus de détails sur LangChain et sur la façon d'obtenir la clé API OpenAI

Alors, commençons
     

Étape 1: Chargement du document 

Tout d'abord, il faut charger le document. Nous allons donc importer PyPDFLoader pour le document PDF 

ClassMethod SavePDF(filePath) [ Language = python ]
{
#pour un fichier PDF, il faut importer PyPDFLoader à partir du framework langchainfrom langchain.document_loaders import PyPDFLoader
# pour un fichier CSV, il faut importer csv_loader# pour un fichier Doc, il faut importer UnstructuredWordDocumentLoader# Pour le document texte, il faut importer TextLoader#importation de l'os pour définir la variable d'environnementimport os
#attribution de la clé API OpenAI à une variable d'environnement 
os.environ['OPENAI_API_KEY'] = "apiKey"#Init du lanceur
loader = PyPDFLoader(filePath)   
#Chargement du document 
documents = loader.load()
return documents
}

Étape 2: Division du document en blocs

Les modèles linguistiques sont souvent limités par la quantité de texte qui peut leur être transmise. Il est donc nécessaire de les diviser en blocs moins volumineux. LangChain fournit plusieurs utilitaires pour ce faire.

L'utilisation d'un séparateur de texte (Text Splitter) peut également contribuer à améliorer les résultats des recherches dans les répertoires de vecteurs, car, par exemple, des blocs moins volumineux ont parfois plus de chances de correspondre à une requête. Tester différentes tailles de blocs (et leur chevauchement) est un exercice intéressant pour adapter les résultats à votre cas d'utilisation.

ClassMethod splitText(documents) [ Language = python ]
{
#Afin de diviser le document, il faut importer RecursiveCharacterTextSplitter du framework Langchain  from langchain.text_splitter import RecursiveCharacterTextSplitter
#Init du séparateur de texte, définition de la taille des blocs (1000) et du chevauchement. = 0
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
#Division du document en plusieurs blocs
texts = text_splitter.split_documents(documents)
return texts
}

Étape 3: Utilisation d'incorporation pour des blocs de données et leur conversion en vecteurs

Les incorporations (embeddings) de texte sont le cœur et l'âme des outils de Large Language Operations.. Techniquement, nous pouvons travailler avec des modèles linguistiques en langage naturel, mais le stockage et l'extraction du langage naturel sont très inefficaces. 

Pour améliorer l'efficacité, il faut transformer les données textuelles en formes vectorielles. Il existe des modèles ML dédiés à la création d'intégrations à partir de textes. Les textes sont convertis en vecteurs multidimensionnels. Une fois ces données incorporées, nous pouvons les regrouper, les trier, les rechercher, etc. Nous pouvons calculer la distance entre deux phrases pour connaître leur degré de parenté. Et le plus intéressant, c'est que ces opérations ne se limitent pas à des mots-clés comme dans les recherches traditionnelles dans les bases de données, mais capturent plutôt la proximité sémantique de deux phrases. Cela rend le système beaucoup plus puissant, grâce à l'apprentissage automatique.
 

Les modèles d'incorporation de texte reçoivent la saisie de texte et renvoient une liste de flottants (embeddings), qui sont la représentation numérique du texte saisi. Les embeddings permettent d'extraire des informations d'un texte. Ces informations peuvent ensuite être utilisées, par exemple, pour calculer les similitudes entre des textes (par exemple, des résumés de films).

Les modèles d'incorporation de texte reçoivent la saisie de texte et renvoient une liste de flottants

    ClassMethod getEmbeddings(query) [ Language = python ]
    {
    #Obtention d'un modèle d'embeddings à partir du framework Langchainfrom langchain.embeddings import OpenAIEmbeddings
    #Definition d'embedding
    embedding = OpenAIEmbeddings()
    return embedding
    }
    

Étape 4: Enregistrement des données dans la base de données de vecteurs

    ClassMethod saveDB(texts,embedding) [ Language = python ]
    {
    #Obtention de la base de données Chroma à partir de langchainfrom langchain.vectorstores import Chroma      
    # Incorporation et stockage des textes# La fourniture d'un répertoire persistant (persist_directory) permet de stocker les embeddings sur le disque# par exemple dans le dossier myData du chemin d'accès à l'application en cours
    persist_directory = "myData"
    vectordb = Chroma.from_documents(documents=texts, embedding=embedding, persist_directory=persist_directory)
    #sauvegarde du document au niveau local
    vectordb.persist()
    vectordb = None
    }
    

Étape 5: Obtention des données (question) de l'utilisateur et leur the intégration

    ClassMethod getVectorData(query) [ Language = python ]
    {
    #REMARQUE: Il faudrait avoir le même embedding utilisée lorsque nous avons sauvegardé des donnéesfrom langchain.embeddings import OpenAIEmbeddings
    #obtention d'embeddings
    embedding = OpenAIEmbeddings()
    #saisie des données de l'utilisateur (paramètre)
    query = query
    #La suite du code...

Étape 6: Connexion à VectorDB et recherche sémantique

#code continue....     from langchain.vectorstores import Chroma
 persist_directory = "myData"## À présent, il est possible de charger la base de données persistante à partir du disque et de l'utiliser comme d'habitude. 
 vectordb = Chroma(persist_directory=persist_directory, embedding_function=embedding)
 return vectordb
 }

Étape 7: Récupération des réponses pertinentes basées sur les requêtes de l'utilisateur et leur envoi au LLM(ChatGPT)

La mémoire de conversation est la façon dont un chatbot peut répondre à de multiples requêtes à la manière d'un chat. Elle assure une conversation cohérente et, sans elle, chaque requête serait traitée comme une entrée totalement indépendante, sans tenir compte des interactions passées.

LLM avec et sans une mémoire de conversation. Les cases bleues représentent les assistances de l'utilisateur et les cases grises représentent les réponses des LLM. Sans mémoire de conversation (à droite), les LLM ne peuvent pas répondre en utilisant la connaissance des interactions précédentes.

La mémoire permet le  Large Language Model (LLM) de se souvenir des interactions précédentes avec l'utilisateur. Par défaut, les LLMs sont  sans état — ce qui signifie que chaque requête entrante est traitée indépendamment des autres interactions. La seule chose qui existe pour un agent sans état est la saisie actuelle, rien d'autre.


Le modèle ConversationalRetrievalChain est un modèle d'IA conversationnelle conçu pour extraire des réponses pertinentes sur la base des requêtes de l'utilisateur. Il fait partie de la technologie de l'équipe de Langchain. Le modèle utilise une approche basée sur la récupération, où il recherche des réponses préexistantes dans une base de données pour trouver la réponse la plus appropriée à une requête donnée. Le modèle est entraîné sur un grand ensemble de conversations pour apprendre les schémas et le contexte afin de fournir des réponses précises et utiles.

ClassMethod retriveResponse(vectordb) [ Language = python ]
{
from langchain.llms import OpenAI
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
#La mémoire de conversation est la façon dont un chatbot peut répondre à de multiples requêtes.
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
#Le ConversationalRetrievalChain est un modèle d'IA conversationnelle conçu pour extraire des réponses pertinentes sur la base des requêtes de l'utilisateur.
qa = ConversationalRetrievalChain.from_llm(OpenAI(temperature=0), vectordb.as_retriever(), memory=memory)
return qa
}


Étape 8: Obtention d'une réponse de la part de LLM et renvoi de celle-ci à l'utilisateur 

ClassMethod getAnswer(qa) [ Language = python ]
{
#Obtention d'une réponse de la part de LLM et renvoi de celle-ci à l'utilisateur
getAnswer = qa.run(query)
return getAnswer
}

Pour plus de détails et de fonctionnalités, veuillez consulter mon application irisChatGPT 

Vidéo connexe

<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/h9JoqbUKFBk" title="YouTube video player" width="560"></iframe>

Je vous remercie

1
0 313
Annonce Irène Mykhailova · Avr 10, 2024

Salut la Communauté,

Nous avons des nouvelles excitantes ! Le nouveau concours de programmation en ligne InterSystems dédié à l'IA générative, à la recherche de vecteurs et au Machine Learning démarre très bientôt !

🏆 Concours InterSystems Vector Search, GenAI et ML 🏆

Durée : avril 22 - mai 19, 2024

Prix : $14,000


0
1 71
Article Lorenzo Scalese · Sept 27, 2023 16m read

Cette publication soutient la démonstration au Global Summit 2023 "Demos and Drinks" avec des détails très probablement perdus dans le bruit de l'événement. Il s'agit d'une démonstration sur la façon dont on peut utiliser les capacités FHIR SQL d'InterSystems du Serveur FHIR avec la solution Super Awesome Identity and Resolution, Zingg.ai pour détecter les enregistrements en double dans votre référentiel FHIR, et l'idée de base derrière la remédiation de ces ressources avec le PID^TOO|| en cours de construction actuellement inscrit dans le programme Incubateur d'InterSystems. Si vous êtes dans

0
0 68
Article Iryna Mykhailova · Mai 10, 2023 6m read

De nombreux facteurs influencent la qualité de vie des gens, et l'un des plus importants est le sommeil. La qualité de notre sommeil détermine notre capacité à fonctionner pendant la journée et affecte notre santé mentale et physique. Un sommeil de bonne qualité est essentiel à notre santé et à notre bien-être général. Par conséquent, en analysant les indicateurs précédant le sommeil, nous pouvons déterminer la qualité de notre sommeil. C'est précisément la fonctionnalité de l'application Sheep's Galaxy.

Sheep's Galaxy est un exemple d'application qui fonctionne avec les technologies IntegratedML et IRIS Cloud SQL d'InterSystems et qui fournit à l'utilisateur un outil d'analyse et d'amélioration de la qualité du sommeil. L'analyse du sommeil prend en compte des facteurs tels que les niveaux de bruit, l'éclairage de la pièce, la durée du sommeil, la consommation de caféine, etc., ce qui permet à l'utilisateur de reconsidérer ses habitudes en matière de sommeil et de créer des conditions optimales pour le sommeil à l'avenir.

Présentation vidéo :

https://www.youtube.com/watch?v=eZ9Wak831x4&ab_channel=MariaGladkova

L'application est basée sur les technologies suivantes :

Partie Frontend :

Pour construire cette application, nous avons utilisé la structure Angular. Il nous a aidé à créer une application simple à page unique. Nous avons utilisé Angular v15, et tous les composants Angular ont été implémentés en tant que standalones pour rationaliser l'expérience de création. Nous n'avons pas utilisé de modules Angular et c'est une bonne pratique pour faire évoluer une application dans le futur si nécessaire. Nous avons également utilisé l'architecture des composants intelligents (Smart Component Architecture) - tous les composants de notre application frontale sont divisés en composants "intelligents" et "muets". Ce concept nous aide à séparer le code de logique métier et le code de présentation entre ces composants. Toute la Logique métier et les demandes adressées au serveur sont conservées dans les services isolés. Pour traiter les données de notre backend, nous utilisons RxJS - une bibliothèque pour composer des programmes asynchrones et basés sur des événements en utilisant des séquences observables. Pour styliser notre application, nous avons utilisé Angular Material - il s'agit d'une bibliothèque de composants d'interface utilisateur que les développeurs peuvent utiliser dans leurs projets Angular pour accélérer le développement d'interfaces utilisateur élégantes et cohérentes. Cette bibliothèque offre un grand nombre de composants d'interface utilisateur réutilisables et magnifiques - nous en avons ajouté quelques-uns comme les cartes, les entrées, les tableaux de données, les sélecteurs de date, et bien d'autres encore. Nous présentons ci-dessous une vue d'ensemble du flux de travail typique d'un utilisateur. Tout d'abord, l'utilisateur passe par le processus d'enregistrement, s'il l'utilise pour la première fois, ou par l'écran d'autorisation.

image

À l'aide de cette application, l'utilisateur entre des renseignements sur son sommeil, tels que son niveau d'activité pendant la journée, le nombre de tasses de café, son confort de sommeil, son niveau de stress et la quantité d'émotions positives, ainsi que la lumière de la pièce et l'heure du coucher.

image

Après chaque saisie de données, l'utilisateur reçoit une notification sur la qualité de son sommeil. Ces données sont ensuite analysées à l'aide d'algorithmes d'apprentissage automatique afin de fournir aux utilisateurs des informations sur leurs habitudes de sommeil.

image

Partie Backend :

Fastapi est un framework python basé sur deux technologies : Pydantic et Starlette. Il a les fonctionnalités suivantes :

  • Il est basé sur des standards ouverts : OpenAPI, schéma JSON, OAuth2 ;
  • Documentation automatique de l'API en swagger ;
  • Implémentation des dépendances ;
  • Il utilise les fonctionnalités de python moderne : annotation de type, asyncio ;
  • Il supporte le code synchrone et asynchrone ;

La structure du projet consiste en des routeurs avec des points d'extrémité, des modèles pour chaque entité et des services de traitement.

Chaque point d'extrémité apparaît dans la documentation atomique à /docs et les champs des points d'extrémité ont une relation avec les modèles de données dans la base de données.

image

Les modèles pydantiques valident automatiquement les données entrantes et sortantes.

image

Le processus de traitement des données des utilisateurs repose sur le protocole, qui vous permet de traiter les données en toute sécurité.

image

Le processus d'interaction avec la base de données est mis en œuvre par la connexion SQL d'IRIS à l'aide de DB API.

image

IRIS Cloud SQL avec IntegratedML :

Tout d'abord, vous devez vous connecter au portail InterSystems Cloud Services. Vous devez ensuite créer un nouveau déploiement IRIS Cloud SQL. Veillez à inclure IntegratedML lorsque vous créez un nouveau déploiement. Lorsqu'il est prêt, vous pouvez obtenir les paramètres de connexion à utiliser dans docker-compose.yml :

image

En ouvrant le menu "IntegratedML Tools", vous avez accès à la création, à l'entraînement et à la validation de votre modèle, ainsi qu'à la possibilité de générer des prédictions sur un champ sélectionné dans le tableau de votre modèle.

image

Dans notre application, nous prédisons la qualité du sommeil sur la base des données de l'utilisateur. Pour ce faire, nous remplissons les champs de la section Prédiction comme suit :

image

Dans la requête générée, le champ prediction contient une prédiction de la qualité du sommeil, le champ probability_quality (probabilité de qualité) contient la probabilité que le sommeil soit " de bonne qualité ".

Liens :

Pour en savoir plus sur notre projet ou l'utiliser comme modèle pour vos futurs travaux : https://openexchange.intersystems.com/package/Sheep%E2%80%99s-Galaxy

Remerciements :

Notre équipe tient à remercier InterSystems et Banksia Global de nous avoir donné l'occasion de travailler avec une technologie de pointe sur des questions importantes.

Développeurs du projet :

0
0 53
Article Guillaume Rongier · Mai 8, 2023 9m read

Bonjour à la communauté,
Dans cet article, je vais présenter mon application iris-mlm-explainer

Cette application web se connecte au service SQL d'InterSystems Cloud pour créer, entraîner, valider et prédire des modèles d'apprentissage automatique, faire des Prédictions et afficher un tableau de bord de tous les modèles entraînés avec une explication du fonctionnement d'un modèle d'apprentissage automatique ajusté. Le tableau de bord fournit des graphiques interactifs sur les performances du modèle, les importances des caractéristiques, les contributions des caractéristiques aux prédictions individuelles, les graphiques de dépendance partielle, les valeurs SHAP (interaction), la visualisation des arbres de décision individuels, etc.

Conditions préalables

  • Vous devez avoir un compte à SQL d'InterSystems Cloud
  • Vous devez avoir <a book="" fr="" getting-started-installing-git="" git-scm.com="" https:="" v2="">Git</a> installé localement.
  • Vous devez avoir <a downloads="" https:="" www.python.org="">Python3</a> installé localement.  

Démarrage

Nous allons suivre les étapes suivantes pour créer et afficher le tableau de bord explicatif d'un modèle :

  • Etape 1 : Fermeture/git pull du référentiel

  • Étape 2 : Connexion au portail de service SQL d'InterSystems Cloud

    • Étape 2.1 : Ajout et gestion de fichiers
    • Étape 2.2 : Importation des fichiers DDL et des fichiers de données
    • Étape 2.3 : Création du modèle
    • Étape 2.4 : Entraînement du modèle
    • Étape 2.5 : Validation du modèle
    • Étape 3 : Activation de l'environnement virtuel Python
  • Étape 4 : Exécution de l'application Web pour la prédiction

  • Étape 5 : Exploration du tableau de bord explicatif

Etape 1 : Fermeture/git Extraction du référentiel

Commençons donc par la première étape

Créer un dossier et Cloner/utiliser le git pull pour le référentiel dans n'importe quel répertoire local.

git clone https://github.com/mwaseem75/iris-mlm-explainer.git

 

Étape 2 : Connexion au portail de service SQL d'InterSystems Cloud

Connectez-vous au portail InterSystems Cloud Service Portal
image

 

 

Sélectionner le déploiement en cours

image

 

Étape 2.1 : Ajout et gestion des fichiers

Cliquez sur Ajout et gestion de fichiers (Add and Manage Files)

image

Le référentiel contient les fichiers USA_Housing_tables_DDL.sql(DDL pour créer les tables), USA_Housing_train.csv(données d'entraînement), et USA_Housing_validate.csv(pour la validation) dans le dossier datasets. Sélectionnez le bouton de téléchargement pour ajouter ces fichiers.

AddFiles

Étape 2.2 : Importation des fichiers DDL et des fichiers de données

Cliquez sur Importation de fichiers, puis sur le bouton radio Instruction(s) DDL ou DML, puis sur le bouton suivant.

ImportDDL

Cliquez sur le bouton radio Intersystems IRIS et cliquez ensuite sur le bouton suivant

IsIRIS

Sélectionnez le fichier USA_Housing_tables_DDL.sql et appuyez sur le bouton d'importation de fichiers.

ImportFileDDL

Cliquez sur le bouton d'importation "Import" dans la boîte de dialogue de confirmation pour créer le tableau.

importconfirm

###importDone

Cliquez sur le bouton des outils de requête SQL (SQL Query tools) pour vérifier que les tableaux sont créés.

###checkTblCreated

Importez des fichiers de données

Cliquez sur Importation de fichiers (Import files), puis sur le bouton radio Données CSV (CSV data), et enfin sur le bouton suivant.

csv1

Selectionnez le fichier USA_Housing_train.csv et cliquez sur le bouton suivant

###csv2

 

Sélectionnez le fichier USA_Housing_train.csv dans la liste déroulante, cochez les cases d'importation de lignes en tant que ligne d'en-tête et de noms de champs dans la ligne d'en-tête correspondant aux noms de colonnes dans le tableau sélectionné, puis cliquez sur Importation de fichiers.

csv3

cliquer sur "importation" dans la boîte de dialogue de confirmation

csv4

Assurez-vous que 4000 lignes sont mises à jour

csv5

Procédez de la même manière pour importer le fichier USA_Housing_validate.csv qui contient 1500 enregistrements.

csv6

Étape 2.3 : Création du modèle

Cliquez sur les outils IntegratedM et sélectionnez Créer un panneau (Create Panel).

Saisissez USAHousingPriceModel dans le champ de nom du modèle (Model Name), sélectionnez le tableau usa_housing_train et Prix dans la liste déroulante des champs à prédire (Field to predict). Cliquez sur le bouton "Création du modèle" pour créer le modèle.

createModel

 

Étape 2.4 : Entraînement du modèle

sélectionnez le panneau d'entraînement (Train Panel), sélectionnez USAHousingPriceModel dans la liste déroulante du modèle à entraîner et saisissez USAHousingPriceModel_t1 dans le champ du nom du modèle d'entraînement (Train Model Name)

###TRAIN1

Le modèle sera entraîné une fois l'état de fonctionnement (Run Status) achevé

###TRAIN2

 

Étape 2.5 : Validation du modèle

Sélectionnez le panneau de validation (Validate Panel), sélectionnez USAHousingPriceModel_t1 dans le modèle entraîné pour valider la liste déroulante, sélectionnez usa_houseing_validate dans le tableau pour valider le modèle à partir de la liste déroulante et cliquez sur le bouton de validation du modèle.

###image

Cliquez sur affichage des mesures de validation pour visualiser les mesures.

showValidation

Cliquez sur l'icône graphique pour afficher le graphique Prédiction VS Réalité.

validationChart

 

Étape 3 : Activation de l'environnement virtuel Python

Le référentiel contient déjà un dossier d'environnement virtuel python (venv) avec toutes les bibliothèques nécessaires.

Il suffit d'activer l'environnement
Pour Unix ou MacOS :

&lt;span class="hljs-meta">$&lt;/span>&lt;span class="bash"> &lt;span class="hljs-built_in">source&lt;/span> venv/bin/activate&lt;/span>

Pour Windows:

venv\scripts\activate

Étape 4 : Définir les paramètres de connexion à InterSystems SQL Cloud

Le référentiel contient le fichier config.py. Il suffit de l'ouvrir et de le paramétrer
image
Mettez les mêmes valeurs que celles utilisées dans InterSystems SQL Cloud
image

 

Étape 4 : Exécution de l'application Web pour la prédiction

Exécutez la commande suivante dans l'environnement virtuel pour démarrer notre application principale

python app.py

###image

Pour démarrer l'application, naviguez jusqu'à http://127.0.0.1:5000/

image

Entrez l'âge de la maison, le nombre de pièces, le nombre de chambres et la population de la région pour obtenir la prédiction

image

Étape 5 : Exploration du tableau de bord explicatif

Enfin, exécutez la commande suivante dans l'environnement virtuel pour démarrer notre application principale

python expdash.py

imageimage
image

Pour démarrer l'application, naviguez jusqu'à http://localhost:8050/image

L'application répertorie tous les modèles entraînés ainsi que notre modèle USAHousingPriceModel. Cliquez sur "aller au panneau de bord" ("go to dashboard") pour voir l'explication du modèle.

Importance des fonctionnalités. Quelles sont les fonctionnalités ayant eu l'impact le plus important ?
image

Mesures quantitatives de la performance des modèles : dans quelle mesure la valeur prédite est-elle proche de la valeur observée ?
image

Prédiction et Comment chaque fonctionnalité a-t-elle contribué à la prédiction ?
image

Ajustez les valeurs des fonctionnalités pour modifier la prédiction
image

Sommaire des SHAPs, Classement des caractéristiques par valeurs de SHAPs
image

Sommaire des interactions, classement des fonctionnalités par valeur d'interaction de SHAP
image

Arbres de décision, affichage des arbres de décision individuels dans la forêt aléatoire
image

Merci

0
0 47
Article Irène Mykhailova · Mai 4, 2023 6m read

Exemple d'utilisation de la base de données FHIR d'InterSystems IRIS for Health pour effectuer de modèles ML via InterSystems IRIS IntegratedML

Description

IntegratedML est une fonctionnalité intéressante pour former/tester et déployer des modèles ML. FHIR est un standard puissant pour l'interopérabilité des informations de santé. Ce projet vise à montrer comment utiliser les outils IRIS/IRIS for Health, par exemple les transformations DTL pour préparer les données FHIR à l'application de modèles ML dans IntegratedML. Voici quelques applications potentielles des idées présentées dans ce projet :

0
0 81
Article Irène Mykhailova · Mai 2, 2023 2m read

En discutant avec un de mes amis, spécialiste du Machine Learning @Renato Banzai , il a évoqué l'un des plus grands défis pour les entreprises aujourd'hui : le déploiement du ML/IA dans des environnements réels.

InterSystems IRIS propose la solution "IntegratedML". IntegratedML est une fonctionnalité très utile pour entraîner, tester et déployer des modèles de ML/IA.

La partie la plus difficile dans la création de ML/IA est de faire le traitement des données, de les nettoyer et de les rendre fiables.

C'est là que nous pouvons tirer parti de la puissante norme FHIR !

L'idée du projet montre comment nous pouvons créer/entraîner/valider des modèles MI/IA avec FHIR et les utiliser avec des données provenant de différentes sources.

0
0 57
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 12, 2023 4m read

Cet article est le deuxième d'une série expliquant comment créer un système d'apprentissage automatique de bout en bout.

Exploration des données

L'Intersystème IRIS dispose déjà de ce dont nous avons besoin pour explorer les données : un moteur SQL ! Pour les personnes qui ont l'habitude d'explorer des données dans des fichiers
csv ou des fichiers texte, cela pourrait aider à accélérer cette étape. Fondamentalement, nous explorons toutes les données pour comprendre l'intersection (jointures), ce qui devrait permettre de créer un jeu de données préparé pour être utilisé par un algorithme d'apprentissage automatique.

Tableau d'articles ( Fourni par l'équipe Intersystems )

image

Tableaude balises ( Fourni par l'équipe Intersystems )

image

Notre défi consiste à classer un article avec les bonnes balises. Et nous avons un tas d'articles et toutes les balises avec description. Il existe plusieurs techniques de classification, mais les cas les plus courants de classification utilisent des données structurées ! Un article, un long texte n'est pas exactement structuré de ce point de vue.

L'apprentissage automatique fonctionne la plupart du temps avec des NOMBRES - Faites avec !

Oui ! Même le modèle de données le plus normalisé contient du texte, mais lorsque nous devons utiliser des algorithmes de ML, nous devons trouver une solution pour convertir tous les textes en nombres. Mais n'oubliez pas que les *données non structurées ne prendront pas les nombres prêts à être utilisés dans un modèle de classification. Il est temps de...

Ingénierie des caractéristiques

Dans cette étape, nous convertissons le texte, les nombres, les éléments non structurés et le chaos dans une matrice (la plupart du temps)... oui, cet élément de vos cours d'algèbre d'autrefois. Si nous avons un tableau qui ressemble déjà à une matrice, vous aurez probablement moins de travail que nous ! Nous avons un grand texte avec des tailles, des formes et des mots différents...

Sac de mots

L'une des façons de transformer un texte long en une matrice est le sac de mots :

expression
Nicole devrait acheter une voiture
Jack devrait vendre son bateau
 [Nicole, Jack, devrait, acheter, vendre, une, son, voiture, bateau]
 [1     ,    0,      1,   1,    0, 1,   0,   1,    0]
 [0     ,    1,      1,   0,    1, 0,   1,   0,    1]

Ce n'est qu'un petit exemple. Mais vous pouvez constater que plus il y a de mots, plus la matrice est grande. Heureusement, nous disposons de nombreux composants pour vous aider à créer des sacs de mots. Dans ce cas, j'ai utilisé les composants de Sklearn pour le faire.

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.preprocessing import MultiLabelBinarizer

ml_bin = MultiLabelBinarizer(classes=all_tags)
matrix_y = ml_bin.fit_transform(a_dataframe)

count_vec = CountVectorizer(ngram_range=(1,1), tokenizer=tokenize, strip_accents='unicode', stop_words=stop_words)
matrix_x = count_vec.fit_transform(a_dataframe)

Après avoir exécuté les méthodes ci-dessus, nous disposons d'un vectoriseur que nous devrons conserver tout le temps que nous voulons prédire. Si nous changeons le vectoriseur, nous risquons de perturber les matrices et rien ne devrait fonctionner par la suite.

Est-ce que je vous ai déjà dit que nous ne devions utiliser que des chiffres ?

Il y a un autre problème ! Pour certains algorithmes, la taille du nombre peut perturber vos intentions. En bref, si un élément de la matrice a une valeur de 1 et qu'un autre élément a une valeur de 987, certains algorithmes pourraient interpréter cela comme l'importance de l'élément et prendre la mauvaise direction.

Algorithmes de classification ML

Il existe de nombreux documents à lire sur les algorithmes de classification, vous pouvez commencer par cet article : https://machinelearningmastery.com/types-of-classification-in-machine-learning/

Article suivant : stratégie de formation (pour les données, oubliez les GIMS)

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

0
0 55
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 31, 2023 22m read

Mots-clés:  IRIS, IntegratedML, apprentissage automatique, Covid-19, Kaggle 

Continuation de la précédente Partie I ... Dans la partie I, nous avons parcouru les approches ML traditionnelles sur ce jeu de données Covid-19 sur Kaggle.

Dans cette partie II, nous allons exécuter les mêmes données et la même tâche, dans sa forme la plus simple possible, à travers IRIS integratedML qui est une interface SQL agréable et élégante pour les options AutoML du backend. Cette interface utilise le même environnement. 

Approche IntegratedML ?

Comment charger des données dans IRIS

integredML-demo-template a défini plusieurs façons de charger des données dans IRIS. Par exemple, je peux définir une classe IRIS personnalisée spécifique à ce fichier xls au format CSV, puis le charger dans un tableau IRIS. Cela permet un meilleur contrôle pour les volumes de données importants. 

Cependant, dans cet article, j'opte pour une méthode simplifiée et légère, en me contentant de charger le jeux des données dans un tableau IRIS via une fonction Python personnalisée que j'ai créée.  Cela nous permet de sauvegarder à tout moment les différentes étapes des dataframes brutes ou traitées dans IRIS, pour des comparaisons similaires avec l'approche ML précédente.

def to_sql_iris(cursor, dataFrame, tableName, schemaName='SQLUser', drop_table=False ):
        """"
        Insertion dynamique d'un dataframe dans un tableau IRIS via SQL par "excutemany"

        Inputs:
            cursor:      Curseur Python JDBC ou PyODBC à partir d'une connexion DB valide et établie
            dataFrame:   Pandas dataframe
            tablename:   Tableau SQL IRIS à créer, à insérer ou à modifier
            schemaName:  IRIS schemaName, par défaut pour "SQLUser"
            drop_table:  Si le tableau existe déjà, le supprimer et le recréer si True ; sinon, le sauvegarder et l'appliquer
        Output:
            True en cas de succès ; False en cas d'exception.
        """
        if drop_table:   
            try:                 
                curs.execute("DROP TABLE %s.%s" %(schemaName, tableName))
            except Exception:
                pass

        try:
            dataFrame.columns = dataFrame.columns.str.replace("[() -]", "_")
            curs.execute(pd.io.sql.get_schema(dataFrame, tableName))
        except Exception:
            pass

        curs.fast_executemany = True
        cols = ", ".join([str(i) for i in dataFrame.columns.tolist()])
        wildc =''.join('?, ' * len(dataFrame.columns))
        wildc = '(' + wildc[:-2] + ')'
        sql = "INSERT INTO " + tableName + " ( " + cols.replace('-', '_') + " ) VALUES" + wildc
        #print(sql)
        curs.executemany(sql, list(dataFrame.itertuples(index=False, name=None)) )
        return True

Configuration de la connexion Python JDBC

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 jaydebeapi
url = "jdbc:IRIS://irisimlsvr:51773/USER"
driver = 'com.intersystems.jdbc.IRISDriver'
user = "SUPERUSER"
password = "SYS"
jarfile = "./intersystems-jdbc-3.1.0.jar"conn = jaydebeapi.connect(driver, url, [user, password], jarfile)
curs = conn.cursor()

 

Définition du point de départ des données

Pour les comparaisons à l'identique, j'ai commencé par le dataframe après les sélections de caractéristiques dans le post précédent (dans la section "Sélection de caractéristiques - Sélection finale"), où "DataS" est le dataframe exact que nous commençons ici.

data = dataS
data = pd.get_dummies(data)
data.ÂGE_AU-DESSUS65 = data.ÂGE_AU-DESSUS65.astype(int)
data.ICU = data.ICU.astype(int)
data_new = data
data_new
<th>
  ÂGE_AU-DESSUS65
</th>

<th>
  GENRE
</th>

<th>
  HTN
</th>

<th>
  AUTRES
</th>

<th>
  CALCIUM_MÉDIAN
</th>

<th>
  CALCIUM_MIN
</th>

<th>
  CALCIUM_MAX
</th>

<th>
  CRÉATININE_MÉDIANE
</th>

<th>
  CRÉATININE_MOYENNE
</th>

<th>
  CRÉATININE_MIN
</th>

<th>
  ...
</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>
  USI
</th>

<th>
  FENÊTRE_0-2
</th>

<th>
  FENÊTRE_2-4
</th>

<th>
  FENÊTRE_4-6
</th>

<th>
  FENÊTRE_6-12
</th>

<th>
  FENÊTRE_AU-DESSUS_12
</th>
<td>
  1
</td>

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
</td>

<td>
  1
</td>

<td>
</td>

<td>
</td>

<td>
</td>

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

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
</td>

<td>
</td>

<td>
  1
</td>

<td>
</td>

<td>
</td>

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

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.183673
</td>

<td>
  0.183673
</td>

<td>
  0.183673
</td>

<td>
  -0.868365
</td>

<td>
  -0.868365
</td>

<td>
  -0.868365
</td>

<td>
  ...
</td>

<td>
  -0.817800
</td>

<td>
  -0.719147
</td>

<td>
  -0.771327
</td>

<td>
  -0.886982
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
  1
</td>

<td>
</td>

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

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  ...
</td>

<td>
  -0.817800
</td>

<td>
  -0.719147
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
  1
</td>

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

<td>
  0.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.326531
</td>

<td>
  0.326531
</td>

<td>
  0.326531
</td>

<td>
  -0.926398
</td>

<td>
  -0.926398
</td>

<td>
  -0.926398
</td>

<td>
  ...
</td>

<td>
  -0.230462
</td>

<td>
  0.096774
</td>

<td>
  -0.242282
</td>

<td>
  -0.814433
</td>

<td>
  1
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
</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>
</td>

<td>
  1.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
</td>

<td>
  1
</td>

<td>
</td>

<td>
</td>

<td>
</td>

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

<td>
  1.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.244898
</td>

<td>
  0.244898
</td>

<td>
  0.244898
</td>

<td>
  -0.934890
</td>

<td>
  -0.934890
</td>

<td>
  -0.934890
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
</td>

<td>
</td>

<td>
  1
</td>

<td>
</td>

<td>
</td>

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

<td>
  1.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
  1
</td>

<td>
</td>

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

<td>
  1.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  0.330359
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  -0.891078
</td>

<td>
  ...
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
  -1.000000
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
  1
</td>

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

<td>
  1.0
</td>

<td>
  0.0
</td>

<td>
  1.0
</td>

<td>
  0.306122
</td>

<td>
  0.306122
</td>

<td>
  0.306122
</td>

<td>
  -0.944798
</td>

<td>
  -0.944798
</td>

<td>
  -0.944798
</td>

<td>
  ...
</td>

<td>
  -0.763868
</td>

<td>
  -0.612903
</td>

<td>
  -0.551337
</td>

<td>
  -0.835052
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
</td>

<td>
</td>

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

1925 lignes × 62 colonnes

Ce qui précède indique que nous disposons de 58 caractéristiques sélectionnées plus 4 autres caractéristiques converties à partir de la colonne non numérique précédente ("FENÊTRE").  

Sauvegarder les données dans le tableau IRIS

Nous utilisons la fonction to_sql_iris ci-dessus pour sauvegarder les données dans le tableau IRIS "CovidPPP62" :

iris_schema = 'SQLUser'
iris_table = 'CovidPPP62'to_sql_iris(curs, data_new, iris_table, iris_schema, drop_table=True) df2 = pd.read_sql("SELECT COUNT(*) from %s.%s" %(iris_schema, iris_table),conn)
display(df2)
<th>
  Aggregate_1
</th>
<td>
  1925
</td>
 Sauvegarder les données dans le tableau IRIS

Définissez ensuite le nom de la vue de formation, le nom du modèle et la colonne cible de la formation, qui est ici " USI ".  

dataTable = iris_table
dataTableViewTrain = dataTable + 'Train1'
dataTablePredict = dataTable + 'Predict1'
dataColumn =  'ICU'
dataColumnPredict = 'ICUPredicted'
modelName = "ICUP621" #choisir un nom - doit être unique du côté serveur

Nous pouvons ensuite diviser les données en une Vue de formation (1700 lignes) et une Vue de test (225 lignes). Nous ne sommes pas obligés de faire cela dans Integrated ML ; c'est juste à des fins de comparaison avec l'article précédent.

curs.execute("CREATE VIEW %s AS SELECT * FROM %s WHERE ID&lt;=1700" % (dataTableViewTrain, dataTable))df62 = pd.read_sql("SELECT * from %s" % dataTableViewTrain, conn)
display(df62)
print(dataTableViewTrain, modelName, dataColumn)
CovidPPP62Train1 ICUP621 ICU

 

Formation du modèle à l'aide de l'AutoML par défaut d'IntegratedML

curs.execute("CREATE MODEL %s PREDICTING (%s)  FROM %s" % (modelName, dataColumn, dataTableViewTrain))curs.execute("TRAIN MODEL %s FROM %s" % (modelName, dataTableViewTrain))df3 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_TRAINED_MODELS", conn)
display(df3)
<th>
  NOM_DU_MODÈLE
</th>

<th>
  NOM_DU_MODÈLE_FORMÉ
</th>

<th>
  FOURNISSEUR
</th>

<th>
  HORODATAGE_FORMÉ
</th>

<th>
  TYPE_DU_MODÈLE
</th>

<th>
  MODÈLE_INFO
</th>
<td>
  USIP621
</td>

<td>
  USIP6212
</td>

<td>
  AutoML
</td>

<td>
  2020-07-22 19:28:16.174000
</td>

<td>
  classification
</td>

<td>
  ModelType:Random Forest, Paquet:sklearn, Prob...
</td>
 
9

Ainsi, nous pouvons voir que le résultat montre qu'IntegratedML a automatiquement choisi "ModelType" comme étant "Random Forest" (forêt aléatoire), et traite le problème comme une tâche de "Classification".  C'est exactement ce que nous avons obtenu après les longues comparaisons de modèles et les sélections par boîte à moustaches, ainsi que le long réglage des paramètres du modèle par quadrillage, etc. dans l'article précédent, n'est-ce pas ?

Remarque: le SQL ci-dessus est le strict minimum selon la syntaxe d'IntegratedML. Je n'ai pas spécifié d'approche de formation ou de sélection de modèle, et je n'ai pas défini de plateforme de ML. Tout a été laissé à la décision de l'IML, qui a réussi à mettre en œuvre sa stratégie de formation interne, avant de se contenter d'un modèle raisonnable avec des résultats finaux corrects. Je dirais que cela a dépassé mes attentes.   

Effectuons un rapide test de comparaison du modèle actuellement entraîné sur notre ensemble de test réservé.

Prédiction des résultats sur la base de données de test

Nous avons utilisé 1700 lignes pour la formation. Ci-dessous, nous créons une vue des données de test avec les 225 lignes restantes, et nous exécutons SELECT PREDICT sur ces enregistrements. Nous sauvegarderons le résultat prédit dans 'dataTablePredict', et le chargerons dans 'df62' en tant que data frame.

dataTableViewTest = "SQLUSER.DTT621"
curs.execute("CREATE VIEW %s AS SELECT * FROM %s WHERE ID > 1700" % (dataTableViewTest, dataTable))curs.execute("DROP TABLE %s" % dataTablePredict )
curs.execute("Create Table %s (%s VARCHAR(100), %s VARCHAR(100))" % (dataTablePredict, dataColumnPredict, dataColumn))curs.execute("INSERT INTO %s  SELECT PREDICT(%s) AS %s, %s FROM %s" % (dataTablePredict, modelName, dataColumnPredict, dataColumn, dataTableViewTest)) df62 = pd.read_sql("SELECT * from %s ORDER BY ID" % dataTablePredict, conn)
display(df62)

Nous n'avons pas besoin de calculer manuellement sa matrice de confusion. Il s'agit simplement d'une comparaison :

TP = df62[(df62['ICUPredicted'] == '1') & (df62['ICU']=='1')].count()['ICU']  
TN = df62[(df62['ICUPredicted'] == '0') & (df62['ICU']=='0')].count()["ICU"]
FN = df62[(df62['ICU'] == '1') & (df62['ICUPredicted']=='0')].count()["ICU"]
FP = df62[(df62['ICUPredicted'] == '1') & (df62['ICU']=='0')].count()["ICU"]
print(TP, FN, '\n', FP, TN)
precision = (TP)/(TP+FP)
recall = (TP)/(TP+FN)
f1 = ((precision*recall)/(precision+recall))*2
accuracy = (TP+TN) / (TP+TN+FP+FN)
print("Precision: ", precision, " Recall: ", recall, " F1: ", f1, " Accuracy: ", accuracy)
34 20
 8 163
Précision:  0.8095238095238095  rappel:  0.6296296296296297  F1:  0.7083333333333334  Exactitude:  0.8755555555555555

Nous pouvons également utiliser la syntaxe IntegratedML pour obtenir sa matrice de confusion intégrée :

# valider les données de test
curs.execute("VALIDATE MODEL %s FROM %s" % (modelName, dataTableViewTest) )  
df5 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS", conn)
df6 = df5.pivot(index='VALIDATION_RUN_NAME', columns='METRIC_NAME', values='METRIC_VALUE')
display(df6)
<th>
  Exactitude
</th>

<th>
  Mesure F
</th>

<th>
  Précision
</th>

<th>
  Rappel
</th>
<th>
   
</th>

<th>
   
</th>

<th>
   
</th>

<th>
   
</th>
<td>
  0.88
</td>

<td>
  0.71
</td>

<td>
  0.81
</td>

<td>
  0.63
</td>
<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>

<td>
  ...
</td>
NOM_MÉTRIQUE
NOM_DE_L'EXÉCUTION_DE_LA_VALIDATION
USIP62121
...

Si l'on compare avec le "Résultat original" de la section " Exécuter une formation de base en LR " dans la partie I, le résultat ci-dessus présente un rappel de 63 % contre 57 %, et une exactitude de 88 % contre 85 %. Il s'agit donc d'un meilleur résultat avec IntegratedML.

Former à nouveau IntegratedML sur des données de formation rééquilibrées via SMOTE

Le test ci-dessus a été effectué sur des données déséquilibrées, dans lesquelles le rapport entre les patients admis en USI et les patients non admis est de 1:3. Donc, comme dans l'article précédent, nous allons simplement effectuer un SMOTE pour que les données soient équilibrées, puis nous allons réexécuter le pipeline IML ci-dessus.

'X_train_res' and 'y_train_res' sont des dataframes après SMOTE de la Partie I précédente dans sa section " Exécuter une formation de base en LR ". 

df_x_train = pd.DataFrame(X_train_res)
df_y_train = pd.DataFrame(y_train_res)
df_y_train.columns=['ICU']df_smote = pd.concat([df_x_train, df_y_train], 1)
display(df_smote)
iris_schema = 'SQLUser'
iris_table = 'CovidSmote'
to_sql_iris(curs, df_smote, iris_table, iris_schema, drop_table=True) # sauvegarder ceci dans un nouveau tableau IRIS portant le nom spécifié
df2 = pd.read_sql("SELECT COUNT(*) from %s.%s" %(iris_schema, iris_table),conn)
display(df2)
<th>
  Aggregate_1
</th>
<td>
  2490
</td>
 

Le jeu de données comporte désormais 2490 lignes au lieu de 1700, car SMOTE a enrichi davantage d'enregistrements avec USI = 1.

dataTable = iris_table
dataTableViewTrain = dataTable + 'TrainSmote'
dataTablePredict = dataTable + 'PredictSmote'
dataColumn =  'ICU'
dataColumnPredict = 'ICUPredictedSmote'
modelName = "ICUSmote1" #choisir un nom - doit être unique du côté serveurcurs.execute("CREATE VIEW %s AS SELECT * FROM %s" % (dataTableViewTrain, dataTable))df_smote = pd.read_sql("SELECT * from %s" % dataTableViewTrain, conn)
display(df_smote)
print(dataTableViewTrain, modelName, dataColumn)
CovidSmoteTrainSmote ICUSmote1 ICU
curs.execute("CREATE MODEL %s PREDICTING (%s)  FROM %s" % (modelName, dataColumn, dataTableViewTrain))curs.execute("TRAIN MODEL %s FROM %s" % (modelName, dataTableViewTrain))

df3 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_TRAINED_MODELS", conn)
display(df3)
<th>
  NOM_DU_MODÈLE
</th>

<th>
NOM_DU_MODÈLE_FORMÉ
</th>

<th>
  FOURNISSEUR
</th>

<th>
  HORODATAGE_FORMÉ
</th>

<th>
  TYPE_DU_MODÈLE
</th>

<th>
  MODEL_INFO
</th>
<td>
  USIP621
</td>

<td>
  USIP6212
</td>

<td>
  AutoML
</td>

<td>
  2020-07-22 19:28:16.174000
</td>

<td>
  classification
</td>

<td>
  ModelType:Random Forest, Paquet:sklearn, Prob...
</td>
<td>
  USISmote1
</td>

<td>
  USISmote12
</td>

<td>
  AutoML
</td>

<td>
  2020-07-22 20:49:13.980000
</td>

<td>
  classification
</td>

<td>
  ModelType:Random Forest, Paquet:sklearn, Prob...
</td>
 
9
12

Ensuite, nous préparons à nouveau un ensemble réservé de 225 lignes de données de test et nous exécutons le modèle reformé de SMOTE sur ces lignes :

df_x_test = pd.DataFrame(X3_test)
df_y_test = pd.DataFrame(y3_test)
df_y_test.columns=['ICU']df_test_smote = pd.concat([df_x_test, df_y_test], 1)
display(df_test_smote)iris_schema = 'SQLUser'
iris_table = 'CovidTestSmote'to_sql_iris(curs, df_test_smote, iris_table, iris_schema, drop_table=True) dataTableViewTest = "SQLUSER.DTestSmote225"
curs.execute("CREATE VIEW %s AS SELECT * FROM %s" % (dataTableViewTest, iris_table))
curs.execute("Create Table %s (%s VARCHAR(100), %s VARCHAR(100))" % (dataTablePredict, dataColumnPredict, dataColumn))
curs.execute("INSERT INTO %s  SELECT PREDICT(%s) AS %s, %s FROM %s" % (dataTablePredict, modelName, dataColumnPredict, dataColumn, dataTableViewTest))

df62 = pd.read_sql("SELECT * from %s ORDER BY ID" % dataTablePredict, conn)
display(df62)

TP = df62[(df62['ICUPredictedSmote'] == '1') & (df62['ICU']=='1')].count()['ICU']  
TN = df62[(df62['ICUPredictedSmote'] == '0') & (df62['ICU']=='0')].count()["ICU"]
FN = df62[(df62['ICU'] == '1') & (df62['ICUPredictedSmote']=='0')].count()["ICU"]
FP = df62[(df62['ICUPredictedSmote'] == '1') & (df62['ICU']=='0')].count()["ICU"]
print(TP, FN, '\n', FP, TN)
precision = (TP)/(TP+FP)
recall = (TP)/(TP+FN)
f1 = ((precision*recall)/(precision+recall))*2
accuracy = (TP+TN) / (TP+TN+FP+FN)
print("Precision: ", precision, " Recall: ", recall, " F1: ", f1, " Accuracy: ", accuracy)
45 15
 9 156
Précision:  0.8333333333333334  Rappel:  0.75  F1:  0.7894736842105262  Exactitude:  0.8933333333333333

# valider les données d'essai à l'aide du modèle reformé de SMOTE
curs.execute("VALIDATE MODEL %s FROM %s" % (modelName, dataTableViewTest) )  #Covid19aTest500, Covid19aTrain1000
df5 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS", conn)
df6 = df5.pivot(index='VALIDATION_RUN_NAME', columns='METRIC_NAME', values='METRIC_VALUE')
display(df6)
<th>
  Exactitude
</th>

<th>
  Mesure F
</th>

<th>
  Précision
</th>

<th>
  Rappel
</th>
<th>
   
</th>

<th>
   
</th>

<th>
   
</th>

<th>
   
</th>
<td>
  0.88
</td>

<td>
  0.71
</td>

<td>
  0.81
</td>

<td>
  0.63
</td>
<td>
  0.89
</td>

<td>
  0.79
</td>

<td>
  0.83
</td>

<td>
  0.75
</td>
NOM_MÉTRIQUE
NOM_DE_L'EXÉCUTION_DE_LA_VALIDATION
USIP62121
USISmote122

Le résultat indique une amélioration significative du rappel de 75 % par rapport aux 63 % précédents, ainsi qu'une légère amélioration de l'exactitude et du score F1.  

Plus notablement, ce résultat est conforme à notre "approche ML traditionnelle" dans l'article précédent, après une "sélection de modèle" intensive et un "réglage des paramètres par quadrillage", comme indiqué dans la section "Exécuter le modèle sélectionné en poursuivant "Ajustement des paramètres via la recherche par quadrillage" supplémentaire". Le résultat de l'IML n'est donc pas mauvais du tout.

**Changement de fournisseur H2O d'IntegratedML **

Nous pouvons modifier le fournisseur AutoML de l'IML d'une seule ligne, puis former à nouveau le modèle comme nous l'avons fait à l'étape précédente :   

curs.execute("SET ML CONFIGURATION %H2O;  ")modelName = 'ICUSmoteH2O'
print(dataTableViewTrain)
curs.execute("CREATE MODEL %s PREDICTING (%s)  FROM %s" % (modelName, dataColumn, dataTableViewTrain))
curs.execute("TRAIN MODEL %s FROM %s" % (modelName, dataTableViewTrain))df3 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_TRAINED_MODELS", conn)
display(df3)
<th>
  NOM_DU_MODÈLE
</th>

<th>
  NOM_DU_MODÈLE_FORMÉ
</th>

<th>
  FOURNISSEUR
</th>

<th>
  HORODATAGE_FORMÉ
</th>

<th>
  TYPE_DU_MODÈLE
</th>

<th>
  MODÈLE_INFO
</th>
<td>
  USISmote1
</td>

<td>
  USISmote12
</td>

<td>
  AutoML
</td>

<td>
  2020-07-22 20:49:13.980000
</td>

<td>
  classification
</td>

<td>
  ModelType:Random Forest, Paquet:sklearn, Prob...
</td>
<td>
  USIPPP62
</td>

<td>
  USIPPP622
</td>

<td>
  AutoML
</td>

<td>
  2020-07-22 17:48:10.964000
</td>

<td>
  classification
</td>

<td>
  ModelType:Random Forest, Paquet:sklearn, Prob...
</td>
<td>
  USISmoteH2O
</td>

<td>
  USISmoteH2O2
</td>

<td>
  H2O
</td>

<td>
  2020-07-22 21:17:06.990000
</td>

<td>
  classification
</td>

<td>
  Aucun
</td>
 
12
13
14
# valider les données de test
curs.execute("VALIDATE MODEL %s FROM %s" % (modelName, dataTableViewTest) )  #Covid19aTest500, Covid19aTrain1000
df5 = pd.read_sql("SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS", conn)
df6 = df5.pivot(index='VALIDATION_RUN_NAME', columns='METRIC_NAME', values='METRIC_VALUE')
display(df6)
<th>
  Exactitude
</th>

<th>
  Mesure F
</th>

<th>
  Précision
</th>

<th>
  Rappel
</th>
<th>
   
</th>

<th>
   
</th>

<th>
   
</th>

<th>
   
</th>
<td>
  0.88
</td>

<td>
  0.71
</td>

<td>
  0.81
</td>

<td>
  0.63
</td>
<td>
  0.89
</td>

<td>
  0.79
</td>

<td>
  0.83
</td>

<td>
  0.75
</td>
<td>
  0.90
</td>

<td>
  0.79
</td>

<td>
  0.86
</td>

<td>
  0.73
</td>
NOM_MÉTRIQUE
NOM_DE_L'EXÉCUTION_DE_LA_VALIDATION
USIP62121
USISmote122
USISmoteH2O21

Les résultats semblent montrer que H2O AutoML a une précision légèrement supérieure, le même F1, mais un rappel légèrement inférieur. Cependant, notre objectif principal dans cette tâche de Covid19 USI est de minimiser les faux négatifs si nous le pouvons. Il semble donc que le changement de fournisseur pour H2O n'ait pas encore permis d'augmenter notre performance cible.

J'aimerais certainement tester également le fournisseur DataRobot d'IntegratedML, mais je n'ai malheureusement pas encore de clé API de DataRobot, alors je vais la mettre de côté ici.

Récapitulatif:

  1. Performance : Pour cette tâche spécifique de l'unité de soins intensifs de Covid-19, nos comparaisons de tests indiquent que les performances de l'IntegratedML d'IRIS sont au moins équivalentes ou similaires aux résultats de l'approche ML traditionnelle. Dans ce cas précis, IntegratedML a été capable de choisir automatiquement et correctement la stratégie d'entraînement interne, et a semblé établir le bon modèle, fournissant le résultat escompté.

  2. Simplicité : IntegratedML a un processus beaucoup plus simplifié que les pipelines ML traditionnels. Comme indiqué ci-dessus, je n'ai plus besoin de me préoccuper de la sélection des modèles et l'ajustement des paramètres, etc. Je n'ai pas non plus besoin de la sélection des caractéristiques, si ce n'est à des fins de comparaison. De plus, je n'ai utilisé que la syntaxe minimale d'IntegratedML, comme indiqué dans le cahier de démonstration d'Integrated-demo-template. Bien sûr, le désavantage est que nous sacrifions les capacités de personnalisation et d'ajustement des outils courants de science des données via leurs pipelines traditionnels, mais c'est aussi plus ou moins vrai pour d'autres plateformes AutoML.

  3. Le prétraitement des données reste important : Il n'y a malheureusement pas de solution miracle ; ou plutôt, cette solution miracle prendrait du temps. Spécifiquement pour cette tâche de Covid19 USI, les tests ci-dessus montrent que les données ont encore beaucoup d'importance pour l'approche actuelle d'IntegratedML : données brutes, caractéristiques sélectionnées avec données manquantes imputées, et données rééquilibrées avec suréchantillonnage SMOTE de base, elles ont toutes abouti à des performances significativement différentes. C'est vrai pour l'AutoML par défaut d'IML et son fournisseur H2O. J'imagine que DataRobot pourrait revendiquer une performance légèrement supérieure, mais cela doit être testé plus avant avec l'enveloppe SQL d'IntegratedML. En bref, la normalisation des données est toujours importante dans IntegratedML.

  4. Déployabilité : Je n'ai pas encore comparé la déployabilité, la gestion de l'API, la surveillance et la facilité d'utilisation non fonctionnelle, etc.

Suivant

  1. Déploiements de modèles : Jusqu'à présent, nous avons fait des démonstrations d'IA sur les radiographies pour le Covid-19 et des prédictions pour l'unité de soins intensifs pour le Covid-19 sur les signes vitaux et les observations. Pouvons-nous les déployer dans les piles de services Flask/FastAPI et IRIS, et exposer leurs capacités ML/DL de démonstration via des API REST/JSON ? Bien sûr, nous pouvons essayer de le faire dans le prochain article. Ensuite, nous pourrons ajouter d'autres capacités d'IA de démonstration au fil du temps, y compris des API NLP, etc.

  2. Interopérabilité de l'API enveloppée dans FHIR : Nous disposons également d'un modèle FHIR, ainsi que d'une API native IRIS, etc. dans cette communauté de développeurs. Pourrions-nous transformer notre service d'IA de démonstration en SMART on FHIR apps, ou en services d'IA enveloppés dans FHIR selon les normes correspondantes - pourrions-nous essayer cela ? Et n'oubliez pas que dans la gamme de produits IRIS, nous avons également API Gateway, ICM avec support Kubernetes, et SAM etc. que nous pourrions également exploiter avec nos piles de démonstrations d'IA.

  3. Démonstration d'intégration avec HealthShare Clinical Viewer et/ou Trak etc ? J'ai brièvement montré une démonstration d'intégration du PACS Viewer d'un fournisseur d'IA tiers (pour les CT Covid-19) avec HealthShare Clinical Viewer, et nous pourrions peut-être terminer cette randonnée avec nos propres services de démonstration d'IA, dans divers domaines de spécialité au fil du temps.

0
0 59
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
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
    Annonce Irène Mykhailova · Oct 10, 2022

    Salut la communauté,

    Rejoignez-nous pour une rencontre de développeurs InterSystems pendant TechCrunch Disrupt 2022 !

    Nous nous réunirons le mercredi 19 octobre au Bartlett Hall, situé au 242 O'Farrell St. (à quelques pâtés de maisons du Moscone Center) de 18 h 00 à 20 h 30 PT, où les conférenciers discuteront de la façon dont les développeurs peuvent apporter le code aux données, et non les données au code avec Embedded Python et Integrated ML sur InterSystems IRIS.

    Nourriture et boissons seront servies accompagnées de discussions.

    Ordre du jour:

    0
    0 34
    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