Tutorial: Clasificación multiclase de incidencias de soporte técnico con ML.NET

Este tutorial de ejemplo ilustra el uso de ML.NET para crear un clasificador de problemas de GitHub para entrenar un modelo que clasifica y predice la etiqueta de área para un problema de GitHub a través de una aplicación de consola de .NET Core con C# en Visual Studio.

En este tutorial aprenderá a:

  • Preparar los datos
  • Transformar los datos
  • Entrenar el modelo
  • Evaluar el modelo
  • Predecir con el modelo entrenado
  • Implementar y predecir con un modelo cargado

Puede encontrar el código fuente para este tutorial en el repositorio dotnet/samples.

Requisitos previos

Creación de una aplicación de consola

Crear un proyecto

  1. Cree una aplicación de consola en C# denominada "GitHubIssueClassification". Seleccione Siguiente.

  2. Seleccione .NET 7 como marco de trabajo. Seleccione Crear.

  3. Cree un directorio denominado Datos en el proyecto para guardar los archivos del conjunto de datos:

    En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Agregar>Nueva carpeta. Escriba "Datos" y presione Entrar.

  4. En el proyecto, cree un directorio denominado Modelos para guardar el modelo:

    En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Agregar>Nueva carpeta. Escriba "Modelos" y presione Entrar.

  5. Instale el paquete NuGet Microsoft.ML:

    Nota

    En este ejemplo se usa la versión estable más reciente de los paquetes NuGet mencionados, a menos que se indique lo contrario.

    En el Explorador de soluciones, haga clic con el botón derecho en Administrar paquetes NuGet. Elija "nuget.org" como origen del paquete, seleccione la pestaña Examinar, busque Microsoft.ML y seleccione el botón Instalar. Seleccione el botón Aceptar en el cuadro de diálogo Vista previa de cambios y, a continuación, seleccione el botón Acepto del cuadro de diálogo Aceptación de la licencia en caso de que esté de acuerdo con los términos de licencia de los paquetes mostrados.

Preparar los datos

  1. Descargue los conjuntos de datos issues_train.tsv e issues_test.tsv y guárdelos en la carpeta Datos que ha creado anteriormente. El primer conjunto de datos entrena el modelo de aprendizaje automático y el segundo puede usarse para evaluar su grado de precisión.

  2. En el Explorador de soluciones, haga clic con el botón derecho en cada uno de los archivos *.tsv y seleccione Propiedades. En Avanzadas, cambie el valor de Copiar en el directorio de salida por Copiar si es posterior.

Crear clases y definir rutas de acceso

Agregue las siguientes instrucciones using adicionales a la parte superior del archivo Program.cs:

using Microsoft.ML;
using GitHubIssueClassification;

Cree tres campos globales para contener las rutas de acceso a los archivos descargados recientemente y variables globales para MLContext,DataView y PredictionEngine:

  • _trainDataPath tiene la ruta de acceso al conjunto de datos utilizado para entrenar el modelo.
  • _testDataPath tiene la ruta de acceso al conjunto de datos utilizado para evaluar el modelo.
  • _modelPath tiene la ruta de acceso donde se guarda el modelo entrenado.
  • _mlContext es el elemento MLContext que proporciona el contexto de procesamiento.
  • _trainingDataView es el elemento IDataView que se usa para procesar el conjunto de datos de entrenamiento.
  • _predEngine es el elemento PredictionEngine<TSrc,TDst> que se usa para las predicciones únicas.

Agregue el código siguiente a la línea directamente debajo de las instrucciones using para especificar esas rutas de acceso y las otras variables:

string _appPath = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) ?? ".";
string _trainDataPath = Path.Combine(_appPath, "..", "..", "..", "Data", "issues_train.tsv");
string _testDataPath = Path.Combine(_appPath, "..", "..", "..", "Data", "issues_test.tsv");
string _modelPath = Path.Combine(_appPath, "..", "..", "..", "Models", "model.zip");

MLContext _mlContext;
PredictionEngine<GitHubIssue, IssuePrediction> _predEngine;
ITransformer _trainedModel;
IDataView _trainingDataView;

Cree algunas clases para los datos de entrada y las predicciones. Agregue una nueva clase a su proyecto:

  1. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y, a continuación, seleccione Agregar>Nuevo elemento.

  2. En el cuadro de diálogo Agregar nuevo elemento, seleccione Clase y cambie el campo Nombre a GitHubIssueData.cs. A continuación, seleccione el botón Agregar.

    Se abre el archivo GitHubIssueData.cs en el editor de código. Agregue la siguiente instrucción using a la parte superior de GitHubIssueData.cs:

using Microsoft.ML.Data;

Quite la definición de clase existente y agregue el código siguiente, que tiene dos clases GitHubIssue y IssuePrediction, al archivo GitHubIssueData.cs:

public class GitHubIssue
{
    [LoadColumn(0)]
    public string? ID { get; set; }
    [LoadColumn(1)]
    public string? Area { get; set; }
    [LoadColumn(2)]
    public required string Title { get; set; }
    [LoadColumn(3)]
    public required string Description { get; set; }
}

public class IssuePrediction
{
    [ColumnName("PredictedLabel")]
    public string? Area;
}

label es la columna que quiere predecir. Los valores de Features identificados son las entradas que se proporcionan al modelo para predecir la etiqueta.

Use LoadColumnAttribute para especificar los índices de las columnas de origen en el conjunto de datos.

GitHubIssue es la clase de conjunto de datos de entrada y contiene los siguientes campos de String:

  • ID, la primera columna (id. de problema de GitHub).
  • Area, la segunda columna (la predicción para el entrenamiento).
  • Title, la tercera columna (título del problema de GitHub) es el primer feature usado para predecir el Area
  • Description, la cuarta columna, es el segundo objeto feature que se usa para la predicción de Area

IssuePrediction es la clase usada para la predicción una vez entrenado el modelo. Tiene un solo elemento string (Area) y un atributo PredictedLabelColumnName. PredictedLabel se usa durante la predicción y la evaluación. Para la evaluación, se utiliza una entrada con los datos de entrenamiento, los valores de predicción y el modelo.

Todas las operaciones de ML.NET se inician en la clase MLContext. La inicialización de mlContext crea un entorno de ML.NET que se puede compartir entre los objetos del flujo de trabajo de creación de modelos. Es similar, conceptualmente, al DBContext en Entity Framework.

Inicialización de variables

Inicialice la variante global _mlContext con una nueva instancia de MLContext con una inicialización aleatoria (seed: 0) para obtener resultados repetibles o deterministas en varios entrenamientos. Reemplace la línea Console.WriteLine("Hello World!") por el código siguiente:

_mlContext = new MLContext(seed: 0);

Carga de los datos

ML.NET usa la interfaz IDataView como una forma flexible y eficaz de describir datos tabulares de texto o numéricos. IDataView puede cargar archivos de texto o en tiempo real (por ejemplo, una base de datos SQL o archivos de registro).

Para inicializar y cargar la variable global _trainingDataView con el fin de volver a usarla para la canalización, agregue el código siguiente después de la inicialización de mlContext:

_trainingDataView = _mlContext.Data.LoadFromTextFile<GitHubIssue>(_trainDataPath,hasHeader: true);

LoadFromTextFile() define el esquema de datos y lee en el archivo. Toma las variables de ruta de acceso de datos y devuelve IDataView.

Agregue el método siguiente después de la llamada al método LoadFromTextFile():

var pipeline = ProcessData();

El método ProcessData ejecuta las tareas siguientes:

  • Extrae y transforma los datos.
  • Devuelve la canalización de procesamiento.

Cree el método ProcessData al final del archivo Program.cs con el código siguiente:

IEstimator<ITransformer> ProcessData()
{

}

Extracción de características y transformación de datos

Como quiere predecir la etiqueta de GitHub de área para un GitHubIssue, utilice el método MapValueToKey() para transformar la columna Area en una columna Label de tipo de clave numérico (un formato admitido por los algoritmos de clasificación) y agréguela como nueva columna de conjunto de datos:

var pipeline = _mlContext.Transforms.Conversion.MapValueToKey(inputColumnName: "Area", outputColumnName: "Label")

Después, llame a mlContext.Transforms.Text.FeaturizeText que transforma las columnas de texto (Title y Description) en un vector numérico para cada una de nombre TitleFeaturized y DescriptionFeaturized. Anexe la caracterización para ambas columnas a la canalización usando el siguiente código:

.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Title", outputColumnName: "TitleFeaturized"))
.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Description", outputColumnName: "DescriptionFeaturized"))

El último paso de preparación de datos combina todas las columnas de característica en la columna Características con el método Concatenate(). De forma predeterminada, un algoritmo de aprendizaje solo procesa las características de la columna Features. Anexe esta transformación a la canalización usando el siguiente código:

.Append(_mlContext.Transforms.Concatenate("Features", "TitleFeaturized", "DescriptionFeaturized"))

A continuación, anexe AppendCacheCheckpoint para almacenar en caché el objeto DataView, de modo que pueda obtener un mayor rendimiento al iterar los datos varias veces con la caché, como se muestra en el código siguiente:

.AppendCacheCheckpoint(_mlContext);

Advertencia

Use AppendCacheCheckpoint para conjuntos de datos pequeños o medianos para reducir el tiempo de entrenamiento. NO lo use (quite. AppendCacheCheckpoint()) al tratar con grandes conjuntos de datos.

Devuelva la canalización al final del método ProcessData.

return pipeline;

En este paso se controla el preprocesamiento y la caracterización. El uso de componentes adicionales disponibles en ML.NET permite conseguir mejores resultados con el modelo.

Creación y entrenamiento del modelo

Agregue la siguiente llamada al método BuildAndTrainModel junto a la siguiente línea después de la llamada al método ProcessData():

var trainingPipeline = BuildAndTrainModel(_trainingDataView, pipeline);

El método BuildAndTrainModel ejecuta las tareas siguientes:

  • Crea la clase de algoritmo de entrenamiento.
  • Entrena el modelo.
  • Predice el área según los datos de entrenamiento.
  • Devuelve el modelo.

Cree el método BuildAndTrainModel, justo después de la declaración del método ProcessData(), mediante el código siguiente:

IEstimator<ITransformer> BuildAndTrainModel(IDataView trainingDataView, IEstimator<ITransformer> pipeline)
{

}

Acerca de la tarea de clasificación

La clasificación es una tarea de aprendizaje automático que usa datos para determinar la categoría, el tipo o la clase de un elemento o fila de datos y suele ser uno de los siguientes tipos:

  • Binario: A o B.
  • Multiclase: varias categorías que se pueden predecir mediante el uso de un único modelo.

Para este tipo de problema, use un algoritmo de aprendizaje de clasificación multiclase, ya que la predicción de categoría de problema puede ser una de varias categorías (multiclase) en lugar de solo dos (binaria).

Anexe el algoritmo de aprendizaje automático a las definiciones de transformación de datos agregando lo siguiente como primera línea de código en BuildAndTrainModel():

var trainingPipeline = pipeline.Append(_mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy("Label", "Features"))
        .Append(_mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

SdcaMaximumEntropy es el algoritmo de entrenamiento de clasificación multiclase. Se anexa a pipeline y acepta TitleDescription (Features) caracterizados y los parámetros de entrada Label para aprender de los datos históricos.

Entrenar el modelo

Ajuste el modelo a los datos splitTrainSet y devuelva el modelo entrenado. Para ello, agregue lo que se indica a continuación como la siguiente línea de código en el método BuildAndTrainModel():

_trainedModel = trainingPipeline.Fit(trainingDataView);

El método Fit() entrena el modelo transformando el conjunto de datos y aplicando el entrenamiento.

PredictionEngine es una API de conveniencia, que le permite pasar datos y luego realizar una predicción en una única instancia de datos. Agregue esto como siguiente línea en el método BuildAndTrainModel():

_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(_trainedModel);

Predecir con el modelo entrenado

Agregue un problema de GitHub para probar la predicción del modelo entrenado en el método Predict mediante la creación de una instancia de GitHubIssue:

GitHubIssue issue = new GitHubIssue() {
    Title = "WebSockets communication is slow in my machine",
    Description = "The WebSockets communication used under the covers by SignalR looks like is going slow in my development machine.."
};

El uso de la función Predict() realiza una predicción en una sola fila de datos:

var prediction = _predEngine.Predict(issue);

Uso del modelo: resultados de la predicción

Muestre GitHubIssue y la predicción de la etiqueta Area correspondiente para compartir los resultados y actuar en consecuencia. Cree una visualización para los resultados mediante el código Console.WriteLine() siguiente:

Console.WriteLine($"=============== Single Prediction just-trained-model - Result: {prediction.Area} ===============");

Devolución del modelo entrenado para su uso para la evaluación

Devuelva el modelo al final del método BuildAndTrainModel.

return trainingPipeline;

Evaluar el modelo

Ahora que ha creado y entrenado el modelo, debe evaluarlo con otro conjunto de datos para el control de calidad y la validación. En el método Evaluate, el modelo creado en BuildAndTrainModel se pasa para ser evaluado. Cree el método Evaluate, justo después de BuildAndTrainModel, como en el código siguiente:

void Evaluate(DataViewSchema trainingDataViewSchema)
{

}

El método Evaluate ejecuta las tareas siguientes:

  • Carga el conjunto de datos de prueba.
  • Crea el evaluador multiclase.
  • Evalúa el modelo y crea métricas.
  • Muestra las métricas.

Agregue una llamada al nuevo método justo debajo de la llamada al método BuildAndTrainModel mediante el código siguiente:

Evaluate(_trainingDataView.Schema);

Como hizo anteriormente con el conjunto de datos de entrenamiento, cargue el conjunto de datos de prueba agregando el código siguiente al método Evaluate:

var testDataView = _mlContext.Data.LoadFromTextFile<GitHubIssue>(_testDataPath,hasHeader: true);

El método Evaluate() calcula las métricas de calidad del modelo utilizando el conjunto de datos especificado. Devuelve un objeto MulticlassClassificationMetrics que contiene las métricas totales calculadas por evaluadores de clasificación multiclase. Para mostrar las métricas a fin de determinar la calidad del modelo, primero tendrá que obtenerlas. Observe el uso del método Transform() de la variable global _trainedModel de aprendizaje automático (una ITransformer) que da entrada a las características y devuelve predicciones. Agregue el código siguiente al método Evaluate como la siguiente línea:

var testMetrics = _mlContext.MulticlassClassification.Evaluate(_trainedModel.Transform(testDataView));

Las siguientes métricas se evalúan para la clasificación multiclase:

  • Microprecisión: todos los pares de ejemplo y clase contribuyen del mismo modo a la métrica de precisión. Quiere que la microprecisión esté lo más cerca posible de 1.

  • Macroprecisión: todas las clases contribuyen del mismo modo a la métrica de precisión. Las clases minoritarias tienen el mismo peso que las clases más grandes. Quiere que la macroprecisión esté lo más cerca posible de 1.

  • Pérdida de registro: vea Pérdida de registro. Le recomendamos que la pérdida logarítmica esté lo más cerca posible de 0.

  • Reducción de la pérdida de registro: parte de [-inf, 1.00], donde 1.00 equivale a una predicción perfecta, y 0 indica una predicción aproximada. Le recomendamos que la reducción de la pérdida de registro esté lo más cerca posible de 1.

Visualización de las métricas para la validación del modelo

Utilice el código siguiente para mostrar las métricas, compartir los resultados y, a continuación, trabajar con ellos:

Console.WriteLine($"*************************************************************************************************************");
Console.WriteLine($"*       Metrics for Multi-class Classification model - Test Data     ");
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
Console.WriteLine($"*       MicroAccuracy:    {testMetrics.MicroAccuracy:0.###}");
Console.WriteLine($"*       MacroAccuracy:    {testMetrics.MacroAccuracy:0.###}");
Console.WriteLine($"*       LogLoss:          {testMetrics.LogLoss:#.###}");
Console.WriteLine($"*       LogLossReduction: {testMetrics.LogLossReduction:#.###}");
Console.WriteLine($"*************************************************************************************************************");

Guardar el modelo en un archivo

Una vez que esté satisfecho con el modelo, guárdelo en un archivo para hacer predicciones más adelante o en otra aplicación. Agregue el código siguiente al método Evaluate .

SaveModelAsFile(_mlContext, trainingDataViewSchema, _trainedModel);

Cree el método SaveModelAsFile debajo del método Evaluate.

void SaveModelAsFile(MLContext mlContext,DataViewSchema trainingDataViewSchema, ITransformer model)
{

}

Agregue el código siguiente al método SaveModelAsFile. Este código usa el método Save para serializar y almacenar el modelo entrenado como archivo ZIP.

mlContext.Model.Save(model, trainingDataViewSchema, _modelPath);

Implementación y predicción con un modelo

Agregue una llamada al nuevo método justo debajo de la llamada al método Evaluate mediante el código siguiente:

PredictIssue();

Cree el método PredictIssue, justo después del método Evaluate (y justo antes del método SaveModelAsFile) con el código siguiente:

void PredictIssue()
{

}

El método PredictIssue ejecuta las tareas siguientes:

  • Carga el modelo guardado
  • Crea un único problema de datos de prueba.
  • Predice el área según los datos de prueba.
  • Combina datos de prueba y predicciones para la generación de informes.
  • Muestra los resultados de la predicción.

Cargue el modelo guardado en la aplicación agregando el código siguiente al método PredictIssue:

ITransformer loadedModel = _mlContext.Model.Load(_modelPath, out var modelInputSchema);

Agregue un problema de GitHub para probar la predicción del modelo entrenado en el método Predict mediante la creación de una instancia de GitHubIssue:

GitHubIssue singleIssue = new GitHubIssue() { Title = "Entity Framework crashes", Description = "When connecting to the database, EF is crashing" };

Como hizo anteriormente, cree una instancia de PredictionEngine con el código siguiente:

_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(loadedModel);

PredictionEngine es una API de conveniencia, que le permite realizar una predicción en una única instancia de datos. PredictionEngine no es seguro para subprocesos. Es aceptable usarlo en entornos de un solo subproceso o prototipo. Para mejorar el rendimiento y la seguridad para subprocesos en entornos de producción, use el servicio PredictionEnginePool, que crea un ObjectPool de objetos de PredictionEngine para su uso en toda la aplicación. Consulte esta guía sobre cómo usar PredictionEnginePool en una API web de ASP.NET Core.

Nota

La extensión del servicio PredictionEnginePool está actualmente en versión preliminar.

Use PredictionEngine para predecir la etiqueta de GitHub de área agregando el código siguiente al método PredictIssue para la predicción:

var prediction = _predEngine.Predict(singleIssue);

Uso del modelo cargado para la predicción

Muestre Area para poder categorizar el problema y actuar en consecuencia. Cree una visualización para los resultados mediante el código Console.WriteLine() siguiente:

Console.WriteLine($"=============== Single Prediction - Result: {prediction.Area} ===============");

Resultados

Los resultados deberían ser similares a los indicados a continuación. A medida que la canalización procesa, muestra mensajes. Puede ver las advertencias o mensajes de procesamiento. Estos mensajes se han quitado de los resultados siguientes para mayor claridad.

=============== Single Prediction just-trained-model - Result: area-System.Net ===============
*************************************************************************************************************
*       Metrics for Multi-class Classification model - Test Data
*------------------------------------------------------------------------------------------------------------
*       MicroAccuracy:    0.738
*       MacroAccuracy:    0.668
*       LogLoss:          .919
*       LogLossReduction: .643
*************************************************************************************************************
=============== Single Prediction - Result: area-System.Data ===============

¡Enhorabuena! Ya ha creado correctamente un modelo de aprendizaje automático para clasificar y predecir una etiqueta Área de un problema de GitHub. Puede encontrar el código fuente para este tutorial en el repositorio dotnet/samples.

Pasos siguientes

En este tutorial ha aprendido a:

  • Preparar los datos
  • Transformar los datos
  • Entrenar el modelo
  • Evaluar el modelo
  • Predecir con el modelo entrenado
  • Implementar y predecir con un modelo cargado

Siga con el siguiente tutorial para obtener más información