TF (Term Frequency) -IDF (Inverse Document Frequency) с нуля на Python.
Создание модели TF-IDF с нуля
В этой статье я объясню, как реализовать технику tf-idf в python с нуля, эта техника используется для поиска смысла предложений, состоящих из слов, и устраняет неспособность техники мешка слов, которая хороша для классификации текста или для помощи машинное чтение слов в числах.
Оглавление:
- Терминология.
- Частота сроков (TF).
- Документ Частота.
- Частота обратного документа.
- Реализация на Python.
1 - Терминология:
- t - термин (слово)
- d - документ (набор слов)
- N - количество корпусов
- корпус - полный набор документов
2-периодичность (TF):
Предположим, у нас есть набор текстовых документов на английском языке, и мы хотим оценить, какой документ наиболее релевантен запросу «Наука о данных - это круто!» Самый простой способ начать - удалить документы, которые не содержат всех трех слов «Данные», «есть», «Наука» и «Круто», но при этом остается много документов. Чтобы различать их, мы можем подсчитать, сколько раз каждый термин встречается в каждом документе; количество раз, когда термин встречается в документе, называется его периодичностью термина.
Вес термина, встречающегося в документе, просто пропорционален частоте использования термина.
Формула:
tf (t, d) = количество t в d / количество слов в d
3 -Частота документов:
Этот измеряет важность документа во всем корпусе, это очень похоже на TF. Единственное отличие состоит в том, что TF - это частотомер для термина t в документе d, где DF - это количество появлений термина t в наборе документов N. Другими словами, DF - это количество документы, в которых присутствует слово. Мы рассматриваем одно вхождение, если термин присутствует в документе хотя бы один раз, нам не нужно знать, сколько раз этот термин присутствует.
df (t) = появление t в документах
4.Частота обратного документа (IDF):
При вычислении TF все термины считаются одинаково важными. Однако известно, что определенные термины, такие как «есть», «из» и «то», могут встречаться много раз, но не имеют большого значения. Таким образом, нам нужно уменьшить частые термины и увеличить количество редких, вычисляя IDF, включается коэффициент обратной частоты документов, который уменьшает вес терминов, которые очень часто встречаются в наборе документов, и увеличивает масса терминов, которые встречаются редко.
IDF - это величина, обратная частоте документа, которая измеряет информативность термина t. Когда мы вычисляем IDF, он будет очень низким для наиболее часто встречающихся слов, таких как стоп-слова (потому что стоп-слова, такие как «есть», присутствуют почти во всех документах, и N / df даст очень низкое значение этому слову. ). Это, наконец, дает то, что мы хотим, относительный вес.
idf (t) = N / df
Теперь есть несколько других проблем с IDF, в случае большого корпуса, скажем 100000000, значение IDF взрывается, чтобы избежать эффекта, который мы берем в журнал idf.
Во время запроса, когда встречается слово, которого нет в словаре, df будет 0. Поскольку мы не можем делить на 0, мы сглаживаем значение, добавляя 1 к знаменателю.
вот окончательная формула:
Формула:
idf (t) = log (N / (df + 1))
Теперь tf-idf является правильной мерой для оценки того, насколько важно слово для документа в коллекции или корпусе. Существует много различных вариантов TF-IDF, но пока давайте сосредоточимся на этой базовой версии.
Формула:
tf-idf (t, d) = tf (t, d) * log (N / (df + 1))
5 -Внедрение TF-IDF в Python с нуля:
Чтобы создать TF-IDF с нуля на Python, представьте себе эти два предложения из другого документа:
first_sentence: «Наука о данных - самая сексуальная работа 21 века».
second_sentence: «Машинное обучение - ключ к науке о данных».
На первом этапе мы должны создать функцию TF для расчета общей частоты встречаемости слов для всех документов. Вот коды ниже:
Сначала, как обычно, необходимо импортировать необходимые библиотеки:
import pandas as pd import sklearn as sk import math
Итак, давайте загрузим наши предложения и объединим их в единый набор:
first_sentence = "Data Science is the sexiest job of the 21st century" second_sentence = "machine learning is the key for data science" #split so each word have their own string first_sentence = first_sentence.split(" ") second_sentence = second_sentence.split(" ")#join them to remove common duplicate words total= set(first_sentence).union(set(second_sentence)) print(total)
Выход :
{'data', 'Science', 'job', 'sexiest', 'the', 'for', 'science', 'machine', 'of', 'is', 'learning', '21st', 'key', 'Data', 'century'}
Теперь давайте добавим способ подсчета слов с помощью словарной пары ключ-значение для обоих предложений:
wordDictA = dict.fromkeys(total, 0) wordDictB = dict.fromkeys(total, 0) for word in first_sentence: wordDictA[word]+=1 for word in second_sentence: wordDictB[word]+=1
Теперь мы помещаем их в фрейм данных и затем просматриваем результат:
pd.DataFrame([wordDictA, wordDictB])
Нет, давайте напишем функцию TF:
def computeTF(wordDict, doc): tfDict = {} corpusCount = len(doc) for word, count in wordDict.items(): tfDict[word] = count/float(corpusCount) return(tfDict) #running our sentences through the tf function: tfFirst = computeTF(wordDictA, first_sentence) tfSecond = computeTF(wordDictB, second_sentence) #Converting to dataframe for visualization tf = pd.DataFrame([tfFirst, tfSecond])
и это ожидаемый результат:
Это все для формулы TF, просто я хочу поговорить о стоп-словах, которые мы должны удалить, потому что они являются наиболее часто встречающимися словами, которые не придают никакого дополнительного значения вектору документа. Фактически, их удаление увеличит эффективность вычислений и использования пространства .
В библиотеке nltk есть метод загрузки стоп-слов, поэтому вместо явного упоминания всех стоп-слов мы можем просто использовать библиотеку nltk и перебирать все слова и удалять стоп-слова. Есть много эффективных способов сделать это, но я просто приведу простой метод.
это образец стоп-слов на английском языке:
и это простой код для загрузки стоп-слов и их удаления.
import nltk nltk.download('stopwords') from nltk.corpus import stopwords stop_words = set(stopwords.words('english')) filtered_sentence = [w for w in wordDictA if not w in stop_words] print(filtered_sentence)
выход :
['data', 'Science', 'job', 'sexiest', 'science', 'machine', 'learning', '21st', 'key', 'Data', 'century']
И теперь, когда мы закончили раздел TF, мы переходим к части IDF:
def computeIDF(docList): idfDict = {} N = len(docList) idfDict = dict.fromkeys(docList[0].keys(), 0) for word, val in idfDict.items(): idfDict[word] = math.log10(N / (float(val) + 1)) return(idfDict) #inputing our sentences in the log file idfs = computeIDF([wordDictA, wordDictB])
и теперь мы реализуем формулу idf, давайте закончим с вычислением TFIDF
def computeTFIDF(tfBow, idfs): tfidf = {} for word, val in tfBow.items(): tfidf[word] = val*idfs[word] return(tfidf) #running our two sentences through the IDF: idfFirst = computeTFIDF(tfFirst, idfs) idfSecond = computeTFIDF(tfSecond, idfs) #putting it in a dataframe idf= pd.DataFrame([idfFirst, idfSecond]) print(idf)
выход :
Это была большая работа. Но полезно знать, если в будущем вас попросят кодировать TF-IDF с нуля. Однако это можно сделать намного проще благодаря библиотеке sklearn. Давайте посмотрим на пример из них ниже:
#first step is to import the library from sklearn.feature_extraction.text import TfidfVectorizer #for the sentence, make sure all words are lowercase or you will run #into error. for simplicity, I just made the same sentence all #lowercase firstV= "Data Science is the sexiest job of the 21st century" secondV= "machine learning is the key for data science" #calling the TfidfVectorizer vectorize= TfidfVectorizer() #fitting the model and passing our sentences right away: response= vectorize.fit_transform([firstV, secondV])
и это ожидаемый результат:
Резюме :
В этом посте мы собираемся объяснить, как использовать Python и технику обработки естественного языка (NLP), известную как Term Frequency - Inverse Document Frequency (tf-idf) для обобщения документов.
Мы будем использовать sklearn вместе с nltk для выполнения этой задачи.
Помните, что вы можете найти полностью рабочий код в моем репозитории на github здесь.
Спасибо за чтение, и я буду рад обсудить любые вопросы или исправления, которые могут у вас возникнуть :) Найдите меня в LinkedIn, если вы хотите обсудить машинное обучение или что-то еще.