从 TFIDFVectorizer / CountVectorizer 减少词向量的维度

Reduce Dimension of word-vectors from TFIDFVectorizer / CountVectorizer

我想使用 TFIDFVectorizer (or CountVectorizer followed by TFIDFTransformer) 来获取我的术语的矢量表示。这意味着,我想要一个向量来表示文档是特征的术语。这只是由 TFIDFVectorizer 创建的 TF-IDF 矩阵的转置。

>>> vectorizer = TfidfVectorizer()
>>> model = vectorizer.fit_transform(corpus)
>>> model.transpose()

但是,我有 800k 个文档,这意味着我的词向量非常稀疏而且非常大(800k 维)。 CountVectorizer 中的标志 max_features 将完全满足我的要求。我可以指定一个维度,CountVectorizer 会尝试将所有信息放入该维度。不幸的是,这个选项是针对文档向量而不是词汇表中的术语。因此,它减少了我的词汇量,因为术语是特征。

有没有办法反其道而行之?比如,在 TFIDFVectorizer 对象开始切割和标准化所有内容之前对其执行转置?如果存在这种方法,我该怎么做?像这样:

>>> countVectorizer = CountVectorizer(input='filename', max_features=300, transpose=True)

我一直在寻找这种方法,但每个指南、代码示例,无论是在谈论文档 TF-IDF 向量而不是术语向量。 提前致谢!

我不知道有任何直接的方法可以做到这一点,但让我提出一种实现方法。

您正在尝试将语料库中的每个术语表示为一个向量,该向量使用语料库中的文档作为其组成特征。因为文档的数量(在你的案例中是特征)非常大,你想以类似于 max_features 所做的方式限制它们。

根据CountVectorizer用户指南(与 TfidfVectorizer 相同):

max_features int, default=None

If not None, build a vocabulary that only consider the top max_features ordered by term frequency across the corpus.

以类似的方式,您希望将排名靠前的文档按“词条出现频率”排序,这听起来可能令人困惑。这可以简单地改写为“保留那些包含最独特术语的文档”。

我能想到的一种方法是使用 inverse_transform 执行以下步骤:

    vectorizer = TfidfVectorizer()
    model = vectorizer.fit_transform(corpus)
    
    # We use the inverse_transform which returns the 
    # terms per document with nonzero entries
    inverse_model = vectorizer.inverse_transform(model)
    
    # Each line in the inverse model corresponds to a document 
    # and contains a list of feature names (the terms).
    # As we want to rank the documents we tranform the list 
    # of feature names to a number of features
    # that each document is represented by.
    inverse_model_count = list(map(lambda doc_vec: len(doc_vec), inverse_model))
    
    # As we are going to sort the list, we need to keep track of the 
    # document id (its index in the corpus), so we create tuples with 
    # the list index of each item before we sort the list.
    inverse_model_count_tuples = list(zip(range(len(inverse_model_count)),
                                          inverse_model_count))
    
    # Then we sort the list by the count of terms 
    # in each document (the second component)
    max_features = 100
    top_documents_tuples = sorted(inverse_model_count_tuples, 
                                  key=lambda item: item[1], 
                                  reverse=True)[:max_features]
    
    # We are interested only in the document ids (the first tuple component)
    top_documents, _ = zip(*top_documents_tuples)
    
    # Having the top_documents ids we can slice the initial model 
    # to keep only the documents indicated by the top_documents list
    reduced_model = model[top_documents]

请注意,此方法仅考虑每个文档的术语数,无论它们的计数 (CountVectorizer) 或权重 (TfidfVectorizer) 是多少。 如果这种方法的方向对你来说是可以接受的,那么用更多的代码也可以考虑到术语的数量或权重。

希望对您有所帮助!