【问题标题】:SparkML Vectors: Accessing Model OutputSparkML 向量:访问模型输出
【发布时间】:2017-06-18 02:42:07
【问题描述】:

我正在尝试访问似乎被锁定在模型对象返回的向量中的值。我在这里和那里看到了一些关于旧/新 Vector 类型的帖子,但这并没有帮助我弄清楚我缺少什么。

来自 CountVectorizer 模型的代码设置了问题。似乎与 org.apache.spark.ml.linalg.VectorUDT 有关,但我不确定。我已经被这个屏蔽到有点尴尬的地步了。

有人可以提供一个代码示例,说明如何解析 features 向量的 3 个元素中的每一个:词汇计数、术语 ID 列表、术语计数列表?

import org.apache.spark.ml.feature.{CountVectorizer, CountVectorizerModel}

sc.version
res1: String = 2.1.1

val df = spark.createDataFrame(Seq(
  (0, Array("a", "b", "c")),
  (1, Array("a", "b", "b", "c", "a"))
)).toDF("id", "words")

// fit a CountVectorizerModel from the corpus
val cvModel: CountVectorizerModel = (new CountVectorizer()
  .setInputCol("words")
  .setOutputCol("features")
  .setVocabSize(3)
  .setMinDF(2)
  .fit(df)
)

// alternatively, define CountVectorizerModel with a-priori vocabulary
val cvm = (new CountVectorizerModel(Array("a", "b", "c"))
  .setInputCol("words")
  .setOutputCol("features")
)

val df_vectorized = cvModel.transform(df)

df_vectorized.show(false)

+---+---------------+-------------------------+
|id |words          |features                 |
+---+---------------+-------------------------+
|0  |[a, b, c]      |(3,[0,1,2],[1.0,1.0,1.0])|
|1  |[a, b, b, c, a]|(3,[0,1,2],[2.0,2.0,1.0])|
+---+---------------+-------------------------+

【问题讨论】:

  • 请分享您尝试并成功解决问题的方法!
  • @eliasah,感谢您的反馈。我尝试了很多东西。我宁愿不要用我所有失败的尝试来混淆这个问题。我觉得解决方案是微不足道的,我只是没有看到它。希望有人可以帮助我。

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


【解决方案1】:

解决方案

我找到了一种访问此特定模型中数据的方法。

import org.apache.spark.ml.linalg.SparseVector

df_vectorized.select("features").rdd.map(_.getAs[SparseVector](0).size).take(2)
df_vectorized.select("features").rdd.map(_.getAs[SparseVector](0).indices).take(2)
df_vectorized.select("features").rdd.map(_.getAs[SparseVector](0).values).take(2)

我不知道这是否是实现这么简单的事情的最佳方法。

想法

我宁愿做如下的事情:

case class MyData(
  id: Int,
  words: Array[String],
  features: (Int, Array[Int], Array[Double])
)

df_vectorized.as[MyData]

但是当我尝试这个时,我得到了以下错误:

java.lang.ClassCastException: org.apache.spark.ml.linalg.VectorUDT cannot be cast to org.apache.spark.sql.types.StructType

即使这样也不是很好,因为在这种情况下不会命名 features 元组的元素。

无论如何,我认为这里的要点是您需要识别模型输出的数据类型,并希望它具有与之关联的访问方法。

即使识别数据类型也是幸运的。我碰巧尝试了以下方法:

df_vectorized.select("features").rdd.map(_.getAs[Seq[Any]](0).size).take(2)

得到了这个错误:

java.lang.ClassCastException: org.apache.spark.ml.linalg.SparseVector cannot be cast to scala.collection.SeqLike

请注意,当我尝试创建 DataSet 时,输出的类被称为 VectorUDT,但现在在我使用 RDD api 时被称为 SparseVector .

这就是我找到正确数据类型的方法。这真的很烦人,因为df_vectorized.schema 的相关输出是 org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7

更让人头疼的是,VectorUDT 的描述如下:Vector 的用户定义类型,允许通过 org.apache.spark.sql.Dataset 轻松与 SQL 交互。也许它确实允许“轻松”交互。不过,我似乎无法弄清楚。

【讨论】:

  • 我找到了解决问题的方法。我会让这个答案挂在这里一点,以防有人有更好的解决方案。
猜你喜欢
  • 2017-03-20
  • 1970-01-01
  • 2017-07-22
  • 2012-04-05
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多