Partilhar via


Tutorial: Analise o sentimento das críticas de filmes usando um modelo TensorFlow pré-treinado no ML.NET

Este tutorial mostra como usar um modelo TensorFlow pré-treinado para classificar o sentimento nos comentários do site. O classificador de sentimento binário é um aplicativo de console C# desenvolvido usando o Visual Studio.

O modelo TensorFlow usado neste tutorial foi treinado usando revisões de filmes do banco de dados IMDB. Depois de terminar de desenvolver o aplicativo, você será capaz de fornecer texto de revisão de filme e o aplicativo irá dizer-lhe se o comentário tem sentimento positivo ou negativo.

Neste tutorial, você aprenderá a:

  • Carregar um modelo TensorFlow pré-treinado
  • Transforme o texto de comentários do site em recursos adequados para o modelo
  • Use o modelo para fazer uma previsão

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

Pré-requisitos

Configuração

Criar o aplicativo

  1. Crie um aplicativo de console C# chamado "TextClassificationTF". Clique no botão Avançar.

  2. Escolha .NET 8 como a estrutura a ser usada. Clique no botão Criar.

  3. Crie um diretório chamado Data em seu projeto para salvar seus arquivos de conjunto de dados.

  4. Instale o Microsoft.ML pacote NuGet:

    Observação

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

    No Gerenciador de Soluções, clique com o botão direito do mouse em seu projeto e selecione Gerenciar pacotes NuGet. Escolha "nuget.org" como a fonte do pacote e, em seguida, selecione o separador Procurar. Procure Microsoft.ML, selecione o pacote desejado e, em seguida, selecione Instalar. Prossiga com a instalação concordando com os termos de licença para o pacote que você escolher. Repita estas etapas para Microsoft.ML.TensorFlow , Microsoft.ML.SampleUtils e SciSharp.TensorFlow.Redist .

Adicionar o modelo TensorFlow ao projeto

Observação

O modelo para este tutorial é do dotnet/machinelearning-testdata repositório GitHub. O modelo está no formato TensorFlow SavedModel.

  1. Baixe o arquivo zip sentiment_modele descompacte.

    O ficheiro zip contém:

    • saved_model.pb: o próprio modelo TensorFlow. O modelo usa uma matriz inteira de comprimento fixo (tamanho 600) de recursos que representam o texto em uma cadeia de caracteres de revisão IMDB e produz duas probabilidades que somam 1: a probabilidade de que a revisão de entrada tenha sentimento positivo e a probabilidade de que a revisão de entrada tenha sentimento negativo.
    • imdb_word_index.csv: um mapeamento de palavras individuais para um valor inteiro. O mapeamento é usado para gerar os recursos de entrada para o modelo TensorFlow.
  2. Copie o conteúdo do diretório sentiment_model mais interno para o diretório sentiment_model do projeto TextClassificationTF. Este diretório contém o modelo e os arquivos de suporte adicionais necessários para este tutorial, conforme mostrado na imagem a seguir:

    sentiment_model conteúdo do diretório

  3. No Gerenciador de Soluções, clique com o botão direito do mouse em cada um dos arquivos no diretório e subdiretório sentiment_model e selecione Propriedades. Em Avançado , altere o valor de Copy para Output Directory para Copy semais recente .

Adicionar diretivas using e variáveis globais

  1. Adicione as seguintes diretivas using adicionais à parte superior do arquivo Program.cs:

    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms;
    
  2. Crie uma variável global logo após as diretivas using para manter o caminho do arquivo de modelo salvo.

    string _modelPath = Path.Combine(Environment.CurrentDirectory, "sentiment_model");
    
    • _modelPath é o caminho do arquivo do modelo treinado.

Modelar os dados

As resenhas de filmes são textos de forma livre. Seu aplicativo converte o texto no formato de entrada esperado pelo modelo em vários estágios discretos.

A primeira é dividir o texto em palavras separadas e usar o arquivo de mapeamento fornecido para mapear cada palavra em uma codificação inteira. O resultado desta transformação é uma matriz inteira de comprimento variável com um comprimento correspondente ao número de palavras na frase.

Propriedade Valor Tipo
Texto de revisão este filme é muito bom string
CaracterísticasDeComprimentoVariável 14,22,9,66,78,... int[]

A matriz de feição de comprimento variável é então redimensionada para um comprimento fixo de 600. Este é o comprimento que o modelo TensorFlow espera.

Propriedade Valor Tipo
Texto de revisão este filme é muito bom string
CaracterísticasDeComprimentoVariável 14,22,9,66,78,... int[]
Caraterísticas 14,22,9,66,78,... int[600]
  1. Crie uma classe para os dados de entrada no final do arquivo de Program.cs.

    /// <summary>
    /// Class to hold original sentiment data.
    /// </summary>
    public class MovieReview
    {
        public string? ReviewText { get; set; }
    }
    

    A classe de dados de entrada, MovieReview, tem um string para comentários do usuário (ReviewText).

  2. Crie uma classe para os recursos de comprimento variável após a classe MovieReview:

    /// <summary>
    /// Class to hold the variable length feature vector. Used to define the
    /// column names used as input to the custom mapping action.
    /// </summary>
    public class VariableLength
    {
        /// <summary>
        /// This is a variable length vector designated by VectorType attribute.
        /// Variable length vectors are produced by applying operations such as 'TokenizeWords' on strings
        /// resulting in vectors of tokens of variable lengths.
        /// </summary>
        [VectorType]
        public int[]? VariableLengthFeatures { get; set; }
    }
    

    A propriedade VariableLengthFeatures tem um VectorType atributo para designá-lo como um vetor. Todos os elementos vetoriais devem ser do mesmo tipo. Em conjuntos de dados com um grande número de colunas, carregar várias colunas como um único vetor reduz o número de passagens de dados quando você aplica transformações de dados.

    Essa classe é usada na ação ResizeFeatures. Os nomes das suas propriedades (neste caso, apenas um) são usados para indicar quais colunas no DataView podem ser usadas como entrada para a ação personalizada de mapeamento.

  3. Crie uma classe para os recursos de comprimento fixo, após a classe VariableLength:

    /// <summary>
    /// Class to hold the fixed length feature vector. Used to define the
    /// column names used as output from the custom mapping action,
    /// </summary>
    public class FixedLength
    {
        /// <summary>
        /// This is a fixed length vector designated by VectorType attribute.
        /// </summary>
        [VectorType(Config.FeatureLength)]
        public int[]? Features { get; set; }
    }
    

    Essa classe é usada na ação ResizeFeatures. Os nomes de suas propriedades (neste caso, apenas uma) são usados para indicar quais colunas no DataView podem ser usadas como a de saída da ação de mapeamento personalizada.

    Observe que o nome da propriedade Features é determinado pelo modelo TensorFlow. Não é possível alterar esse nome de propriedade.

  4. Crie uma classe para a previsão após a classe FixedLength:

    /// <summary>
    /// Class to contain the output values from the transformation.
    /// </summary>
    public class MovieReviewSentimentPrediction
    {
        [VectorType(2)]
        public float[]? Prediction { get; set; }
    }
    

    MovieReviewSentimentPrediction é a classe de previsão usada após o treinamento do modelo. MovieReviewSentimentPrediction tem uma única matriz float (Prediction) e um atributo VectorType.

  5. Crie outra classe para manter valores de configuração, como o comprimento do vetor de recurso:

    static class Config
    {
        public const int FeatureLength = 600;
    }
    

Crie o MLContext, o dicionário de pesquisa e a ação para redimensionar recursos

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

  1. Substitua a linha Console.WriteLine("Hello World!") pelo código a seguir para declarar e inicializar a variável mlContext:

    MLContext mlContext = new MLContext();
    
  2. Crie um dicionário para codificar palavras como inteiros usando o método LoadFromTextFile para carregar dados de mapeamento de um arquivo, conforme mostrado na tabela a seguir:

    Palavra Índice
    Crianças 362
    quer 181
    errado 355
    efeitos 302
    sensação 547

    Adicione o código abaixo para criar o mapa de pesquisa:

    var lookupMap = mlContext.Data.LoadFromTextFile(Path.Combine(_modelPath, "imdb_word_index.csv"),
        columns: new[]
            {
                new TextLoader.Column("Words", DataKind.String, 0),
                new TextLoader.Column("Ids", DataKind.Int32, 1),
            },
        separatorChar: ','
        );
    
  3. Adicione um Action para redimensionar a matriz inteira de palavras de comprimento variável para uma matriz inteira de tamanho fixo, com as próximas linhas de código:

    Action<VariableLength, FixedLength> ResizeFeaturesAction = (s, f) =>
    {
        var features = s.VariableLengthFeatures;
        Array.Resize(ref features, Config.FeatureLength);
        f.Features = features;
    };
    

Carregue o modelo TensorFlow pré-treinado

  1. Adicione código para carregar o modelo TensorFlow:

    TensorFlowModel tensorFlowModel = mlContext.Model.LoadTensorFlowModel(_modelPath);
    

    Depois que o modelo é carregado, você pode extrair seu esquema de entrada e saída. Os esquemas são exibidos apenas para interesse e aprendizagem. Não precisa deste código para que a aplicação final funcione:

    DataViewSchema schema = tensorFlowModel.GetModelSchema();
    Console.WriteLine(" =============== TensorFlow Model Schema =============== ");
    var featuresType = (VectorDataViewType)schema["Features"].Type;
    Console.WriteLine($"Name: Features, Type: {featuresType.ItemType.RawType}, Size: ({featuresType.Dimensions[0]})");
    var predictionType = (VectorDataViewType)schema["Prediction/Softmax"].Type;
    Console.WriteLine($"Name: Prediction/Softmax, Type: {predictionType.ItemType.RawType}, Size: ({predictionType.Dimensions[0]})");
    
    

    O esquema de entrada é a matriz de comprimento fixo de palavras codificadas inteiras. O esquema de saída é uma matriz flutuante de probabilidades que indica se o sentimento de uma avaliação é negativo ou positivo. Estes valores somam 1, pois a probabilidade de ser positivo é o complemento da probabilidade de o sentimento ser negativo.

Criar o pipeline de ML.NET

  1. Crie o pipeline e divida o texto de entrada em palavras usando a transformação TokenizeIntoWords, como na seguinte linha de código:

    IEstimator<ITransformer> pipeline =
        // Split the text into individual words
        mlContext.Transforms.Text.TokenizeIntoWords("TokenizedWords", "ReviewText")
    

    O TokenizeIntoWords transform usa espaços para dividir o texto/string em palavras. Ele cria uma nova coluna e divide cada cadeia de caracteres de entrada em um vetor de substrings com base no separador definido pelo usuário.

  2. Mapeie as palavras em sua codificação inteira usando a tabela de pesquisa que você declarou acima:

    // Map each word to an integer value. The array of integer makes up the input features.
    .Append(mlContext.Transforms.Conversion.MapValue("VariableLengthFeatures", lookupMap,
        lookupMap.Schema["Words"], lookupMap.Schema["Ids"], "TokenizedWords"))
    
  3. Redimensione as codificações inteiras de comprimento variável para a codificação de comprimento fixo exigida pelo modelo:

    // Resize variable length vector to fixed length vector.
    .Append(mlContext.Transforms.CustomMapping(ResizeFeaturesAction, "Resize"))
    
  4. Classifique a entrada com o modelo TensorFlow carregado:

    // Passes the data to TensorFlow for scoring
    .Append(tensorFlowModel.ScoreTensorFlowModel("Prediction/Softmax", "Features"))
    

    A saída do modelo TensorFlow é chamada de Prediction/Softmax. Observe que o nome Prediction/Softmax é determinado pelo modelo TensorFlow. Não é possível alterar este nome.

  5. Crie uma nova coluna para a previsão de saída:

    // Retrieves the 'Prediction' from TensorFlow and copies to a column
    .Append(mlContext.Transforms.CopyColumns("Prediction", "Prediction/Softmax"));
    

    Você precisa copiar a coluna Prediction/Softmax em uma com um nome que possa ser usado como uma propriedade em uma classe C#: Prediction. O caractere / não é permitido em um nome de propriedade C#.

Criar o modelo de ML.NET a partir do pipeline

  1. Adicione o código para criar o modelo a partir do pipeline:

    // Create an executable model from the estimator pipeline
    IDataView dataView = mlContext.Data.LoadFromEnumerable(new List<MovieReview>());
    ITransformer model = pipeline.Fit(dataView);
    

    Um modelo de ML.NET é criado a partir da cadeia de estimadores no pipeline chamando o método Fit. Nesse caso, você não está ajustando nenhum dado para criar o modelo, pois o modelo TensorFlow já foi treinado anteriormente. Você fornece um objeto de exibição de dados vazio para satisfazer os requisitos do método Fit.

Use o modelo para fazer uma previsão

  1. Adicione o método PredictSentiment acima da classe MovieReview:

    void PredictSentiment(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Adicione o seguinte código para criar o PredictionEngine como a primeira linha no método PredictSentiment():

    var engine = mlContext.Model.CreatePredictionEngine<MovieReview, MovieReviewSentimentPrediction>(model);
    

    O PredictionEngine é uma API de conveniência, que permite executar uma predição numa única instância de dados. PredictionEngine não é seguro para threads. É aceitável usar em ambientes monothread ou protótipos. Para melhorar o desempenho e a segurança de threads em ambientes de produção, use o serviço PredictionEnginePool, que cria uma ObjectPool de objetos PredictionEngine para uso em todo o aplicativo. Consulte este guia para usar PredictionEnginePool numAPI Web do ASP.NET Core.

    Observação

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

  3. Adicione um comentário para testar a previsão do modelo treinado no método Predict() criando uma instância de MovieReview:

    var review = new MovieReview()
    {
        ReviewText = "this film is really good"
    };
    
  4. Transfira os dados de comentário de teste para o Prediction Engine adicionando as seguintes linhas de código no método PredictSentiment():

    var sentimentPrediction = engine.Predict(review);
    
  5. A função Predict() faz uma previsão em uma única linha de dados:

    Propriedade Valor Tipo
    Previsão [0.5459937, 0.454006255] flutuar[]
  6. Exiba a previsão de sentimento usando o seguinte código:

    Console.WriteLine($"Number of classes: {sentimentPrediction.Prediction?.Length}");
    Console.WriteLine($"Is sentiment/review positive? {(sentimentPrediction.Prediction?[1] > 0.5 ? "Yes." : "No.")}");
    
  7. Adicione uma chamada ao PredictSentiment depois de chamar o método Fit():

    PredictSentiment(mlContext, model);
    

Resultados obtidos

Crie e execute seu aplicativo.

Os resultados devem ser semelhantes aos seguintes. Durante o processamento, as mensagens são exibidas. Poderá ver avisos ou mensagens de processamento. Essas mensagens foram removidas dos seguintes resultados para maior clareza.

Number of classes: 2
Is sentiment/review positive ? Yes

Parabéns;! Agora você criou com sucesso um modelo de aprendizado de máquina para classificar e prever o sentimento das mensagens reutilizando um modelo de TensorFlow pré-treinado no ML.NET.

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

Neste tutorial, você aprendeu como:

  • Carregar um modelo pré-treinado do TensorFlow
  • Transforme o texto de comentários do site em recursos adequados para o modelo
  • Use o modelo para fazer uma previsão