Tutoriel : Créer, évaluer et noter un modèle de classification de texte
Ce tutoriel présente un exemple de bout en bout d’un workflow Synapse Data Science pour un modèle de classification de texte, dans Microsoft Fabric. Le scénario utilise word2vec et une régression logistique, sur Spark, pour déterminer le genre d'un livre à partir du jeu de données de la British Library, uniquement basé sur le titre.
Ce tutoriel décrit les étapes suivantes :
- Installer des bibliothèques personnalisées
- Charger les données
- Comprendre et traiter les données avec l’analyse exploratoire des données
- Effectuer l’apprentissage d’un modèle Machine Learning avec word2vec et régression logistique, et suivre des expériences avec MLflow et la fonctionnalité de autologging Fabric
- Charger le modèle Machine Learning pour le scoring et les prédictions
Conditions préalables
Obtenez un abonnement Microsoft Fabric . Vous pouvez également vous inscrire à une version d’évaluation gratuite de Microsoft Fabric .
Connectez-vous à Microsoft Fabric.
Utilisez le sélecteur d’expérience en bas à gauche de votre page d’accueil pour basculer vers Fabric.
- Si vous n’avez pas de lakehouse Microsoft Fabric, créez-en un en suivant les étapes décrites dans Créer un lakehouse dans Microsoft Fabric.
Suivez avec un carnet
Vous pouvez choisir l’une de ces options à suivre dans un bloc-notes :
- Ouvrez et exécutez le notebook intégré.
- Chargez votre bloc-notes à partir de GitHub.
Ouvrir le notebook intégré
L'exemple de cahier de classification de genre Titre accompagne ce didacticiel.
Pour ouvrir le bloc-notes d'exemple pour ce didacticiel, suivez les instructions de Préparez votre système pour les tutoriels de la science des données.
Assurez-vous d’attacher un lakehouse au notebook avant de commencer à exécuter du code.
Importer le notebook à partir de GitHub
AIsample - Title Genre Classification.ipynb est le notebook qui accompagne ce didacticiel.
Pour ouvrir le bloc-notes associé pour ce didacticiel, suivez les instructions de Préparer votre système pour les didacticiels de science des données pour importer le bloc-notes dans votre espace de travail.
Si vous préférez copier et coller le code à partir de cette page, vous pouvez créer un bloc-notes.
Assurez-vous d'attacher un lakehouse au notebook avant de commencer à exécuter du code.
Étape 1 : Installer des bibliothèques personnalisées
Pour le développement de modèles Machine Learning ou l’analyse des données ad hoc, vous devrez peut-être installer rapidement une bibliothèque personnalisée pour votre session Apache Spark. Vous avez deux options d’installation des bibliothèques.
- Utilisez les fonctionnalités d’installation inline (
%pip
ou%conda
) de votre notebook pour installer une bibliothèque, dans votre bloc-notes actuel uniquement. - Vous pouvez également créer un environnement Fabric, installer des bibliothèques à partir de sources publiques ou charger des bibliothèques personnalisées vers celui-ci, puis l’administrateur de votre espace de travail peut attacher l’environnement comme valeur par défaut pour l’espace de travail. Toutes les bibliothèques de l’environnement seront ensuite disponibles pour être utilisées dans les blocs-notes et les définitions de travaux Spark dans l’espace de travail. Pour plus d’informations sur les environnements, consultez créer, configurer et utiliser un environnement dans Microsoft Fabric.
Pour le modèle de classification, utilisez la bibliothèque wordcloud
pour représenter la fréquence du mot dans le texte, où la taille d’un mot représente sa fréquence. Pour ce tutoriel, utilisez %pip install
pour installer wordcloud
dans votre notebook.
Remarque
Le noyau PySpark redémarre après l’exécution de %pip install
. Installez les bibliothèques nécessaires avant d’exécuter d’autres cellules.
# Install wordcloud for text visualization by using pip
%pip install wordcloud
Étape 2 : Charger les données
Le jeu de données contient des métadonnées sur les livres de la British Library qu’une collaboration entre la bibliothèque et Microsoft a numérisés. Les métadonnées sont des informations de classification pour indiquer si un livre est de fiction ou de non-fiction. Avec ce jeu de données, l’objectif est d’entraîner un modèle de classification qui détermine le genre d’un livre, uniquement en fonction de son titre.
ID d’enregistrement BL | Type de ressource | Nom | Dates associées au nom | Type de nom | Rôle | Tous les noms | Titre | Titres alternatifs | Titre de la série | Nombre dans la série | Pays de publication | Lieu de publication | Éditeur | Date de publication | Édition | Description physique | Classification Dewey | BL shelfmark | Sujets | Genre | Langues | Notes | ID d’enregistrement BL pour la ressource physique | identifiant_de_classification | identifiant_utilisateur | created_at | subject_ids | annotator_date_pub | annotator_normalised_date_pub | annotator_edition_statement | annotator_genre | annotator_FAST_genre_terms | annotator_FAST_subject_terms | commentaires de l'annotateur | annotator_main_language | annotator_other_languages_summaries | annotator_summaries_language | annotator_translation | langue_originale_de_l'annotateur | annotator_publisher | annotator_place_pub | pays_annotateur | titre_d'annotateur | Lien vers un livre numérisé | Annotée |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
014602826 | Monographie | Yearsley, Ann | 1753-1806 | personne | En outre, Hannah, 1745-1833 [personne] ; Yearsley, Ann, 1753-1806 [personne] | Poèmes à plusieurs reprises [Avec une lettre préliminaire d’Hannah More.] | Angleterre | Londres | 1786 | Note de manuscrit de la quatrième édition | Magasin numérique 11644.d.32 | Anglais | 003996603 | Faux | |||||||||||||||||||||||||||||||
014602830 | Monographie | A, T. | personne | Oldham, John, 1653-1683 [personne]; A, T. [personne] | Un Satyr contre Vertue. (Un poème : censé être prononcé par un Town-Hector [Par John Oldham. Préface signée : T. A.]) | Angleterre | Londres | 1679 | 15 pages (4°) | Magasin numérique 11602.ee.10. (2.) | Anglais | 000001143 | Faux |
Définissez les paramètres suivants pour pouvoir appliquer ce notebook sur différents jeux de données :
IS_CUSTOM_DATA = False # If True, the user must manually upload the dataset
DATA_FOLDER = "Files/title-genre-classification"
DATA_FILE = "blbooksgenre.csv"
# Data schema
TEXT_COL = "Title"
LABEL_COL = "annotator_genre"
LABELS = ["Fiction", "Non-fiction"]
EXPERIMENT_NAME = "sample-aisample-textclassification" # MLflow experiment name
Téléchargez le jeu de données et chargez-le dans le lakehouse
Ce code télécharge une version publiquement disponible du jeu de données, puis la stocke dans un lakehouse Fabric.
Important
Ajoutez un lakehouse au bloc-notes avant de le lancer. L’échec de cette opération entraîne une erreur.
if not IS_CUSTOM_DATA:
# Download demo data files into the lakehouse, if they don't exist
import os, requests
remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/Title_Genre_Classification"
fname = "blbooksgenre.csv"
download_path = f"/lakehouse/default/{DATA_FOLDER}/raw"
if not os.path.exists("/lakehouse/default"):
# Add a lakehouse, if no default lakehouse was added to the notebook
# A new notebook won't link to any lakehouse by default
raise FileNotFoundError(
"Default lakehouse not found, please add a lakehouse and restart the session."
)
os.makedirs(download_path, exist_ok=True)
if not os.path.exists(f"{download_path}/{fname}"):
r = requests.get(f"{remote_url}/{fname}", timeout=30)
with open(f"{download_path}/{fname}", "wb") as f:
f.write(r.content)
print("Downloaded demo data files into lakehouse.")
Importer des bibliothèques requises
Avant tout traitement, vous devez importer les bibliothèques requises, y compris les bibliothèques pour spark et SynapseML:
import numpy as np
from itertools import chain
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import seaborn as sns
import pyspark.sql.functions as F
from pyspark.ml import Pipeline
from pyspark.ml.feature import *
from pyspark.ml.tuning import CrossValidator, ParamGridBuilder
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import (
BinaryClassificationEvaluator,
MulticlassClassificationEvaluator,
)
from synapse.ml.stages import ClassBalancer
from synapse.ml.train import ComputeModelStatistics
import mlflow
Définir des hyperparamètres
Définissez certains hyperparamètres pour l’entraînement du modèle.
Important
Modifiez ces hyperparamètres uniquement si vous comprenez chaque paramètre.
# Hyperparameters
word2vec_size = 128 # The length of the vector for each word
min_word_count = 3 # The minimum number of times that a word must appear to be considered
max_iter = 10 # The maximum number of training iterations
k_folds = 3 # The number of folds for cross-validation
Commencez à enregistrer le temps nécessaire pour exécuter ce notebook :
# Record the notebook running time
import time
ts = time.time()
Configurer le suivi des expériences MLflow
L’autologging étend les fonctionnalités de journalisation MLflow. L’autologging capture automatiquement les valeurs des paramètres d’entrée et les métriques de sortie d’un modèle Machine Learning lorsque vous l’entraînez. Vous consignez ensuite ces informations dans l’espace de travail. Dans l’espace de travail, vous pouvez accéder aux informations et les visualiser avec les API MLflow, ou l’expérience correspondante, dans l’espace de travail. Pour en savoir plus sur l’autologging, consultez autologging dans Microsoft Fabric.
# Set up Mlflow for experiment tracking
mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True) # Disable Mlflow autologging
Pour désactiver la connexion automatique de Microsoft Fabric dans une session de notebook, appelez mlflow.autolog()
et définissez disable=True
:
Lire les données de date brutes du lakehouse
raw_df = spark.read.csv(f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True)
Étape 3 : Effectuer une analyse exploratoire des données
Explorez le jeu de données avec la commande display
, pour afficher les statistiques de haut niveau pour le jeu de données et afficher les vues de graphique :
display(raw_df.limit(20))
Préparer les données
Supprimez les doublons pour nettoyer les données :
df = (
raw_df.select([TEXT_COL, LABEL_COL])
.where(F.col(LABEL_COL).isin(LABELS))
.dropDuplicates([TEXT_COL])
.cache()
)
display(df.limit(20))
Appliquez l’équilibrage de classe pour résoudre tous les biais :
# Create a ClassBalancer instance, and set the input column to LABEL_COL
cb = ClassBalancer().setInputCol(LABEL_COL)
# Fit the ClassBalancer instance to the input DataFrame, and transform the DataFrame
df = cb.fit(df).transform(df)
# Display the first 20 rows of the transformed DataFrame
display(df.limit(20))
Fractionnez les paragraphes et les phrases en unités plus petites pour tokeniser le jeu de données. De cette façon, il devient plus facile d’attribuer une signification. Ensuite, supprimez les mots vides pour améliorer les performances. La suppression de mots vides implique la suppression de mots qui apparaissent généralement dans l'ensemble des documents du corpus. La suppression de mots vides est l’une des étapes de prétraitement les plus couramment utilisées dans les applications de traitement en langage naturel (NLP).
# Text transformer
tokenizer = Tokenizer(inputCol=TEXT_COL, outputCol="tokens")
stopwords_remover = StopWordsRemover(inputCol="tokens", outputCol="filtered_tokens")
# Build the pipeline
pipeline = Pipeline(stages=[tokenizer, stopwords_remover])
token_df = pipeline.fit(df).transform(df)
display(token_df.limit(20))
Affichez la bibliothèque wordcloud pour chaque classe. Une bibliothèque wordcloud est une présentation visuellement importante des mots clés qui apparaissent fréquemment dans les données de texte. La bibliothèque wordcloud est efficace, car le rendu des mots-clés forme une image colorée nuageuse, permettant de mieux saisir les principales données textuelles d'un seul coup d'œil. En savoir plus sur wordcloud.
# WordCloud
for label in LABELS:
tokens = (
token_df.where(F.col(LABEL_COL) == label)
.select(F.explode("filtered_tokens").alias("token"))
.where(F.col("token").rlike(r"^\w+$"))
)
top50_tokens = (
tokens.groupBy("token").count().orderBy(F.desc("count")).limit(50).collect()
)
# Generate a wordcloud image
wordcloud = WordCloud(
scale=10,
background_color="white",
random_state=42, # Make sure the output is always the same for the same input
).generate_from_frequencies(dict(top50_tokens))
# Display the generated image by using matplotlib
plt.figure(figsize=(10, 10))
plt.title(label, fontsize=20)
plt.axis("off")
plt.imshow(wordcloud, interpolation="bilinear")
Enfin, utilisez word2vec pour vectoriser le texte. La technique word2vec crée une représentation vectorielle de chaque mot dans le texte. Les mots utilisés dans des contextes similaires, ou qui ont des relations sémantiques, sont capturés efficacement à travers leur proximité dans l’espace vectoriel. Cette proximité indique que les mots similaires ont des vecteurs de mots similaires.
# Label transformer
label_indexer = StringIndexer(inputCol=LABEL_COL, outputCol="labelIdx")
vectorizer = Word2Vec(
vectorSize=word2vec_size,
minCount=min_word_count,
inputCol="filtered_tokens",
outputCol="features",
)
# Build the pipeline
pipeline = Pipeline(stages=[label_indexer, vectorizer])
vec_df = (
pipeline.fit(token_df)
.transform(token_df)
.select([TEXT_COL, LABEL_COL, "features", "labelIdx", "weight"])
)
display(vec_df.limit(20))
Étape 4 : Entraîner et évaluer le modèle
Avec les données en place, définissez le modèle. Dans cette section, vous allez entraîner un modèle de régression logistique pour classifier le texte vectorisé.
Préparer des jeux de données d’entraînement et de test
# Split the dataset into training and testing
(train_df, test_df) = vec_df.randomSplit((0.8, 0.2), seed=42)
Suivre les expériences de Machine Learning
Une expérience de Machine Learning est l’unité principale de l’organisation et du contrôle pour toutes les exécutions de Machine Learning associées. Une exécution correspond à une seule exécution du code de modèle.
Le suivi des expériences Machine Learning gère toutes les expériences et leurs composants, par exemple les paramètres, les métriques, les modèles et d’autres artefacts. Le suivi permet l’organisation de tous les composants requis d’une expérience de Machine Learning spécifique. Il permet également la reproduction facile des résultats passés avec des expériences enregistrées. En savoir plus sur les expériences de Machine Learning dans Microsoft Fabric.
# Build the logistic regression classifier
lr = (
LogisticRegression()
.setMaxIter(max_iter)
.setFeaturesCol("features")
.setLabelCol("labelIdx")
.setWeightCol("weight")
)
Ajuster les hyperparamètres
Générez une grille de paramètres pour effectuer une recherche sur les hyperparamètres. Créez ensuite un estimateur multi-évaluateur pour produire un modèle CrossValidator
:
# Build a grid search to select the best values for the training parameters
param_grid = (
ParamGridBuilder()
.addGrid(lr.regParam, [0.03, 0.1])
.addGrid(lr.elasticNetParam, [0.0, 0.1])
.build()
)
if len(LABELS) > 2:
evaluator_cls = MulticlassClassificationEvaluator
evaluator_metrics = ["f1", "accuracy"]
else:
evaluator_cls = BinaryClassificationEvaluator
evaluator_metrics = ["areaUnderROC", "areaUnderPR"]
evaluator = evaluator_cls(labelCol="labelIdx", weightCol="weight")
# Build a cross-evaluator estimator
crossval = CrossValidator(
estimator=lr,
estimatorParamMaps=param_grid,
evaluator=evaluator,
numFolds=k_folds,
collectSubModels=True,
)
Évaluer le modèle
Nous pouvons évaluer les modèles sur le jeu de données de test pour les comparer. Un modèle bien formé doit présenter des performances élevées, sur les métriques pertinentes, lors de l’exécution sur les jeux de données de validation et de test.
def evaluate(model, df):
log_metric = {}
prediction = model.transform(df)
for metric in evaluator_metrics:
value = evaluator.evaluate(prediction, {evaluator.metricName: metric})
log_metric[metric] = value
print(f"{metric}: {value:.4f}")
return prediction, log_metric
Suivre les expériences à l’aide de MLflow
Démarrez le processus d’entraînement et d’évaluation. Utilisez MLflow pour suivre toutes les expériences, ainsi que les paramètres de journal, les métriques et les modèles. Toutes ces informations sont consignées sous le nom de l’expérience dans l’espace de travail.
with mlflow.start_run(run_name="lr"):
models = crossval.fit(train_df)
best_metrics = {k: 0 for k in evaluator_metrics}
best_index = 0
for idx, model in enumerate(models.subModels[0]):
with mlflow.start_run(nested=True, run_name=f"lr_{idx}") as run:
print("\nEvaluating on test data:")
print(f"subModel No. {idx + 1}")
prediction, log_metric = evaluate(model, test_df)
if log_metric[evaluator_metrics[0]] > best_metrics[evaluator_metrics[0]]:
best_metrics = log_metric
best_index = idx
print("log model")
mlflow.spark.log_model(
model,
f"{EXPERIMENT_NAME}-lrmodel",
registered_model_name=f"{EXPERIMENT_NAME}-lrmodel",
dfs_tmpdir="Files/spark",
)
print("log metrics")
mlflow.log_metrics(log_metric)
print("log parameters")
mlflow.log_params(
{
"word2vec_size": word2vec_size,
"min_word_count": min_word_count,
"max_iter": max_iter,
"k_folds": k_folds,
"DATA_FILE": DATA_FILE,
}
)
# Log the best model and its relevant metrics and parameters to the parent run
mlflow.spark.log_model(
models.subModels[0][best_index],
f"{EXPERIMENT_NAME}-lrmodel",
registered_model_name=f"{EXPERIMENT_NAME}-lrmodel",
dfs_tmpdir="Files/spark",
)
mlflow.log_metrics(best_metrics)
mlflow.log_params(
{
"word2vec_size": word2vec_size,
"min_word_count": min_word_count,
"max_iter": max_iter,
"k_folds": k_folds,
"DATA_FILE": DATA_FILE,
}
)
Pour afficher vos expériences :
- Sélectionnez votre espace de travail dans le volet de navigation gauche
- Recherchez et sélectionnez le nom de l’expérience (dans ce cas, sample_aisample-textclassification)
Étape 5 : Noter et enregistrer les résultats de prédiction
Microsoft Fabric permet aux utilisateurs d’opérationnaliser des modèles Machine Learning avec la fonction évolutive PREDICT
. Cette fonction prend en charge le scoring par lots (ou l’inférence par lot) dans n’importe quel moteur de calcul. Vous pouvez créer des prédictions par lots directement à partir d’un bloc-notes ou de la page d’élément d’un modèle particulier. Pour en savoir plus sur PREDICT et comment l’utiliser dans Fabric, consultez évaluation de modèle d'apprentissage automatique avec PREDICT dans Microsoft Fabric.
À partir des résultats d’évaluation précédents, le modèle 1 a les métriques les plus importantes pour la zone sous la courbe Precision-Recall (AUPRC) et pour la zone sous la caractéristique d’exploitation du récepteur de courbes (AUC-ROC). Par conséquent, vous devez utiliser le modèle 1 pour la prédiction.
La mesure AUC-ROC est largement utilisée pour mesurer les performances des classifieurs binaires. Toutefois, il devient parfois plus approprié d’évaluer le classifieur en fonction des mesures AUPRC. Le graphique AUC-ROC visualise le compromis entre le taux de vrais positifs (TPR) et le taux de faux positifs (FPR). La courbe AUPRC combine la précision (valeur prédictive positive ou PPV) et le rappel (taux positif réel ou TPR) dans une visualisation unique.
# Load the best model
model_uri = f"models:/{EXPERIMENT_NAME}-lrmodel/1"
loaded_model = mlflow.spark.load_model(model_uri, dfs_tmpdir="Files/spark")
# Verify the loaded model
batch_predictions = loaded_model.transform(test_df)
batch_predictions.show(5)
# Code to save userRecs in the lakehouse
batch_predictions.write.format("delta").mode("overwrite").save(
f"{DATA_FOLDER}/predictions/batch_predictions"
)
# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")