我有一组句子中的词,已经进行了分词并应用了词频转换。
int numFeatures = 9000; hashingTF = new HashingTF().setInputCol("filtered").setOutputCol("features") .setNumFeatures(numFeatures); DataFrame rawFeaturizedData = hashingTF.transform(stopWordsRemoved); rawFeaturizedData.show();
当我打印数据框时,我看到“features”列的值如下所示
(9000,[2010,2113,2599,3807,5109,5849],[1.0,1.0,1.0,1.0,1.0,1.0])
9000是为词频计算配置的特征数量。我将其设置为9000,因为在应用文本转换(如停用词删除、词形还原等)后有8000个唯一词。
[2010,2113,2599,3807,5109,5849] – 我假设这些是文本中每个词(特征)分配的数字
[1.0,1.0,1.0,1.0,1.0,1.0] 是什么? – 根据定义,词频会对词进行哈希并计算每个词的权重。这就是权重吗?为什么它总是显示为1.0?
回答:
如下所示:
(9000,[2010,2113,2599,3807,5109,5849],[1.0,1.0,1.0,1.0,1.0,1.0])
是Spark中SparseVector
的字符串表示,其中:
- 开头的数字是向量的大小(这里是特征的数量)。
- 第一个数组是非零索引的列表。
- 第二个数组是值的列表(这里是权重)。
索引等于1的条件是:
- 没有重复的标记。
- 没有哈希冲突。
假设输入数据如下所示:
val df = Seq("orange orange apple", "apple orange kiwi").toDF("text") .withColumn("filtered", split($"text", "\\s+"))
如果我们使用11个特征:
val hashingTF11 = new HashingTF() .setInputCol("filtered") .setOutputCol("features") .setNumFeatures(11)
并转换:
hashingTF11.transform(df).show(2, false)
我们将在第一行看到2.0
(orange出现了两次):
+-------------------+-----------------------+---------------------------+|text |filtered |features |+-------------------+-----------------------+---------------------------+|orange orange apple|[orange, orange, apple]|(11,[9,10],[2.0,1.0]) ||apple orange kiwi |[apple, orange, kiwi] |(11,[6,9,10],[1.0,1.0,1.0])|+-------------------+-----------------------+---------------------------+
但如果我们将特征数量减少到10:
val hashingTF10 = new HashingTF() .setInputCol("filtered") .setOutputCol("features") .setNumFeatures(10)
并转换:
hashingTF10.transform(df).show(2, false)
两行都会有权重为2.0的特征:
+-------------------+-----------------------+--------------------+|text |filtered |features |+-------------------+-----------------------+--------------------+|orange orange apple|[orange, orange, apple]|(10,[1,3],[1.0,2.0])||apple orange kiwi |[apple, orange, kiwi] |(10,[1,3],[2.0,1.0])|+-------------------+-----------------------+--------------------+
这是由于哈希冲突造成的。