Tutorial: Analisar o sentimento de resenhas 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 filme do banco de dados do IMDB. Depois de terminar de desenvolver o aplicativo, você poderá fornecer texto de revisão de filme e o aplicativo informará se a revisão tem sentimento positivo ou negativo.
Neste tutorial, você aprenderá a:
- Carregar um modelo pré-treinado do TensorFlow
- Transformar texto de comentário do site em recursos adequados para o modelo
- Usar o modelo para fazer uma previsão
Você pode encontrar o código-fonte deste tutorial no dotnet/samples repositório.
Pré-requisitos
- Visual Studio 2022 com a carga de trabalho "Desenvolvimento do .NET Desktop" instalada.
Configuração
Criar o aplicativo
Crie um aplicativo de console C# chamado "TextClassificationTF". Clique no botão Avançar.
Escolha .NET 8 como a estrutura a ser usada. Selecione o botão Criar.
Crie um diretório chamado Data em seu projeto para salvar os arquivos do conjunto de dados.
Instale o pacote NuGet Microsoft.ML:
Nota
Este exemplo usa a versão estável mais recente dos pacotes NuGet mencionados, a menos que indicado de outra forma.
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 origem do pacote e, em seguida, selecione a guia Procurar. Pesquise por Microsoft.ML, escolha o pacote desejado e, em seguida, clique em Instalar. Prossiga com a instalação concordando com os termos de licença do pacote escolhido. Repita estas etapas 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 dotnet/machinelearning-testdata gitHub. O modelo está no formato TensorFlow SavedModel.
Baixe o arquivo zip sentiment_modele descompacte.
O arquivo zip contém:
saved_model.pb
: o próprio modelo TensorFlow. O modelo usa uma matriz de inteiro de comprimento fixo (tamanho 600) de recursos que representam o texto em uma cadeia de caracteres de avaliações do IMDB e gera duas probabilidades que somam 1: a probabilidade de que a avaliação de entrada tenha um sentimento positivo e a probabilidade de que a avaliação de entrada tenha um 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.
Copie o conteúdo do diretório
sentiment_model
mais interno para o diretório TextClassificationTF do projetosentiment_model
. Este diretório contém o modelo e os arquivos de suporte adicionais necessários para este tutorial, conforme mostrado na imagem a seguir:No Gerenciador de Soluções, clique com o botão direito do mouse em cada um dos arquivos no diretório e subdiretório do
sentiment_model
e selecione Propriedades. Em Avançado, altere o valor de Copiar para Diretório de Saída para Copiar se for mais novo.
Adicionar diretivas using
e variáveis globais
Adicione as seguintes diretivas
using
à parte superior do arquivo Program.cs:using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms;
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 críticas de cinema são texto 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 de inteiro. O resultado dessa transformação é uma matriz de inteiros 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 |
VariableLengthFeatures | 14,22,9,66,78,... | int[] |
A matriz de recursos de comprimento variável é redimensionada para um comprimento fixo de 600. Esse é o comprimento que o modelo tensorFlow espera.
Propriedade | Valor | Tipo |
---|---|---|
Texto de Revisão | este filme é muito bom | string |
VariableLengthFeatures | 14,22,9,66,78,... | int[] |
Características | 14,22,9,66,78,... | int[600] |
Crie uma classe para seus dados de entrada na parte inferior do arquivo 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 umstring
para comentários do usuário (ReviewText
).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 atributo VectorType para designá-la como um vetor. Todos os elementos de vetor 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 dados passados quando você aplica transformações de dados.Essa classe é usada na ação
ResizeFeatures
. Os nomes das propriedades (neste caso, apenas uma) são usados para indicar quais colunas na DataView podem ser usadas como a entrada para a ação de mapeamento personalizada.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 um) são usados para indicar quais colunas no DataView podem ser usadas como a saída da ação de mapeamento personalizada.Observe que o nome da propriedade
Features
é determinado pelo modelo tensorFlow. Você não pode alterar esse nome de propriedade.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 defloat
(Prediction
) e um atributoVectorType
.Crie outra classe para manter valores de configuração, como o comprimento do vetor do recurso:
static class Config { public const int FeatureLength = 600; }
Criar o MLContext, o dicionário de pesquisa e a ação para redimensionar os recursos
A classe MLContext é um ponto de partida para todas as operações do ML.NET. Inicializar mlContext
cria um novo ambiente ML.NET que pode ser compartilhado entre os objetos de fluxo de trabalho de criação de modelo. É semelhante, conceitualmente, a DBContext
no Entity Framework.
Substitua a linha
Console.WriteLine("Hello World!")
pelo seguinte código para declarar e inicializar a variável mlContext:MLContext mlContext = new MLContext();
Crie um dicionário para codificar palavras como inteiros usando o método
LoadFromTextFile
para carregar dados de mapeamento de um arquivo, conforme visto na tabela a seguir:Word Índice garotada 362 desejar 181 errado 355 Efeitos 302 sentimento 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: ',' );
Adicione um
Action
para redimensionar uma matriz de inteiros de comprimento variável para uma matriz de inteiros de tamanho fixo, com as linhas de código a seguir:Action<VariableLength, FixedLength> ResizeFeaturesAction = (s, f) => { var features = s.VariableLengthFeatures; Array.Resize(ref features, Config.FeatureLength); f.Features = features; };
Carregar o modelo pré-treinado do TensorFlow
Adicione código para carregar o modelo tensorFlow:
TensorFlowModel tensorFlowModel = mlContext.Model.LoadTensorFlowModel(_modelPath);
Depois que o modelo for carregado, você poderá extrair seu esquema de entrada e saída. Os esquemas são exibidos somente para interesse e aprendizado. Você não precisa desse código para que o aplicativo 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 em inteiros. O esquema de saída é uma matriz flutuante de probabilidades que indica se o sentimento de uma revisão é negativo ou positivo. Esses valores somam 1, pois a probabilidade de ser positivo é o complemento da probabilidade do sentimento ser negativo.
Criar um pipeline do ML.NET
Crie o pipeline e divida o texto de entrada em palavras usando 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 usa espaços para analisar o texto/a cadeia de caracteres em palavras. Ele cria uma nova coluna e divide cada cadeia de caracteres de entrada para um vetor de subcadeias de caracteres com base no separador definido pelo usuário.
Mapeie as palavras para a codificação de inteiro 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"))
Redimensione as codificações de inteiro de comprimento variável para a de comprimento fixo necessária para o modelo:
// Resize variable length vector to fixed length vector. .Append(mlContext.Transforms.CustomMapping(ResizeFeaturesAction, "Resize"))
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
Prediction/Softmax
. Observe que o nomePrediction/Softmax
é determinado pelo modelo TensorFlow. Você não pode alterar esse nome.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#.
Crie o modelo de ML.NET a partir do pipeline
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 avaliadores 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 atender aos requisitos do métodoFit
.
Usar o modelo para fazer uma previsão
Adicione o método
PredictSentiment
acima da classeMovieReview
:void PredictSentiment(MLContext mlContext, ITransformer model) { }
Adicione o seguinte código para criar o
PredictionEngine
como a primeira linha no métodoPredictSentiment()
:var engine = mlContext.Model.CreatePredictionEngine<MovieReview, MovieReviewSentimentPrediction>(model);
O
PredictionEngine é uma API de conveniência, que permite que você execute uma previsão em uma única instância de dados. PredictionEngine
não é thread-safe. É aceitável usá-lo em ambientes de thread único ou de protótipo. Para aprimorar o desempenho e o acesso thread-safe em ambientes de produção, use o serviçoPredictionEnginePool
, que cria umObjectPool
de objetosPredictionEngine
para uso em todo o aplicativo. Confira este guia sobre como usar oPredictionEnginePool
em uma API Web ASP.NET Core.Nota
A extensão de serviço
PredictionEnginePool
está atualmente em versão preliminar.Adicione um comentário para testar a previsão do modelo treinado no método
Predict()
criando uma instância deMovieReview
:var review = new MovieReview() { ReviewText = "this film is really good" };
Transmita os dados de comentário de teste para o
Prediction Engine
adicionando as próximas linhas de código ao métodoPredictSentiment()
:var sentimentPrediction = engine.Predict(review);
A função Predict() faz uma previsão em uma única linha de dados.
Propriedade Valor Tipo Predição [0.5459937, 0.454006255] float[] 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.")}");
Adicione uma chamada para
PredictSentiment
depois de chamar o métodoFit()
:PredictSentiment(mlContext, model);
Resultados
Crie e execute seu aplicativo.
Seus resultados devem ser semelhantes aos seguintes. Durante o processamento, as mensagens são exibidas. Você pode 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 êxito um modelo de machine learning para classificar e prever o sentimento de mensagens reutilizando um modelo de TensorFlow
pré-treinado em ML.NET.
Você pode encontrar o código-fonte deste tutorial no dotnet/samples repositório.
Neste tutorial, você aprendeu a:
- Carregar um modelo pré-treinado do TensorFlow
- Transformar texto de comentário do site em recursos adequados para o modelo
- Usar o modelo para fazer uma previsão