如何从Spark ML Lib中的TF Vector RDD获取单词细节?

17

我使用Spark中的HashingTF创建了术语频率。对于每个单词,我使用tf.transform得到了其词频。

但结果以以下格式显示。

[<hashIndexofHashBucketofWord1>,<hashIndexofHashBucketofWord2> ...]
,[termFrequencyofWord1, termFrequencyOfWord2 ....]

例:

(1048576,[105,3116],[1.0,2.0])

使用tf.indexOf("word"),我能够获取哈希桶中的索引。

但是,我该如何通过索引获取单词?

1个回答

26

很抱歉,你做不到。由于哈希是非单射的,因此没有反函数。换句话说,无限数量的标记可以映射到单个桶中,因此不可能确定实际上哪一个在那里。

如果您使用大型哈希表,且唯一标记数相对较低,则可以尝试从存储在数据集中的桶到可能的标记之间创建查找表。这是一对多的映射,但是如果满足上述条件,则冲突数量应该相对较低。

如果需要可逆转换,则可以使用组合TokenizerStringIndexer并手动构建稀疏特征向量。

另请参见:Spark使用什么哈希函数进行HashingTF,我如何复制它?

编辑:

在Spark 1.5+(PySpark 1.6+)中,您可以使用CountVectorizer,它应用可逆转换并存储词汇表。

Python:

from pyspark.ml.feature import CountVectorizer

df = sc.parallelize([
    (1, ["foo", "bar"]), (2, ["foo", "foobar", "baz"])
]).toDF(["id", "tokens"])

vectorizer = CountVectorizer(inputCol="tokens", outputCol="features").fit(df)
vectorizer.vocabulary
## ('foo', 'baz', 'bar', 'foobar')

Scala:

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

val df = sc.parallelize(Seq(
    (1, Seq("foo", "bar")), (2, Seq("foo", "foobar", "baz"))
)).toDF("id", "tokens")

val model: CountVectorizerModel = new CountVectorizer()
  .setInputCol("tokens")
  .setOutputCol("features")
  .fit(df)

model.vocabulary
// Array[String] = Array(foo, baz, bar, foobar)
其中0号位置的元素对应于索引0,1号位置的元素对应于索引1,以此类推。

2
我想补充一下,在文档中可以看到,自1.2.0版本以来,您可以调用indexOf(term)。 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接