Di supervised learning, dataset diam menunggu model; di RL, data muncul dari perilaku agent sendiri. Konsekuensinya satu dilema yang tidak pernah benar-benar usai: aksi terbaik versi pengetahuan saat ini, atau aksi yang belum pernah dicoba yang mungkin lebih baik? Memilih selalu yang terbaik saat ini membuat agent terkunci pada kesimpulan awal yang mungkin keliru; mencoba terus-menerus membuat agent membayar biaya aksi buruk tanpa pernah menuai hasil. Seluruh algoritma pada chapter sebelumnya — Q-learning, REINFORCE, DQN, actor-critic — diam-diam sudah membawa jawaban tertentu atas dilema ini melalui epsilon-greedy; saatnya kita angkat topik itu ke depan dan bandingkan empat strategi eksplorasi secara adil pada dunia yang sama.

Inti Dilema #

Bayangkan dua tombol mesin penjual kopi di kantor; satu tombol sudah sering dipakai dan hasilnya lumayan, satu lagi belum pernah dicoba. Memakai yang pertama memberi hasil yang pasti; mencoba yang kedua memberi informasi — dan informasi itu hanya bisa dibeli dengan risiko hasil buruk. Dua sifat membuat dilema ini tajam di RL:

  • Nilai yang belum dicoba tak terlihat. Tabel Q yang diawali nol tidak membedakan “aksi buruk” dari “aksi belum pernah dicoba” — keduanya tampak sama-sama tidak menjanjikan.
  • Data bergantung perilaku. Agent yang tidak pernah memilih suatu aksi tidak akan pernah menerima bukti tentang aksi itu; ketidaktahuan menjadi permanen.

Empat Strategi #

StrategiMekanismeKarakter
epsilon tetap kecilselalu sisakan peluang acaksederhana, tapi tak pernah berhenti membayar biaya eksplorasi
epsilon meluruhmulai banyak mencoba, perlahan memastikaneksplorasi besar saat tabel pengetahuan masih kosong — pola standar industri
softmax (Boltzmann)peluang ∝ exp(Q/temperatur)memilih proporsional nilai; temperatur tinggi = berani
inisialisasi optimistikawali Q dengan nilai tinggiaksi yang belum teruji tampak menjanjikan dan dicoba lebih dulu tanpa acak

Epsilon-greedy dengan peluruhan adalah pilihan paling umum, dan sudah kita lihat dua kali: jadwal 0.99^episode dengan batas bawah 0.05 pada chapter Deep Q-Network . Strategi keempat, inisialisasi optimistik, bekerja lewat psikologi terbalik: karena Q yang belum dikoreksi nilainya tinggi, kebijakan greedy sendirinya memilih pasangan yang belum pernah dicoba; eksplorasi terjadi tanpa satu pun aksi acak, lalu berhenti alami ketika nilai-nilai itu mulai dikoreksi ke bawah.

Demo: Empat Strategi pada Dunia yang Sama #

Dunia GridWorld 4x4 dari chapter Value Function dipakai ulang; keempat strategi melatih Q-learning dengan anggaran identik 500 episode. Berkas epsilon_strategi.py juga mengevaluasi kebijakan greedy hasil tiap strategi tanpa eksplorasi sama sekali:

python
"""Empat strategi eksplorasi pada Q-learning GridWorld 4x4.

Dunia sama dengan chapter Value Function: mulai (0,0), target (3,3),
reward -0.05 per langkah, +1 saat tiba, batas 25 langkah per episode.
Empat varian dibandingkan selama 500 episode:
1. epsilon tetap 1.0  -- aksi selalu acak (eksplorasi murni),
2. epsilon tetap 0.1  -- sedikit eksplorasi selamanya,
3. epsilon meluruh    -- 1.0 menurun 0.99 per episode hingga batas 0.05,
4. optimistik         -- epsilon 0, tetapi tabel Q diawali nilai +1.0
   sehingga aksi yang belum dicoba tampak menjanjikan dan dicoba dulu.
"""

import numpy as np

UKURAN = 4
START, GOAL = (0, 0), (3, 3)
AKSI = [(-1, 0), (1, 0), (0, -1), (0, 1)]
MAKS_LANGKAH = 25


def step(state, aksi):
    """Satu interaksi; kembalikan (state_baru, reward, selesai)."""
    db, dk = AKSI[aksi]
    nb, nk = state[0] + db, state[1] + dk
    state_baru = (nb, nk) if (0 <= nb < UKURAN and 0 <= nk < UKURAN) else state
    selesai = state_baru == GOAL
    return state_baru, (1.0 if selesai else -0.05), selesai


STRATEGI = ["eps=1.0", "eps=0.1", "meluruh", "optimistik"]


def epsilon_pada(mode, episode):
    """Nilai epsilon untuk suatu episode."""
    if mode == 0:
        return 1.0
    if mode == 1:
        return 0.1
    if mode == 2:
        return max(0.05, 0.99 ** (episode - 1))
    return 0.0


def latih(mode, seed=7, jumlah_episode=500, alfa=0.1, gamma=0.9):
    """Latih Q-learning dengan strategi eksplorasi tertentu."""
    rng = np.random.default_rng(seed)
    Q = np.ones((UKURAN, UKURAN, 4)) if mode == 3 else np.zeros((UKURAN, UKURAN, 4))
    riwayat = []
    for episode in range(1, jumlah_episode + 1):
        epsilon = epsilon_pada(mode, episode)
        state, total = START, 0.0
        for _ in range(MAKS_LANGKAH):
            if rng.random() < epsilon:
                aksi = int(rng.integers(0, 4))
            else:
                aksi = int(np.argmax(Q[state[0], state[1]]))
            state_baru, reward, selesai = step(state, aksi)
            target = reward + gamma * (0.0 if selesai
                                       else Q[state_baru[0], state_baru[1]].max())
            Q[state[0], state[1], aksi] += alfa * (
                target - Q[state[0], state[1], aksi])
            total += reward
            state = state_baru
            if selesai:
                break
        riwayat.append(total)
    return Q, riwayat


def evaluasi_greedy(Q, jumlah_episode=20):
    """Ukur return tanpa eksplorasi sama sekali."""
    hasil = []
    for _ in range(jumlah_episode):
        state, total = START, 0.0
        for _ in range(MAKS_LANGKAH):
            aksi = int(np.argmax(Q[state[0], state[1]]))
            state, reward, selesai = step(state, aksi)
            total += reward
            if selesai:
                break
        hasil.append(total)
    return float(np.mean(hasil)), sum(h > 0 for h in hasil)


print("epsilon strategi 'meluruh' per 50 episode:",
      ", ".join(f"{epsilon_pada(2, e):.2f}" for e in [1, 50, 100, 150, 200, 250, 300, 500]))

tabel_q, tabel_riwayat = [], []
for mode in range(4):
    Q, riwayat = latih(mode)
    tabel_q.append(Q)
    tabel_riwayat.append(riwayat)

print("\nMean total reward per blok 50 episode (training, dengan eksplorasi):")
print(f"  {'blok':>11s} " + " ".join(f"{s:>9s}" for s in STRATEGI))
for i in range(0, 500, 50):
    baris = " ".join(
        f"{np.mean(tabel_riwayat[m][i:i + 50]):>+9.2f}" for m in range(4))
    print(f"  {i + 1:4d}-{i + 50:3d}    {baris}")

print("\nMean return 100 episode terakhir (training):")
for m, nama in enumerate(STRATEGI):
    print(f"  {nama:10s}: {np.mean(tabel_riwayat[m][-100:]):+.3f}")

print("\nEvaluasi greedy 20 episode (tanpa eksplorasi):")
for m, nama in enumerate(STRATEGI):
    rata, sukses = evaluasi_greedy(tabel_q[m])
    print(f"  {nama:10s}: mean {rata:+.2f}, sukses {sukses}/20")

Output yang Dihasilkan:

text
epsilon strategi 'meluruh' per 50 episode: 1.00, 0.61, 0.37, 0.22, 0.14, 0.08, 0.05, 0.05

Mean total reward per blok 50 episode (training, dengan eksplorasi):
         blok   eps=1.0   eps=0.1   meluruh optimistik
     1- 50        -0.57     +0.43     -0.19     +0.03
    51-100        -0.80     +0.72     +0.51     +0.53
   101-150        -0.97     +0.71     +0.64     +0.64
   151-200        -0.87     +0.73     +0.71     +0.69
   201-250        -0.94     +0.73     +0.71     +0.71
   251-300        -0.90     +0.72     +0.74     +0.73
   301-350        -0.77     +0.72     +0.74     +0.74
   351-400        -0.72     +0.70     +0.74     +0.75
   401-450        -0.72     +0.72     +0.74     +0.75
   451-500        -0.97     +0.72     +0.73     +0.75

Mean return 100 episode terakhir (training):
  eps=1.0   : -0.844
  eps=0.1   : +0.722
  meluruh   : +0.733
  optimistik: +0.749

Evaluasi greedy 20 episode (tanpa eksplorasi):
  eps=1.0   : mean +0.75, sukses 20/20
  eps=0.1   : mean +0.75, sukses 20/20
  meluruh   : mean +0.75, sukses 20/20
  optimistik: mean +0.75, sukses 20/20

Dua lapis hasil ini menyimpan pelajaran berbeda. Pada kurva training (kolom dengan eksplorasi aktif), eps=1.0 tertahan di sekitar -0.9 — agen selamanya berjalan acak sehingga total reward per episode tidak pernah membaik; eps=0.1 cepat naik ke +0.43 lalu menempel di +0.72, terhambat biaya tetap 10% aksi acak; meluruh dan optimistik menembus ke +0.73-+0.75 karena eksplorasinya surut tepat saat pengetahuan matang. Namun pada evaluasi greedy, keempatnya sama-sama +0.75 dengan sukses 20/20 — termasuk eps=1.0 yang kurva trainingnya tampak buruk! Penjelasannya: eksplorasi murni sepanjang 500 episode ternyata menyediakan cukup kunjungan untuk mengisi seluruh tabel Q di dunia kecil yang deterministik ini, dan return training yang rendah hanyalah biaya eksplorasi yang sedang dibayar, bukan kebijakan buruk. Pada dunia besar dengan anggaran ketat, agen yang tidak pernah mengeksploitasi tidak akan punya waktu mengisi pengetahuannya — di sanalah strategi keempat ini berpisah nasib. Mari kita telaah kode di atas baris per baris:

  1. Baris 21-27 (step): dunia GridWorld 4x4 — sama persis dengan chapter Value Function agar hasil dapat dibandingkan.
  2. Baris 33-41 (epsilon_pada): empat kebijakan eksplorasi dirumuskan sebagai satu fungsi — tetap 1.0, tetap 0.1, meluruh max(0.05, 0.99^(episode-1)), dan 0.0 untuk mode optimistik.
  3. Baris 47: kunci strategi optimistik — np.ones mengawali tabel Q dengan nilai +1.0 untuk mode 3, np.zeros untuk lainnya.
  4. Baris 44-67 (latih): siklus Q-learning standar dengan seed per mode; generator ber-seed (dokumentasi numpy.random.Generator ) membuat keempat pelatihan dapat direproduksi.
  5. Baris 70-82 (evaluasi_greedy): pengukuran terpisah — 20 episode tanpa eksplorasi sedikit pun; inilah angka yang menggambarkan kualitas kebijakan sejati.
  6. Baris 85-99: tabel mean reward per blok 50 episode untuk keempat strategi berdampingan.
  7. Baris 101-108: dua ringkasan — mean return 100 episode terakhir saat training, lalu evaluasi greedy yang memisahkan biaya eksplorasi dari mutu kebijakan.

Perbandingan barusan menyingkap satu jebakan pengukuran: kurva training bisa tampak buruk padahal kebijakannya baik, dan sebaliknya. Lapis terakhir section ini merapikan persoalan itu — bagaimana menilai agen RL secara jujur dengan metrik, evaluasi terpisah, dan beberapa seed — pada chapter Evaluasi Reinforcement Learning.