【问题标题】:Select top n TFIDF features for a given document为给定文档选择前 n 个 TFIDF 特征
【发布时间】:2019-03-29 01:38:05
【问题描述】:

我正在使用 TFIDF 稀疏矩阵进行文档分类,并且希望仅保留每个文档的前 n 个(例如 50 个)术语(按 TFIDF 分数排名)。请参阅下面的编辑

import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer

tfidfvectorizer = TfidfVectorizer(analyzer='word', stop_words='english', 
                              token_pattern='[A-Za-z][\w\-]*', max_df=0.25)
n = 50

df = pd.read_pickle('my_df.pickle')
df_t = tfidfvectorizer.fit_transform(df['text'])

df_t
Out[15]: 
<21175x201380 sparse matrix of type '<class 'numpy.float64'>'
    with 6055621 stored elements in Compressed Sparse Row format>

我已经尝试按照this post中的示例进行操作,虽然我的目的不是显示特征,而只是在训练之前为每个文档选择前n个。但是我得到一个内存错误,因为我的数据太大而无法转换为密集矩阵。

df_t_sorted = np.argsort(df_t.toarray()).flatten()[::1][n]
Traceback (most recent call last):

  File "<ipython-input-16-e0a74c393ca5>", line 1, in <module>
    df_t_sorted = np.argsort(df_t.toarray()).flatten()[::1][n]

  File "C:\Users\Me\AppData\Local\Continuum\anaconda3\lib\site-packages\scipy\sparse\compressed.py", line 943, in toarray
    out = self._process_toarray_args(order, out)

  File "C:\Users\Me\AppData\Local\Continuum\anaconda3\lib\site-packages\scipy\sparse\base.py", line 1130, in _process_toarray_args
    return np.zeros(self.shape, dtype=self.dtype, order=order)

MemoryError

有没有什么方法可以在不使用密集表示(即不使用 toarray() 调用)并且不减少比我已经拥有的特征空间更多的情况下(使用 min_df)来做我想做的事情?

注意:max_features 参数不是我想要的,因为它只考虑“按词频在整个语料库中排序的最高 max_features”(文档here),而我想要的是文档级别的排名。

编辑:我想知道解决这个问题的最佳方法是否是将所有特征的值除了 n-best 设置为零。我这样说是因为已经计算了词汇表,所以特征索引必须保持不变,因为我想将它们用于其他目的(例如,可视化对应于 n-best 的实际单词功能)。

一位同事编写了一些代码来检索 n 个排名最高的特征的索引:

n = 2
tops = np.zeros((df_t.shape[0], n), dtype=int) # store the top indices in a new array
for ind in range(df_t.shape[0]):
    tops[ind,] = np.argsort(-df_t[ind].toarray())[0, 0:n] # for each row (i.e. document) sort the (inversed, as argsort is ascending) list and slice top n

但从那里,我需要:

  1. 检索剩余(即排名最低的)索引列表并“就地”修改值,或
  2. 遍历原始矩阵 (df_t) 并将所有值设置为 0,tops 中的 n 个最佳索引除外。

有一个帖子 here 解释如何使用 csr_matrix,但我不确定如何将其付诸实践以获得我想要的。

【问题讨论】:

    标签: python scikit-learn sparse-matrix text-classification tf-idf


    【解决方案1】:

    正如您提到的,TfidfVectorizer 的max_features 参数是选择特征的一种方式。

    如果您正在寻找一种将与目标变量的关系考虑在内的替代方法,您可以使用 sklearn 的SelectKBest。通过设置k=50,这将过滤您的数据以获得最佳功能。用于选择的指标可以指定为参数score_func

    例子:

    from sklearn.feature_selection import SelectKBest
    
    tfidfvectorizer = TfidfVectorizer(analyzer='word', stop_words='english', 
                              token_pattern='[A-Za-z][\w\-]*', max_df=0.25)
    
    df_t = tfidfvectorizer.fit_transform(df['text'])
    df_t_reduced = SelectKBest(k=50).fit_transform(df_t, df['target'])
    

    您也可以将其链接到管道中:

    pipeline = Pipeline([("vectorizer", TfidfVectorizer()),
                         ("feature_reduction", SelectKBest(k=50)),
                         ("classifier", classifier)])
    

    【讨论】:

    • 谢谢你,但是(除非我弄错了)它看起来不像 SelectKBest 是我所追求的,因为它似乎计算了整个语料库中的 k-best 特征(所以文档不包含任何 k 最佳项仅用零表示)。我想要做的是按 TFIDF 分数的降序对每个文档的特征进行排名,然后选择前 k 个特征(比如先排序,然后用列表切片)。
    • @ogenz,对不起,我不明白这是你想要做的。我会留下我的答案,以防它帮助其他人。
    【解决方案2】:

    您可以将 numpy 数组拆分为多个以释放内存。然后将它们连接起来

    import numpy as np
    from sklearn.feature_extraction.text import TfidfVectorizer
    from sklearn.datasets import fetch_20newsgroups
    
    data = fetch_20newsgroups(subset='train').data
    
    tfidfvectorizer = TfidfVectorizer(analyzer='word', stop_words='english', 
                                      token_pattern='[A-Za-z][\w\-]*', max_df=0.25)
    df_t = tfidfvectorizer.fit_transform(data)
    
    n = 10
    
    df_t = tfidfvectorizer.fit_transform(data)
    
    df_top = [np.argsort(df_t[i: i+500, :].toarray(), axis=1)[:, :n]
              for i in range(0, df_t.shape[0], 500)]
    
    np.concatenate(df_top, axis=0).shape
    >> (11314, 10)
    

    【讨论】:

      【解决方案3】:
      from nltk.tokenize import word_tokenize
      from sklearn.feature_extraction.text import TfidfVectorizer
      vect = TfidfVectorizer(tokenizer=word_tokenize,ngram_range=(1,2), binary=True, max_features=50)
      TFIDF=vect.fit_transform(df['processed_cv_data'])
      

      TfidfVectorizer 中传递的 ma​​x_features 参数将挑选出按其词频而非排序的前 50 个特征Tf-idf 分数。 您可以使用以下方式查看功能:

      print(vect.get_feature_names())
      

      【讨论】:

        猜你喜欢
        • 2018-11-22
        • 2017-07-20
        • 2021-05-12
        • 2023-03-14
        • 2014-01-18
        • 2023-04-04
        • 2012-12-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多