GloVe untuk Wikipedia Bahasa Indonesia

Update Nov 2021: walaupun sudah berumur 3 tahun, posting ini ternyata masih cukup banyak yang mengakses. Bagi yang membutuhkan pretrained Glove data wikipedia Bahasa Indonesia (50 dimensi), dapat mendownloadnya di: https://drive.google.com/file/d/1jgnvIEp8rE3dh68lZXBHfyxzmeky9z6w/view?usp=sharing  Pretrained ini  dibuat tahun 2018, jadi saya tidak tahu apakah masih bisa digunakan sekarang di 2021, dan mohon jangan kontak saya tentang ini 🙂 Lagipula ada teknik lain seperti BERT, GPT, XLNet yang kemungkinan besar kinerjanya lebih baik.

— end update —

Sebelumnya saya sudah membuat vector word2vec  Wikipedia Bhs Indonesia dengan Gensim. Posting ini akan membahas model embedded word yang lain yaitu GloVe.  Saya akan gunakan untuk task NER. Pengalaman saya dulu untuk task textual entailment bahasa Inggris, Glove lebih baik daripada Word2Vec.

Untuk GloVe, saya tidak menemukan implementasinya dalam Python, yang ada adalah dari penulisnya langsung dalam C.  Berikut langkah-langkahnya.

  1. Download source code dari https://nlp.stanford.edu/projects/glove/
  2. Ekstrak dan masuk ke directorynya, lalu ketik “make” untuk mem-build source code.
  3. Jalankan ./demo.sh   demo ini akan mendownload data text8 sekitar 30MB. Jika berhasil artinya program bisa kita gunakan.
  4. Siapkan file teks gabungan dari artikel wikipedia bahasa indonesia (posting saya tentang ini)
  5. Ubah demo.sh jadi seperti ini. File input ada di variabel CORPUS, file output ada di variabel SAVE_FILE.   Saya buang bagian download file dan bagian evaluasi.
#!/bin/bash

CORPUS=wiki.id.case.text
VOCAB_FILE=vocab.txt
COOCCURRENCE_FILE=cooccurrence.bin
COOCCURRENCE_SHUF_FILE=cooccurrence.shuf.bin
BUILDDIR=build
SAVE_FILE=glove_wiki_id_50
VERBOSE=2
MEMORY=4.0
VOCAB_MIN_COUNT=5
VECTOR_SIZE=50
MAX_ITER=15
WINDOW_SIZE=15
BINARY=2
NUM_THREADS=8
X_MAX=10

$BUILDDIR/vocab_count -min-count $VOCAB_MIN_COUNT -verbose $VERBOSE  $VOCAB_FILE
if [[ $? -eq 0 ]]
  then
  $BUILDDIR/cooccur -memory $MEMORY -vocab-file $VOCAB_FILE -verbose $VERBOSE -window-size $WINDOW_SIZE  $COOCCURRENCE_FILE
  if [[ $? -eq 0 ]]
  then
    $BUILDDIR/shuffle -memory $MEMORY -verbose $VERBOSE  $COOCCURRENCE_SHUF_FILE
    if [[ $? -eq 0 ]]
    then
       $BUILDDIR/glove -save-file $SAVE_FILE -threads $NUM_THREADS -input-file $COOCCURRENCE_SHUF_FILE -x-max $X_MAX -iter $MAX_ITER -vector-size $VECTOR_SIZE -binary $BINARY -vocab-file $VOCAB_FILE -verbose $VERBOSE

    fi
  fi
fi

Untuk mencoba hasilnya, kita bisa gunakan code sebelumnya karena Gensim bisa mengkonversi file GloVe.

Konversi dari Glove ke word2vec (diambil dari: https://radimrehurek.com/gensim/scripts/glove2word2vec.html)

from gensim.test.utils import datapath, get_tmpfile
from gensim.models import KeyedVectors
from gensim.scripts.glove2word2vec import glove2word2vec

namaFileGlove = "glove_wiki_id.txt"
glove_file = datapath(namaFileGlove)
tmp_file = get_tmpfile("w2vec_glove_wiki_id.txt")

glove2word2vec(glove_file, tmp_file)

Sekarang kita coba dengan code yang sama dengan Word2Vec sebelumnya (untuk load gunakan KeyedVectors.load_word2vec_format). Supaya sama, saya gunakan ukuran VECTOR_SIZE=400, walaupun prosesnya jadi lebih lama dan filenya lebih besar.

from gensim.models import KeyedVectors
namaFileModel = "w2vec_glove_wiki_id.txt"
model = KeyedVectors.load_word2vec_format(namaFileModel)
hasil = model.most_similar("Bandung")
print("Bandung:{}".format(hasil))
hasil = model.most_similar("tempo")
print("tempo:{}".format(hasil))
hasil = model.most_similar("Tempo")
print("Tempo:{}".format(hasil))
hasil = model.most_similar("Soekarno")
print("Soekarno:{}".format(hasil))

sim = model.similarity("bakso", "nasi")
print("Kedekatan bakso-nasi: {}".format(sim))
sim = model.similarity("bakso", "pecel")
print("Kedekatan bakso-pecel: {}".format(sim))
sim = model.similarity("bakso", "mobil")
print("Kedekatan bakso-mobil: {}".format(sim))

hasil = model.most_similar_cosmul(positive=['perempuan', 'raja'], negative=['pria'])
print("pria-raja, perempuan-?: {}".format(hasil))

hasil = model.most_similar_cosmul(positive=['perempuan', 'raja'], negative=['lelaki'])
print("lelaki-raja, perempuan-?:{}".format(hasil))

hasil = model.most_similar_cosmul(positive=['minuman', 'mangga'], negative=['buah'])
print("buah-mangga, minuman-?:{}".format(hasil))

Hasilnya sebagai berikut

Bandung:[('Bogor', 0.5553832650184631), ('Surabaya', 0.5533844232559204), ('Jakarta', 0.5264717936515808), ('Medan', 0.5121393203735352), ('Semarang', 0.4910121262073517), ('Yogyakarta', 0.4880320131778717), ('Malang', 0.48358896374702454), ('Jawa', 0.4750467836856842), ('ITB', 0.4737907946109772), ('Persib', 0.4654899537563324)]
tempo:[('indonesiana', 0.5886592268943787), ('doeloe', 0.5427557229995728), ('putu_suasta', 0.48804518580436707), ('tapin', 0.46188244223594666), ('https', 0.41826149821281433), ('cepat', 0.40567928552627563), ('ketukan', 0.4037955701351166), ('irama', 0.3982717990875244), ('lambat', 0.39812949299812317), ('maestoso', 0.39417707920074463)]
Tempo:[('Majalah', 0.54466712474823), ('Koran', 0.5328548550605774), ('Doeloe', 0.5282064080238342), ('majalah', 0.4538464844226837), ('Kompas', 0.4463438391685486), ('wartawan', 0.4179822504520416), ('koran', 0.41709277033805847), ('Harian', 0.40668201446533203), ('Republika', 0.3915051221847534), ('Post', 0.38742369413375854)]
Soekarno:[('Hatta', 0.6839763522148132), ('Soeharto', 0.5900896787643433), ('Sukarno', 0.5895135998725891), ('Bung', 0.49154624342918396), ('Vannico', 0.4613707363605499), ('Megawati', 0.46065616607666016), ('Karno', 0.4603942334651947), ('Presiden', 0.4588601887226105), ('Ekki', 0.45219823718070984), ('WIII', 0.4458869993686676)]
Kedekatan bakso-nasi: 0.33218569528946
Kedekatan bakso-pecel: 0.3385669314106577
Kedekatan bakso-mobil: 0.1036423556873547
pria-raja, perempuan-?: [('Raja', 0.8700850605964661), ('kerajaan', 0.8684984445571899), ('Yehuda', 0.8591107130050659), ('cucu', 0.8312298059463501), ('AbiMilki', 0.821474552154541), ('memerintah', 0.8194707632064819), ('saudara', 0.8159937262535095), ('Daud', 0.8155518770217896), ('Kerajaan', 0.8149770498275757), ('penguasa', 0.8049719333648682)]
lelaki-raja, perempuan-?:[('Raja', 0.9214608669281006), ('kerajaan', 0.919419527053833), ('Kerajaan', 0.8668190240859985), ('AbiMilki', 0.8551638722419739), ('ratu', 0.8542945384979248), ('penguasa', 0.8345737457275391), ('terakhir', 0.8345482349395752), ('disebutkan', 0.8269140720367432), ('istana', 0.82608562707901), ('istri', 0.8246856331825256)]
buah-mangga, minuman-?:[('beralkohol', 0.7880735397338867), ('Schorle', 0.7836616039276123), ('bersoda', 0.7783095240592957), ('manggaan', 0.7711527943611145), ('jeruk', 0.7603545784950256), ('anggur', 0.7549997568130493), ('Minuman', 0.7476464509963989), ('Frappuccino', 0.740592360496521), ('jahe', 0.7360817790031433), ('mocha', 0.7357983589172363)]

Penasaran, berikut hasil kalau vector_size-nya 50 (default)

Bandung:[('Surabaya', 0.8777784109115601), ('Malang', 0.8505295515060425), ('Jakarta', 0.8406218886375427), ('Medan', 0.8344693183898926), ('Semarang', 0.8225082159042358), ('Yogyakarta', 0.8207614421844482), ('Bogor', 0.8181610703468323), ('Makassar', 0.7571447491645813), ('Tangerang', 0.7515754699707031), ('Solo', 0.7264706492424011)]
tempo:[('doeloe', 0.7084428668022156), ('indonesiana', 0.6802346706390381), ('read', 0.6363065242767334), ('pas', 0.6065201759338379), ('indonesia', 0.5810031890869141), ('pda', 0.5744251608848572), ('putu_suasta', 0.5698538422584534), ('nada', 0.5527507066726685), ('html', 0.5519558787345886), ('irama', 0.5514932870864868)]
Tempo:[('Koran', 0.8052877187728882), ('Majalah', 0.7781724333763123), ('Kompas', 0.7708441019058228), ('Gramedia', 0.7339286208152771), ('Penerbit', 0.7299134731292725), ('Harian', 0.7244901657104492), ('Republika', 0.7203424572944641), ('koran', 0.7195203900337219), ('KOMPAS', 0.7062090635299683), ('Doeloe', 0.7039147615432739)]
Soekarno:[('Hatta', 0.876067042350769), ('Sukarno', 0.8076358437538147), ('Soeharto', 0.7557047605514526), ('Bung', 0.7302334308624268), ('kemerdekaan', 0.7065078616142273), ('Karno', 0.6804633736610413), ('Basuki', 0.6803600788116455), ('Kemerdekaan', 0.6702237129211426), ('Yudhoyono', 0.6673594117164612), ('Susilo', 0.6618077754974365)]
Kedekatan bakso-nasi: 0.6207393500954625
Kedekatan bakso-pecel: 0.5784330569151002
Kedekatan bakso-mobil: 0.28361517810153536
pria-raja, perempuan-?: [('Yehuda', 0.9973295331001282), ('memerintah', 0.9838510155677795), ('Herodes', 0.9673323631286621), ('Raja', 0.9654756784439087), ('Daud', 0.9616796970367432), ('putranya', 0.9616104960441589), ('kerajaan', 0.9497379660606384), ('cucu', 0.9484671950340271), ('Firaun', 0.947074830532074), ('menantu', 0.9469170570373535)]
lelaki-raja, perempuan-?:[('kerajaan', 1.0183593034744263), ('memerintah', 1.0134179592132568), ('penguasa', 1.0113284587860107), ('Raja', 0.9971156716346741), ('Kerajaan', 0.9939565658569336), ('takhta', 0.9919894933700562), ('tahta', 0.9914684891700745), ('istana', 0.9877175092697144), ('kekuasaan', 0.983529269695282), ('MANURUNGNGE', 0.9810593128204346)]
buah-mangga, minuman-?:[('Arak', 1.0535870790481567), ('Crawlers', 0.9980041980743408), ('Carpet', 0.9971945285797119), ('Rimpang', 0.

Sepertinya untuk analogi lebih bagus Word2Vec. Berbeda dengan word2vec, Bakso-nasi lebih dekat dibandingkan bakso-pecel. Hasil kedekatan kata juga berbeda. Kalau lihat sekilas sepertinya lebih bagus Word2Vec, tapi saat saya coba untuk task NER, lebih bagus GloVe (naik dari 0.70 ke 0.72 untuk ukuran 50 sedangkan untuk ukuran vector 400 hasilnya hanya naik sedikit). Mungkin perlu buat dataset untuk evaluasi word embedding ini.

Update:
Jika mau men-train dokumen Bahasa Inggris di demo.sh ada fungsi untuk mengevaluasi, code pythonnya menggunakan Python2 dan lib numpy, jika ingin menggunakan virtualenv, langkahnya sbb:

masuk ke direktory Glove,
mkdir virtenv
virtualenv -p /usr/bin/python2 virtenv
source virtenv/bin/activate
pip install numpy

Update demo.sh sebelum pemanggilan evaluate:

source virtenv/bin/activate
python eval/python/evaluate.py

12 tanggapan untuk “GloVe untuk Wikipedia Bahasa Indonesia”

  1. Selamat pagi pak, bolehkah saya meminta hasil traing glove dengan bahasa Indonesia? Karena saya sudah mencoba cara yg bapak jelaskan diatas, namun masih belum bisa. Terimakasih pak

    1. Lumayan besar kalau diupload (perasaan dulu saya pernah upload tapi lupa dimana). Saran saya lebih baik cari library python, sudah ada beberapa (googling dengan keyword python glove).

  2. Selamat malam bapak, saat menggunakan perintah make sesuai step ke-2 di cmd muncul galat seperti ini :

    D:\PI\nlp\Glovee\GloVe-1.2>mingw32-make
    mkdir -p build
    gcc src/glove.c -o build/glove -lm -pthread -Ofast -march=native -funroll-loops
    -Wno-unused-result
    src/glove.c: In function ‘initialize_parameters’:
    src/glove.c:67:6: warning: implicit declaration of function ‘posix_memalign’ [-W
    implicit-function-declaration]
    a = posix_memalign((void **)&W, 128, 2 * vocab_size * vector_size * sizeof(rea
    l)); // Might perform better than malloc
    ^~~~~~~~~~~~~~
    C:\Users\GARRYD~1\AppData\Local\Temp\ccPP5xSX.o:glove.c:(.text+0xb73): undefined
    reference to `posix_memalign’
    C:\Users\GARRYD~1\AppData\Local\Temp\ccPP5xSX.o:glove.c:(.text+0xba5): undefined
    reference to `posix_memalign’
    collect2.exe: error: ld returned 1 exit status
    mingw32-make: *** [Makefile:12: glove] Error 1

    D:\PI\nlp\Glovee\GloVe-1.2>

    kira-kira kenapa yaa pak?
    terima kasih atas ilmunya..

      1. terima kasih atas respon yang diberikan..
        sudah dicoba bapak, setelah eksekusi program demo.sh program stuck pada ‘BUILIDING VOCABULARY processed 0 token’

    1. Glove dibuat setelah Word2Vec, jadi akan sulit cari paper yang menunjuukkan kelebihan Word2Vec daripada Glove. Tapi sekarang sih sudah banyak yang lebih baik Glove, jadi diskusi antara Glove vs Word2Vec sudah tidak relevan lagi.

  3. Selamat siang Pak, saya sudah mengikuti langkah-langkah yang Bapak berikan untuk melakukan embedding word dengan GloVe. Namun untuk hasil similarity dan lainnya, berbeda jauh dari yang Bapak hasilkan. Kira-kira itu karena faktor apa ya Pak?

    Untuk variablenya saya samakan dengan code pada artikel ini. Dengan korpora wikipedia terbaru dan dijalankan di linux. Terimakasih sebelumnya.

Tinggalkan komentar