【问题标题】:why does tfidf object takes so much space?为什么 tfidf 对象占用这么多空间?
【发布时间】:2019-12-14 09:47:57
【问题描述】:

当我执行时,我有大约 100,000 篇长文章,总共大约 5GB 的文本

TfidfVectorizer

它从 sklearn 构建了一个 6GB 的模型。这怎么可能?不是只需要存储那4000字的文档频率,那4000字是什么吗?我猜 TfidfVectorizer 会为每个文档存储这样的 4000 维向量。是否有可能以某种方式错误设置了某些设置?

【问题讨论】:

    标签: tf-idf tfidfvectorizer


    【解决方案1】:

    我知道有一个答案,但需要为其他人考虑一些额外的信息。当您直接腌制 TFIDFVectorizer 时,您还保存了向量器的停用词属性,但在词汇表建立后就没有必要了。在我们的一个模型中,词汇表中有 3000 个单词,但保存的模型占用了 250MB 空间,因此检查模型我们看到 1000 万个停用词也与模型一起存储。然后我们在TfidfVectorizer看到了如下警告

    “stop_words_ 属性在酸洗时会变大并增加模型大小。此属性仅用于自省,可以使用 delattr 安全删除或在酸洗前设置为 None。”

    应用它显着减小了我们的模型大小。

    【讨论】:

      【解决方案2】:

      TF-IDF 矩阵形状是 (number_of_documents, number_of_unique_words)。因此,对于每个文档,您都会从数据集中获得每个单词的特征。对于大型数据集,它可能会变得臃肿。

      在你的情况下 (100000 (docs) * 4000 (words) * 4 (np.float64 bytes))/1024**3 ~ 1.5 Gb

      此外,默认情况下,Scipy TfidfVectorizer 尝试使用稀疏矩阵 (scipy.sparse.csr.csr_matrix) 对其进行补偿。即使对于长文档,矩阵也往往包含很多零。所以通常是小于原始尺寸的订单。如果我是正确的,它应该低于 1.5 GB。

      这就是问题所在。你的模型中真的只有 4000 字吗(由TfidfVectorizer(max_features=4000) 控制?

      如果您不关心单个词的频率,您可以使用 PCA 或其他技术来减小向量大小。

          dense_matrix = tf_idf_matrix.todense()
          components_number = 300
          reduced_data = PCA(n_components=300).fit_transform(dense_matrix)
      

      或者你可以使用类似 doc2vec 的东西。 https://radimrehurek.com/gensim/models/doc2vec.html

      使用它,您将获得形状的矩阵(number_of_documents,embedding_size)。嵌入大小通常在(100 到 600)之间。您可以使用 dbow_words 参数训练 doc2vec 模型,而无需存储单个词向量。

      如果你关心单个词的特征,我认为唯一合理的解决方案是减少词的数量。

      相关的stackoverflow帖子:

      ----关于维度缩减

      How do i visualize data points of tf-idf vectors for kmeans clustering?

      ----关于使用生成器训练 TFIDF

      Sklearn TFIDF on large corpus of documents

      How to get tf-idf matrix of a large size corpus, where features are pre-specified?

      tf-idf on a somewhat large (65k) amount of text files


      模型本身不应该占用太多空间。我想如果TfidfVectorizer tokenizerpreprocessor 属性中有一些重物是可能的。

      class Tokenizer: 
              def __init__(self): 
                  self.s = np.random.uniform(0,1, size=(10000,10000)) 
              def tokenizer(self, text): 
                  text = text.lower().split() 
                  return text
          tokenizer = Tokenizer()                                                                                                                                                   
          vectorizer = TfidfVectorizer(tokenizer=tokenizer.tokenizer)
          pickle.dump(vectorizer, open("vectorizer.pcl", "wb"))
      

      酸洗后会占用700多mb。

      【讨论】:

      • 谢谢!我还有一个问题。我实际上的意思是模型尺寸很大,而不是转换后的 x。你的意思是模型本身会存储我所有输入数据的转换后的 x 吗?有没有可能让它不存储这么大的东西。我通常只是采用模型并转换新数据。所以我真的不想存储转换后的 x。
      • 对不起。我误解了你的问题。 TfidfVectorizer 实例仅存储自己的 vectorizer.vocabulary_ 和 vectorizer.idf_,第一个存储单词计数字典,第二个存储分别带有 idfs 的 numpy 数组。即使对于大型数据集,它们都需要
      • 我明白了。感谢您的回复!我的 tfidf 正在存储 ngrams = (1,2)、大量文档(可能有大量拼写错误)。它是否存储所有可能导致大小变大的二元组?
      • 对不起,我不太明白。你的意思是你计算二元组的tfidf吗?即使在这种情况下,TfidfVectorizer 也不应该占用太多空间。也许,你能提供你调用 Tfidf-vectorizer 的代码吗?
      猜你喜欢
      • 1970-01-01
      • 2013-12-03
      • 2013-01-01
      • 2018-08-20
      • 1970-01-01
      • 2012-02-12
      • 2023-01-03
      • 2020-03-21
      • 2021-10-06
      相关资源
      最近更新 更多