Compartir vía


Tutorial: Entrenamiento de un modelo de clasificación de ML.NET para clasificar imágenes

Aprenda a entrenar un modelo de clasificación para clasificar imágenes mediante un modelo tensorFlow previamente entrenado para el procesamiento de imágenes.

El modelo tensorFlow se ha entrenado para clasificar imágenes en mil categorías. Dado que el modelo de TensorFlow sabe cómo reconocer patrones en imágenes, el modelo de ML.NET puede usar parte de él en su canalización para convertir imágenes sin procesar en características o entradas para entrenar un modelo de clasificación.

En este tutorial, aprenderá a:

  • Comprender el problema
  • Incorporar el modelo TensorFlow previamente entrenado a la canalización de ML.NET
  • Entrenamiento y evaluación del modelo de ML.NET
  • Clasificación de una imagen de prueba

Puede encontrar el código fuente de este tutorial en el repositorio dotnet/samples . De forma predeterminada, la configuración del proyecto de .NET para este tutorial tiene como destino .NET Core 2.2.

Prerrequisitos

Selección de la tarea de aprendizaje automático correcta

Aprendizaje profundo

El aprendizaje profundo es un subconjunto de Machine Learning, que está revolucionando áreas como Computer Vision y reconocimiento de voz.

Los modelos de aprendizaje profundo se entrenan mediante grandes conjuntos de datos etiquetados y redes neuronales que contienen varias capas de aprendizaje. Aprendizaje profundo:

  • Funciona mejor en algunas tareas como la visión por computadora.
  • Requiere grandes cantidades de datos de entrenamiento.

La clasificación de imágenes es una tarea de clasificación específica que nos permite clasificar automáticamente imágenes en categorías como:

  • Detectar una cara humana en una imagen o no.
  • Detección de gatos y perros.

O, como en las imágenes siguientes, determinar si una imagen es un alimento, un juguete o un dispositivo.

imagen de pizza imagen de oso de peluche imagen de tostadora

Nota:

Las imágenes anteriores pertenecen a Wikimedia Commons y se atribuyen de la siguiente manera:

El entrenamiento de un modelo de clasificación de imágenes desde cero requiere establecer millones de parámetros, una ton de datos de entrenamiento etiquetados y una gran cantidad de recursos de proceso (cientos de horas de GPU). Aunque no es tan eficaz como entrenar un modelo personalizado desde cero, el uso de un modelo entrenado previamente le permite acceder a este proceso trabajando con miles de imágenes frente a millones de imágenes etiquetadas y crear un modelo personalizado bastante rápidamente (dentro de una hora en una máquina sin una GPU). Este tutorial escala ese proceso aún más, usando solo una docena de imágenes de entrenamiento.

Inception model está entrenado para clasificar imágenes en mil categorías, pero para este tutorial, debe clasificar imágenes en un conjunto de categorías más pequeño y solo esas categorías. Puede usar la Inception modelcapacidad de reconocer y clasificar imágenes en las nuevas categorías limitadas del clasificador de imágenes personalizado.

  • Víveres
  • Juguete
  • Dispositivo

En este tutorial se usa el modelo de aprendizaje profundo de inicio de TensorFlow, un modelo de reconocimiento de imágenes popular entrenado en el ImageNet conjunto de datos. El modelo tensorFlow clasifica imágenes completas en mil clases, como "Umbrella", "Jersey" y "Lavavajillas".

Dado que el Inception model ya ha sido entrenado previamente en miles de imágenes diferentes, contiene internamente las características de imagen necesarias para la identificación de imágenes. Podemos usar estas características de imagen internas en el modelo para entrenar un nuevo modelo con muchas menos clases.

Como se muestra en el diagrama siguiente, agregará una referencia a los paquetes NuGet de ML.NET en las aplicaciones de .NET o .NET Framework. En segundo plano, ML.NET incluye y hace referencia a la biblioteca nativa TensorFlow que permite escribir código que carga un archivo de modelo entrenado TensorFlow existente.

Diagrama de transformaciones de TensorFlow ML.NET Arch

Clasificación multiclase

Después de usar el modelo de inicio de TensorFlow para extraer características adecuadas como entrada para un algoritmo de aprendizaje automático clásico, se agrega un clasificador multiclase ML.NET.

El instructor específico que se usa en este caso es el algoritmo de regresión logística multinómica.

El algoritmo implementado por este instructor funciona bien en problemas con un gran número de características, que es el caso de un modelo de aprendizaje profundo que funciona en los datos de imagen.

Para más información, consulte Aprendizaje profundo frente al aprendizaje automático.

Data

Hay dos orígenes de datos: el .tsv archivo y los archivos de imagen. El tags.tsv archivo contiene dos columnas: la primera se define como ImagePath y la segunda es la Label correspondiente a la imagen. El siguiente archivo de ejemplo no tiene una fila de encabezado y tiene este aspecto:

broccoli.jpg	food
pizza.jpg	food
pizza2.jpg	food
teddy2.jpg	toy
teddy3.jpg	toy
teddy4.jpg	toy
toaster.jpg	appliance
toaster2.png	appliance

Las imágenes de entrenamiento y pruebas se encuentran en las carpetas de recursos que descargará en un archivo ZIP. Estas imágenes pertenecen a Wikimedia Commons.

Wikimedia Commons, el repositorio multimedia gratuito. Consultado el 10:48, 17 de octubre de 2018 de: https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear

Configuración

Creación de un proyecto

  1. Cree una aplicación de consola de C# denominada "TransferLearningTF". Haga clic en el botón Siguiente .

  2. Elija .NET 8 como marco de trabajo que se va a usar. Haga clic en el botón Crear.

  3. Instale el paquete NuGet de 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 y busque Microsoft.ML.
    • Seleccione el botón Instalar .
    • Seleccione el botón Aceptar en el cuadro de diálogo Vista previa de cambios .
    • 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.
    • Repita estos pasos para Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist y Microsoft.ML.TensorFlow.

Descarga de recursos

  1. Descargue el archivo ZIP del directorio de recursos del proyecto y descomprima.

  2. Copia el directorio assets en tu directorio del proyecto TransferLearningTF. Este directorio y sus subdirectorios contienen los datos y los archivos de soporte técnico (excepto el modelo de inicio, que descargará y agregará en el paso siguiente) necesario para este tutorial.

  3. Descargue el modelo de inicio y descomprima.

  4. Copie el contenido del directorio inception5h que acaba de descomprimir en el directorio TransferLearningTF del proyecto assets/inception. Este directorio contiene el modelo y los archivos de soporte técnico adicionales necesarios para este tutorial, como se muestra en la siguiente imagen:

    Contenido del directorio de inicio

  5. En el Explorador de soluciones, haga clic con el botón derecho en cada uno de los archivos del directorio de recursos y subdirectorios y seleccione Propiedades. En Avanzado, cambie el valor de Copiar al directorio de salida a Copiar si es más reciente.

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

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

    using Microsoft.ML;
    using Microsoft.ML.Data;
    
  2. Agregue el código siguiente a la línea situada debajo de las using directivas para especificar las rutas de acceso de los recursos:

    string _assetsPath = Path.Combine(Environment.CurrentDirectory, "assets");
    string _imagesFolder = Path.Combine(_assetsPath, "images");
    string _trainTagsTsv = Path.Combine(_imagesFolder, "tags.tsv");
    string _testTagsTsv = Path.Combine(_imagesFolder, "test-tags.tsv");
    string _predictSingleImage = Path.Combine(_imagesFolder, "toaster3.jpg");
    string _inceptionTensorFlowModel = Path.Combine(_assetsPath, "inception", "tensorflow_inception_graph.pb");
    
  3. Cree clases para los datos de entrada y las predicciones.

    public class ImageData
    {
        [LoadColumn(0)]
        public string? ImagePath;
    
        [LoadColumn(1)]
        public string? Label;
    }
    

    ImageData es la clase de datos de imagen de entrada y tiene los siguientes String campos:

    • ImagePath contiene el nombre del archivo de imagen.
    • Label contiene un valor para la etiqueta de imagen.
  4. Agregue una nueva clase al proyecto para ImagePrediction:

    public class ImagePrediction : ImageData
    {
        public float[]? Score;
    
        public string? PredictedLabelValue;
    }
    

    ImagePrediction es la clase de predicción de imágenes y tiene los siguientes campos:

    • Score contiene el porcentaje de confianza de una clasificación de imagen determinada.
    • PredictedLabelValue contiene un valor para la etiqueta de clasificación de imágenes previstas.

    ImagePrediction es la clase que se usa para la predicción después de entrenar el modelo. Tiene un string (ImagePath) para la ruta de acceso de la imagen. Label se usa para reutilizar y entrenar el modelo. PredictedLabelValue se usa durante la predicción y evaluación. Para la evaluación, se usa una entrada con datos de entrenamiento, los valores previstos y el modelo.

Inicialización de variables

  1. Inicialice la mlContext variable con una nueva instancia de MLContext. Reemplace la Console.WriteLine("Hello World!") línea por el código siguiente:

    MLContext mlContext = new MLContext();
    

    La MLContext clase es un punto de partida para todas las operaciones de ML.NET e 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.

Crear una estructura para los parámetros del modelo Inception

  1. El modelo Inception tiene varios parámetros que necesita proporcionar. Cree una estructura para asignar los valores de parámetro a nombres descriptivos con el código siguiente, justo después de inicializar la mlContext variable:

    struct InceptionSettings
    {
        public const int ImageHeight = 224;
        public const int ImageWidth = 224;
        public const float Mean = 117;
        public const float Scale = 1;
        public const bool ChannelsLast = true;
    }
    

Crea un método de utilidad de visualización

Dado que mostrará los datos de imagen y las predicciones relacionadas más de una vez, cree un método de utilidad de visualización para controlar la visualización de la imagen y los resultados de predicción.

  1. Cree el DisplayResults() método, justo después del InceptionSettings struct, con el código siguiente:

    void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData)
    {
    
    }
    
  2. Rellene el cuerpo del DisplayResults método :

    foreach (ImagePrediction prediction in imagePredictionData)
    {
        Console.WriteLine($"Image: {Path.GetFileName(prediction.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} ");
    }
    

Creación de un método para realizar una predicción

  1. Cree el ClassifySingleImage() método , justo antes del DisplayResults() método , con el código siguiente:

    void ClassifySingleImage(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Cree un objeto ImageData que contenga la ruta completa junto con el nombre del archivo de imagen para el único ImagePath. Agregue el código siguiente como las líneas siguientes en el ClassifySingleImage() método :

    var imageData = new ImageData()
    {
        ImagePath = _predictSingleImage
    };
    
  3. Realice una sola predicción agregando el código siguiente como la línea siguiente en el ClassifySingleImage método :

    // Make prediction function (input = ImageData, output = ImagePrediction)
    var predictor = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model);
    var prediction = predictor.Predict(imageData);
    

    Para obtener la predicción, use el método Predict(). 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 hilo o en prototipos. Para mejorar el rendimiento y la seguridad de los subprocesos en entornos de producción, use el PredictionEnginePool servicio , que crea un ObjectPool de PredictionEngine objetos 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:

    PredictionEnginePool la extensión de servicio está actualmente en versión preliminar.

  4. Muestre el resultado de la predicción como la siguiente línea de código en el ClassifySingleImage() método :

    Console.WriteLine($"Image: {Path.GetFileName(imageData.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} ");
    

Construye la canalización del modelo de ML.NET

Una tubería de modelo de ML.NET es una cadena de estimadores. No se produce ninguna ejecución durante la construcción de la canalización. Los objetos estimadores se crean pero no se ejecutan.

  1. Adición de un método para generar el modelo

    Este método es el corazón del tutorial. Crea una canalización para el modelo y entrena la canalización para generar el modelo de ML.NET. También evalúa el modelo con algunos datos de prueba no vistos anteriormente.

    Cree el GenerateModel() método , justo después de la InceptionSettings estructura y justo antes del DisplayResults() método , con el código siguiente:

    ITransformer GenerateModel(MLContext mlContext)
    {
    
    }
    
  2. Agregue los estimadores para cargar, cambiar el tamaño y extraer los píxeles de los datos de la imagen:

    IEstimator<ITransformer> pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: _imagesFolder, inputColumnName: nameof(ImageData.ImagePath))
                    // The image transforms transform the images into the model's expected format.
                    .Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: InceptionSettings.ImageWidth, imageHeight: InceptionSettings.ImageHeight, inputColumnName: "input"))
                    .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: InceptionSettings.ChannelsLast, offsetImage: InceptionSettings.Mean))
    

    Los datos de imagen deben procesarse en el formato que espera el modelo de TensorFlow. En este caso, las imágenes se cargan en la memoria, se cambian de tamaño a un tamaño coherente y los píxeles se extraen en un vector numérico.

  3. Agregue el estimador para cargar el modelo de TensorFlow y puntuarlo:

    .Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel).
        ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
    

    Esta fase de la canalización carga el modelo de TensorFlow en memoria y, a continuación, procesa el vector de valores de píxeles a través de la red del modelo de TensorFlow. La aplicación de entradas a un modelo de aprendizaje profundo y la generación de una salida mediante el modelo se conoce como Scoring. Cuando se usa el modelo en su totalidad, la puntuación realiza una inferencia o predicción.

    En este caso, se usan todos los modelos de TensorFlow, excepto la última capa, que es la capa que hace la inferencia. La salida de la capa penúltima está etiquetada softmax_2_preactivation. La salida de esta capa es eficazmente un vector de características que caracterizan las imágenes de entrada originales.

    Este vector de características generado por el modelo de TensorFlow se usará como entrada para un algoritmo de entrenamiento de ML.NET.

  4. Agregue el estimador para mapear las etiquetas de cadena en los datos de entrenamiento a valores clave enteros.

    .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
    

    El entrenador ML.NET que se agrega a continuación requiere que las etiquetas estén en formato key en lugar de cadenas de texto arbitrarias. Una clave es un número que tiene una correspondencia uno a uno con un valor en cadena.

  5. Agregue el algoritmo de entrenamiento ML.NET:

    .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
    
  6. Agregue el estimador para volver a asignar el valor de clave previsto a una cadena:

    .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel"))
    .AppendCacheCheckpoint(mlContext);
    

Entrenamiento del modelo

  1. Cargue los datos de entrenamiento usando el envoltorio LoadFromTextFile. Agregue el código siguiente como la línea siguiente en el GenerateModel() método :

    IDataView trainingData = mlContext.Data.LoadFromTextFile<ImageData>(path:  _trainTagsTsv, hasHeader: false);
    

    Los datos de ML.NET se representan como una interfaz IDataView. IDataView es una manera flexible y eficaz de describir datos tabulares (numéricos y texto). Los datos se pueden cargar desde un archivo de texto o en tiempo real (por ejemplo, archivos de base de datos SQL o de registro) en un IDataView objeto .

  2. Entrene el modelo con los datos cargados anteriormente:

    ITransformer model = pipeline.Fit(trainingData);
    

    El Fit() método entrena el modelo aplicando el conjunto de datos de entrenamiento a la canalización.

Evaluación de la precisión del modelo

  1. Cargue y transforme los datos de prueba agregando el código siguiente a la siguiente línea del GenerateModel método:

    IDataView testData = mlContext.Data.LoadFromTextFile<ImageData>(path: _testTagsTsv, hasHeader: false);
    IDataView predictions = model.Transform(testData);
    
    // Create an IEnumerable for the predictions for displaying results
    IEnumerable<ImagePrediction> imagePredictionData = mlContext.Data.CreateEnumerable<ImagePrediction>(predictions, true);
    DisplayResults(imagePredictionData);
    

    Hay algunas imágenes de ejemplo que puede usar para evaluar el modelo. Al igual que los datos de entrenamiento, estos deben cargarse en un IDataView, para que el modelo pueda transformarlos.

  2. Agregue el código siguiente al GenerateModel() método para evaluar el modelo:

    MulticlassClassificationMetrics metrics =
        mlContext.MulticlassClassification.Evaluate(predictions,
            labelColumnName: "LabelKey",
            predictedLabelColumnName: "PredictedLabel");
    

    Una vez que tenga el conjunto de predicciones, el método Evaluate():

    • Evalúa el modelo (compara los valores previstos con el conjunto de datos labelsde prueba ).
    • Devuelve las métricas de rendimiento del modelo.
  3. Mostrar las métricas de precisió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($"LogLoss is: {metrics.LogLoss}");
    Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
    

    Las métricas siguientes se evalúan para la clasificación de imágenes:

    • Log-loss - consulte Pérdida de registro. Quiere que el logaritmo de pérdida esté lo más cerca posible de cero.
    • Per class Log-loss. Quiere que el Log-loss por clase esté lo más cerca posible de cero.
  4. Agregue el código siguiente para devolver el modelo entrenado como línea siguiente:

    return model;
    

Ejecutar la aplicación

  1. Agregue la llamada a GenerateModel después de la creación de la MLContext clase :

    ITransformer model = GenerateModel(mlContext);
    
  2. Agregue la llamada al ClassifySingleImage() método después de la llamada al GenerateModel() método :

    ClassifySingleImage(mlContext, model);
    
  3. Ejecute la aplicación de consola (Ctrl + F5). Los resultados deben ser similares a los siguientes resultados. (Es posible que vea advertencias o mensajes de procesamiento, pero estos mensajes se han quitado de los siguientes resultados para mayor claridad).

    =============== Training classification model ===============
    Image: broccoli2.jpg predicted as: food with score: 0.8955513
    Image: pizza3.jpg predicted as: food with score: 0.9667718
    Image: teddy6.jpg predicted as: toy with score: 0.9797683
    =============== Classification metrics ===============
    LogLoss is: 0.0653774699265059
    PerClassLogLoss is: 0.110315812569315 , 0.0204391272836966 , 0
    =============== Making single image classification ===============
    Image: toaster3.jpg predicted as: appliance with score: 0.9646884
    

¡Felicidades! Ahora ha creado correctamente un modelo de clasificación en ML.NET para clasificar imágenes mediante un TensorFlow previamente entrenado para el procesamiento de imágenes.

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

En este tutorial, ha aprendido a:

  • Comprender el problema
  • Incorpore el modelo TensorFlow previamente entrenado a la canalización de ML.NET
  • Entrenamiento y evaluación del modelo de ML.NET
  • Clasificación de una imagen de prueba

Consulte el repositorio de GitHub de ejemplos de Machine Learning para explorar un ejemplo de clasificación de imágenes expandida.