Lewati ke konten utama

Algoritma Reinforcement Learning SARSA di Python: Panduan Lengkap

Pelajari SARSA, algoritma reinforcement learning on-policy. Pahami aturan pembaruannya, hiperparameter, dan perbedaannya dari Q-learning dengan contoh Python praktis dan implementasinya.
· 15 mnt Baca

Jelajahi bersama AI

Reinforcement learning (RL) adalah paradigma machine learning yang kuat. Dalam RL, perangkat lunak, biasanya disebut agen, belajar berinteraksi dengan lingkungan untuk menyelesaikan masalah kompleks melalui coba-coba, semuanya tanpa campur tangan manusia. Di antara algoritma RL, SARSA menonjol karena sifat on-policy yang efisien.

SARSA adalah singkatan dari State-Action-Reward-State-Action, yang merepresentasikan siklus yang diikuti agen untuk memecahkan masalah. Siklus ini memungkinkan agen belajar dari kesalahan masa lalunya dan sesekali memberanikan diri mencoba hal baru. Perilaku ini membuat algoritma sangat efektif pada jenis masalah tertentu dan membedakannya dari algoritma off-policy seperti Q-learning.

Dalam tutorial ini, Anda akan mempelajari cara kerja SARSA dan bagaimana mengimplementasikannya di Python. Untuk memantapkan pemahaman, kita akan menggunakan masalah klasik Taxi Ride sepanjang pembahasan. Kita juga akan membahas kelebihan, keterbatasan, dan aplikasi dunia nyata dari SARSA.

Apa itu SARSA? Jawaban Singkat

SARSA, singkatan dari State-Action-Reward-State-Action, menggambarkan urutan peristiwa dalam proses pembelajaran. Ini adalah metode pembelajaran yang efektif bagi program komputer (agen) untuk mengambil keputusan yang baik dalam berbagai skenario.

Gagasan utama di balik SARSA adalah coba-coba. Agen mengambil sebuah aksi dalam suatu situasi, mengamati hasilnya, dan menyesuaikan strateginya berdasarkan hasil tersebut (baik atau buruk). Proses ini diulangi berkali-kali, sehingga keputusan agen membaik seiring waktu.

Yang membuat SARSA istimewa di antara algoritma RL adalah SARSA belajar dari pilihan nyata yang dibuat agen, termasuk ketika agen mencoba hal baru. Pendekatan ini sangat berguna ketika perjalanan pembelajaran sama pentingnya dengan hasil akhirnya.

Ibarat robot yang belajar bersepeda dengan benar-benar mengendarainya—jatuh bangun—alih-alih mencari rute terpendek dari A ke B dengan roda bantu pelindung.

Menyiapkan Lingkungan untuk Tutorial

Dalam tutorial ini, kita akan banyak menggunakan Numpy dan pustaka reinforcement learning Gymnasium. Numpy akan membantu kita menulis algoritma SARSA, sedangkan Gymnasium menyediakan lingkungan bawaan untuk menguji pekerjaan kita.

Mari pasang keduanya di lingkungan virtual baru dengan perintah berikut:

$ conda create -n sarsa python=3.9 -y
$ conda activate sarsa
$ pip install "gymnasium[atari]" numpy matplotlib
$ pip install autorom[accept-rom-license]  # Downloading Gym env data files
$ AutoROM --accept-license  # Accepting the license for data files
$ pip install ipykernel  # Install Jupyter kernel manager
$ ipython kernel install --user --name=sarsa  # Add the new Conda env to Jupyter

Sebelum lanjut, saya sangat menganjurkan Anda membaca artikel Pengantar Reinforcement Learning kami. Artikel tersebut membahas gagasan mendasar RL, seperti agen, lingkungan, dilema eksplorasi versus eksploitasi, dan Q-learning.

Menjelaskan Lingkungan Taxi-V3

Sepanjang tutorial, kita akan menggunakan lingkungan Taxi-v3, yang merupakan masalah reinforcement learning klasik dari pustaka Gymnasium. Lingkungan ini mensimulasikan sopir taksi yang menavigasi dunia kisi 5x5 untuk menjemput dan menurunkan penumpang.

Untuk memuat lingkungan, kita menggunakan metode .make() dari Gymnasium dengan mode render rgb_array (agar nanti bisa memvisualisasikan lingkungan):

import gymnasium as gym
env = gym.make('Taxi-v3', render_mode='rgb_array')

Lingkungan berupa kisi 5x5 dengan empat lokasi khusus: merah (R), hijau (G), kuning (Y), dan biru (B). Taksi mulai pada kotak acak dan harus menjemput penumpang di salah satu lokasi berwarna dan menurunkannya di lokasi lain. 

Taksi dapat bergerak ke Utara, Selatan, Timur, atau Barat serta dapat mencoba menjemput atau menurunkan penumpang.

Berikut cara memvisualisasikan keadaan awal lingkungan dengan Matplotlib:

import matplotlib.pyplot as plt
# Reset the environment to get an initial state
# Each time we reset the environment, we get a new random state
initial_state, _ = env.reset()
# Render the initial state
img = env.render()
# Create a figure and display the environment
fig, ax = plt.subplots(figsize=(8, 8))
ax.imshow(img)
# Remove axis ticks
ax.set_xticks([])
ax.set_yticks([]);

Keadaan awal contoh dari masalah reinforcement learning taksi yang akan diselesaikan menggunakan sarsa

Pertama, kita me-reset lingkungan untuk mendapatkan keadaan awal. Lalu, kita tampilkan keadaan awal ini dengan fungsi render, menerima array gambar Numpy. Fungsi Matplotlib imshow() mengambil array ini dan menghasilkan visualisasi bersih tanpa tanda sumbu.

Luangkan waktu untuk memahami tata letak dunia kisi Taxi-v3, perhatikan posisi taksi, penghalang, lokasi penumpang, dan tujuan.

Agen (taksi) menerima +20 poin untuk berhasil menurunkan penumpang. Upaya penjemputan atau penurunan yang ilegal menghasilkan hadiah -10. Sementara itu, setiap langkah waktu menghasilkan hadiah -1 untuk mendorong taksi menyelesaikan tugas dengan cepat.

Satu episode di lingkungan Taxi-v3 berakhir jika penurunan berhasil atau ketika jumlah langkah waktu maksimum tercapai.

# The number of states and actions
n_states = env.observation_space.n
n_actions = env.action_space.n
print(n_states)
print(n_actions)
500
6

Ada 500 state dalam ruang state lingkungan. Setiap state direpresentasikan oleh:

  • Baris taksi (0–4)
  • Kolom taksi (0–4)
  • Lokasi penumpang (0–3 untuk R, G, Y, B, atau 4 untuk di dalam taksi)
  • Lokasi tujuan (0–3 untuk R, G, Y, B)
  • Total state = 5 (baris)×5 (kolom)×5 (lokasi penumpang)×4 (lokasi tujuan)=500.

Kode aksi adalah:

  • 0: Bergerak ke Selatan
  • 1: Bergerak ke Utara
  • 2: Bergerak ke Timur
  • 3: Bergerak ke Barat
  • 4: Menjemput penumpang
  • 5: Menurunkan penumpang

Tujuannya adalah agar agen mempelajari kebijakan optimal untuk memaksimalkan total hadiahnya dengan menjemput dan menurunkan penumpang secara efisien.

Siklus Interaksi SARSA

Sebelum menulis algoritma lengkap, mari lihat bagaimana siklus State-Action-Reward-State-Action bekerja menggunakan lingkungan kita.

Pertama, kita tentukan berapa banyak episode yang kita inginkan untuk melanjutkan interaksi. Satu episode merepresentasikan satu kali jalankan penuh tugas taksi, dari state awal hingga berhasil menurunkan penumpang atau mencapai jumlah langkah waktu maksimum. Setiap episode memungkinkan agen belajar dari pengalamannya dan memperbaiki strateginya seiring waktu.

n_episodes = 5000

Sekarang, kita tulis loop interaksi:

for episode in range(n_episodes):
   state, _ = env.reset()
   done = False
   total_reward = 0
   steps = 0
   while not done:
       # Choose a random action
       action = env.action_space.sample()
       # Take the action and observe the result
       next_state, reward, terminated, truncated, _ = env.step(action)
       done = terminated or truncated
       # Update total reward and step count
       total_reward += reward
       steps += 1
       # Move to the next state
       state = next_state
   if episode % 1000 == 0:
       print(f"Episode {episode}, Total Reward: {total_reward}, Steps: {steps}")
Episode 0, Total Reward: -812, Steps: 200
Episode 1000, Total Reward: -830, Steps: 200
Episode 2000, Total Reward: -902, Steps: 200
Episode 3000, Total Reward: -522, Steps: 129
Episode 4000, Total Reward: -767, Steps: 200

Kode di atas mendemonstrasikan siklus interaksi SARSA dasar tanpa mengimplementasikan algoritma pembelajaran apa pun:

  1. Reset lingkungan di awal setiap episode — (S), env.reset().
  2. Ambil aksi acak — (A), env.step(action). Versi ini menggunakan aksi acak untuk mendemonstrasikan loop interaksi.
  3. Terima hadiah (R) dan state berikutnya (S_1), next_state, reward, ... = env.take(action).
  4. Ambil aksi (A_1) pada state baru.

Dalam loop interaksi di atas, taksi terus bergerak ke segala arah di lingkungan dan melakukan aksi acak hingga langkah waktu habis.

Menganimasikan Siklus Interaksi SARSA

Sebelum melanjutkan, mari implementasikan fitur untuk menganimasikan loop interaksi kita. Ini memungkinkan kita melihat secara visual taksi berinteraksi dengan lingkungan.

Membuat animasi akan menjadi proses sederhana:

  • Pada setiap langkah waktu, kita tangkap state lingkungan dalam array gambar menggunakan fungsi env.render().
  • Kita kumpulkan array gambar tersebut dalam variabel terpisah.
  • Dengan pustaka bernama moviepy, kita gabungkan semua array gambar untuk membuat satu GIF.

Mari modifikasi kodenya:

env = gym.make("Taxi-v3", render_mode="rgb_array")
n_episodes = 1
frames = []  # for animation
for episode in range(n_episodes):
   # Reset the environment
   state, _ = env.reset()
   # Capture the state as an image
   img = env.render()
   frames.append(img)
   done = False
   total_reward = 0
   steps = 0
   while not done:
       # Choose a random action
       action = env.action_space.sample()
       # Take the action and observe the result
       next_state, reward, terminated, truncated, _ = env.step(action)
       done = terminated or truncated
      
       # Capture the next state as an image
       img = env.render()
       frames.append(img)
       # Update total reward and step count
       total_reward += reward
       steps += 1
       # Move to the next state
       state = next_state

Pada versi ini, kita set jumlah episode hanya satu, karena merender state lingkungan sebagai gambar memakan banyak waktu. Kita juga membuat daftar kosong untuk menyimpan array gambar. Lalu, loop interaksi berlanjut seperti sebelumnya. Satu-satunya perbedaan adalah dua baris kode tambahan di mana kita merender lingkungan sebagai gambar dan menambahkannya ke frames.

Sekarang, kita seharusnya memiliki 201 gambar di dalam frames (satu gambar ekstra untuk state tambahan):

>>> len(frames)
201

Mari ubah gambar-gambar ini menjadi GIF menggunakan pustaka moviepy:

from moviepy.editor import ImageSequenceClip  # pip install moviepy
def create_gif(frames: list, filename, fps=5):
   """
   Creates a GIF animation from a list of RGBA NumPy arrays.
   Args:
       frames: A list of RGBA NumPy arrays representing the animation frames.
       filename: The output filename for the GIF animation.
       fps: The frames per second of the animation (default: 10).
   """
   clip = ImageSequenceClip(frames, fps=fps)
   clip.write_gif(filename, fps=fps)
# Example usage
create_gif(frames, "animation.gif", fps=25)  # saves the GIF locally

Fungsi create_gif() mengambil daftar frame dan mengonversinya menjadi GIF menggunakan kelas ImageSequenceClip dari moviepy. Parameter penting adalah frames per second, fps, yang mengendalikan durasi GIF. Semakin banyak frame per detik, semakin pendek GIF-nya.

Pada akhirnya, kita mengonversi frame dari satu episode menjadi GIF dengan 25 FPS. Berikut hasilnya:

GIF yang menampilkan interaksi acak agen (sebuah taksi) di lingkungan taksi, merepresentasikan siklus State-Action-Reward-Action-State

Seperti yang terlihat, taksi tidak tahu apa yang dilakukannya dan bahkan tidak mendekati penumpang. Mari kita berikan kecerdasan dengan menambahkan SARSA ke sistem navigasinya.

Mengimplementasikan SARSA di Python Langkah demi Langkah

Kita akan membangun kode SARSA dari nol agar setiap langkahnya mudah diingat.

1. Menyiapkan lingkungan Gymnasium:

import gymnasium as gym
import numpy as np
import matplotlib.pyplot as plt
# Create the Taxi environment
env = gym.make("Taxi-v3", render_mode="rgb_array")

2. Inisialisasi Q-table

# Initialize Q-table
n_states = env.observation_space.n
n_actions = env.action_space.n
Q_table = np.zeros((n_states, n_actions))

Pada langkah ini, kita memperkenalkan struktur data baru — Q-table. Dimensinya adalah (jumlah state) x (jumlah aksi). Tabel tersebut akan tampak seperti ini bagi agen kita, si sopir taksi:

Representasi visual Q-table, yang penting untuk algoritma reinforcement learning Q-learning dan SARSA.

Awalnya, Q-table akan terisi dengan nol:

>>> Q_table.shape
(500, 6)

Kemudian, saat agen mulai berinteraksi dengan lingkungan dipandu oleh SARSA, ia akan memperbarui Q-table dengan nilai Q. Nilai Q adalah skor yang memberi tahu agen aksi mana yang terbaik dilakukan, mengingat state saat ini.

3. Mendefinisikan hiperparameter SARSA

Setelah menginisialisasi Q-table, kita set hiperparameter SARSA ke nilai umum (dibahas lebih lanjut nanti):

# SARSA parameters
alpha = 0.1  # Learning rate
gamma = 0.99  # Discount factor
epsilon = 0.1  # Exploration rate for epsilon-greedy policy
n_episodes = 20000

4. Menetapkan penyimpanan untuk metrik kinerja

Lalu, kita mendefinisikan dua daftar untuk menyimpan metrik kinerja: total hadiah dan jumlah langkah waktu untuk setiap episode. Tujuan agen adalah mengumpulkan sebanyak mungkin hadiah dalam waktu sesingkat mungkin:

# Lists to store performance metrics
episode_rewards = []
episode_lengths = []

5. Kebijakan epsilon-greedy untuk mengambil aksi

Pada bagian sebelumnya, agen kita tidak terpandu — ia mengambil aksi acak. Kita ingin mengubahnya dengan memberi sopir strategi Epsilon-Greedy:

def epsilon_greedy(state, epsilon):
   if np.random.random() < epsilon:
       # Take random action - explore
       return env.action_space.sample()
   else:
       # Take action with the highest Q-value - exploit
       return np.argmax(Q_table[state])

Strategi ini dimaksudkan untuk mengendalikan keseimbangan krusial antara eksplorasi dan eksploitasi. Dengan probabilitas epsilon, agen mengeksplorasi lingkungan dengan mengambil aksi acak, sedangkan dengan probabilitas 1-epsilon, ia mengeksploitasi pengetahuan saat ini dengan memilih aksi dengan nilai Q tertinggi dari Q-table. Pendekatan ini memungkinkan agen menemukan strategi baru yang berpotensi lebih baik sekaligus memanfaatkan apa yang sudah dipelajari.

6. Menulis loop pelatihan SARSA

Akhirnya, kita tulis loop pelatihan SARSA. Awal loop ini sudah familier. Satu-satunya perbedaan adalah kita menggunakan fungsi epsilon_greedy() untuk menentukan aksi mana yang diambil di state saat ini:

# SARSA training loop
for episode in range(n_episodes):
   state, _ = env.reset()
   action = epsilon_greedy(state, epsilon)
   done = False
   total_reward = 0
   steps = 0
   ...

Lalu, kita mulai loop while yang memungkinkan menjalankan siklus interaksi hingga mencapai state terminasi:

# SARSA training loop
for episode in range(n_episodes):
   ...
   while not done:
       next_state, reward, terminated, truncated, _ = env.step(action)
       done = terminated or truncated
       next_action = epsilon_greedy(next_state, epsilon)

Di dalam loop while, kita mengambil aksi yang dikembalikan oleh epsilon_greedy() dan menerima state berikutnya, hadiah untuk aksi kita, serta nilai boolean apakah episode berakhir atau tidak.

Kemudian, kita sampai pada bagian krusial — aturan pembaruan SARSA:

# SARSA training loop
for episode in range(n_episodes):
   ...
   while not done:
       next_state, reward, terminated, truncated, _ = env.step(action)
       done = terminated or truncated
       next_action = epsilon_greedy(next_state, epsilon)
       # SARSA update rule
       Q_table[state, action] += alpha * (
           reward + gamma * Q_table[next_state, next_action] - Q_table[state, action]
       )

Aturan pembaruan berasal dari rumus berikut:

Rumus untuk aturan pembaruan SARSA

[Sumber]

Kita akan mempelajari intuisi di balik rumus ini pada bagian selanjutnya. Untuk saat ini, anggap saja rumus tersebut sebagai semacam trik matematika yang memperbarui nilai Q pada Q-table sesuai aturan SARSA.

Setelah melakukan pembaruan Q, kita ubah variabel state dan action ke state dan aksi berikutnya, tambahkan hadiah yang diterima ke total hadiah episode, dan tingkatkan jumlah langkah waktu.

# SARSA training loop
for episode in range(n_episodes):
   ...
   while not done:
       ...
       state = next_state
       action = next_action
       total_reward += reward
       steps += 1

Loop while berlanjut hingga kita mencapai jumlah langkah maksimum (200 untuk lingkungan taksi) atau ketika taksi berhasil menurunkan penumpangnya di lokasi yang benar.

Setelah loop berakhir, kita catat total hadiah episode dan panjang episode. Kita juga mencetak rata-rata hadiah dan panjang episode setiap 1000 episode:

# SARSA training loop
for episode in range(n_episodes):
   ...
   while not done:
       ...
   episode_rewards.append(total_reward)
   episode_lengths.append(steps)
   if episode % 1000 == 0:
       avg_reward = np.mean(episode_rewards[-1000:])
       avg_length = np.mean(episode_lengths[-1000:])
       print(f"Episode {episode}, Avg Reward: {avg_reward:.2f}, Avg Length: {avg_length:.2f}")

Berikut loop interaksi lengkap yang dieksekusi:

# SARSA training loop
for episode in range(n_episodes):
   state, _ = env.reset()
   action = epsilon_greedy(state, epsilon)
   done = False
   total_reward = 0
   steps = 0
   while not done:
       next_state, reward, terminated, truncated, _ = env.step(action)
       done = terminated or truncated
       next_action = epsilon_greedy(next_state, epsilon)
       Q_table[state, action] += alpha * (
           reward + gamma * Q_table[next_state, next_action] - Q_table[state, action]
       )
       state = next_state
       action = next_action
       total_reward += reward
       steps += 1
   episode_rewards.append(total_reward)
   episode_lengths.append(steps)
   if episode % 2000 == 0:
       avg_reward = np.mean(episode_rewards[-1000:])
       avg_length = np.mean(episode_lengths[-1000:])
       print(f"Episode {episode}, Avg Reward: {avg_reward:.2f}, Avg Length: {avg_length:.2f}")
Episode 0, Avg Reward: -551.00, Avg Length: 185.00
Episode 2000, Avg Reward: -4.37, Avg Length: 19.47
Episode 4000, Avg Reward: 1.98, Avg Length: 15.09
Episode 6000, Avg Reward: 2.29, Avg Length: 14.79
Episode 8000, Avg Reward: 2.06, Avg Length: 14.80
Episode 10000, Avg Reward: 2.16, Avg Length: 14.78
Episode 12000, Avg Reward: 2.06, Avg Length: 14.89
Episode 14000, Avg Reward: 2.33, Avg Length: 14.81
Episode 16000, Avg Reward: 2.36, Avg Length: 14.66
Episode 18000, Avg Reward: 2.53, Avg Length: 14.72

Seperti terlihat pada output, rata-rata hadiah dan jumlah langkah per episode turun drastis seiring kita menjalankan lebih banyak episode.

Kita bisa melihatnya secara visual dengan memplot array episode_rewards dan episode_lengths:

# Plot the learning curve
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(episode_rewards)
plt.title("Episode Rewards")
plt.xlabel("Episode")
plt.ylabel("Total Reward")
plt.subplot(1, 2, 2)
plt.plot(episode_lengths)
plt.title("Episode Lengths")
plt.xlabel("Episode")
plt.ylabel("Number of Steps")
plt.tight_layout()
plt.show()

Dua plot yang menunjukkan dua metrik kinerja untuk SARSA: total hadiah per episode dan panjang episode

Plot kiri menampilkan total hadiah yang diperoleh pada setiap episode. Kita dapat mengamati bahwa:

  • Awalnya, hadiah rendah dan sangat bervariasi, menunjukkan agen sedang mengeksplorasi dan belajar.
  • Seiring waktu, ada tren kenaikan pada hadiah, menandakan agen memperbaiki kebijakannya.
  • Menjelang akhir, hadiah tampak stabil pada level lebih tinggi, menunjukkan agen telah mempelajari kebijakan yang cukup baik.

Plot kanan menunjukkan jumlah langkah yang diambil pada setiap episode. Kita dapat melihat bahwa:

  • Di awal, episode cenderung lebih panjang, karena agen mengambil aksi yang kurang optimal.
  • Seiring pembelajaran, terdapat tren penurunan panjang episode secara umum.
  • Panjang episode akhirnya stabil, menunjukkan agen telah belajar menyelesaikan tugas dengan lebih efisien.

Mengorganisasi Kode ke dalam Fungsi

Dalam waktu singkat, kita telah membahas banyak hal. Sekarang mari mundur selangkah dan mengorganisasi semuanya yang sudah kita tulis. Kita akan membuat fungsi untuk tiap langkah implementasi SARSA.

Pertama, fungsi untuk membuat lingkungan:

import gymnasium as gym
import numpy as np
import matplotlib.pyplot as plt
from moviepy.editor import ImageSequenceClip
def create_environment(env_name="Taxi-v3", render_mode="rgb_array"):
   """Create and return a Gymnasium environment."""
   return gym.make(env_name, render_mode=render_mode)

Lalu, fungsi untuk menginisialisasi Q-table berdasarkan lingkungan:

def initialize_q_table(env):
   """Initialize and return a Q-table for the given environment."""
   n_states = env.observation_space.n
   n_actions = env.action_space.n
   return np.zeros((n_states, n_actions))

Strategi epsilon-greedy yang menerima lingkungan, Q-table, state saat ini, dan epsilon:

def epsilon_greedy(env, Q_table, state, epsilon=0.1):
   """Epsilon-greedy action selection."""
   if np.random.random() < epsilon:
       return env.action_space.sample()
   else:
       return np.argmax(Q_table[state])

Aturan pembaruan SARSA, yang membutuhkan Q-table, state saat ini, aksi yang diambil pada state tersebut, hadiah untuk aksi, state dan aksi berikutnya:

def sarsa_update(Q_table, state, action, reward, next_state, next_action, alpha, gamma):
   """Perform SARSA update on Q-table."""
   Q_table[state, action] += alpha * (
       reward + gamma * Q_table[next_state, next_action] - Q_table[state, action]
   )

Terakhir, fungsi besar untuk melatih agen dengan SARSA yang membutuhkan lingkungan, jumlah episode, serta parameter alpha, gamma, dan epsilon:

def train_sarsa(env, n_episodes=20000, alpha=0.1, gamma=0.99, epsilon=0.1):
   """Train the agent using SARSA algorithm."""
   Q_table = initialize_q_table(env)
   episode_rewards = []
   episode_lengths = []
   for episode in range(n_episodes):
       state, _ = env.reset()
       action = epsilon_greedy(env, Q_table, state, epsilon)
       done = False
       total_reward = 0
       steps = 0
       while not done:
           next_state, reward, terminated, truncated, _ = env.step(action)
           done = terminated or truncated
           next_action = epsilon_greedy(env, Q_table, next_state, epsilon)
           sarsa_update(
               Q_table, state, action, reward, next_state, next_action, alpha, gamma
           )
           state = next_state
           action = next_action
           total_reward += reward
           steps += 1
       episode_rewards.append(total_reward)
       episode_lengths.append(steps)
   return Q_table, episode_rewards, episode_lengths

Juga, fungsi untuk memplot metrik kinerja:

def plot_learning_curve(episode_rewards, episode_lengths):
   """Plot the learning curve."""
   plt.figure(figsize=(12, 5))
   plt.subplot(1, 2, 1)
   plt.plot(episode_rewards)
   plt.title("Episode Rewards")
   plt.xlabel("Episode")
   plt.ylabel("Total Reward")
   plt.subplot(1, 2, 2)
   plt.plot(episode_lengths)
   plt.title("Episode Lengths")
   plt.xlabel("Episode")
   plt.ylabel("Number of Steps")
   plt.tight_layout()
   plt.show()

Fungsi create_gif() kita sebelumnya:

def create_gif(frames, filename, fps=5):
   """Creates a GIF animation from a list of frames."""
   clip = ImageSequenceClip(frames, fps=fps)
   clip.write_gif(filename, fps=fps)

Dan satu fungsi lagi untuk menjalankan satu episode dengan rendering menggunakan Q-table yang sudah dipelajari lengkap (untuk keperluan animasi):

def run_episode(env, Q_table, epsilon=0):
   """Run a single episode using the learned Q-table."""
   state, _ = env.reset()
   done = False
   total_reward = 0
   frames = [env.render()]
   while not done:
       action = epsilon_greedy(env, Q_table, state, epsilon)
       next_state, reward, terminated, truncated, _ = env.step(action)
       done = terminated or truncated
       frames.append(env.render())
       total_reward += reward
       state = next_state
   return frames, total_reward

Sekarang, mari eksekusi semuanya:

if __name__ == "__main__":
   env = create_environment()
  
   Q_table, episode_rewards, episode_lengths = train_sarsa(env, n_episodes=20000)
   plot_learning_curve(episode_rewards, episode_lengths)
  
   frames, total_reward = run_episode(env, Q_table)
   create_gif(frames, "images/sarsa_final_animation.gif", fps=1)

Dua plot yang menunjukkan dua metrik kinerja untuk SARSA: total hadiah per episode dan panjang episode

Plot performa terlihat bagus. Sekarang, mari lihat GIF yang dihasilkan:

GIF yang menunjukkan penjemputan dan penurunan penumpang yang berhasil oleh agen taksi reinforcement learning yang dilatih menggunakan algoritma SARSA

Hore! Taksi dengan benar menjemput penumpang dari kotak biru dan menurunkannya di kotak kuning.

Saya telah menempelkan seluruh kode terorganisasi untuk mengimplementasikan SARSA ke sebuah gist GitHub agar Anda bisa kembali kapan pun Anda mau.

Intuisi di Balik Aturan Pembaruan SARSA

Inti dari SARSA adalah aturan pembaruannya, yang mengendalikan bagaimana agen belajar dari pengalamannya. Mari uraikan aturan ini dan jelajahi intuisinya:

Q(s, a) = Q(s, a) + α [R + γ Q(s', a') - Q(s, a)]

Memahami komponennya

  • Q(s, a): Nilai Q saat ini untuk mengambil aksi ‘a’ pada state ‘s’.
  • α (alpha): Laju pembelajaran, mengendalikan seberapa cepat informasi baru diintegrasikan.
  • R: Hadiah yang diterima setelah mengambil aksi.
  • γ (gamma): Faktor diskonto, menentukan pentingnya hadiah di masa depan.
  • Q(s’, a’): Estimasi nilai Q dari pasangan state-aksi berikutnya.

Proses pembelajaran

Aturan pembaruan SARSA bertujuan menyempurnakan pemahaman agen tentang lingkungan dengan menyesuaikan nilai Q berdasarkan pengalaman baru. Begini cara kerjanya:

  1. Agen mengambil sebuah aksi dan mengamati hadiah serta state berikutnya.
  2. Agen menghitung selisih antara nilai Q saat ini dan estimasi nilai Q baru berdasarkan hadiah yang diamati dan nilai pasangan state-aksi berikutnya.
  3. Selisih ini, diskalakan oleh laju pembelajaran, digunakan untuk memperbarui nilai Q.

Kesalahan perbedaan temporal

Istilah [R + γ * Q(s’, a’) — Q(s, a)] dikenal sebagai kesalahan perbedaan temporal (temporal difference/TD error). Anggap saja sebagai ukuran “kejutan”:

  • TD error positif: Hasil lebih baik dari yang diharapkan.
  • TD error negatif: Hasil lebih buruk dari yang diharapkan.
  • TD error nol: Hasil cocok sempurna dengan estimasi saat ini.

Kesalahan ini membantu agen terus menyempurnakan estimasinya, mendorong proses pembelajaran menuju kebijakan yang optimal.

Peran hiperparameter

1. Laju pembelajaran (α):

  • Mengontrol kecepatan pembelajaran.
  • α lebih tinggi: Pembelajaran lebih cepat, tetapi berpotensi tidak stabil.
  • α lebih rendah: Pembelajaran lebih lambat namun lebih stabil.

2. Faktor diskonto (γ):

  • Menyeimbangkan hadiah langsung dan masa depan.
  • γ mendekati 1: Agen menghargai hadiah masa depan hampir setara dengan hadiah langsung.
  • γ lebih rendah: Agen lebih fokus pada hadiah langsung.

3. Laju eksplorasi (ε):

  • Meski tidak ada di aturan pembaruan, ini krusial untuk kebijakan epsilon-greedy.
  • Menyeimbangkan eksplorasi (mencoba aksi baru) dan eksploitasi (menggunakan aksi yang sudah diketahui bagus).
  • ε lebih tinggi: Lebih banyak eksplorasi, berpotensi menemukan strategi lebih baik dengan biaya kinerja jangka pendek.

Gambaran besar

Aturan pembaruan SARSA memungkinkan agen belajar dari pengalaman dengan terus menyesuaikan estimasi nilai state-aksi. Dengan setiap interaksi, agen menjadi sedikit lebih “bijak” tentang lingkungannya. Selama banyak episode, proses ini mengarah pada pengembangan kebijakan optimal untuk menavigasi lingkungan.

Dengan menyetel hiperparameter, kita dapat mengendalikan berbagai aspek proses pembelajaran, memungkinkan SARSA beradaptasi dengan berbagai jenis masalah dan lingkungan. Fleksibilitas ini, dikombinasikan dengan aturan pembaruan yang intuitif, menjadikan SARSA algoritma reinforcement learning yang kuat dan banyak digunakan.

SARSA vs. Q-learning: Perbedaan Utama

Walau SARSA dan Q-learning sama-sama algoritma reinforcement learning yang banyak digunakan, keduanya memiliki beberapa perbedaan penting. Dan perbedaan itu krusial untuk memahami kapan dan bagaimana menggunakan masing-masing algoritma.

1. On-policy vs. off-policy

Sebagai algoritma on-policy, SARSA mempelajari nilai dari kebijakan yang diikutinya, termasuk langkah-langkah yang diambil selama eksplorasi. Q-learning bersifat off-policy; ia mempelajari nilai dari kebijakan optimal — bahkan ketika tidak mengikuti kebijakan itu, tetap mempelajari nilai kebijakan optimal ketika pada akhirnya mencapai akhir episode. Itulah mengapa kita menyebutkan di awal bahwa SARSA harus digunakan ketika perjalanan pembelajaran sama pentingnya dengan hasilnya. Q-learning tidak terlalu peduli pada perjalanan pembelajaran.

2. Aturan pembaruan

  • SARSA: Q(s, a) = Q(s, a) + α * [R + γ * Q(s’, a’) — Q(s, a)]
  • Q-learning: Q(s, a) = Q(s, a) + α * [R + γ * max(Q(s’, a’)) — Q(s, a)]

Perbedaan kuncinya adalah SARSA menggunakan nilai Q dari aksi berikutnya yang benar-benar diambil (a’), sedangkan Q-learning menggunakan nilai Q maksimum dari state berikutnya (max(Q(s’, a’))).

3. Pertimbangan eksplorasi

Saat memperbarui nilai Q, SARSA tidak mengabaikan kebijakan eksplorasi dan karenanya lebih konservatif. Sebaliknya, Q-learning selalu mengasumsikan bahwa agen akan mengambil aksi optimal di masa depan dan karena itu lebih agresif.

4. Konvergensi

Meskipun keduanya pada akhirnya mencapai kebijakan optimal, Q-learning sering kali dapat belajar lebih cepat, khususnya di lingkungan deterministik.

5. Keamanan

Di lingkungan di mana eksplorasi dapat menimbulkan hasil buruk, SARSA umumnya mempelajari kebijakan yang lebih aman karena mempertimbangkan kebijakan aktual yang diikuti.

Dalam masalah klasik “cliff walking”, SARSA biasanya mempelajari jalur yang lebih aman yang menjauh dari tepi tebing, sedangkan Q-learning mungkin mempelajari jalur yang lebih berisiko yang berjalan di sepanjang tepi.

6. Stabilitas

Dalam lingkungan acak tertentu, SARSA bisa lebih stabil karena memperhitungkan aksi berikutnya yang sebenarnya, bahkan ketika aksi itu merupakan aksi eksplorasi yang suboptimal.

7. Sensitivitas hiperparameter

Q-learning bisa lebih sensitif terhadap pemilihan laju pembelajaran dan laju eksplorasi, terutama di lingkungan dengan stokastisitas signifikan.

8. Aplikasi dunia nyata

Dalam robotika atau sistem fisik lain di mana eksplorasi lingkungan mahal dan kita ingin menerapkan kebijakan yang lebih aman, kita mungkin lebih memilih algoritma on-policy SARSA. Ketika berada di dunia simulasi, permainan, atau lingkungan lain di mana kita bisa mendapatkan banyak umpan balik dan ingin menemukan kebijakan optimal dengan cara yang cepat dan cukup aman, kita mungkin lebih menyukai Q-learning.

Jadi Anda mungkin berpikir bahwa SARSA adalah “wilayah yang lebih aman”, dan Q-learning adalah pendekatan yang lebih cepat dan lebih nekat. Dalam praktiknya, ini sering bergantung pada masalah spesifik. Keduanya sangat kuat, dan selalu masuk akal untuk mengetahui perbedaan di antara keduanya.

Kesimpulan

Dalam panduan komprehensif ini, kita telah mengeksplorasi algoritma SARSA, mencakup konsep inti, detail implementasi, dan aplikasi praktis menggunakan lingkungan Taxi-v3.

Poin-poin utama meliputi:

  1. Sifat on-policy SARSA dan intuisi di balik aturan pembaruannya
  2. Implementasi Python dan teknik visualisasi
  3. Perbandingan dengan Q-learning, menyoroti kekuatan dan kasus penggunaan

Kemampuan SARSA untuk mempelajari kebijakan yang lebih aman membuatnya cocok untuk aplikasi dunia nyata di mana biaya eksplorasi tinggi, meskipun dalam beberapa skenario mungkin konvergen lebih lambat dibanding algoritma off-policy seperti Q-learning.

Ingat, memilih antara SARSA dan algoritma lain bergantung pada masalah dan lingkungan spesifik Anda. Eksperimen dan penyetelan sangat krusial untuk hasil optimal.

Kami mendorong Anda membangun fondasi ini dengan mengeksplorasi lingkungan yang lebih kompleks, mengimplementasikan SARSA dengan aproksimasi fungsi, atau mendalami algoritma reinforcement learning lainnya.

Berikut beberapa sumber terkait untuk membantu Anda di sepanjang jalan:

SARSA FAQs

Apa itu algoritma SARSA dalam reinforcement learning?

SARSA (State-Action-Reward-State-Action) adalah algoritma reinforcement learning on-policy yang memperbarui nilai Q berdasarkan pengalaman nyata agen, termasuk aksi eksplorasi.

Apa perbedaan SARSA dengan Q-learning?

SARSA bersifat on-policy dan memperbarui nilai Q menggunakan aksi berikutnya yang benar-benar diambil, sedangkan Q-learning bersifat off-policy dan menggunakan nilai Q maksimum dari state berikutnya, yang menghasilkan perilaku pembelajaran yang berbeda.

Apa saja hiperparameter kunci dalam SARSA, dan bagaimana pengaruhnya terhadap pembelajaran?

Hiperparameter kunci adalah laju pembelajaran (α), faktor diskonto (γ), dan laju eksplorasi (ε). Masing-masing mengendalikan kecepatan pembelajaran, pentingnya hadiah masa depan, dan keseimbangan antara eksplorasi dan eksploitasi.

Bagaimana saya dapat mengimplementasikan algoritma SARSA di Python?

Artikel ini menyediakan panduan langkah demi langkah untuk mengimplementasikan SARSA di Python, termasuk menyiapkan lingkungan, menginisialisasi Q-table, dan menulis loop pelatihan.

Apa aplikasi praktis SARSA dalam skenario dunia nyata?

SARSA cocok untuk aplikasi di mana biaya eksplorasi tinggi, seperti robotika dan sistem fisik, karena cenderung mempelajari kebijakan yang lebih aman dibanding algoritma off-policy seperti Q-learning.

Bexruz (Bex) Tuychiev

Penulis

Bexruz (Bex) Tuychiev

Saya adalah kreator konten data science dengan pengalaman lebih dari 2 tahun dan salah satu dengan jumlah pengikut terbesar di Medium. Saya suka menulis artikel mendalam tentang AI dan ML dengan sedikit gaya sarkastik—karena harus ada sesuatu untuk membuatnya tidak terlalu membosankan. Saya telah menghasilkan lebih dari 130 artikel dan satu kursus di DataCamp, dengan satu lagi sedang dalam proses. Konten saya telah dilihat oleh lebih dari 5 juta pasang mata, dan 20 ribu di antaranya menjadi pengikut di Medium dan LinkedIn. 

Topik

Terkait

blogs

Tutorial Korelasi di R

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

blogs

Spaghetti Plot dan Jalur Badai