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
- Visual Studio 2022 con la carga de trabajo "Desarrollo de escritorio de .NET" instalada.
- El Archivo de entrenamiento sobre problemas de GitHub delimitado por pestañas (issues_train.tsv).
- El Archivo de prueba sobre problemas de GitHub delimitado por pestañas (issues_test.tsv).
Creación de una aplicación de consola
Creación de un proyecto
Cree una aplicación de consola de C# denominada "GitHubIssueClassification". Seleccione Siguiente.
Elija .NET 7 como marco de trabajo que se va a usar. Seleccione Crear.
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.
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.
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
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.
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
, DataView
y 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:
En Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Agregar>Nuevo elemento.
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;
Quite la definición de clase existente y agregue el código siguiente al archivo GitHubIssueData.cs. Este código tiene dos clases,
GitHubIssue
yIssuePrediction
.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 deFeatures
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 elementofeature
usado para predecir elArea
. - La cuarta columna
Description
es la segundafeature
usada para predecir elArea
.
IssuePrediction
es la clase que se usa para la predicción una vez entrenado el modelo. Tiene un solostring
(Area
) y un atributoPredictedLabel
ColumnName
. ElPredictedLabel
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, aDBContext
enEntity Framework
.- La primera columna
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 BuildAndTrainModel
como 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 Title
y Description
(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
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.