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
- Visual Studio 2022 con la carga de trabajo "Desarrollo de escritorio de .NET" instalada.
- Archivo de problemas de GitHub delimitado por pestañas (issues_train.tsv).
- Prueba de problemas de GitHub delimitado por pestañas (issues_test.tsv).
Creación de una aplicación de consola
Crear un proyecto
Cree una aplicación de consola en C# denominada "GitHubIssueClassification". Seleccione Siguiente.
Seleccione .NET 7 como marco de trabajo. Seleccione Crear.
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.
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.
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
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.
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:
En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y, a continuación, seleccione Agregar>Nuevo elemento.
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 primerfeature
usado para predecir elArea
Description
, la cuarta columna, es el segundo objetofeature
que se usa para la predicción deArea
IssuePrediction
es la clase usada para la predicción una vez entrenado el modelo. Tiene un solo elemento string
(Area
) y un atributo PredictedLabel
ColumnName
. 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 Title
y Description
(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