在 ML.NET 中执行 ITransformer.Transform 后从 IDataView 中提取 MultiClass 结果

Extract MultiClass results from IDataView after performing ITransformer.Transform in ML.NET

我正在尝试一般地使用 ML.NET,而不必创建 class 作为模型的输入和输出。 为此,在使用此创建模型后:

        public static (ITransformer model, double accuracy) TrainMultiClassModel(MulticlassExperimentSettings experimentSettings, MLContext mlContext, IDataView myview, string LabelName)
    {
        ITransformer trainedModel;
        MulticlassClassificationExperiment experiment = mlContext.Auto().CreateMulticlassClassificationExperiment(experimentSettings);

        ExperimentResult<MulticlassClassificationMetrics> experimentResult = experiment.Execute(myview, LabelName);
        RunDetail<MulticlassClassificationMetrics> best = experimentResult.BestRun;

        trainedModel = best.Model;

        return (trainedModel, best.ValidationMetrics.MacroAccuracy);
    }

其中 myView 包含正确设置 DataKinds 的 CSV 文件。

数据示例:

然后我通过 运行 执行该模型,如下所示:

            MemoryStream modelStream = new MemoryStream(ModelData);
            ITransformer trainedModel = mlContext.Model.Load(modelStream, out var modelInputSchema);
            var predictions = trainedModel.Transform(myview);

同样,myView 包含来自 CSV 文件的数据,只是预测列为空。

现在我们有了 "predictions",它是 IDataView 类型。

对于回归结果,这很简单。查找名为 "Score" 的架构并将其加载为 float:

float[] scoreColumn = predictions.GetColumn<float>("Score").ToArray();

但是它如何用于 MultiClass 实验?有一个名为 "PredictedLabel" 的模式,类型为 "String",但它包含 0 到 1 之间的数字,如下所示:

var labelColumn = predictions.Schema.FirstOrDefault(s => s.Name == "PredictedLabel" && s.IsHidden == false);
string[] scoreColumn = predictions.GetColumn<string>(labelColumn).ToArray();

我如何获得(在本例中)物种的实际名称?或者我是否必须以某种方式将数字映射到名称?我要使用哪种映射 table?

提前致谢。

编辑:Eric 的代码给出了这个列表:

1.4
1.9
0.2
0.4
 0.3
0.1
0.5
0.6
1.5
1.3
1.6
1.0
1.1
1.8
1.2
1.7
2.5
2.1
2.2
2.0
2.4
2.3

那些是 22,这很奇怪:正确物种的 none 确实有 22 个字符(以防那是名字中的字符),而我只输入了 4 行数据来解决。 "PredictedLabel" 同时输出 4 个值,但仍然是数字:

但现在我想知道:我该如何阅读这个字段?也许它包含答案:

您要使用的是一种名为GetKeyValues的方法。这将为您提供一个 VBuffer<ReadOnlyMemory<char>>,其中缓冲区中的每个字符串都是 "value" 对应索引到 "keys" 或 "classes" 中的 multi-class class化模型。

var predictions = trainedModel.Transform(myview);

var labelColumn = predictions.Schema[labelName]; // this is "Species" in your example above

VBuffer<ReadOnlyMemory<char>> keys = default;
labelColumn.GetKeyValues(ref keys);

foreach (var key in keys.DenseValues())
{
    Console.WriteLine(key);
}

为了完整起见,并解决最初问题中的困惑,这里是答案。

首先,为什么 "PredictedLabel" 和 "GetKeyValues"(来自 Erics 的回答)没有提供可用的结果?这里的问题是我使用 IDataView 的方式。在训练数据时,我加载了整个 CSV,包括 "ID" 列,这是我在执行模型时没有提供的(因为该列对于使用模型没有价值)。在切换到始终省略 "ID" 列并在训练和执行中使用相同的 CSV 布局后,Eric 和我的方法都开始起作用了。

因此,当您想将结果解释为正确的格式时,首先要查看生成的 DataView 架构中是否存在 "PredictedLabel"。

if (predictions.Schema.Any(s => s.Name == "PredictedLabel"))

如果是,请检查其数据类型。这就是您如何区分 MultiClass 和 Binary 结果:

    var labelColumn = predictions.Schema.FirstOrDefault(s => s.Name == "PredictedLabel" && s.IsHidden == false);            
    if (labelColumn.Type.ToString() == "Boolean")
{
    bool[] binaryResults = predictions.GetColumn<bool>(labelColumn).ToArray();
}

(或)

    if (labelColumn.Type.ToString() == "String")
{
    string[] multiclassResults = predictions.GetColumn<string>(labelColumn).ToArray();
}

multiclassResults 现在将以字符串形式包含您写下的 MultiClass 结果。

如果没有 PredictedLabel,应该有一个 "Score" 架构,其中包含您的回归结果:

float[] regressionResults = predictions.GetColumn<float>("Score").ToArray();