TF-IDF (Term Frequency-Inverse Document Frequency) : Representasi Vector Data Text

Muhammad Yunus
8 min readApr 30, 2020

--

Konsep dan Penerapan pada Python menggunakan Pandas dan Scikit-Learn

Halo semua, kembali kita lanjutkan bahasan sebelumnya tentang text preprocessing disini,

Ditahap akhir dari text preprocessing adalah term-weighting .Term-weighting merupakan proses pemberian bobot term pada dokumen. Pembobotan ini digunakan nantinya oleh algoritma Machine Learning untuk klasifikasi dokumen. Ada beberapa metode yang dapat digunakan, salah satunya adalah TF-IDF (Term Frequency-Inverse Document Frequency).

Prepare Data

Sekarang kita mulai dengan terlebih dahulu menyiapkan data yang diperlukan. Kita akan gunakan file Text_Preprocessing.csv yang sebelumnya disimpan. Baca file tersebut menggunakan Pandas, kita hanya membutuhkan kolom label dan tweet_tokens_stemmed . Rename kolom pada Dataframe menjadi ["label", "tweet"] .

result pada Jupyter Notebook,

jika kita cek, item pada kolom tweet memiliki tipe data <class str> , kita perlu ubah string diatas menjadi list dan simpan pada Pandas Series tweet_list,

result pada Jupyter Notebook,

Term Frequency (TF)

Term Frequency merupakan frekuensi kemunculan term i pada dokumen j dibagi dengan total term pada dokumen j. Ditulis dalam bentuk,

pada Python kita implementasikan dengan cara berikut,

document merupakan Pandas Series row tweet_list yang sebelumnya dibuat. Setelah itu kita .apply() fungsi .calc_TF() kedalam Pandas Series 'tweet_list' dan simpan hasilnya pada Series 'TF_dict',

result pada Jupyter Notebook, print Pandas Series 'TF_dict' untuk index row Dataframe ke-90,

Inverse Document Frequency (IDF)

IDF berfungsi mengurangi bobot suatu term jika kemunculannya banyak tersebar diseluruh dokumen, dituliskan dalam bentuk,

N adalah jumlah total document dalam corpus, N =|D|.

|{d D : td}| = df(t) , adalah jumlah dokumen yang mengandung term t. IDF juga dapat dituliskan dalam bentuk,

Penambahan 1 untuk menghindari pembagian terhadap 0 jika df(t) tidak ditemukan pada corpus.

untuk mencari df(t) pada python kita implementasikan dengan cara berikut,

Kita buat dictionary DF , dimana key-nya adalah term dan value-nya adalah jumlah document (DF_dict) yang menggantung term tersebut.

Berikut adalah result pada Jupyter Notebook untuk dictionary DF ,

Untuk menghitung IDF pada Python dengan cara berikut,

karena variable DF merupakan dictionary, pada fungsi calc_idf() kita dapat mencari nilai IDF tiap term dengan mendapatkan document frequency tiap term (__DF[term]), selanjutnya kita simpan kedalam dictionary dengan nama IDF .

Nah, dari dictionary TF dan IDF kita dapat menentukan TF-IDF dengan mengalikan kedua dictionary tersebut value by value dan simpan kedalam Pandas Series. Untuk pengerjaanya, kita akan menggunakan fungsi .apply() terhadap fungsi calc_TF_IDF() sebagai berikut,

hasil diatas (dictionary TF , IDF , dan Series TF-IDF ) kita dapat tampilkan dengan cara berikut,

result pada Jupyter Notebook,

Sekarang kita jadikan Series TF-IDF menjadi TF-IDF vector data berbentuk Sparse Matrix dengan dimensi (n_samples, n_feature), n_feature yang akan kita gunakan adalah top 50 term dengan TF-IDF terbesar, sedangkan n_samples sebanyak 23225 row data tweet.

Sparse Matrix untuk sample ke-0 dengan n_feature = 50, result pada Jupyter Notebook,

kita juga dapat menampilkan top 50 term TF-IDF dengan cara berikut,

result pada Jupyter Notebook,

Menghitung TF-IDF menggunakan Scikit-Learn

Diatas kita sudah melakukan perhitungan TF-IDF tanpa menggunakan library khusus. Sekarang kita akan coba menghitung TF-IDF menggunakan library Scikit-Learn.

Scikit-Learn atau dikenal juga dengan sebutan Sklearn merupakan library Machine Learning yang memiliki berbagai feature yang mendukung algoritma classification, regression dan clustering , diataranya support vector machines, random forests, gradient boosting, k-means and DBSCAN, dan juga didesain untuk dapat digunakan bersama library NumPy dan SciPy.

Install Scikit-Learn,

conda install -c intel scikit-learn

Untuk menghitung TF-IDF dari corpus yang kita miliki dengan menggunakan Scikit-Learn, kita akan menggunakan module TfidfVectorizer .

Pertama kita perlu menyiaplan corpus berupa Pandas Series tweet_join dengan row data berupa list term dalam string,

sehingga dari Series tweet degan format list,

dapat terbentuk Series tweet_join dengan format string,

Pada Library Scikit-Learn perhitungan TF-IDF dilakukan pada beberapa bagian,

  1. TF dihitung pada class CountVectorizer >fit_transform()
  2. IDF dihitung pada classTfidfTransformer > fit()
  3. TF-IDF dihitung pada class TfidfTransformer > transform()

Untuk kemudahan Scikit-Learn menyediakan class TfidfVectorizer yang didalamnya dapat menghitung CountVectorizer dan TfidfTransformer .

Scikit-Learn TF-IDF Formula

Formula untuk menghitung IDF pada Scikit-Learn, berbeda dengan yang kita bahas diawal, jika parameter smooth_idf=True pada TfidfVectorizer, maka IDF dirumuskan sebagai,

idf(t) = log [ (1 + n) / (1 + df(t)) ] + 1

sebaliknya jika smooth_idf=False ,

idf(t) = log [ n / df(t) ] + 1

Scikit-Learn menggunakan L2 Normalization by Default

Sparse matrix dengan size (n_samples, n_feature) pada Scikit-Learn akan di normalisasi ke normalizer L2 by default, dengan formula,

Kita dapat memilih untuk tidak menggunakan normalizer pada TfidfVectorizer dengan menambahkan parameter norm=None .

Lebih lengkapnya dapat dilihat pada source library Scikit-Learn untuk text processing, disini,

Menghitung TF-IDF menggunakan TfidfVectorizer

Untuk menghitung TF-IDF menggunakan Scikit-Learn, dapat dilakukan dengan cara berikut,

method TfidfVectorizer() ketika diterapkan pada documents/corpus dengan fungsi .fit_transform() , akan menghasilkan matrix berukuran (len(TWEET_DATA[“tweet_join”]) , max_features ). Diatas kita set max_feature = 50, untuk mendapatkan 50 top term dengan term frequency terbesar.

Dokumetasi terkait TfidfVectorizer() dapat ditemukan disini,

Kita dapat melihat list top 50 term yang meiliki TF-IDF terbesar dengan cara berikut,

Result pada Jupyter Notebook,

jika kita lihat, top 50 TF-IDF menggunakan Scikit-Learn TfidfVectorizer() menghasilkan result berbeda dengan hasil yang kita buat sebelumnya, ini seperti dibahas diatas bahwa pada TfidfVectorizer() mengimplementasikan formula yang sedikit berbeda dengan standar text book, dan menerapkan normalisasi L2 pada sparse matrix yang terbentuk.

Menghitung TF Scikit-Learn dengan CountVectorizer() / L1 Norm

Saat menghitung TF pada fungsi TfidfVectorizer() pada Scikit-Learn tidak dilakukan normalisasi, sehingga bentuk formula TF pada Scikit-Learn, dirumuskan sebagai berikut,

Sehingga jika kita memiliki dua buah dukumen sebagai berikut,

'hari ini cerah setelah kemarin mendung',
'jakarta hari kemarin mendung'

maka hasil vector TF pada Scikit-Learn,

[1, 1, 1, 0, 1, 1, 1],
[0, 1, 0, 1, 1, 1, 0]

dengan feature name,

['cerah', 'hari', 'ini', 'jakarta', 'kemarin', 'mendung', 'setelah']

Nah, untuk mengatasi hal ini kita tidak bisa hanya menggunakan fungsi TfidfVectorizer(), kita akan menggunakan fungsi CountVectorizer() yang dapat menghasilkan vector TF, setelah itu kita apply L1 normalization dengan fungsi normalize() pada library scikitlearn.preprocessing sehingga formulanya tepat sama dengan definisi TF diawal tulisan. L1 Normalization ditulis dalam bentuk,

Selanjutnya kita lakukan perkalian antara TF dan IDF dengan fungsi multiply() , sehingga didapatkan TFIDF vector. Penggunaan smooth_idf = False seperti dibahas sebelumnya agar fungsi IDF berbentuk,

idf(t) = log [ n / df(t) ] + 1

Berikut implementasinya,

TF-IDF Unigram, Bigram dan Trigram menggunakan Scikit-Learn

Jika kita lihat kembali kalkulasi untuk TF-IDF menggunakan Scikit-Learn baik yang menggunakan L1 Normalization maupun L2 Normalization, hanya melibatkan satu term saja, ini disebut TF-IDF unigram.

Untuk menghitung TF-IDF bigram dan trigram menggunakan Scikit-Learn, kita dapat menambahkan argument ngram_range=(min_n, max_n) dengan min_n dan max_n merupakan batasan minimum dan maksimum ngram yang akan digunakan pada fungsi TfidfVectorizer() maupun CountVectorizer() .

ngram_range=(1,1) artinya hanya hitung TFIDF unigram,

ngram_range=(1,2) artinya hitung TFIDF unigram dan bigram,

ngram_range=(2,2) artinya hanya hitung TFIDF bigram,

dst..

Contoh perhitungan TF-IDF L1 Normalization Unigram, Bigram, Trigram berikut implementasinya,

kita dapat melihat list term unigram, bigram dan trigram pada seluruh dokumen dengan cara berikut,

tfidf.get_feature_names()

result pada Jupyter Notebook,

Selain itu juga kita dapat memasukan blok program diatas kedalam sebuah fungsi agar mudah untuk diatur ketika menentukan n_gram. Berikut implementasinya, jika kita ingin membuat tfidf_mat untuk masing masing n_gram(unigram, bigram, trigram),

sehingga kita akan memiliki 3 buah sparse matriks (tfidf_mat_unigram , tfidf_mat_bigram dan tfidf_mat_trigram ).

Save to Excel

Sekarang kita akan simpan data diatas kedalam Excel dengan cara berikut,

  • Save TF-IDF Unigram
  • Save TF-IDF Bigram
  • Save TFIDF Trigram

Save to .NPZ

Selain itu kita juga save sparse matrix TFIDF kedalam format .npz, yang merupakan format file ntuk menyimpan numpy array. Lakukan dengan cara berikut,

  • Selanjutnya kita simpan juga feature name untuk unigram, bigram dan trigram yang tersimpan dalam variable terms_unigram, terms_bigram dan terms_trigram kedalam file json,

ditahap ini kita sudah dapat membuat sparse matrix TF-IDF dengan L1 normalization untuk unigram, bigram dan trigram.

Jika kalian membutuhkan full code diatas, dapat didownload pada github saya,

--

--

Muhammad Yunus
Muhammad Yunus

Written by Muhammad Yunus

IoT Engineer, Software Developer & Machine Learning Enthusiast

Responses (14)