使用相关和随机语料库计算 TF-IDF 单词分数
Posted
技术标签:
【中文标题】使用相关和随机语料库计算 TF-IDF 单词分数【英文标题】:Compute TF-IDF word score with relevant and random corpus 【发布时间】:2019-04-14 23:05:56 【问题描述】:给定一个相关文档的语料库 (CORPUS) 和一个随机文档的语料库 (ran_CORPUS),我想使用 ran_CORPUS 作为基线计算 CORPUS 中所有单词的 TF-IDF 分数。在我的项目中,ran_CORPUS 的文档数量大约是 CORPUS 的 10 倍。
CORPUS = ['this is a relevant document',
'this one is a relevant text too']
ran_CORPUS = ['the sky is blue',
'my cat has a furry tail']
我的计划是规范化文档,将 CORPUS 中的所有文档制作成一个文档(CORPUS 现在是一个包含一个长字符串元素的列表)。对于 CORPUS,我附加了所有 ran_CORPUS 文档。然后使用sklearn's TfidfTransformer
计算语料库的TF-IDF 矩阵(现在由CORPUS 和ran_CORPUS 组成)。最后选择该 CORPUS 的第一行以获得我最初相关 CORPUS 的 TF-IDF 分数。
有人知道这种方法是否可行,是否有简单的编码方法?
【问题讨论】:
【参考方案1】:当您说“这种方法是否可行”时,我想您的意思是将所有相关文档合并为一个并进行矢量化处理是否提供了一个有效的模型。我想这取决于您要尝试使用该模型做什么。
我不是一个数学家,但我想这就像将所有文档的分数平均到一个向量空间中,所以你已经失去了个人所占据的原始向量空间的一些空间形状相关文件。所以你试图制作一个“主”或“原型”文档来代表一个主题?
如果您接下来要对测试文档进行相似度匹配,或者通过距离比较进行分类,那么您可能已经失去了原始文档向量化的一些微妙之处。整个主题的各个方面可能比平均值所代表的要多。
更具体地说,假设您的原始“相关语料库”有两个文档集群,因为实际上有两个主要的子主题由不同的重要特征组表示。稍后在进行分类时,测试文档可以单独匹配这些集群中的任何一个 - 再次因为它们接近两个子主题之一。在这种情况下,通过对整个“相关语料库”进行平均,您最终会得到一个位于这两个集群之间的单个文档,但不能准确地表示任何一个。因此,测试演示文稿可能根本不匹配 - 取决于分类技术。
我认为如果不在适当的特定语料库上进行试验就很难说。
不管有效性如何,下面是它的实现方式。
请注意,您还可以使用 TfidfVectorizer 将矢量化和 Tfidf'ing 步骤合二为一。结果并不总是完全相同,但在这种情况下是一样的。
此外,您说规范化文档 - 通常您可能会在输入需要规范化分布的分类算法(如 SVM)之前对向量表示进行规范化。但是我认为 TFIDF 自然会正常化,因此它似乎没有任何进一步的影响(我可能在这里错了)。
import logging
from sklearn import preprocessing
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer, TfidfTransformer
CORPUS = ['this is a relevant document',
'this one is a relevant text too']
ran_CORPUS = ['the sky is blue',
'my cat has a furry tail']
doc_CORPUS = ' '.join([str(x) for x in CORPUS])
ran_CORPUS.append(doc_CORPUS)
count_vect = CountVectorizer()
X_counts = count_vect.fit_transform(ran_CORPUS)
tfidf_transformer = TfidfTransformer()
X_tfidf = tfidf_transformer.fit_transform(X_counts)
logging.debug("\nCount + TdidfTransform \n%s" % X_tfidf.toarray())
# or do it in one pass with TfidfVectorizer
vectorizer = TfidfVectorizer()
X_tfidf = vectorizer.fit_transform(ran_CORPUS)
logging.debug("\nTdidfVectoriser \n%s" % X_tfidf.toarray())
# normalising doesn't achieve much as tfidf is already normalised.
normalizer = preprocessing.Normalizer()
X_tfidf = normalizer.transform(X_tfidf)
logging.debug("\nNormalised:\n%s" % X_tfidf.toarray())
Count + TdidfTransform
[[0.52863461 0. 0. 0. 0. 0.40204024
0. 0. 0. 0.52863461 0. 0.
0.52863461 0. 0. ]
[0. 0.4472136 0. 0.4472136 0.4472136 0.
0.4472136 0. 0. 0. 0.4472136 0.
0. 0. 0. ]
[0. 0. 0.2643173 0. 0. 0.40204024
0. 0.2643173 0.52863461 0. 0. 0.2643173
0. 0.52863461 0.2643173 ]]
TdidfVectoriser
[[0.52863461 0. 0. 0. 0. 0.40204024
0. 0. 0. 0.52863461 0. 0.
0.52863461 0. 0. ]
[0. 0.4472136 0. 0.4472136 0.4472136 0.
0.4472136 0. 0. 0. 0.4472136 0.
0. 0. 0. ]
[0. 0. 0.2643173 0. 0. 0.40204024
0. 0.2643173 0.52863461 0. 0. 0.2643173
0. 0.52863461 0.2643173 ]]
Normalised:
[[0.52863461 0. 0. 0. 0. 0.40204024
0. 0. 0. 0.52863461 0. 0.
0.52863461 0. 0. ]
[0. 0.4472136 0. 0.4472136 0.4472136 0.
0.4472136 0. 0. 0. 0.4472136 0.
0. 0. 0. ]
[0. 0. 0.2643173 0. 0. 0.40204024
0. 0.2643173 0.52863461 0. 0. 0.2643173
0. 0.52863461 0.2643173 ]]
【讨论】:
以上是关于使用相关和随机语料库计算 TF-IDF 单词分数的主要内容,如果未能解决你的问题,请参考以下文章