Я запускаю TF-IDF Vectorizer от SKLearn, но у меня возникают проблемы при воссоздании значений вручную (чтобы понять, что происходит).
Чтобы добавить некоторый контекст, у меня есть список документов, из которых я извлек именованные объекты (в моих реальных данных это go до 5 граммов, но здесь я ограничил это биграммами). Я только хочу знать оценки TF-IDF для этих значений и думал, что передача этих терминов через параметр vocabulary
сделает это.
Вот некоторые фиктивные данные, аналогичные тем, с которыми я работаю:
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
# list of named entities I want to generate TF-IDF scores for
named_ents = ['boston','america','france','paris','san francisco']
# my list of documents
docs = ['i have never been to boston',
'boston is in america',
'paris is the capitol city of france',
'this sentence has no named entities included',
'i have been to san francisco and paris']
# find the max nGram in the named entity vocabulary
ne_vocab_split = [len(word.split()) for word in named_ents]
max_ngram = max(ne_vocab_split)
tfidf = TfidfVectorizer(vocabulary = named_ents, stop_words = None, ngram_range=(1,max_ngram))
tfidf_vector = tfidf.fit_transform(docs)
output = pd.DataFrame(tfidf_vector.T.todense(), index=named_ents, columns=docs)
Примечание: Я знаю, что стоп-слова удаляются по умолчанию, но некоторые из названных сущностей в моем фактическом наборе данных включают фразы, такие как «государственный департамент». Таким образом, они были сохранены здесь.
Здесь мне нужна помощь. Я понимаю, что мы рассчитываем TF-IDF следующим образом:
TF: термин частоты: который согласно рекомендациям SKlearn является "числом раз в данном документе встречается термин "
IDF: частота обратных документов: натуральный логарифм с соотношением 1 + количество документов и 1 + количество документов, содержащих срок. Согласно тем же рекомендациям в ссылке, результирующее значение имеет добавленную 1, чтобы предотвратить деление на ноль.
Затем мы умножаем TF на IDF , чтобы получить общее TF-IDF для данного термина в данном документе.
Пример
Давайте возьмем первый столбец в качестве примера, который имеет только одну именованную сущность 'Бостон', и согласно приведенному выше коду имеет TF-IDF для первого документа 1. Однако, когда я работаю с этим вручную, я получаю следующее:
TF = 1
IDF = log-e(1+total docs / 1+docs with 'boston') + 1
' ' = log-e(1+5 / 1+2) + 1
' ' = log-e(6 / 3) + 1
' ' = log-e(2) + 1
' ' = 0.69314 + 1
' ' = 1.69314
TF-IDF = 1 * 1.69314 = 1.69314 (not 1)
Возможно, я что-то упускаю в документации, где говорится, что оценки ограничены 1, но я не могу понять, где я ошибся. Кроме того, с учетом приведенных выше расчетов не должно быть различий между оценкой Бостона в первом столбце и во втором столбце, поскольку термин появляется в каждом документе только один раз.
Редактировать После публикации вопроса я подумал, что, возможно, термин «частота» рассчитывался как отношение либо количества символов в документе, либо количества именованных объектов в документе. Например, во втором документе SKlearn генерирует для Бостона оценку 0.627914
. Если я вычисляю TF как отношение токенов = 'boston' (1): все униграммовые токены (4), я получаю TF 0.25
, который при подаче заявки на TF-IDF возвращает чуть более 0.147
,
Точно так же, когда я использую соотношение токенов = 'boston' (1): все токены NE (2) и применяю TF-IDF, я получаю оценку 0.846
. Ясно, что я где-то ошибаюсь.