Word Embedding Bahasa Indonesia menggunakan Fasttext (Part 1)

Mengenal Word Embedding

Word embedding mudahnya adalah istilah yang digunakan untuk teknik mengubah sebuah kata menjadi sebuah vektor atau array yang terdiri dari kumpulan angka.

Ketika kita akan membuat model machine learning yang menerima input sebuah teks, tentu machine learning tidak bisa langsung menerima mentah-mentah teks yang kita miliki. Cara “tradisional” untuk membaca teks tersebut adalah sebagai berikut:

  1. Buat kamus kata dengan cara mendaftar semua kata yang ada di dataset
  2. Setiap menerima sebuah string kata, string tersebut diubah menjadi sebuah integer dengan memberinya nomor. Penomoran ini bisa ditentukan berdasarkan urutan di kamus kata yang kita miliki. Misalnya pada ilustrasi di bawah, string “Makan” menjadi angka 3, string “Lari” menjadi angka 5, dst.
  3. Angka-angka tersebut kita ubah lagi menjadi sebuah vektor (array 1 dimensi) yang memiliki panjang sepanjang banyak kata yang kita miliki di kamus. Array tersebut hanya akan bernilai 1 atau 0 (disebut one hot encoding). Nilai 1 diposisikan pada indeks yang merupakan nomor kata tersebut sedangkan elemen lainnya bernilai 0. Contohnya untuk kata “makan”, dengan banyak kosakata yang kita miliki adalah 100 kata, maka dari kata tersebut kita akan memperoleh sebuah vektor dengan panjang 100 yang berisi 0 semua kecuali pada posisi ke 3 yang bernilai 1.
Ilustrasi mengubah string menjadi one-hot encoding

Nah coba saja bayangkan kamus kita ukurannya mencapai 10,000 kata, maka untuk setiap katanya akan di-convert menjadi vektor ukuran 10,000 yang hampir semua elemennya bernilai 0 semua. Metode ini selain kurang efisien dalam memori juga tidak memberikan banyak informasi.

Dengan metode word embedding kita dapat mengubah kata menjadi sebuah vektor yang berisi angka-angka dengan ukuran yang cukup kecil untuk mengandung informasi yang lebih banyak. Informasi yang diperoleh akan cukup banyak sampai-sampai vektor kita akan dapat mendeteksi makna, seperti kata “marah” dan “mengamuk” itu lebih memiliki kedekatan nilai ketimbang kata “marah” dengan “bahagia”.

Apa itu FastText?

FastText adalah library yang dikeluarkan oleh Facebook yang dapat digunakan untuk word embedding. Sebenarnya, FastText sendiri adalah pengembangan dari library Word2Vec yang telah lebih lama terkenal sebagai library untuk word embedding.

FastText memiliki keunggulan dibanding Word2Vec. Salah satunya adalah kemampuan FastText untuk menangani kata yang tidak pernah kita jumpai sebelumnya (Out Of Vocabulary word atau dikenal OOV). Misalnya kata-kata yang tidak baku seperti “Pengoptimalisasian” tetap akan diperoleh vektornya. Library Word2Vec ataupun teknik one hot encoding tradisional yang seperti dijelaskan sebelumnya akan menghasilkan eror ketika menerima kata yang tidak pernah ada di kamus.

FastText memberikan opsi untuk menggunakan salah satu dari dua algoritma utama, yakni CBOW dan Skipgram. Kedua algoritma tersebut menggunakan bantuan Neural network untuk mendapatkan model terbaik yang mampu merepresentasikan sebuah kata dalam vektor.

PreTrained FastText Bahasa Indonesa

Ada banyak cara menggunakan library FastText untuk kasus Bahasa Indonesia, cara paling mudah adalah dengan menggunakan Pretrained model, atau model yang telah dilatih oleh seseorang sehingga kita tinggal menggunakannya tanpa harus melatihnya terlebih dahulu.

Model resmi (terdapat lebih dari 150 bahasa) bisa di download di sini. Model tersebut dibuat berdasarkan paper oleh Edouard Grave, dkk yang berjudul Learning Word Vectors for 157 Languages. Bersyukurnya, bahasa Indonesia ada di antara 157 bahasa tersebut.

Saat akan mendownload, kalian akan sadar terdapat 2 jenis model yang disediakan oleh FastText, yakni cc.id.300.vec.gz dan cc.id.300.bin.gz. Jika diperhatikan sekilas dari nama filenya, tampak simbol id berarti itu adalah model bahasa Indonesia dan angka 300 menunjukkan besar dimensi vektornya.

Untuk bagian vec/bin menunjukkan tipe model tersebut, vec menunjukkan model tersebut hanyalah berupa text file yang berisi kamus daftar vector untuk setiap kata (perlu membuat program sendiri untuk mengatasi OOV), sedangkan bin menunjukkan file tersebut adalah file binary siap pakai dengan termasuk di dalamnya file .vec, algoritma untuk mengatasi OOV, catatan hyperparameter untuk melatih ulang, dsb.

Perlu diketahui, FastText hanya menyediakan pretrained model berupa model binary FastText (.bin) atau text file kumpulan kata beserta vektornya (.vec). Untuk menggunakan model atau text file tersebut pada proses word embedding kita akan menggunakan library lain lagi, yakni Gensim.

Menggunakan Gensim

Bagi pengguna Python, sebenarnya terdapat dua libray besar yang bisa kita gunakan untuk word embedding menggunakan FastText, yang pertama adalah library Python FastText bawaan asli, dan yang kedua adalah Gensim, library yang lebih umum untuk word embedding namun juga telah support FastText.

Di sini kita akan menggunakan Gensim untuk menggunakan model FastText. Install terlebih dahulu menggunakan perintah berikut:

Lalu import di program python menggunakan perintah:

Dalam Gensim saat ini cara paling mudah untuk me-load pretrained model FastText adalah menggunakan load_fasttext_format (lihat bagian Catatan). Fungsi tersebut membutuhkan file *.bin dari pretrained model. Kita bisa download terlebih dahulu file *.bin tersebut (~4-5GB) dari halaman resmi FastText.

Setelah berhasil terdownload, unzip file tersebut terlebih dahulu, lalu kita bisa memanggil model tersebut dengan perintah berikut:

Dan kita bisa uji model yang telah kita load dengan kode berikut:

Dapat dilihat pada program di atas kata “algoritmatik” tidak ada di kamus model yang kita gunakan (False), tetapi FastText tetap bisa menghasilkan nilai vektor untuk kata tersebut sehingga bisa dicari kata mirip terdekatnya (algoritma).

Untuk melihat nilai vektor dari kata “algoritmatik” kita bisa memunculkan dengan cara:

Penutup

Salah satu kekurangan menggunakan pretrained model adalah ukuran yang luar biasa besar (~7GB setelah di ekstrak), hal ini membuat kita pengguna komputer yang memiliki RAM kecil kesulitan untuk menggunakannya.

Kita bisa menggunakan Google Colab untuk menangani masalah tersebut, tetapi ada metode lain yang bisa kita gunakan, yakni kita coba melatih model kita sendiri. Dengan melatih sendiri kita bisa lebih mengatur ukuran model menyesuaikan kebutuhan. InsyaAllah proses melatih word embedding akan berlanjut di Part 2. Baca juga kelanjutan penggunaan Fasttext dengan library aslinya di Part 1.5

Catatan Seputar Gensim:

Di versi terbaru Gensim (> 3.7.2), kita disarankan menggunakan dua metode lain untuk me-load pretrained model, yakni menggunakan load_facebook_vectors atau load_facebook_model. Kedua fungsi tersebut merupakan fungsi yang telah diperbarui dari fungsi load_fasttext_format sehingga seharusnya lebih cepat.

Namun, ketika tulisan ini di tulis masih ada sebuah bug yang membuat belum bisa digunakannya fungsi tersebut. Jika bug ini sudah diperbaiki insyaAllah akan ada update untuk tulisan ini

Sumber featured image Pexels.com

Belajar Machine Learning via StackExchange

Salah satu yang menantang menurut saya untuk belajar Artificial Intelligence/Machine Learning/Data Mining adalah untuk belajar saja, kadang kita perlu menuliskan sintaks kode yang lumayan panjang dan kompleks. Mulai dari merapikan data, preprocessing, feature extraction, sampai proses utamanya sendiri. Kadang hal ini yang bikin jadi down dulu sebelum memulai belajar, apalagi bagi kita yang kesulitan meluangkan banyak waktu untuk sekadar latihan.

Nah, salah satu solusi belajar yang saya temui cukup membantu saya adalah dengan aktif di ruang diskusi yang membahas Machine Learning di internet. Salah satu forum diskusi yang cukup baik menurut saya adalah forum-forum terbitan StackExchange, seperti Stackoverflow, CrossValidated, atau AIStackExchange. Bagi kita programmer, saya yakin nama-nama itu bukanlah nama yang asing. Walau bukan benar-benar “forum diskusi” (situs StackExchange adalah situs tanya jawab atau QA site) situs-situs tersebut cukup baik untuk digunakan sebagai sarana belajar.

Salah satu sisi positif yang saya rasakan dari aktif di StackExchange kita bisa belajar dengan memperdalam logika dan teori dengan waktu yang relatif lebih singkat, tanpa harus membuat kode yang cukup panjang.

Note: aktif di forum hanyalah salah satu alternatif bagi teman-teman yang kesulitan meluangkan waktu banyak tapi tetap ingin belajar. Namun, bagi teman-teman yang ingin serius mendalami bidang ini, saya tetap sangat menyarankan untuk meluangkan waktu khusus untuk belajar untuk menyelesaikan kasus-kasus dan coding dari scratch.

Belajar Machine Learning via StackExchange

Ada beberapa cara bagi yang ingin belajar machine learning via stackexchange. Bisa dengan cara membaca-baca pertanyaan yang telah dijawab, aktif bertanya, ataupun aktif menjawab.

Belajar dari Pertanyaan Orang Lain

Cobalah mencari pertanyaan yang setopik dengan materi yang ingin kalian perlajari. Telusuri satu persatu pertanyaan yang sudah pernah ditanyakan, siapa tahu kalian menemukan pertanyaan atau jawaban yang menarik yang sebenarnya cukup penting untuk ditanyakan tapi kita tidak pernah terpikirkan.

Seperti pertanyaan yang baru-baru ini saya temui: kenapa kita menggunakan istilah “Machine Learning”, bukan “Program Learning” atau Bisakah kita menggunakan Neural Network untuk mendeteksi suatu bilangan ituΒ  prima atau bukan.

Dengan melihat jawaban orang lain kita juga jadi bisa menambah wawasan dengan menemukan solusi solusi menarik bagaimana orang menyelesaikan masalahnya.

Berani Bertanya

Tidak ada salahnya untuk bertanya asal dengan cara yang baik. Ada dua cara untuk kita bertanya di StackExchange, yang pertama kita bisa membuat pertanyaan baru, dan yang kedua adalah bertanya untuk meminta kejelasan jawaban via kolom komentar (ini butuh reputasi).

Untuk membuat pertanyaan baru, pastikan terlebih dahulu pertanyaan itu belum pernah ditanyakan sebelumnya. Untuk lebih yakin, cobalah googling kembali pertanyaan itu, atau bahkan lakukan parafrase jika perlu. Selain itu, pastikan juga kalian sudah membaca aturan singkat di halaman tour yang selalu ada di situs StackExchange manapun.

Contohnya di StackOverflow kalian akan mengenal istilah MVCE (Minimum Veriviable Complete Example), yakni sebuah aturan bagaimana memberikan contoh program kita yang eror secara minimalis. Secara tidak langsung, kita akan belajar bagaimana menjelaskan eror pada program kita secara baik kepada orang lain.

Note: Ingat, jika ingin mendapat jawaban yang baik, maka bertanyalah dengan cara baik.

Mencoba Memberi Jawaban

Selalu ada ilmu yang bisa kita bagi! Cobalah cari pertanyaan-pertanyaan sederhana yang sekiranya bisa kita jawab. Dengan mencoba menjawab beberapa pertanyaan, kita akan belajar untuk memahami lebih dalam materi yang kita pelajari. Kalau ada orang bilang, dengan mengajar ilmu kita bertambah, maka benar saja, dengan mencoba menjawab pertanyaan-pertanyaan di sana kita akan semakin bertambah wawasannya. Kita akan belajar bagaimana menjelaskan dan memberi contoh yang menjawab pertanyaan pengguna lain.

Takut di-downvote πŸ™

Ketika memberi jawaban atau pertanyaan, tentunya kita akan mendapat beragam feedback entah dari pengguna lain atau dari si-penanya. Mulai dari komentar, flag, atau downvote. Jangan minder jika ada feedback negatif, toh, namanya juga belajar dan diskusi πŸ™‚ Manusia tidak ada yang sempurna untuk luput dari kesalahan dan juga tidak semua manusia baik dan ramah untuk berdiskusi. Gunakan hal tersebut sebagai pengalaman untuk menjawab di kemudian hari.

Saya juga masih beberapa kali dapat komentar pedas atau “flag” pada pertanyaan saya karena tidak sesuai topik, tetapi bukan berarti lalu saya akan menghakimi forum tersebut tidak ramah dan melepas kesempatan saya belajar di sana.

Mulai Belajar!

Banyak pengalaman dan ilmu yang saya peroleh dengan aktif di StackExchange. Saya ingat bagaimana StackExchange telah membantu saya tidak hanya menyelesaikan skripsi saya, tetapi juga memahami lebih dalam tools yang saya gunakan. Selain itu semenjak aktif di StackExchange, saya juga merasa banyak terlatih untuk berkomunikasi dengan bahasa inggris secara natural. Jadi, Jangan ragu untuk memulai πŸ˜‰ Semoga Bermanfaat!

Sumber gambar: Pexels

simple neural net

Neural Net in 4 lines! using Scikit-Learn MLPClassifier

See the code below:

That’s right, those 4 lines code can create a Neural Net with one hidden layer! 😐

Scikit-learn just released stable version 0.18. One of the new features is MLPClassifer and you can see in the code above, it’s powerful enough to create a simple neural net program.

That code just a snippet of my Iris Classifier Program that you can see on Github. Of course, in practice, you still need to create loader, pre-process, pre-training, or other modules. But, if you see other python libraries like Keras, Lasagne, or Theano, I think this is the easiest way to create a simple neural net. I said “simple” because when you need to create more complex model that need more complex algorithm or many addons, I think it’ll become difficult to use MLPClassifier. But, for some simple project, I think I’ll choose this scikit tool πŸ™‚

Program Explanation

Line 1: you need to load MLPClassifier

Line 2: we create an object called ‘mlp’ which is a MLPClassifier. We set hidden_layer_size to (10) which means we add one hidden layer with 10 neurons. Then we set solver as ‘sgd’ because we will use Stochastic Gradient Descent as optimizer. Then we set learning_rate_init to 0.01, this is a learning rate value (be careful, don’t confuse with alpha parameter in MLPClassifer). Then the last, we set 500 as the maximum number of training iteration.

Line 3: Train the model

Line 4: Test the model

That’s it! and my first run I got more than 90% accuration in Iris Dataset πŸ™‚ try it!

And actually, you can create “Deeper” neural net with add more layers easily, just change hidden_layer_sizes. For example, hidden_layer_sizes=(10,10,10) will create 3 hidden layer with 10 neuron each.

source image: Flickr

Parser Kalimat Sederhana untuk Bahasa Indonesia

Beberapa waktu lalu saya mendapat tugas kerja untuk membuat sebuah text summarizer (perangkum bacaan) menjadi sebuah kalimat sederhana. Istri saya yang lebih mendalami bidang NLP menyarankan untuk menggunakan teknik yang sederhana:

Temukan kalimat utama, dan jadikan kalimat tersebut sebagai rangkuman.

Saya setuju ide itu, selain tidak serumit jika mengunakan machine learning yang kompleks, rasanya cara itu sudah cukup cocok untuk kasus saya. Istri saya memberi tahu saya beberapa algoritma yang bisa digunakan dan sebuah peringatan bahwa bagian paling sulit adalah nanti bagaimana membuat parser kalimat (program yang dapat mengekstrak kalimat-kalimat yang menyusuk sebuah dokumen teks).

Saya buat parser ini menggunakan bahasa pemrograman Python, dengan bantuan beberapa package (re untuk regex, dsb.).

Split berdasar penanda akhir kalimat

Percobaan pertama yang saya lakukan adalah menggunakan regex untuk men-split data teks berdasarkan beberapa karakter yang biasa menjadi penanda akhir dari sebuah kalimat. Karakter pemisah yang saya gunakan awalanya aadalah tanda titik (“.”), tanda tanya (“?”), dan tanda seru (“!”) yang setelahnya terdapat sebuah spasi atau sudah di akhir dokumen.

Setelah coba dijalankan, saya menemukan beberapa fakta menarik. Pertama, seharusnya saya tidak perlu memisahkan berdasarkan tanda tanya dan tanda seru karena kedua tanda tersebut hanya muncul di kalimat langsung yang tidak perlu di split. Jadi berikutnya kita cukup split di tanda titik.

Kedua, asumsi saya menggunakan tambahan “sebuah spasi setelah karakter” ternyata benar-benar bermanfaat karena parser akhirnya tidak men-split tanda titik yang bukan akhir kalimat, misalnya 6.700 korban.

Kalimat langsung

“Roses are red. Violets are Blue,” said Hugo.

Dalam kasus saya, kalimat di dalam kalimat langsung tidak boleh dipisah. Untuk menghindari pemisahan, perlu dibuat aturan khusus (saya rasa ini bisa di-handle menggunakan regex). Ide saya sementara ini dengan membuat variabel untuk mengecek sebuah simbol pemisah ada di dalam double quote atau tidak, lalu jika tanda titik misalnya ada di antara double quote, maka kita beri “tanda” agar tidak di split.

“Tanda” agar tidak di-split

Untuk menandai sebuah simbol tidak boleh di split, saya sisipkan simbol yang unik (yang saya yakin tidak akan muncul di dokumen saya) sebelum dan setelah tanda titik. Saya gunakan simbol @#...@#.

“Roses are red@#.@# Violets are Blue,” said Hugo.

Mengatasi Singkatan

Ini adalah bagian yang juga sulit, misalnya ada kalimat:

Tadi malam saya bertemu H. Akbar M. dan drs. Rian. Kami adalah sahabat dekat dulunya.

Jika diperhatikan tanda titik setelah huruf “H” dan huruf “M”, bukanlah tanda akhir dari kalimat, begitu juga tanda titik setelah “drs”. Tanda titik yang digunakan untuk memisah kalimat adalah setelah kata “Rian”.

Awalnya saya berpikir untuk tidak mensplit tanda titik yang sebelumnya hanya satu huruf, tapi “drs” lebih dari satu huruf dan juga merupakan singkatan. Kita harus menemukan sebuah kata adalah singkatan atau bukan.

Deteksi singkatan

Pada projek ini ada dua aturan yang gunakan:

  1. Jika kata sebelum tanda titik hanya terdiri dari satu huruf, maka itu adalah singkatan. Contoh: “M.”, “H.”
  2. Jika tidak, maka cek terlebih dahulu di kamus singkatan (saya buat sendiri), jika ditemukan, maka kata tersebut singkatan. Contoh: “Prof.”, “Dr.”, “Hj.”, “dll.”, “Moch.”

Secara tidak langsung, aturan ini juga menangani singkatan panjang seperti “S.W.A.T.”. Setelah berhasil mendeteksi singkatan, dengan ide yang sama kita kasih “tanda” pada tanda titiknya, lalu split dengan fungsi regex seperti sebelumnya.

Hapus “tanda”

Setelah berhasil split kalimat, jangan lupa untuk menghilangkan simbol yang tadi kita gunakan sebagai “tanda”. Caranya bisa dengan manual seach atau dengan regex.

Program

Program bisa diakses di Google Colab berikut

Image from: https://museafrica.com

A* algorithm for puzzle

A* Algorithm in Python to solve 8 puzzle problem

My team got this as A* algorithm assignment in Artificial Intelligence class few years ago taught by Mrs. Afiahayati, Ph.D. We should create an implementation of A* algorithm (read: “A” Star) to solve 8 puzzle problem. This puzzle problem is the small version of 15 sliding puzzle game.

A* Algorithm

In my opinion A* Algorithm (read more about it here) is looks like combination of Breadth First Search (BFS) and Depth First Search (DFS) algorithm (or maybe Dijkstra’s too(?)). It’s using Heuristic scoring to estimate the step from vertex to goal so make the system may running faster, and like Dijkstra’s, it’s a complete search which always finding a best solution. Read this to get better explanation.

My team agreed to use Manhattan distance to estimate distance between the current state and the goal state (h) and count the number of step as exact cost (g).

Implementation

I wrote the code using Python. And after several hours coding I found python have a “magical” function that make easy to write πŸ™‚ My first implementation was not using any class at all and it made the code hard to read. After I saw this implementation, I realize that code is much prettier than mine, so I rewrite my code using Node class with similar class concept from that code.

See the complete source code on Github