lawarob-rl/ex1.py
Eric Seuret e4306824e1 Ex1
2025-11-04 06:41:01 +01:00

299 lines
8.5 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
import gymnasium as gym
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
def initialize_environment():
"""Initialisiere die FrozenLake Umgebung (deterministisch)."""
env = gym.make('FrozenLake-v1', is_slippery=False)
return env
def initialize_q_table(n_states, n_actions):
"""Initialisiere Q-Tabelle mit Nullen."""
return np.zeros((n_states, n_actions))
def select_action(state, Q, epsilon, n_actions):
"""
TODO: Implementiere ε-greedy Aktionswahl.
Args:
state: Aktueller Zustand
Q: Q-Tabelle
epsilon: Explorations-Wahrscheinlichkeit
n_actions: Anzahl möglicher Aktionen
Returns:
Gewählte Aktion
Hinweis:
- Mit Wahrscheinlichkeit ε: Wähle zufällige Aktion (Exploration)
- Mit Wahrscheinlichkeit 1-ε: Wähle beste Aktion gemäss Q-Tabelle (Exploitation)
- Verwende np.random.random() für Zufallszahl und np.random.randint() für zufällige Aktion
- Verwende np.argmax() um die beste Aktion zu finden
"""
...
def q_learning_update(Q, state, action, reward, next_state, alpha, gamma, done):
"""
TODO: Implementiere Q-Learning Update-Regel.
Q(s,a) ← Q(s,a) + α · [r + γ · max Q(s',a') - Q(s,a)]
Args:
Q: Q-Tabelle
state: Aktueller Zustand
action: Ausgeführte Aktion
reward: Erhaltene Belohnung
next_state: Nächster Zustand
alpha: Lernrate
gamma: Diskontierungsfaktor
done: Episode beendet?
Hinweis:
- Berechne TD Target: r + γ · max Q(s',a')
- Falls done=True: TD Target = r (keine zukünftige Belohnung mehr)
- Berechne TD Error: TD Target - Q(s,a)
- Update: Q(s,a) += α · TD Error
- Verwende np.argmax() um die beste nächste Aktion zu finden
"""
...
def train_q_learning(env, n_episodes=2000, alpha=0.1, gamma=0.99,
epsilon_start=1.0, epsilon_min=0.01, epsilon_decay=0.999):
"""
TODO: Implementiere Q-Learning Trainingsschleife.
Args:
env: Gymnasium Environment
n_episodes: Anzahl Trainings-Episoden
alpha: Lernrate
gamma: Diskontierungsfaktor
epsilon_start: Initiale Explorations-Rate
epsilon_min: Minimale Explorations-Rate
epsilon_decay: Explorations-Abnahme-Rate
Returns:
Q: Trainierte Q-Tabelle
rewards: Liste der Episoden-Belohnungen
Hinweis:
1. Initialisiere Q-Tabelle und epsilon
2. Für jede Episode:
a. Environment zurücksetzen (env.reset())
b. Solange nicht fertig:
- Aktion wählen mit select_action()
- Aktion ausführen in Environment (env.step())
- Q-Tabelle updaten mit q_learning_update()
- Zustand updaten
c. Epsilon decay: epsilon = max(epsilon_min, epsilon * epsilon_decay)
d. Episode-Belohnung speichern
3. Fortschritt ausgeben alle 100 Episoden
"""
# Initialisierung
n_states = env.observation_space.n
n_actions = env.action_space.n
Q = initialize_q_table(n_states, n_actions)
epsilon = epsilon_start
rewards = []
# TODO: Implementiere Trainingsschleife hier
...
return Q, rewards
def evaluate_policy(env, Q, n_episodes=100):
"""
Evaluiere gelernte Policy ohne Exploration.
Diese Funktion ist bereits implementiert.
Args:
env: Gymnasium Environment
Q: Trainierte Q-Tabelle
n_episodes: Anzahl Evaluations-Episoden
Returns:
success_rate: Erfolgsrate in Prozent
avg_reward: Durchschnittliche Belohnung pro Episode
"""
successes = 0
total_reward = 0
for episode in range(n_episodes):
state, _ = env.reset()
done = False
episode_reward = 0
while not done:
# Greedy Aktion (keine Exploration)
action = np.argmax(Q[state, :])
state, reward, terminated, truncated, _ = env.step(action)
done = terminated or truncated
episode_reward += reward
total_reward += episode_reward
if episode_reward > 0:
successes += 1
success_rate = (successes / n_episodes) * 100
avg_reward = total_reward / n_episodes
return success_rate, avg_reward
def plot_learning_curve(rewards, window=100):
"""
Plotte Lernkurve mit gleitendem Durchschnitt.
Diese Funktion ist bereits implementiert.
Args:
rewards: Liste der Episoden-Belohnungen
window: Fenstergrösse für gleitenden Durchschnitt
"""
plt.figure(figsize=(10, 6))
plt.plot(rewards, alpha=0.3, label='Episoden-Belohnung')
# Gleitender Durchschnitt
if len(rewards) >= window:
moving_avg = np.convolve(rewards, np.ones(window)/window, mode='valid')
plt.plot(range(window-1, len(rewards)), moving_avg,
label=f'Gleitender Durchschnitt ({window} Episoden)', linewidth=2)
plt.xlabel('Episode')
plt.ylabel('Belohnung')
plt.title('Lernkurve')
plt.legend(loc='lower right')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
def visualize_q_table(Q):
"""
Visualisiere Q-Tabelle als Heatmap.
Diese Funktion ist bereits implementiert.
Args:
Q: Q-Tabelle
"""
plt.figure(figsize=(10, 8))
sns.heatmap(Q, annot=True, fmt='.2f', cmap='YlOrRd',
xticklabels=['', '', '', ''],
yticklabels=[str(i) for i in range(Q.shape[0])])
plt.title('Q-Tabelle nach Training')
plt.xlabel('Aktion')
plt.ylabel('Zustand')
plt.tight_layout()
plt.show()
def visualize_policy(Q):
"""
Visualisiere gelernte Policy auf dem Grid.
Diese Funktion ist bereits implementiert.
Args:
Q: Q-Tabelle
"""
policy = np.argmax(Q, axis=1)
action_arrows = {0: '', 1: '', 2: '', 3: ''}
print("\n" + "="*40)
print("GELERNTE POLICY")
print("="*40)
print("\nFrozenLake Grid:")
print("SFFF")
print("FHFH")
print("FFFH")
print("HFFG")
print("\nOptimale Aktionen:")
policy_grid = policy.reshape(4, 4)
for i, row in enumerate(policy_grid):
row_str = ' '.join([action_arrows[a] for a in row])
print(f"Reihe {i}: {row_str}")
print("\nZustand-für-Zustand Policy:")
for state in range(16):
row, col = state // 4, state % 4
print(f"Zustand {state:2d} (Reihe {row}, Spalte {col}): {action_arrows[policy[state]]}")
print("="*40 + "\n")
def main():
"""Hauptfunktion für alle Aufgaben aus Übung 1."""
print("="*60)
print("Q-LEARNING FÜR FROZENLAKE (DETERMINISTISCH)")
print("Praktische Übung 1")
print("="*60)
# Environment initialisieren
env = initialize_environment()
n_states = env.observation_space.n
n_actions = env.action_space.n
print(f"\nEnvironment: FrozenLake-v1 (is_slippery=False)")
print(f"Zustände: {n_states}")
print(f"Aktionen: {n_actions}")
# ========================================
# HYPERPARAMETER
# ========================================
n_episodes = 2000
alpha = 0.4 # Lernrate - Versuche: 0.01, 0.5
gamma = 0.99 # Diskontierung - Versuche: 0.5, 0.99
epsilon_start = 1.0
epsilon_min = 0.01
epsilon_decay = 0.999 # Versuche: 1.0 (kein Decay)
# Q-Learning trainieren
print("\n--- Q-Learning Training ---")
print(f"Hyperparameter: α={alpha}, γ={gamma}, ε_decay={epsilon_decay}")
Q, rewards = train_q_learning(
env,
n_episodes=n_episodes,
alpha=alpha,
gamma=gamma,
epsilon_start=epsilon_start,
epsilon_min=epsilon_min,
epsilon_decay=epsilon_decay
)
# Lernkurve plotten
print("\n--- Lernkurve ---")
plot_learning_curve(rewards)
# Policy evaluieren
print("\n--- Policy Evaluation ---")
success_rate, avg_reward = evaluate_policy(env, Q, n_episodes=100)
print(f"Erfolgsrate (100 Episoden): {success_rate:.1f}%")
print(f"Durchschnittliche Belohnung: {avg_reward:.3f}")
# Visualisierungen
print("\n--- Visualisierungen ---")
visualize_q_table(Q)
visualize_policy(Q)
print("\n" + "="*60)
print("TRAINING ABGESCHLOSSEN!")
print("="*60)
print("\nÄndere die Hyperparameter oben und führe erneut aus!")
print(" - Versuche α = 0.01 oder α = 0.5")
print(" - Versuche γ = 0.5 oder γ = 0.99")
print(" - Versuche epsilon_decay = 1.0 (kein Decay)")
env.close()
if __name__ == "__main__":
main()