Skip to content Skip to sidebar Skip to footer

Text Classification with NLP: Tf-Idf vs Word2Vec vs BERT

Daftar Isi

Preprocessing, Model Design, Evaluation, Explainability for Bag-of-Words, Word Embedding, Language models

Text Classification with NLP: Tf-Idf vs Word2Vec vs BERT
Text Classification with NLP: Tf-Idf vs Word2Vec vs BERT


Ringkasan

Pada artikel ini, menggunakan NLP dan Python, saya akan menjelaskan 3 strategi berbeda untuk klasifikasi multikelas teks: Bag-of-Words kuno (dengan Tf-Idf ), Word Embedding yang terkenal (dengan Word2Vec), dan model Bahasa mutakhir (dengan BERT).

NLP (Natural Language Processing) adalah bidang kecerdasan buatan yang mempelajari interaksi antara komputer dan bahasa manusia, khususnya bagaimana memprogram komputer untuk memproses dan menganalisis sejumlah besar data bahasa alami. NLP sering diterapkan untuk mengklasifikasikan data teks. Klasifikasi teks adalah masalah menetapkan kategori ke data teks sesuai dengan isinya.

Ada berbagai teknik untuk mengekstrak informasi dari data teks mentah dan menggunakannya untuk melatih model klasifikasi. Tutorial ini membandingkan pendekatan sekolah lama Bag-of-Words (digunakan dengan algoritma pembelajaran mesin sederhana), model Word Embedding yang populer (digunakan dengan jaringan saraf pembelajaran mendalam), dan model Bahasa yang canggih (digunakan dengan pembelajaran transfer dari transformator berbasis perhatian) yang telah sepenuhnya merevolusi lanskap NLP.

Saya akan menyajikan beberapa kode Python berguna yang dapat dengan mudah diterapkan dalam kasus serupa lainnya (cukup salin, tempel, jalankan) dan berjalan melalui setiap baris kode dengan komentar sehingga Anda dapat mereplikasi contoh ini (tautan ke kode lengkap di bawah).

Saya akan menggunakan "Himpunan data kategori berita" di mana Anda diberikan judul berita dari tahun 2012 hingga 2018 yang diperoleh dari HuffPost dan Anda diminta untuk mengklasifikasikannya dengan kategori yang tepat, oleh karena itu ini adalah masalah klasifikasi multikelas (tautan di bawah).

Secara khusus, saya akan melalui:

Setup: mengimpor paket, membaca data, Preprocessing, Partitioning.
Bag-of-Words: Rekayasa Fitur & Pemilihan Fitur & Pembelajaran Mesin dengan scikit-learn, Pengujian &Evaluasi, Penjelasan dengan kapur.
Word Embedding: Memasang Word2Vec dengan gensim, Feature Engineering & Deep Learning dengan tensorflow/keras, Testing & Evaluation, Explainability dengan mekanisme Attention.
Model Bahasa: Rekayasa Fitur dengan transformator, Transfer Learning dari BERT yang telah dilatih sebelumnya dengan transformator dan tensorflow/keras, Pengujian &Evaluasi.

Setup
Pertama-tama, saya perlu mengimpor perpustakaan berikut:

## for data
import json
import pandas as pd
import numpy as np
## for plotting
import matplotlib.pyplot as plt
import seaborn as sns
## for processing
import re
import nltk
## for bag-of-words
from sklearn import feature_extraction, model_selection, naive_bayes, pipeline, manifold, preprocessing
## for explainer
from lime import lime_text
## for word embedding
import gensim
import gensim.downloader as gensim_api
## for deep learning
from tensorflow.keras import models, layers, preprocessing as kprocessing
from tensorflow.keras import backend as K
## for bert language model
import transformers

Himpunan data terkandung ke dalam file json, jadi pertama-tama saya akan membacanya menjadi daftar kamus dengan json dan kemudian mengubahnya menjadi Dataframe pandas.

 lst_dics = []

with open('data.json', mode='r', errors='ignore') as json_file:

    for dic in json_file:

        lst_dics.append( json.loads(dic) )

## print the first one

lst_dics[0]


The original dataset contains over 30 categories, but for the purposes of this tutorial, I will work with a subset of 3: Entertainment, Politics, and Tech.


## create dtf

dtf = pd.DataFrame(lst_dics)

## filter categories

dtf = dtf[ dtf["category"].isin(['ENTERTAINMENT','POLITICS','TECH']) ][["category","headline"]]

## rename columns

dtf = dtf.rename(columns={"category":"y", "headline":"text"})

## print 5 random rows

dtf.sample(5)

Untuk memahami komposisi himpunan data, saya akan melihat distribusi univariat target dengan menunjukkan frekuensi label dengan plot batang.

fig, ax = plt.subplots()

fig.suptitle("y", fontsize=12)

dtf["y"].reset_index().groupby("y").count().sort_values(by= 

       "index").plot(kind="barh", legend=False, 

        ax=ax).grid(axis='x')

plt.show()

Himpunan data tidak seimbang: proporsi berita Teknologi sangat kecil dibandingkan dengan yang lain, ini akan membuat model mengenali berita Teknologi agak sulit.

Sebelum menjelaskan dan membangun model, saya akan memberikan contoh prapemrosesan dengan membersihkan teks, menghapus kata-kata berhenti, dan menerapkan lemmatisasi. Saya akan menulis fungsi dan menerapkannya ke seluruh kumpulan data.


'''
Preprocess a string.
:parameter
:param text: string - name of column containing text
:param lst_stopwords: list - list of stopwords to remove
:param flg_stemm: bool - whether stemming is to be applied
:param flg_lemm: bool - whether lemmitisation is to be applied
:return
cleaned text
'''

def utils_preprocess_text(text, flg_stemm=False, flg_lemm=True, lst_stopwords=None):

## clean (convert to lowercase and remove punctuations and
characters and then strip)
text = re.sub(r'[^\w\s]', '', str(text).lower().strip())

## Tokenize (convert from string to list)
lst_text = text.split()

## remove Stopwords
if lst_stopwords is not None:
lst_text = [word for word in lst_text if word not in
lst_stopwords]


## Stemming (remove -ing, -ly, ...)
if flg_stemm == True:
ps = nltk.stem.porter.PorterStemmer()
lst_text = [ps.stem(word) for word in lst_text]

## Lemmatisation (convert the word into root word)
if flg_lemm == True:
lem = nltk.stem.wordnet.WordNetLemmatizer()
lst_text = [lem.lemmatize(word) for word in lst_text]

## back to string from list
text = " ".join(lst_text)
return text

 

Bag Of Words

Model Bag-of-Words sederhana: ia membangun kosakata dari korpus dokumen dan menghitung berapa kali kata-kata itu muncul di setiap dokumen. Dengan kata lain, setiap kata dalam kosakata menjadi fitur dan dokumen diwakili oleh vektor dengan panjang kosakata yang sama ("sekantong kata"). Misalnya, mari kita ambil 3 kalimat dan mewakilinya dengan pendekatan ini:

Seperti yang dapat Anda bayangkan, pendekatan ini menyebabkan masalah dimensi yang signifikan: semakin banyak dokumen yang Anda miliki, semakin besar kosakatanya, sehingga matriks fitur akan menjadi matriks yang sangat jarang. Oleh karena itu, model Bag-of-Words biasanya didahului dengan preprocessing penting (word cleaning, stop words removal, stemming/lemmatization) yang bertujuan untuk mengurangi masalah dimensi. 

Istilah frekuensi belum tentu merupakan representasi terbaik untuk teks. Bahkan, Anda dapat menemukan di korpus kata-kata umum dengan frekuensi tertinggi tetapi sedikit kekuatan prediktif atas variabel target. Untuk mengatasi masalah ini ada varian lanjutan dari Bag-of-Words yang, alih-alih penghitungan sederhana, menggunakan istilah frekuensi–frekuensi dokumen terbalik (atau Tf–Idf). Pada dasarnya, nilai suatu kata meningkat secara proporsional untuk dihitung, tetapi berbanding terbalik dengan frekuensi kata dalam korpus.

Mari kita mulai dengan Rekayasa Fitur, proses untuk membuat fitur dengan mengekstrak informasi dari data. Saya akan menggunakan vectorizer Tf-Idf dengan batas 10.000 kata (jadi panjang kosakata saya adalah 10k), menangkap unigram (yaitu "baru" dan "york") dan bigram (yaitu "new york"). Saya akan memberikan kode untuk vectorizer hitungan klasik juga:

## Count (classic BoW)

vectorizer = feature_extraction.text.CountVectorizer(max_features=10000, ngram_range=(1,2))

## Tf-Idf (advanced variant of BoW)

vectorizer = feature_extraction.text.TfidfVectorizer(max_features=10000, ngram_range=(1,2))

Now I will use the vectorizer on the preprocessed corpus of the train set to extract a vocabulary and create the feature matrix.


corpus = dtf_train["text_clean"]

vectorizer.fit(corpus)

X_train = vectorizer.transform(corpus)

dic_vocabulary = vectorizer.vocabulary_

The feature matrix X_train has a shape of 34,265 (Number of documents in training) x 10,000 (Length of vocabulary) and it’s pretty sparse:


sns.heatmap(X_train.todense()[:,np.random.randint(0,X.shape[1],100)]==0, vmin=0, vmax=1, cbar=False).set_title('Sparse Matrix Sample')


In order to know the position of a certain word, we can look it up in the vocabulary:


word = "new york"

dic_vocabulary[word]

If the word exists in the vocabulary, this command prints a number N, meaning that the Nth feature of the matrix is that word.

 

Post a Comment for "Text Classification with NLP: Tf-Idf vs Word2Vec vs BERT"