Agent gridworld pada Chapter Membangun Agent Q-Learning untuk Gridworld menyelesaikan peta 6×6 dengan tabel berisi 144 entri — kecil, transparan, dan cukup. Babak penutup Section ini membahas apa yang terjadi ketika perkakas tabular itu berhadapan dengan dunia yang jauh lebih besar: bingkai permainan video, telemetri robot, atau riwayat interaksi pengguna, tempat jumlah state melebihi jumlah partikel yang bisa dihitung. Jawaban atas dinding skala tersebut adalah deep reinforcement learning — mengganti Q-table dengan neural network yang menaksir nilai dari fitur mentah. Karena lingkungan Course ini tidak memasang torch, tensorflow, maupun gymnasium, Chapter ini bersifat konseptual: kita membongkar mekanisme DQN, policy gradient, dan aktor-kritik dengan membaca, bukan dengan melatih — ditopang satu skrip aritmetika NumPy yang tetap berjalan dan mencetak angka.

Dinding Skala: Ketika Tabel Tidak Muat #

Alasan fundamental deep RL bisa diringkas menjadi satu kalimat: tabel menyimpan satu angka per state, sedangkan jaringan berbagi parameter lintas state yang serupa. Gridworld 6×6 memiliki 36 state; bingkai permainan beresolusi 210×160 dengan tiga kanal warna memiliki 100.800 nilai piksel, sehingga jumlah bingkai berbeda yang mungkin mencapai sekitar 10^242751 — mustahil di tabel mana pun, sementara jaringan yang membaca piksel mentah tetap hanya menyimpan beberapa juta parameter. Pertukarannya nyata: tabel menyimpan nilai eksak untuk state yang pernah dikunjungi, sedangkan jaringan menghasilkan taksiran yang menggeneralisasi — baik untuk state serupa yang belum pernah dilihat, tetapi bisa keliru di wilayah tanpa data. Mari kita hitung dinding itu secara eksplisit.

python
# Aritmetika sederhana untuk menjawab satu pertanyaan: sampai ukuran
# berapa Q-table masih masuk akal, dan seberapa kecil jaringan saraf
# yang menggantikannya? Semua angka dihitung dari keputusan desain yang
# eksplisit (jumlah state, jumlah aksi, lebar layer) -- tidak ada angka
# yang diambil dari sumber lain.

import numpy as np

N_AKSI = 4
BYTE_FLOAT64 = 8      # Q-table di Course ini memakai np.float64
BYTE_FLOAT32 = 4      # bobot jaringan lazim disimpan sebagai float32

SATUAN = ["B", "KB", "MB", "GB", "TB", "PB", "EB"]


def format_ukuran(jumlah_byte):
    """Cetak ukuran byte dalam satuan yang paling mudah dibaca."""
    nilai = float(jumlah_byte)
    indeks = 0
    while nilai >= 1024.0 and indeks < len(SATUAN) - 1:
        nilai /= 1024.0
        indeks += 1
    return f"{nilai:,.1f} {SATUAN[indeks]}"


print("Skenario 1: Q-table penuh (4 aksi, float64 = 8 byte per entri)")
print(f"{'jumlah state':>16} {'entri tabel':>16} {'ukuran':>12}")
for jumlah_state in [10**3, 10**6, 10**9, 10**12]:
    entri = jumlah_state * N_AKSI
    print(f"{jumlah_state:>16,} {entri:>16,} "
          f"{format_ukuran(entri * BYTE_FLOAT64):>12}")


def hitung_parameter(layer):
    """Jumlah parameter MLP: bobot m x n ditambah bias n per sambungan."""
    return sum(m * n + n for m, n in zip(layer[:-1], layer[1:]))


print("\nSkenario 2: jaringan saraf pengganti tabel (float32 = 4 byte per parameter)")
print(f"{'arsitektur':<24} {'parameter':>12} {'ukuran':>12}")
ARSITEKTUR = [
    [64, 128, 128, 4],        # fitur ringkas 64 dimensi
    [512, 256, 256, 4],       # fitur menengah
    [10080, 512, 256, 4],     # bingkai 210x160 RGB pipih (10080 nilai piksel)
]
for layer in ARSITEKTUR:
    p = hitung_parameter(layer)
    print(f"{'[' + ', '.join(str(n) for n in layer) + ']':<24} {p:>12,} "
          f"{format_ukuran(p * BYTE_FLOAT32):>12}")

PIKSEL_PER_BINGKAI = 210 * 160 * 3
log10_bingkai = PIKSEL_PER_BINGKAI * np.log10(256)
log10_byte_tabel = log10_bingkai + np.log10(N_AKSI * BYTE_FLOAT64)
print(f"\nSudut pandang citra mentah 210x160 RGB:")
print(f"  nilai piksel per bingkai          : {PIKSEL_PER_BINGKAI:,}")
print(f"  jumlah bingkai berbeda yang mungkin ~ 10^{log10_bingkai:.0f}")
print(f"  Q-table float64 untuk semuanya    : ~ 10^{log10_byte_tabel:.0f} byte")

p_tabel = 10**9 * N_AKSI * BYTE_FLOAT64
p_jaringan = hitung_parameter(ARSITEKTUR[2]) * BYTE_FLOAT32
print(f"\nPerbandingan: Q-table 10^9 state = {format_ukuran(p_tabel)} vs "
      f"jaringan piksel = {format_ukuran(p_jaringan)} "
      f"(jaringan {p_tabel / p_jaringan:.0f} kali lebih ringkas)")

Output yang Dihasilkan:

text
Skenario 1: Q-table penuh (4 aksi, float64 = 8 byte per entri)
    jumlah state      entri tabel       ukuran
           1,000            4,000      31.2 KB
       1,000,000        4,000,000      30.5 MB
   1,000,000,000    4,000,000,000      29.8 GB
1,000,000,000,000 4,000,000,000,000      29.1 TB

Skenario 2: jaringan saraf pengganti tabel (float32 = 4 byte per parameter)
arsitektur                  parameter       ukuran
[64, 128, 128, 4]              25,348      99.0 KB
[512, 256, 256, 4]            198,148     774.0 KB
[10080, 512, 256, 4]        5,293,828      20.2 MB

Sudut pandang citra mentah 210x160 RGB:
  nilai piksel per bingkai          : 100,800
  jumlah bingkai berbeda yang mungkin ~ 10^242751
  Q-table float64 untuk semuanya    : ~ 10^242752 byte

Perbandingan: Q-table 10^9 state = 29.8 GB vs jaringan piksel = 20.2 MB (jaringan 1511 kali lebih ringkas)

Mari kita bedah bagian-bagian pentingnya:

  1. Baris 26–31 (Skenario 1): ukuran Q-table dihitung lurus dari definisi — jumlah state dikali 4 aksi dikali 8 byte float64. Sepuluh juta state baru menuntut 30,5 MB; satu miliar state menuntut 29,8 GB — dan itupun belum menyentuh masalah kedua: sebagian besar entri tidak akan pernah dikunjungi untuk diisi nilai.
  2. Baris 34–49 (Skenario 2): hitung_parameter menjumlahkan bobot m × n plus bias n untuk setiap sambungan antar-layer. Jaringan pembaca piksel mentah [10080, 512, 256, 4] hanya menyimpan 5.293.828 parameter atau 20,2 MB — dibandingkan tabel satu miliar state, jaringan ini 1.511 kali lebih ringkas.
  3. Baris 51–57 (aritmetika eksponen): jumlah bingkai yang mungkin dihitung di ruang logaritmik — 100800 × log10(256) — karena angka aslinya tidak muat di float64. Hasil 10^242751 bingkai menegaskan bahwa pendekatan tabular tidak sekadar mahal, melainkan mustahil pada input visual.

Angka-angka tersebut adalah alasan keberadaan DQN — Deep Q-Network — yang mengganti tabel dengan jaringan saraf: input state, output satu taksiran Q per aksi. Rumus pembaruan TD tetap rumus Q-learning yang sudah kita tulis; yang berubah hanyalah cara Q dihitung, sehingga pembaruan menjadi pembaruan bobot jaringan lewat backpropagation.

DQN: Dua Alat Penstabil #

Melatih jaringan dengan target yang ia hasilkan sendiri menimbulkan masalah kestabilan yang khas — gabungan pendekatan fungsi, bootstrapping (target dibangun dari taksiran lain), dan pembelajaran off-policy dikenal sebagai kombinasi rawan divergen. DQN menaklukkan masalah tersebut dengan dua mekanisme yang layak dihafal karena muncul di hampir semua algoritme modern.

Pertama, experience replay. Setiap pengalaman (s, a, r, s′) disimpan ke dalam penyangga berkapasitas besar, dan pelatihan menarik mini-batch acak dari sana — bukan langsung dari pengalaman terbaru. Dua efek penstabil mengikuti: sampel yang tidak berurutan memutus korelasi antar-langkah berturutan yang membuat gradient menyimpang ke satu arah, dan satu pengalaman bisa dipakai beberapa kali sehingga data mahal tidak terbuang sekali lewat. Watak off-policy Q-learning (Chapter Q-Learning) menjadi syaratnya: target r + γ·max Q(s′,·) memang tidak mensyaratkan data berasal dari kebijakan terkini, sehingga pengalaman lama tetap sahih.

Kedua, target network. Masalah inti pembelajaran TD dengan jaringan adalah target yang ikut bergeser setiap kali bobot bergeser — seperti mengejar sasaran yang berpindah. DQN menanganinya dengan menyimpan salinan jaringan yang bobotnya dibekukan selama ribuan langkah; target dihitung dari salinan beku tersebut, dan salinan diperbarui berkala dengan menyalin bobot jaringan utama. Sasaran kini stabil dalam jangka pendek, galat pembelajaran menjadi terarah, dan pelatihan yang sebelumnya mudah berayun menjadi jauh lebih terkendali.

Policy Gradient dan Peta Keluarga #

DQN dan seluruh variannya menaksir nilai lalu memilih aksi darinya — jalur value-based. Jalur kedua menghapus nilai sama sekali: policy gradient memparameterisasi kebijakan langsung sebagai π(a|s; θ) — misalnya jaringan yang mengeluarkan peluang per aksi — lalu menaikkan peluang aksi-aksi yang ternyata menghasilkan return tinggi. Intuisinya sederhana: peluang aksi yang baik dinaikkan dan peluang aksi yang buruk diturunkan, sebanding dengan kontribusi masing-masing terhadap return, dengan arah dan besaran pergeseran dihitung lewat turunan (gradient) nilai harapan return terhadap θ. Jalur ini unggul pada aksi kontinu — sudut sendi robot tidak punya argmax yang praktis untuk dihitung.

Keluarga ketiga menggabungkan keduanya. Actor-critic memakai dua jaringan: aktor (policy) yang bertindak, dan kritik (value function) yang menilai tindakan tersebut sehingga sinyal pembelajaran tidak perlu menunggu episode selesai. Peta lengkapnya:

KeluargaYang dipelajariKekuatanContoh algoritme
Value-basedQ(s, a) atau V(s); kebijakan diekstrakSampel efisien, watak off-policyQ-learning, DQN
Policy-basedπ(a|s; θ) langsungAksi kontinu, kebijakan acak halusREINFORCE
Actor-criticAktor π + kritik V bersamaSinyal pembelajaran bertahap, stabilA2C/A3C, SAC, PPO

Tonggak dan Kesulitan yang Jujur #

Sejarah deep RL memuat beberapa tonggak yang layak disebut dengan bahasa netral. TD-Gammon (1992) menggabungkan pembelajaran TD dengan jaringan untuk permainan papan backgammon dan mencapai taraf pemain terbaik. DQN (dipublikasikan 2015 oleh tim DeepMind) melatih satu jaringan yang sama — tanpa aturan permainan apa pun selain skor — hingga sejajar kinerja pemain manusia pada puluhan judul permainan Atari dari piksel mentah. AlphaGo (2016) mengalahkan juara dunia Go dengan menggabungkan pencarian pohon Monte Carlo, jaringan kebijakan, dan pembelajaran dari permainan latihan mandiri; penerusnya memurnikan pendekatan menjadi pembelajaran murni dari permainan sendiri. Pada robotika, deep RL melatih kebijakan manipulasi dan lokomosi langsung dari sensor, menggantikan sebagian rekayasa kontrol manual.

Daftar kesulitannya sama panjangnya dan harus dibaca sebelum terlalu percaya. Efisiensi sampel rendah: DQN membutuhkan puluhan juta bingkai — ribuan jam permainan setara — untuk tugas yang manusia pelajari dalam menit. Ketidakstabilan dan kepekaan: hasil pelatihan bergantung pada hyperparameter, seed acak, dan detail implementasi; dua kali lari bisa menghasilkan selisih kinerja besar. Perancangan ganjaran rawan celah: agent menemukan perilaku yang memaksimalkan angka ganjaran tetapi menyimpang dari maksud perancangnya — misalnya berputar menandai waktu demi bonus pengumpulan, atau membiarkan tugas utama tidak selesai karena ganjaran samping lebih mudah. Persoalan penyelarasan tujuan ini adalah bidang riset aktif, bukan catatan kaki. Tabular Q-learning kita punya batas ukuran; deep RL punya batas kepastian — dua batas yang berbeda sifat namun sama nyatanya.

Kerangka penutup Section ini sederhana: RL tabular memberi kita intuisi mekanis yang lengkap — lingkar, MDP, TD, eksplorasi — dan deep RL memperbesannya dengan pengganti tabel bernama neural network. Akan tetapi, sepanjang Course ini jaringan saraf selalu tampil sebagai kotak yang belum pernah kita buka: apa itu neuron, mengapa ada fungsi aktivasi, bagaimana backpropagation menghitung bobot yang benar, dan kapan deep learning memang layak dipilih. Membuka kotak itulah tugas Section berikutnya, yang dimulai dari Chapter Dari Machine Learning ke Deep Learning.

Referensi Resmi #

  • Gymnasium — situs resmi pustaka lingkungan RL standar, termasuk lingkungan Atari dan dokumentasi API reset/step yang menjadi lingkar agent-environment de facto industri.
  • numpy — numpy.log10 — API resmi logaritma basis 10 yang dipakai skrip untuk menghitung ruang state citra tanpa overflow.
  • numpy — numpy.memmap — API resmi pemetaan array besar ke berkas; relevan ketika Q-table raksasa hendak disimpan di luar RAM sebagai perbandingan praktis.