Partilhar via


Tutorial: Categorizar problemas de suporte usando a classificação multiclasse com ML.NET

Este tutorial de exemplo ilustra o uso do ML.NET para criar um classificador de problemas do GitHub para treinar um modelo que classifica e prevê o rótulo de área para um problema do GitHub por meio de um aplicativo de console .NET usando C# no Visual Studio.

Neste tutorial, você aprenderá a:

  • Prepare os seus dados
  • Transformar os dados
  • Treinar o modelo
  • Avaliar o modelo
  • Prever com o modelo treinado
  • Desdobrar e realizar previsões com um modelo já carregado

Você pode encontrar o código-fonte deste tutorial no repositório dotnet/samples .

Pré-requisitos

Criar um aplicativo de console

Criar um projeto

  1. Crie uma aplicação de consola C# chamada "GitHubIssueClassification". Selecione Avançar.

  2. Escolha .NET 7 como a estrutura a ser usada. Selecione Criar.

  3. Crie um diretório chamado Data em seu projeto para salvar seus arquivos de conjunto de dados:

    No Gerenciador de Soluções, clique com o botão direito do mouse em seu projeto e selecione Adicionar>Nova Pasta. Digite "Dados" e pressione Enter.

  4. Crie um diretório chamado Models em seu projeto para salvar seu modelo:

    No Gerenciador de Soluções, clique com o botão direito do mouse em seu projeto e selecione Adicionar>Nova Pasta. Digite "Modelos" e pressione a tecla Enter.

  5. 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, selecione a guia Procurar, procure Microsoft.ML e selecione Instalar. Selecione o botão OK na caixa de diálogo Pré-visualização de Alterações e, em seguida, selecione o botão Aceito na caixa de diálogo Aceitação de Licença caso concorde com os termos da licença para os pacotes listados.

Prepare os seus dados

  1. Transfira o conjunto de dados issues_train.tsv e o conjunto de dados issues_test.tsv e guarde-os na pasta Data que criou anteriormente. O primeiro conjunto de dados treina o modelo de aprendizado de máquina e o segundo pode ser usado para avaliar a precisão do seu modelo.

  2. No Gerenciador de Soluções, clique com o botão direito do mouse em cada um dos arquivos *.tsv e selecione Propriedades. Em Avançado, 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 diretivas using adicionais à parte superior do arquivo Program.cs:

using Microsoft.ML;
using GitHubIssueClassification;

Crie três campos globais para manter os caminhos para os arquivos baixados recentemente e variáveis globais para os MLContext, DataViewe PredictionEngine:

  • _trainDataPath tem o caminho para o conjunto de dados usado para treinar o modelo.
  • _testDataPath tem o caminho para o conjunto de dados usado para avaliar o modelo.
  • _modelPath tem o caminho onde o modelo treinado é salvo.
  • _mlContext é o MLContext que fornece contexto de processamento.
  • _trainingDataView é o IDataView usado para processar o conjunto de dados de treinamento.
  • _predEngine é o PredictionEngine<TSrc,TDst> usado para previsões individuais.

Adicione o seguinte código à linha diretamente abaixo das diretivas using para especificar esses caminhos e as outras variáveis:

string _appPath = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) ?? ".";
string _trainDataPath = Path.Combine(_appPath, "..", "..", "..", "Data", "issues_train.tsv");
string _testDataPath = Path.Combine(_appPath, "..", "..", "..", "Data", "issues_test.tsv");
string _modelPath = Path.Combine(_appPath, "..", "..", "..", "Models", "model.zip");

MLContext _mlContext;
PredictionEngine<GitHubIssue, IssuePrediction> _predEngine;
ITransformer _trainedModel;
IDataView _trainingDataView;

Crie algumas classes para seus dados de entrada e previsões. Adicione uma nova classe ao seu projeto:

  1. No Gerenciador de Soluções , clique com o botão direito do mouse no projeto e selecione Adicionar>Novo Item.

  2. Na caixa de diálogo Adicionar Novo Item, selecione Classe e altere o campo Nome para GitHubIssueData.cs. Em seguida, selecione Adicionar.

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

    using Microsoft.ML.Data;
    
  3. Remova a definição de classe existente e adicione o seguinte código ao arquivo GitHubIssueData.cs. Este código tem duas classes, GitHubIssue e IssuePrediction.

    public class GitHubIssue
    {
        [LoadColumn(0)]
        public string? ID { get; set; }
        [LoadColumn(1)]
        public string? Area { get; set; }
        [LoadColumn(2)]
        public required string Title { get; set; }
        [LoadColumn(3)]
        public required string Description { get; set; }
    }
    
    public class IssuePrediction
    {
        [ColumnName("PredictedLabel")]
        public string? Area;
    }
    

    A label é a coluna que você deseja prever. Os Features identificados são as entradas que você dá ao modelo para prever o rótulo.

    Utilize o LoadColumnAttribute para especificar os índices das colunas de origem no conjunto de dados.

    GitHubIssue é a classe do conjunto de dados de entrada e tem os seguintes campos String:

    • A primeira coluna ID (ID de Problema do GitHub).
    • A segunda coluna Area (a previsão para o treinamento).
    • A terceira coluna Title (título da edição do GitHub) é a primeira feature usada para prever o Area.
    • A quarta coluna Description é a segunda feature usada para prever o Area.

    IssuePrediction é a classe usada para previsão após o modelo ter sido treinado. Tem um único string (Area) e um atributo PredictedLabelColumnName. O PredictedLabel é usado durante a previsão e avaliação. Para a avaliação, é usada uma entrada com dados de treinamento, os valores previstos e o modelo.

    Todas as operações ML.NET começam na classe MLContext. 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, a DBContext em Entity Framework.

Inicializar variáveis

Inicialize a variável global _mlContext com uma nova instância de MLContext com uma semente aleatória (seed: 0) para resultados determinísticos/repetíveis em vários treinamentos. Substitua a linha Console.WriteLine("Hello World!") pelo seguinte código:

_mlContext = new MLContext(seed: 0);

Carregue os dados

ML.NET usa a interface IDataView como uma maneira flexível e eficiente de descrever dados numéricos ou tabulares de texto. IDataView pode carregar arquivos de texto ou em tempo real (por exemplo, banco de dados SQL ou arquivos de log).

Para inicializar e carregar a variável global _trainingDataView para usá-la para o pipeline, adicione o seguinte código após a inicialização do mlContext:

_trainingDataView = _mlContext.Data.LoadFromTextFile<GitHubIssue>(_trainDataPath,hasHeader: true);

O LoadFromTextFile() define o esquema de dados e lê no arquivo. Recebe as variáveis do caminho de dados e retorna um IDataView.

Adicione o seguinte depois de chamar o método LoadFromTextFile():

var pipeline = ProcessData();

O método ProcessData executa as seguintes tarefas:

  • Extrai e transforma os dados.
  • Retorna o pipeline de processamento.

Crie o método ProcessData na parte inferior do arquivo de Program.cs usando o seguinte código:

IEstimator<ITransformer> ProcessData()
{

}

Extraia recursos e transforme os dados

Como pretendes prever o rótulo do GitHub da Área para um GitHubIssue, usa o método MapValueToKey() para transformar a coluna Area em uma coluna de tipo de chave numérica Label (um formato aceite por algoritmos de classificação) e adicioná-la como uma nova coluna do conjunto de dados.

var pipeline = _mlContext.Transforms.Conversion.MapValueToKey(inputColumnName: "Area", outputColumnName: "Label")

Em seguida, chame mlContext.Transforms.Text.FeaturizeText, que transforma as colunas de texto (Title e Description) num vetor numérico para cada TitleFeaturized e DescriptionFeaturizedchamado. Anexe a featurização de ambas as colunas ao pipeline com o seguinte código:

.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Title", outputColumnName: "TitleFeaturized"))
.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Description", outputColumnName: "DescriptionFeaturized"))

A última etapa na preparação de dados combina todas as colunas de características na coluna Recursos usando o método Concatenate(). Por padrão, um algoritmo de aprendizagem processa apenas características da coluna Features. Anexe essa transformação ao pipeline com o seguinte código:

.Append(_mlContext.Transforms.Concatenate("Features", "TitleFeaturized", "DescriptionFeaturized"))

Em seguida, acrescente um AppendCacheCheckpoint para armazenar em cache o DataView para que, quando você iterar sobre os dados várias vezes usando o cache, possa obter um melhor desempenho, como com o código a seguir:

.AppendCacheCheckpoint(_mlContext);

Advertência

Use AppendCacheCheckpoint para conjuntos de dados pequenos/médios para reduzir o tempo de treinamento. NÃO o utilize (remover . AppendCacheCheckpoint()) ao manipular conjuntos de dados muito grandes.

Retorne o pipeline no final do método ProcessData.

return pipeline;

Esta etapa lida com o pré-processamento e a extração de características. O uso de componentes adicionais disponíveis no ML.NET pode permitir melhores resultados com seu modelo.

Construa e treine o modelo

Adicione a seguinte chamada ao método BuildAndTrainModelcomo a próxima linha após a chamada para o método ProcessData():

var trainingPipeline = BuildAndTrainModel(_trainingDataView, pipeline);

O método BuildAndTrainModel executa as seguintes tarefas:

  • Cria a classe de algoritmo de treinamento.
  • Treina o modelo.
  • Prevê a área com base em dados de treinamento.
  • Devolve o modelo.

Crie o método BuildAndTrainModel, logo após a declaração do método ProcessData(), usando o seguinte código:

IEstimator<ITransformer> BuildAndTrainModel(IDataView trainingDataView, IEstimator<ITransformer> pipeline)
{

}

Sobre a tarefa de classificação

A classificação é uma tarefa de aprendizado de máquina que usa dados para determinar a categoria, o tipo ou a classe de um item ou linha de dados e é frequentemente um dos seguintes tipos:

  • Binário: A ou B.
  • Multiclasse: várias categorias que podem prever-se usando um único modelo.

Para este tipo de problema, use um algoritmo de aprendizagem de classificação multiclasse, uma vez que a previsão da categoria do problema pode ser uma de várias categorias (multiclasse) em vez de apenas duas (binária).

Anexe o algoritmo de aprendizado de máquina às definições de transformação de dados adicionando o seguinte como a primeira linha de código em BuildAndTrainModel():

var trainingPipeline = pipeline.Append(_mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy("Label", "Features"))
        .Append(_mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

O SdcaMaximumEntropy é o seu algoritmo de formação para classificação multiclasse. Isto é anexado ao pipeline e aceita os Title e Description featurizados (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():

_trainedModel = trainingPipeline.Fit(trainingDataView);

O método Fit()treina seu modelo transformando o conjunto de dados e aplicando o treinamento.

O PredictionEngine é uma API prática que permite passar e depois executar uma previsão em uma única instância de dados. Adicione esta como a próxima linha no método BuildAndTrainModel():

_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(_trainedModel);

Prever com o modelo treinado

Adicione um problema do GitHub para testar a previsão do modelo treinado no método Predict criando uma instância de GitHubIssue:

GitHubIssue issue = new GitHubIssue() {
    Title = "WebSockets communication is slow in my machine",
    Description = "The WebSockets communication used under the covers by SignalR looks like is going slow in my development machine.."
};

Use a função Predict() para fazer uma previsão em uma única linha de dados:

var prediction = _predEngine.Predict(issue);

Use o modelo: Resultados de previsão

Exiba GitHubIssue e a previsão do rótulo correspondente de Area para partilhar os resultados e agir em conformidade. Crie uma exibição para os resultados usando o seguinte código Console.WriteLine():

Console.WriteLine($"=============== Single Prediction just-trained-model - Result: {prediction.Area} ===============");

Devolve o modelo treinado para ser usado na avaliação.

Retornar o modelo no final do método BuildAndTrainModel.

return trainingPipeline;

Avaliar o modelo

Agora que você criou e treinou o modelo, precisa avaliá-lo com um conjunto de dados diferente para garantia de qualidade e validação. No método Evaluate, o modelo criado em BuildAndTrainModel é passado para ser avaliado. Crie o método Evaluate, logo após BuildAndTrainModel, como no código a seguir:

void Evaluate(DataViewSchema trainingDataViewSchema)
{

}

O método Evaluate executa as seguintes tarefas:

  • Carrega o conjunto de dados de teste.
  • Cria o avaliador multiclasse.
  • Avalia o modelo e cria métricas.
  • Exibe as métricas.

Adicione uma chamada ao novo método, logo abaixo da chamada de método BuildAndTrainModel, usando o seguinte código:

Evaluate(_trainingDataView.Schema);

Como você fez anteriormente com o conjunto de dados de treinamento, carregue o conjunto de dados de teste adicionando o seguinte código ao método Evaluate:

var testDataView = _mlContext.Data.LoadFromTextFile<GitHubIssue>(_testDataPath,hasHeader: true);

O método Evaluate() calcula as métricas de qualidade para o modelo usando o conjunto de dados especificado. Ele retorna um objeto MulticlassClassificationMetrics que contém as métricas gerais calculadas por avaliadores de classificação de várias classes. Para exibir as métricas para determinar a qualidade do modelo, você precisa obtê-las primeiro. Observe o uso do método Transform() do aprendizado de máquina variável global (um ITransformer) para inserir os recursos e previsões de retorno. Adicione o seguinte código ao método Evaluate como a próxima linha:

var testMetrics = _mlContext.MulticlassClassification.Evaluate(_trainedModel.Transform(testDataView));

As seguintes métricas são avaliadas para classificação multiclasse:

  • Micro Precisão - Cada par de classe de amostra contribui igualmente para a métrica de precisão. Você quer que a Micro Accuracy seja o mais próxima possível de uma.
  • Precisão de macro - Cada classe contribui igualmente para a métrica de precisão. Às classes minoritárias é atribuído o mesmo peso que às classes maiores. Você deseja que a Precisão de Macro seja o mais próxima possível de um.
  • Log-loss - consulte Log Loss. Você quer que o log loss seja o mais próximo de zero possível.
  • Redução de perda de log - Varia de [-inf, 1,00], onde 1,00 representa previsões perfeitas e 0 indica previsões baseadas na média. Você quer que a redução da perda logarítmica seja tão próxima de um quanto possível.

Exibir as métricas para validação do modelo

Use o código a seguir para exibir as métricas, compartilhar os resultados e, em seguida, agir sobre eles:

Console.WriteLine($"*************************************************************************************************************");
Console.WriteLine($"*       Metrics for Multi-class Classification model - Test Data     ");
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
Console.WriteLine($"*       MicroAccuracy:    {testMetrics.MicroAccuracy:0.###}");
Console.WriteLine($"*       MacroAccuracy:    {testMetrics.MacroAccuracy:0.###}");
Console.WriteLine($"*       LogLoss:          {testMetrics.LogLoss:#.###}");
Console.WriteLine($"*       LogLossReduction: {testMetrics.LogLossReduction:#.###}");
Console.WriteLine($"*************************************************************************************************************");

Salvar o modelo em um arquivo

Uma vez satisfeito com seu modelo, salve-o em um arquivo para fazer previsões posteriormente ou em outro aplicativo. Adicione o seguinte código ao método Evaluate.

SaveModelAsFile(_mlContext, trainingDataViewSchema, _trainedModel);

Crie o método SaveModelAsFile abaixo do seu método Evaluate.

void SaveModelAsFile(MLContext mlContext,DataViewSchema trainingDataViewSchema, ITransformer model)
{

}

Adicione o seguinte código ao seu método SaveModelAsFile. Esse código usa o método Save para serializar e armazenar o modelo treinado como um arquivo zip.

mlContext.Model.Save(model, trainingDataViewSchema, _modelPath);

Implantar e prever com um modelo

Adicione uma chamada ao novo método, logo abaixo da chamada de método Evaluate, usando o seguinte código:

PredictIssue();

Crie o método PredictIssue, logo após o método Evaluate (e imediatamente antes do método SaveModelAsFile), usando o seguinte código:

void PredictIssue()
{

}

O método PredictIssue executa as seguintes tarefas:

  • Carrega o modelo guardado.
  • Cria um único problema de dados de teste.
  • Prevê a área com base em dados de teste.
  • Combina dados de teste e previsões para relatórios.
  • Exibe os resultados previstos.

Carregue o modelo salvo em seu aplicativo adicionando o seguinte código ao método PredictIssue:

ITransformer loadedModel = _mlContext.Model.Load(_modelPath, out var modelInputSchema);

Adicione um problema do GitHub para testar a previsão do modelo treinado no método Predict criando uma instância de GitHubIssue:

GitHubIssue singleIssue = new GitHubIssue() { Title = "Entity Framework crashes", Description = "When connecting to the database, EF is crashing" };

Como fez anteriormente, crie uma instância PredictionEngine com o seguinte código:

_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(loadedModel);

O PredictionEngine é uma API de conveniência que permite executar uma previsão em uma única instância de dados. PredictionEngine não é seguro para threads. É aceitável usar em ambientes monothread ou de protótipo. 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 numaASP.NET Core Web API.

Observação

A extensão de serviço PredictionEnginePool está atualmente em versão de pré-visualização.

Use o PredictionEngine para prever o rótulo Area GitHub adicionando o seguinte código ao método PredictIssue para a previsão:

var prediction = _predEngine.Predict(singleIssue);

Usar o modelo carregado para previsão

Exibir Area para categorizar o problema e agir de acordo. Crie uma exibição para os resultados usando o seguinte código Console.WriteLine():

Console.WriteLine($"=============== Single Prediction - Result: {prediction.Area} ===============");

Resultados obtidos

Os resultados devem ser semelhantes aos seguintes. À medida que o pipeline processa, ele exibe mensagens. Poderá ver avisos ou mensagens de processamento. Essas mensagens foram removidas dos seguintes resultados para maior clareza.

=============== Single Prediction just-trained-model - Result: area-System.Net ===============
*************************************************************************************************************
*       Metrics for Multi-class Classification model - Test Data
*------------------------------------------------------------------------------------------------------------
*       MicroAccuracy:    0.738
*       MacroAccuracy:    0.668
*       LogLoss:          .919
*       LogLossReduction: .643
*************************************************************************************************************
=============== Single Prediction - Result: area-System.Data ===============

Parabéns;! Agora você criou com sucesso um modelo de aprendizado de máquina para classificar e prever um rótulo de área para um problema do GitHub. Você pode encontrar o código-fonte deste tutorial no repositório dotnet/samples .

Próximos passos

Neste tutorial, você aprendeu como:

  • Prepare os seus dados
  • Transformar os dados
  • Treinar o modelo
  • Avaliar o modelo
  • Prever com o modelo treinado
  • Implantar e fazer previsões com um modelo carregado

Avance para o próximo tutorial para saber mais.