Tutorial: Analisar o sentimento dos comentários do site com a classificação binária no ML.NET
Este tutorial mostra-lhe como criar uma aplicação de consola .NET Core que classifica o sentimento dos comentários do site e toma a ação adequada. O classificador de sentimento binário utiliza C# no Visual Studio 2022.
Neste tutorial, ficará a saber como:
- Criar uma aplicação de consola
- Preparar dados
- Carregar os dados
- Criar e preparar o modelo
- Avaliar o modelo
- Utilizar o modelo para fazer uma predição
- Veja os resultados
Pode encontrar o código fonte deste tutorial no repositório dotnet/samples .
Pré-requisitos
Criar uma aplicação de consola
Crie uma Aplicação de Consola C# denominada "SentimentAnalysis". Clique no botão Seguinte .
Selecione .NET 6 como a arquitetura a utilizar. Clique no botão Criar.
Crie um diretório com o nome Dados no seu projeto para guardar os ficheiros do conjunto de dados.
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.
Preparar os dados
Nota
Os conjuntos de dados deste tutorial são de "De Grupo a Etiquetas Individuais com Funcionalidades Profundas", Kotzias et. al, . KDD 2015 e alojado no Repositório UCI Machine Learning - Dua, D. e Karra Taniskidou, E. (2017). Repositório UCI Machine Learning [http://archive.ics.uci.edu/ml]. Irvine, AC: Universidade da Califórnia, Escola de Informação e Ciências da Computação.
Transfira o ficheiro ZIP do conjunto de dados Frases Etiquetadas pelo Sentimento UCI e deszipe.
Copie o
yelp_labelled.txt
ficheiro para o diretório Dados que criou.Em Explorador de Soluções, clique com o botão direito do rato no
yelp_labeled.txt
ficheiro e selecione Propriedades. Em Avançadas, altere o valor de Copiar para Diretório de Saída para Copiar se for mais recente.
Criar classes e definir caminhos
Adicione as seguintes instruções adicionais
using
à parte superior do ficheiro Program.cs :using Microsoft.ML; using Microsoft.ML.Data; using SentimentAnalysis; using static Microsoft.ML.DataOperationsCatalog;
Adicione o seguinte código à linha abaixo das
using
instruções, para criar um campo para manter o caminho de ficheiro do conjunto de dados transferido recentemente:string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "yelp_labelled.txt");
Em seguida, crie classes para os seus dados de entrada e predições. Adicione uma nova classe ao seu projeto:
Em Explorador de Soluções, clique com o botão direito do rato no projeto e, em seguida, selecione Adicionar>Novo Item.
Na caixa de diálogo Adicionar Novo Item , selecione Classe e altere o campo Nome para SentimentData.cs. Em seguida, selecione o botão Adicionar .
O ficheiro SentimentData.cs é aberto no editor de código. Adicione a seguinte
using
instrução à parte superior de 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 ficheiro 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 de conjunto de dados de entrada, SentimentData
, tem um string
para comentários de utilizador (SentimentText
) e um bool
valor (Sentiment
) de 1 (positivo) ou 0 (negativo) para sentimento. Ambos os campos têm atributos LoadColumn anexados aos mesmos, o que descreve a ordem dos ficheiros de dados de cada campo. Além disso, a Sentiment
propriedade tem um atributo ColumnName para designá-lo como o Label
campo. O ficheiro de exemplo seguinte não tem uma linha de cabeçalho e tem o seguinte aspeto:
SentimentText | Sentimento (Etiqueta) |
---|---|
A garçonete estava um pouco lenta no serviço. | 0 |
A crosta não é boa. | 0 |
Uau... Adorei este lugar. | 1 |
O serviço foi muito rápido. | 1 |
SentimentPrediction
é a classe de predição utilizada após a preparação do modelo. Herda de para SentimentData
que a entrada SentimentText
possa ser apresentada juntamente com a predição de saída. O Prediction
valor booleano é o valor que o modelo prevê quando fornecido com a nova entrada SentimentText
.
A classe SentimentPrediction
de saída contém duas outras propriedades calculadas pelo modelo: - Score
a classificação não processada calculada pelo modelo e Probability
- a classificação calibrada para a probabilidade de o texto ter um sentimento positivo.
Para este tutorial, a propriedade mais importante é Prediction
.
Carregar 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 texto). Os dados podem ser carregados a partir de um ficheiro de texto ou em tempo real (por exemplo, base de dados SQL ou ficheiros de registo) para um IDataView
objeto.
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.
Prepare a aplicação e, em seguida, carregue os dados:
Substitua a
Console.WriteLine("Hello World!")
linha pelo seguinte código 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
LoadData()
método na parte inferior doProgram.cs
ficheiro com o seguinte código:TrainTestData LoadData(MLContext mlContext) { }
O
LoadData()
método executa as seguintes tarefas:- Carrega os dados.
- Divide o conjunto de dados carregado em conjuntos de dados de preparação e teste.
- Devolve os conjuntos de dados de preparação e teste divididos.
Adicione o seguinte código como a primeira linha do
LoadData()
método:IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentData>(_dataPath, hasHeader: false);
O método LoadFromTextFile() define o esquema de dados e lê no ficheiro. Utiliza as variáveis do caminho de dados e devolve um
IDataView
.
Dividir o conjunto de dados para preparação e teste de modelos
Ao preparar um modelo, utiliza parte do conjunto de dados para o preparar 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 linha seguinte no
LoadData()
método:TrainTestData splitDataView = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
O código anterior utiliza o método TrainTestSplit() para dividir o conjunto de dados carregado em conjuntos de dados de preparação e teste e devolvê-los na DataOperationsCatalog.TrainTestData classe. Especifique a percentagem de dados do conjunto de testes com o
testFraction
parâmetro . A predefinição é 10%, neste caso, utiliza 20% para avaliar mais dados.Devolva o
splitDataView
no final doLoadData()
método:return splitDataView;
Criar e preparar o modelo
Adicione a seguinte chamada ao
BuildAndTrainModel
método abaixo da chamada aoLoadData
método:ITransformer model = BuildAndTrainModel(mlContext, splitDataView.TrainSet);
O
BuildAndTrainModel()
método executa as seguintes tarefas:- Extrai e transforma os dados.
- Prepara o modelo.
- Prevê o sentimento com base nos dados de teste.
- Devolve o modelo.
Crie o
BuildAndTrainModel()
método, abaixo doLoadData()
método, com 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
FeaturizeText()
método no código anterior converte a coluna de texto (SentimentText
) numa coluna de tipoFeatures
de chave numérica utilizada pelo algoritmo de machine learning e adiciona-a como uma nova coluna de conjunto de dados:SentimentText Sentimento Funcionalidades A garçonete estava um pouco lenta em serviço. 0 [0.76, 0.65, 0.44, ...] A crosta não é boa. 0 [0.98, 0.43, 0.54, ...] Uau... Adorei este 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
Esta aplicação utiliza um algoritmo de classificação que categoriza itens ou linhas de dados. A aplicação categoriza os comentários do site como positivos ou negativos, pelo que deve utilizar a tarefa de classificação binária.
Acrescente a tarefa de machine learning às definições de transformação de dados ao adicionar o seguinte como a próxima linha de código em BuildAndTrainModel()
:
.Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features"));
O SdcaLogisticRegressionBinaryTrainer é o algoritmo de preparação de classificação. Isto é acrescentado ao estimator
e aceita os parâmetros em destaque SentimentText
(Features
) e os Label
parâmetros de entrada para aprender com os dados históricos.
Preparar o modelo
Ajuste o modelo aos splitTrainSet
dados e devolva o modelo preparado ao adicionar o seguinte como a próxima linha de código no BuildAndTrainModel()
método :
Console.WriteLine("=============== Create and Train the Model ===============");
var model = estimator.Fit(splitTrainSet);
Console.WriteLine("=============== End of training ===============");
Console.WriteLine();
O método Fit() prepara o seu modelo ao transformar o conjunto de dados e aplicar a preparação.
Devolver o modelo preparado para ser utilizado para avaliação
Devolva o modelo no final do BuildAndTrainModel()
método:
return model;
Avaliar o modelo
Depois de preparar o modelo, utilize os dados de teste para validar o desempenho do modelo.
Crie o
Evaluate()
método logo apósBuildAndTrainModel()
, com o seguinte código:void Evaluate(MLContext mlContext, ITransformer model, IDataView splitTestSet) { }
O
Evaluate()
método executa as seguintes tarefas:- Carrega o conjunto de dados de teste.
- Cria o avaliador BinaryClassification.
- Avalia o modelo e cria métricas.
- Apresenta as métricas.
Adicione uma chamada ao novo método abaixo da chamada de
BuildAndTrainModel
método com o seguinte código:Evaluate(mlContext, model, splitDataView.TestSet);
Transforme os
splitTestSet
dados ao adicionar o seguinte código aEvaluate()
:Console.WriteLine("=============== Evaluating Model accuracy with Test data==============="); IDataView predictions = model.Transform(splitTestSet);
O código anterior utiliza o método Transform() para fazer predições para várias linhas de entrada fornecidas de um conjunto de dados de teste.
Avalie o modelo ao adicionar o seguinte como a próxima linha de código no
Evaluate()
método :CalibratedBinaryClassificationMetrics metrics = mlContext.BinaryClassification.Evaluate(predictions, "Label");
Assim que tiver o conjunto de predição (predictions
), o método Evaluate() avalia o modelo, que compara os valores previstos com os valores reais Labels
no conjunto de dados de teste e devolve um objeto CalibratedBinaryClassificationMetrics sobre o desempenho do modelo.
Apresentar as métricas para validação de modelos
Utilize o seguinte código para apresentar 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
Accuracy
métrica obtém a precisão de um modelo, que é a proporção de predições corretas no conjunto de testes.A
AreaUnderRocCurve
métrica indica o quão confiante o modelo está a classificar corretamente as classes positivas e negativas. Quer que o seja oAreaUnderRocCurve
mais próximo possível de um.A
F1Score
métrica obtém a classificação F1 do modelo, que é uma medida de equilíbrio entre precisão e revocação. Quer que o seja oF1Score
mais próximo possível de um.
Prever o resultado dos dados de teste
Crie o
UseModelWithSingleItem()
método logo após oEvaluate()
método, com o seguinte código:void UseModelWithSingleItem(MLContext mlContext, ITransformer model) { }
O
UseModelWithSingleItem()
método executa as seguintes tarefas:- Cria um único comentário de dados de teste.
- Prevê o sentimento com base nos dados de teste.
- Combina dados de teste e predições para relatórios.
- Apresenta os resultados previstos.
Adicione uma chamada ao novo método diretamente sob a chamada do
Evaluate()
método com o seguinte código:UseModelWithSingleItem(mlContext, model);
Adicione o seguinte código para criar como primeira linha no
UseModelWithSingleItem()
Método:PredictionEngine<SentimentData, SentimentPrediction> predictionFunction = mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(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 oPredictionEnginePool
serviço, que cria umObjectPool
dosPredictionEngine
objetos para utilização em toda a sua aplicação. Veja este guia sobre como utilizarPredictionEnginePool
numa API Web ASP.NET Core.Nota
PredictionEnginePool
A extensão de serviço está atualmente em pré-visualização.Adicione um comentário para testar a predição do modelo preparado no
UseModelWithSingleItem()
método ao criar uma instância deSentimentData
:SentimentData sampleStatement = new SentimentData { SentimentText = "This was a very bad steak" };
Transmita os dados do comentário de teste ao
PredictionEngine
ao adicionar o seguinte como as linhas seguintes de código noUseModelWithSingleItem()
método :var resultPrediction = predictionFunction.Predict(sampleStatement);
A função Predict() faz uma predição numa única linha de dados.
Apresentar
SentimentText
e a predição de sentimento correspondente com 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();
Utilizar o modelo para predição
Implementar e prever itens de lote
Crie o
UseModelWithBatchItems()
método logo após oUseModelWithSingleItem()
método, com o seguinte código:void UseModelWithBatchItems(MLContext mlContext, ITransformer model) { }
O
UseModelWithBatchItems()
método executa as seguintes tarefas:- Cria dados de teste em lote.
- Prevê o sentimento com base nos dados de teste.
- Combina dados de teste e predições para relatórios.
- Apresenta os resultados previstos.
Adicione uma chamada ao novo método diretamente sob a chamada do
UseModelWithSingleItem()
método com o seguinte código:UseModelWithBatchItems(mlContext, model);
Adicione alguns comentários para testar as predições do modelo preparado no
UseModelWithBatchItems()
método :IEnumerable<SentimentData> sentiments = new[] { new SentimentData { SentimentText = "This was a horrible meal" }, new SentimentData { SentimentText = "I love this spaghetti." } };
Prever sentimento de comentário
Utilize o modelo para prever o sentimento dos dados de comentários com 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 apresentar as predições
Crie um cabeçalho para as predições com o seguinte código:
Console.WriteLine();
Console.WriteLine("=============== Prediction Test of loaded model with multiple samples ===============");
Uma SentimentPrediction
vez que é herdado de SentimentData
, o Transform()
método preenchido SentimentText
com os campos previstos. À medida que o processo de ML.NET é processado, cada componente adiciona colunas, o que facilita a apresentaçã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
Os seus resultados devem ser semelhantes aos seguintes. Durante o processamento, as mensagens são apresentadas. 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! Criou com êxito um modelo de machine learning para classificar e prever o sentimento das mensagens.
A criação de modelos com êxito é um processo iterativo. Este modelo tem uma qualidade inferior inicial, uma vez que o tutorial utiliza pequenos conjuntos de dados para fornecer preparação rápida de modelos. Se não estiver satisfeito com a qualidade do modelo, pode tentar melhorá-la ao fornecer conjuntos de dados de preparação maiores ou ao escolher diferentes algoritmos de preparação com diferentes hiperparâmetres para cada algoritmo.
Pode encontrar o código fonte deste tutorial no repositório dotnet/samples .
Passos seguintes
Neste tutorial, ficou a saber como:
- Criar uma aplicação de consola
- Preparar dados
- Carregar os dados
- Criar e preparar o modelo
- Avaliar o modelo
- Utilizar o modelo para fazer uma predição
- Veja os resultados
Avance para o próximo tutorial para saber mais