Word2Vec : Embedding Teks Berbahasa Indonesia (ft. Fasttext)

Eko Setiawan
7 min readFeb 14, 2023

--

Photo by Tim Mossholder on Unsplash

Gensim merupakan library word embdeding yang memiliki performa yang sangat baik (jika jumlah datanya banyak), namun menurut saya ada satu kelemahan yang cukup mendasar dari Gensim yaitu: tidak bisa memproses 2 kata atau lebih.

Dalam bahasa Indonesia, ada cukup banyak entitas yang direpresentasikan dengan 2 kata atau lebih, misalnya “sepeda motor”. Berikut adalah hasil dari model Wikihow Gensim saat saya mencoba mencari kata-kata yang mirip dengan “sepeda motor”.

Model Wikihow Gensim tidak memiliki embedding untuk “sepeda motor”

Jika kita ingat lagi pada saat pelatihan model Wikihow Gensim, seluruh teks telah dipecah perkata melalui tokenization. Model Gensim selalu berasumsi bahwa kata yang akan diproses adalah satu kata. Dalam contoh di atas, model Wikihow Gensim hanya memiliki vektor untuk kata “sepeda” dan “motor”, tidak dengan “sepeda motor”.

Ada beberapa teknik yang tersedia untuk memecahkan masalah multi kata ini, salah satunya adalah menggunakan sebagian / potongan dari kata (dikenal dengan sub-word).

Jika di Gensim kata “sepeda” merupakan perwakilan satu entitas, dengan pendekatan sub-word (n=3), kata tersebut bisa dibagi menjadi: “sep”, “epe”, “ped” dan “eda”. Tidak hanya satu kata, kita juga bisa membuat subword dari dua kata.

Fasttext merupakan library word embedding yang menggunakan pendekatan sub-word dalam pembuatan vektor yang merepresentasikan tiap kata.

Detail mengenai bagaimana cara kerja Fasttext dapat anda baca melalui website resmi Fasttext atau menonton video penjelasan berikut ini.

Catatan: Artikel ini merupakan lanjutan dari artikel Word2Vec: Embedding Teks Berbahasa Indonesia yang menggunakan library Gensim.

Pada artikel ini, saya akan menjelaskan bagaimana langkah-langkah saya dalam membuat model word embedding menggunakan library Fasttest dan data Wikihow. Untuk data yang saya gunakan dapat diakses pada link berikut.

Mari kita mulai ngodingnya, seperti biasa saya akan menggunakan Google Colab.

Karena Fasttext tidak tersedia di Google Colab secara default, saya harus menginstalnya terlebih dahulu.

!pip install fasttext

Pra-Proses Data

Untuk mengakses data Wikihow melalui Colab, data tersebut harus didownload terlebih dahulu dan diupload ke Google Drive kita. Data Wikihow yang akan digunakan memiliki nama file “indonesia.pkl” dan berformat pickle.

Pemilik data ini sendiri sudah memberikan contoh kode untuk memasukkan data ke Jupyter Notebook pada link ini.

# import libraries
import pickle
import os
import pandas as pd
import numpy as np
import re

# setting pandas's columns
pd.set_option('display.max_colwidth', None)

# connecting to google drive
from google.colab import drive
drive.mount('/content/drive',force_remount=True)

# load data
data_path = r'/content/drive/MyDrive/dataset/data_nlp/indonesian.pkl'
with open(data_path, 'rb') as f:
indo_docs=pickle.load(f)

f.close()

Oh ya, gunakan data_path sesuai dengan lokasi file dataset masing-masing.

Data ini terdiri dari 16.308 artikel dari WikiHow, masing-masing artikel terdiri dari beberapa langkah yang berisi teks penjelasan dalam bahasa indonesia.

Contoh salah satu artikel pada data

Tiap data point (artikel) terdiri dari link artikel berbahasa indonesia, judul dari tiap metode, kesimpulan dari tiap metode, ringkasan langlah-langkah dari tiap metode, judul dalam bahasa inggris dan link artikel dalam bahasa inggris.

Setiap artikel memiliki jumlah metode yang berbeda-beda, begitu juga jumlah kata-katanya.

Setelah melalui melakukan beberapa percobaan koding, saya memutuskan untuk hanya memindahkan bagian judul dari masing-masing metode (sub_title), kesimpulan dari metode (summary) dan ringkasan langkah-langkah (document) metode tersebut.

def convert_docs_to_df(docs_data):
# list for storing each elements of data
article_sub_title = []
article_summary = []
article_document = []

# looping on each article on data
for doc in list(docs_data.items()):
text = doc[1]
titles = list(text.keys())

# looping on each sub_title / step on article
for sub_title in titles:
article_sub_title.append(sub_title)
article_summary.append(text[sub_title]['summary'])
article_document.append(text[sub_title]['document'])

result = pd.DataFrame({'sub_title' : article_sub_title, 'summary' : article_summary, 'document' : article_document})
return result

# convert the pickle data
data = convert_docs_to_df(indo_docs)
Data WikiHow dalam tabel

Dari 16.308 artikel, ada 47.481 metode yang berhasil diambil dari data pickle. Untuk memperbanyak data teks dalam pelatihan model embedding, saya menggabungkan kesimpulan dari tiap metode (summary) dengan ringkasan langkah-langkah (document).

data['full_document'] = data.summary + " " + data.document

Teks yang ada merupakan teks mentah yang masih terdapat banyak angka, tanda baca, huruf kapital dan karakter lainnya. Skrip Python dibawah ini saya gunakan untuk membersihkan data.

# let's clean the data
def text_cleaning(text):
result = text.lower() # apply lowercas
result = result.replace('-', ' ') # get rid of punctuations
result = result.replace('+', ' ')
result = result.replace('..', ' ')
result = result.replace('.', ' ')
result = result.replace(',', ' ')
result = result.replace('\n', ' ') # get rid of new line
result = re.findall('[a-z\s]', result, flags=re.UNICODE) # only use text character (a-z) and space
result = "".join(result)
final = " ".join(result.split())

return final # clean text

# clean our data
data['cleaned_document'] = data.full_document.apply(lambda r: text_cleaning(r))
Contoh data setelah dibersihkan

Data sudah selesai diproses, mari lanjut dengan membuat model embedding.

Melatih Model Embedding

Berbeda dengan Gensim yang memerlukan data teks yang ditokenisasi, Fasttext memerlukan file latih dalam bentuk file teks (.txt). Oleh karena itu, kolom “cleaned_document” harus kita jadikan file .txt terlebih dahulu dan disave pada Google Drive

# set our text file's location path
text_file_path = r'/content/drive/MyDrive/proyek_pribadi/NLP/data/wikihow_indo_fasttext.txt'

# convert the cleaned_document column to text file
data.to_csv(text_file_path, columns=['cleaned_document'], header=None, index=False)
Pastikan file .txt telah muncul di Google Drive

Saatnya melatih model word embedding dengan Fasttext.

import fasttext

# trainning our embedding model
model_fasttext = fasttext.train_unsupervised(text_file_path)

# model path
model_fasttext_path = r'/content/drive/MyDrive/proyek_pribadi/NLP/model_file/word2vec-fasttext-wikihow.bin'

# save the model
model_fasttext.save_model(model_fasttext_path)

# load the model
model_fasttext = fasttext.load_model(model_fasttext_path)

Efek pertama dari penggunaan teknik sub-word adalah membuat waktu pelatihan menjadi lebih lama dan ukuran file model jauh lebih besar. Dengan Google Colab, proses pelatihan model ini membutuhkan waktu hampir 45 menit dibandingan dengan model Gensim yang hanya kurang lebih 5 menit.

Ukuran model Gensim dan Fasttext

Dengan Gensim 4.2.0 dan data Wikihow, model yang dihasilkan hanya berukuran 30,5 MB. Model Fasttext dengan data yang sama memiliki ukuran 792,9 MB (25 kali lipat model Gensim).

Mari kita lihat performa model Fasttext dalam mencari kata yang memiliki kesamaan makna.

model_fasttext.get_nearest_neighbors('pintar')
Kata-kata yang mirip dengan “pintar” menurut Fasttext

Terlihat bahwa model Fasttext lebih mengutamakan kata yang merupakan kata turunan (telah diberi imbuhan). Meskipun demikian, kata “cerdas” tetap muncul di 5 kata teratas dan kata-kata terkait ponsel pintar juga muncul di 10 kata teratas.

model_fasttext.get_nearest_neighbors('pria')
Kata-kata yang mirip dengan “pria” menurut Fasttext

Seluruh kata yang muncul berkaitan dengan jenis kelamin walaupun model Fasttext juga belum bisa membedakan “pria” dengan “wanita”. Dari contoh kedua ini terlihat bahwa pendekatan sub-word sangat menonjolkan hubungan kemiripan karakter / huruf yang digunakan oleh kata. Sehingga sebagian besar yang muncul adalah kata imbuhan.

Mari kita mencoba kelebihan Fasttext yang tidak tersedia di model Gensim.

model_fasttext.get_nearest_neighbors('sepeda motor')
Kata-kata yang mirip dengan “sepeda motor” menurut Fasttext

Ukuran model yang besar adalah harga yang harus kita bayar untuk tambahan kelebihan berikut ini. Akhirnya kita bisa memproses entitas yang kita representasikan dengan dua kata atau lebih. Hasil dari Fasttext di atas juga cukup lumayan, model Fasttext mampu menampilkan kata-kata yang terkait dengan kata “sepeda motor”.

Selain memproses dua kata atau lebih, penggunaan sub-word pada model Fasttext juga memungkinkan kita untuk mencari kata-kata dengan input kata yang tidak lengkap. Hal ini sangat bermanfaat untuk menangani kesalahan ketik saat input data.

Penggunan sub-word juga membuat model Fasttext terbebas dari masalah Out of Vocabulary (OOV).

# mencoba kata matahari yang typo
model_fasttext.get_nearest_neighbors('mtahari')
Kata-kata yang mirip dengan kata “mtahari” menurut Fasttext

Model Fasttext mampu mendeteksi kata matahari yang sengaja saya kurangi hurufnya dengan “mtahari”. Kemampuan untuk mendeteksi kata dari input yang typo ini sangat berguna untuk memproses bahasa yang digunakan di sosial media.

Seperti yang kita tahu, bahasa di sosial media yang digunakan saat ini terdiri dari berbagai kata-kata gaul, singkatan, tambahan huruf dan lainnya.

Pada artikel word embedding menggunakan Gensim, saya telah menampilkan visualisasi 2 dimensi dari sejumlah kata, mari kita coba visualisasikan kata-kata tersebut namun dengan vektor menurut model Fasttext.

Visualisasi kata-kata bahasa Indonesia

Oh ya, penjelasan mengenai kode-kode dibawah ini dapat dibaca pada artikel word embedding dengan Gensim berikut ini.

Di sini saya hanya membahas hasil visualisasinya saja.

from sklearn.decomposition import PCA

words = ['cabai', 'terong', 'pedas', 'manis', 'asin', 'apel', 'pisang', 'anggur',
'pesawat', 'mobil', 'mesin', 'motor', 'harimau', 'singa', 'kucing',
'jerapah', 'zebra', 'rumah', 'gedung', 'cantik', 'ganteng', 'gajah',
'kelinci', 'anjing', 'sapi', 'kerbau', 'bawang', 'kunyit', 'merica']

# Store the words vector in list
word_vector = []

# convert each word to vector
for word in words:
word_vector.append(model_fasttext.get_word_vector(word))

# convert the n=100 vector to 2D vector
pca = PCA(n_components=2)
result = pca.fit_transform(word_vector)
import plotly.express as px

# Create the scatter plot
fig = px.scatter(x=result[:, 0], y=result[:, 1])

# Annotate each data point
for i, txt in enumerate(words):
fig.add_annotation(
x=result[i, 0],
y=result[i, 1],
text=txt,
xref="x",
yref="y",
showarrow=True,
arrowhead=7,
ax=20,
ay=-30
)

# adjust graph size
fig.update_layout(
height=800,
width=800,
title='Visualisasi Kata-kata Indonesia (ft. Fasttext)'
)

# Show the plot
fig.show()
Plot Hubungan Antar Kata (menurut model Fasttext)

Dari beberapa gugus yang ada terlihat bahwa model Fasttext mampu membedakan kelompok benda mati, bumbu dapur, buah, rasa dan hewan. Namun untuk kata sifat, kata “ganteng” dan “cantik” masih tergabung di gugus hewan.

Berbeda dengan model Gensim, model Fasttext tidak memisahkan golongan hewan peliharaan dengan hewan liar.

Oke, sampai disini penjelasan saya mengenai langkah-langkah membuat word embedding menggunakan Fasttext. Jika memiliki pertanyaan atau respon silahkan sampaikan di bawah ya.

Terima kasih.

--

--