这第一篇文章介绍了强化学习的基本概念。 在下一篇文章中,我们将探索基于价值的方法,如Q学习和SARSA,这些方法为智能体在更复杂的环境中学习最优策略提供了强大的技术。
更多 LLM 架构文章点击查看:
LLM 架构专栏
大模型架构专栏文章阅读指南
1. AI 智能体,颠覆还是赋能?一文读懂!
2. 1W8000字 解锁 AI 高效运作密码:工作流与智能体如何协同?
3. 万字深度剖析 AI 代理:类型、应用及优势与局限全解析
4. 1W5000字 深度剖析大模型Agent框架
5. Agent系列 1W字用Python从零搭建AI智能体
强化学习代表了我们对人工智能思考方式的深刻转变——从仅仅识别模式的系统,转变为通过交互学习并通过经验改进的智能体。正如我们将在本系列中看到的,这种范式正在推动当今一些最令人印象深刻的人工智能成就,并开辟机器学习研究的新前沿。
强化学习的基础
击败围棋世界冠军的算法可不只是按程序设定运行,它还会学习。在复杂城市环境中自动驾驶的汽车,并非遵循着明确指令,而是在不断适应。重塑我们数字体验的突破性语言模型,也不只是在静态数据上进行训练,还通过交互不断优化。
超越传统学习:强化学习范式
机器学习传统上分为两个常见类别:监督学习(从有标记的示例中学习)和无监督学习(在无标记的数据中寻找模式)。强化学习则代表了一种根本不同的方法。
在强化学习中,智能体通过与环境互动来学习,根据其采取的行动获得奖励或惩罚。这里没有预先标记的示例,也没有静态数据集,只有动态反馈引导智能体趋向最优行为。
这种范式转变反映了人类学习复杂行为的实际方式:通过试错、在反馈的引导下并受目标驱动。
强化学习的核心组件
要理解强化学习,我们需要拆解其基本组件:
- 智能体:学习者或决策者。
- 环境:智能体与之互动的系统。
- 状态:当前的情况或配置。
- 行动:智能体可以采取的行为。
- 奖励:评估行动的反馈信号。
- 策略:智能体选择行动的策略。
这些元素之间的相互作用形成了一个持续的循环:智能体观察当前状态,根据其策略采取行动,获得奖励,并转移到新的状态。这个循环不断重复,智能体不断优化其策略以最大化累积奖励。
强化学习与其他范式的区别在于探索(尝试新行动以发现其结果)和利用(利用已知的奖励)之间的关键相互作用。这种基本的矛盾——探索 - 利用困境,是强化学习独特挑战的核心。
神奇背后的数学:马尔可夫决策过程
强化学习直观吸引力的背后,是一个严谨的数学框架:马尔可夫决策过程(MDP)。MDP为在结果部分随机、部分受决策者控制的情况下进行决策建模提供了正式基础。
一个MDP由以下部分组成:
- 一组状态 $S$。
- 一组行动 $A$。
- 转移概率 $P(s’|s,a)$,定义了在采取行动 $a$ 时,从状态 $s$ 转移到状态 $s’$ 的可能性。
- 奖励函数 $R(s,a,s’)$,定义了由于行动 $a$ 从 $s$ 转移到 $s’$ 后获得的即时奖励。
- 折扣因子 $\gamma$,决定了即时奖励与未来奖励的相对重要性。
从数学角度来看,强化学习的目标是找到一个策略 $\pi$,最大化预期累积折扣奖励:
$$V^{\pi}(s) = E_{\pi}[\sum_{t=0}^{\infty}\gamma^{t}R_{t+1}|s_{0}=s]$$
其中:
- $V^{\pi}(s)$ 是价值函数,表示从状态 $s$ 开始并遵循策略 $\pi$ 时的预期回报。
- $\gamma$ 是折扣因子(介于0和1之间)。
- $R_{t+1}$ 是在第 $t$ 步之后获得的奖励。
这个框架的神奇之处在于它能够捕捉从游戏到机器人技术再到资源管理等截然不同领域的复杂顺序决策问题。
探索 - 利用困境:深入探究
也许强化学习中最引人入胜的挑战是平衡探索和利用。这不仅仅是一个技术问题,而是一个在各个领域都存在的基本困境:
- 利用:选择已知能产生高奖励的行动。
- 探索:尝试新行动,有可能发现更好的策略。
考虑一个选择餐厅的类比:你是回到一家你知道自己喜欢的餐厅(利用),还是尝试一家可能更好的新餐厅(探索)?无论选择哪一个方向出错,你要么错过发现更好餐厅的机会,要么浪费一次保证有良好体验的机会。
在强化学习中,这种困境体现在各种方法中:
- $\epsilon$-贪婪策略:以概率 $1-\epsilon$ 选择已知最好的行动,以概率 $\epsilon$ 选择随机行动。
- Softmax策略:根据行动的估计值成比例地选择行动。
- 上置信界(UCB):根据对行动潜在价值的乐观估计来选择行动。
平衡探索和利用的艺术仍然是强化学习最活跃的研究领域之一,算法不断发展以解决这一基本矛盾。
简单的老虎机问题:你的第一个强化学习实现
强化学习(RL)乍一看可能很复杂,但我们可以通过一个经典问题来开始理解它:多臂老虎机问题。让我们以一种更容易可视化和理解的方式来拆解它。
什么是多臂老虎机问题?
想象你在一家赌场,里面有多个老虎机(也叫 “臂”)。每台老虎机都有自己隐藏的给予奖励的概率。你的目标很简单:尽可能多赢钱。但有个难题——你不知道哪台机器的 payouts 比其他的更好。你需要通过试错来弄清楚。
这就产生了我们所说的 “探索与利用困境”:
- 探索:尝试不同的老虎机,了解哪台更好。
- 利用:坚持使用你目前认为最好的老虎机。
逐步理解我们的实现
让我们逐步构建解决方案:
import numpy as np
import matplotlib.pyplot as plt
class MultiArmedBandit:
def __init__(self, n_arms=10):
self.true_rewards = np.random.normal(0, 1, n_arms)
self.n_arms = n_arms
print("每台老虎机的真实奖励值(智能体未知):", self.true_rewards)
print("最优的老虎机是 #", np.argmax(self.true_rewards), ",预期奖励为",
np.max(self.true_rewards))
def pull(self, arm):
return np.random.normal(self.true_rewards[arm], 1)
class EpsilonGreedyAgent:
def __init__(self, n_arms=10, epsilon=0.1, learning_rate=0.1):
self.n_arms = n_arms
self.epsilon = epsilon
self.learning_rate = learning_rate
self.q_values = np.zeros(n_arms)
self.arm_counts = np.zeros(n_arms)
def select_action(self):
if np.random.random() < self.epsilon:
return np.random.randint(self.n_arms)
else:
return np.argmax(self.q_values)
def update(self, arm, reward):
self.arm_counts[arm] += 1
self.q_values[arm] += self.learning_rate * (reward - self.q_values[arm])
def run_bandit_experiment(n_arms=10, n_steps=1000, epsilon=0.1, learning_rate=0.1, random_seed=42):
np.random.seed(random_seed)
bandit = MultiArmedBandit(n_arms)
agent = EpsilonGreedyAgent(n_arms, epsilon=epsilon, learning_rate=learning_rate)
rewards = np.zeros(n_steps)
optimal_actions = np.zeros(n_steps)
optimal_arm = np.argmax(bandit.true_rewards)
for step in range(n_steps):
arm = agent.select_action()
optimal_actions[step] = 1 if arm == optimal_arm else 0
reward = bandit.pull(arm)
rewards[step] = reward
agent.update(arm, reward)
cumulative_average_reward = np.cumsum(rewards) / (np.arange(n_steps) + 1)
optimal_action_percentage = np.cumsum(optimal_actions) / (np.arange(n_steps) + 1)
return {
'rewards': rewards,
'cumulative_average_reward': cumulative_average_reward,
'optimal_action_percentage': optimal_action_percentage,
'agent': agent,
'bandit': bandit,
'optimal_arm': optimal_arm
}
def visualize_results(results):
plt.figure(figsize=(12, 10))
plt.subplot(2, 1, 1)
plt.plot(results['cumulative_average_reward'])
plt.xlabel('步骤')
plt.ylabel('平均奖励')
plt.title('随时间的平均奖励')
plt.grid(True, alpha=0.3)
plt.subplot(2, 1, 2)
plt.plot(results['optimal_action_percentage'])
plt.xlabel('步骤')
plt.ylabel('最优行动百分比')
plt.title('选择最优行动的频率')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print("\n最终结果:")
print(f"智能体对每台老虎机的最终价值估计: {results['agent'].q_values.round(3)}")
print(f"真实奖励值: {results['bandit'].true_rewards.round(3)}")
print(f"最优老虎机: {results['optimal_arm']}")
print(f"每台老虎机被拉动的次数: {results['agent'].arm_counts.astype(int)}")
plt.figure(figsize=(10, 5))
plt.bar(range(len(results['agent'].arm_counts)), results['agent'].arm_counts)
plt.xlabel('老虎机')
plt.ylabel('拉动次数')
plt.title('老虎机选择分布')
plt.show()
results = run_bandit_experiment(n_arms=10, n_steps=1000, epsilon=0.1)
visualize_results(results)
def compare_epsilons():
epsilons = [0.01, 0.1, 0.5]
plt.figure(figsize=(15, 6))
for i, epsilon in enumerate(epsilons):
results = run_bandit_experiment(epsilon=epsilon, random_seed=42)
plt.subplot(1, 2, 1)
plt.plot(results['cumulative_average_reward'], label=f'ε={epsilon}')
plt.subplot(1, 2, 2)
plt.plot(results['optimal_action_percentage'], label=f'ε={epsilon}')
plt.subplot(1, 2, 1)
plt.xlabel('步骤')
plt.ylabel('平均奖励')
plt.title('随时间的平均奖励')
plt.legend()
plt.grid(True, alpha=0.3)
plt.subplot(1, 2, 2)
plt.xlabel('步骤')
plt.ylabel('最优行动百分比')
plt.title('最优行动频率')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
智能体通过经验逐渐改进其奖励估计,这通过两个关键可视化得以展示:随时间的平均奖励和最优行动频率。这优雅地展示了强化学习智能体如何通过与不确定环境的直接互动发现最优策略。
拆解代码和概念
- 环境:我们的一排老虎机
在代码中,我们首先创建了MultiArmedBandit
类,它代表我们的一排老虎机。每台老虎机都有一个智能体不知道的隐藏 “真实奖励” 值。
class MultiArmedBandit:
def __init__(self, n_arms=10):
self.true_rewards = np.random.normal(0, 1, n_arms)
self.n_arms = n_arms
想象每台老虎机都有自己的 “个性”:有些很慷慨(正奖励值),有些很吝啬(负奖励值)。我们使用正态分布,所以大多数老虎机是中等水平,有少数非常好或非常差的。当我们拉动拉杆(臂)时,我们根据那台机器的真实值加上一些随机噪声获得奖励:
def pull(self, arm):
return np.random.normal(self.true_rewards[arm], 1)
噪声使学习变得更困难——仅仅因为一台机器一次支付丰厚并不意味着它实际上是整体最好的机器!
2. 智能体:我们的赌场玩家
EpsilonGreedyAgent
类代表试图最大化奖励的玩家:
class EpsilonGreedyAgent:
def __init__(self, n_arms=10, epsilon=0.1, learning_rate=0.1):
self.epsilon = epsilon
self.q_values = np.zeros(n_arms)
智能体一开始一无所知(所有估计值为零),必须通过试错学习。关键参数是 $\epsilon$,它控制智能体探索与利用的频率:
def select_action(self):
if np.random.random() < self.epsilon:
return np.random.randint(self.n_arms)
else:
return np.argmax(self.q_values)
每次拉动后,智能体更新其对该臂价值的估计:
def update(self, arm, reward):
self.arm_counts[arm] += 1
self.q_values[arm] += self.learning_rate * (reward - self.q_values[arm])
这个更新规则是许多强化学习算法使用的简化版本。它的意思是:“根据新信息的方向稍微调整你的估计。”
3. 实验:随时间学习
主要实验运行许多步骤,智能体选择臂、接收奖励并更新其知识:
for step in range(n_steps):
arm = agent.select_action()
reward = bandit.pull(arm)
agent.update(arm, reward)
我们跟踪:
- 每一步收到的奖励。
- 智能体是否选择了最优臂(真实奖励最高的臂)。
- 结果:我们学到了什么?
智能体通过试错逐渐了解哪些臂更好。我们用两个关键图可视化这个学习过程:
- 随时间的平均奖励:显示智能体在学习过程中是否获得了更好的奖励。
- 最优行动百分比:显示智能体选择真正最佳臂的频率。
核心强化学习循环
这个简单的例子展示了强化学习的基本循环:
- 观察:智能体观察当前状态(在这种情况下,只知道有哪些臂可用)。
- 行动:智能体选择一个行动(拉哪条臂)。
- 接收奖励:环境给出反馈(拉臂获得的奖励)。
- 学习:智能体更新其对世界的理解。
超越老虎机:构建实际应用
虽然多臂老虎机提供了一个易于理解的切入点,但现实世界的强化学习应用要处理复杂得多的场景:庞大的状态空间、延迟的奖励和部分可观测的环境。
想想DeepMind的AlphaGo:状态空间包括所有可能的围棋棋盘配置(比可观测宇宙中的原子数量还多)。奖励严重延迟(只有在游戏结束时才收到)。早期行动与最终结果之间的联系极其复杂。
然而基本原理仍然相同:智能体与环境互动,接收奖励,并学习一种策略以最大化累积奖励。
挑战与局限
尽管强化学习在概念上很优雅,但它面临着重大挑战:
- 样本效率:强化学习算法通常需要与环境进行大量交互才能有效学习。
- 稳定性:学习过程可能不稳定,超参数的微小变化可能导致截然不同的结果。
- 奖励设计:设计真正捕捉所需行为的奖励函数出奇地困难。
- 泛化能力:智能体通常难以将在一个环境中学到的知识转移到另一个环境中。
这些挑战代表了活跃的研究前沿,最近基于模型的方法、离策略学习和分层强化学习的进展解决了许多这些局限性。
推荐阅读
1. DeepSeek-R1的顿悟时刻是如何出现的? 背后的数学原理
2. 微调 DeepSeek LLM:使用监督微调(SFT)与 Hugging Face 数据
3. 使用 DeepSeek-R1 等推理模型将 RAG 转换为 RAT
4. DeepSeek R1:了解GRPO和多阶段训练
5. 深度探索:DeepSeek-R1 如何从零开始训练
6. DeepSeek 发布 Janus Pro 7B 多模态模型,免费又强大!
评论