强化学习概述#
什么是强化学习?#
强化学习(Reinforcement Learning) 是智能体通过与环境交互,根据奖励信号学习最优策略的机器学习方法。
核心特点#
- 交互式学习:通过试错学习
- 延迟奖励:奖励可能延迟到来
- 探索与利用:平衡探索新动作和利用已知好动作
应用场景#
- 游戏AI:AlphaGo、Dota 2
- 机器人控制:行走、抓取
- 自动驾驶:决策规划
- 推荐系统:个性化推荐
基本概念#
智能体与环境#
智能体(Agent)
↓ 动作 a_t
环境(Environment)
↓ 状态 s_{t+1}, 奖励 r_{t+1}
智能体关键要素#
1. 状态(State)#
环境的当前情况,用 s 表示。
2. 动作(Action)#
智能体可以执行的操作,用 a 表示。
3. 奖励(Reward)#
环境对动作的反馈,用 r 表示。
4. 策略(Policy)#
从状态到动作的映射,用 π(a|s) 表示。
5. 价值函数(Value Function)#
评估状态或动作的价值。
马尔可夫决策过程#
MDP定义#
MDP(Markov Decision Process) 是强化学习的数学框架:
$$ \text{MDP} = (S, A, P, R, \gamma) $$其中:
- $S$ :状态空间
- $A$ :动作空间
- $P$ :转移概率 $P(s'|s,a)$
- $R$ :奖励函数 $R(s,a,s')$
- $\gamma$ :折扣因子 $[0,1]$
马尔可夫性质#
未来只依赖于当前状态:
$$ P(s_{t+1}|s_t, a_t, s_{t-1}, \ldots) = P(s_{t+1}|s_t, a_t) $$目标#
找到最优策略 $\pi^*$ ,最大化累积奖励:
$$ G_t = r_{t+1} + \gamma r_{t+2} + \gamma^2 r_{t+3} + \ldots $$价值函数#
状态价值函数#
在策略 $\pi$ 下,状态 $s$ 的价值:
$$ V^\pi(s) = \mathbb{E}_\pi[G_t | s_t = s] $$动作价值函数(Q函数)#
在状态 $s$ 执行动作 $a$ 的价值:
$$ Q^\pi(s,a) = \mathbb{E}_\pi[G_t | s_t = s, a_t = a] $$最优价值函数#
$$ V^*(s) = \max_\pi V^\pi(s) $$ $$ Q^*(s,a) = \max_\pi Q^\pi(s,a) $$Bellman方程#
状态价值#
$$ V^\pi(s) = \sum_a \pi(a|s) \sum_{s'} P(s'|s,a)[R(s,a,s') + \gamma V^\pi(s')] $$Q函数#
$$ Q^\pi(s,a) = \sum_{s'} P(s'|s,a)\left[R(s,a,s') + \gamma \sum_{a'} \pi(a'|s')Q^\pi(s',a')\right] $$Q-Learning#
概述#
Q-Learning 是值函数方法,学习最优Q函数。
更新规则#
$$ Q(s_t, a_t) \leftarrow Q(s_t, a_t) + \alpha[r_{t+1} + \gamma \max_a Q(s_{t+1}, a) - Q(s_t, a_t)] $$其中 $\alpha$ 是学习率。
特点#
- 离策略:可以学习最优策略,而不遵循它
- 表格方法:适用于离散状态空间
Deep Q-Network (DQN)#
使用神经网络近似Q函数:
$$ Q(s,a; \theta) \approx Q^*(s,a) $$关键技巧#
- 经验回放:存储经验,随机采样
- 目标网络:使用固定目标网络稳定训练
DQN损失#
$$ L(\theta) = \mathbb{E}\left[\left(r + \gamma \max_{a'} Q(s', a'; \theta^-) - Q(s, a; \theta)\right)^2\right] $$其中 $\theta^-$ 是目标网络参数。
策略梯度#
概述#
策略梯度 直接优化策略,而不是价值函数。
策略梯度定理#
$$ \nabla_\theta J(\theta) = \mathbb{E}[\nabla_\theta \log \pi_\theta(a|s) Q^\pi(s,a)] $$REINFORCE算法#
$$ \theta \leftarrow \theta + \alpha \nabla_\theta \log \pi_\theta(a_t|s_t) G_t $$Actor-Critic#
结合策略梯度和价值函数:
- Actor:学习策略 $\pi(a|s)$
- Critic:学习价值函数 $V(s)$ 或 $Q(s,a)$
A3C (Asynchronous Advantage Actor-Critic)#
使用优势函数:
$$ A(s,a) = Q(s,a) - V(s) $$代码实现#
Q-Learning#
import numpy as np
import random
class QLearning:
def __init__(self, states, actions, learning_rate=0.1, gamma=0.9, epsilon=0.1):
self.states = states
self.actions = actions
self.lr = learning_rate
self.gamma = gamma
self.epsilon = epsilon
self.Q = np.zeros((states, actions))
def choose_action(self, state):
if random.random() < self.epsilon:
return random.randint(0, self.actions - 1)
else:
return np.argmax(self.Q[state])
def update(self, state, action, reward, next_state):
current_q = self.Q[state, action]
max_next_q = np.max(self.Q[next_state])
new_q = current_q + self.lr * (reward + self.gamma * max_next_q - current_q)
self.Q[state, action] = new_qDQN实现#
import torch
import torch.nn as nn
import torch.optim as optim
import random
from collections import deque
class DQN(nn.Module):
def __init__(self, state_dim, action_dim):
super(DQN, self).__init__()
self.fc1 = nn.Linear(state_dim, 128)
self.fc2 = nn.Linear(128, 128)
self.fc3 = nn.Linear(128, action_dim)
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_dim, action_dim, lr=0.001, gamma=0.99, epsilon=1.0):
self.state_dim = state_dim
self.action_dim = action_dim
self.gamma = gamma
self.epsilon = epsilon
self.epsilon_min = 0.01
self.epsilon_decay = 0.995
self.q_network = DQN(state_dim, action_dim)
self.target_network = DQN(state_dim, action_dim)
self.target_network.load_state_dict(self.q_network.state_dict())
self.optimizer = optim.Adam(self.q_network.parameters(), lr=lr)
self.memory = deque(maxlen=10000)
def remember(self, state, action, reward, next_state, done):
self.memory.append((state, action, reward, next_state, done))
def act(self, state):
if random.random() <= self.epsilon:
return random.randrange(self.action_dim)
with torch.no_grad():
q_values = self.q_network(torch.FloatTensor(state))
return q_values.argmax().item()
def replay(self, batch_size=32):
if len(self.memory) < batch_size:
return
batch = random.sample(self.memory, batch_size)
states, actions, rewards, next_states, dones = zip(*batch)
states = torch.FloatTensor(states)
actions = torch.LongTensor(actions)
rewards = torch.FloatTensor(rewards)
next_states = torch.FloatTensor(next_states)
dones = torch.BoolTensor(dones)
current_q = self.q_network(states).gather(1, actions.unsqueeze(1))
next_q = self.target_network(next_states).max(1)[0].detach()
target_q = rewards + (self.gamma * next_q * ~dones)
loss = nn.MSELoss()(current_q.squeeze(), target_q)
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
if self.epsilon > self.epsilon_min:
self.epsilon *= self.epsilon_decay
def update_target_network(self):
self.target_network.load_state_dict(self.q_network.state_dict())REINFORCE实现#
class PolicyNetwork(nn.Module):
def __init__(self, state_dim, action_dim):
super(PolicyNetwork, self).__init__()
self.fc1 = nn.Linear(state_dim, 128)
self.fc2 = nn.Linear(128, 128)
self.fc3 = nn.Linear(128, action_dim)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
return torch.softmax(self.fc3(x), dim=-1)
class REINFORCE:
def __init__(self, state_dim, action_dim, lr=0.001, gamma=0.99):
self.gamma = gamma
self.policy = PolicyNetwork(state_dim, action_dim)
self.optimizer = optim.Adam(self.policy.parameters(), lr=lr)
self.episode_rewards = []
self.episode_log_probs = []
def select_action(self, state):
probs = self.policy(torch.FloatTensor(state))
dist = torch.distributions.Categorical(probs)
action = dist.sample()
log_prob = dist.log_prob(action)
return action.item(), log_prob
def store_transition(self, log_prob, reward):
self.episode_log_probs.append(log_prob)
self.episode_rewards.append(reward)
def update(self):
returns = []
G = 0
for r in reversed(self.episode_rewards):
G = r + self.gamma * G
returns.insert(0, G)
returns = torch.FloatTensor(returns)
returns = (returns - returns.mean()) / (returns.std() + 1e-9)
policy_loss = []
for log_prob, G in zip(self.episode_log_probs, returns):
policy_loss.append(-log_prob * G)
self.optimizer.zero_grad()
policy_loss = torch.stack(policy_loss).sum()
policy_loss.backward()
self.optimizer.step()
self.episode_rewards = []
self.episode_log_probs = []总结#
- 强化学习:通过交互学习最优策略
- MDP:强化学习的数学框架
- Q-Learning:值函数方法,学习Q函数
- DQN:使用神经网络近似Q函数
- 策略梯度:直接优化策略
- REINFORCE:基础的策略梯度算法
关键要点:
- 强化学习是交互式学习
- 需要平衡探索和利用
- Q-Learning学习价值函数
- 策略梯度直接优化策略
- DQN结合深度学习和Q-Learning
延伸阅读#
- 深度强化学习:DQN、A3C、PPO
- 多智能体强化学习:多智能体系统
- 模仿学习:从专家演示学习
- 元学习:快速适应新任务