给定相关文档的语料库 (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 现在是一个包含一个长字符串元素的列表)。我将所有 ran_CORPUS 文档附加到 CORPUS 中。然后,我使用 sklearn 的 TfidfTransformer 计算语料库的 TF-IDF 矩阵(现在由 CORPUS 和 ran_CORPUS 组成)。最后选择该 CORPUS 的第一行来获取我的初始相关 CORPUS 的 TF-IDF 分数。
有人知道这种方法是否可行以及是否有一种简单的编码方法?
最佳答案
当您说“这种方法是否可行”时,我想您的意思是,将所有相关文档合并为一个并进行矢量化是否会提供一个有效的模型。我想这取决于您要尝试使用该模型做什么。
我不是一个数学家,但我想这就像将所有文档的分数平均到一个向量空间中,因此你丢失了个体占用的原始向量空间的一些空间形状相关文件。那么您是否尝试过制作一个“主”或“原型(prototype)”文档来代表一个主题?
如果您随后要进行类似与测试文档的相似性匹配或通过距离比较进行分类之类的操作,那么您可能会失去原始文档矢量化的一些微妙之处。整个主题可能包含比平均值所代表的更多方面。
更具体地说,假设您的原始“相关语料库”有两个文档集群,因为实际上有两个主要子主题,由不同组的重要特征表示。稍后在进行分类时,测试文档可以单独匹配这些集群中的任何一个 - 同样是因为它们接近两个子主题之一。在这种情况下,通过对整个“相关语料库”进行平均,您最终会得到一个位于这两个集群之间的单个文档,但不能准确地代表其中任何一个。因此,测试演示可能根本不匹配 - 取决于分类技术。
我认为如果没有在适当的特定语料库上进行试验就很难说。
无论有效性如何,下面是它的实现方式。
请注意,您还可以使用 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 ]]
关于python-3.x - 使用相关和随机语料库计算 TF-IDF 单词得分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53258578/