Tutorial: Clasificación de flores de iris mediante la agrupación en clústeres k-means con ML.NET

En este tutorial se muestra cómo usar ML.NET para crear un modelo de agrupación en clústeres para el conjunto de datos de flores de iris.

En este tutorial aprenderá a:

  • Entender el problema
  • Seleccionar la tarea de aprendizaje automático adecuada
  • Preparar los datos
  • Cargar y transformar los datos
  • Elegir un algoritmo de aprendizaje
  • Entrenar el modelo
  • Usar el modelo para las predicciones

Requisitos previos

Entender el problema

Este problema consiste en dividir el conjunto de flores de iris en grupos diferentes según las características de la flor. Esas características son la longitud y el ancho del sépalo, y la longitud y ancho del pétalo. Para este tutorial, se supone que el tipo de cada flor es desconocido. Le interesa conocer la estructura de un conjunto de datos a partir de las características y predecir cómo se ajusta una instancia de datos a esta estructura.

Seleccionar la tarea de aprendizaje automático adecuada

Como no se sabe a qué grupo pertenece cada flor, seleccione la tarea de aprendizaje automático no supervisado. Para dividir un conjunto de datos en grupos de manera que los elementos del mismo grupo sean más similares entre sí que con los de otros grupos, use una tarea de aprendizaje automático de agrupación en clústeres.

Creación de una aplicación de consola

  1. Cree una aplicación de consolaen C# llamada "IrisFlowerClustering". Haga clic en el botón Next (Siguiente).

  2. Seleccione .NET 6 como marco de trabajo que va a usarse. Haga clic en el botón Crear.

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

    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. 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 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 el conjunto de datos iris.data y guárdelo en la carpeta Datos que ha creado en el paso anterior. Para obtener más información sobre el conjunto de datos de iris, vea la página de Wikipedia Conjunto de datos de flor de Iris y la página Iris Data Set (Conjunto de datos Iris), que es el origen del conjunto de datos.

  2. En el Explorador de soluciones, haga clic con el botón derecho en el archivo iris.data y seleccione Propiedades. En Avanzadas, cambie el valor de Copiar en el directorio de salida por Copiar si es posterior.

El archivo iris.data contiene cinco columnas que representan lo siguiente:

  • La longitud del sépalo en centímetros
  • El ancho del sépalo en centímetros
  • La longitud del pétalo en centímetros
  • El ancho del pétalo en centímetros
  • El tipo de flor de iris.

Para el ejemplo de agrupación en clústeres, en este tutorial se ignora la última columna.

Crear clases de datos

Cree clases para los datos de entrada y las predicciones:

  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 IrisData.cs. A continuación, seleccione el botón Agregar.

  3. Agregue la directiva using siguiente al archivo nuevo:

    using Microsoft.ML.Data;
    

Quite la definición de clase existente y agregue el código siguiente, que define dos clases IrisData y ClusterPrediction, al archivo IrisData.cs:

public class IrisData
{
    [LoadColumn(0)]
    public float SepalLength;

    [LoadColumn(1)]
    public float SepalWidth;

    [LoadColumn(2)]
    public float PetalLength;

    [LoadColumn(3)]
    public float PetalWidth;
}

public class ClusterPrediction
{
    [ColumnName("PredictedLabel")]
    public uint PredictedClusterId;

    [ColumnName("Score")]
    public float[]? Distances;
}

IrisData es la clase de datos de entrada y tiene definiciones para cada una de las características del conjunto de datos. Use el atributo LoadColumn para especificar los índices de las columnas de origen en el archivo de conjunto de datos.

La clase ClusterPrediction representa el resultado del modelo de agrupación en clústeres aplicado a una instancia de IrisData. Use el atributo ColumnName para enlazar los campos PredictedClusterId y Distances a las columnas PredictedLabel y Score respectivamente. En el caso de la tarea de agrupación en clústeres, esas columnas tienen el significado siguiente:

  • La columna PredictedLabel contiene el identificador del clúster previsto.
  • La columna Score contiene una matriz con las distancias euclidianas cuadradas a los centroides de clúster. La longitud de la matriz es igual al número de clústeres.

Nota

Use el tipo float para representar los valores de punto flotante en las clases de entrada y predicción de datos.

Definir rutas de acceso de datos y modelos

Vuelva al archivo Program.cs y agregue dos campos para contener las rutas de acceso al archivo de conjuntos de datos y al archivo en el que se guarda el modelo:

  • _dataPath contiene la ruta de acceso al archivo con el conjunto de datos utilizado para entrenar el modelo.
  • _modelPath contiene la ruta de acceso al archivo en el que se almacena el modelo entrenado.

Agregue el código siguiente en las instrucciones using para especificar esas rutas de acceso:

string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "iris.data");
string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "IrisClusteringModel.zip");

Creación del contexto de ML

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

using Microsoft.ML;
using IrisFlowerClustering;

Reemplace la línea Console.WriteLine("Hello World!"); por el código siguiente:

var mlContext = new MLContext(seed: 0);

La clase Microsoft.ML.MLContext representa el entorno de aprendizaje automático y proporciona mecanismos para puntos de entrada y de registro para la carga de datos, entrenamiento del modelo, predicción y otras tareas. Esto es comparable conceptualmente a usar DbContext en Entity Framework.

Configuración de la carga de datos

Agregue el código siguiente al método MLContext para configurar la manera de cargar los datos:

IDataView dataView = mlContext.Data.LoadFromTextFile<IrisData>(_dataPath, hasHeader: false, separatorChar: ',');

El MLContext.Data.LoadFromTextFile método de extensión genérico deduce el esquema del conjunto de datos del tipo IrisData proporcionado y devuelve IDataView, que se puede usar como entrada para los transformadores.

Crear una canalización de aprendizaje

Para este tutorial, la canalización de aprendizaje de la tarea de agrupación en clústeres consta de los dos pasos siguientes:

  • concatenar las columnas cargadas en una columna Características, que usa un instructor de agrupación en clústeres;
  • usar un instructor KMeansTrainer para entrenar el modelo mediante el algoritmo de agrupación en clústeres k-means++.

Agregue lo siguiente después de cargar los datos:

string featuresColumnName = "Features";
var pipeline = mlContext.Transforms
    .Concatenate(featuresColumnName, "SepalLength", "SepalWidth", "PetalLength", "PetalWidth")
    .Append(mlContext.Clustering.Trainers.KMeans(featuresColumnName, numberOfClusters: 3));

En el código se especifica que el conjunto de datos se debe dividir en tres clústeres.

Entrenar el modelo

Los pasos que se agregaron en las secciones anteriores prepararon la canalización para el aprendizaje, pero no se ha ejecutado ninguno. Agregue la siguiente línea al final del archivo para realizar la carga de datos y el entrenamiento del modelo:

var model = pipeline.Fit(dataView);

Guardado del modelo

En este punto, tiene un modelo que se puede integrar en cualquiera de las aplicaciones de .NET nuevas o existentes. Para guardar el modelo en un archivo .zip, agregue el código siguiente debajo de la llamada al método Fit:

using (var fileStream = new FileStream(_modelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
{
    mlContext.Model.Save(model, dataView.Schema, fileStream);
}

Usar el modelo para las predicciones

Para realizar predicciones, use la clase PredictionEngine<TSrc,TDst>, que toma instancias del tipo de entrada a través de la canalización de transformador y genera instancias del tipo de salida. Agregue la línea siguiente para crear una instancia de esa clase:

var predictor = mlContext.Model.CreatePredictionEngine<IrisData, ClusterPrediction>(model);

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.

Cree la clase TestIrisData para guardar las instancias de datos de prueba:

  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 TestIrisData.cs. A continuación, seleccione el botón Agregar.

  3. Modifique la clase para que sea estática, como en el ejemplo siguiente:

    static class TestIrisData
    

En este tutorial se presenta una instancia de datos de iris dentro de esta clase. Puede agregar otros escenarios para experimentar con el modelo. Agregue el código siguiente a la clase TestIrisData:

internal static readonly IrisData Setosa = new IrisData
{
    SepalLength = 5.1f,
    SepalWidth = 3.5f,
    PetalLength = 1.4f,
    PetalWidth = 0.2f
};

Para determinar a qué clúster pertenece el elemento especificado, vuelva al archivo Program.cs y agregue el código siguiente al final:

var prediction = predictor.Predict(TestIrisData.Setosa);
Console.WriteLine($"Cluster: {prediction.PredictedClusterId}");
Console.WriteLine($"Distances: {string.Join(" ", prediction.Distances ?? Array.Empty<float>())}");

Ejecute el programa para ver qué clúster contiene la instancia de datos especificada y las distancias cuadradas desde esa instancia a los centroides de clúster. Los resultados deberían ser similares a los indicados a continuación:

Cluster: 2
Distances: 11.69127 0.02159119 25.59896

¡Enhorabuena! Ha creado correctamente un modelo de aprendizaje automático para la agrupación en clústeres de iris y lo ha usado para realizar predicciones. Puede encontrar el código fuente de este tutorial en el repositorio dotnet/samples de GitHub.

Pasos siguientes

En este tutorial ha aprendido a:

  • Entender el problema
  • Seleccionar la tarea de aprendizaje automático adecuada
  • Preparar los datos
  • Cargar y transformar los datos
  • Elegir un algoritmo de aprendizaje
  • Entrenar el modelo
  • Usar el modelo para las predicciones

Visite nuestro repositorio de GitHub para obtener más información y encontrar más ejemplos.