web-dev-qa-db-ja.com

特定のドキュメントの上位n個のTFIDF機能を選択します

私はドキュメント分類のためにTFIDFスパース行列を使用しており、各ドキュメントの上位n(たとえば50)の用語のみを保持したいと考えています(TFIDFスコアでランク付けされています)。以下の[〜#〜] edit [〜#〜]を参照してください。

_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-最高の特徴に対応する実際の単語を視覚化するため)に使用するため、特徴インデックスは同じままである必要があります。 )。

同僚が、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_)をループし、topsn最適なインデックスを除くすべての値を0に設定します。

Csr_matrixの操作方法を説明する投稿 here がありますが、これを実践して必要なものを取得する方法がわかりません。

6
ongenz

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)
1
J. Doe