Учебник. Классификация заявок на поддержку с использованием мультиклассовой классификации с помощью ML.NET

В этом практическом руководстве демонстрируется создание классификатора задач GitHub для обучения модели, классифицирующей и прогнозирующей метки области для задач на GitHub, с помощью ML.NET в консольном приложении .NET Core на языке C# в Visual Studio.

В этом руководстве вы узнаете, как:

  • подготавливать данные;
  • Преобразование данных
  • Обучение модели
  • Оценка модели
  • Прогнозирование с помощью обученной модели
  • Развертывание и прогнозирование с помощью загруженной модели

Исходный код для этого руководства можно найти в репозитории dotnet/samples.

Предварительные требования

Создание консольного приложения

Создание проекта

  1. Создайте консольное приложение C# с именем GitHubIssueClassification. Выберите Далее.

  2. Выберите .NET 7 в качестве используемой платформы. Нажмите кнопку создания.

  3. Создайте каталог с именем Data в папке проекта, чтобы сохранить в нем файлы с наборами данных:

    В обозревателе решений щелкните проект правой кнопкой мыши и выберите Добавить>Новая папка. Введите "Данные" и нажмите клавишу ВВОД.

  4. Создайте каталог с именем Models в папке проекта, чтобы сохранить модель:

    В обозревателе решений щелкните проект правой кнопкой мыши и выберите Добавить>Новая папка. Введите "Models" и нажмите клавишу ВВОД.

  5. Установите пакет NuGet для Microsoft.ML:

    Примечание

    В этом примере используется последняя стабильная версия пакетов NuGet, упомянутых выше, если не указано иное.

    В обозревателе решений щелкните проект правой кнопкой мыши и выберите Управление пакетами NuGet. Выберите nuget.org в качестве источника пакета, откройте вкладку "Обзор", выполните поиск по запросу Microsoft.ML и нажмите кнопку Установить. Нажмите кнопку ОК в диалоговом окне Предварительный просмотр изменений, а затем нажмите кнопку Принимаю в диалоговом окне Принятие условий лицензионного соглашения, если вы согласны с указанными условиями лицензионного соглашения для выбранных пакетов.

подготавливать данные;

  1. Скачайте наборы данных issues_train.tsv и issues_test.tsv и сохраните их в ранее созданную папку Data . Первый из этих наборов данных обучает модель машинного обучения, а второй позволяет оценить точность полученной модели.

  2. В Обозреватель решений щелкните правой кнопкой мыши каждый из файлов *.tsv и выберите Свойства. В разделе Дополнительно для параметра Копировать в выходной каталог установите значение Копировать более позднюю версию.

Создание классов и определение путей

Добавьте следующие новые операторы using в начало файла Program.cs:

using Microsoft.ML;
using GitHubIssueClassification;

Создайте три глобальных поля для хранения путей к недавно скачанным файлам и глобальные переменные для MLContext, DataView и PredictionEngine:

  • _trainDataPath содержит путь к набору данных, используемому для обучения модели;
  • _testDataPath содержит путь к набору данных, используемому для оценки модели;
  • _modelPath содержит путь, по которому сохраняется обученная модель.
  • _mlContext соответствует классу MLContext, предоставляющему контекст для обработки;
  • _trainingDataView представляет собой интерфейс IDataView, используемый для обработки обучающего набора данных;
  • _predEngine соответствует классу PredictionEngine<TSrc,TDst>, используемому для одиночных прогнозов;

Добавьте следующий код в строку сразу под операторами using, чтобы определить эти пути и другие переменные:

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;

Создайте несколько классов для входных данных и прогнозов. Добавьте в проект новый класс:

  1. В обозревателе решений щелкните проект правой кнопкой мыши и выберите пункты Добавить>Новый элемент.

  2. В диалоговом окне Добавление нового элемента выберите Класс и в поле Имя укажите GitHubIssueData.cs. Теперь нажмите кнопку Добавить.

    Файл GitHubIssueData.cs откроется в редакторе кода. Добавьте следующий оператор using в начало файла GitHubIssueData.cs:

using Microsoft.ML.Data;

Удалите из файла GitHubIssueData.cs существующее определение класса и добавьте следующий код с двумя классами GitHubIssue и 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;
}

label — это столбец для прогнозирования. Определены Featuresвходные данные, которые вы предоставляете модели для прогнозирования метки.

Используйте атрибут LoadColumnAttribute, чтобы указать индексы исходных столбцов в файле набора данных.

GitHubIssue является классом входного набора данных и имеет следующие поля String:

  • Первый столбец ID (идентификатор задачи GitHub).
  • Второй столбец Area (прогноз для обучения).
  • Третий столбец Title (название задачи GitHub) является первым feature, используемым для прогнозирования Area
  • четвертый столбец Description является вторым feature , используемым для прогнозирования Area

Класс IssuePrediction используется для прогнозирования после обучения модели. Он имеет один параметр типа string (Area) и атрибут PredictedLabelColumnName. PredictedLabel используется для прогнозирования и оценки. Для оценки применяются входные обучающие данные, прогнозируемые значения и модель.

Все операции ML.NET запускаются в классе MLContext. Инициализация mlContext создает новую среду ML.NET, которую могут совместно использовать объекты рабочего процесса создания модели. По сути, он аналогичен классу DBContext в Entity Framework.

Инициализация переменных

Инициализируйте _mlContext глобальную переменную с новым экземпляром MLContext со случайным начальным значением (seed: 0) для повторяемых или детерминированных результатов в нескольких обучениях. Замените строку Console.WriteLine("Hello World!") следующим кодом:

_mlContext = new MLContext(seed: 0);

Загрузка данных

ML.NET использует интерфейс IDataView в качестве гибкого и эффективного средства описания числовых или текстовых табличных данных. IDataView может загружать данные из текстового файла или в режиме реального времени (например, из базы данных SQL или файлов журнала).

Чтобы инициализировать и загрузить глобальную _trainingDataView переменную для ее использования в конвейере, добавьте следующий код после инициализации mlContext :

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

Метод LoadFromTextFile() определяет схему данных и считывает файл. Он принимает переменные, содержащие пути к данным, и возвращает объект IDataView.

Добавьте следующий код после вызова метода LoadFromTextFile().

var pipeline = ProcessData();

Метод ProcessData выполняет следующие задачи:

  • извлечение и преобразование данных;
  • возвращение конвейера обработки.

Создайте метод ProcessData в конце файла Program.cs, используя следующий код:

IEstimator<ITransformer> ProcessData()
{

}

Извлечение признаков и преобразование данных

Мы хотим прогнозировать метки области GitHub для GitHubIssue, поэтому стоит использовать метод MapValueToKey() для преобразования столбца Area в числовой тип ключа столбца Label (формат, который принимают алгоритмы классификации) и добавить его как новый столбец набора данных:

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

Затем вызовите mlContext.Transforms.Text.FeaturizeText, который преобразует столбцы текста (Title и Description) в числовой вектор для вызываемых TitleFeaturized и DescriptionFeaturized соответственно. Добавьте присвоение признаков для обоих столбцов в конвейере, используя следующий код:

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

Последний шаг на этапе подготовки данных заключается в объединении всех столбцов признаков в столбце Features с помощью метода преобразования Concatenate(). По умолчанию алгоритм обучения обрабатывает только признаки, представленные в столбце Features. Добавьте это преобразование в конвейер, используя следующий код:

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

Затем добавьте AppendCacheCheckpoint для кэширования DataView, которое может ускорить обучение при многократных итерациях по данным, используя следующий код:

.AppendCacheCheckpoint(_mlContext);

Предупреждение

Используйте AppendCacheCheckpoint для небольших и средних наборов данных для ускорения обучения. НЕ используйте AppendCacheCheckpoint (удалите .AppendCacheCheckpoint()) при обработке очень больших наборов данных.

Выполните возврат конвейера в конце метода ProcessData.

return pipeline;

На этом этапе выполняется предварительная обработка и присвоение признаков. Дополнительные компоненты из ML.NET могут дать более точные результаты для вашей модели.

Сборка и обучение модели

Добавьте следующий вызов метода BuildAndTrainModel в качестве следующей строки после вызова метода ProcessData():

var trainingPipeline = BuildAndTrainModel(_trainingDataView, pipeline);

Метод BuildAndTrainModel выполняет следующие задачи:

  • создание класса алгоритма обучения;
  • обучение модели;
  • прогнозирование области на основе обучающих данных;
  • возвращение модели.

Создайте метод BuildAndTrainModel сразу после объявления метода ProcessData(), используя следующий код:

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

}

Сведения о задаче классификации

Классификацией называют задачу машинного обучения, которая использует данные для определения категории, типа или класса для некоторого элемента или ряда данных. Часто она имеет следующие виды:

  • Двоичная: A или B.
  • Многоклассовая: несколько категорий, которые прогнозируются по одной модели.

Для таких проблем используйте обучающий алгоритм многоклассовой классификации, поскольку прогноз категории проблемы может относиться к нескольким категориям (многоклассовая), а не только к двум (двоичная).

Добавьте алгоритм машинного обучения к определениям преобразований данных, добавив следующее в первой строке кода в BuildAndTrainModel():

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

SdcaMaximumEntropy — ваш алгоритм обучения классификации по нескольким классам. Он добавляется в pipeline и принимает в качестве входных параметров Title и Description (Features) с присвоенными признаками, а также Label для обучения по историческим данным.

Обучение модели

Обучите модель на основе данных splitTrainSet и получите обученную модель, добавив в метод BuildAndTrainModel() следующие строки кода:

_trainedModel = trainingPipeline.Fit(trainingDataView);

Метод Fit() обучает модель путем преобразования набора данных и применения обучения.

Класс PredictionEngine представляет собой удобный API, позволяющий передать один экземпляр данных и осуществить прогнозирование на его основе. Добавьте следующую строку кода в метод BuildAndTrainModel():

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

Прогнозирование с помощью обученной модели

Добавьте задачу GitHub для тестирования прогноза обученной модели в методе Predict, создав экземпляр 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.."
};

Используйте функцию Predict(), которая создает прогноз по одной строке данных.

var prediction = _predEngine.Predict(issue);

Использование модели: результаты прогнозирования

Отобразите GitHubIssue и соответствующий прогноз метки Area, чтобы поделиться результатами и обработать их должным образом. Создайте отображение для результатов с помощью следующего кода Console.WriteLine():

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

Возврат обученной модели для оценки

Выполните возврат модели в конце метода BuildAndTrainModel.

return trainingPipeline;

Оценка модели

Итак, вы завершили создание и обучение модели, и теперь ее можно оценить по другому набору данных, чтобы проверить ее точность и качество прогнозирования. В методе Evaluate передается для оценки модель, созданная в BuildAndTrainModel. Создайте метод Evaluate сразу после метода BuildAndTrainModel как показано в следующем коде:

void Evaluate(DataViewSchema trainingDataViewSchema)
{

}

Метод Evaluate выполняет следующие задачи:

  • загрузка тестового набора данных;
  • создание средства оценки многоклассовой классификации;
  • оценка модели и создание метрик;
  • отображение метрик.

Добавьте вызов нового метода сразу под вызовом метода BuildAndTrainModel, используя следующий код:

Evaluate(_trainingDataView.Schema);

Как и ранее с набором данных для обучения, загрузите тестовый набор данных, добавив следующий код в метод Evaluate:

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

Метод Evaluate() вычисляет метрики качества для модели на основе указанного набора данных. Он возвращает объект MulticlassClassificationMetrics, содержащий общие метрики, вычисляемые средствами оценки многоклассовой классификации. Чтобы отобразить метрики для оценки качества модели, сначала их необходимо получить. Используйте метод Transform() для глобальной переменной _trainedModel машинного обучения (ITransformer) для ввода признаков и возврата прогнозов. В качестве следующей строки в методе Evaluate добавьте приведенный ниже код:

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

Для многоклассовой классификации выполняется оценка следующих метрик:

  • Микроточность — на метрику точности в равной степени влияет каждая пара "пример-класс". Значение микроточности должно быть максимально близко к единице.

  • Макроточность — на метрику точности в равной степени влияет каждый класс. Миноритарным классам назначается тот же вес, что и более крупным. Значение макроточности должно быть максимально близко к единице.

  • Логарифмические потери — см. термин логарифмические потери. Значение логарифмических потерь должно быть максимально близко к нулю.

  • Минимизация логарифмических потерь — находится в диапазоне [-inf, 1,00], где 1,00 — идеальный прогноз, а 0 — среднее прогнозное значение. Значение минимизации логарифмических потерь должно быть максимально близко к единице.

Отображение метрик для проверки модели

Используйте следующий код для отображения метрик, передачи результатов и выполнения действий по ним:

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($"*************************************************************************************************************");

Сохранение модели в файл

После того как модель будет готова, сохраните ее в файл, чтобы делать прогнозы позднее или в другом приложении. Добавьте следующий код в метод Evaluate .

SaveModelAsFile(_mlContext, trainingDataViewSchema, _trainedModel);

Создайте метод SaveModelAsFile под методом Evaluate.

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

}

Добавьте приведенный ниже код в метод SaveModelAsFile. Этот код использует метод Save для сериализации и хранения обученной модели в виде ZIP-файла.

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

Развертывание и прогнозирование с помощью модели

Добавьте вызов нового метода сразу под вызовом метода Evaluate, используя следующий код:

PredictIssue();

Создайте метод PredictIssue сразу после метода Evaluate (и непосредственно перед методом SaveModelAsFile), вставив в него следующий код:

void PredictIssue()
{

}

Метод PredictIssue выполняет следующие задачи:

  • загрузка сохраненной модели;
  • создание одной задачи с тестовыми данными;
  • Прогнозирует область на основе тестовых данных.
  • объединение тестовых данных и прогнозов для создания отчетов;
  • отображение результатов прогнозирования.

Загрузите сохраненную модель в приложение, добавив в метод PredictIssue следующий код:

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

Добавьте задачу GitHub для тестирования прогноза обученной модели в методе Predict, создав экземпляр GitHubIssue:

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

Как и ранее, создайте экземпляр PredictionEngine следующим кодом:

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

Класс PredictionEngine представляет собой удобный API, позволяющий осуществить прогнозирование на основе единственного экземпляра данных. PredictionEngine не является потокобезопасным. Допустимо использовать в средах прототипов или средах с одним потоком. Для улучшенной производительности и потокобезопасности в рабочей среде используйте службу PredictionEnginePool, которая создает ObjectPool объектов PredictionEngine для использования во всем приложении. См. руководство по использованию PredictionEnginePool в веб-API ASP.NET Core.

Примечание

Расширение службы PredictionEnginePool сейчас доступно в предварительной версии.

Используйте PredictionEngine для прогнозирования метки области GitHub, добавив следующий код в метод прогноза PredictIssue:

var prediction = _predEngine.Predict(singleIssue);

Использование загруженной модели для прогнозирования

Отобразите Area, чтобы категоризировать задачу и обработать ее должным образом. Создайте отображение для результатов с помощью следующего кода Console.WriteLine():

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

Результаты

Результаты выполнения должны выглядеть примерно так, как показано ниже. В процессе работы конвейер выводит сообщения. Вы можете видеть предупреждения или обработанные сообщения. Для удобства эти сообщения удалены из следующих результатов.

=============== 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 ===============

Поздравляем! Вы успешно создали модель машинного обучения для классификации и прогнозирования метки области у задачи GitHub. Исходный код для этого руководства можно найти в репозитории dotnet/samples.

Следующие шаги

В этом руководстве вы узнали, как:

  • подготавливать данные;
  • Преобразование данных
  • Обучение модели
  • Оценка модели
  • Прогнозирование с помощью обученной модели
  • Развертывание и прогнозирование с помощью загруженной модели

Переходите к следующему руководству: