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 flux de travail de science des données Synapse pour un modèle de classification de texte dans Microsoft Fabric. Le scénario utilise word2vec et la régression logistique sur Spark pour déterminer le genre d’un livre à partir du jeu de données de la British library, uniquement en fonction du titre du livre.
Ce didacticiel couvre ces étapes :
- Installer des bibliothèques personnalisées
- Chargement des données
- Comprendre et traiter les données par le biais d’une analyse exploratoire des données
- Effectuer l’apprentissage d’un modèle Machine Learning à l’aide de word2vec et de la régression logistique et suivre des expériences avec MLflow et la fonctionnalité de journalisation automatique Fabric
- Charger le modèle Machine Learning pour le scoring et les prédictions
Prérequis
Obtenir un abonnement Microsoft Fabric. Ou, inscrivez-vous pour un essai gratuit de Microsoft Fabric.
Connectez-vous à Microsoft Fabric.
Utilisez le sélecteur d’expérience sur le côté gauche de votre page d’accueil pour basculer vers l’expérience Science des données Synapse.
- Si vous ne disposez pas de lakehouse Microsoft Fabric, créez-en un en suivant les étapes décrites dans Créer un lakehouse dans Microsoft Fabric.
Suivre dans un notebook
Vous pouvez choisir l’une de ces options pour suivre l’évolution de la situation dans un notebook :
- Ouvrez et exécutez le notebook intégré dans l’expérience science des données Synapse
- Chargez votre notebook à partir de GitHub vers l’expérience science des données Synapse
Ouvrir le notebook intégré
L’exemple de notebook Classification du genre du titre accompagne ce tutoriel.
Pour ouvrir l’exemple de notebook intégré du tutoriel dans l’expérience de science des données Synapse :
Accédez à la page d’accueil science des données Synapse.
Sélectionnez Utiliser un échantillon.
Sélectionnez l’échantillon correspondant :
- À partir de l’onglet par défaut Workflows de bout en bout (Python), si l’exemple concerne un tutoriel Python.
- À partir de l’onglet Workflows de bout en bout (R), si l’exemple concerne un tutoriel R.
- À partir de l’onglet Tutoriels rapides, si l’exemple concerne un tutoriel rapide.
Attachez un lakehouse au notebook avant de commencer à exécuter le code.
Importer un notebook à partir de GitHub
AIsample - Title Genre Classification.ipynb est le notebook qui accompagne ce didacticiel.
Pour ouvrir le notebook accompagnant ce tutoriel, suivez les instructions fournies dans Préparer votre système pour le tutoriel sur la science des données afin d’importer les notebooks dans votre espace de travail.
Si vous préférez copier et coller le code de cette page, vous pouvez créer un nouveau notebook.
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èle Machine Learning ou l’analyse de données ad hoc, vous pourriez avoir besoin d’installer rapidement une bibliothèque personnalisée pour votre session Apache Spark. Vous avez deux options d’installation des bibliothèques.
- Utilisez les capacités d’installation en ligne (
%pip
ou%conda
) de votre notebook pour installer une bibliothèque, dans votre notebook actuel uniquement - Vous pouvez également créer un environnement Fabric, installer des bibliothèques à partir de sources publiques ou y charger des bibliothèques personnalisées. Ensuite, l’administrateur de votre espace de travail peut attacher l’environnement en tant qu’environnement par défaut pour l’espace de travail. Toutes les bibliothèques de l’environnement seront ensuite disponibles pour être utilisées dans les notebooks et les définitions de travail 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 des mots dans un 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 : Chargement des données
Le jeu de données contient des métadonnées sur les livres de la British Library qui ont été numérisés dans le cadre d’une collaboration entre la bibliothèque et Microsoft. Les métadonnées sont des informations de classification pour indiquer si un livre est de fiction ou non. 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 variables | Titre de la série | Nombre dans la série | Pays de publication | Lieu de publication | Serveur de publication | Date de publication | Édition | Description physique | Classification Dewey | BL shelfmark | Rubriques | Genre | Langages | Notes | ID d’enregistrement BL pour la ressource physique | classification_id | user_id | created_at | subject_ids | annotator_date_pub | annotator_normalised_date_pub | annotator_edition_statement | annotator_genre | annotator_FAST_genre_terms | annotator_FAST_subject_terms | annotator_comments | annotator_main_language | annotator_other_languages_summaries | annotator_summaries_language | annotator_translation | annotator_original_language | annotator_publisher | annotator_place_pub | annotator_country | annotator_title | Lien vers un livre numérisé | Annotée |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
014602826 | Monographie | Yearsley, Ann | 1753-1806 | personne | Plus, Hannah, 1745-1833 [personne]; Yearsley, Ann, 1753-1806 [personne] | Poèmes à plusieurs reprises [Avec une lettre préliminaire d’Hannah More.] | England | London | 1786 | Note MANUSCRITE de la quatrième édition | Magasin numérique 11644.d.32 | Anglais | 003996603 | False | |||||||||||||||||||||||||||||||
014602830 | Monographie | A, T. | personne | Oldham, John, 1653-1683 [personne]; A, T. [personne] | A Satyr against Vertue. (Un poème : censé être prononcé par un Town-Hector [Par John Oldham. Préface signée : T. A.]) | England | London | 1679 | 15 pages (4°) | Magasin numérique 11602.ee.10. (2.) | Anglais | 000001143 | False |
Définissez les paramètres suivants pour appliquer ce notebook à 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écharger le jeu de données et le charger dans le lakehouse
Ce code télécharge une version disponible publiquement du jeu de données, puis la stocke dans un lakehouse Fabric.
Important
Ajoutez un lakehouse au notebook avant de l’exécuter. Dans le cas contraire, vous obtiendrez 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 les bibliothèques nécessaires
Avant tout traitement, vous devez importer les bibliothèques requises, y compris celles 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
Commencer à 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
La journalisation automatique étend les fonctionnalités de journalisation MLflow. La journalisation automatique capture automatiquement les valeurs des paramètres d’entrée et les métriques de sortie d’un modèle Machine Learning au fur et à mesure que 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. 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 journalisation automatique de Microsoft Fabric dans une session de notebook, appelez mlflow.autolog()
et définissez disable=True
:
Lire les données de date brutes de la 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 à l’aide de la commande display
pour afficher les statistiques générales du 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 tout 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 se produisent généralement dans tous les 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 du 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 de couleur de type cloud pour mieux capturer les données de texte principales en un clin 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 ayant des relations sémantiques sont capturés efficacement par 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 : Effectuer l’apprentissage et évaluer le modèle
Avec les données en place, définissez le modèle. Dans cette section, vous entraînez un modèle de régression logistique pour classifier le texte vectorisé.
Préparation de jeux de données d’apprentissage 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 d’apprentissage automatique
Une expérience de Machine Learning est l’unité principale d’organisation et de contrôle pour tous les cycles d’apprentissage automatique connexes. Une exécution correspond à une seule exécution de code de modèle.
Le suivi des expériences d’apprentissage automatique gère toutes les expériences et leurs composants, tels que les paramètres, les métriques, les modèles et d’autres artefacts. Le suivi permet d’organiser tous les composants requis d’une expérience d’apprentissage automatique 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 d’apprentissage automatique dans Microsoft Fabric.
# Build the logistic regression classifier
lr = (
LogisticRegression()
.setMaxIter(max_iter)
.setFeaturesCol("features")
.setLabelCol("labelIdx")
.setWeightCol("weight")
)
Optimiser les hyperparamètres
Générez une grille de paramètres pour effectuer une recherche sur les hyperparamètres. Créez ensuite un estimateur d’évaluateur croisé 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 entraîné doit démontrer des performances élevées sur les indicateurs de performance pertinents lorsqu’il est exécuté 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 et les paramètres de journalisation, 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 :
- Sur la gauche, sélectionnez votre espace de travail.
- 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 à l’aide de 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 Scoring de modèle Machine Learning avec PREDICT dans Microsoft Fabric.
À partir des résultats d’évaluation ci-dessus, le modèle 1 a les plus grandes métrique pour AUPRC (Area Under the Precision-Recall Curve) et AUC-ROC (Area Under the Curve Receiver Operating Characteristic). Vous devez donc 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 est parfois plus approprié d’évaluer le classifieur en fonction de la mesure 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 de vrais positifs 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.")