3

我是新来的星火2. 我试图星火TFIDF例如星火HashingTF如何工作

sentenceData = spark.createDataFrame([ 
    (0.0, "Hi I heard about Spark") 
], ["label", "sentence"]) 

tokenizer = Tokenizer(inputCol="sentence", outputCol="words") 
wordsData = tokenizer.transform(sentenceData) 


hashingTF = HashingTF(inputCol="words", outputCol="rawFeatures", numFeatures=32) 
featurizedData = hashingTF.transform(wordsData) 

for each in featurizedData.collect(): 
    print(each) 

它输出

Row(label=0.0, sentence=u'Hi I heard about Spark', words=[u'hi', u'i', u'heard', u'about', u'spark'], rawFeatures=SparseVector(32, {1: 3.0, 13: 1.0, 24: 1.0})) 

我预计在rawFeatures我会得到长期的频率就像{0:0.2, 1:0.2, 2:0.2, 3:0.2, 4:0.2}。因为条款频率为:

tf(w) = (Number of times the word appears in a document)/(Total number of words in the document) 

在我们的例子是:tf(w) = 1/5 = 0.2为每个单词,因为每个字在文档中apears一次。 如果我们想象输出rawFeatures字典包含单词索引作为关键字,并且文档中的单词出现次数为值,为什么键1等于3.0?没有文字出现在文档中3次。 这让我感到困惑。我错过了什么?

回答

2

TL; DR;这只是一个简单的哈希碰撞。 HashingTF需要hash(word) % numBuckets来确定存储桶并且像这里那样具有非常少的存储桶数量的冲突是可以预期的。一般来说,您应该使用更多数量的桶,或者如果碰撞不可接受,请使用CountVectorizer

详细说明。 HashingTF默认使用Murmur哈希。 [u'hi', u'i', u'heard', u'about', u'spark']将被散列为[-537608040, -1265344671, 266149357, 146891777, 2101843105]。如果您follow the source你会看到,实现等同于:

import org.apache.spark.unsafe.types.UTF8String 
import org.apache.spark.unsafe.hash.Murmur3_x86_32.hashUnsafeBytes 

Seq("hi", "i", "heard", "about", "spark") 
    .map(UTF8String.fromString(_)) 
    .map(utf8 => 
    hashUnsafeBytes(utf8.getBaseObject, utf8.getBaseOffset, utf8.numBytes, 42)) 
Seq[Int] = List(-537608040, -1265344671, 266149357, 146891777, 2101843105) 

当你把这些值non-negative modulo你会得到[24, 1, 13, 1, 1]

List(-537608040, -1265344671, 266149357, 146891777, 2101843105) 
    .map(nonNegativeMod(_, 32)) 
List[Int] = List(24, 1, 13, 1, 1) 

从三个词该列表(我,关于和火花)哈希到同一个桶,每个出现一次,因此你得到的结果。

相关: