Tutorial: Inspeção visual automatizada usando a transferência de aprendizado com a API de Classificação de Imagem do ML.NET

Saiba como treinar um modelo de aprendizado profundo personalizado usando a transferência de aprendizado, um modelo TensorFlow pré-treinado e a API de classificação de imagem do ML.NET para classificar imagens de superfícies concretas como rachadas ou não rachadas.

Neste tutorial, você aprenderá a:

  • Compreender o problema
  • Saber mais sobre a API de Classificação de Imagem do ML.NET
  • Entender o modelo pré-treinado
  • Usar a transferência de aprendizado para treinar um modelo de classificação de imagem do TensorFlow personalizado
  • Classificar imagens com o modelo personalizado

Pré-requisitos

Visão geral do exemplo de transferência de aprendizado de classificação de imagem

Este exemplo é um aplicativo de console do .NET Core em C# que classifica imagens usando um modelo do TensorFlow de aprendizado profundo pré-treinado. O código para este exemplo pode ser encontrado no navegador de exemplos.

Compreender o problema

A classificação de imagem é um problema de pesquisa visual computacional. A classificação de imagem usa uma imagem como entrada e a categoriza em uma classe prescrita. Os modelos de classificação de imagem normalmente são treinados usando redes neurais e de aprendizado profundo. Confira Aprendizado profundo versus machine learning para mais informações.

Alguns cenários em que a classificação de imagem é útil incluem:

  • Reconhecimento de rosto
  • Detecção de Emoções
  • Diagnóstico médico
  • Detecção de monumentos

Este tutorial treina um modelo de classificação de imagem personalizado para executar a inspeção visual automatizada de decks de ponte para identificar estruturas danificadas por rachaduras.

API de Classificação de Imagem do ML.NET

O ML.NET fornece várias maneiras de executar a classificação de imagem. Este tutorial aplica a transferência de aprendizado usando a API de Classificação de Imagem. A API de Classificação de Imagem usa TensorFlow.NET, uma biblioteca de baixo nível que fornece associações C# para a API do TensorFlow C++.

O que é a transferência de aprendizado?

Transferência de aprendizado aplica o conhecimento obtido com a resolução de um problema a outro problema relacionado.

Treinar um modelo de aprendizado profundo do zero requer a configuração de vários parâmetros, uma grande quantidade de dados de treinamento rotulados e uma grande quantidade de recursos de computação (centenas de horas de GPU). O uso de um modelo pré-treinado com a transferência de aprendizado permite que você siga um atalho para o processo de treinamento.

Processo de treinamento

A API de Classificação de Imagem inicia o processo de treinamento carregando um modelo pré-treinado do TensorFlow. O processo de treinamento consiste em duas etapas:

  1. Fase de gargalo
  2. Fase de treinamento

Etapas de treinamento

Fase de gargalo

Durante a fase de gargalo, o conjunto de imagens de treinamento é carregado e os valores de pixel são usados como entrada ou recursos para as camadas congeladas do modelo pré-treinado. As camadas congeladas incluem todas as camadas na rede neural até a penúltima camada, informalmente conhecida como camada de gargalo. Essas camadas são chamadas de congeladas porque nenhum treinamento ocorrerá nelas camadas e as operações são de passagem. É nessas camadas congeladas em que os padrões de nível inferior que ajudam um modelo a distinguir as diferentes classes são calculados. Quanto maior o número de camadas, maior será a utilização computacional dessa etapa. Felizmente, como esse é um cálculo único, os resultados podem ser armazenados em cache e usados em execuções posteriores ao experimentar parâmetros diferentes.

Fase de treinamento

Depois que os valores de saída da fase de gargalo são calculados, eles são usados como entrada para treinar novamente a camada final do modelo. Esse processo é iterativo e é executado pelo número de vezes especificado por parâmetros de modelo. Durante cada execução, a perda e a precisão são avaliadas. Em seguida, os ajustes apropriados são feitos para melhorar o modelo com a meta de minimizar a perda e maximizar a precisão. Depois que o treinamento for concluído, dois formatos de modelo serão gerados. Um deles é a versão .pb do modelo e o outro é a versão serializada .zip do ML.NET do modelo. Ao trabalhar em ambientes compatíveis com ML.NET, é recomendável usar a versão .zip do modelo. No entanto, em ambientes em que não há suporte para ML.NET, você tem a opção de usar a versão .pb.

Entender o modelo pré-treinado

O modelo pré-treinado usado neste tutorial é a variante de 101 camadas do modelo ResNet (Rede Residual) v2. O modelo original é treinado para classificar imagens em mil categorias. O modelo usa como entrada uma imagem do tamanho 224 x 224 e gera as probabilidades de classe para cada uma das classes em que é treinado. Parte desse modelo é usada para treinar um novo modelo usando imagens personalizadas para fazer previsões entre duas classes.

Criar um aplicativo de console

Agora que você tem uma compreensão geral da transferência de aprendizado e da API de Classificação de Imagem, é hora de compilar o aplicativo.

  1. Crie um Aplicativo de Console C# chamado "DeepLearning_ImageClassification_Binary". Clique no botão Avançar.

  2. Escolha o .NET 6 como a estrutura a ser usada. Selecione o botão Criar.

  3. Instale o pacote NuGet Microsoft.ML:

    Observação

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

    1. No Gerenciador de Soluções, clique com o botão direito do mouse no seu projeto e selecione Gerenciar Pacotes NuGet.
    2. Escolha "nuget.org" como a fonte do pacote.
    3. Selecione a guia Procurar.
    4. Marque a caixa de seleção Incluir pré-lançamento.
    5. Pesquise Microsoft.ML.
    6. Selecione o botão Instalar.
    7. Selecione o botão OK na caixa de diálogo Visualizar Alterações e selecione o botão Aceito na caixa de diálogo Aceitação da Licença, se concordar com o termos de licença para os pacotes listados.
    8. Repita essas etapas para os pacotes NuGet Microsoft.ML.Vision, SciSharp.TensorFlow.Redist versão 2.3.1 e Microsoft.ML.ImageAnalytics.

Preparar e compreender os dados

Observação

Os conjuntos de dados deste tutorial são de Maguire, Marc; Dorafshan, Sattar; e Thomas, Robert J., "SDNET2018: A concrete crack image dataset for machine learning applications" (2018). Navegue por todos os conjuntos de dados. Papel 48. https://digitalcommons.usu.edu/all_datasets/48

SDNET2018 é um conjunto de dados de imagem que contém anotações para estruturas de concreto rachadas e não rachadas (decks de ponte, paredes e pavimento).

Amostras do deck de ponte do conjunto de dados SDNET2018

Os dados são organizados em três subdiretórios:

  • D contém imagens do baralho de ponte
  • P contém imagens de pavimento
  • W contém imagens de parede

Cada um desses subdiretórios contém dois subdiretórios prefixados adicionais:

  • C é o prefixo usado para superfícies rachadas
  • U é o prefixo usado para superfícies não rachadas

Neste tutorial, somente imagens do deck de ponte são usadas.

  1. Baixe o conjunto de dados e descompacte-o.
  2. Crie um diretório chamado "ativos" em seu projeto para salvar seus arquivos de conjunto de dados.
  3. Copie os subdiretórios de CD e UD do diretório descompactado recentemente para o diretório de ativos.

Criar classes de entrada e saída

  1. Abra o arquivo Program.cs e substitua as instruções using na parte superior do arquivo pelo seguinte:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.IO;
    using Microsoft.ML;
    using static Microsoft.ML.DataOperationsCatalog;
    using Microsoft.ML.Vision;
    
  2. Abaixo da classe Program em Program.cs, crie uma classe chamada ImageData. Essa classe é usada para representar os dados carregados inicialmente.

    class ImageData
    {
        public string ImagePath { get; set; }
    
        public string Label { get; set; }
    }
    

    ImageData contém as propriedades a seguir:

    • ImagePath é o caminho totalmente qualificado em que a imagem é armazenada.
    • Label é a categoria à qual a imagem pertence. Esse é o valor a ser previsto.
  3. Crie classes para os dados de entrada e saída

    1. Abaixo da classe ImageData, defina o esquema dos dados de entrada em uma nova classe chamada ModelInput.

      class ModelInput
      {
          public byte[] Image { get; set; }
          
          public UInt32 LabelAsKey { get; set; }
      
          public string ImagePath { get; set; }
      
          public string Label { get; set; }
      }
      

      ModelInput contém as propriedades a seguir:

      • Image é a representação byte[] da imagem. O modelo espera que os dados de imagem sejam desse tipo para treinamento.
      • LabelAsKey é a representação numérica do Label.
      • ImagePath é o caminho totalmente qualificado em que a imagem é armazenada.
      • Label é a categoria à qual a imagem pertence. Esse é o valor a ser previsto.

      Somente Image e LabelAsKey são usados para treinar o modelo e fazer previsões. As propriedades ImagePath e Label são mantidas por conveniência para acessar o nome e a categoria do arquivo de imagem original.

    2. Em seguida, abaixo da classe ModelInput, defina o esquema dos dados de saída em uma nova classe chamada ModelOutput.

      class ModelOutput
      {
          public string ImagePath { get; set; }
      
          public string Label { get; set; }
      
          public string PredictedLabel { get; set; }
      }
      

      ModelOutput contém as propriedades a seguir:

      • ImagePath é o caminho totalmente qualificado em que a imagem é armazenada.
      • Label é a categoria original à qual a imagem pertence. Esse é o valor a ser previsto.
      • PredictedLabel é o valor previsto pelo modelo.

      Semelhante a ModelInput, somente PredictedLabel é necessário para fazer previsões, pois ele contém a previsão feita pelo modelo. As propriedades ImagePath e Label são retidas por conveniência para acessar o nome e a categoria do arquivo de imagem original.

Criar diretório de workspace

Quando os dados de treinamento e validação não são alterados com frequência, é uma boa prática armazenar em cache os valores de gargalo computados para execuções adicionais.

  1. Em seu projeto, crie um diretório chamado workspace para armazenar os valores de gargalo computados e a versão .pb do modelo.

Definir caminhos e inicializar variáveis

  1. Nas instruções de uso, defina a localização de seus ativos, valores de gargalo computados e a versão .pb do modelo.

    var projectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../"));
    var workspaceRelativePath = Path.Combine(projectDirectory, "workspace");
    var assetsRelativePath = Path.Combine(projectDirectory, "assets");
    
  2. Inicialize a variável mlContext com uma nova instância de MLContext.

    MLContext mlContext = new MLContext();
    

    A classe MLContext é um ponto de partida para todas as operações do ML.NET, e a inicialização de mlContext cria um novo ambiente do ML.NET que pode ser compartilhado entre os objetos do fluxo de trabalho de criação de modelo. Ele é semelhante, conceitualmente, a DbContext no Entity Framework.

Carregar os dados

Criar método utilitário de carregamento de dados

As imagens são armazenadas em dois subdiretórios. Antes de carregar os dados, ele precisa ser formatado em uma lista de objetos ImageData. Para fazer isso, crie o método LoadImagesFromDirectory.

IEnumerable<ImageData> LoadImagesFromDirectory(string folder, bool useFolderNameAsLabel = true)
{

}
  1. Dentro do LoadImagesFromDirectory, adicione o seguinte código para obter todos os caminhos de arquivo dos subdiretórios:

    var files = Directory.GetFiles(folder, "*",
        searchOption: SearchOption.AllDirectories);
    
  2. Em seguida, itere em cada um dos arquivos usando uma instrução foreach.

    foreach (var file in files)
    {
    
    }
    
  3. Dentro da instrução foreach, verifique se há suporte para as extensões de arquivo. A API de Classificação de Imagem dá suporte a formatos JPEG e PNG.

    if ((Path.GetExtension(file) != ".jpg") && (Path.GetExtension(file) != ".png"))
        continue;
    
    
  4. Em seguida, obtenha o rótulo do arquivo. Se o parâmetro useFolderNameAsLabel estiver definido como true, o diretório pai em que o arquivo é salvo será usado como o rótulo. Caso contrário, ele esperará que o rótulo seja um prefixo do nome do arquivo ou do próprio nome do arquivo.

    var label = Path.GetFileName(file);
    
    if (useFolderNameAsLabel)
        label = Directory.GetParent(file).Name;
    else
    {
        for (int index = 0; index < label.Length; index++)
        {
            if (!char.IsLetter(label[index]))
            {
                label = label.Substring(0, index);
                break;
            }
        }
    }
    
  5. Por fim, crie uma instância de ModelInput.

    yield return new ImageData()
    {
        ImagePath = file,
        Label = label
    };
    

Preparar os dados

  1. Chame o método utilitário LoadImagesFromDirectory para obter a lista de imagens usadas para treinamento depois de inicializar a variável mlContext.

    IEnumerable<ImageData> images = LoadImagesFromDirectory(folder: assetsRelativePath, useFolderNameAsLabel: true);
    
  2. Em seguida, carregue as imagens para um método IDataView usando LoadFromEnumerable.

    IDataView imageData = mlContext.Data.LoadFromEnumerable(images);
    
  3. Os dados são carregados na ordem em que foram lidos dos diretórios. Para equilibrar os dados, embaralhe-os usando o método ShuffleRows.

    IDataView shuffledData = mlContext.Data.ShuffleRows(imageData);
    
  4. Os modelos de machine learning esperam que a entrada esteja em formato numérico. Portanto, alguns pré-processamentos precisam ser feitos nos dados antes do treinamento. Crie uma EstimatorChain composta pelas transformações MapValueToKey e LoadRawImageBytes. A transformação MapValueToKey usa o valor categórico na coluna Label, converte-o em um valor numérico KeyType e armazena-o em uma nova coluna chamada LabelAsKey. O LoadImages usa os valores da coluna ImagePath com o parâmetro imageFolder para carregar imagens para treinamento.

    var preprocessingPipeline = mlContext.Transforms.Conversion.MapValueToKey(
            inputColumnName: "Label",
            outputColumnName: "LabelAsKey")
        .Append(mlContext.Transforms.LoadRawImageBytes(
            outputColumnName: "Image",
            imageFolder: assetsRelativePath,
            inputColumnName: "ImagePath"));
    
  5. Use o método Fit para aplicar os dados ao preprocessingPipelineEstimatorChain seguido pelo método Transform, que retorna um IDataView que contém os dados pré-processados.

    IDataView preProcessedData = preprocessingPipeline
                        .Fit(shuffledData)
                        .Transform(shuffledData);
    
  6. Para treinar um modelo, é importante ter um conjunto de dados de treinamento, bem como um conjunto de dados de validação. O modelo é treinado no conjunto de treinamento. A qualidade das previsões em dados invisíveis é medida pelo desempenho em relação ao conjunto de validação. Com base nos resultados desse desempenho, o modelo faz ajustes no que aprendeu em um esforço para melhorar. O conjunto de validação pode vir da divisão do conjunto de dados original ou de outra fonte que já foi reservada para essa finalidade. Nesse caso, o conjunto de dados pré-processado é dividido em conjuntos de treinamento, validação e teste.

    TrainTestData trainSplit = mlContext.Data.TrainTestSplit(data: preProcessedData, testFraction: 0.3);
    TrainTestData validationTestSplit = mlContext.Data.TrainTestSplit(trainSplit.TestSet);
    

    O exemplo de código acima executa duas divisões. Primeiro, os dados pré-processados são divididos e 70% são usados para treinamento, enquanto os 30% restantes são usados para validação. Em seguida, o conjunto de validação de 30% é dividido em conjuntos de validação e teste em que 90% são usados para validação e 10% são usados para teste.

    Um modo de pensar sobre a finalidade dessas partições de dados é fazer um exame. Ao estudar para um exame, você analisa suas anotações, livros ou outros recursos para entender os conceitos que estão no exame. É para isso que serve o conjunto de trens. Então, você pode fazer um exame simulado para validar seu conhecimento. É aí que o conjunto de validação é útil. Você deseja verificar se você tem uma boa compreensão dos conceitos antes de fazer o exame real. Com base nesses resultados, você anota o que errou ou não entendeu bem e incorporou suas alterações à medida que analisa para o exame real. Por fim, faça o exame. É para isso que o conjunto de testes é usado. Você nunca viu as perguntas que estão no exame e agora usa o que aprendeu com o treinamento e a validação para aplicar seu conhecimento à tarefa em questão.

  7. Atribua às partições seus respectivos valores para os dados de treinamento, validação e teste.

    IDataView trainSet = trainSplit.TrainSet;
    IDataView validationSet = validationTestSplit.TrainSet;
    IDataView testSet = validationTestSplit.TestSet;
    

Definir o pipeline de treinamento

O treinamento de modelo consiste em algumas etapas. Primeiro, a API de Classificação de Imagem é usada para treinar o modelo. Em seguida, os rótulos codificados na coluna PredictedLabel são convertidos novamente em seu valor categórico original usando a transformação MapKeyToValue.

  1. Crie uma variável para armazenar um conjunto de parâmetros obrigatórios e opcionais para um ImageClassificationTrainer.

    var classifierOptions = new ImageClassificationTrainer.Options()
    {
        FeatureColumnName = "Image",
        LabelColumnName = "LabelAsKey",
        ValidationSet = validationSet,
        Arch = ImageClassificationTrainer.Architecture.ResnetV2101,
        MetricsCallback = (metrics) => Console.WriteLine(metrics),
        TestOnTrainSet = false,
        ReuseTrainSetBottleneckCachedValues = true,
        ReuseValidationSetBottleneckCachedValues = true
    };
    

    Um ImageClassificationTrainer usa vários parâmetros opcionais:

    • FeatureColumnName é a coluna usada como entrada para o modelo.
    • LabelColumnName é a coluna para o valor a ser previsto.
    • ValidationSet é o IDataView que contém os dados de validação.
    • Arch define qual das arquiteturas de modelo pré-treinadas usar. Este tutorial usa a variante de 101 camadas do modelo ResNetv2.
    • MetricsCallback associa uma função para acompanhar o progresso durante o treinamento.
    • TestOnTrainSet diz para o modelo medir o desempenho em relação ao conjunto de treinamento quando nenhum conjunto de validação está presente.
    • ReuseTrainSetBottleneckCachedValues diz para o modelo se os valores armazenados em cache devem ser usados na fase de gargalo em execuções subsequentes. A fase de gargalo é uma computação de passagem única que é computacionalmente intensiva na primeira vez que é executada. Se os dados de treinamento não forem alterados e você quiser experimentar usando um número diferente de épocas ou tamanho do lote, usar os valores armazenados em cache reduzirá significativamente o tempo necessário para treinar um modelo.
    • ReuseValidationSetBottleneckCachedValues é semelhante a ReuseTrainSetBottleneckCachedValues, porém, nesse caso, é para o conjunto de dados de validação.
    • WorkspacePath define o diretório em que armazenar os valores de gargalo computados e a versão .pb do modelo.
  2. Defina o pipeline EstimatorChain de treinamento que consiste em mapLabelEstimator e em ImageClassificationTrainer.

    var trainingPipeline = mlContext.MulticlassClassification.Trainers.ImageClassification(classifierOptions)
        .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
    
  3. Use o método Fit para treinar seu modelo.

    ITransformer trainedModel = trainingPipeline.Fit(trainSet);
    

Usar o modelo

Agora que você treinou seu modelo, é hora de usá-lo para classificar imagens.

Crie um método utilitário chamado OutputPrediction para exibir informações de previsão no console.

private static void OutputPrediction(ModelOutput prediction)
{
    string imageName = Path.GetFileName(prediction.ImagePath);
    Console.WriteLine($"Image: {imageName} | Actual Value: {prediction.Label} | Predicted Value: {prediction.PredictedLabel}");
}

Classifique uma só imagem

  1. Crie um método chamado ClassifySingleImage para fazer e gerar uma só previsão de imagem.

    void ClassifySingleImage(MLContext mlContext, IDataView data, ITransformer trainedModel)
    {
    
    }
    
  2. Crie um PredictionEngine dentro do método ClassifySingleImage. O PredictionEngine é uma API de conveniência, que permite passar uma única instância de dados e, em seguida, executar uma previsão nessa única instância de dados.

    PredictionEngine<ModelInput, ModelOutput> predictionEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(trainedModel);
    
  3. Para acessar uma só instância de ModelInput, converta dataIDataView em um IEnumerable usando o método CreateEnumerable e obtenha a primeira observação.

    ModelInput image = mlContext.Data.CreateEnumerable<ModelInput>(data,reuseRowObject:true).First();
    
  4. Use o método Predict para classificar a imagem.

    ModelOutput prediction = predictionEngine.Predict(image);
    
  5. Gere a previsão para o console com o método OutputPrediction.

    Console.WriteLine("Classifying single image");
    OutputPrediction(prediction);
    
  6. Chame ClassifySingleImage abaixo chamando o método Fit usando o conjunto de testes de imagens.

    ClassifySingleImage(mlContext, testSet, trainedModel);
    

Classificar várias imagens

  1. Adicione um método chamado ClassifyImages abaixo do método ClassifySingleImage para fazer e gerar várias previsões de imagem.

    void ClassifyImages(MLContext mlContext, IDataView data, ITransformer trainedModel)
    {
    
    }
    
  2. Crie uma IDataView contendo as previsões usando o método Transform. Adicione o seguinte código dentro do método ClassifyImages.

    IDataView predictionData = trainedModel.Transform(data);
    
  3. Para iterar as previsões, converta predictionDataIDataView em um método IEnumerable usando CreateEnumerable e obtenha as primeiras 10 observações.

    IEnumerable<ModelOutput> predictions = mlContext.Data.CreateEnumerable<ModelOutput>(predictionData, reuseRowObject: true).Take(10);
    
  4. Iterar e gerar os rótulos originais e previstos para as previsões.

    Console.WriteLine("Classifying multiple images");
    foreach (var prediction in predictions)
    {
        OutputPrediction(prediction);
    }
    
  5. Por fim, chame ClassifyImages abaixo do método ClassifySingleImage() usando o conjunto de testes de imagens.

    ClassifyImages(mlContext, testSet, trainedModel);
    

Executar o aplicativo

Execute seu aplicativo de console. A saída deve ser semelhante àquela abaixo. Você poderá ver avisos ou mensagens de processamento, mas essas mensagens foram removidas dos resultados a seguir para maior clareza. Para fins de brevidade, a saída foi condensada.

Fase de gargalo

Nenhum valor é impresso para o nome da imagem porque as imagens são carregadas como um byte[], portanto, não há nenhum nome de imagem a ser exibido.

Phase: Bottleneck Computation, Dataset used:      Train, Image Index: 279
Phase: Bottleneck Computation, Dataset used:      Train, Image Index: 280
Phase: Bottleneck Computation, Dataset used: Validation, Image Index:   1
Phase: Bottleneck Computation, Dataset used: Validation, Image Index:   2

Fase de treinamento

Phase: Training, Dataset used: Validation, Batch Processed Count:   6, Epoch:  21, Accuracy:  0.6797619
Phase: Training, Dataset used: Validation, Batch Processed Count:   6, Epoch:  22, Accuracy:  0.7642857
Phase: Training, Dataset used: Validation, Batch Processed Count:   6, Epoch:  23, Accuracy:  0.7916667

Classificar a saída de imagens

Classifying single image
Image: 7001-220.jpg | Actual Value: UD | Predicted Value: UD

Classifying multiple images
Image: 7001-220.jpg | Actual Value: UD | Predicted Value: UD
Image: 7001-163.jpg | Actual Value: UD | Predicted Value: UD
Image: 7001-210.jpg | Actual Value: UD | Predicted Value: UD

Após a inspeção da imagem 7001-220.jpg, você pode ver que ela de fato não está rachada.

Imagem do conjunto de dados SDNET2018 usado para previsão

Parabéns! Agora você criou com sucesso um modelo de aprendizado profundo para classificar imagens.

Aprimorar o modelo

Se você não estiver satisfeito com os resultados do modelo, tente melhorar o desempenho tentando algumas das seguintes abordagens:

  • Mais dados: quanto mais exemplos um modelo aprender, melhor será seu desempenho. Baixe o conjunto de dados SDNET2018 completo e use-o para treinar.
  • Aumentar os dados: uma técnica comum para adicionar variedade aos dados é aumentar os dados usando uma imagem e aplicando diferentes transformações (girar, inverter, mudar, cortar). Isso adiciona exemplos mais variados para o modelo aprender.
  • Treinar por mais tempo: quanto mais tempo você treinar, mais ajustado ficará o modelo. Aumentar o número de épocas pode melhorar o desempenho do modelo.
  • Experimentar os hiperparâmetros: além dos parâmetros usados neste tutorial, outros parâmetros podem ser ajustados para melhorar potencialmente o desempenho. Alterar a taxa de aprendizado, que determina a magnitude das atualizações feitas no modelo após cada época, pode melhorar o desempenho.
  • Usar uma arquitetura de modelo diferente: dependendo da aparência dos dados, o modelo que pode aprender melhor seus recursos pode ser diferente. Se você não estiver satisfeito com o desempenho do modelo, tente alterar a arquitetura.

Próximas etapas

Neste tutorial, você aprendeu a criar um modelo de aprendizado profundo personalizado usando a transferência de aprendizado, um modelo TensorFlow de classificação de imagem pré-treinado e a API de Classificação de Imagem ML.NET para classificar imagens de superfícies de concreto como rachadas ou não rachadas.

Avance para o próximo tutorial para saber mais.