Термінова частота / обернена частота документа (TF / IDF): зважування


12

У мене є набір даних, який представляє 1000 документів і всі слова, які містяться в ньому. Отже, рядки представляють документи, а стовпці - слова. Так, наприклад, значення у комірці означає час, коли виникає в документі . Тепер я повинен знайти "вагу" слів, використовуючи метод tf / idf, але я фактично не знаю, як це зробити. Може хтось, будь ласка, допоможе мені?j i(i,j)ji


Статистика tf-idf-статистики для вилучення ключових слів - joyofdata.de/blog/tf-idf-statistic-keyword-extraction
Raffael

Відповіді:


12

У Вікіпедії є хороша стаття на цю тему, доповнена формулами. Значення у вашій матриці - це термін "частоти". Вам просто потрібно знайти idf: (log((total documents)/(number of docs with the term))і помножити 2 значення.

У R ви можете зробити так:

set.seed(42)
d <- data.frame(w=sample(LETTERS, 50, replace=TRUE))
d <- model.matrix(~0+w, data=d)

tf <- d
idf <- log(nrow(d)/colSums(d))
tfidf <- d

for(word in names(idf)){
  tfidf[,word] <- tf[,word] * idf[word]
}

Ось набори даних:

> colSums(d)
wA wC wD wF wG wH wJ wK wL wM wN wO wP wQ wR wS wT wV wX wY wZ 
 3  1  3  1  1  1  1  2  4  2  2  1  1  3  2  2  2  4  5  5  4 
> head(d)
  wA wC wD wF wG wH wJ wK wL wM wN wO wP wQ wR wS wT wV wX wY wZ
1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0
2  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0
3  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
4  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0
5  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0
6  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0
> head(round(tfidf, 2))
  wA wC wD wF wG   wH wJ wK wL wM   wN wO wP   wQ wR wS wT   wV  wX  wY wZ
1  0  0  0  0  0 0.00  0  0  0  0 0.00  0  0 0.00  0  0  0 0.00 2.3 0.0  0
2  0  0  0  0  0 0.00  0  0  0  0 0.00  0  0 0.00  0  0  0 0.00 0.0 2.3  0
3  0  0  0  0  0 3.91  0  0  0  0 0.00  0  0 0.00  0  0  0 0.00 0.0 0.0  0
4  0  0  0  0  0 0.00  0  0  0  0 0.00  0  0 0.00  0  0  0 2.53 0.0 0.0  0
5  0  0  0  0  0 0.00  0  0  0  0 0.00  0  0 2.81  0  0  0 0.00 0.0 0.0  0
6  0  0  0  0  0 0.00  0  0  0  0 3.22  0  0 0.00  0  0  0 0.00 0.0 0.0  0

Ви також можете переглянути idf кожного терміна:

> log(nrow(d)/colSums(d))
      wA       wC       wD       wF       wG       wH       wJ       wK       wL       wM       wN       wO       wP       wQ       wR       wS       wT       wV       wX       wY       wZ 
2.813411 3.912023 2.813411 3.912023 3.912023 3.912023 3.912023 3.218876 2.525729 3.218876 3.218876 3.912023 3.912023 2.813411 3.218876 3.218876 3.218876 2.525729 2.302585 2.302585 2.525729 

Спасибі за вашу допомогу! Але чи можна отримати якесь значення для кожного слова, яке представляє деяку вагомість (замість цілої матриці)? Тепер у нас є ціла матриця ваг. Я роблю деякий вибір функції і хочу використовувати tf / idf як метод фільтра ...
ABC

@ABC tf-idf за визначенням відноситься до повної матриці ваг. Можливо, вас цікавлять самі ваги idf, які ви могли б отримати log((number of docs)/(number of docs containing the term)). Ви також можете просто відфільтрувати нечасті терміни.
Зак

Дуже ясно! Дуже цінується.
ABC

13

є пакет tm (видобуток тексту) http://cran.r-project.org/web/packages/tm/index.html, який повинен робити саме те, що вам потрібно:

#read 1000 txt articles from directory data/txt
corpus  <-Corpus(DirSource("data/txt"), readerControl = list(blank.lines.skip=TRUE));
#some preprocessing
corpus <- tm_map(corpus, removeWords, stopwords("english"))
corpus <- tm_map(corpus, stripWhitespace)
corpus <- tm_map(corpus, stemDocument, language="english")
#creating term matrix with TF-IDF weighting
terms <-DocumentTermMatrix(corpus,control = list(weighting = function(x) weightTfIdf(x, normalize = FALSE)))

#or compute cosine distance among documents
dissimilarity(tdm, method = "cosine")

R - функціональна мова, тому читання коду може бути складним (наприклад, x у термінах)


2

У вашому коді помилка: colSums обчислює кількість виникнення в корпусі, а не кількість текстів зі словом.

Версія, що обчислює такі, була б:

tfidf=function(mat){
  tf <- mat
  id=function(col){sum(!col==0)}
  idf <- log(nrow(mat)/apply(mat, 2, id))
  tfidf <- mat
  for(word in names(idf)){tfidf[,word] <- tf[,word] * idf[word]}
  return(tfidf)
  }


1

Я запізнююсь на цю вечірку, але я грався з поняттями tc-idf (я хочу наголосити на слові "концепція", тому що я не слідкував за жодними книгами для фактичних розрахунків; тому вони можуть бути дещо відключені, і, безумовно, легше виконується з такими пакунками, як {tm: Text Mining Package}, як було сказано), і я думаю, що я отримав, можливо, пов'язане з цим питанням, або, в будь-якому випадку, це може бути хорошим місцем для його опублікування.


SET-UP: У мене є корпус з 5довгих пунктів , які вибираються зі друкованих засобів масової інформації, text 1через 5такі , як The New York Times . Нібито, це дуже маленьке «тіло», крихітна бібліотека, так би мовити, але записи в цій «цифровій» бібліотеці не випадкові: перший і п’ятий записи стосуються футболу (або «футболу» для «соціального клубу» (?) тут), а точніше про найбільшу команду сьогодні. Так, наприклад, text 1починається як ...

"Протягом останніх дев'яти років Мессі привів ФК" Барселона "до національних та міжнародних титулів, побиваючи окремі рекорди способами, які здаються потойбічним ..."

Дуже хороша! З іншого боку, ви напевно хочете пропустити вміст у трьох записах між ними. Ось приклад ( text 2):

"Протягом декількох годин по всьому Техасу, пан Рубіо припустив, що містер Трамп мочився в штанах і використовував нелегальних іммігрантів, щоб виправити його невпинні повідомлення в Twitter ..."

Тож що робити, щоб за всяку ціну уникнути "серфінгу" від " text 1до" text 2, продовжуючи радіти літературі про всемогутній ФК "Барселона" text 5?


TC-IDF: Я виділив слова в кожному textна довгі вектори. Потім підраховували частоту кожного слова, створюючи п’ять векторів (по одному на кожний text), у яких textпідраховували лише слова, що зустрічаються у відповідних - усі інші слова, що належать іншим texts, оцінювались в нуль. Наприклад, у першому фрагменті text 1його вектору було б число 1 для слова "Мессі", а "Трамп" - 0. Це частина ТС .

Частина idf також була розрахована окремо для кожного text, і в результаті вийшло 5 "векторів" (я думаю, я розглядав їх як кадри даних), що містять логарифмічні перетворення підрахунків документів (на жаль, від нуля до п'яти, враховуючи нашу маленьку бібліотеку ), що містить задане слово як у:

01log(No. documents1+No. docs containing a word) . Кількість документів дорівнює 5. Ось частина, яка може відповідати ОП: для кожного розрахунку idf textрозглянутий документ був виключений з підрахунку . Але якщо слово з'явилося у всіх документах, її IDF був ще завдяки в знаменнику - наприклад , слова «в» мав значення 0, так як він присутній у всіх с.01text

Запис мудра множенням для кожного було значенням кожного слова для кожного з елементів бібліотеки - локально поширені, глобально рідкісні слова .tc×idftext


ПОРІВНЯННЯ: Тепер справа в тому, щоб виконати крапкові продукти серед цих "векторів важливості слова".

Передбачувано, точковий твір text 1з " text 5було" 13.42645, а text 1v. text2Був лише 2.511799.

Незграбний код R (нічого не наслідувати) знаходиться тут .

Знову ж таки, це дуже рудиментарне моделювання, але я думаю, що це дуже графічно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.