SparkML 向量:访问模型输出
SparkML Vectors: Accessing Model Output
我正在尝试访问似乎被锁定在模型对象返回的向量中的值。我在这里和那里看到了一些关于 old/new 矢量类型的帖子,但这并没有帮助我弄清楚我遗漏了什么。
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])|
+---+---------------+-------------------------+
解决方案
我找到了访问此特定模型中数据的方法。
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
请注意,当我尝试创建数据集时,输出的 class 被称为 VectorUDT,但现在被称为 当我使用 RDD api.
时,SparseVector
这就是我找到正确数据类型的方式。这真的很烦人,因为 df_vectorized.schema
的相关输出是 org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7.
更让人头疼的是,VectorUDT 的描述如下:Vector 的用户定义类型,允许通过 org.apache.spark.sql.Dataset 与 SQL 轻松交互。也许它确实允许 'easy' 交互。不过我似乎无法弄清楚。
我正在尝试访问似乎被锁定在模型对象返回的向量中的值。我在这里和那里看到了一些关于 old/new 矢量类型的帖子,但这并没有帮助我弄清楚我遗漏了什么。
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])|
+---+---------------+-------------------------+
解决方案
我找到了访问此特定模型中数据的方法。
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
请注意,当我尝试创建数据集时,输出的 class 被称为 VectorUDT,但现在被称为 当我使用 RDD api.
时,SparseVector这就是我找到正确数据类型的方式。这真的很烦人,因为 df_vectorized.schema
的相关输出是 org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7.
更让人头疼的是,VectorUDT 的描述如下:Vector 的用户定义类型,允许通过 org.apache.spark.sql.Dataset 与 SQL 轻松交互。也许它确实允许 'easy' 交互。不过我似乎无法弄清楚。