此示例教程展示如何使用 ML.NET 创建 GitHub 问题分类器来训练模型,该模型通过 Visual Studio 中的 C# 和 .NET 控制台应用程序用于分类和预测 GitHub 问题的 Area 标签。
本教程中,您将学习如何:
- 准备数据
- 转换数据
- 训练模型
- 评估模型
- 使用训练的模型进行预测
- 使用加载的模型部署和预测
可以在 dotnet/samples 存储库中找到本教程的源代码。
先决条件
- 安装了“.NET 桌面开发”工作负载的 Visual Studio 2022 或更高版本。
- GitHub 颁发训练选项卡分隔文件(issues_train.tsv)。
- GitHub 问题测试制表符分隔文件(issues_test.tsv)。
创建控制台应用程序
创建项目
创建名为“GitHubIssueClassification”的 C# 控制台应用程序 。 选择“下一步”。
选择 .NET 7 作为要使用的框架。 选择 创建。
在项目中创建名为 Data 的目录以保存数据集文件:
在 解决方案资源管理器中,右键单击项目并选择“ 添加新>文件夹”。 键入“Data”,然后按 Enter。
在项目中创建名为 Models 的目录以保存模型:
在 解决方案资源管理器中,右键单击项目并选择“ 添加新>文件夹”。 键入“模型”,然后按 Enter。
安装 Microsoft.ML NuGet 包:
注释
此示例使用提到的 NuGet 包的最新稳定版本,除非另有说明。
在解决方案资源管理器中,右键单击项目并选择“ 管理 NuGet 包”。 选择“nuget.org”作为包源,选择“浏览”选项卡,搜索 Microsoft.ML ,然后选择“ 安装”。 选择“预览更改”对话框中的“确定”按钮,然后选择“许可接受”对话框中的“我接受”按钮(如果同意列出的程序包的许可条款)。
准备数据
下载 issues_train.tsv 和 issues_test.tsv 数据集,并将其保存到之前创建的 Data 文件夹中。 第一个数据集训练机器学习模型,第二个数据集可用于评估模型的准确性。
在解决方案资源管理器中,右键单击每个 *.tsv 文件并选择 “属性”。 在 高级 下,将 复制到输出目录 的值更改为 若较新则复制。
创建类并定义路径
将以下附加 using 指令添加到 Program.cs 文件的顶部:
using Microsoft.ML;
using GitHubIssueClassification;
创建三个全局字段,用于保存最近下载的文件的路径以及 <
-
_trainDataPath具有用于训练模型的数据集的路径。 -
_testDataPath具有用于评估模型的数据集的路径。 -
_modelPath具有保存已训练模型的路径。 -
_mlContext是提供处理上下文的MLContext。 -
_trainingDataViewIDataView用于处理训练数据集。 -
_predEnginePredictionEngine<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;
为输入数据和预测创建一些类。 向项目添加新类:
在 解决方案资源管理器中,右键单击该项目,然后选择“ 添加新>项”。
在“ 添加新项 ”对话框中,选择“ 类 ”并将“ 名称 ”字段更改为 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 问题 ID)。 - 第二列
Area(用于训练的预测值)。 - 第三列(GitHub 问题标题)是用于预测第
Title一列。featureArea - 第四列是用于预测第二
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 标签,使用 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"))
数据准备的最后一步使用 Concatenate() 方法将所有特征列合并到功能列。 默认情况下,学习算法仅处理 “功能 ”列中的功能。 使用以下代码将此转换追加到管道:
.Append(_mlContext.Transforms.Concatenate("Features", "TitleFeaturized", "DescriptionFeaturized"))
接下来,追加一个用于缓存 DataView 的缓存 AppendCacheCheckpoint ,因此,使用缓存多次循环访问数据时,性能可能会更好,如以下代码所示:
.AppendCacheCheckpoint(_mlContext);
警告
将 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);
使用训练的模型进行预测
通过创建以下实例Predict,添加 GitHub 问题以测试方法中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 对象,该对象包含多类分类计算器计算的总体指标。
若要显示指标以确定模型的质量,需要先获取它们。
请注意,使用机器学习全局变量(_trainedModel)的 Transform()方法输入特征并返回预测。 将以下代码作为下一行添加到 Evaluate 方法:
var testMetrics = _mlContext.MulticlassClassification.Evaluate(_trainedModel.Transform(testDataView));
以下指标针对多类分类进行评估:
- Micro Accuracy - 每个样本类对都同样有助于准确性指标。 希望 Micro Accuracy 尽可能接近一个。
- 宏准确性 - 每个类都同样有助于准确性指标。 少数类的权重与较大的类相同。 希望宏准确性尽可能接近一个。
- 日志丢失 - 请参阅 日志丢失。 希望日志丢失尽可能接近零。
- 对数损失减少 - 范围为 [-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);
通过创建以下实例Predict,添加 GitHub 问题以测试方法中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该服务,该服务会创建一个ObjectPoolPredictionEngine对象用于整个应用程序。 请参阅本指南,了解如何在 ASP.NET Core Web API 中使用PredictionEnginePool。
注释
PredictionEnginePool 服务扩展目前为预览版。
PredictionEngine通过向预测方法添加以下代码PredictIssue来预测区域 GitHub 标签:
var prediction = _predEngine.Predict(singleIssue);
使用加载的模型进行预测
显示 Area 以便对问题进行分类并相应地采取行动。 使用以下 Console.WriteLine() 代码为结果生成显示:
Console.WriteLine($"=============== Single Prediction - Result: {prediction.Area} ===============");
Results
结果应如下所示。 当管道处理时,它会显示消息。 你可能会看到警告或处理消息。 为了清楚起见,这些消息已从以下结果中删除。
=============== 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 存储库中找到本教程的源代码。
后续步骤
在本教程中,你将学习到如何:
- 准备数据
- 转换数据
- 训练模型
- 评估模型
- 使用训练的模型进行预测
- 使用加载的模型部署和预测
请继续学习下一篇教程,了解详细信息。