Compartir a través de


Tutorial: Categorización de problemas de soporte técnico mediante la clasificación multiclase con ML.NET

En este tutorial de ejemplo se muestra 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 de un problema de GitHub a través de una aplicación de consola de .NET mediante C# en Visual Studio.

En este tutorial, aprenderá a:

  • Preparación de los datos
  • Transformación de los datos
  • Entrenamiento del modelo
  • Evaluación del modelo
  • Predicción con el modelo entrenado
  • Implementación y predicción con un modelo cargado

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

Prerrequisitos

Creación de una aplicación de consola

Creación de un proyecto

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

  2. Elija .NET 7 como marco de trabajo que se va a usar. Seleccione Crear.

  3. Cree un directorio denominado Data 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. Cree un directorio denominado Models en el proyecto para guardar el modelo:

    En Solution Explorer, 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 el proyecto y seleccione Administrar paquetes NuGet. Elija "nuget.org" como origen del paquete, seleccione la pestaña Examinar, busque Microsoft.ML y seleccione Instalar. Seleccione el botón OK en el cuadro de diálogo Vista previa de cambios y, a continuación, seleccione el botón Acepto en el cuadro de diálogo Aceptación de Licencia si está de acuerdo con los términos de licencia de los paquetes enumerados.

Preparación de los datos

  1. Descargue los conjuntos de datos issues_train.tsv y issues_test.tsv y guárdelos en la carpeta Data que creó anteriormente. El primer conjunto de datos entrena el modelo de machine Learning y el segundo se puede usar para evaluar la precisión del modelo.

  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.

Creación de clases y definición de rutas de acceso

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

using Microsoft.ML;
using GitHubIssueClassification;

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

  • _trainDataPath tiene la ruta de acceso al conjunto de datos usado para entrenar el modelo.
  • _testDataPath tiene la ruta de acceso al conjunto de datos usado 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 directivas using para especificar esas rutas de acceso y las demás 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 al proyecto:

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

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

    El archivo GitHubIssueData.cs se abre en el editor de código. Agregue la siguiente directiva using a la parte superior de GitHubIssueData.cs:

    using Microsoft.ML.Data;
    
  3. Quite la definición de clase existente y agregue el código siguiente al archivo GitHubIssueData.cs. Este código tiene dos clases, GitHubIssue y IssuePrediction.

    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 tiene los siguientes campos String:

    • La primera columna ID (ID del problema de GitHub).
    • La segunda columna Area (la predicción para el entrenamiento).
    • La tercera columna Title (título del problema de GitHub) es el primer elemento feature usado para predecir el Area.
    • La cuarta columna Description es la segunda feature usada para predecir el Area.

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

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

Inicializar variables

Inicialice la variable global _mlContext con una nueva instancia de MLContext con una semilla aleatoria (seed: 0) para obtener resultados repetibles y deterministas a través de múltiples 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 manera flexible y eficaz de describir datos tabulares numéricos o de texto. IDataView puede cargar archivos de texto o en tiempo real (por ejemplo, archivos de registro o base de datos SQL).

Para inicializar y cargar la variable global _trainingDataView para 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);

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

Agregue lo siguiente después de llamar al método LoadFromTextFile():

var pipeline = ProcessData();

El método ProcessData ejecuta las siguientes tareas:

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

Cree el método ProcessData en la parte inferior del archivo Program.cs con el código siguiente:

IEstimator<ITransformer> ProcessData()
{

}

Extracción de características y transformación de los 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")

A continuación, llame a mlContext.Transforms.Text.FeaturizeText, que transforma las columnas de texto (Title y Description) en un vector numérico para cada uno llamado 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 la preparación de datos combina todas las columnas de características en la columna Características mediante el método Concatenate(). De forma predeterminada, un algoritmo de aprendizaje procesa solo las características de la columna Características. Anexe esta transformación a la canalización con el código siguiente:

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

A continuación, anexe un AppendCacheCheckpoint para almacenar en caché la vista de datos, por lo que al iterar los datos varias veces mediante la memoria caché podría obtener un mejor rendimiento, como con 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 manejar conjuntos de datos muy grandes.

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 puede permitir mejores resultados con el modelo.

Compilación y entrenamiento del modelo

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

var trainingPipeline = BuildAndTrainModel(_trainingDataView, pipeline);

El método BuildAndTrainModel ejecuta las siguientes tareas:

  • Crea la clase de algoritmo de entrenamiento.
  • Entrena el modelo.
  • Predice el área en función de los datos de entrenamiento.
  • Devuelve el modelo.

Cree el método BuildAndTrainModel, justo después de la declaración del método ProcessData(), con 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 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 (binario).

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.

Entrenamiento del modelo

Ajuste el modelo a los datos splitTrainSet y devuelva el modelo entrenado agregando lo siguiente como la siguiente línea de código en el método BuildAndTrainModel():

_trainedModel = trainingPipeline.Fit(trainingDataView);

El método Fit()entrena el modelo mediante la transformación del conjunto de datos y la aplicación del entrenamiento.

El PredictionEngine es una API conveniente que permite introducir y luego realizar una predicción en una sola instancia de datos. Agregue esto como la línea siguiente en el método BuildAndTrainModel():

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

Predicción 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.."
};

Use la función predict() de para realizar una predicción en una sola fila de datos:

var prediction = _predEngine.Predict(issue);

Uso del modelo: Resultados de predicción

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

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

Devolver el modelo entrenado para utilizar en la evaluación

Devuelve el modelo al final del método BuildAndTrainModel.

return trainingPipeline;

Evaluación del modelo

Ahora que ha creado y entrenado el modelo, debe evaluarlo con un conjunto de datos diferente para garantizar la 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 siguientes tareas:

  • 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 mediante el conjunto de datos especificado. Devuelve un objeto MulticlassClassificationMetrics que contiene las métricas generales calculadas por evaluadores de clasificación multiclase. Para mostrar las métricas para determinar la calidad del modelo, primero debe obtenerlas. Observe el uso del método de Transform() de la variable global de aprendizaje automático _trainedModel (una ITransformer) para ingresar las características y devolver predicciones. Agregue el código siguiente al método Evaluate como línea siguiente:

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

Las métricas siguientes 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.
  • Precisión de macro: cada clase contribuye igualmente a la métrica de precisión. Las clases minorías tienen un peso igual 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 pérdida logística: Rango de [-inf, 1.00], donde 1.00 indica predicciones perfectas y 0 indica predicciones medias. Le recomendamos que la reducción de la pérdida de registro esté lo más cerca posible de 1.

Mostrar las métricas para la validación del modelo

Use el código siguiente para mostrar las métricas, compartir los resultados y, a continuación, actuar sobre ellas:

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 satisfecho con el modelo, guárdelo en un archivo para realizar 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 un 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 siguientes tareas:

  • Carga el modelo guardado.
  • Crea un único problema de datos de prueba.
  • Predice el área en función de los datos de prueba.
  • Combina datos de prueba y predicciones para los informes.
  • Muestra los resultados previstos.

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

El PredictionEngine es una API útil que permite realizar una predicción en una sola instancia de datos. PredictionEngine no es seguro para subprocesos. Es aceptable usarlo en entornos de un solo subproceso o prototipo. Para optimizar el rendimiento y garantizar la seguridad de los hilos en entornos de producción, use el servicio PredictionEnginePool, que crea un ObjectPool de PredictionEngine objetos para su utilización 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 de servicio PredictionEnginePool actualmente está en versión preliminar.

Use el 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

Mostrar Area para clasificar el problema y actuar en consecuencia. Cree una presentación para los resultados con el código Console.WriteLine() siguiente:

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

Resultados

Los resultados deben ser similares a los siguientes. A medida que la canalización procesa, muestra mensajes. Es posible que vea advertencias o mensajes de procesamiento. Estos mensajes se han quitado de los siguientes resultados 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 ===============

¡Felicidades! Ahora ha construido con éxito un modelo de aprendizaje automático para la clasificación y predicción de una etiqueta de área de un problema de GitHub. Puede encontrar el código fuente de este tutorial en el repositorio dotnet/samples.

Pasos siguientes

En este tutorial, ha aprendido a:

  • Preparación de los datos
  • Transformación de los datos
  • Entrenamiento del modelo
  • Evaluación del modelo
  • Predicción con el modelo entrenado
  • Implementación y predicción con un modelo cargado

Pase al siguiente tutorial para obtener más información.