Compartilhar 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 uma classificação de problema do GitHub para treinar um modelo que classifica e prevê o rótulo de área de um problema do GitHub por meio de um aplicativo de console do .NET Core usando C# no Visual Studio.

Neste tutorial, você aprenderá a:

  • Preparar seus dados
  • Transformar os dados
  • Treinar o modelo
  • Avaliar o modelo
  • Prever com o modelo treinado
  • Implantar e prever com um modelo carregado

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

Pré-requisitos

Criar um aplicativo de console

Criar um projeto

  1. Crie um aplicativo de console C# chamado "GitHubIssueClassification". Selecione Avançar.

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

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

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

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

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

  5. Instalar 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 no seu projeto e selecione Gerenciar Pacotes NuGet. Escolha "nuget.org" como a origem do Pacote, selecione a guia Procurar, pesquise Microsoft.ML e selecione o botão Instalar. Selecione o botão OK na caixa de diálogo Visualizar Alterações e selecione o botão Aceito na caixa de diálogo Aceitação da Licença, se concordar com o termos de licença para os pacotes listados.

Preparar seus dados

  1. Baixe os conjuntos de dados issues_train.tsv e issues_test.tsv e salve-os na pasta Dados que foi criada. 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 novo.

Criar classes e definir demarcadores

Adicione as seguintes instruções using adicionais ao início 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 MLContext, DataView e PredictionEngine:

  • _trainDataPath tem o demarcador para o conjunto de dados usado para treinar o modelo.
  • _testDataPath tem o demarcador para o conjunto de dados usado para avaliar o modelo.
  • _modelPath tem o demarcador em que o modelo treinado é salvo.
  • _mlContext é o MLContext que fornece o 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 instruções de uso para especificar estes caminhos e 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 os dados de entrada e as 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 o botão Adicionar.

    O arquivo GitHubIssueData.cs é aberto no editor de códigos. Adicione a seguinte instrução using acima de GitHubIssueData.cs:

using Microsoft.ML.Data;

Remova a definição de classe existente e adicione o seguinte código, que tem duas classes, GitHubIssue e IssuePrediction, ao arquivo GitHubIssueData.cs:

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;
}

O label é a coluna que você deseja prever. O Features identificado são as entradas que você atribui ao modelo para prever o rótulo.

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

GitHubIssue é a classe de 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 do treinamento)
  • a terceira coluna Title (título do problema de GitHub) é o primeiro feature usado para prever o Area
  • a quarta coluna Description é o segundo feature usado para prever o Area

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

Todas as operações do ML.NET iniciam na classe MLContext. Inicializar mlContext cria um novo ambiente do ML.NET que pode ser compartilhado entre os objetos do fluxo de trabalho de criação de modelo. É similar, 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 obter resultados repetíveis/determinísticos entre vários treinamentos. Substitua a linha Console.WriteLine("Hello World!") pelo código a seguir:

_mlContext = new MLContext(seed: 0);

Carregar os dados

O ML.NET usa a interface IDataView como uma maneira flexível e eficiente de descrever dados numéricos ou tabulares de texto. O 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 utilizá-la para o pipeline, adicione o seguinte código após a inicialização de mlContext:

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

O LoadFromTextFile() define o esquema de dados e lê o arquivo. Ele usa as variáveis de caminho de dados e retorna uma IDataView.

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

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 Program.cs usando o seguinte código:

IEstimator<ITransformer> ProcessData()
{

}

Extrair recursos e transformar os dados

Uma vez que você deseja prever o rótulo do GitHub de Área de um GitHubIssue, use o método MapValueToKey() para transformar a coluna Area em um tipo de chave numérica Label (um formato aceito pelos algoritmos de classificação da coluna) e adicione-o como uma nova coluna de conjunto de dados:

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

Em seguida, chame mlContext.Transforms.Text.FeaturizeText que transforma as colunas do texto (Title e Description) em um vetor numérico para cada TitleFeaturized e DescriptionFeaturized chamado. Acrescente a personalização para ambas as colunas ao pipeline com o código a seguir:

.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 recursos na coluna Recursos usando o método Concatenate(). Por padrão, um algoritmo de aprendizado processa apenas os recursos da coluna Features. Acrescente esta transformação ao pipeline com o código a seguir:

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

Em seguida, acrescente um AppendCacheCheckpoint para armazenar a DataView em cache, para melhorar o desempenho ao iterar nos dados várias vezes usando o cache, como no código a seguir:

.AppendCacheCheckpoint(_mlContext);

Aviso

Use AppendCacheCheckpoint para conjuntos de dados pequenos/médios a fim de reduzir o tempo de treinamento. NÃO o utilize (remova .AppendCacheCheckpoint()) ao lidar com conjuntos de dados grandes.

Retorne o pipeline no final do método ProcessData.

return pipeline;

Esta etapa manipula o pré-processamento/personalização. Usar componentes adicionais disponíveis no ML.NET pode permitir melhores resultados com o seu modelo.

Criar e treinar o modelo

Adicione a seguinte chamada ao método BuildAndTrainModel como a próxima linha após a chamada ao 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.
  • Retorna 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 costuma ser de um dos seguintes tipos:

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

Para esse tipo de problema, use um algoritmo de aprendizado de classificação Multiclasse, pois a previsão de categoria do problema pode ser uma das várias categorias (multiclasse), em vez de apenas duas (binária).

Acrescente 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 é seu algoritmo de treinamento de classificação multiclasse. Isso é anexado ao pipeline e aceita os Title e Description (Features) personalizados e os parâmetro de entrada Label para aprender com os 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 o modelo transformando o conjunto de dados e aplicando o treinamento.

O PredictionEngine é uma API de conveniência, que permite passar uma única instância de dados e, em seguida, executar uma previsão nessa única instância de dados. Adicione isso 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 ao criar 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() faz uma previsão em uma única coluna de dados:

var prediction = _predEngine.Predict(issue);

Usar o modelo: resultados de previsão

Exiba GitHubIssue e a previsão de rótulo Area correspondente para compartilhar os resultados e agir de acordo com eles. Crie uma exibição para os resultados usando o seguinte código Console.WriteLine():

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

Retornar o modelo treinado a ser usado para avaliação

Retorne 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 do 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 pelos avaliadores de classificação multiclasse. Para exibir as métricas para determinar a qualidade do modelo, você precisará obtê-las primeiro. Observe o uso do método Transform() da variável global _trainedModel de aprendizado de máquina (um Transformador) para inserir os recursos e retornar previsões. Adicione o seguinte código ao método Evaluate como a linha seguinte:

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

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

  • Microprecisão – todo par de classe/exemplo contribui igualmente para a métrica de precisão. Convém que a Microprecisão seja tão próxima de 1 quanto possível.

  • Macroprecisão – toda classe contribui igualmente para a métrica de precisão. Classes minoritárias recebem o mesmo peso que as classes maiores. Convém que a Macroprecisão seja tão próxima de 1 quanto possível.

  • Perda de log – consulte Perda de log. Convém que a Perda de log seja tão próxima de zero quanto possível.

  • Redução de perda de log – varia de [-inf, 1.00], em que 1.00 é composto pelas previsões perfeitas e 0 indica previsões de média. Convém que a redução de perda de log seja tão próxima de 1 quanto possível.

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

Use o código a seguir para exibir as métricas, compartilhar os resultados e, em seguida, agir com relação a 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

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

SaveModelAsFile(_mlContext, trainingDataViewSchema, _trainedModel);

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

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

}

Adicione o código a seguir ao 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 do método Evaluate usando o seguinte código:

PredictIssue();

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

void PredictIssue()
{

}

O método PredictIssue executa as seguintes tarefas:

  • Carrega o modelo salvo
  • Cria um único problema dos 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 ao criar uma instância de GitHubIssue:

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

Como você fez anteriormente, crie uma instância de PredictionEngine com o código a seguir:

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

O PredictionEngine é uma API de conveniência, que permite executar uma previsão em uma instância individual de dados. PredictionEngine não é thread-safe. É aceitável usá-lo em ambientes de thread único ou de protótipo. Para aprimorar o desempenho e o acesso thread-safe em ambientes de produção, use o serviço PredictionEnginePool, que cria um ObjectPool de objetos PredictionEngine para uso em todo o aplicativo. Confira este guia sobre como usar o PredictionEnginePool em uma API Web ASP.NET Core.

Observação

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

Use o PredictionEngine para prever o rótulo do GitHub de Área 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

Exiba Area para categorizar o problema e agir adequadamente para solucioná-lo. Crie uma exibição para os resultados usando o seguinte código Console.WriteLine():

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

Resultados

Seus resultados devem ser semelhantes aos seguintes. Conforme o pipeline processa, exibe mensagens. Você pode ver avisos ou mensagens de processamento. Essas mensagens foram removidas dos resultados a seguir para ficar mais claro.

=============== 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 machine learning para classificar e prever um rótulo de Área para um problema do GitHub. Você pode encontrar o código-fonte para este tutorial no repositório dotnet/samples.

Próximas etapas

Neste tutorial, você aprendeu a:

  • Preparar seus dados
  • Transformar os dados
  • Treinar o modelo
  • Avaliar o modelo
  • Prever com o modelo treinado
  • Implantar e prever com um modelo carregado

Avançar para o próximo tutorial para saber mais