Frekuensi istilah / frekuensi dokumen terbalik (TF / IDF): bobot

12

Saya punya dataset yang mewakili 1000 dokumen dan semua kata yang muncul di dalamnya. Jadi baris mewakili dokumen dan kolom mewakili kata-kata. Jadi misalnya, nilai dalam sel berarti waktu kata j muncul dalam dokumen i . Sekarang, saya harus menemukan 'bobot' dari kata-kata itu, menggunakan metode tf / idf, tetapi saya sebenarnya tidak tahu bagaimana melakukan ini. Bisakah seseorang tolong bantu saya?(i,j)ji

ABC
sumber
The tf-idf-Statistik Untuk Ekstraksi Kata Kunci - joyofdata.de/blog/tf-idf-statistic-keyword-extraction
Raffael

Jawaban:

12

Wikipedia memiliki artikel bagus tentang topik ini, lengkap dengan formula. Nilai-nilai dalam matriks Anda adalah frekuensi istilah. Anda hanya perlu menemukan idf: (log((total documents)/(number of docs with the term))dan mengalikan 2 nilai.

Di R, Anda bisa melakukannya sebagai berikut:

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

Berikut dataset:

> 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

Anda juga dapat melihat idf dari setiap istilah:

> 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 
Zach
sumber
Terima kasih atas bantuan Anda! Tetapi apakah mungkin untuk mendapatkan nilai untuk setiap kata yang mewakili bobot (bukan seluruh matriks)? Sekarang kita memiliki seluruh matriks bobot. Saya sedang melakukan beberapa pemilihan fitur dan ingin menggunakan tf / idf sebagai metode filter ...
ABC
@ABC tf-idf menurut definisi mengacu pada matriks bobot penuh. Mungkin Anda tertarik pada bobot idf saja, yang akan Anda dapatkan log((number of docs)/(number of docs containing the term)). Anda juga bisa menyaring istilah yang jarang.
Zach
Sangat jelas! Sangat dihargai.
ABC
13

ada paket tm (penambangan teks) http://cran.r-project.org/web/packages/tm/index.html yang harus melakukan persis yang Anda butuhkan:

#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 adalah bahasa fungsional sehingga membaca kode bisa rumit (misalnya x dalam istilah)

xhudik
sumber
2

Kode Anda memiliki kesalahan: colSums menghitung jumlah kemunculan di corpus, bukan jumlah teks dengan kata.

Komputasi versi seperti itu adalah:

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)
  }
user46661
sumber
1

Ada paket R baru yang bisa melakukan ini: textir: Inverse Regression for Text Analysis

Perintah yang relevan adalah tfidf, contoh dari manual:

data(we8there)
## 20 high-variance tf-idf terms
colnames(we8thereCounts)[
order(-sdev(tfidf(we8thereCounts)))[1:20]]
vonjd
sumber
1

Saya terlambat ke pesta ini, tetapi saya bermain dengan konsep tc-idf (saya ingin menekankan kata 'konsep' karena saya tidak mengikuti buku apa pun untuk perhitungan yang sebenarnya; jadi mereka mungkin agak canggung, dan pasti lebih mudah dilakukan dengan paket seperti {tm: Text Mining Package}, seperti yang disebutkan), dan saya pikir apa yang saya dapatkan mungkin terkait dengan pertanyaan ini, atau, dalam hal apa pun, ini mungkin tempat yang baik untuk mempostingnya.


SET-UP: Saya memiliki corpus dari 5paragraf panjang yang diambil dari media cetak, text 1melalui 5seperti The New York Times . Diduga, itu adalah "tubuh" yang sangat kecil, perpustakaan kecil, sehingga untuk berbicara, tetapi entri dalam perpustakaan "digital" ini tidak acak: Entri pertama dan kelima berurusan dengan sepak bola (atau 'sepak bola' untuk 'klub sosial' (?) di sekitar sini), dan lebih khusus lagi tentang tim terhebat hari ini. Jadi, misalnya, text 1dimulai dengan ...

"Selama sembilan tahun terakhir, Messi telah membawa FC Barcelona meraih gelar nasional dan internasional sambil memecahkan rekor individu dengan cara yang tampak seperti dunia lain ..."

Sangat bagus! Di sisi lain Anda pasti ingin melewatkan konten di tiga entri di antaranya. Berikut ini sebuah contoh ( text 2):

"Dalam rentang beberapa jam di Texas, Tuan Rubio menyarankan agar Tuan Trump buang air kecil di celana panjangnya dan menggunakan imigran gelap untuk menyampaikan pesan Twitternya yang tak henti-hentinya ..."

Jadi apa yang harus dilakukan untuk menghindari "berselancar" dengan text 1cara apa pun text 2, sambil terus bersukacita dalam literatur tentang FC Barcelona yang maha kuasa text 5?


TC-IDF: Saya mengisolasi kata-kata di setiap textvektor menjadi panjang. Kemudian menghitung frekuensi setiap kata, membuat lima vektor (satu untuk masing-masing text) di mana hanya kata-kata yang ditemui dalam yang sesuai textyang dihitung - semua kata lain, milik yang lain text, bernilai nol. Dalam cuplikan pertama text 1, misalnya, vektornya akan memiliki hitungan 1 untuk kata "Messi", sedangkan "Trump" akan memiliki 0. Ini adalah bagian tc .

Bagian idf juga dihitung secara terpisah untuk masing-masing text, dan menghasilkan 5 "vektor" (saya pikir saya memperlakukan mereka sebagai frame data), yang berisi transformasi logaritmik dari jumlah dokumen (sayangnya, hanya dari nol menjadi lima, mengingat perpustakaan kecil kami) ) mengandung kata yang diberikan seperti pada:

catatan(Dokumen tidak1+Tidak. Dokumen berisi kata)text01text

tc×idftext


PERBANDINGAN: Sekarang hanya masalah melakukan dot produk di antara "vektor pentingnya kata" ini.

Bisa ditebak, produk titik text 1dengan text 5adalah 13.42645, sedangkan text 1v. text2Hanya 2.511799.

Kode R kikuk (tidak ada yang meniru) ada di sini .

Sekali lagi, ini adalah simulasi yang sangat sederhana, tetapi saya pikir ini sangat grafis.

Antoni Parellada
sumber