用相关和随机语料库计算TF-IDF单词分数

时间:2018-11-12 08:50:08

标签: python-3.x scikit-learn nlp tf-idf natural-language-processing

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

有人知道这种方法是否可行,是否有简单的编码方法?

1 个答案:

答案 0 :(得分: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 ]]