Terim sıklığı / ters belge sıklığı (TF / IDF): ağırlıklandırma


12

1000 belgeyi ve içinde görünen tüm kelimeleri temsil eden bir veri setim var. Böylece satırlar belgeleri ve sütunlar kelimeleri temsil eder. Yani, örneğin, hücrede değer kez kelimenin açılımı belgede oluşur . Şimdi, tf / idf yöntemini kullanarak kelimelerin 'ağırlıklarını' bulmak zorundayım, ama aslında bunu nasıl yapacağımı bilmiyorum. Birisi bana yardım edebilir mi?j i(i,j)ji


Yanıtlar:


12

Wikipedia'nın konuyla ilgili formüller içeren iyi bir makalesi var . Matrisinizdeki değerler frekans terimleridir. Sadece idf: (log((total documents)/(number of docs with the term))ve birden çok 2 değerini bulmanız gerekir .

R'de bunu şu şekilde yapabilirsiniz:

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]
}

İşte veri kümeleri:

> 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

Ayrıca her terimin idf'sine de bakabilirsiniz:

> 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 

Yardımın için teşekkürler! Fakat her kelime için bir ağırlıklandırma (bir matris yerine) temsil eden bir değer elde etmek mümkün müdür? Şimdi bir ağırlık matrisimiz var. Bazı özellik seçimi yapıyorum ve bir filtre yöntemi olarak tf / idf kullanmak istiyorum ...
ABC

@ABC tf-idf tanım olarak ağırlıkların tam matrisini ifade eder. Belki de sadece idf ağırlıklarıyla ilgileniyorsunuz, ki bu da geçiyordu log((number of docs)/(number of docs containing the term)). Ayrıca sık olmayan terimleri de filtreleyebilirsiniz.
Zach

Çok açık! Gerçekten takdir ediyorum.
ABC

13

tam olarak ihtiyacınız olan tm (metin madenciliği) http://cran.r-project.org/web/packages/tm/index.html paketi vardır :

#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 işlevsel bir dildir, bu nedenle okuma kodu zor olabilir (örneğin, x cinsinden)


2

Kodunuzda bir hata var: colSums, kelimedeki metin sayısını değil, topluluktaki oluşum sayısını hesaplar.

Böyle bir bilgi işlem versiyonu:

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

Bu partiye geç kaldım, ama tc-idf kavramlarıyla oynuyordum ('hesaplama' kelimesini vurgulamak istiyorum çünkü gerçek hesaplamalar için herhangi bir kitap takip etmedim; bu yüzden biraz kapalı olabilirler ve kesinlikle {tm: Text Mining Package}belirtildiği gibi paketlerle daha kolay bir şekilde gerçekleştirilebilir ) ve bence aldım bu soru ile ilgili olabilir veya her halükarda, bunu göndermek için iyi bir yer olabilir.


AYARI: Bir var külliyat içinde 5yazılı basın, alınan uzun paragraflar text 1aracılığıyla 5gibi New York Times . İddiaya göre, bu çok küçük bir "beden", küçük bir kütüphane, tabiri caizse olduğunu ancak bu "dijital" kütüphanede girişleri rastgele değildir: Birinci ve beşinci girişleri 'sosyal kulüp' için futbol (ya da 'futbol' ile anlaşma (?) etrafında) ve daha özel olarak bugünün en büyük takımı hakkında. Mesela text 1...

"Son dokuz yıldır Messi, FC Barcelona'yı ulusal ve uluslararası unvanlara yönlendirirken, bireysel kayıtları dünya çapında görünen yollarla kırdı ..."

Çok hoş! Öte yandan, aradaki üç girişteki içeriği kesinlikle atlamak istersiniz. İşte bir örnek ( text 2):

"Teksas'taki birkaç saat içinde Bay Rubio, Bay Trump'ın pantolonunda idrar yaptığını ve durmayan Twitter mesajlarına dokunmak için yasadışı göçmenleri kullandığını söyledi ..."

Yani ne "sörf" ne pahasına olursa olsun kaçınmak için yapmanız text 1için text 2de, devam ederken Yüce Barcelona FC hakkında literatürde sevinmek için text 5?


TC-IDF: Kelimeleri her birinde textuzun vektörlere ayırdım. Daha sonra, her bir kelimenin frekansını saydı, textiçinde sadece karşılık gelen sözcüklerin textsayıldığı beş vektör (her biri için bir tane ) oluşturuldu - diğer texts'ye ait diğer tüm kelimeler sıfır olarak değerlendi. Örneğin, ilk parçacığında text 1vektörü "Messi" kelimesi için 1 sayılırken "Trump" 0 olur. Bu tc bölümüdür.

IDF parçası ayrıca, her için ayrı ayrı hesaplandı texteden küçük bir kütüphane verilen sadece sıfırdan beşe kadar, ne yazık ki belgeleri (sayar logaritmik dönüşümleri içeren, (I veri çerçeveleri olarak tedavi düşünmek) ve 5 "vektörler" sonuçlandı ) aşağıdaki gibi belirli bir kelime içeren:

01log(No. documents1+No. docs containing a word) . Doküman sayısı 5'tir. Burada OP'yetext cevap verebilecek kısım gelir: her idf hesaplaması için, dikkate alınan tutar taksitten çıkarılmıştır . Bir kelime tüm belgelerde ortaya kalırsa, onun idf hala sayesinde hepsi mevcuttu, çünkü örneğin kelime "" vardı öneme 0 - paydada s.01text

Giriş-bilge çarpma her için oldu her kelimenin önemi kütüphane öğelerin her biri için - lokal yaygın küresel nadir kelimeler .tc×idftext


KARŞILAŞTIRMALAR: Artık sadece bu "kelime önemi vektörleri" arasında nokta ürünler gerçekleştirmek meselesiydi.

Tahmin edileceği gibi, nokta ürünü text 1ile text 5oldu 13.42645ise, text 1v. text2Yalnızca oldu 2.511799.

Zorlu R kodu (taklit edecek bir şey yok) burada .

Yine, bu çok ilkel bir simülasyon, ama bence çok grafik.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.