Apache spark Spark中HashingTF和CountVectorizer的区别是什么?
尝试在Spark中进行文档分类。我不确定哈希在HashingTF中做了什么;它会牺牲准确性吗?我怀疑,但我不知道。spark doc说它使用了“散列技巧”。。。这只是工程师使用的另一个非常糟糕/混乱的命名示例(我也有罪)。CountVectorizer还需要设置词汇表大小,但它有另一个参数,阈值参数,可用于排除文本语料库中低于某个阈值的单词或标记。我不明白这两个变压器之间的区别。这一点的重要性在于算法中的后续步骤。例如,如果我想对生成的tfidf矩阵执行SVD,那么词汇表大小将决定SVD矩阵的大小,这会影响代码的运行时间,还有模型性能等。除了API文档和没有深度的非常琐碎的示例之外,我通常很难找到有关Spark Mllib的任何源代码。散列技巧实际上是功能散列的另一个名称 我引用了维基百科的定义: 在机器学习中,与内核技巧类似,特征哈希(也称为哈希技巧)是一种快速且节省空间的特征矢量化方法,即将任意特征转化为向量或矩阵中的索引。它的工作原理是将哈希函数应用于特征,并将其哈希值直接用作索引,而不是在关联数组中查找索引 您可以在中阅读更多关于它的信息 实际上,对于节省空间的特征矢量化Apache spark Spark中HashingTF和CountVectorizer的区别是什么?,apache-spark,apache-spark-mllib,apache-spark-ml,Apache Spark,Apache Spark Mllib,Apache Spark Ml,尝试在Spark中进行文档分类。我不确定哈希在HashingTF中做了什么;它会牺牲准确性吗?我怀疑,但我不知道。spark doc说它使用了“散列技巧”。。。这只是工程师使用的另一个非常糟糕/混乱的命名示例(我也有罪)。CountVectorizer还需要设置词汇表大小,但它有另一个参数,阈值参数,可用于排除文本语料库中低于某个阈值的单词或标记。我不明白这两个变压器之间的区别。这一点的重要性在于算法中的后续步骤。例如,如果我想对生成的tfidf矩阵执行SVD,那么词汇表大小将决定SVD矩阵的大
然而,
CountVectorizer
只执行词汇提取,并将其转换为向量 几个重要的区别:
- 部分可逆(
)与不可逆(countvectorier
)-由于哈希是不可逆的,因此无法从哈希向量恢复原始输入。从另一方面来说,带有模型(索引)的计数向量可用于恢复无序输入。因此,使用散列输入创建的模型可能更难解释和监控HashingTF
- 内存和计算开销-
只需要一次数据扫描,除了原始输入和向量之外,不需要额外的内存哈希函数
需要对数据进行额外扫描以构建模型,并需要额外内存来存储词汇表(索引)。对于unigram语言模型,这通常不是一个问题,但对于较高的n-gram,这可能会非常昂贵或不可行CountVectorizer
- 哈希取决于向量的大小、哈希函数和文档。计数取决于向量的大小、训练语料库和文档李>
- 信息丢失的一个来源-在
的情况下,这是可能发生冲突的降维<代码>计数向量器丢弃不常用的令牌。它如何影响下游模型取决于特定的用例和数据HashingTF
- 信息丢失的一个来源-在
from pyspark.ml.feature import HashingTF, IDF, Tokenizer
from pyspark.ml.feature import CountVectorizer
sentenceData = spark.createDataFrame([
(0.0, "Hi I heard about Spark"),
(0.0, "I wish Java could use case classes"),
(1.0, "Logistic regression models are neat")],
["label", "sentence"])
tokenizer = Tokenizer(inputCol="sentence", outputCol="words")
wordsData = tokenizer.transform(sentenceData)
hashingTF = HashingTF(inputCol="words", outputCol="Features", numFeatures=100)
hashingTF_model = hashingTF.transform(wordsData)
print "Out of hashingTF function"
hashingTF_model.select('words',col('Features').alias('Features(vocab_size,[index],[tf])')).show(truncate=False)
# fit a CountVectorizerModel from the corpus.
cv = CountVectorizer(inputCol="words", outputCol="Features", vocabSize=20)
cv_model = cv.fit(wordsData)
cv_result = model.transform(wordsData)
print "Out of CountVectorizer function"
cv_result.select('words',col('Features').alias('Features(vocab_size,[index],[tf])')).show(truncate=False)
print "Vocabulary from CountVectorizerModel is \n" + str(cv_model.vocabulary)
输出如下所示
散列TF忽略了对LDA等技术至关重要的词汇表。为此,必须使用CountVectorizer函数。
与vocab大小无关,CountVectorizer函数估计术语频率,而无需任何近似值
CountVectorizer(inputCol="words", outputCol="features")
.fit(original_df)
.transform(original_df)
HashingTF(inputCol="words", outputCol="features")
.transform(original_df)
// alternatively, define CountVectorizerModel with a-priori vocabulary
val cvm = new CountVectorizerModel(Array("a", "b", "c"))
.setInputCol("words")
.setOutputCol("features")
cvModel.transform(df).show(false)
wordsData = spark.createDataFrame([([
'one', 'two', 'three', 'four', 'five',
'six', 'seven', 'eight', 'nine', 'ten'],)], ['tokens'])
hashing = HashingTF(inputCol="tokens", outputCol="hashedValues", numFeatures=pow(2,4))
hashed_df = hashing.transform(wordsData)
hashed_df.show(truncate=False)
+-----------------------------------------------------------+
|hashedValues |
+-----------------------------------------------------------+
|(16,[0,1,2,6,8,11,12,13],[1.0,1.0,1.0,3.0,1.0,1.0,1.0,1.0])|
+-----------------------------------------------------------+
...16...
....v-------8x-------v....
...[0,1,2,6,8,11,12,13]...
...---------------v
... [1.0,1.0,1.0,3.0,1.0,1.0,1.0,1.0] ...