Как TfidfVectorizer вычисляет оценки на тестовых данных - PullRequest
3 голосов
/ 16 апреля 2019

В scikit-learn TfidfVectorizer позволяет нам соответствовать тренировочным данным, а затем использовать тот же векторизатор для преобразования наших тестовых данных. Выходные данные преобразования данных поезда представляют собой матрицу, которая представляет оценку tf-idf для каждого слова в данном документе.

Однако как встроенный векторизатор вычисляет оценку для новых входных данных? Я догадался, что либо:

  1. Оценка слова в новом документе, вычисленная путем суммирования оценок одного и того же слова по документам в обучающем наборе.
  2. Новый документ «добавляется» к существующему корпусу, и вычисляются новые оценки.

Я пытался вывести операцию из источника scikit-learn code , но не смог понять это. Это один из вариантов, которые я упоминал ранее, или что-то еще? Пожалуйста, помогите.

1 Ответ

1 голос
/ 17 апреля 2019

Это определенно первое: каждое слово idf (обратная частота документов) рассчитывается только на основе учебных документов. Это имеет смысл, поскольку именно эти значения рассчитываются при вызове fit в векторизаторе. Если бы второй вариант, который вы описали, был верным, мы бы каждый раз по существу заменяли векторизатор, и мы также вызывали бы information leak, поскольку idf из набора тестов использовались бы во время оценки модели.

Помимо этих чисто концептуальных объяснений, вы также можете запустить следующий код, чтобы убедить себя:

from sklearn.feature_extraction.text import TfidfVectorizer
vect = TfidfVectorizer()
x_train = ["We love apples", "We really love bananas"]
vect.fit(x_train)
print(vect.get_feature_names())
>>> ['apples', 'bananas', 'love', 'really', 'we']

x_test = ["We really love pears"]

vectorized = vect.transform(x_test)
print(vectorized.toarray())
>>> array([[0.        , 0.        , 0.50154891, 0.70490949, 0.50154891]])

Следуя рассуждениям о том, как работает методика подбора, вы можете самостоятельно пересчитать эти значения tfidf:

«яблоки» и «бананы», очевидно, имеют значение tfidf, равное 0, потому что они не появляются в x_test. «груши», с другой стороны, не существуют в x_train и поэтому даже не появятся при векторизации. Следовательно, только «любовь», «действительно» и «мы» будут иметь значение tfidf.

Scikit-learn реализует tfidf как log ((1 + n) / (1 + df) + 1) * f, где n - количество документов в обучающем наборе (2 для нас), df количество документов в какое слово появляется только в обучающем наборе , а f - счетчик частоты слова в тестовом наборе. Следовательно:

tfidf_love = (np.log((1+2)/(1+2))+1)*1
tfidf_really = (np.log((1+2)/(1+1))+1)*1
tfidf_we = (np.log((1+2)/(1+2))+1)*1

Затем вам нужно масштабировать эти значения tfidf на расстояние L2 вашего документа:

tfidf_non_scaled = np.array([tfidf_love,tfidf_really,tfidf_we])
tfidf_list = tfidf_non_scaled/sum(tfidf_non_scaled**2)**0.5

print(tfidf_list)
>>> [0.50154891 0.70490949 0.50154891]

Вы можете видеть, что на самом деле мы получаем одинаковые значения, что подтверждает то, как scikit-learn реализовал эту методологию.

...