Önceki yazıda KartPole problemini Çapraz-Entropi Yöntemiyle çözdük: 200 aday politika örnekleniyor, en iyilerinden 40'ı seçilip bir Gauss dağılımı yeniden uyarlanıyor ve bu işlem tekrarlanıyordu. Mükemmel 500 puana 50 iterasyonda ulaşarak harika sonuçlar elde ettik. Ancak her iterasyonda 200 aday, toplamda 10.000 değerlendirme anlamına geliyor. Acaba dört iyi sayı bulmak için gerçekten 200 kişilik bir popülasyona mı ihtiyacımız var? Bu yazıyı ilham alan orijinal kod çok daha basit bir yaklaşım benimsemişti. Popülasyon yerine tek bir parametre seti tutuluyor ve her iterasyonda bu parametreler rastgele bozuluyordu. Bozulma sonucu puan artarsa kabul ediliyor ve bozulma aralığı daraltılıyordu. Bu kadar basit: ne popülasyon, ne dağılım uyarlama, ne de gradyanlar. Kaynak dosyasındaki yorumda şöyle deniyordu: "tıpkı benzetilmiş tavlama gibi." Bu yazının sonunda algoritmayı sıfırdan uygulayacak, KartPole-v1 problemini mükemmel 500 puanla çözecek ve bunun benzetilmiş tavlama kuramıyla nasıl bağlantılı olduğunu anlayacağız. Hadi yapalım. Etkileşimli not defterini açmak için rozete tıklayın: İşte tam uygulama. CEM gibi, dört parametreli doğrusal bir politika kullanıyoruz (gözlem boyutuna göre bir parametre). Ancak popülasyon örnelemek yerine tek bir çözümü bozuyoruz:
import numpy as np
import gymnasium as gym
def evaluate_policy(env_name, theta, n_episodes=10):"""Doğrusal politika ile birden fazla bölümü çalıştır ve ortalama ödülü döndür.""" total_reward = 0 for _ in range(n_episodes): env = gym.make(env_name) obs, _ = env.reset() episode_reward = 0 done = False while not done: action = 1 if np.dot(theta, obs) > 0 else 0 obs, reward, terminated, truncated, _ = env.step(action) episode_reward += reward done = terminated or truncated env.close() total_reward += episode_reward return total_reward / n_episodes
def simulated_annealing(env_name, n_params, n_iter=80, n_eval_episodes=10, alpha=1.0, decay=0.9):"""Politika aramada benzetilmiş tavlama ile adım boyutunu azaltan tepe tırmanma.""" best_theta = np.zeros(n_params) best_score = evaluate_policy(env_name, best_theta, n_eval_episodes) for i in range(n_iter):
En iyi çözümü boz (alpha ile ölçeklendirilmiş düzgün gürültü)
perturbation = (np.random.rand(n_params) - 0.5) * alpha candidate = best_theta + perturbation
Adayı birden fazla bölümde değerlendir
score = evaluate_policy(env_name, candidate, n_eval_episodes)
# Sadece daha iyiyse kabul et, ardından adım boyutunu daraltif score > best_score: best_theta = candidate best_score = score alpha *= decay print(f"İter {i+1:3d} | Puan: {score:.1f} | En İyi: {best_score:.1f} | Alfa: {alpha:.4f}") return best_theta
best_theta = simulated_annealing('CartPole-v1', n_params=4)
# İter 1 | Puan: 9.6 | En İyi: 9.6 | Alfa: 1.0000
# İter 9 | Puan: 128.7 | En İyi: 128.7 | Alfa: 0.6561
# İter 14 | Puan: 314.2 | En İyi: 314.2 | Alfa: 0.5314
# İter 24 | Puan: 465.7 | En İyi: 465.7 | Alfa: 0.4783
# İter 41 | Puan: 500.0 | En İyi: 500.0 | Alfa: 0.3874Mükemmel puan 41 iterasyonda elde edildi. 100 değerlendirme bölümüyle doğrulayalım: scores = [evaluate_policy('CartPole-v1', best_theta, n_episodes=1) for _ in range(100)] print(f"Ortalama: {np.mean(scores):.0f} +/- {np.std(scores):.0f}")
Ortalama: 496 +/- 12
Dört parametre, sıfır gradyan, toplam 800 bölüm değerlendirmesi. CEM'in 10.000 ya da REINFORCE'ın 5.000 bölüm değerlendirmesiyle karşılaştırın.
Ne Oldu?
Algoritma tek bir aday çözüm tutuyor ve onu boz-değerlendir-kabul et döngüsüyle geliştiriyor. İşte tam döngü:
Doğrusal Politika
CEM yazısında olduğu gibi, KartPole'un 4 boyutlu bir gözlem vektörü var (arabaların konumu, hızı, direğin açısı, açısal hızı). Politikamız basit bir nokta çarpımı: action = 1 if np.dot(theta, obs) > 0 else 0 Bu bir doğrusal sınıflandırıcıdır: ağırlıklı gözlem toplamı pozitifse sağa it, değilse sola it. Ajanın tüm "zekası" dört sayıda gizli.
Yapay zeka özeti
Learn how to solve CartPole-v1 using simulated annealing, a simple yet effective algorithm for reinforcement learning