Pengenalan Recurrent Neural Network (RNN) – Bagian 1

Jaringan saraf berulang atau recurrent neural network (RNN) adalah jenis arsitektur jaringan saraf tiruan yang pemrosesannya dipanggil berulang-ulang untuk memroses masukan yang biasanya adalah data sekuensial. RNN masuk dalam kategori deep learning karena data diproses melalui banyak lapis (layer). RNN telah mengalami kemajuan yang pesat dan telah merevolusi bidang-bidang seperti pemrosesan bahasa alami (NLP), pengenalan suara, sintesa musik, pemrosesan data finansial seri waktu, analisa deret DNA, analisa video, dan sebagainya. Hal-hal yang dapat dilakukan RNN dapat Anda baca misalnya di artikel Andrej Karpathy The Unreasonable Effectiveness of Recurrent Neural Networks.

Untuk mendalami RNN lebih lanjut, mari kita mulai dengan motivasi kenapa RNN diciptakan.

Pemrosean Data Sekuensial

Data sekuensial (sequence data) mempunyai karakteristik di mana sampel diproses dengan suatu urutan (misalnya waktu), dan suatu sampel dalam urutan mempunyai hubungan erat satu dengan yang lain.

Contoh-contoh data sekuensial dan aplikasinya misalnya:

  • rangkaian kata-kata dalam penerjemahan bahasa
  • sinyal audio dalam pengenalan suara
  • nada-nada dalam sintesa musik
  • rangkaian kata-kata dalam klasifikasi sentimen
  • deret DNA dalam pemrosesan rangkaian DNA
  • rangkaian gambar-gambar (frame) pada pengenalan aktivitas video
  • kata-kata dalam pengenalan nama entitas

Pemrosesan data sekuensial seperti di atas tidak cocok dilakukan dengan model umpan maju (feed forward) yang sudah kita kenal seperti model linear, multi-layer perceptron, dan CNN. Kendala utamanya adalah:

  • model-model ini tidak mempunyai “memori”; setiap sampel akan diproses secara sama tanpa ada konsiderasi atas sampel-sampel sebelumnya.
  • model-model tersebut mengasumsikan data yang IID (independent and identically distributed), dan hal ini tidak dapat dipenuhi oleh data sekuensial karena suatu sampel mempunyai ketergantungan yang erat dengan sampel-sampel lainnya.
  • model-model ini memroses masukan dengan panjang input yang tetap, sedangkan data sekuensial mempunyai panjang yang tidak tentu, dan bisa jadi sangat panjang.
  • model-model ini tidak bisa mengaplikasikan/men-generalisasikan fitur yang dipelajari di satu posisi ke posisi lain (misalnya model mengenali Joni sebagai nama orang di posisi awal kalimat, seharusnya model juga mengenali Joni sebagai nama orang ketika dia muncul di posisi lain dalam kalimat).

Pentingnya mempunyai “memori” dapat kita lihat di contoh-contoh berikut. Misalnya kita melakukan analisis sentimen pada ulasan ini:

Tidak ada yang membuat saya senang, tertawa, dan bahagia dalam film ini.

Sebuah model yang naif mungkin akan menyimpulkan bahwa kalimat di atas adalah ulasan positif, karena ada banyak kata-kata positif di kalimat di atas (“senang”, “tertawa”, “bahagia”). Padahal jauh di depan ada kata “tidak”.

Contoh lain:

Joni yang biasanya selalu memakai topi pergi ke toko sebelah.

Dalam konteks kalimat di atas, yang pergi ke toko adalah Joni, bukan topi, walaupun kata “topi” lebih dekat dengan kata “pergi”.

Intuisi RNN

RNN memroses input secara sekuensial, sampel per sampel. Dalam tiap pemrosesan, output yang dihasilkan tidak hanya merupakan fungsi dari sampel itu saja, tapi juga berdasarkan state internal yang merupakan hasil dari pemrosesan sampel-sampel sebelumnya (atau setelahnya, pada bidirectional RNN).

Berikut adalah ilustrasi bagaimana RNN bekerja. Misalnya kita membuat RNN untuk menerjemahkan bahasa Indonesia ke bahasa Inggris

Intuisi RNN - Translasi Bahasa
Ilustrasi di atas kelihatan rumit, tapi sebenarnya cukup mudah dipahami.

  • sumbu horizontal adalah waktu, direpresentasikan dengan simbol t. Dapat kita bayangkan pemrosesan berjalan dari kiri ke kanan. Selanjutnya kita sebut t adalah langkah waktu (time step).
  • Keseluruhan input adalah kalimat, dalam hal ini:

Budi pergi ke sekolah .

  • Pemrosean input oleh RNN adalah kata demi kata. Input kata-kata ini disimbolkan dengan x1 ,x2 , … ,x5 , atau secara umum xt.
  • Output adalah kalimat, dalam hal ini:

Budi goes to school .

  • RNN memberikan output kata demi kata, dan ini kita simbolkan dengan ŷ1ŷ2,  …, ŷ5 , atau secara umum ŷt .
  • Dalam tiap pemrosesan, RNN akan menyimpan state internal yaitu st, yang  diberikan dari satu langkah waktu ke langkah waktu berikutnya. Inilah “memori” dari RNN.

Dengan contoh di atas, kita bisa generalisasikan arsitektur RNN sebagai berikut.

Representasi RNN

Tambahan yang tidak terdapat di diagram sebelumnya adalah U, V, dan W, yang merupakan parameter-parameter yang dimiliki RNN. Kita akan bahas pemakaian parameter-parameter ini nanti.

Penting untuk dipahami bahwa walaupun ada empat kotak RNN di gambar di atas, empat kotak itu mencerminkan satu modul RNN yang sama (satu instans model dengan parameter-parameter U, V, dan W yang sama). Penggambaran di atas hanya agar aspek sekuensialnya lebih tergambar.

Alternatif representasinya adalah seperti ini, agar lebih jelas bahwa hanya ada satu modul RNN:

Representasi RNN (loop)

Inilah sebabnya kenapa arsitektur ini disebut RNN. Kata recurrent (berulang) dalam RNN timbul karena RNN melakukan perhitungan yang sama secara berulang-ulang atas input yang kita berikan.

Sering juga kedua ilustrasi di atas digabungkan jadi satu sbb:

RNN

Sesuai dengan gambar di atas, ilustrasi di sebelah kanan adalah penjabaran (unrolled) dari versi berulang di sebelah kiri.

Jenis-jenis Pemrosesan RNN

Banyak ke Banyak

Pada jenis ini, baik input dan output adalah data sekuensial yang jumlahnya banyak.

Kind - Many to Many

Contoh penggunaan jenis ini adalah:

  • translasi bahasa
  • pengenalan suara

Pada jenis ini jumlah output yang dihasilkan tidak harus sama dengan jumlah input, dan biasanya model akan menghasilkan output hanya setelah semua input selesai diproses, agar model dapat mengetahui sebanyak mungkin konteks untuk menghasilkan output.

Arsitektur seperti ini juga disebut encoderdecoder, di mana bagian encoder bertugas memroses input dan bagian decoder bertugas menghasilkan output. Pada gambar di atas, encoder dan decoder ditandai dengan huruf E dan D.

Banyak ke Satu

Pada jenis pemrosesan ini, model memroses banyak input, tapi output yang dihasilkan hanya satu.

Kind - Many to One

Contoh penggunaan jenis ini:

  • deteksi sentimen
  • nilai ulasan film otomatis

Pada aplikasi deteksi sentimen misalnya, input berupa kata-kata dan model akan memberikan satu output berupa nilai sentimen yang sesuai.

Satu ke Banyak

Pada jenis pemrosesan ini, model hanya membutuhkan satu input saja, namun bisa menghasilkan banyak output.

Kind - One to Many

Penggunaan arsitektur jenis ini terutama pada aplikasi sintesa, misalnya:

  • sintesa musik
  • sintesa esai

Misalnya pada sintesa musik, inputnya hanya satu misalnya jenis musik (jazz, dangdut, dsb), lalu model akan mensintesa nada demi nada sehingga menghasilkan musik yang bisa dinikmati.

Mekanisme Dasar RNN

Input dan Output

Tiap sampel input xt direpresentasikan sebagai sebuah vektor. Misalnya pada aplikasi translasi bahasa, tiap kata (xt) direpresentasikan dengan hot vector dari indeks kata itu dalam kosa kata.

Contoh:

  • Kata “anggrek” adalah kata ke-134 dalam kosa kata (vocabulary) yang besarnya 8,000 kata. Maka hot vector untuk merepresentasikan kata “anggrek” sebagai xt adalah:

Hot vector

  • Jadi hot vector adalah vektor yang semua elemennya nol, kecuali elemen yang dimaksudkan (yaitu elemen ke-134 dalam contoh di atas).

Output pada tiap langkah waktu (ŷt) berupa vektor juga. Dalam aplikasi translasi bahasa, output adalah probabilitas dari masing-masing kata dalam kosa kata untuk menjadi ŷt:

Output

Dengan contoh vektor output di atas, probabilitas kata pertama (misalnya “aardvark”)  sebagai output adalah 0.00042, probabilitas kata kedua adalah 0.00001, dsb.

Untuk memilih kata yang tepat sebagai ŷt, tinggal memilih kata dengan probabilitas tertinggi pada vektor output tersebut.

Propagasi ke Depan (Forward Propagation)

Misalkan kita tinjau RNN pada satu langkah waktu t.

Feed Forward

Untuk setiap langkah waktu t, pertama kita kalkulasi state st dari input (xt) dan state sebelumnya (st-1), masing-masing dikalikan dengan parameter U dan W lalu diproses dengan fungsi aktivasi tanh.

st = tanh( U · xt + W · st-1 )

(catatan: operator · adalah perkalian matriks)

Dari st kemudian dikalkulasi output ŷt dengan cara mengalikan dengan parameter V dan melewatkan pada fungsi aktivasi softmax:

ŷt = softmax( V · s)

Proses di atas juga sering divisualisasikan sebagai berikut.

RNN Feed Forward Visualization

Visualisasi seperti di atas sering kita temukan di artikel tentang RNN, dan akan kita pakai di artikel berikutnya, sehingga cukup penting untuk dikenal.

Dimensi-Dimensi

Ketika mendesain RNN, kita harus menentukan ada berapa unit dalam hidden layer kita untuk menyimpan state. Misalkan kita set 100 unit. Dengan 8000 kata dalam kosa kata, maka dimensi-dimensi dari input, output, dan parameter-parameter adalah:

x_t \in \mathbb{R} ^{8000} \\ \hat{y}_t \in \mathbb{R} ^{8000} \\ s_t \in \mathbb{R} ^{100} \\ U \in \mathbb{R} ^{100 \times 8000} \\ V \in \mathbb{R} ^{8000 \times 100} \\ W \in \mathbb{R} ^{100 \times 100} \\

Loss Function

Untuk tiap sampel di tiap langkah waktu (misalnya sebuah kata), fungsi loss-nya didefinisikan sebagai:

\mathcal{L}_t(y_t,\hat{y}_t) =- y_t \log \hat{y}_t

Jadi untuk suatu input (misalnya sebuah kalimat), loss function-nya adalah:

\mathcal{L}(y,\hat{y}) =- \frac{1}{T_x} \sum_{t =1 }^{T_x} y_t \log \hat{y}_t

Simbol Tmenyatakan jumlah sampel dalam input, sehingga kalkulasi di atas pada dasarnya adalah menjumlahkan kesalahan prediksi dari tiap sampel untuk tiap sampel dalam input.

Gradient Descent dan Backpropagation Through Time (BTT)

Tujuan dari training adalah untuk menemukan parameter U, V, dan W sehingga nilai loss di atas mencapai minimum. Cara yang paling umum adalah dengan menggunakan stochastic gradient descent (SGD). Dalam SGD, kita mengiterasi seluruh sampel dan dalam tiap iterasi parameter U, V, dan W digeser sedikit ke suatu arah yang mengecilkan loss. Arah untuk masing-masing parameter ditentukan oleh gradiennya, yaitu \frac{\partial L}{\partial U} \\  \frac{\partial L}{\partial V} \\  , dan \frac{\partial L}{\partial W} \\  .

Pada jaringan saraf tiruan biasa, gradien-gradien ini dikalkulasi dalam proses yang disebut backpropagation atau disingkat backprop. Secara umum, RNN juga melakukan backprop, namun ada hal yang khusus.

Karena parameter U, V, dan W (terutama U dan W) mengandung kalkulasi dari langkah waktu langkah waktu sebelumnya, maka untuk mengalkulasi gradien pada langkah waktu t, kita harus menghitung turunannya pada langkah waktu t-1, t-2, t-3, dan seterusnya sampai titik awal (t=1). Inilah yang memunculkan istilah backpropagation though time (BTT) ini.

Kita tidak akan membahas formula BTT di sini karena terlalu panjang dan karena ini tidak perlu kita pikirkan kalau Anda memakai framework seperti TensorFlow atau Keras (backprop-nya akan ditangani framework). Kalau Anda ingin mendalami formula ini, bisa dimulai dari artikel di WILDML ini.

Permasalahan Vanishing Gradient

Bayangkan kita mempunyai NN dengan banyak lapis seperti di bawah ini.

Vanishing Gradients

Dengan lapis yang banyak ini, sulit bagi simpul-simpul di lapis di bagian awal NN untuk “belajar” dari perubahan di ŷ, karena gradien yang timbul dari perubahan di ŷ tersebut semakin lama akan semakin mengecil dalam proses back-propagation, dan akhirnya menjadi kecil sekali mendekati nol atau dikatakan “menghilang” ketika sampai di lapis-lapis awal NN.

Hal ini disebabkan oleh sifat perkalian antar bilangan pecahan. Bayangkan misalkan suatu bilangan pecahan 1/4, dikalikan dengan bilangan pecahan lain misalnya 1/3, maka dalam satu operasi ini nilainya sudah menjadi 1/12. Dikalikan pecahan lain misalnya 1/5, nilainya menjadi 1/60, dst. Nilai ini akan mengecil secara eksponensial, dan dengan nilai pecahan yang kecil dan banyaknya operasi perkalian, nilainya akan mendekati nol.

Demikian sebaliknya jika nilai gradiennya besar, maka akan menimbulkan masalah lain yaitu nilai gradien yang “meledak” (exploding gradient). Tapi masalah ini lebih mudah ditangani, misalnya dengan menerapkan suatu batas atas untuk nilai gradien.

Jumlah lapis dalam RNN sendiri bisa panjang sekali, sepanjang jumlah deretan dalam masukan, dan ini menimbulkan permasalahan tersendiri karena RNN sering harus menyimpan ketergantungan dari input yang letaknya cukup berjauhan. Contohnya misalnya model kita harus menemukan kata yang tepat untuk mengisi kata berikutnya berdasarkan kata-kata yang sudah dia lihat sebelumya:

Ching Ching is a cute little panda. … Everyone loves ___.

Tempat kosong di atas diperuntukkan untuk sebuah kata ganti, dan untuk mengisinya RNN harus mengingat subjek atau objek apa yang sedang dibicarakan dalam paragraf itu, dan itu tempatnya di awal paragraf. Dengan semakin banyak kata di antara kedua lokasi, semakin sulit bagi RNN untuk menyimpan hubungan ini  karena permasalahan gradien yang menghilang di atas.

Ada beberapa cara untuk memecahkan masalah ini, misalnya dengan inisialisasi parameter yang benar, regularisasi, dan penggunaan ReLU untuk mengganti fungsi aktivasi tanh atau sigmoid. Cara lain yang populer adalah dengan menggunakan unit RNN lain yaitu LSTM dan GRU.

Jaringan LSTM (Long Short Term Memory) dan GRU (Gated Recurrent Unit) adalah dua arsitektur RNN yang paling populer. Kita akan bahas keduanya di artikel mendatang.

Referensi

Iklan

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout /  Ubah )

Foto Google+

You are commenting using your Google+ account. Logout /  Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout /  Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout /  Ubah )

Connecting to %s

Buat situs web atau blog gratis di WordPress.com.

Atas ↑

%d blogger menyukai ini: