Was ist Reinforcement Learning?
Reinforcement Learning (RL) ist ein Paradigma des Machine Learning, bei dem ein Agent lernt, durch Interaktion mit einer Umgebung optimale Entscheidungen zu treffen. Anders als beim überwachten Lernen gibt es keine vordefinierten richtigen Antworten - der Agent lernt durch Trial-and-Error und Belohnungen.
RL hat spektakuläre Erfolge erzielt: von AlphaGo's Sieg gegen den Go-Weltmeister über autonome Fahrzeuge bis hin zu Robotersteuerung. Es ist besonders geeignet für sequentielle Entscheidungsprobleme, bei denen Aktionen langfristige Konsequenzen haben.
Die RL-Komponenten
Ein RL-System besteht aus vier Hauptkomponenten: Agent (Lerner), Environment (Umgebung), Actions (Aktionen) und Rewards (Belohnungen). Der Agent wählt Aktionen, die Umgebung reagiert mit neuen Zuständen und Belohnungen.
Q-Learning: Der klassische Ansatz
Q-Learning ist einer der fundamentalen RL-Algorithmen. Er lernt eine Q-Funktion, die den erwarteten zukünftigen Reward für jede Zustands-Aktions-Kombination schätzt.
import numpy as np
import gym
class QLearningAgent:
def __init__(self, n_states, n_actions, learning_rate=0.1,
discount_factor=0.95, epsilon=1.0):
self.q_table = np.zeros((n_states, n_actions))
self.lr = learning_rate
self.gamma = discount_factor
self.epsilon = epsilon
self.epsilon_decay = 0.995
self.epsilon_min = 0.01
def choose_action(self, state):
if np.random.random() < self.epsilon:
return np.random.randint(0, self.q_table.shape[1])
else:
return np.argmax(self.q_table[state])
def update(self, state, action, reward, next_state):
current_q = self.q_table[state, action]
max_next_q = np.max(self.q_table[next_state])
new_q = current_q + self.lr * (reward + self.gamma * max_next_q - current_q)
self.q_table[state, action] = new_q
self.epsilon = max(self.epsilon_min, self.epsilon * self.epsilon_decay)
env = gym.make('FrozenLake-v1')
agent = QLearningAgent(env.observation_space.n, env.action_space.n)
for episode in range(10000):
state = env.reset()[0]
done = False
while not done:
action = agent.choose_action(state)
next_state, reward, done, truncated, info = env.step(action)
agent.update(state, action, reward, next_state)
state = next_state
Q-Learning Kernkonzepte
- Q-Value: Erwarteter kumulativer Reward für eine Aktion in einem Zustand
- Exploration vs Exploitation: Balance zwischen Erkunden und Ausnutzen
- Epsilon-Greedy: Strategie für Exploration (hohe Epsilon = mehr Exploration)
- Discount Factor: Gewichtung zukünftiger vs. sofortiger Rewards
Deep Q-Networks (DQN)
DQN kombiniert Q-Learning mit Deep Neural Networks und ermöglicht RL in hochdimensionalen Zustandsräumen wie Videospielen. Dies war der Durchbruch von DeepMind mit Atari-Spielen.
import torch
import torch.nn as nn
import torch.optim as optim
from collections import deque
import random
class DQN(nn.Module):
def __init__(self, state_size, action_size):
super(DQN, self).__init__()
self.fc1 = nn.Linear(state_size, 128)
self.fc2 = nn.Linear(128, 128)
self.fc3 = nn.Linear(128, action_size)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
return self.fc3(x)
class DQNAgent:
def __init__(self, state_size, action_size):
self.state_size = state_size
self.action_size = action_size
self.memory = deque(maxlen=10000)
self.gamma = 0.95
self.epsilon = 1.0
self.epsilon_decay = 0.995
self.epsilon_min = 0.01
self.learning_rate = 0.001
self.model = DQN(state_size, action_size)
self.target_model = DQN(state_size, action_size)
self.optimizer = optim.Adam(self.model.parameters(),
lr=self.learning_rate)
def remember(self, state, action, reward, next_state, done):
self.memory.append((state, action, reward, next_state, done))
def act(self, state):
if np.random.random() <= self.epsilon:
return random.randrange(self.action_size)
state = torch.FloatTensor(state).unsqueeze(0)
q_values = self.model(state)
return torch.argmax(q_values).item()
def replay(self, batch_size):
if len(self.memory) < batch_size:
return
batch = random.sample(self.memory, batch_size)
for state, action, reward, next_state, done in batch:
target = reward
if not done:
next_state_tensor = torch.FloatTensor(next_state).unsqueeze(0)
target = reward + self.gamma * torch.max(
self.target_model(next_state_tensor)
).item()
state_tensor = torch.FloatTensor(state).unsqueeze(0)
q_values = self.model(state_tensor)
target_f = q_values.clone()
target_f[0][action] = target
loss = nn.MSELoss()(q_values, target_f)
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
Policy Gradient Methoden
Policy Gradient Methoden optimieren direkt die Policy (Handlungsstrategie) statt einer Value-Funktion. Dies ist besonders nützlich für kontinuierliche Aktionsräume.
import torch
import torch.nn as nn
from torch.distributions import Categorical
class PolicyNetwork(nn.Module):
def __init__(self, state_size, action_size):
super(PolicyNetwork, self).__init__()
self.fc1 = nn.Linear(state_size, 128)
self.fc2 = nn.Linear(128, action_size)
def forward(self, x):
x = torch.relu(self.fc1(x))
action_probs = torch.softmax(self.fc2(x), dim=-1)
return action_probs
class REINFORCEAgent:
def __init__(self, state_size, action_size):
self.policy = PolicyNetwork(state_size, action_size)
self.optimizer = optim.Adam(self.policy.parameters(), lr=0.001)
self.gamma = 0.99
self.saved_log_probs = []
self.rewards = []
def select_action(self, state):
state = torch.FloatTensor(state)
probs = self.policy(state)
m = Categorical(probs)
action = m.sample()
self.saved_log_probs.append(m.log_prob(action))
return action.item()
def update_policy(self):
R = 0
returns = []
for r in self.rewards[::-1]:
R = r + self.gamma * R
returns.insert(0, R)
returns = torch.tensor(returns)
returns = (returns - returns.mean()) / (returns.std() + 1e-9)
policy_loss = []
for log_prob, R in zip(self.saved_log_probs, returns):
policy_loss.append(-log_prob * R)
self.optimizer.zero_grad()
policy_loss = torch.cat(policy_loss).sum()
policy_loss.backward()
self.optimizer.step()
self.saved_log_probs = []
self.rewards = []
Actor-Critic Methoden
Actor-Critic kombiniert die Vorteile von Value-Based und Policy-Based Methoden. Der Actor wählt Aktionen, während der Critic die Qualität dieser Aktionen bewertet.
import torch
import torch.nn as nn
class ActorCritic(nn.Module):
def __init__(self, state_size, action_size):
super(ActorCritic, self).__init__()
self.shared = nn.Sequential(
nn.Linear(state_size, 128),
nn.ReLU()
)
self.actor = nn.Sequential(
nn.Linear(128, 128),
nn.ReLU(),
nn.Linear(128, action_size),
nn.Softmax(dim=-1)
)
self.critic = nn.Sequential(
nn.Linear(128, 128),
nn.ReLU(),
nn.Linear(128, 1)
)
def forward(self, state):
features = self.shared(state)
action_probs = self.actor(features)
state_value = self.critic(features)
return action_probs, state_value
class A2CAgent:
def __init__(self, state_size, action_size):
self.model = ActorCritic(state_size, action_size)
self.optimizer = optim.Adam(self.model.parameters(), lr=0.001)
def train_step(self, state, action, reward, next_state, done):
state = torch.FloatTensor(state)
next_state = torch.FloatTensor(next_state)
action_probs, value = self.model(state)
_, next_value = self.model(next_state)
td_target = reward + (1 - done) * 0.99 * next_value
td_error = td_target - value
m = Categorical(action_probs)
actor_loss = -m.log_prob(torch.tensor(action)) * td_error.detach()
critic_loss = td_error.pow(2)
loss = actor_loss + critic_loss
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
Proximal Policy Optimization (PPO)
PPO ist einer der modernsten und zuverlässigsten RL-Algorithmen. Er ist die Grundlage vieler erfolgreicher Anwendungen, einschließlich ChatGPT's RLHF-Training.
from stable_baselines3 import PPO
from stable_baselines3.common.vec_env import DummyVecEnv
from stable_baselines3.common.callbacks import EvalCallback
import gym
env = gym.make('CartPole-v1')
env = DummyVecEnv([lambda: env])
eval_env = gym.make('CartPole-v1')
eval_env = DummyVecEnv([lambda: eval_env])
eval_callback = EvalCallback(
eval_env,
best_model_save_path='./logs/',
log_path='./logs/',
eval_freq=1000,
deterministic=True
)
model = PPO(
"MlpPolicy",
env,
learning_rate=3e-4,
n_steps=2048,
batch_size=64,
n_epochs=10,
gamma=0.99,
gae_lambda=0.95,
clip_range=0.2,
verbose=1,
tensorboard_log="./ppo_tensorboard/"
)
model.learn(
total_timesteps=100000,
callback=eval_callback
)
model.save("ppo_cartpole")
obs = env.reset()
for i in range(1000):
action, _states = model.predict(obs, deterministic=True)
obs, reward, done, info = env.step(action)
if done:
obs = env.reset()
PPO Vorteile
PPO ist sample-effizient, stabil und einfach zu implementieren. Es verwendet einen Clipping-Mechanismus, um zu große Policy-Updates zu vermeiden und damit das Training zu stabilisieren.
Best Practices für RL-Projekte
Reinforcement Learning kann herausfordernd sein. Hier sind bewährte Praktiken für erfolgreiche RL-Implementierungen:
RL Best Practices
- Einfach beginnen: Starten Sie mit einfachen Umgebungen (CartPole, FrozenLake)
- Reward Shaping: Design Sie informative Reward-Funktionen
- Hyperparameter: Experimentieren Sie systematisch mit Lernrate, Gamma, etc.
- Stabilität: Nutzen Sie bewährte Algorithmen wie PPO oder SAC
- Monitoring: Tracken Sie Episode Rewards und Success Rate
- Reproducibility: Setzen Sie Random Seeds für reproduzierbare Ergebnisse
Fazit
Reinforcement Learning ist ein faszinierendes und mächtiges Paradigma des Machine Learning. Von einfachen Q-Learning-Algorithmen bis zu fortgeschrittenen Deep RL-Methoden - RL ermöglicht es Agenten, komplexe Aufgaben durch Erfahrung zu meistern.
Der Einstieg in RL erfordert Geduld und Experimentierfreude. Beginnen Sie mit klassischen Algorithmen, verstehen Sie die Grundkonzepte und arbeiten Sie sich zu modernen Deep RL-Methoden vor. Die Belohnung ist die Fähigkeit, autonome Systeme zu entwickeln, die selbstständig lernen und sich verbessern.
Nächste Schritte
Erkunden Sie fortgeschrittene Themen wie Multi-Agent RL, Inverse RL und Model-Based RL. OpenAI Gym und Stable-Baselines3 sind exzellente Ressourcen für praktisches Lernen!