Partilhar via


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

  1. Crie uma Aplicação de Consola C# denominada "SentimentAnalysis". 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.

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.

  1. Transfira o ficheiro ZIP do conjunto de dados Frases Etiquetadas pelo Sentimento UCI e deszipe.

  2. Copie o yelp_labelled.txt ficheiro para o diretório Dados que criou.

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

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

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

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

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

  1. 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 testFractionparâmetro . A predefinição é 10%, neste caso, utiliza 20% para avaliar mais dados.

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

    return splitDataView;
    

Criar e preparar o modelo

  1. Adicione a seguinte chamada ao BuildAndTrainModelmétodo abaixo da chamada ao LoadData 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.
  2. Crie o BuildAndTrainModel() método, abaixo do LoadData() método, com 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 FeaturizeText() método no código anterior converte a coluna de texto (SentimentText) numa coluna de tipo Features 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.

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

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

    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.

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

Prever o resultado dos dados de teste

  1. Crie o UseModelWithSingleItem() método logo após o Evaluate() 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.
  2. Adicione uma chamada ao novo método diretamente sob a chamada do Evaluate() método com o seguinte código:

    UseModelWithSingleItem(mlContext, model);
    
  3. 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 o PredictionEnginePool serviço, que cria um ObjectPool dos PredictionEngine objetos 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.

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

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

    var resultPrediction = predictionFunction.Predict(sampleStatement);
    

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

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

  1. Crie o UseModelWithBatchItems() método logo após o UseModelWithSingleItem() 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.
  2. Adicione uma chamada ao novo método diretamente sob a chamada do UseModelWithSingleItem() método com o seguinte código:

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