Partilhar via


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

  1. Crie um aplicativo C# Console chamado "SentimentAnalysis". 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 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.

  1. Baixe arquivo ZIP do conjunto de dados UCI Sentiment Labeled Sentencese descompacte.

  2. Copie o arquivo yelp_labelled.txt para o diretório Data que você criou.

  3. 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

  1. 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;
    
  2. 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");
    
  3. 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.

  4. O arquivo SentimentData.cs é aberto no editor de códigos. Adicionar a seguinte diretiva using ao topo da SentimentData.cs:

    using Microsoft.ML.Data;
    
  5. Remova a definição de classe existente e adicione o seguinte código, que tem duas classes SentimentData e SentimentPrediction, 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:

  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. Adicione o seguinte como a próxima linha de código:

    TrainTestData splitDataView = LoadData(mlContext);
    
  3. Crie um método LoadData() na parte inferior do arquivo de Program.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.
  4. 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.

  1. 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.

  2. Retorne o splitDataView no final do método LoadData():

    return splitDataView;
    

Construa e treine o modelo

  1. Adicione a seguinte chamada ao método BuildAndTrainModelabaixo da chamada ao método LoadData:

    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.
  2. Crie o método BuildAndTrainModel(), abaixo do método LoadData(), usando o seguinte código:

    ITransformer BuildAndTrainModel(MLContext mlContext, IDataView splitTrainSet)
    {
    
    }
    

Extrair e transformar os dados

  1. 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érica Features 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 Fit() treina seu modelo transformando o conjunto de dados e aplicando o treinamento.

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.

  1. Crie o método Evaluate(), logo após BuildAndTrainModel(), 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.
  2. Adicione uma chamada ao novo método abaixo da chamada de método BuildAndTrainModel usando o seguinte código:

    Evaluate(mlContext, model, splitDataView.TestSet);
    
  3. Transforme os dados splitTestSet adicionando o seguinte código a Evaluate():

    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.

  4. 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 (), o método Evaluate() avalia o modelo, que compara os valores previstos com o real no conjunto de dados de teste e retorna um objeto CalibratedBinaryClassificationMetrics sobre o desempenho do modelo.

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 o AreaUnderRocCurve 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 o F1Score seja o mais próximo possível de 1.

Prever o resultado dos dados do teste

  1. Crie o método UseModelWithSingleItem(), logo após o método Evaluate(), 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.
  2. Adicione uma chamada ao novo método logo abaixo da chamada de método Evaluate() usando o seguinte código:

    UseModelWithSingleItem(mlContext, model);
    
  3. 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ço PredictionEnginePool, que cria uma ObjectPool de objetos PredictionEngine para uso em todo o aplicativo. Consulte este guia sobre como usar PredictionEnginePool em umASP.NET Core Web API .

    Observação

    PredictionEnginePool ampliação de serviço está atualmente em versão preliminar.

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

    SentimentData sampleStatement = new SentimentData
    {
        SentimentText = "This was a very bad steak"
    };
    
  5. Passe os dados de comentário de teste para o PredictionEngine adicionando o seguinte como as próximas linhas de código no método UseModelWithSingleItem():

    var resultPrediction = predictionFunction.Predict(sampleStatement);
    

    A função Predict() faz uma previsão em uma única linha de dados.

  6. 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

  1. Crie o método UseModelWithBatchItems(), logo após o método UseModelWithSingleItem(), 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.
  2. Adicione uma chamada ao novo método logo abaixo da chamada de método UseModelWithSingleItem() usando o seguinte código:

    UseModelWithBatchItems(mlContext, model);
    
  3. 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