Выберите лучшие n функций TFIDF для данного документа - PullRequest
0 голосов
/ 24 октября 2018

Я работаю с разреженными матрицами 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>

Я попытался следовать примеру в этом сообщении , хотя моя цель не в том, чтобы отобразить функции, а просто выбратьtop 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, упорядоченные по термину"частота по всему корпусу"(документы здесь ) и что я хочу, это ранжирование на уровне документа.

РЕДАКТИРОВАТЬ: Интересно, еслиЛучший способ решить эту проблему - установить значения всех функций , за исключением 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) и установить всезначения до 0, за исключением n лучших показателей в tops.

Здесь есть сообщение здесь , объясняющее, как работать с csr_matrix, но яЯ не уверен, как применить это на практике, чтобы получить то, что я хочу.

Ответы [ 3 ]

0 голосов
/ 25 октября 2018

Вы можете разбить ваш массивный массив на несколько, чтобы освободить память.Затем просто объедините их

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)
0 голосов
/ 25 мая 2019
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'])

Параметр max_features , переданный в TfidfVectorizer , выберет 50 лучших функций, упорядоченных по их значению TFIDF .Вы можете просмотреть функции, используя:

print(vect.get_feature_names())
0 голосов
/ 24 октября 2018

Как вы упомянули, параметр max_features в TfidfVectorizer является одним из способов выбора функций.

Если вы ищете альтернативный способ, который учитывает отношение к целевой переменной, вы можете использоватьsklearn's 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)])
...