Вычислить оценку слова TF-IDF с соответствующим и случайным корпусом - PullRequest
0 голосов
/ 12 ноября 2018

Учитывая совокупность соответствующих документов (CORPUS) и совокупность случайных документов (ran_CORPUS), я хочу вычислить оценки TF-IDF для всех слов в CORPUS, используя ran_CORPUS в качестве базовой линии. В моем проекте у ran_CORPUS примерно в 10 раз больше документов, чем у CORPUS.

CORPUS = ['this is a relevant document',
          'this one is a relevant text too']
ran_CORPUS = ['the sky is blue',
              'my cat has a furry tail']

Мой план состоит в том, чтобы нормализовать документы, сделать все документы в CORPUS одним документом (теперь CORPUS представляет собой список с одним длинным строковым элементом). К CORPUS я добавляю все документы ran_CORPUS. Используя sklearn's TfidfTransformer, я бы тогда вычислял матрицу TF-IDF для корпуса (состоящего теперь из CORPUS и ran_CORPUS). И, наконец, выберите первую строку этого CORPUS, чтобы получить оценки TF-IDF для моего первоначального соответствующего CORPUS.

Кто-нибудь знает, может ли этот подход работать и существует ли простой способ его кодирования?

1 Ответ

0 голосов
/ 17 ноября 2018

Когда вы говорите «может ли этот подход работать», я предполагаю, что вы подразумеваете, что объединение всех соответствующих документов в один и векторизация представляют собой действительную модель. Я думаю, это зависит от того, что вы собираетесь делать с этой моделью.

Я не большой математик, но я представляю, что это похоже на усреднение баллов для всех ваших документов в одном векторном пространстве, поэтому вы потеряли часть формы пространства, которое исходное векторное пространство занимало отдельное лицо. соответствующие документы. Итак, вы пытались сделать «мастер» или «прототип» документа, который предназначен для представления темы?

Если вы собираетесь выполнить что-то вроде сопоставления сходства с тестовыми документами или классификации по дистанционному сравнению, то вы, возможно, утратили некоторую тонкость векторизации исходных документов. В общей теме может быть больше аспектов, чем представляют собой средние значения.

Точнее, представьте, что ваш исходный «соответствующий корпус» состоит из двух блоков документов, потому что на самом деле есть две основные подтемы, представленные различными группами важных функций. Позже, выполняя классификацию, тестовые документы могут соответствовать каждому из этих кластеров индивидуально - опять же, потому что они близки к одной из двух подтем. Усредняя весь «релевантный корпус» в этом случае, вы получите один документ, который находится посередине между этими двумя кластерами, но точно не представляет ни того, ни другого. Поэтому презентации теста могут не совпадать вообще - в зависимости от метода классификации.

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

Независимо от действительности, ниже показано, как это может быть реализовано.

Обратите внимание, что вы также можете использовать TfidfVectorizer для объединения шагов векторизации и Tfidf'ing в одно. Результаты не всегда одинаковы, но в данном случае они совпадают.

Кроме того, вы говорите, что нормализуйте документы - обычно вы можете нормализовать векторное представление перед подачей в алгоритм классификации, который требует нормализованного распределения (такого как SVM). Тем не менее, я думаю, что TFIDF естественным образом нормализуется, поэтому он, похоже, не оказывает никакого дополнительного влияния (я могу ошибаться).

import logging
from sklearn import preprocessing
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer, TfidfTransformer

CORPUS = ['this is a relevant document',
          'this one is a relevant text too']
ran_CORPUS = ['the sky is blue',
              'my cat has a furry tail']

doc_CORPUS = ' '.join([str(x) for x in CORPUS])
ran_CORPUS.append(doc_CORPUS)

count_vect = CountVectorizer()
X_counts = count_vect.fit_transform(ran_CORPUS)
tfidf_transformer = TfidfTransformer()
X_tfidf = tfidf_transformer.fit_transform(X_counts)

logging.debug("\nCount + TdidfTransform \n%s" % X_tfidf.toarray())

# or do it in one pass with TfidfVectorizer
vectorizer = TfidfVectorizer()
X_tfidf = vectorizer.fit_transform(ran_CORPUS)

logging.debug("\nTdidfVectoriser \n%s" % X_tfidf.toarray())

# normalising doesn't achieve much as tfidf is already normalised.
normalizer = preprocessing.Normalizer() 
X_tfidf = normalizer.transform(X_tfidf)
logging.debug("\nNormalised:\n%s" % X_tfidf.toarray())


Count + TdidfTransform 
[[0.52863461 0.         0.         0.         0.         0.40204024
  0.         0.         0.         0.52863461 0.         0.
  0.52863461 0.         0.        ]
 [0.         0.4472136  0.         0.4472136  0.4472136  0.
  0.4472136  0.         0.         0.         0.4472136  0.
  0.         0.         0.        ]
 [0.         0.         0.2643173  0.         0.         0.40204024
  0.         0.2643173  0.52863461 0.         0.         0.2643173
  0.         0.52863461 0.2643173 ]]

TdidfVectoriser 
[[0.52863461 0.         0.         0.         0.         0.40204024
  0.         0.         0.         0.52863461 0.         0.
  0.52863461 0.         0.        ]
 [0.         0.4472136  0.         0.4472136  0.4472136  0.
  0.4472136  0.         0.         0.         0.4472136  0.
  0.         0.         0.        ]
 [0.         0.         0.2643173  0.         0.         0.40204024
  0.         0.2643173  0.52863461 0.         0.         0.2643173
  0.         0.52863461 0.2643173 ]]

Normalised:
[[0.52863461 0.         0.         0.         0.         0.40204024
  0.         0.         0.         0.52863461 0.         0.
  0.52863461 0.         0.        ]
 [0.         0.4472136  0.         0.4472136  0.4472136  0.
  0.4472136  0.         0.         0.         0.4472136  0.
  0.         0.         0.        ]
 [0.         0.         0.2643173  0.         0.         0.40204024
  0.         0.2643173  0.52863461 0.         0.         0.2643173
  0.         0.52863461 0.2643173 ]]
...