【问题标题】:Why does Spark ML NaiveBayes output labels that are different from the training data?为什么 Spark ML NaiveBayes 输出的标签与训练数据不同?
【发布时间】:2016-02-15 23:12:01
【问题描述】:

我使用Apache Spark ML(版本1.5.1)中的NaiveBayes分类器来预测一些文本类别。但是,分类器输出的标签与我的训练集中的标签不同。我做错了吗?

这是一个小例子,可以粘贴到例如Zeppelin 笔记本:

import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.classification.NaiveBayes
import org.apache.spark.ml.feature.{HashingTF, Tokenizer}
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.sql.Row

// Prepare training documents from a list of (id, text, label) tuples.
val training = sqlContext.createDataFrame(Seq(
  (0L, "X totally sucks :-(", 100.0),
  (1L, "Today was kind of meh", 200.0),
  (2L, "I'm so happy :-)", 300.0)
)).toDF("id", "text", "label")

// Configure an ML pipeline, which consists of three stages: tokenizer, hashingTF, and lr.
val tokenizer = new Tokenizer()
  .setInputCol("text")
  .setOutputCol("words")
val hashingTF = new HashingTF()
  .setNumFeatures(1000)
  .setInputCol(tokenizer.getOutputCol)
  .setOutputCol("features")
val nb = new NaiveBayes()

val pipeline = new Pipeline()
  .setStages(Array(tokenizer, hashingTF, nb))

// Fit the pipeline to training documents.
val model = pipeline.fit(training)

// Prepare test documents, which are unlabeled (id, text) tuples.
val test = sqlContext.createDataFrame(Seq(
  (4L, "roller coasters are fun :-)"),
  (5L, "i burned my bacon :-("),
  (6L, "the movie is kind of meh")
)).toDF("id", "text")

// Make predictions on test documents.
model.transform(test)
  .select("id", "text", "prediction")
  .collect()
  .foreach { case Row(id: Long, text: String, prediction: Double) =>
    println(s"($id, $text) --> prediction=$prediction")
  }

小程序的输出:

(4, roller coasters are fun :-)) --> prediction=2.0
(5, i burned my bacon :-() --> prediction=0.0
(6, the movie is kind of meh) --> prediction=1.0

预测标签集 {0.0, 1.0, 2.0} 与我的训练集标签 {100.0, 200.0, 300.0} 不相交。

问题:如何将这些预测标签映射回我的原始训练集标签?

额外问题:为什么训练集标签必须是双精度的,而任何其他类型都可以像标签一样工作?似乎没有必要。

【问题讨论】:

    标签: scala apache-spark machine-learning naivebayes apache-spark-ml


    【解决方案1】:

    但是,分类器输出的标签与我的训练集中的标签不同。我做错了吗?

    有点。据我所知,您遇到了SPARK-9137 描述的问题。一般来说,ML 中的所有分类器都期望基于 0 的标签(0.0、1.0、2.0、...),但 ml.NaiveBayes 中没有验证步骤。在后台数据被传递给mllib.NaiveBayes,它没有这个限制,所以训练过程很顺利。

    当模型转换回ml 时,预测函数只假设标签正确,returns predicted label using Vector.argmax,因此得到的结果。您可以使用例如StringIndexer 来修复标签。

    为什么训练集标签必须是双精度的,而任何其他类型都可以像标签一样工作?

    我想这主要是保持简单和可重用的 API 的问题。这样LabeledPoint 可以用于分类和回归问题。此外,它在内存使用和计算成本方面是一种有效的表示。

    【讨论】:

    • 我明白你的解释,谢谢。然而,从可用性的角度来看,这种行为似乎是一个错误,因为不应该期望用户知道 API 的内部结构。但是,正如您所指出的,这已在 issue 9137 中进行了描述。谢谢。
    • 我什至会争辩说,强迫用户选择 0-n 范围内的双重类型标签首先是不直观的。通常数据的标签是字符串,比如名字。这迫使用户将这些标签映射到双打作为预处理,这是无聊的样板代码。
    • 是的,这令人困惑。更糟糕的是,如果标签与预期范围重叠,它可能是一个无声的错误。关于标签有点复杂,并且存在静态类型、标签哈希性和编码成本等不同的问题。
    猜你喜欢
    • 2016-08-03
    • 2018-06-07
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    相关资源
    最近更新 更多