Compartir vía


Tutorial: Creación, evaluación y puntuación de un modelo de clasificación de texto

En este tutorial se presenta un ejemplo completo de un flujo de trabajo de ciencia de datos de Synapse para un modelo de clasificación de texto, en Microsoft Fabric. El escenario utiliza word2vec y regresión logística, en Spark, para determinar el género de un libro del conjunto de datos de la Biblioteca Británica, basándose únicamente en el título del libro.

En este tutorial se describen estos pasos:

  • Instalación de bibliotecas personalizadas
  • Carga de los datos
  • Descripción y procesamiento de los datos con análisis de datos exploratorios
  • Entrenamiento de un modelo de Machine Learning con word2vec y regresión logística, y seguimiento de experimentos mediante MLflow y la característica de registro automático de Fabric
  • Carga del modelo de Machine Learning para la puntuación y las predicciones

Prerrequisitos

Seguimiento en un cuaderno

Puede elegir una de estas opciones para realizar un seguimiento en un cuaderno:

  • Abra y ejecute el cuaderno integrado.
  • Cargue el cuaderno desde GitHub.

Abra el cuaderno integrado.

El cuaderno de ejemplo Clasificación de género de título acompaña a este tutorial.

  1. Para abrir el cuaderno de ejemplo de este tutorial, siga las instrucciones de Preparar el sistema para tutoriales de ciencia de datos.

  2. Asegúrese de adjuntar un almacén de lago de datos al cuaderno antes de ejecutar el código.

Importación del cuaderno desde GitHub

AIsample- Title Genre Classification.ipynb es el cuaderno que acompaña a este tutorial.

Paso 1: Instalación de bibliotecas personalizadas

Para el desarrollo de modelos de Machine Learning o el análisis de datos ad hoc, es posible que tenga que instalar rápidamente una biblioteca personalizada para la sesión de Apache Spark. Tiene dos opciones para instalar bibliotecas.

  • Utiliza las capacidades de instalación en línea (%pip o %conda) de tu notebook para instalar una biblioteca, solo en el notebook actual.
  • Como alternativa, puede crear un entorno de Fabric, instalar bibliotecas desde orígenes públicos o cargar bibliotecas personalizadas en él y, a continuación, el administrador del área de trabajo puede asociar el entorno como valor predeterminado para el área de trabajo. Todas las bibliotecas del entorno estarán disponibles para su uso en los cuadernos y las definiciones de trabajos de Spark en el área de trabajo. Para obtener más información sobre los entornos, consulte crear, configurar y usar un entorno en Microsoft Fabric.

Para el modelo de clasificación, use la biblioteca wordcloud para representar la frecuencia de palabras en el texto, donde el tamaño de una palabra representa su frecuencia. Para este tutorial, use %pip install para instalar wordcloud en tu portátil.

Nota

El kernel de PySpark se reinicia después de que se ejecute %pip install. Instale las bibliotecas necesarias antes de ejecutar cualquier otra celda.

# Install wordcloud for text visualization by using pip
%pip install wordcloud

Paso 2: Cargar los datos

El conjunto de datos tiene metadatos sobre los libros de la Biblioteca Británica que una colaboración entre la biblioteca y Microsoft digitalizaron. Los metadatos son información de clasificación para indicar si un libro es ficción o no ficción. Con este conjunto de datos, el objetivo es entrenar un modelo de clasificación que determine el género de un libro, solo en función de su título.

Id. de registro de BL Tipo de recurso Nombre Fechas asociadas con el nombre Tipo de nombre Rol Todos los nombres Título Títulos variantes Título de la serie Número dentro de la serie País de publicación Lugar de publicación Publicador Fecha de publicación Edición Descripción física Clasificación de dewey Signatura topográfica de BL Temas Género Idiomas Notas Id. de registro de BL para el recurso físico classification_id identificador de usuario created_at subject_ids annotator_date_pub annotator_normalised_date_pub annotator_edition_statement annotator_genre annotator_FAST_genre_terms annotator_FAST_subject_terms comentarios_del_annotador annotator_main_language annotator_other_languages_summaries annotator_summaries_language annotator_translation idioma_original_del_annotador annotator_publisher annotator_place_pub país_del_anotador título del anotador Vínculo al libro digitalizado annotated
014602826 Monografía Yearsley, Ann 1753-1806 person More, Hannah, 1745-1833 [persona]; Yearsley, Ann, 1753-1806 [persona] Poemas en varias ocasiones [Con una carta preliminar de Hannah More.] Inglaterra Londres 1786 Cuarta edición de la nota de MANUSCRITO Digital Store 11644.d.32 Inglés 003996603 Falso
014602830 Monografía A, T. person Oldham, John, 1653-1683 [persona]; A, T. [persona] Un Satyr contra Vertue. (Un poema: se supone que debe ser recitado por un Town-Hector [Por John Oldham. El prefacio firmado: T. A.]) Inglaterra Londres 1679 15 páginas (4°) Digital Store 11602.ee.10. (2.) Inglés 000001143 Falso

Defina los parámetros siguientes para que pueda aplicar este cuaderno en diferentes conjuntos de datos:

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

Descarga del conjunto de datos y carga en el almacén de lago de datos

Este código descarga una versión disponible públicamente del conjunto de datos y, a continuación, la almacena en una instancia de Fabric Lakehouse.

Importante

Agregue un almacén de lago de datos al cuaderno antes de ejecutarlo. Si no lo hace, se producirá un error.

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.")

Importación de bibliotecas necesarias

Antes de cualquier procesamiento, debe importar las bibliotecas necesarias, incluidas las bibliotecas de Spark y 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

Definir hiperparámetros

Defina algunos hiperparámetros para el entrenamiento del modelo.

Importante

Modifique estos hiperparámetros solo si comprende cada parámetro.

# 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

Inicie la grabación del tiempo necesario para ejecutar este cuaderno:

# Record the notebook running time
import time

ts = time.time()

Configuración del seguimiento de experimentos de MLflow

El registro automático amplía las funcionalidades de registro de MLflow. El registro automático captura automáticamente los valores de los parámetros de entrada y las métricas de salida de un modelo de Machine Learning a medida que se entrena. A continuación, registre esta información en el área de trabajo. En el área de trabajo, puede acceder a la información y visualizarla con las API de MLflow o el experimento correspondiente en el área de trabajo. Para obtener más información sobre el registro automático, consulte Registro automático en Microsoft Fabric.

# Set up Mlflow for experiment tracking

mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True)  # Disable Mlflow autologging

Para deshabilitar el registro automático de Microsoft Fabric en una sesión de cuaderno, llame a mlflow.autolog() y establezca disable=True:

Lectura de datos sin procesar desde el almacén de lago de datos

raw_df = spark.read.csv(f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True)

Paso 3: Realizar análisis de datos exploratorios

Explore el conjunto de datos con el comando display para ver las estadísticas de alto nivel del conjunto de datos y mostrar las vistas del gráfico:

display(raw_df.limit(20))

Preparación de los datos

Quite los duplicados para limpiar los datos:

df = (
    raw_df.select([TEXT_COL, LABEL_COL])
    .where(F.col(LABEL_COL).isin(LABELS))
    .dropDuplicates([TEXT_COL])
    .cache()
)

display(df.limit(20))

Aplique equilibrio de clases para solucionar cualquier sesgo:

# 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))

Divida los párrafos y oraciones en unidades más pequeñas para tokenizar el conjunto de datos. De este modo, resulta más fácil asignar significado. Después, quite las palabras irrelevantes para mejorar el rendimiento. La eliminación de palabras irrelevantes implica la eliminación de palabras que suelen aparecer en todos los documentos del corpus. La eliminación de palabras irrelevantes es uno de los pasos de preprocesamiento más usados en las aplicaciones de procesamiento de lenguaje natural (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))

Muestra la biblioteca de wordcloud para cada clase. Una biblioteca de wordcloud es una presentación visualmente destacada de palabras clave que aparecen con frecuencia en los datos de texto. La biblioteca de wordcloud es eficaz porque la representación de palabras clave forma una imagen de color similar a la nube, para capturar mejor los datos de texto principales de un vistazo. Más información sobre 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")

Por último, use word2vec para vectorizar el texto. La técnica word2vec crea una representación vectorial de cada palabra del texto. Las palabras usadas en contextos similares, o que tienen relaciones semánticas, se capturan de forma eficaz a través de su proximidad en el espacio vectorial. Esta cercanía indica que las palabras similares tienen vectores de palabra similares.

# 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))

Paso 4: Entrenamiento y evaluación del modelo

Con los datos implementados, defina el modelo. En esta sección, entrenará un modelo de regresión logística para clasificar el texto vectorizado.

Preparación de conjuntos de datos de entrenamiento y prueba

# Split the dataset into training and testing
(train_df, test_df) = vec_df.randomSplit((0.8, 0.2), seed=42)

Seguimiento de experimentos de aprendizaje automático

Un experimento de aprendizaje automático es la unidad principal de organización y control para todas las ejecuciones de aprendizaje automático relacionadas. Una ejecución corresponde a una sola ejecución de código de modelo.

El seguimiento de experimentos de aprendizaje automático administra todos los experimentos y sus componentes, por ejemplo, parámetros, métricas, modelos y otros artefactos. El seguimiento permite la organización de todos los componentes necesarios de un experimento de aprendizaje automático específico. También permite la reproducción sencilla de los resultados pasados con experimentos guardados. Obtenga más información sobre los experimentos de aprendizaje automático en Microsoft Fabric.

# Build the logistic regression classifier
lr = (
    LogisticRegression()
    .setMaxIter(max_iter)
    .setFeaturesCol("features")
    .setLabelCol("labelIdx")
    .setWeightCol("weight")
)

Ajuste de hiperparámetros

Cree una cuadrícula de parámetros para buscar en los hiperparámetros. Después, cree un estimador de evaluador cruzado para generar un modelo de 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,
)

Evaluación del modelo

Podemos evaluar los modelos en el conjunto de datos de prueba para compararlos. Un modelo bien entrenado debe demostrar un alto rendimiento, en las métricas pertinentes, cuando se ejecuta en los conjuntos de datos de validación y prueba.

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

Seguimiento de experimentos mediante MLflow

Inicie el proceso de entrenamiento y evaluación. Use MLflow para realizar un seguimiento de todos los experimentos y los parámetros de registro, las métricas y los modelos. Toda esta información se registra bajo el nombre del experimento en el área de trabajo.

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,
        }
    )

Para ver los experimentos:

  1. Seleccione el área de trabajo en el panel de navegación izquierdo.
  2. Busque y seleccione el nombre del experimento; en este caso, sample_aisample-textclassification

Captura de pantalla de un experimento.

Paso 5: Puntuación y guardado de resultados de predicción

Microsoft Fabric permite a los usuarios poner en marcha modelos de aprendizaje automático con la función escalable PREDICT. Esta función admite la puntuación por lotes (o la inferencia por lotes) en cualquier motor de proceso. Puede crear predicciones por lotes directamente desde un cuaderno o la página de elementos de un modelo determinado. Para más información sobre PREDICT y cómo usarlo en Fabric, consulte puntuación de modelos de Machine Learning con PREDICT en Microsoft Fabric.

A partir de los resultados de la evaluación anterior, el modelo 1 tiene las métricas más grandes de área bajo la curva de precisión-coincidencia (AUPRC) y área bajo la curva de característica operativa del receptor (AUC-ROC). Por lo tanto, debe usar el modelo 1 para la predicción.

La medida AUC-ROC se usa ampliamente para medir el rendimiento de los clasificadores binarios. Sin embargo, a veces resulta más adecuado evaluar el clasificador en función de las medidas de AUPRC. El gráfico de AUC-ROC visualiza el equilibrio entre la tasa positiva verdadera (TPR) y la tasa de falsos positivos (FPR). La curva AUPRC combina precisión (valor predictivo positivo o PPV) y recuperación (tasa positiva verdadera o TPR) en una sola visualización.

# 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.")