Natural Language Processing (NLP)

Belajar mengembangkan model ML untuk pemrosesan bahasa manusia

Dadan Dahman W.
Howdy Sysinfo
10 min readJul 19, 2021

--

Berbeda dengan pemrosesan gambar yang telah kita pelajari, pemrosesan teks memiliki tantangan tersendiri seperti perbedaan panjang teks, bahasa, serta bagaimana merepresentasikan teks ke dalam format yang dapat diterima oleh sebuah model.

Materi yang akan dibahas pada modul ini antara lain:

  • Penggunaan Tokenizer
  • Implementasi Embedding
  • Layer LSTM
  • Klasifikasi teks 2 kelas dan multi-kelas

Pengenalan Tokenisasi dan Sequences

Mengembangkan model untuk masalah computer vision relatif lebih mudah karena nilai-nilai piksel pada gambar sudah dalam format bilangan numerik yang dapat diolah model. Namun bagaimana dengan teks dan kata-kata?

Salah satu cara yang dapat dilakukan adalah mengonversi setiap huruf pada sebuah kata ke dalam bilangan tertentu misalnya ke dalam format ASCII seperti di bawah.

Namun teknik ini memiliki masalah tersendiri karena, 2 buah kata berbeda dapat terdiri dari huruf-huruf yang sama seperti “Palu” dan “Lupa”. Walaupun 2 kata tersebut memiliki huruf-huruf yang sama, namun artinya sangat berbeda. Hal yang lebih baik dilakukan dibanding mengkonversi setiap huruf dalam kata, adalah dengan mengonversi setiap kata dalam sebuah kalimat ke bilangan tertentu. Dengan begini Setiap kata yang memiliki arti berbeda, akan diperlakukan berbeda oleh model. Seperti kata lupa dan palu.

Proses mengonversi kata-kata ke dalam bilangan numerik dapat kita sebut juga sebagai tokenisasi. Setelah melakukan tokenisasi pada teks, hal selanjutnya adalah mengubah setiap kalimat dalam teks kita ke dalam sequence. Sebuah sekuens adalah sebuah larik yang berisi kumpulan token sesuai dengan setiap kata pada sebuah kalimat dalam teks.

Dari contoh di atas dapat dilihat jika panjang kedua sequence tersebut tidak sama. Ingat pada kasus klasifikasi gambar bahwa, ukuran gambar yang berbeda harus diproses dahulu hingga ukurannya seragam agar bisa diproses oleh model ML. Begitu juga dengan teks. Setelah setiap kalimat pada teks dikonversi menjadi sequence, kita harus memastikan agar setiap sequence sama panjang agar bisa dilatih pada model.

Proses untuk mengubah setiap sequence agar memiliki panjang yang sama adalah padding. Pada padding, setiap sequence dibuat sama panjang dengan menambahkan nilai 0 secara sufiks atau prefiks hingga mencapai panjang maksimum sequence. Selain itu padding juga dapat memotong sequence hingga panjangnya sesuai dengan panjang maksimum sequence.

Latihan Tokenization

Pada latihan kali ini kita akan belajar bagaimana melakukan tokenization dan membuat sequence dari teks kita. Untuk menggunakan tokenizer, impor library di bawah.

Kemudian buat objek tokenizer dengan memanggil fungsi tokenizer dan melengkapi parameternya. Parameter num_words adalah jumlah kata yang akan dikonversi ke dalam token/bilangan numerik. Jika parameter num_words diisi 15, maka hanya 15 huruf yang paling sering muncul akan ditokenisasi dari seluruh kata pada dataset.

Sedangkan parameter oov_token adalah parameter yang berfungsi untuk mengganti kata-kata yang tidak ditokenisasi menjadi karakter tertentu. Pada praktiknya, lebih baik untuk mengganti kata yang tidak dikenali dengan suatu kata tertentu dibanding melewatkan kata tersebut untuk mengurangi informasi yang hilang. Hal inilah yang dapat dilakukan dengan menambahkan parameter OOV.

Lalu, buat teks yang akan kita tokenisasi dan kita pakai untuk pelatihan model.

Untuk melakukan tokenisasi, panggil fungsi fit_on_text() pada objek tokenizer dan isi teks kita sebagai argumennya.

Kemudian, kita akan mengubah kalimat ke dalam nilai yang sesuai dengan fungsi texts_to_sequences.

Untuk melihat hasil tokenisasi, kita bisa memanggil atribut word_index dari objek tokenizer. atribut word index mengembalikan dictionary berupa kata sebagai key dan token atau nilai numeriknya sebagai value. Perlu diperhatikan bahwa tanda baca dan huruf kapital tidak diproses oleh tokenizer. Contohnya kata “Selamat!” dan “SELAMAT” akan diperlakukan sebagai kata yang sama. Hasil dari cell di bawah menunjukkan bahwa kata-kata yang out-of-vocabulary akan diberi token bernilai 1.

Contoh OOV seperti di bawah. Kata ‘belajar’, ‘sejak’, dan ‘SMP’ tidak ada memiliki token pada dictionary hasil tokenisasi. Tanpa OOV, sequence yang dihasilkan akan seperti output pada baris pertama di mana, kata yang tidak memiliki token tidak dimasukkan pada sequence. Jika kita menggunakan OOV, maka setiap kata yang tidak memiliki token akan diberikan token yang seragam. Dengan OOV, informasi urutan setiap kata pada kalimat tidak hilang.

Setelah tokenisasi, untuk mengubah kalimat ke dalam nilai-nilai yang sesuai dapat dengan menggunakan fungsi text_to_sequence() dan masukkan parameter dari teks kita. Ketika sequence telah dibuat, hal yang perlu kita lakukan adalah padding. Yup, padding adalah proses untuk membuat setiap kalimat pada teks memiliki panjang yang seragam. Sama seperti melakukan resize gambar, agar resolusi setiap gambar sama besar. Untuk menggunakan padding impor library pad_sequence. Kemudian buat panggil fungsi pad_sequence() dan masukkan sequence hasil tokenisasi sebagai parameternya.

Hasil setelah padding adalah setiap sequence memiliki panjang yang sama. Padding dapat melakukan ini dengan menambahkan 0 secara default pada awal sequence yang lebih pendek

Jika kita ingin merubah sehingga 0 ditambahkan di akhir sequence, kita dapat menggunakan parameter padding dengan nilai ‘post’. Selain itu kita dapat mengatur berapa maksimum panjang setiap sequence dengan parameter maxlen dan nilai yang kita inginkan. Jika kita mengisi nilai 5, maka panjang sebuah sequence tidak akan melebihi 5.

Jika teks kita memiliki panjang lebih dari nilai parameter maxlen misalnya 5, maka secara default nilai dari sequence akan diambil 5 nilai terakhir atau 5 kata terakhir saja dari setiap kalimat. Untuk mengubah pengaturan ini dan mengambil 5 kata terakhir dari tiap kalimat, kita dapat menggunakan parameter truncating dan mengisi nilai ‘post’.

Embedding

Pada klasifikasi teks, kita perlu melakukan embedding yang merupakan kunci dalam klasifikasi teks di Tensorflow. Embedding memungkinkan model ML untuk memahami makna di setiap kata dan mengelompokkan kata-kata dengan makna yang mirip agar berdekatan. Misalnya komentar pada sebuah video youtube, di mana kata-kata “menarik”, “keren”, dan “luar biasa” akan dikelompokkan berdekatan. Pengelompokkan ini dapat dicapai dengan memetakan setiap kata ke dalam vektor atau larik. Di mana kata yang mirip akan memiliki nilai vektor yang mirip.

Makna dari sebuah kata didapat dari label dari data tersebut. Misalnya pada teks yang berlabel negatif terdapat banyak kata ‘membosankan’, dan ‘jelek’. Maka kedua kata tersebut memiliki makna yang mirip sehingga nilai vektor mereka mirip. Informasi lebih detail mengenai Embedding dapat Anda lihat pada tautan berikut

Untuk mengimplementasikan Embedding pada Keras juga sangatlah mudah. Pada model sequential, kita tinggal memanggil fungsi Embedding() dan mengisi parameter total kata yang di tokenisasi, panjang kalimat, serta dimensi embedding yang diinginkan. Karena hasil dari embedding merupakan larik 2 dimensi yang berisi panjang setiap kalimat, dan dimensi embedding, maka kita memerlukan fungsi flatten().

Setelah mengimplementasikan Embedding pada model sekuensial kita, panggil fungsi compile. Untuk optimizer, kita dapat menggunakan optimizer yang telah kita pelajari sebelumnya. Sedangkan loss disesuaikan dengan kelas yang terdapat pada dataset.

Untuk fungsi fit, kita memerlukan parameter teks yang telah di-padding, label dari data training, jumlah epoch, serta data validasi.

Dapat dilihat pada penjelasan sebelumnya bahwa pengembangan model untuk NLP tidak jauh berbeda dengan kasus klasifikasi gambar.

Binary Text Classification

Sebelumnya kita telah belajar bagaimana melakukan tokenisasi dan membuat sequence dari setiap kalimat pada teks. Bayangkan jika Anda memiliki restoran dan Anda memiliki ratusan ribu review pelanggan. Anda menginginkan agar membedakan antara review positif dan negatif menjadi terotomasi sehingga Anda dapat memfilter review pelanggan dengan mudah.

Untuk latihan kali ini kita akan menggunakan dataset Yelp yang berisi review dari beberapa restoran di Amerika Serikat. Dataset terdiri dari 2 kelas yaitu 0 dan 1 yang menunjukkan apakah review tersebut positif atau negatif. Dataset dapat diunduh pada tautan ini.

Setelah dataset diunduh, kita load dataset pada Colaboratory. Dan pastinya kita buat dataframe dari dataset kita agar lebih mudah diproses.

Untuk melihat 5 sampel terakhir dari dataset kita, panggil fungsi tail().

Setelah itu kita bagi dataset menjadi train dan test set.

Agar teks dapat dipahami oleh model, kita harus lakukan tokenisasi. Gunakan fungsi tokenizer pada data latih dan data test. Jangan lupa gunakan fungsi pad_sequences agar setiap sequence sama panjang.

Untuk arsitektur yang akan digunakan adalah layer embedding, dengan argumen pertama sesuai dengan jumlah vocabulary/kata yang kita pakai pada tokenizer. Argumen selanjutnya adalah dimensi embedding, dan input_length yang merupakan panjang dari sequence. Nah di kita tidak menggunakan layer Flatten melainkan kita menggantinya dengan GlobalAveragePooling1D. Fungsi ini bekerja lebih baik pada kasus NLP dibanding Flatten.

Setelah arsitektur model dibentuk, dan loss function serta optimizer ditentukan, kita dapat memulai pelatihan model kita. Di sini penulis menggunakan 30 epoch. Anda bebas bereksperimen dengan nilai yang lain.

Hasil dari pelatihan model kita menunjukkan akurasi yang cukup baik dengan data yang sangat sedikit.

Long Short-Term Memory (LSTM) Layer

Sebelumnya kita telah belajar mengenai embedding untuk mengelompokkan kata yang memiliki kemiripan makna. Namun pada klasifikasi teks, kita tidak dapat hanya memahami sebuah kalimat berdasarkan kata-kata saja. Misalnya kalimat “Saya suka programming”, dan “Saya tidak suka programming”, sama-sama memiliki kata suka di dalamnya namun, makna kedua kalimat tersebut berlawanan. Jadi urutan kata-kata juga sangat berpengaruh dalam arti sebuah kalimat.

Teori di balik LSTM sangatlah rumit seperti di atas. Namun kita akan menggunakan contoh sederhana yang mudah Anda pahami. Bayangkan kalimat berikut.

“Di Indonesia, salah satu olahan nasi paling populer adalah nasi…”

Anda kemungkinan akan menjawab nasi goreng. Kenapa Anda menjawab seperti itu? Karena adanya petunjuk pada kata Indonesia dan populer. Dapat kita lihat bahwa konteks dari sebuah kata, dipengaruhi oleh kata-kata yang mendahuluinya. Jaringan saraf dapat melakukan hal ini dengan menggunakan LSTM. Long Short-Term Memory (LSTM) adalah teknik yang umum digunakan dalam pemrosesan bahasa alami yang memungkinkan agar model dapat memahami makna sebuah kalimat berdasarkan urutan kata, seperti pada contoh nasi goreng kita.

Untuk mengimplementasikan LSTM sendiri sangatlah mudah pada Keras. Kita cukup menambahkan layer LSTM dan mengisi parameter dengan jumlah output yang diinginkan dari layer tersebut. Contoh penggunaan LSTM dapat dilihat pada kode di bawah. Kita dapat meletakkan layer LSTM setelah layer embedding dan sebelum Dense layer.

Multiclass Text Classification

Pada latihan kali ini kita akan melakukan klasifikasi teks multikelas menggunakan lstm.

Pada latihan ini kita akan menggunakan dataset yang berisi sinopsis dari beberapa film Indonesia dan genrenya. Tujuan kita adalah menentukan genre sebuah film berdasarkan sinopsisnya. Dataset dapat Anda unduh pada tautan berikut.

Pada cell pertama impor library pandas dan ubah dataset menjadi dataframe. Kemudian buang kolom ‘judul_film’ karena kita hanya akan menggunakan sinopsis sebagai atribut untuk dilatih pada model.

Panggil fungsi head() pada dataframe untuk menampilkan 5 sampel teratas pada dataset.

Karena label kita berupa data kategorikal, maka kita perlu melakukan proses one-hot-encoding. Jalankan kode di bawah untuk melakukan one-hot-encoding dan membuat dataframe baru.

Berikut adalah tampilan dari dataframe yang telah kita proses.

Agar dapat diproses oleh model, kita perlu mengubah nilai-nilai dari dataframe ke dalam tipe data numpy array menggunakan atribut values.

Lalu, bagi data untuk training dan data untuk testing.

Kemudian kita ubah setiap kata pada dataset kita ke dalam bilangan numerik dengan fungsi Tokenizer. Setelah tokenisasi selesai, kita perlu membuat mengonversi setiap sampel menjadi sequence.

Untuk arsitektur model kita menggunakan layer Embedding dengan dimensi embedding sebesar 16, serta dimensi dari input sebesar nilai num_words pada objek tokenizer. Jangan lupa panggil fungsi compile dan tentukan optimizer serta loss function yang akan dipakai oleh model.

Terakhir kita dapat mulai melatih model kita dengan memanggil fungsi fit().

Akurasi dari model kita menunjukkan terjadinya overfitting karena akurasi pada data testing sangat besar, sedangkan akurasi pada data validasi jauh lebih kecil. Hal ini masih sangat luar biasa karena kita hanya memiliki 1000 buah sampel data!

Akhirnya kita telah paham bagaimana mengembangkan model ML untuk salah satu kasus NLP yaitu klasifikasi teks. Ada telah paham bagaimana memproses teks, serta menggunakan Embedding dan LSTM layer pada arsitektur modul Anda.

--

--