2

给定一个相关文档的语料库 (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 TfidfTransformerI 计算语料库的 TF-IDF 矩阵(现在由 CORPUS 和 ran_CORPUS 组成)。最后选择该 CORPUS 的第一行以获得我最初相关 CORPUS 的 TF-IDF 分数。

有谁知道这种方法是否可行以及是否有一种简单的编码方法?

4

1 回答 1

2

当您说“这种方法是否可行”时,我认为您的意思是将所有相关文档合并为一个并进行矢量化呈现一个有效的模型。我想这取决于您要尝试使用该模型做什么。

我不是一个数学家,但我想这就像将所有文档的分数平均到一个向量空间中,所以你失去了一些空间的形状,原始向量空间被各个相关文档占据。所以你试图制作一个“主”或“原型”文档来代表一个主题?

如果您接下来要对测试文档进行相似性匹配或通过距离比较进行分类,那么您可能已经失去了原始文档矢量化的一些微妙之处。整个主题的各个方面可能比平均值所代表的要多。

更具体地说,假设您的原始“相关语料库”有两个文档集群,因为实际上有两个主要的子主题由不同的重要特征组表示。稍后在进行分类时,测试文档可以单独匹配这些集群中的任何一个 - 再次因为它们接近两个子主题之一。在这种情况下,通过对整个“相关语料库”进行平均,您最终会得到一个位于这两个集群之间的单个文档,但不能准确地表示任何一个。因此,测试演示文稿可能根本不匹配 - 取决于分类技术。

我认为如果不在适当的特定语料库上进行试验就很难说。

无论有效性如何,以下是如何实现它。

请注意,您还可以使用 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 ]]
于 2018-11-17T01:19:33.560 回答