首页 > 解决方案 > 从 TFIDFVectorizer / CountVectorizer 减少词向量的维度

问题描述

我想使用TFIDFVectorizer(或CountVectorizer后跟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 向量而不是术语向量。非常感谢您!

标签: pythonscikit-learntf-idftfidfvectorizercountvectorizer

解决方案


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

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

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

max_features int,默认=无

如果不是 None,则构建一个仅考虑按语料库中的词频排序的最高 max_features 的词汇表。

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

我能想到的一种方法是使用 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) 是多少。如果您可以接受这种方法的方向,则可以使用更多代码来考虑术语的计数或权重。

我希望这有帮助!


推荐阅读