教程:配合使用 K 平均值聚类分析和 ML.NET 来对鸢尾花分类

本教程演示如何使用 ML.NET 为 虹膜花数据集生成 聚类分析模型

在本教程中,你将学习如何:

  • 了解问题
  • 选择适当的机器学习任务
  • 准备数据
  • 加载和转换数据
  • 选择学习算法
  • 训练模型
  • 使用模型进行预测

先决条件

了解问题

此问题是关于根据花的特征将虹膜花集划分为不同的组。 这些特征是萼片的长度和宽度以及花瓣的长度和宽度。 对于本教程,假定每个花的类型未知。 你想要从特征中了解数据集的结构,并预测数据实例如何适应此结构。

选择适当的机器学习任务

鉴于不知道每朵花属于哪个分组,应选择非监管式机器学习任务。 若要以相同组中的元素与其他组中的元素更相似的方式划分数据集,请使用 聚类分析 机器学习任务。

创建控制台应用程序

  1. 创建名为“IrisFlowerClustering”的 C# 控制台应用程序。 单击 “下一步” 按钮。

  2. 选择 .NET 8 作为要使用的框架。 单击“创建”按钮。

  3. 在项目中创建名为 数据 的目录来存储数据集和模型文件:

    解决方案资源管理器中,右键单击项目并选择“添加>新文件夹。 键入“Data”并选择 Enter

  4. 安装 Microsoft.ML NuGet 包:

    注意

    此示例使用提到的 NuGet 包的最新稳定版本,除非另有说明。

    解决方案资源管理器中,右键单击项目并选择 管理 NuGet 包。 选择“nuget.org”作为包源,选择 浏览 选项卡,搜索 Microsoft.ML,然后选择 安装。 在“预览更改”对话框中,选择“确定”按钮,然后选择“许可证接受”对话框中的“我接受”按钮,如果您同意列出软件包的许可条款。

准备数据

  1. 下载 iris.data 数据集,并将其保存到在上一步中创建的 数据 文件夹中。 有关鸢尾花数据集的详细信息,请参阅维基百科页面 鸢尾花数据集鸢尾花数据集页面,数据集的信息来源。

  2. 解决方案资源管理器中,右键单击 iris.data 文件,然后选择 属性。 在“高级”下,将“复制到输出目录”的值更改为“如果较新则复制”

iris.data 文件包含五列,这些列表示:

  • 花萼长度(厘米)
  • 萼片宽度(厘米)
  • 花瓣长度(厘米)
  • 花瓣宽度(厘米)
  • 虹膜花的类型

出于聚类分析示例的目的,本教程将忽略最后一列。

创建数据类

为输入数据和预测创建类:

  1. 解决方案资源管理器中,右键单击项目,然后选择“添加>新项

  2. 在“添加新项 对话框中,选择 并将 名称 字段更改为 IrisData.cs。 然后选择“添加”。

  3. 将以下 using 指令添加到新文件:

    using Microsoft.ML.Data;
    

删除现有类定义,并将以下代码(用于定义类 IrisDataClusterPrediction)添加到 IrisData.cs 文件中:

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 属性将 PredictedClusterIdDistances 字段分别绑定到 PredictedLabelScore 列。 对于聚类分析任务,这些列具有以下含义:

  • PredictedLabel 列包含所预测的群集的 ID。
  • 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 相当。

设置数据加载

MLContext 下面添加以下代码,以设置加载数据的方式:

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

泛型 MLContext.Data.LoadFromTextFile 扩展方法 从提供的 IrisData 类型推断数据集架构,并返回可用作转换器输入的 IDataView

创建学习管道

在本教程中,群集任务的学习管道包括两个步骤:

  • 将加载的列连接到“Features”列,由聚类分析训练程序使用
  • 使用 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 服务,该服务可创建 PredictionEngine 对象的 ObjectPool,以便在应用程序中使用。 请参阅本指南,了解如何在 ASP.NET Core Web API中 使用

注意

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

祝贺! 现已成功地生成用于鸢尾花聚类分析的机器学习模型并将其用于预测。 可以在 dotnet/samples GitHub 存储库中找到本教程的源代码。

后续步骤

在本教程中,你将学习如何:

  • 了解问题
  • 选择适当的机器学习任务
  • 准备数据
  • 加载和转换数据
  • 选择学习算法
  • 训练模型
  • 使用模型进行预测

查看 dotnet/machinelearning GitHub 存储库,继续学习并查找更多示例。