我是Spark 2的新手。 我试过Spark tfidf例子
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
,因为每个单词在文档中都会出现一次。
如果我们想象输出rawFeatures
字典包含单词索引作为键,以及文档中单词出现的数量作为值,为什么键1
等于3.0
?文档中没有出现3次单词。
这对我来说很困惑。我错过了什么?
答案 0 :(得分: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)
列表中的三个单词(i,about和spark)散列到同一个桶中,每个单词出现一次,因此得到的结果。
相关: