【发布时间】:2019-08-11 12:14:16
【问题描述】:
我正在一个无监督的集群场景中试验 ML.NET。我的起始数据少于 30 条记录,TSV 文件中有 5 个特征,例如(当然标签会被忽略):
Label S1 S2 S3 S4 S5
alpha 0.274167987321712 0.483359746434231 0.0855784469096672 0.297939778129952 0.0332805071315372
beta 0.378208470054279 0.405409549510871 0.162317151706584 0.292342604802355 0.0551994848048085
...
我的起点是iris tutorial,这是 K-means 聚类的一个样本。就我而言,我想要 3 个集群。正如我刚刚学习的那样,一旦创建了模型,我想用它来将聚类数据添加到原始文件副本中的每条记录中,这样我就可以检查它们并绘制散点图。
我从这个训练代码开始(比如MyModel 是代表其模型的 POCO 类,具有S1-S5 的属性):
// load data
MLContext mlContext = new MLContext(seed: 0);
IDataView dataView = mlContext.Data.LoadFromTextFile<MyModel>
(dataPath, hasHeader: true, separatorChar: '\t');
// train model
const string featuresColumnName = "Features";
EstimatorChain<ClusteringPredictionTransformer<KMeansModelParameters>>
pipeline = mlContext.Transforms
.Concatenate(featuresColumnName, "S1", "S2", "S3", "S4", "S5")
.Append(mlContext.Clustering.Trainers.KMeans(featuresColumnName,
numberOfClusters: 3));
TransformerChain<ClusteringPredictionTransformer<KMeansModelParameters>>
model = pipeline.Fit(dataView);
// save model
using (FileStream fileStream = new FileStream(modelPath,
FileMode.Create, FileAccess.Write, FileShare.Write))
{
mlContext.Model.Save(model, dataView.Schema, fileStream);
}
然后,我加载保存的模型,从原始数据中读取每条记录,并获取其集群 ID。这听起来有点令人费解,但我在这里的学习意图是检查结果,然后再玩它们。结果应与质心坐标和点坐标一起保存在一个新文件中。
然而,这个 API 似乎不够透明,无法轻松访问质心;我只找到了一个post,它相当旧,并且它的代码不再编译。我宁愿用它作为通过反射恢复数据的提示,但这是一个 hack。
另外,我不确定框架提供的数据的细节。我可以看到每个质心都有 3 个向量(在示例代码中名为 cx cy cz),每个向量都有 5 个元素(我假设这 5 个特征按照它们的串联输入顺序,即从 S1 到 S5) ;此外,每个预测提供 3 倍距离(dxdydz)。如果这些假设没问题,我可以像这样为每条记录分配一个集群 ID:
// for each record in the original data
foreach (MyModel record in csvReader.GetRecords<MyModel>())
{
// get its cluster ID
MyPrediction prediction = predictor.Predict(record);
// get the centroids just once, as of course they are the same
// for all the records referring their distances to them
if (cx == null)
{
// get centroids (via reflection...):
// https://github.com/dotnet/machinelearning/blob/master/docs/samples/Microsoft.ML.Samples/Dynamic/Trainers/Clustering/KMeansWithOptions.cs#L49
// https://social.msdn.microsoft.com/Forums/azure/en-US/c09171c0-d9c8-4426-83a9-36ed72a32fe7/kmeans-output-centroids-and-cluster-size?forum=MachineLearning
VBuffer<float>[] centroids = default;
var last = ((TransformerChain<ITransformer>)model)
.LastTransformer;
KMeansModelParameters kparams = (KMeansModelParameters)
last.GetType().GetProperty("Model").GetValue(last);
kparams.GetClusterCentroids(ref centroids, out int k);
cx = centroids[0].GetValues().ToArray();
cy = centroids[1].GetValues().ToArray();
cz = centroids[2].GetValues().ToArray();
}
float dx = prediction.Distances[0];
float dy = prediction.Distances[1];
float dz = prediction.Distances[2];
// ... calculate and save full details for the record ...
}
鉴于这种情况,我想我可以通过以下方式获取有关预训练模型中每个记录位置的所有详细信息:
-
dx、dy、dz是距离。 -
cx[0]cy[0]cy[0]+距离(分别为dx、dy和dz)应该是S1点的位置;cx[1]cy[1]cz[1]+距离S2的位置;以此类推,直到 S5(cx[4]等)。
在这种情况下,我可以在 3D 散点图中绘制这些数据。然而,我对 ML.NET 完全陌生,因此我不确定这些假设,而且很可能我走错了路。谁能指出我正确的方向?
【问题讨论】:
标签: c# machine-learning ml.net