Partilhar via


Tutorial: Treine um modelo de classificação ML.NET para categorizar imagens

Aprenda a treinar um modelo de classificação para categorizar imagens usando um modelo TensorFlow pré-treinado para processamento de imagens.

O modelo TensorFlow foi treinado para classificar imagens em mil categorias. Como o modelo TensorFlow sabe reconhecer padrões em imagens, o modelo ML.NET pode utilizar parte dele no seu pipeline para converter imagens raw em características ou entradas para treinar um modelo de classificação.

Neste tutorial, aprenderás como:

  • Entenda o problema
  • Incorpore o modelo pré-treinado TensorFlow na pipeline do ML.NET
  • Treine e avalie o modelo ML.NET
  • Classificar uma imagem de teste

Podes encontrar o código-fonte deste tutorial no repositório dotnet/samples . Por padrão, a configuração do projeto .NET para este tutorial tem como alvo o .NET Core 2.2.

Pré-requisitos

Selecione a tarefa de aprendizagem automática certa

Aprendizagem profunda

A aprendizagem profunda é um subconjunto da Aprendizagem Automática, que está a revolucionar áreas como a visão computacional e o reconhecimento de voz.

Os modelos de aprendizagem profunda são treinados utilizando grandes conjuntos de dados rotulados e redes neuronais que contêm múltiplas camadas de aprendizagem. Aprendizagem profunda:

  • Tem melhor desempenho em algumas tarefas como visão computacional.
  • Requer enormes quantidades de dados de treino.

A classificação de imagens é uma tarefa específica de classificação que nos permite classificar automaticamente imagens em categorias tais como:

  • Detetar um rosto humano numa imagem ou não.
  • Detetar gatos vs. cães.

Ou, como nas imagens seguintes, determinar se uma imagem é um alimento, brinquedo ou eletrodoméstico:

Imagem da pizza Imagem do ursinho de peluche Imagem da torradeira

Observação

As imagens anteriores pertencem à Wikimedia Commons e são atribuídas da seguinte forma:

Treinar um modelo de classificação de imagem do zero requer definir milhões de parâmetros, uma tonelada de dados de treino rotulados e uma enorme quantidade de recursos de computação (centenas de horas de GPU). Embora não seja tão eficaz como treinar um modelo personalizado do zero, usar um modelo pré-treinado permite-lhe encurtar este processo trabalhando com milhares de imagens em vez de milhões de imagens rotuladas e construir um modelo personalizado relativamente rapidamente (dentro de uma hora numa máquina sem GPU). Este tutorial reduz ainda mais esse processo, usando apenas uma dúzia de imagens de treino.

O Inception model é treinado para classificar imagens em mil categorias, mas para este tutorial, deve classificar imagens num conjunto de categorias mais reduzido, e apenas nessas categorias. Pode usar a Inception modelcapacidade de reconhecer e classificar imagens para as novas categorias limitadas do seu classificador de imagens personalizado.

  • Alimentação
  • Brinquedo
  • Aparelho

Este tutorial utiliza o modelo de aprendizagem profunda TensorFlow Inception , um modelo popular de reconhecimento de imagens treinado com o conjunto de ImageNet dados. O modelo TensorFlow classifica imagens inteiras em mil classes, como "Umbrella", "Jersey" e "Dishwasher".

Como o Inception model já foi pré-treinado em milhares de imagens diferentes, internamente contém as características de imagem necessárias para a identificação de imagens. Podemos utilizar estas características internas da imagem no modelo para treinar um novo modelo com muito menos classes.

Como mostrado no diagrama seguinte, adicionar uma referência aos pacotes NuGet do ML.NET na sua aplicação .NET ou .NET Framework. Nos bastidores, o ML.NET inclui e faz referência à biblioteca nativa TensorFlow que permite escrever código que carrega um ficheiro de modelo treinado TensorFlow existente.

Diagrama de arquitetura de transformação TensorFlow do ML.NET

Classificação multiclasse

Depois de usar o modelo de início TensorFlow para extrair características adequadas como entrada para um algoritmo clássico de aprendizagem automática, adiciona-se um classificador multiclasse ML.NET.

O treinador específico utilizado neste caso é o algoritmo de regressão logística multinomial.

O algoritmo implementado por este formador tem um bom desempenho em problemas com um grande número de funcionalidades, como é o caso de um modelo de aprendizagem profunda que opera com dados de imagem.

Para mais informações, veja Deep learning vs. machine learning.

Data

Existem duas fontes de dados: o .tsv ficheiro e os ficheiros de imagem. O tags.tsv ficheiro contém duas colunas: a primeira é definida como ImagePath e a segunda é a Label correspondente à imagem. O seguinte ficheiro de exemplo não tem linha de cabeçalho e tem este aspeto:

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

As imagens de treino e testes estão localizadas nas pastas de assets que irá descarregar num ficheiro zip. Estas imagens pertencem à Wikimedia Commons.

Wikimedia Commons, o repositório gratuito de media. Consultado às 10:48, 17 de outubro de 2018 de: https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear

Configuração

Criar um projeto

  1. Crie uma aplicação de consola C# chamada "TransferLearningTF". Clique no botão Seguinte.

  2. Escolhe o .NET 8 como framework a usar. Clique no botão Criar .

  3. Instale o Pacote Microsoft.ML NuGet:

    Observação

    Este exemplo utiliza a versão estável mais recente dos pacotes NuGet mencionados, salvo indicação em contrário.

    • No Explorador de Soluções, clique com o botão direito no seu projeto e selecione Gerir Pacotes NuGet.
    • Escolha "nuget.org" como a fonte do Pacote, selecione o separador Navegar, procure por Microsoft.ML.
    • Selecione o botão Instalar.
    • Selecione o botão OK na janela de Pré-visualização de Alterações .
    • Selecione o botão Aceitar no diálogo de Aceitação de Licença se concordar com os termos da licença dos pacotes listados.
    • Repita estes passos para Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist e Microsoft.ML.TensorFlow.

Descarregar recursos

  1. Descarregue o ficheiro zip do diretório de ativos do projeto e descompacte.

  2. Copie o assets diretório para o diretório do seu projeto TransferLearningTF . Este diretório e os seus subdiretórios contêm os dados e ficheiros de suporte (exceto o modelo Inception, que irá descarregar e adicionar no próximo passo) necessários para este tutorial.

  3. Descarrega o modelo Inception e descomprime.

  4. Copie o conteúdo do diretório inception5h que acabou de descompactar para o diretório do seu projeto TransferLearningTF. Este diretório contém o modelo e ficheiros de suporte adicionais necessários para este tutorial, como mostrado na imagem seguinte:

    Conteúdos do diretório Inception

  5. No Explorador de Soluções, clique com o botão direito em cada um dos ficheiros no diretório e subdiretórios do ativo e selecione Propriedades. Em Avançado, altere o valor de Copiar para Diretório de Saída para Cópia, se for mais recente.

Criar classes e definir caminhos

  1. Adicione as seguintes diretivas adicionais using no topo do ficheiro Program.cs :

    using Microsoft.ML;
    using Microsoft.ML.Data;
    
  2. Adicione o seguinte código à linha logo abaixo das using diretivas para especificar os caminhos dos ativos:

    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. Cria classes para os teus dados de entrada e previsões.

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

    ImageData é a classe de dados da imagem de entrada e tem os seguintes String campos:

    • ImagePath contém o nome do ficheiro imagem.
    • Label contém um valor para a etiqueta da imagem.
  4. Adicione uma nova turma ao seu projeto para ImagePrediction:

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

    ImagePrediction é a classe de previsão da imagem e tem os seguintes campos:

    • Score contém a percentagem de confiança para uma dada classificação de imagem.
    • PredictedLabelValue contém um valor para a etiqueta de classificação de imagem prevista.

    ImagePrediction é a classe usada para a previsão após o modelo ter sido treinado. Tem um string (ImagePath) para o percurso da imagem. É Label usado para reutilizar e treinar o modelo. É PredictedLabelValue utilizado durante a previsão e avaliação. Para avaliação, utiliza-se uma entrada com dados de treino, os valores previstos e o modelo.

Inicializar variáveis

  1. Inicialize a mlContext variável com uma nova instância de MLContext. Substitua a Console.WriteLine("Hello World!") linha pelo seguinte código:

    MLContext mlContext = new MLContext();
    

    A MLContext classe é um ponto de partida para todas as operações ML.NET, e a inicialização mlContext cria um novo ambiente ML.NET que pode ser partilhado entre os objetos de fluxo de trabalho de criação de modelos. É semelhante, do ponto de vista conceptual, ao DBContext no Entity Framework.

Criar uma estrutura para os parâmetros do modelo Inception

  1. O modelo Inception tem vários parâmetros que tens de cumprir. Crie um struct para mapear os valores dos parâmetros para nomes amigáveis com o seguinte código, logo após inicializar a variável mlContext.

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

Criar um método de utilidade de visualização

Como irá mostrar os dados da imagem e as previsões relacionadas mais do que uma vez, crie um método utilitário de visualização para gerir a visualização da imagem e dos resultados da previsão.

  1. Crie o DisplayResults() método, logo após a InceptionSettings struct, usando o seguinte código:

    void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData)
    {
    
    }
    
  2. Preencha o corpo do DisplayResults método:

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

Crie um método para fazer uma previsão

  1. Crie o ClassifySingleImage() método, mesmo antes do DisplayResults() método, usando o seguinte código:

    void ClassifySingleImage(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Crie um ImageData objeto que contenha o caminho totalmente qualificado e o nome do ficheiro de imagem para o único ImagePath. Adicione o seguinte código como as linhas seguintes no ClassifySingleImage() método:

    var imageData = new ImageData()
    {
        ImagePath = _predictSingleImage
    };
    
  3. Faça uma única previsão, adicionando o seguinte código como a linha seguinte do ClassifySingleImage método:

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

    Para obter a previsão, use o método Predict(). O PredictionEngine é uma API de conveniência, que permite realizar uma previsão sobre uma única instância de dados. PredictionEngine não é seguro para rosca. É aceitável usar em ambientes monofio ou ambientes de protótipo. Para melhorar o desempenho e a segurança das threads em ambientes de produção, use o PredictionEnginePool serviço, que cria um ObjectPool conjunto de PredictionEngine objetos para usar em toda a sua aplicação. Consulte este guia sobre como usar PredictionEnginePool numa API Web Core ASP.NET.

    Observação

    PredictionEnginePool A extensão do serviço está atualmente em pré-visualização.

  4. Mostrar o resultado da previsão como a próxima linha de código no ClassifySingleImage() método:

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

Construir o pipeline do modelo ML.NET

Um fluxo de trabalho de modelos ML.NET é uma cadeia de estimadores. Não ocorre nenhuma execução durante a construção do oleoduto. Os objetos estimadores são criados mas não executados.

  1. Adicionar um método para gerar o modelo

    Este método é o cerne do tutorial. Cria um pipeline para o modelo e treina esse pipeline para produzir o modelo ML.NET. Também avalia o modelo com base em alguns dados de teste anteriormente inéditos.

    Crie o GenerateModel() método, logo após a InceptionSettings estrutura e logo antes do DisplayResults() método, usando o seguinte código:

    ITransformer GenerateModel(MLContext mlContext)
    {
    
    }
    
  2. Adicione os estimadores para carregar, redimensionar e extrair os píxeis dos dados da imagem:

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

    Os dados da imagem precisam de ser processados no formato que o modelo TensorFlow espera. Neste caso, as imagens são carregadas na memória, redimensionadas para um tamanho consistente, e os píxeis são extraídos num vetor numérico.

  3. Adicione o estimador para carregar o modelo TensorFlow, e pontue-o:

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

    Esta etapa do pipeline carrega o modelo TensorFlow na memória e depois processa o vetor dos valores dos píxeis através da rede de modelos TensorFlow. Aplicar entradas a um modelo de aprendizagem profunda e gerar uma saída usando o modelo é denominado Scoring. Ao usar o modelo na sua totalidade, a pontuação faz uma inferência, ou previsão.

    Neste caso, usas todo o modelo TensorFlow exceto a última camada, que é a camada que faz a inferência. A saída da penúltima camada é rotulada como softmax_2_preactivation. A saída desta camada é efetivamente um vetor de características que caracterizam as imagens de entrada originais.

    Este vetor de características gerado pelo modelo TensorFlow será usado como entrada para um algoritmo de treino ML.NET.

  4. Adicione o estimador para mapear as etiquetas das cadeias nos dados de treino para valores inteiros de chave:

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

    O treinador do ML.NET que é adicionado a seguir exige que as suas etiquetas estejam no formato key em vez de strings arbitrárias. Uma chave é um número que tem um mapeamento um para um para um valor de cadeia.

  5. Adicione o algoritmo de treino ML.NET:

    .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
    
  6. Adicione o estimador para mapear o valor-chave previsto de volta numa cadeia:

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

Treinar o modelo

  1. Carregue os dados de treino usando o wrapper LoadFromTextFile. Adicione o seguinte código como a linha seguinte no GenerateModel() método:

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

    Os dados em ML.NET são representados como uma interface IDataView. IDataView é uma forma flexível e eficiente de descrever dados tabulares (numéricos e textuais). Os dados podem ser carregados a partir de um ficheiro de texto ou em tempo real (por exemplo, base de dados SQL ou ficheiros de log) para um IDataView objeto.

  2. Treine o modelo com os dados carregados acima:

    ITransformer model = pipeline.Fit(trainingData);
    

    O Fit() método treina o seu modelo aplicando o conjunto de dados de treino ao pipeline.

Avaliar a precisão do modelo

  1. Carregue e transforme os dados de teste, adicionando o seguinte código à linha seguinte do 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);
    

    Existem algumas imagens de exemplo que pode usar para avaliar o modelo. Tal como os dados de treino, estes precisam de ser carregados num IDataView, para que possam ser transformados pelo modelo.

  2. Adicione o seguinte código ao GenerateModel() método para avaliar o modelo:

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

    Depois de definir a previsão, o método Evaluate():

    • Avalia o modelo (compara os valores previstos com o conjunto de dados labelsde teste ).
    • Devolve as métricas de desempenho do modelo.
  3. Mostrar as métricas de precisão do modelo

    Use o seguinte código para mostrar as métricas, partilhar os resultados e depois agir com base neles:

    Console.WriteLine($"LogLoss is: {metrics.LogLoss}");
    Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
    

    As seguintes métricas são avaliadas para classificação de imagens:

    • Log-loss - ver Perda de Log. Queres que a perda logarítmica seja o mais próxima possível de zero.
    • Per class Log-loss. Queres que a perda logarítima por classe seja o mais próxima possível de zero.
  4. Adicione o seguinte código para devolver o modelo treinado na linha seguinte:

    return model;
    

Execute o aplicativo

  1. Adicione a chamada após GenerateModel a criação da MLContext turma:

    ITransformer model = GenerateModel(mlContext);
    
  2. Adicione a chamada ao ClassifySingleImage() método após a chamada ao GenerateModel() método:

    ClassifySingleImage(mlContext, model);
    
  3. Executa a tua aplicação de consola (Ctrl + F5). Os seus resultados devem ser semelhantes aos resultados seguintes. (Pode ver avisos ou mensagens de processamento, mas estas mensagens foram removidas dos resultados seguintes para maior clareza.)

    =============== 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
    

Parabéns! Agora construiu com sucesso um modelo de classificação em ML.NET para categorizar imagens, utilizando um TensorFlow pré-treinado para processamento de imagens.

Podes encontrar o código-fonte deste tutorial no repositório dotnet/samples .

Neste tutorial, você aprendeu como:

  • Entenda o problema
  • Incorpore o modelo pré-treinado TensorFlow na pipeline do ML.NET
  • Treine e avalie o modelo ML.NET
  • Classificar uma imagem de teste

Consulte o repositório de exemplos de Machine Learning no GitHub para explorar uma amostra expandida de classificação de imagens.