散列向量化器和 tfidf 向量化器有什么区别

数据挖掘 nlp scikit-学习 文本挖掘 tfidf 散列向量化器
2021-09-26 00:32:55

我正在将文本文档的语料库转换为每个文档的词向量。我已经尝试过使用TfidfVectorizerHashingVectorizer

我知道 a不像 a 那样HashingVectorizer考虑IDF分数TfidfVectorizer我仍在使用 a 的原因HashingVectorizer是它在处理大型数据集时提供的灵活性,如此此处所述。(我的原始数据集有 3000 万个文档)

目前,我正在处理 45339 个文档的样本,因此,我也有能力使用TfidfVectorizer当我在同一个 45339 文档上使用这两个矢量化器时,我得到的矩阵是不同的。

hashing = HashingVectorizer()
with LSM('corpus.db')) as corpus:
    hashing_matrix = hashing.fit_transform(corpus)
print(hashing_matrix.shape) 

散列矩阵形状(45339、1048576)

tfidf = TfidfVectorizer()
with LSM('corpus.db')) as corpus:
    tfidf_matrix = tfidf.fit_transform(corpus)
print(tfidf_matrix.shape) 

tfidf 矩阵形状(45339、663307)

HashingVectorizer我想更好地理解 a和 a之间的区别TfidfVectorizer,以及这些矩阵大小不同的原因——尤其是单词/术语的数量。

4个回答

主要区别在于HashingVectorizer将散列函数应用于每个文档中TfidfVectorizer的词频计数,其中通过惩罚出现在语料库中更广泛的词来缩放每个文档中的词频计数。这里有一个很棒的总结

  • 哈希函数是将术语映射到特征的有效方法;它不一定需要仅应用于术语频率,但这HashingVectorizer就是这里使用的方式。除了 45339 个文档,我怀疑特征向量的长度为 1048576,因为它是默认的 2^20 n_features您可以减少这种情况并降低处理成本,但会增加碰撞风险,其中函数将不同的术语映射到相同的特征

  • 根据词向量的用例,可以显着减少散列特征向量的长度(以及复杂性),而准确性/有效性的损失可接受(由于增加的冲突)。Scikit-learn 有一些可以提供帮助的散列参数,例如alternate_sign.

  • 如果散列矩阵比字典宽,则意味着散列矩阵中的许多列条目将为空,这不仅是因为给定文档不包含特定术语,而且因为它们在整个文档中都是空的矩阵。如果不是,它可能会将多个术语发送到同一个特征哈希——这就是我们一直在谈论的“冲突”。HashingVectorizer有一个可以缓解这种情况的设置,alternate_sign默认情况下是打开的,在此处描述。

  • “词频 - 逆文档频率”获取每个文档中的词频,并通过惩罚在整个语料库中出现频率更高的词来对它们进行加权。直觉是根据情境找到的术语更有可能代表特定文档的主题。这与散列函数的不同之处在于,必须在语料库中有完整的词词典才能计算逆文档频率。我希望您的 tf.idf 矩阵维度是 45339 个文档,语料库中的 663307 个单词;Manning 等人提供了更多的详细信息和计算示例。

Leskovec 等人的“海量数据集挖掘”有大量关于特征散列和 tf.idf 的详细信息,作者在此处提供了 pdf 。

HashingVectorizer一个n_features默认参数1048576在散列时,它们实际上并没有计算字典映射术语到唯一索引以用于每个索引。相反,您只需对每个术语进行哈希处理并使用足够大的大小,以免发生太多冲突:hash(term) mod table_size. 您可以通过设置使返回的矩阵为您想要的任何大小n_features如果您认为默认值不合理,则应将其调整为适合您的语料库(尽管它需要更多内存,但将其设置得更大会导致更少的冲突)。

from sklearn.feature_extraction.text import HashingVectorizer
vectorizer = HashingVectorizer()
print(vectorizer.transform(['a very small document']).shape)
(1, 1048576)

small_vectorizer = HashingVectorizer(n_features=5)
print(small_vectorizer.transform(['a very small document']).shape)    
(1, 5)

HashingVectorizer 和 CountVectorizer(注意不是 Tfidfvectorizer)旨在做同样的事情。即将文本文档的集合转换为标记出现的矩阵。

如果您希望通过其相对重要性 (IDF) 对词频进行加权,那么您应该使用 Tfidfvectorizer。如果您需要原始计数或标准化计数(词频),则应使用 CountVectorizer 或 HashingVectorizer。

要了解 HashingVectorizer,请参阅这篇关于HashingVectorizer 与 CountVectorizer的文章。

有关 Tfidfvectorizer 的更多信息,请参阅这篇关于如何使用 Tfidftransformer 和 Tfidfvectorizer 的文章

散列向量化器


散列向量化器是一个向量化器,它使用散列技巧来找到标记字符串名称来特征整数索引映射。文本文档到矩阵的转换是由这个向量化器完成的,它将文档的集合转换为一个稀疏矩阵,其中保存了令牌出现次数。

HashingVectorizerCountVectorizer旨在做同样的事情。即将文本文档的集合转换为标记出现的矩阵。不同之处在于HashingVectorizer不存储结果词汇表(即唯一标记)。

使用HashingVectorizer,每个标记直接映射到矩阵中的列位置,其大小是预定义的。例如,如果矩阵中有 10,000 列,则每个标记映射到 10,000 列中的 1 列。这种映射通过散列发生。使用的散列函数称为Murmurhash3

TfidfVectorizer


TF IDF是两个人进行研究的结果。他们是Hans Peter Luhn,因其在词频方面的工作(1957 年)而受到赞誉,而Karen Spärck Jones 则为逆文档频率(1972 年)做出了贡献

TF-IDF代表Term Frequency-Inverse Document Frequency tf-idf 权重是信息检索和文本挖掘中常用的权重。该权重是一种统计度量,用于评估单词对集合或语料库中的文档的重要性。重要性与单词在文档中出现的次数成比例增加,但会被语料库中单词的频率抵消。TF-IDF加权方案的变体通常被搜索引擎用作在给定用户查询的情况下对文档的相关性进行评分和排名的中心工具。

TF-IDF是一种流行的方法,用于衡量NLP任务的术语,因为它根据术语在文档中的重要性分配一个值,该值由其在语料库中所有文档中的重要性来衡量,这在数学上消除了英语中自然出现的单词,并选择更能描述您的文本的单词。

计算TF-IDF

通常,TF-IDF由两个术语组成:

TF:词频,衡量一个词在文档中出现的频率。由于每个文档的长度都不同,因此一个词在长文档中出现的次数可能比在短文档中出现的次数要多得多。因此,术语频率通常除以文档长度(也就是文档中的术语总数)作为标准化的一种方式:

F()=术语 t 在文档中出现的次数文档中的术语总数

IDF:逆文档频率,衡量一个词的重要性。在计算TF时,所有项都被认为同样重要。然而,众所周知,某些术语,例如“is”、“of”和“that”,可能会出现很多次但并不重要。因此,我们需要通过计算以下内容来权衡频繁项,同时扩大稀有项:

一世DF()=lG(文件总数包含术语 t 的文档数)

F-一世DF()=F()*一世DF()