Partilhar via


Tutorial: Analisar o sentimento das críticas de filmes com um modelo do TensorFlow pré-preparado no ML.NET

Este tutorial mostra-lhe como utilizar um modelo do TensorFlow pré-preparado para classificar o sentimento nos comentários do site. O classificador de sentimento binário é uma aplicação de consola C# desenvolvida com o Visual Studio.

O modelo TensorFlow utilizado neste tutorial foi preparado com críticas de filmes da base de dados IMDB. Depois de concluir o desenvolvimento da aplicação, poderá fornecer texto de revisão de filmes e a aplicação irá indicar-lhe se a revisão tem sentimentos positivos ou negativos.

Neste tutorial, ficará a saber como:

  • Carregar um modelo do TensorFlow pré-preparado
  • Transformar o texto do comentário do site em funcionalidades adequadas para o modelo
  • Utilizar o modelo para fazer uma predição

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

Pré-requisitos

Configuração

Criar a aplicação

  1. Crie uma Aplicação de Consola C# denominada "TextClassificationTF". Clique no botão Seguinte .

  2. Selecione .NET 6 como a arquitetura a utilizar. Clique no botão Criar.

  3. Crie um diretório com o nome Dados no seu projeto para guardar os ficheiros do conjunto de dados.

  4. Instale o Pacote NuGet Microsoft.ML:

    Nota

    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 do rato no projeto e selecione Gerir Pacotes NuGet. Selecione "nuget.org" como a origem do pacote e, em seguida, selecione o separador Procurar. Procure Microsoft.ML, selecione o pacote que pretende e, em seguida, selecione o botão Instalar . Prossiga com a instalação ao concordar com os termos de licença do pacote que escolher. Repita estes passos para Microsoft.ML.TensorFlow, Microsoft.ML.SampleUtils e SciSharp.TensorFlow.Redist.

Adicionar o modelo TensorFlow ao projeto

Nota

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

  1. Transfira o ficheiro zip sentiment_model e deszipe.

    O ficheiro zip contém:

    • saved_model.pb: o próprio modelo tensorFlow. O modelo tem uma matriz de carateres inteiros de comprimento fixo (tamanho 600) que representa o texto numa cadeia de revisão IMDB e produz duas probabilidades que somam 1: a probabilidade de a revisão de entrada ter um sentimento positivo e a probabilidade de a revisão de entrada ter um sentimento negativo.
    • imdb_word_index.csv: um mapeamento de palavras individuais para um valor inteiro. O mapeamento é utilizado para gerar as funcionalidades de entrada do modelo TensorFlow.
  2. Copie os conteúdos do diretório mais sentiment_model interno para o diretório de projeto sentiment_modelTextClassificationTF. Este diretório contém o modelo e os ficheiros de suporte adicionais necessários para este tutorial, conforme mostrado na imagem seguinte:

    sentiment_model conteúdos do diretório

  3. Em Explorador de Soluções, clique com o botão direito do rato em cada um dos ficheiros no sentiment_model diretório e subdiretório e selecione Propriedades. Em Avançadas, altere o valor de Copiar para Diretório de Saída para Copiar se for mais recente.

Adicionar instruções de utilização e variáveis globais

  1. Adicione as seguintes instruções adicionais using à parte superior do ficheiro Program.cs :

    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms;
    
  2. Crie uma variável global logo após as instruções de utilização para manter o caminho do ficheiro de modelo guardado.

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

Modelar os dados

As críticas de filmes são texto de forma livre. A sua aplicação converte o texto no formato de entrada esperado pelo modelo em várias fases discretas.

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

Propriedade Valor Tipo
ReviewText este filme é muito bom string
VariableLengthFeatures 14,22,9,66,78,... int[]

Em seguida, a matriz de funcionalidades de comprimento variável é redimensionada para um comprimento fixo de 600. Este é o comprimento esperado pelo modelo TensorFlow.

Propriedade Valor Tipo
ReviewText este filme é muito bom string
VariableLengthFeatures 14,22,9,66,78,... int[]
Funcionalidades 14,22,9,66,78,... int[600]
  1. Crie uma classe para os seus dados de entrada na parte inferior do ficheiro 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 de utilizador (ReviewText).

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

    /// <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 VariableLengthFeatures propriedade tem um atributo VectorType para designá-lo como um vetor. Todos os elementos do vetor têm de ser do mesmo tipo. Em conjuntos de dados com um grande número de colunas, carregar múltiplas colunas como um único vetor reduz o número de passes de dados quando aplica transformações de dados.

    Esta classe é utilizada na ação ResizeFeatures . Os nomes das respetivas propriedades (neste caso, apenas uma) são utilizados para indicar que colunas no DataView podem ser utilizadas como entrada para a ação de mapeamento personalizado.

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

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

    Esta classe é utilizada na ação ResizeFeatures . Os nomes das respetivas propriedades (neste caso, apenas uma) são utilizados para indicar que colunas no DataView podem ser utilizadas como saída da ação de mapeamento personalizado.

    Tenha em atenção que o nome da propriedade Features é determinado pelo modelo TensorFlow. Não pode alterar este nome de propriedade.

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

    /// <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 predição utilizada após a preparação do modelo. MovieReviewSentimentPrediction tem uma única float matriz (Prediction) e um VectorType atributo.

  5. Crie outra classe para conter valores de configuração, como o comprimento do vetor da funcionalidade:

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

Criar o MLContext, o dicionário de pesquisa e a ação para redimensionar funcionalidades

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

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

    MLContext mlContext = new MLContext();
    
  2. Crie um dicionário para codificar palavras como números inteiros com o LoadFromTextFile método para carregar dados de mapeamento de um ficheiro, conforme visto na seguinte tabela:

    Word Índice
    crianças 362
    quer 181
    errado 355
    effects 302
    sentir 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 de números inteiros de palavras de comprimento variável a uma matriz de número inteiro de tamanho fixo, com as linhas de código seguintes:

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

Carregar o modelo tensorFlow pré-preparado

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

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

    Assim que o modelo for carregado, pode extrair o respetivo esquema de entrada e saída. Os esquemas são apresentados 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 por número inteiro. O esquema de saída é uma matriz flutuante de probabilidades que indica se o sentimento de uma revisão é negativo ou positivo. Estes valores somam-se a 1, uma vez que 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 com a transformação TokenizeIntoWords para dividir o texto em palavras como a próxima linha de código:

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

    A transformação TokenizeIntoWords utiliza espaços para analisar o texto/cadeia em palavras. Cria uma nova coluna e divide cada cadeia de entrada num vetor de subcadeias com base no separador definido pelo utilizador.

  2. Mapeie as palavras para a respetiva codificação de número inteiro com a tabela de referência que 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 de número inteiro de comprimento variável para o comprimento fixo exigido 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 chama-se Prediction/Softmax. Tenha em atenção que o nome Prediction/Softmax é determinado pelo modelo TensorFlow. Não pode alterar este nome.

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

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

    Tem de copiar a Prediction/Softmax coluna para uma com um nome que pode ser utilizado como uma propriedade numa classe C#: Prediction. O / caráter não é permitido num 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 ao chamar o Fit método. Neste caso, não estamos a ajustar quaisquer dados para criar o modelo, uma vez que o modelo TensorFlow já foi preparado anteriormente. Fornecemos um objeto de vista de dados vazio para satisfazer os requisitos do Fit método.

Utilizar o modelo para fazer uma predição

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

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

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

    PredictionEngine é uma API de conveniência, que lhe permite efetuar uma predição numa única instância de dados. PredictionEngine não é seguro para threads. É aceitável utilizar em ambientes de thread único ou protótipo. Para melhorar o desempenho e a segurança dos threads em ambientes de produção, utilize o PredictionEnginePool serviço, que cria um ObjectPool objeto PredictionEngine para utilização em toda a sua aplicação. Veja este guia sobre como utilizar PredictionEnginePool numa API Web ASP.NET Core.

    Nota

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

  3. Adicione um comentário para testar a predição do modelo preparado no Predict() método ao criar uma instância de MovieReview:

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

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

    Propriedade Valor Tipo
    Predição [0.5459937, 0.454006255] float[]
  6. Apresentar predição de sentimentos com 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 a PredictSentiment depois de chamar o Fit() método:

    PredictSentiment(mlContext, model);
    

Resultados

Crie e execute a sua aplicação.

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

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

Parabéns! Criou com êxito um modelo de machine learning para classificar e prever o sentimento das mensagens ao reutilizar um modelo pré-preparado TensorFlow no ML.NET.

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

Neste tutorial, ficou a saber como:

  • Carregar um modelo do TensorFlow pré-preparado
  • Transformar o texto do comentário do site em funcionalidades adequadas para o modelo
  • Utilizar o modelo para fazer uma predição