【问题标题】:How to Predict with a Spark MLlib model trained in LibSVM format如何使用以 LibSVM 格式训练的 Spark MLlib 模型进行预测
【发布时间】:2018-03-15 06:39:29
【问题描述】:

我使用 LibSVM 格式的训练数据文件训练我的模型,如此处所述http://spark.apache.org/docs/2.2.0/mllib-linear-methods.html。具体我用了这部分

val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt")

// Split data into training (60%) and test (40%).
val splits = data.randomSplit(Array(0.6, 0.4), seed = 11L)
val training = splits(0).cache()
val test = splits(1)

// Run training algorithm to build the model
val model = new LogisticRegressionWithLBFGS()
  .setNumClasses(10)
  .run(training)

但我的问题是,您如何为在预测时以这种方式训练的模型准备特征?我想出的解决方案是以 libsvm 格式保存一个中间文件(使用虚拟标签,因为我只想预测)并使用 MLUtils.loadLibSVMFile 加载它,然后将结果应用于训练模型以进行预测。然而,这种策略效率很低,而且在我的系统中,这需要非常昂贵的collect() 调用。有什么方法可以将我的数据放入正确的LabeledPoint 格式,而无需先将其放入 LibSVM 格式(需要中间文件)?我希望我不必深入了解MLUtils.loadLibSVMFile 的内部结构来弄清楚如何将libSVM 格式的行转换为LabeledPoint 对象。

PS:看起来 Spark 的 ML 管道是一种更好的方法,但我不想放弃我迄今为止所做的所有工作,并在可以帮助的情况下尝试该策略。

【问题讨论】:

  • 实际上,如果您有能力创建 LibSVM 文件,那么是什么阻止您自己创建向量并在预测中使用它们?您已经将您的功能放入 filr,所以它们应该已经准备好了...?
  • @Shaido - 是的,我知道如何将特征放入文件中 - 只是不知道如何从文件中读取它们并转换为最终传递给模型的向量。我可以深入研究MLUtils.loadLibSVMFile 来解决这个问题,但我希望我不必这样做(但我最终做到了)

标签: scala apache-spark machine-learning apache-spark-mllib


【解决方案1】:

当您完成模型训练并只想使用它进行预测时,您不需要拥有LabeledPoint 格式的数据。您唯一需要的是一个向量(密集或稀疏,请参阅here 了解更多信息)来进行预测。

val prediction = model.predict(features)

当然,也可以转换为LabeledPoint,尽管不是必须的。一个小例子:

val rdd = sc.parallelize(Array(
    (1, List(1.0,4.0,8.0)),
    (2, List(3.0,3.0,8.0)),
    (3, List(5.0,5.0,9.0))))

val rdd2 = rdd.map{ case(k, vs) => 
  LabeledPoint(k.toDouble, Vectors.dense(vs.toArray))
}

可以在 LibSVM 格式和 Spark 向量之间进行转换。在您的 LibSVM 文件中,每一行的格式如下:

<label> <index1>:<value1> <index2>:<value2> ... <indexN>:<valueN>

索引其中是特征向量中的索引(训练和预测的顺序相同)。 MLUtils.loadLibSVMFile() 将在此之后创建 LabeledPoint,即每个LabeledPoint 将如下所示:

LabeledPoint(label, Vectors.sparse(N, Array(index1-1, index2-1, ...), Array(value1, value2, ...)))

示例中使用了SparseVector,因为 LibSVM 文件同时指定了索引和值。

在 LibSVM 中,索引从 1 开始,而更常见的约定(包括创建SparseVector)是从 0 开始,因此,在从 LibSVM 格式转换时,需要从索引中减去 1。

按照此操作,您可以轻松地自己创建向量来进行预测。

【讨论】:

  • 是的,但我的问题更多是关于如何创建这个向量。特征向量元素的顺序很重要。如果预测时的顺序与训练时的顺序不同,那么预测就会偏离。那么如何知道预测时特征向量的元素顺序与训练时 MLUtils.loadLibSVMFile 从 libsvm 文件中生成的顺序相同呢?
  • @user1893354 在应该回答您问题的答案中添加了其他信息。
  • 是的,这回答了我的问题——但我希望 Spark 有更多的内置解决方案。顺便说一句,我深入研究了代码,代码和 libsvm 索引从 1 开始,但是在读取时,spark 会从每个中减去 1,因此最终向量中的索引实际上应该是 libsvm 索引 - 1(您可能希望将其添加到您的答案)
猜你喜欢
  • 2016-05-29
  • 2017-02-06
  • 2017-12-11
  • 2020-09-07
  • 2017-05-17
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
相关资源
最近更新 更多