跨文档词项TF-IDF得分之和的解释

24

首先,让我们提取每个文档中每个词语的TF-IDF得分:

from gensim import corpora, models, similarities
documents = ["Human machine interface for lab abc computer applications",
              "A survey of user opinion of computer system response time",
              "The EPS user interface management system",
              "System and human system engineering testing of EPS",
              "Relation of user perceived response time to error measurement",
              "The generation of random binary unordered trees",
              "The intersection graph of paths in trees",
              "Graph minors IV Widths of trees and well quasi ordering",
              "Graph minors A survey"]
stoplist = set('for a of the and to in'.split())
texts = [[word for word in document.lower().split() if word not in stoplist] for document in documents]
dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]
tfidf = models.TfidfModel(corpus)
corpus_tfidf = tfidf[corpus]

将其打印出来:

for doc in corpus_tfidf:
    print doc

[输出]:
[(0, 0.4301019571350565), (1, 0.4301019571350565), (2, 0.4301019571350565), (3, 0.4301019571350565), (4, 0.2944198962221451), (5, 0.2944198962221451), (6, 0.2944198962221451)]
[(4, 0.3726494271826947), (7, 0.27219160459794917), (8, 0.3726494271826947), (9, 0.27219160459794917), (10, 0.3726494271826947), (11, 0.5443832091958983), (12, 0.3726494271826947)]
[(6, 0.438482464916089), (7, 0.32027755044706185), (9, 0.32027755044706185), (13, 0.6405551008941237), (14, 0.438482464916089)]
[(5, 0.3449874408519962), (7, 0.5039733231394895), (14, 0.3449874408519962), (15, 0.5039733231394895), (16, 0.5039733231394895)]
[(9, 0.21953536176370683), (10, 0.30055933182961736), (12, 0.30055933182961736), (17, 0.43907072352741366), (18, 0.43907072352741366), (19, 0.43907072352741366), (20, 0.43907072352741366)]
[(21, 0.48507125007266594), (22, 0.48507125007266594), (23, 0.48507125007266594), (24, 0.48507125007266594), (25, 0.24253562503633297)]
[(25, 0.31622776601683794), (26, 0.31622776601683794), (27, 0.6324555320336759), (28, 0.6324555320336759)]
[(25, 0.20466057569885868), (26, 0.20466057569885868), (29, 0.2801947048062438), (30, 0.40932115139771735), (31, 0.40932115139771735), (32, 0.40932115139771735), (33, 0.40932115139771735), (34, 0.40932115139771735)]
[(8, 0.6282580468670046), (26, 0.45889394536615247), (29, 0.6282580468670046)]

如果我们想要找到这个语料库中单词的“显著性”或“重要性”,我们能否简单地将所有文档中的tf-idf分数总和除以文档数量来计算呢?即:
>>> tfidf_saliency = Counter()
>>> for doc in corpus_tfidf:
...     for word, score in doc:
...         tfidf_saliency[word] += score / len(corpus_tfidf)
... 
>>> tfidf_saliency
Counter({7: 0.12182694202050007, 8: 0.11121194156107769, 26: 0.10886469856464989, 29: 0.10093919463036093, 9: 0.09022272408985754, 14: 0.08705221175200946, 25: 0.08482488519466996, 6: 0.08143359568202602, 10: 0.07480097322359022, 12: 0.07480097322359022, 4: 0.07411881371164887, 13: 0.07117278898823597, 5: 0.07104525967490458, 27: 0.07027283689263066, 28: 0.07027283689263066, 11: 0.060487023243988705, 15: 0.055997035904387725, 16: 0.055997035904387725, 21: 0.05389680556362955, 22: 0.05389680556362955, 23: 0.05389680556362955, 24: 0.05389680556362955, 17: 0.048785635947490406, 18: 0.048785635947490406, 19: 0.048785635947490406, 20: 0.048785635947490406, 0: 0.04778910634833961, 1: 0.04778910634833961, 2: 0.04778910634833961, 3: 0.04778910634833961, 30: 0.045480127933079706, 31: 0.045480127933079706, 32: 0.045480127933079706, 33: 0.045480127933079706, 34: 0.045480127933079706})

从输出结果来看,我们可以认为在这个语料库中最常见的单词是:

>>> dictionary[7]
u'system'
>>> dictionary[8]
u'survey'
>>> dictionary[26]
u'graph'

如果是这样,在多个文档中计算单词TF-IDF分数之和的数学解释是什么?


请问您能否将您的“字典”输出附加到您的问题中。我想与我的“字典”进行比较,以便在我的答案中更新输出表格。 - stovfl
哎呀,抱歉我没有保存它。由于我正在使用Python3,所以字典会有所不同,如果我重新运行它,字典就不一样了。但是单词的排名应该是确定性的,因为它基于静态计数,重新运行gensim代码,你应该会得到相同的前三名“系统、调查、图表”。 - alvas
抱歉,无法使用gensim。 - stovfl
5个回答

6

TF-IDF在语料库中的解释是给定术语的语料库中最高TF-IDF值。

在corpus_tfidf中找到前几个单词。

    topWords = {}
    for doc in corpus_tfidf:
        for iWord, tf_idf in doc:
            if iWord not in topWords:
                topWords[iWord] = 0

            if tf_idf > topWords[iWord]:
                topWords[iWord] = tf_idf

    for i, item in enumerate(sorted(topWords.items(), key=lambda x: x[1], reverse=True), 1):
        print("%2s: %-13s %s" % (i, dictionary[item[0]], item[1]))
        if i == 6: break

输出对比表格:
注意:无法使用gensim创建与corpus_tfidf匹配的dictionary
只能显示单词索引。

Question tfidf_saliency   topWords(corpus_tfidf)  Other TF-IDF implentation  
---------------------------------------------------------------------------  
1: Word(7)   0.121        1: Word(13)    0.640    1: paths         0.376019  
2: Word(8)   0.111        2: Word(27)    0.632    2: intersection  0.376019  
3: Word(26)  0.108        3: Word(28)    0.632    3: survey        0.366204  
4: Word(29)  0.100        4: Word(8)     0.628    4: minors        0.366204  
5: Word(9)   0.090        5: Word(29)    0.628    5: binary        0.300815  
6: Word(14)  0.087        6: Word(11)    0.544    6: generation    0.300815  

TF-IDF的计算总是考虑到语料库。 已测试Python版本: 3.4.2

“文档”的定义是模糊的。我认为在文档集合中最大的tf-idf分数并不代表语料库的tf-idf。 - alvas
1
你能给一个链接展示“文档”的定义是什么吗?你对以下公式有何看法:得分 = 语料库中每个术语的 tf-idf 值之和。 - stovfl
在语料库中的句子的情况下,句子是一个文档吗?还是一组句子是一个文档?在TF-IDF的情况下,如果TF是在整个语料库中计算的(跨所有句子求和),那么这仍然是tf-idf吗?在语料库中使用文档的概念来处理句子有些模糊。 - alvas
这取决于你想要什么!如果你为你的项目定义了一个文档必须至少有10个句子,那么就删除所有不符合这个前提条件的文档。对于tf-idf I,我会接受只有一个句子甚至一个单词的文档,因为这些文档得到的tf-idf很低。TF是按术语而不是按句子计算的。 - stovfl
顺便问一下,“Other TF-IDF implementation”是什么? - alvas
1
@alvas:它不像gensim那样是一个包,而是展示了如何实现tf-idf。http://aimotion.blogspot.de/2011/12/machine-learning-with-python-meeting-tf.html - stovfl

3

这是一个很棒的讨论。感谢您发起这个主题。@avip提出的包括文档长度的想法似乎很有趣。我们需要进行实验并检查结果。同时,让我尝试以稍微不同的方式提出问题。当查询TF-IDF相关性分数时,我们试图解释什么?

  1. Possibly trying to understand the word relevance at the document level
  2. Possibly trying to understand the word relevance per Class
  3. Possibly trying to understand the word relevance overall ( in the whole corpus )

     # # features, corpus = 6 documents of length 3
     counts = [[3, 0, 1],
               [2, 0, 0],
               [3, 0, 0],
               [4, 0, 0],
               [3, 2, 0],
               [3, 0, 2]]
     from sklearn.feature_extraction.text import TfidfTransformer
     transformer = TfidfTransformer(smooth_idf=False)
     tfidf = transformer.fit_transform(counts)
     print(tfidf.toarray())
    
     # lambda for basic stat computation
     summarizer_default = lambda x: np.sum(x, axis=0)
     summarizer_mean = lambda x: np.mean(x, axis=0)
    
     print(summarizer_default(tfidf))
     print(summarizer_mean(tfidf))
    

结果:

# Result post computing TF-IDF relevance scores
array([[ 0.81940995,  0.        ,  0.57320793],
           [ 1.        ,  0.        ,  0.        ],
           [ 1.        ,  0.        ,  0.        ],
           [ 1.        ,  0.        ,  0.        ],
           [ 0.47330339,  0.88089948,  0.        ],
           [ 0.58149261,  0.        ,  0.81355169]])

# Result post aggregation (Sum, Mean) 
[[ 4.87420595  0.88089948  1.38675962]]
[[ 0.81236766  0.14681658  0.2311266 ]]

如果我们仔细观察,我们会发现在所有文档中都出现的特征1并没有被完全忽略,因为sklearn实现的idf = log [ n / df(d, t) ] + 1. 在分母上加了一个+1,这样只是恰好在所有文档中出现的重要单词不会被忽略。例如,单词“bike”在将某个文档分类为“motorcycle”(20_newsgroup数据集)时经常出现。
关于前两个问题,一个问题是试图解释和理解可能出现在文档中的前几个共同特征。在这种情况下,以某种形式汇总包括文档中所有可能的单词出现情况并不会在数学上削弱任何东西。我认为这样的查询对探索数据集并帮助理解数据集非常有用。类似的逻辑也可以应用于使用Hashing进行向量化。
相关性得分=mean(tf(t,d) * idf(t,d)) = mean( (bias + inital_wt * F(t,d) / max{F(t',d)}) * log(N/df(d, t)) + 1 ))
第三个问题非常重要,因为它可能对选择用于构建预测模型的特征产生贡献。仅使用独立的TF-IDF分数进行特征选择可能会在多个层面上产生误导。采用更理论的统计检验,如与TF-IDF相关性分数配对的'chi2'可能是更好的方法。这种统计测试还评估了特征与各自目标类之间的重要性。
当然,将这样的解释与模型学习的特征权重结合起来将有助于完全理解文本派生特征的重要性。
** 这个问题在这里无法详细解答。但是,希望以上内容有所帮助。其他人有什么看法?
参考资料:https://arxiv.org/abs/1707.05261

2

有两种情境可以计算突出性。

  1. 语料库中的突出性
  2. 单个文档中的突出性

语料库中的突出性可以通过计算特定单词在语料库中出现的次数或者单词出现在文档中的倒数(IDF=倒排文档频率)来简单地计算。因为具有特定意义的单词不会随处可见。

文档中的突出性是通过tf_idf计算的。因为它由两种信息组成:全局信息(基于语料库)和本地信息(基于文档)。声称“文档中具有较大频率的单词在当前文档中更重要”并非完全正确或错误,因为它取决于单词的全局突出性。在一个特定的文档中,您会发现许多像“it、is、am、are…”这样频率很高的单词,但这些单词在任何文档中都不重要,您可以将它们视为停用词!

---- 编辑 ---

分母(=len(corpus_tfidf))是一个常量值,如果您想处理测量的序数而不是基数,则可以忽略该值。另一方面,我们知道IDF意味着倒排文档频率,因此可以表示为1/DF。我们知道DF是一个语料库级别的值,而TF是一个文档级别的值。TF-IDF总和将文档级别的TF转换为语料库级别的TF。实际上,总和等于这个公式:

count(单词)/ count(包含单词的文档)

这种测量可以称为逆散射值。当值增加时,意味着单词被聚集到更小的文档子集中,反之亦然。

我认为这个公式并不那么有用。


在文档内部和跨文档中,“重要性” / “显著性”的概念是通过TF-IDF和IDF的定义清晰明了的。但你并没有回答跨文档中TF-IDF总和的解释是什么。 ;P - alvas

0

我也遇到了同样的问题。我会在这里分享我的解决方案,但不确定它有多有效。

基本上,在计算tf-idf之后,我们得到的是一个术语与文档之间的矩阵。

[terms/docs : doc1  ,  doc2 , doc3..... docn
 term1      : tf(doc1)-idf, tf(doc2)-idf , tf(doc3)-idf.....
 .
 .
 .
 termn ........ ]

我们可以将列doc1,doc2 ... docn视为根据n个不同指标给出的每个术语的分数。如果我们在列之间求和,我们只是对得分进行平均,这是一种天真的方式,不能完全代表所捕获的信息。由于这是一个前k个检索问题,因此我们可以做得更好。一种有效的算法是Fagin算法,它基于以下思想:
扫描排序列表,直到找到已在所有列表中看到的k个数据项,然后算法可以停止,并且保证在迄今为止看到的所有数据项中,即使那些未出现在所有列表中的数据项,也可以找到前k个数据项。
这里的排序列表仅意味着特定文档的单个列成为列表,我们有n个这样的列表。因此,对每个列表进行排序,然后对其进行Fagins操作。
了解更多here

-1
如果我们想找到这个文集中单词的“显著性”或“重要性”,我们能不能简单地对所有文档的TF-IDF分数求和并除以文档的数量?如果可以的话,跨文档的TF-IDF分数之和的数学解释是什么?
如果你将跨文档的TD-IDF分数相加,本来得分较低的术语可能会得到提升,而得分较高的术语可能会被降低。
我认为简单地除以总文档数不足以进行适当的标准化来解决这个问题。也许将文档长度纳入标准化因子中?无论如何,我认为所有这些方法仍然需要针对特定领域进行调整。
所以,一般来说,从数学上讲,我希望您会得到一个不可取的平均效果。

1
当对文档进行TF-IDF求和时,不进行文档归一化是否会导致与IDF相似的数字/效果? - alvas
我认为它会相似,但是预计准确性(由人判断)会下降。我在考虑权重日志N/n_term:如果文档在上下文中不相关,n_term就太容易偏斜了。尽管如此,如果N足够大,这可能没问题?也许您可以手动比较有/没有在第一个文档上求和的术语? - avip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接