Tutorial: Analisar o sentimento dos comentários do site com classificação binária em ML.NET
Este tutorial mostra como criar um aplicativo de console .NET que classifica o sentimento dos comentários do site e executa a ação apropriada. O classificador de sentimento binário usa C# no Visual Studio 2022.
Neste tutorial, você aprenderá a:
- Criar um aplicativo de console
- Preparar dados
- Carregue os dados
- Construa e treine o modelo
- Avaliar o modelo
- Use o modelo para fazer uma previsão
- Ver os resultados
Você pode encontrar o código-fonte deste tutorial no repositório dotnet/samples
Pré-requisitos
Criar um aplicativo de console
Crie um aplicativo C# Console chamado "SentimentAnalysis". Clique no botão Avançar.
Escolha .NET 8 como a estrutura a ser usada. Clique no botão Criar.
Crie um diretório chamado Data em seu projeto para salvar seus arquivos de conjunto de dados.
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.
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. 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.
Prepare os seus dados
Observação
Os conjuntos de dados para este tutorial são do 'From Group to Individual Labels using Deep Features', Kotzias et. al,. KDD 2015, e hospedado no UCI Machine Learning Repository - Dua, D. e Karra Taniskidou, E. (2017). Repositório UCI Machine Learning [http://archive.ics.uci.edu/ml]. Irvine, CA: Universidade da Califórnia, Escola de Informação e Ciência da Computação.
Baixe arquivo ZIP do conjunto de dados UCI Sentiment Labeled Sentencese descompacte.
Copie o arquivo
yelp_labelled.txt
para o diretório Data que você criou.No Gerenciador de Soluções, clique com o botão direito do mouse no arquivo
yelp_labelled.txt
e selecione Propriedades. Em Opções Avançadas, altere o valor de Copiar para o Diretório de Saída para Copiar se for mais recente.
Criar classes e definir caminhos
Adicione as seguintes diretivas
using
adicionais à parte superior do arquivo Program.cs:using Microsoft.ML; using Microsoft.ML.Data; using SentimentAnalysis; using static Microsoft.ML.DataOperationsCatalog;
Adicione o seguinte código à linha logo abaixo das diretivas
using
, para criar um campo para armazenar o caminho do arquivo do conjunto de dados baixado recentemente:string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "yelp_labelled.txt");
Em seguida, crie classes para seus dados de entrada e previsões. Adicione uma nova classe ao seu projeto:
No Gerenciador de Soluções , clique com o botão direito do mouse no projeto e selecione Adicionar>Novo Item.
Na caixa de diálogo Adicionar Novo Item, selecione a Classe e altere o campo Nome para SentimentData.cs. Em seguida, selecione Adicionar.
O arquivo SentimentData.cs é aberto no editor de códigos. Adicionar a seguinte diretiva
using
ao topo da SentimentData.cs:using Microsoft.ML.Data;
Remova a definição de classe existente e adicione o seguinte código, que tem duas classes
SentimentData
eSentimentPrediction
, ao arquivo SentimentData.cs:public class SentimentData { [LoadColumn(0)] public string? SentimentText; [LoadColumn(1), ColumnName("Label")] public bool Sentiment; } public class SentimentPrediction : SentimentData { [ColumnName("PredictedLabel")] public bool Prediction { get; set; } public float Probability { get; set; } public float Score { get; set; } }
Como os dados foram preparados
A classe do conjunto de dados de entrada, SentimentData
, tem um string
para comentários do usuário (SentimentText
) e um valor de bool
(Sentiment
) de 1 (positivo) ou 0 (negativo) para sentimento. Ambos os campos têm atributos LoadColumn anexados a eles, que descrevem a ordem de cada campo no ficheiro de dados. Além disso, a propriedade Sentiment
tem um atributo ColumnName para designá-la como o campo Label
. O arquivo de exemplo a seguir não tem uma linha de cabeçalho e tem esta aparência:
SentimentText | Sentimento (Rótulo) |
---|---|
A garçonete foi um pouco lenta no serviço. | 0 |
Crosta não é boa. | 0 |
Uau... Adorei esse lugar. | 1 |
O serviço foi muito rápido. | 1 |
SentimentPrediction
é a classe de previsão usada após o treinamento do modelo. É herdado de SentimentData
para que a entrada SentimentText
possa ser exibida juntamente com a previsão de saída. O booleano Prediction
é o valor que o modelo prevê quando é fornecido com nova entrada SentimentText
.
A classe de saída SentimentPrediction
contém duas outras propriedades calculadas pelo modelo: Score
- a pontuação bruta calculada pelo modelo e Probability
- a pontuação calibrada para a probabilidade de o texto ter um sentimento positivo.
Para este tutorial, a propriedade mais importante é Prediction
.
Carregue os dados
Os dados no ML.NET são representados como uma interface IDataView .
IDataView
é uma forma flexível e eficiente de descrever dados tabulares (numéricos e de texto). Os dados podem ser carregados de um arquivo de texto ou em tempo real (por exemplo, banco de dados SQL ou arquivos de log) para um objeto IDataView
.
A classe MLContext é um ponto de partida para todas as operações de 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.
Você prepara o aplicativo e, em seguida, carrega dados:
Substitua a linha
Console.WriteLine("Hello World!")
pelo código a seguir para declarar e inicializar a variável mlContext:MLContext mlContext = new MLContext();
Adicione o seguinte como a próxima linha de código:
TrainTestData splitDataView = LoadData(mlContext);
Crie um método
LoadData()
na parte inferior do arquivo deProgram.cs
usando o seguinte código:TrainTestData LoadData(MLContext mlContext) { }
O método
LoadData()
executa as seguintes tarefas:- Carrega os dados.
- Divide o conjunto de dados carregado em conjuntos de dados de treino e teste.
- Retorna os conjuntos de dados de treino e teste divididos.
Adicione o seguinte código como a primeira linha do método
LoadData()
:IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentData>(_dataPath, hasHeader: false);
O método de LoadFromTextFile() define o esquema de dados e lê no arquivo. Ele recebe as variáveis de caminho de dados e retorna um
IDataView
.
Dividir o conjunto de dados para treinamento e teste de modelos
Ao preparar um modelo, você usa parte do conjunto de dados para treiná-lo e parte do conjunto de dados para testar a precisão do modelo.
Para dividir os dados carregados nos conjuntos de dados necessários, adicione o seguinte código como a próxima linha no método
LoadData()
:TrainTestData splitDataView = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
O código anterior usa o método TrainTestSplit() para dividir o conjunto de dados carregado em conjuntos de dados de treino e de teste e retornar na classe DataOperationsCatalog.TrainTestData. Especifique a porcentagem de dados do conjunto de teste com o parâmetro
testFraction
. O padrão é 10%, neste caso você usa 20% para avaliar mais dados.Retorne o
splitDataView
no final do métodoLoadData()
:return splitDataView;
Construa e treine o modelo
Adicione a seguinte chamada ao método
BuildAndTrainModel
abaixo da chamada ao métodoLoadData
:ITransformer model = BuildAndTrainModel(mlContext, splitDataView.TrainSet);
O método
BuildAndTrainModel()
executa as seguintes tarefas:- Extrai e transforma os dados.
- Treina o modelo.
- Prevê o sentimento com base em dados de teste.
- Retorna o modelo.
Crie o método
BuildAndTrainModel()
, abaixo do métodoLoadData()
, usando o seguinte código:ITransformer BuildAndTrainModel(MLContext mlContext, IDataView splitTrainSet) { }
Extrair e transformar os dados
Chame
FeaturizeText
como a próxima linha de código:var estimator = mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: nameof(SentimentData.SentimentText))
O método
FeaturizeText()
no código anterior converte a coluna de texto (SentimentText
) em um tipo de chave numéricaFeatures
coluna usada pelo algoritmo de aprendizado de máquina e a adiciona como uma nova coluna de conjunto de dados:SentimentText Sentimento Caraterísticas A garçonete foi um pouco lenta no serviço. 0 [0.76, 0.65, 0.44, …] Crosta não é boa. 0 [0.98, 0.43, 0.54, …] Uau... Adorei esse lugar. 1 [0.35, 0.73, 0.46, …] O serviço foi muito rápido. 1 [0.39, 0, 0.75, …]
Adicionar um algoritmo de aprendizagem
Este aplicativo usa um algoritmo de classificação que categoriza itens ou linhas de dados. O aplicativo categoriza os comentários do site como positivos ou negativos, portanto, use a tarefa de classificação binária.
Acrescente a tarefa de aprendizado de máquina às definições de transformação de dados adicionando o seguinte como a próxima linha de código em BuildAndTrainModel()
:
.Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features"));
O SdcaLogisticRegressionBinaryTrainer é o seu algoritmo de formação de classificação. Isto é anexado ao estimator
e aceita os SentimentText
featurizado (Features
) e os parâmetros de entrada Label
para aprender a partir dos dados históricos.
Treinar o modelo
Ajuste o modelo aos dados splitTrainSet
e retorne o modelo treinado adicionando o seguinte como a próxima linha de código no método BuildAndTrainModel()
:
Console.WriteLine("=============== Create and Train the Model ===============");
var model = estimator.Fit(splitTrainSet);
Console.WriteLine("=============== End of training ===============");
Console.WriteLine();
O método
Retornar o modelo treinado para utilização na avaliação
Retorne o modelo no final do método BuildAndTrainModel()
:
return model;
Avaliar o modelo
Depois que o modelo for treinado, use os dados de teste para validar o desempenho do modelo.
Crie o método
Evaluate()
, logo apósBuildAndTrainModel()
, com o seguinte código:void Evaluate(MLContext mlContext, ITransformer model, IDataView splitTestSet) { }
O método
Evaluate()
executa as seguintes tarefas:- Carrega o conjunto de dados de teste.
- Cria o avaliador BinaryClassification.
- Avalia o modelo e cria métricas.
- Exibe as métricas.
Adicione uma chamada ao novo método abaixo da chamada de método
BuildAndTrainModel
usando o seguinte código:Evaluate(mlContext, model, splitDataView.TestSet);
Transforme os dados
splitTestSet
adicionando o seguinte código aEvaluate()
:Console.WriteLine("=============== Evaluating Model accuracy with Test data==============="); IDataView predictions = model.Transform(splitTestSet);
O código anterior usa o método
Transform() para fazer previsões para várias linhas de entrada fornecidas de um conjunto de dados de teste. Avalie o modelo adicionando o seguinte como a próxima linha de código no método
Evaluate()
:CalibratedBinaryClassificationMetrics metrics = mlContext.BinaryClassification.Evaluate(predictions, "Label");
Depois de definir a previsão (
Exibindo as métricas para validação do modelo
Use o código a seguir para exibir as métricas:
Console.WriteLine();
Console.WriteLine("Model quality metrics evaluation");
Console.WriteLine("--------------------------------");
Console.WriteLine($"Accuracy: {metrics.Accuracy:P2}");
Console.WriteLine($"Auc: {metrics.AreaUnderRocCurve:P2}");
Console.WriteLine($"F1Score: {metrics.F1Score:P2}");
Console.WriteLine("=============== End of model evaluation ===============");
A métrica
Accuracy
obtém a precisão de um modelo, que é a proporção de previsões corretas no conjunto de testes.A métrica
AreaUnderRocCurve
indica o quão confiante o modelo está classificando corretamente as classes positiva e negativa. Você quer que oAreaUnderRocCurve
seja o mais próximo de um possível.A métrica
F1Score
obtém a pontuação F1 do modelo, que é uma medida de equilíbrio entre precisão e recall. Você quer que oF1Score
seja o mais próximo possível de 1.
Prever o resultado dos dados do teste
Crie o método
UseModelWithSingleItem()
, logo após o métodoEvaluate()
, usando o seguinte código:void UseModelWithSingleItem(MLContext mlContext, ITransformer model) { }
O método
UseModelWithSingleItem()
executa as seguintes tarefas:- Cria um único comentário dos dados de teste.
- Prevê o sentimento com base em dados de teste.
- Combina dados de teste e previsões para relatórios.
- Exibe os resultados previstos.
Adicione uma chamada ao novo método logo abaixo da chamada de método
Evaluate()
usando o seguinte código:UseModelWithSingleItem(mlContext, model);
Adicione o seguinte código para criar como a primeira linha no método
UseModelWithSingleItem()
:PredictionEngine<SentimentData, SentimentPrediction> predictionFunction = mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(model);
O PredictionEngine é uma API de conveniência, que permite executar uma previsão numa única instância de dados.
PredictionEngine
não é seguro para threads. É aceitável usá-lo em ambientes de fio único (single-threaded) ou em protótipos. Para melhorar o desempenho e a segurança de threads em ambientes de produção, use o serviçoPredictionEnginePool
, que cria umaObjectPool
de objetosPredictionEngine
para uso em todo o aplicativo. Consulte este guia sobre como usarPredictionEnginePool
em umASP.NET Core Web API .Observação
PredictionEnginePool
ampliação de serviço está atualmente em versão preliminar.Adicione um comentário para testar a previsão do modelo treinado no método
UseModelWithSingleItem()
criando uma instância deSentimentData
:SentimentData sampleStatement = new SentimentData { SentimentText = "This was a very bad steak" };
Passe os dados de comentário de teste para o
PredictionEngine
adicionando o seguinte como as próximas linhas de código no métodoUseModelWithSingleItem()
:var resultPrediction = predictionFunction.Predict(sampleStatement);
A função
Predict() faz uma previsão em uma única linha de dados. Exiba
SentimentText
e a previsão de sentimento correspondente usando o seguinte código:Console.WriteLine(); Console.WriteLine("=============== Prediction Test of model with a single sample and test dataset ==============="); Console.WriteLine(); Console.WriteLine($"Sentiment: {resultPrediction.SentimentText} | Prediction: {(Convert.ToBoolean(resultPrediction.Prediction) ? "Positive" : "Negative")} | Probability: {resultPrediction.Probability} "); Console.WriteLine("=============== End of Predictions ==============="); Console.WriteLine();
Use o modelo para previsão
Implantar e prever itens em lote
Crie o método
UseModelWithBatchItems()
, logo após o métodoUseModelWithSingleItem()
, usando o seguinte código:void UseModelWithBatchItems(MLContext mlContext, ITransformer model) { }
O método
UseModelWithBatchItems()
executa as seguintes tarefas:- Cria dados de teste em lote.
- Prevê o sentimento com base em dados de teste.
- Combina dados de teste e previsões para relatórios.
- Exibe os resultados previstos.
Adicione uma chamada ao novo método logo abaixo da chamada de método
UseModelWithSingleItem()
usando o seguinte código:UseModelWithBatchItems(mlContext, model);
Adicione alguns comentários para testar as previsões do modelo treinado no método
UseModelWithBatchItems()
:IEnumerable<SentimentData> sentiments = new[] { new SentimentData { SentimentText = "This was a horrible meal" }, new SentimentData { SentimentText = "I love this spaghetti." } };
Prever o sentimento do comentário
Use o modelo para predizer o sentimento dos dados de comentário usando o método Transform().
IDataView batchComments = mlContext.Data.LoadFromEnumerable(sentiments);
IDataView predictions = model.Transform(batchComments);
// Use model to predict whether comment data is Positive (1) or Negative (0).
IEnumerable<SentimentPrediction> predictedResults = mlContext.Data.CreateEnumerable<SentimentPrediction>(predictions, reuseRowObject: false);
Combinar e exibir as previsões
Crie um cabeçalho para as previsões usando o seguinte código:
Console.WriteLine();
Console.WriteLine("=============== Prediction Test of loaded model with multiple samples ===============");
Uma vez que SentimentPrediction
é herdada de SentimentData
, o método Transform()
preencheu SentimentText
com os campos previstos. À medida que o processo ML.NET processa, cada componente adiciona colunas, e isso facilita a exibição dos resultados:
foreach (SentimentPrediction prediction in predictedResults)
{
Console.WriteLine($"Sentiment: {prediction.SentimentText} | Prediction: {(Convert.ToBoolean(prediction.Prediction) ? "Positive" : "Negative")} | Probability: {prediction.Probability} ");
}
Console.WriteLine("=============== End of predictions ===============");
Resultados obtidos
Os resultados devem ser semelhantes aos seguintes. Durante o processamento, as mensagens são exibidas. Poderá ver avisos ou mensagens de processamento. Estes foram removidos dos seguintes resultados para maior clareza.
Model quality metrics evaluation
--------------------------------
Accuracy: 83.96%
Auc: 90.51%
F1Score: 84.04%
=============== End of model evaluation ===============
=============== Prediction Test of model with a single sample and test dataset ===============
Sentiment: This was a very bad steak | Prediction: Negative | Probability: 0.1027377
=============== End of Predictions ===============
=============== Prediction Test of loaded model with a multiple samples ===============
Sentiment: This was a horrible meal | Prediction: Negative | Probability: 0.1369192
Sentiment: I love this spaghetti. | Prediction: Positive | Probability: 0.9960636
=============== End of predictions ===============
=============== End of process ===============
Press any key to continue . . .
Parabéns;! Agora você criou com sucesso um modelo de aprendizado de máquina para classificar e prever o sentimento das mensagens.
A construção de modelos bem-sucedidos é um processo iterativo. Este modelo tem qualidade inicial inferior, pois o tutorial usa pequenos conjuntos de dados para fornecer treinamento rápido de modelo. Se você não estiver satisfeito com a qualidade do modelo, pode tentar melhorá-lo fornecendo conjuntos de dados de treinamento maiores ou escolhendo diferentes algoritmos de treinamento com diferentes hiperparâmetros para cada algoritmo.
Você pode encontrar o código-fonte deste tutorial no repositório dotnet/samples
Próximos passos
Neste tutorial, você aprendeu como:
- Criar um aplicativo de console
- Preparar dados
- Carregue os dados
- Construa e treine o modelo
- Avaliar o modelo
- Use o modelo para fazer uma previsão
- Ver os resultados
Avance para o próximo tutorial para saber mais