Учебник. Категоризация цветов ириса с использованием кластеризации k-средних в ML.NET

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

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

  • Определение проблемы
  • Выбор подходящей задачи машинного обучения
  • Подготовка данных
  • Загрузка и преобразование данных
  • Выбор алгоритма обучения
  • Обучение модели
  • Использование модели для прогнозирования

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

Определение проблемы

Задача — разделить ирисы на группы в зависимости от признаков цветка. Эти признаки — длина и ширина чашелистика и длина и ширина лепестка. В этом руководстве предполагается, что тип каждого цветка неизвестен. Вы научитесь структурировать набор данных по признакам и предсказывать, как экземпляр данных будет вписываться в эту структуру.

Выбор подходящей задачи машинного обучения

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

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

  1. Создайте консольное приложение C# с именем IrisFlowerClustering. Нажмите кнопку Далее.

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

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

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

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

    Примечание

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

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

Подготовка данных

  1. Скачайте набор данных iris.data и сохраните его в папке Data, созданной на предыдущем шаге. Дополнительные сведения о наборе данных ирисов см. на странице Википедии Ирисы Фишера и на странице Набор данных ирисов, который является источником набора данных.

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

Файл Iris.data содержит пять столбцов со следующими данными:

  • длина чашелистика в сантиметрах;
  • ширина чашелистика в сантиметрах;
  • длина лепестка в сантиметрах;
  • ширина лепестка в сантиметрах;
  • тип ириса.

В этом примере кластеризации мы не будем учитывать последний столбец.

Создание классов данных

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

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

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

  3. Добавьте следующую директиву using в новый файл:

    using Microsoft.ML.Data;
    

Удалите из файла IrisData.cs существующее определение класса и добавьте следующий код, который определяет классы IrisData и ClusterPrediction:

public class IrisData
{
    [LoadColumn(0)]
    public float SepalLength;

    [LoadColumn(1)]
    public float SepalWidth;

    [LoadColumn(2)]
    public float PetalLength;

    [LoadColumn(3)]
    public float PetalWidth;
}

public class ClusterPrediction
{
    [ColumnName("PredictedLabel")]
    public uint PredictedClusterId;

    [ColumnName("Score")]
    public float[]? Distances;
}

Класс IrisData содержит входные данные и определения для каждого признака в наборе данных. Используйте атрибут LoadColumn, чтобы указать индексы исходных столбцов в файле набора данных.

Класс ClusterPrediction представляет выходные данные модели кластеризации, примененные к экземпляру IrisData. Используйте атрибут ColumnName, чтобы привязать поля PredictedClusterId и Distances к столбцам PredictedLabel и Score соответственно. В случае задачи кластеризации эти столбцы означают следующее:

  • Столбец PredictedLabel содержит идентификатор прогнозируемого кластера.
  • Столбец Score содержит массив с квадратом Евклидовых расстояний до центроидов кластера. Длина массива равна числу кластеров.

Примечание

Используйте тип float для представления значений с плавающей запятой в классах данных ввода и прогнозирования.

Определение путей к данным и модели

Вернитесь к файлу Program.cs и добавьте два поля, которые будут содержать пути к файлу с наборами данных и к файлу для сохранения модели.

  • _dataPath содержит путь к файлу с набором данных, используемым для обучения модели.
  • _modelPath содержит путь к файлу для сохранения обучаемой модели.

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

string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "iris.data");
string _modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "IrisClusteringModel.zip");

Создание контекста машинного обучения ML

Добавьте дополнительные директивы using в начало файла Program.cs.

using Microsoft.ML;
using IrisFlowerClustering;

Замените строку Console.WriteLine("Hello World!"); следующим кодом:

var mlContext = new MLContext(seed: 0);

Класс Microsoft.ML.MLContext представляет среду машинного обучения и предоставляет механизмы для ведения журнала и точек входа для загрузки данных, обучения модели, прогнозирования и других задач. Концептуально это сопоставимо с использованием DbContext в Entity Framework.

Настройка загрузки данных

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

IDataView dataView = mlContext.Data.LoadFromTextFile<IrisData>(_dataPath, hasHeader: false, separatorChar: ',');

Универсальный метод расширения MLContext.Data.LoadFromTextFile выводит схему набора данных на основе предоставленного типа IrisData и возвращает интерфейс IDataView, который можно использовать в качестве входных данных для преобразования.

Создание конвейера обучения

В этом руководстве настройка конвейера обучения задач кластеризации состоит из следующих двух шагов:

  • объедините загруженные столбцы в один столбец Функции, который используется тренером кластеризации;
  • используйте тренер KMeansTrainer для обучения модели с помощью алгоритма кластеризации k-means++.

После загрузки данных добавьте следующий код:

string featuresColumnName = "Features";
var pipeline = mlContext.Transforms
    .Concatenate(featuresColumnName, "SepalLength", "SepalWidth", "PetalLength", "PetalWidth")
    .Append(mlContext.Clustering.Trainers.KMeans(featuresColumnName, numberOfClusters: 3));

В этом коде указано, что набор данных нужно разделить на три кластера.

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

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

var model = pipeline.Fit(dataView);

Сохранение модели

На этом этапе у вас есть модель, которую можно интегрировать с любыми существующими или новыми приложениями .NET. Чтобы сохранить модель в ZIP-файл, добавьте следующий код под вызовом метода Fit:

using (var fileStream = new FileStream(_modelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
{
    mlContext.Model.Save(model, dataView.Schema, fileStream);
}

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

Чтобы получить прогноз, используйте класс PredictionEngine<TSrc,TDst>, который принимает экземпляры входного типа через конвейер преобразователя и создает экземпляры выходного типа. Добавьте следующую строку, чтобы создать экземпляр этого класса:

var predictor = mlContext.Model.CreatePredictionEngine<IrisData, ClusterPrediction>(model);

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

Примечание

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

Создание класса TestIrisData для размещения тестовых экземпляров данных:

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

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

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

    static class TestIrisData
    

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

internal static readonly IrisData Setosa = new IrisData
{
    SepalLength = 5.1f,
    SepalWidth = 3.5f,
    PetalLength = 1.4f,
    PetalWidth = 0.2f
};

Чтобы узнать, к какому кластеру принадлежит указанный элемент, вернитесь к файлу Program.cs и добавьте следующий код в конец файла:

var prediction = predictor.Predict(TestIrisData.Setosa);
Console.WriteLine($"Cluster: {prediction.PredictedClusterId}");
Console.WriteLine($"Distances: {string.Join(" ", prediction.Distances ?? Array.Empty<float>())}");

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

Cluster: 2
Distances: 11.69127 0.02159119 25.59896

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

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

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

  • Определение проблемы
  • Выбор подходящей задачи машинного обучения
  • Подготовка данных
  • Загрузка и преобразование данных
  • Выбор алгоритма обучения
  • Обучение модели
  • Использование модели для прогнозирования

Извлеките наш репозиторий GitHub, чтобы продолжить обучение и получить дополнительные примеры.