深圳幻海软件技术有限公司 欢迎您!

ML.NET Cookbook:(17)如何在分类数据上训练模型?

2023-03-28

一般来说,所有的ML.NET学习器都希望这些特征是一个浮点向量。因此,如果您的一些数据不是一个float,您需要将其转换为float。如果我们的数据包含“分类”特征(比如“enum”),我们需要以某种方式对它们进行“特征化”。ML.NET提供了几种将分类数据转换为功能的方法:独热编码基于哈希的独热编

一般来说,所有的ML.NET学习器都希望这些特征是一个浮点向量。因此,如果您的一些数据不是一个float,您需要将其转换为float。

如果我们的数据包含“分类”特征(比如“enum”),我们需要以某种方式对它们进行“特征化”。ML.NET提供了几种将分类数据转换为功能的方法:

  • 独热编码

  • 基于哈希的独热编码

  • 二进制编码(将类别索引转换为位序列并使用位作为特征)

如果某些类别的基数非常高(有很多不同的值,但通常只有几个),那么独热编码可能是浪费的。我们可以使用基于计数的特征选择来减少我们编码的槽的数量。

与规范化一样,将分类特征化直接包含在ML.NET学习管道中是一种很好的做法:这样您就可以确保分类转换

  • 只是在训练数据上“训练”,而不是在你的测试数据上,

  • 正确应用于所有新传入的数据,而无需在预测时进行额外的预处理。

下面是成人普查数据集[1]的分类处理示例:

  1. Label Workclass education marital-status occupation relationship ethnicity sex native-country-region age fnlwgt education-num capital-gain capital-loss hours-per-week
  2. 0 Private 11th Never-married Machine-op-inspct Own-child Black Male United-States 25 226802 7 0 0 40
  3. 0 Private HS-grad Married-civ-spouse Farming-fishing Husband White Male United-States 38 89814 9 0 0 50
  4. 1 Local-gov Assoc-acdm Married-civ-spouse Protective-serv Husband White Male United-States 28 336951 12 0 0 40
  5. 1 Private Some-college Married-civ-spouse Machine-op-inspct Husband Black Male United-States 44 160323 10 7688 0 40
  1. // 创建加载器:定义数据列以及它们在文本文件中的位置。
  2. var loader = mlContext.Data.CreateTextLoader(new[] 
  3.     {
  4.         new TextLoader.Column("Label", DataKind.Boolean, 0),
  5.         // 我们将把所有分类特征加载到一个大小为8的向量列中。
  6.         new TextLoader.Column("CategoricalFeatures", DataKind.String, 18),
  7.         // 类似地,将所有数字特征加载到一个大小为6的向量中。
  8.         new TextLoader.Column("NumericalFeatures", DataKind.Single, 914),
  9.         // 让我们单独加载“Workclass”列。
  10.         new TextLoader.Column("Workclass", DataKind.String, 1)
  11.     },
  12.     hasHeader: true
  13. );
  14. // 加载数据。
  15. var data = loader.Load(dataPath);
  16. // 检查分类列的前10条记录以检查它们是否被正确读取。
  17. var catColumns = data.GetColumn<string[]>(data.Schema["CategoricalFeatures"]).Take(10).ToArray();
  18. // 建造多条可选的特征化管道。
  19. var pipeline =
  20.     // 将每个分类特征转换为独热编码。
  21.     mlContext.Transforms.Categorical.OneHotEncoding("CategoricalOneHot""CategoricalFeatures")
  22.     // 将所有分类特征转换为索引,并构建一个“词袋”。
  23.     .Append(mlContext.Transforms.Categorical.OneHotEncoding("CategoricalBag""CategoricalFeatures", OneHotEncodingEstimator.OutputKind.Bag))
  24.     // 对workclass列进行独热编码,然后删除列集中少于10个实例的所有类别。
  25.     .Append(mlContext.Transforms.Categorical.OneHotEncoding("WorkclassOneHot""Workclass"))
  26.     .Append(mlContext.Transforms.FeatureSelection.SelectFeaturesBasedOnCount("WorkclassOneHotTrimmed""WorkclassOneHot", count: 10));
  27. // 让我们训练管道,然后将其应用于同一个数据上。
  28. var transformedData = pipeline.Fit(data).Transform(data);
  29. // 检查结果数据集的某些列。
  30. var categoricalBags = transformedData.GetColumn<float[]>(transformedData.Schema["CategoricalBag"]).Take(10).ToArray();
  31. var workclasses = transformedData.GetColumn<float[]>(transformedData.Schema["WorkclassOneHotTrimmed"]).Take(10).ToArray();
  32. // 当然,如果我们想训练模型,我们需要合成一个包含所有特征的浮点向量。
  33. // 我们可以这样做:
  34. var fullLearningPipeline = pipeline
  35.     // 连接3个分类管道中的2个,以及数字特征。
  36.     .Append(mlContext.Transforms.Concatenate("Features""NumericalFeatures""CategoricalBag""WorkclassOneHotTrimmed"))
  37.     // 将数据缓存在内存中,以便下面的训练器能够访问训练样本,而无需从磁盘多次加载它们。
  38.     .AppendCacheCheckpoint(mlContext)
  39.     // 现在我们要训练了。我们选择了我们的FastTree训练器来完成这个分类任务。
  40.     .Append(mlContext.BinaryClassification.Trainers.FastTree(numTrees: 50));
  41. // 训练模型。
  42. var model = fullLearningPipeline.Fit(data);


参考资料

[1]

成人普查数据集: https://github.com/dotnet/machinelearning/blob/main/test/data/adult.tiny.with-schema.txt

文章知识点与官方知识档案匹配,可进一步学习相关知识
OpenCV技能树OpenCV中的深度学习图像分类14917 人正在系统学习中