第1章:强化学习问题(The Reinforcement Learning Problem)
一、导读
1.1 本章学习目标
第1章是整本《强化学习:导论》的开篇之作,它为读者建立了强化学习的基本框架和核心概念。与监督学习不同,强化学习关注的是智能体如何在与环境的交互中通过学习来做出最优决策。本章不深入数学细节,而是通过直觉和示例帮助读者理解强化学习的本质特征。
本章的核心学习目标包括:
- 理解强化学习的基本框架:智能体(agent)与环境(environment)之间的交互关系,以及状态(state)、动作(action)、奖励(reward)三要素
- 掌握强化学习与其他机器学习范式的区别:强化学习的两个核心特征——试错学习(trial-and-error)和延迟奖励(delayed reward)
- 理解奖励假说(Reward Hypothesis):所有目标都可以被描述为标量奖励信号的最大化期望
- 理解探索与利用的困境(Exploration vs. Exploitation Dilemma):智能体必须在获取新信息和利用已有知识之间做出权衡
- 了解强化学习的历史脉络:从行为心理学到现代强化学习的演进路线
- 建立策略(policy)和价值函数(value function)的初步概念:策略决定行为,价值函数评估状态的好坏
1.2 为什么第一章如此重要
强化学习是机器学习三大范式之一(监督学习、无监督学习、强化学习),也是最具"智能感"的学习方式。一个能下棋的AI、一个能自动驾驶的汽车、一个能控制机器人行走的算法,背后都是强化学习在发挥作用。
第1章的重要性在于它定义了强化学习的"语言"。就像学习一门编程语言需要先理解变量、函数、控制流等基本概念一样,学习强化学习需要先理解智能体、环境、状态、动作、奖励、策略、价值函数等核心概念。这些概念贯穿全书,后续每一章都在这个框架下展开。
更重要的是,第1章揭示了强化学习问题的独特挑战。在监督学习中,我们有明确的标签告诉模型正确答案;在强化学习中,智能体必须通过自己的尝试来发现哪些行为能带来最大的累积奖励。这种"没有老师"的学习方式,使得强化学习既强大又困难。
1.3 核心问题引导
在阅读本章时,请带着以下问题思考:
强化学习与监督学习的本质区别是什么?为什么有些问题不能用监督学习来解决?
什么是"奖励信号"?为什么我们可以假设所有目标都能用标量奖励来描述?
智能体为什么不能总是选择当前看来最优的动作?探索的代价和收益分别是什么?
策略和价值函数有什么区别?它们各自在强化学习中扮演什么角色?
强化学习与博弈论、最优控制、行为心理学有什么联系和区别?
一个复杂的任务(如下围棋)如何被分解为一系列状态-动作-奖励的序列?
二、核心概念详解
2.1 智能体与环境的交互
强化学习的核心思想可以用一个简单的交互循环来描述:智能体在时间步 $t$ 处于状态 $S_t$,执行动作 $A_t$,环境响应新的状态 $S_{t+1}$ 和奖励 $R_{t+1}$。这个过程不断重复,形成一条轨迹(trajectory):
$$S_0, A_0, R_1, S_1, A_1, R_2, S_2, A_2, R_3, \ldots$$
import numpy as np
class SimpleEnvironment:
def __init__(self, n_states=5, n_actions=2):
self.n_states = n_states
self.n_actions = n_actions
self.state = 0
def reset(self):
self.state = 0
return self.state
def step(self, action):
reward = 0
if action == 1:
reward = np.random.normal(0, 1)
self.state = (self.state + 1) % self.n_states
return self.state, reward
env = SimpleEnvironment()
state = env.reset()
for t in range(10):
action = np.random.randint(2)
next_state, reward = env.step(action)
print(f"t={t}: state={state}, action={action}, "
f"next_state={next_state}, reward={reward:.2f}")
state = next_state这个交互模型看似简单,却蕴含了丰富的内涵。状态可以是棋盘的布局、机器人的关节角度、股票市场的行情;动作可以是移动棋子、控制电机、买卖股票;奖励可以是赢棋的+1、到达目标的+100、投资收益。
关键洞察:强化学习的目标不是最大化即时奖励,而是最大化累积奖励(return)。这意味着智能体可能需要牺牲短期利益来获取长期收益。
2.2 奖励假说
奖励假说是强化学习的基石:所有目标都可以被描述为标量奖励信号的最大化期望。
这个假说看似激进,但它具有深刻的合理性。人类的行为可以被理解为追求某种"目标"——生存、繁衍、快乐、成就感。这些目标虽然复杂,但都可以被编码为某种标量信号。在人工智能中,我们人为地设计奖励信号来定义任务目标。
class RewardDesign:
def __init__(self):
self.total_reward = 0
def chess_reward(self, outcome):
if outcome == 'win':
return 1.0
elif outcome == 'lose':
return -1.0
return 0.0
def robot_walking_reward(self, forward_velocity, energy_cost):
return forward_velocity - 0.01 * energy_cost
def trading_reward(self, portfolio_value_change):
return portfolio_value_change奖励设计(reward shaping)是强化学习应用中最关键的环节之一。设计不当的奖励信号可能导致智能体学到意想不到的行为(reward hacking)。例如,如果奖励只关注速度而忽略能量消耗,机器人可能会学会翻滚而不是行走。
2.3 策略与价值函数
策略(policy) 是智能体在给定状态下的行为规则。确定性策略 $\pi(s) = a$ 直接将状态映射到动作;随机策略 $\pi(a|s)$ 给出在状态 $s$ 下选择动作 $a$ 的概率。
价值函数(value function) 评估状态(或状态-动作对)的"好坏程度"。状态价值函数 $v_\pi(s)$ 表示在策略 $\pi$ 下从状态 $s$ 出发能获得的期望回报:
$$v_\pi(s) = \mathbb{E}_\pi[G_t | S_t = s] = \mathbb{E}_\pi\left[\sum_{k=0}^{\infty} \gamma^k R_{t+k+1} \Big| S_t = s\right]$$
其中 $\gamma \in [0, 1]$ 是折扣因子(discount factor),它决定了未来奖励的当前价值。
import numpy as np
def compute_value_function(env, policy, gamma=0.99, theta=1e-6):
n_states = env.n_states
V = np.zeros(n_states)
while True:
delta = 0
for s in range(n_states):
v = V[s]
new_v = 0
for a in range(env.n_actions):
prob = policy[s][a]
if prob == 0:
continue
expected_return = 0
for next_s in range(n_states):
trans_prob = env.transition_prob(s, a, next_s)
reward = env.reward(s, a, next_s)
expected_return += trans_prob * (reward + gamma * V[next_s])
new_v += prob * expected_return
V[s] = new_v
delta = max(delta, abs(v - V[s]))
if delta < theta:
break
return V策略和价值函数的关系是:策略决定了行为方式,价值函数评估了这种行为方式的好坏。强化学习的核心目标就是找到最优策略 $\pi_*$,使得对应的价值函数最大。
2.4 探索与利用的困境
这是强化学习中最核心的矛盾之一:
- 利用(Exploitation):选择当前估计价值最高的动作,以获取最大即时收益
- 探索(Exploration):选择当前估计价值较低或未尝试过的动作,以获取更多信息
过度利用会导致智能体陷入局部最优;过度探索会浪费大量资源在低价值动作上。
class ExplorationStrategies:
def __init__(self, n_actions=3):
self.n_actions = n_actions
self.q_values = np.zeros(n_actions)
self.counts = np.zeros(n_actions)
def epsilon_greedy(self, epsilon=0.1):
if np.random.random() < epsilon:
return np.random.randint(self.n_actions)
return np.argmax(self.q_values)
def ucb(self, c=2.0, total_steps=100):
total = max(1, np.sum(self.counts))
ucb_values = self.q_values + c * np.sqrt(
np.log(total) / np.maximum(1, self.counts)
)
return np.argmax(ucb_values)
def boltzmann(self, temperature=1.0):
probs = np.exp(self.q_values / temperature)
probs /= probs.sum()
return np.random.choice(self.n_actions, p=probs)探索与利用的平衡在不同任务中有不同的最优策略。在确定性环境中,UCB(Upper Confidence Bound)方法提供了理论保证;在随机环境中,可能需要更复杂的探索策略。
2.5 强化学习的分类
强化学习算法可以从多个维度进行分类:
基于价值 vs 基于策略 vs Actor-Critic:
- 基于价值(Value-based):学习价值函数,间接得到策略(如 Q-learning)
- 基于策略(Policy-based):直接优化策略参数(如 REINFORCE)
- Actor-Critic:同时学习策略(Actor)和价值函数(Critic)
Model-based vs Model-free:
- Model-based:学习环境的状态转移模型,通过规划(planning)来决策
- Model-free:直接学习价值函数或策略,不显式建模环境
On-policy vs Off-policy:
- On-policy:从行为策略中学习,要求行为策略与目标策略一致(如 Sarsa)
- Off-policy:从不同于行为策略的数据中学习(如 Q-learning)
class RLAlgorithmTaxonomy:
def __init__(self):
self.algorithms = {
'value_based': ['Q-learning', 'DQN', 'SARSA'],
'policy_based': ['REINFORCE', 'PPO', 'TRPO'],
'actor_critic': ['A2C', 'A3C', 'SAC', 'DDPG'],
'model_based': ['Dyna-Q', 'MBPO', 'Dreamer'],
'model_free': ['Q-learning', 'REINFORCE', 'PPO'],
}
def classify(self, name):
for category, algos in self.algorithms.items():
if name in algos:
return category
return 'unknown'2.6 强化学习的历史与展望
强化学习的思想来源多元:
- 行为心理学:Thorndike 的效果律(Law of Effect)——带来满意结果的行为会被加强
- 最优控制:Bellman 的动态规划理论——通过递归分解解决多阶段决策问题
- 时间差分学习:Sutton 和 Barto 将动物学习中的时序预测误差与强化学习联系起来
- 深度学习:Mnih 等人将深度神经网络与 Q-learning 结合,催生了深度强化学习
timeline = {
1950: "Turing 提出'机器能否思考'的问题",
1954: "Minsky 构建第一个强化学习系统 SNARC",
1960: "Widrow 和 Hoff 提出 ADALINE 自适应线性元件",
1977: "Werbos 提出 Actor-Critic 架构",
1989: "Watkins 提出 Q-learning 算法",
1992: "Tesauro 的 TD-Gammon 达到世界级双陆棋水平",
2013: "DeepMind 的 DQN 在 Atari 游戏上超越人类",
2016: "AlphaGo 击败李世石,深度强化学习震惊世界",
2017: "AlphaZero 从零学习围棋、象棋、将棋并超越所有人类",
2020: "GPT-3 展示了大规模语言模型中的强化学习潜力",
}
for year, event in timeline.items():
print(f"{year}: {event}")三、实战案例
3.1 案例一:网格世界中的简单智能体
网格世界(Grid World)是强化学习中最经典的教学环境之一。智能体在一个 $n \times m$ 的网格中移动,目标是到达指定位置获取奖励。
import numpy as np
class GridWorld:
def __init__(self, width=5, height=5):
self.width = width
self.height = height
self.goal = (height - 1, width - 1)
self.state = (0, 0)
self.actions = {'up': (-1, 0), 'down': (1, 0),
'left': (0, -1), 'right': (0, 1)}
def reset(self):
self.state = (0, 0)
return self.state
def step(self, action):
dr, dc = self.actions[action]
new_r = max(0, min(self.height - 1, self.state[0] + dr))
new_c = max(0, min(self.width - 1, self.state[1] + dc))
self.state = (new_r, new_c)
if self.state == self.goal:
return self.state, 1.0, True
return self.state, -0.01, False
def state_to_index(self, state):
return state[0] * self.width + state[1]
def q_learning_gridworld(episodes=1000, alpha=0.1, gamma=0.99, epsilon=0.1):
env = GridWorld()
n_states = env.width * env.height
n_actions = len(env.actions)
Q = np.zeros((n_states, n_actions))
action_names = list(env.actions.keys())
for ep in range(episodes):
state = env.reset()
s_idx = env.state_to_index(state)
done = False
while not done:
if np.random.random() < epsilon:
a_idx = np.random.randint(n_actions)
else:
a_idx = np.argmax(Q[s_idx])
action = action_names[a_idx]
next_state, reward, done = env.step(action)
ns_idx = env.state_to_index(next_state)
Q[s_idx][a_idx] += alpha * (
reward + gamma * np.max(Q[ns_idx]) - Q[s_idx][a_idx]
)
s_idx = ns_idx
return Q, env
Q, env = q_learning_gridworld()
print("Learned Q-values shape:", Q.shape)
state = env.reset()
path = [state]
for _ in range(20):
s_idx = env.state_to_index(state)
a_idx = np.argmax(Q[s_idx])
action = list(env.actions.keys())[a_idx]
state, reward, done = env.step(action)
path.append(state)
if done:
break
print("Learned path:", path)3.2 案例二:多臂老虎机与探索策略对比
多臂老虎机(Multi-Armed Bandit)是强化学习中最简单的模型,它只有一步决策,没有状态转移。这个简化模型足以展示探索与利用的核心矛盾。
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
class MultiArmedBandit:
def __init__(self, n_arms=10, mean=0, std=1):
self.n_arms = n_arms
self.true_values = np.random.normal(mean, std, n_arms)
def pull(self, arm):
return np.random.normal(self.true_values[arm], 1)
def run_bandit_experiment(n_arms=10, n_steps=1000, n_runs=200):
strategies = {
'epsilon=0 (greedy)': 0.0,
'epsilon=0.01': 0.01,
'epsilon=0.1': 0.1,
'UCB (c=2)': 'ucb',
}
results = {}
for name, param in strategies.items():
avg_rewards = np.zeros(n_steps)
for run in range(n_runs):
bandit = MultiArmedBandit(n_arms)
Q = np.zeros(n_arms)
N = np.zeros(n_arms)
for step in range(n_steps):
if param == 'ucb':
total = max(1, np.sum(N))
ucb_vals = Q + 2 * np.sqrt(
np.log(total) / np.maximum(1, N)
)
arm = np.argmax(ucb_vals)
else:
if np.random.random() < param:
arm = np.random.randint(n_arms)
else:
arm = np.argmax(Q)
reward = bandit.pull(arm)
N[arm] += 1
Q[arm] += (reward - Q[arm]) / N[arm]
avg_rewards[step] += reward
avg_rewards /= n_runs
results[name] = avg_rewards
return results
results = run_bandit_experiment()
print("Bandit experiment completed")
for name, rewards in results.items():
print(f"{name}: final avg reward = {rewards[-1]:.3f}")3.3 案例三:倒立摆的简单控制
倒立摆(CartPole)是经典的强化学习控制任务。目标是控制小车左右移动,使杆子保持直立。
import numpy as np
class SimpleCartPole:
def __init__(self):
self.gravity = 9.8
self.mass_cart = 1.0
self.mass_pole = 0.1
self.total_mass = self.mass_cart + self.mass_pole
self.length = 0.5
self.polemass_length = self.mass_pole * self.length
self.force_mag = 10.0
self.tau = 0.02
self.theta_threshold = 12 * 2 * 3.14159 / 360
self.x_threshold = 2.4
self.reset()
def reset(self):
self.state = np.random.uniform(-0.05, 0.05, 4)
return self.state
def step(self, action):
x, x_dot, theta, theta_dot = self.state
force = self.force_mag if action == 1 else -self.force_mag
costheta = np.cos(theta)
sintheta = np.sin(theta)
temp = (force + self.polemass_length * theta_dot**2 * sintheta) / self.total_mass
thetaacc = (self.gravity * sintheta - costheta * temp) / \
(self.length * (4.0/3.0 - self.mass_pole * costheta**2 / self.total_mass))
xacc = temp - self.polemass_length * thetaacc * costheta / self.total_mass
x = x + self.tau * x_dot
x_dot = x_dot + self.tau * xacc
theta = theta + self.tau * theta_dot
theta_dot = theta_dot + self.tau * thetaacc
self.state = np.array([x, x_dot, theta, theta_dot])
done = bool(
x < -self.x_threshold or x > self.x_threshold or
theta < -self.theta_threshold or theta > self.theta_threshold
)
reward = 1.0 if not done else 0.0
return self.state, reward, done
def simple_policy(state):
x, x_dot, theta, theta_dot = state
if theta > 0:
return 0
return 1
env = SimpleCartPole()
total_reward = 0
state = env.reset()
for step in range(200):
action = simple_policy(state)
state, reward, done = env.step(action)
total_reward += reward
if done:
break
print(f"Simple policy survived {step + 1} steps, total reward: {total_reward}")四、本章小结
第1章建立了强化学习的基本框架,核心要点如下:
强化学习的本质:智能体通过与环境的交互,学习最优行为策略以最大化累积奖励。它与监督学习的根本区别在于——没有明确的标签指导,智能体必须通过试错来学习。
奖励假说:所有目标都可以被描述为标量奖励信号的最大化期望。这个假说是强化学习的理论基础,但也意味着奖励设计是应用中最关键的环节。
策略与价值函数:策略决定行为,价值函数评估行为的好坏。强化学习的目标就是找到最优策略。
探索与利用:这是强化学习永恒的主题。智能体必须在获取新信息和利用已有知识之间做出权衡,不同的探索策略适用于不同的场景。
分类体系:基于价值/策略/Actor-Critic、Model-based/Model-free、On-policy/Off-policy 构成了强化学习算法的分类框架。
本章为后续章节奠定了基础。第2章将通过多臂老虎机问题深入研究探索与利用的困境;第3章将引入马尔可夫决策过程(MDP)的数学框架;后续章节将逐步展开各种求解方法。
五、思考与练习
思考题
考虑一个自动推荐系统(如短视频推荐),它的状态、动作和奖励分别是什么?如何设计奖励函数才能让用户长期满意而不是短期上瘾?
为什么说"所有目标都可以用标量奖励描述"这个假说是有争议的?能否举出反例?
如果一个强化学习任务的折扣因子 $\gamma = 0$,智能体会表现出什么行为?$\gamma = 1$ 时呢?
在一个迷宫导航任务中,如果每走一步奖励 -1,到达终点奖励 +100,智能体可能学到什么策略?如果每走一步奖励 0 呢?
探索与利用的困境在人类生活中有哪些体现?你能想到哪些解决策略?
编程练习
实现一个随机策略智能体:在第3.1节的网格世界中,实现一个完全随机策略的智能体,统计它到达目标的平均步数,与 Q-learning 的结果对比。
多臂老虎机实验:实现 $\epsilon$-greedy 策略,分别测试 $\epsilon = 0, 0.01, 0.1, 0.5$ 的情况,绘制平均奖励曲线,分析探索率对性能的影响。
折扣因子的影响:在网格世界中,分别设置 $\gamma = 0.5, 0.9, 0.99$,观察 Q-learning 学到的策略有何不同。