吴恩达机器学习课程(PyTorch 适配)学习笔记:3.4 强化学习
3.4 强化学习
3.4.1 强化学习概述(定义 + 火星探测器示例 + MDP基础)
强化学习的核心定义
强化学习(Reinforcement Learning, RL)是一种智能体(Agent)通过与环境(Environment)交互试错,学习最优行为策略的机器学习范式。其核心区别于监督/无监督学习:
- 无监督学习:无标签,目标是发现数据结构;
- 监督学习:有明确标签,目标是学习输入到标签的映射;
- 强化学习:无直接标签,但有奖励信号(Reward),目标是通过最大化累积奖励学习“做什么”(动作选择)。
强化学习的本质是“延迟奖励下的序列决策问题”——智能体当前的动作不仅影响即时奖励,更会影响未来的状态和长期奖励,例如下棋时每一步的落子都需考虑后续多步的胜负。
火星探测器:强化学习实例
以“火星探测器自主探索资源”为例,直观理解强化学习的交互逻辑:
任务场景
火星探测器(Agent)需要在未知火星表面(Environment)探索:
- 目标:寻找水资源和能源(最大化长期奖励);
- 约束:能源有限(动作消耗能源,能源耗尽任务失败)、地形复杂(部分区域无法通行);
- 交互:探测器每一步可选择“前进/后退/左转/右转”(动作),环境会返回新的位置(状态)和奖励(如找到水资源+100,消耗能源-1,掉入沟壑-50)。
学习过程
- 初始阶段:探测器随机选择动作(如误打误撞进入沟壑,获得-50奖励);
- 学习阶段:通过记录“状态-动作-奖励-下一状态”的经验,逐渐发现“靠近绿色区域(水资源)的动作能获得高奖励”;
- 最优阶段:最终学会“优先向水资源方向移动,避开沟壑,最小化能源消耗”的策略。
强化学习的数学基础:马尔可夫决策过程(MDP)
几乎所有强化学习问题都可建模为马尔可夫决策过程(Markov Decision Process, MDP),其核心是“状态的马尔可夫性”——未来状态仅依赖于当前状态,与历史状态无关,数学表示为:
P(st+1∣st,at)=P(st+1∣s0,a0,...,st,at)P(s_{t+1} | s_t, a_t) = P(s_{t+1} | s_0,a_0,...,s_t,a_t)P(st+1∣st,at)=P(st+1∣s0,a0,...,st,at)
MDP由5元组(S,A,P,R,γ)(\mathcal{S}, \mathcal{A}, P, R, \gamma)(S,A,P,R,γ)定义:
- S\mathcal{S}S:状态空间(如探测器的所有可能位置+能源值);
- A\mathcal{A}A:动作空间(如4个移动方向);
- PPP:状态转移概率(P(s′∣s,a)P(s'|s,a)P(s′∣s,a)表示在状态sss执行动作aaa后,转移到s′s's′的概率);
- RRR:奖励函数(R(s,a,s′)R(s,a,s')R(s,a,s′)表示从sss执行aaa到s′s's′获得的即时奖励);
- γ\gammaγ:折扣因子(0≤γ≤10 \leq \gamma \leq 10≤γ≤1,用于权衡即时奖励和未来奖励,γ=0\gamma=0γ=0只关注当下,γ=1\gamma=1γ=1同等重视未来)。
3.4.2 强化学习核心概念(回报 + 策略 + 价值函数)
强化学习的核心概念围绕“如何量化动作的好坏”和“如何选择最优动作”展开,是理解后续算法的基础。
1. 回报(Return):长期奖励的累积
回报GtG_tGt定义为从时刻ttt开始的累积折扣奖励,是强化学习的“目标函数”,数学表示为:
Gt=rt+1+γrt+2+γ2rt+3+...=∑k=0∞γkrt+k+1G_t = r_{t+1} + \gamma r_{t+2} + \gamma^2 r_{t+3} + ... = \sum_{k=0}^{\infty} \gamma^k r_{t+k+1}Gt=rt+1+γrt+2+γ2rt+3+...=k=0∑∞γkrt+k+1
- 折扣因子γ\gammaγ的意义:
- γ=0\gamma=0γ=0:仅关注即时奖励(短视行为,如探测器只在乎当前步是否耗能);
- γ=1\gamma=1γ=1:未来奖励与即时奖励同等重要(长期规划,如探测器愿意消耗当前能源寻找远处的水资源);
- 实际应用中γ\gammaγ通常取0.9~0.99,既重视长期目标,又避免无限期累积导致的计算问题。
2. 策略(Policy):状态到动作的映射
策略π(a∣s)\pi(a|s)π(a∣s)是智能体的“行为准则”,表示在状态sss下选择动作aaa的概率分布:
- 确定性策略:π(s)=a\pi(s) = aπ(s)=a(给定sss时,确定选择动作aaa,如“在状态sss必须前进”);
- 随机性策略:π(a∣s)=p\pi(a|s) = pπ(a∣s)=p(给定sss时,以概率ppp选择动作aaa,如“在状态sss有80%概率前进,20%概率左转”)。
强化学习的核心目标是学习最优策略π∗\pi^*π∗,使得从任意初始状态sss出发的期望回报最大:
π∗=argmaxπE[Gt∣st=s,π]\pi^* = \arg\max_{\pi} \mathbb{E}[G_t | s_t = s, \pi]π∗=argπmaxE[Gt∣st=s,π]
3. 价值函数:量化状态/动作的“好坏”
价值函数是评估“状态有多好”或“在状态sss下选择动作aaa有多好”的工具,分为状态值函数和动作值函数两类。
(1)状态值函数Vπ(s)V^\pi(s)Vπ(s)
定义:在策略π\piπ下,从状态sss出发的期望回报,表示“遵循策略π\piπ时,状态sss的长期价值”:
Vπ(s)=Eπ[Gt∣st=s]V^\pi(s) = \mathbb{E}_\pi[G_t | s_t = s]Vπ(s)=Eπ[Gt∣st=s]
(2)动作值函数Qπ(s,a)Q^\pi(s,a)Qπ(s,a)
定义:在策略π\piπ下,从状态sss出发选择动作aaa后,再遵循策略π\piπ的期望回报,表示“在状态sss选择动作aaa的长期价值”:
Qπ(s,a)=Eπ[Gt∣st=s,at=a]Q^\pi(s,a) = \mathbb{E}_\pi[G_t | s_t = s, a_t = a]Qπ(s,a)=Eπ[Gt∣st=s,at=a]
两者关系
动作值函数是状态值函数的细化——Vπ(s)V^\pi(s)Vπ(s)是对状态sss的整体评估,Qπ(s,a)Q^\pi(s,a)Qπ(s,a)是对“状态sss+动作aaa”组合的评估,数学上满足:
Vπ(s)=∑a∈Aπ(a∣s)Qπ(s,a)V^\pi(s) = \sum_{a \in \mathcal{A}} \pi(a|s) Q^\pi(s,a)Vπ(s)=a∈A∑π(a∣s)Qπ(s,a)
(状态sss的价值 = 所有可能动作的价值按选择概率加权求和)
最优价值函数
当策略为最优策略π∗\pi^*π∗时,对应的价值函数称为最优价值函数:
- 最优状态值函数:V∗(s)=maxπVπ(s)V^*(s) = \max_{\pi} V^\pi(s)V∗(s)=maxπVπ(s)(状态sss的最大可能价值);
- 最优动作值函数:Q∗(s,a)=maxπQπ(s,a)Q^*(s,a) = \max_{\pi} Q^\pi(s,a)Q∗(s,a)=maxπQπ(s,a)(“状态sss+动作aaa”的最大可能价值)。
最优动作值函数是强化学习的“金钥匙”——若已知Q∗(s,a)Q^*(s,a)Q∗(s,a),最优策略可直接通过“贪心选择”得到:
π∗(a∣s)={1if a=argmaxa′∈AQ∗(s,a′)0otherwise\pi^*(a|s) = \begin{cases} 1 & \text{if } a = \arg\max_{a' \in \mathcal{A}} Q^*(s,a') \\ 0 & \text{otherwise} \end{cases}π∗(a∣s)={10if a=argmaxa′∈AQ∗(s,a′)otherwise
(在状态sss下,选择Q∗(s,a)Q^*(s,a)Q∗(s,a)最大的动作aaa)
4. 探索与利用(Exploration vs. Exploitation)
强化学习的核心矛盾:
- 利用(Exploitation):选择当前已知价值最高的动作(如探测器一直走已发现的安全路线);
- 探索(Exploration):尝试未选择过的动作(如探测器尝试新路线,可能发现更多资源,但也可能掉入沟壑)。
常见平衡策略
- ε-贪心(ε-Greedy):以概率1−ε1-\varepsilon1−ε选择当前最优动作(利用),以概率ε\varepsilonε随机选择动作(探索);ε\varepsilonε通常随训练推进逐渐减小(初期多探索,后期多利用)。
- Upper Confidence Bound(UCB):选择“价值估计 + 不确定性惩罚”最大的动作,既利用已知信息,又优先探索不确定性高的动作。
3.4.3 贝尔曼方程(原理 + 推导 + 应用)
贝尔曼方程(Bellman Equation)是强化学习的“数学核心”,将价值函数分解为“即时奖励”和“未来价值的折扣”,为价值函数的计算和学习提供了递归框架。
贝尔曼方程的核心思想
基于马尔可夫性,“当前状态的价值”等于“即时奖励”加上“下一状态价值的折扣期望”,即:
当前价值=即时奖励+γ×未来价值的期望\text{当前价值} = \text{即时奖励} + \gamma \times \text{未来价值的期望}当前价值=即时奖励+γ×未来价值的期望
这一思想贯穿所有强化学习算法——无论是动态规划(DP)、时序差分(TD)还是Q学习,本质都是通过贝尔曼方程更新价值函数。
1. 状态值函数的贝尔曼方程
推导过程
根据状态值函数Vπ(s)V^\pi(s)Vπ(s)的定义(从sss出发的期望回报),结合回报GtG_tGt的递归结构:
Gt=rt+1+γGt+1G_t = r_{t+1} + \gamma G_{t+1}Gt=rt+1+γGt+1
对两边取期望(条件为当前状态st=ss_t = sst=s和策略π\piπ):
Eπ[Gt∣st=s]=Eπ[rt+1+γGt+1∣st=s]\mathbb{E}_\pi[G_t | s_t = s] = \mathbb{E}_\pi[r_{t+1} + \gamma G_{t+1} | s_t = s]Eπ[Gt∣st=s]=Eπ[rt+1+γGt+1∣st=s]
左边即Vπ(s)V^\pi(s)Vπ(s),右边拆分期望(期望的线性性质):
Vπ(s)=Eπ[rt+1∣st=s]+γEπ[Gt+1∣st=s]V^\pi(s) = \mathbb{E}_\pi[r_{t+1} | s_t = s] + \gamma \mathbb{E}_\pi[G_{t+1} | s_t = s]Vπ(s)=Eπ[rt+1∣st=s]+γEπ[Gt+1∣st=s]
再根据马尔可夫性,Eπ[Gt+1∣st=s]=Eπ[Vπ(st+1)∣st=s]\mathbb{E}_\pi[G_{t+1} | s_t = s] = \mathbb{E}_\pi[V^\pi(s_{t+1}) | s_t = s]Eπ[Gt+1∣st=s]=Eπ[Vπ(st+1)∣st=s](下一时刻的期望回报即下一状态的状态值函数),最终得到:
Vπ(s)=∑a∈Aπ(a∣s)[∑s′∈SP(s′∣s,a)(R(s,a,s′)+γVπ(s′))]V^\pi(s) = \sum_{a \in \mathcal{A}} \pi(a|s) \left[ \sum_{s' \in \mathcal{S}} P(s'|s,a) \left( R(s,a,s') + \gamma V^\pi(s') \right) \right]Vπ(s)=a∈A∑π(a∣s)[s′∈S∑P(s′∣s,a)(R(s,a,s′)+γVπ(s′))]
2. 动作值函数的贝尔曼方程
类似地,动作值函数Qπ(s,a)Q^\pi(s,a)Qπ(s,a)的贝尔曼方程为:
Qπ(s,a)=∑s′∈SP(s′∣s,a)(R(s,a,s′)+γ∑a′∈Aπ(a′∣s′)Qπ(s′,a′))Q^\pi(s,a) = \sum_{s' \in \mathcal{S}} P(s'|s,a) \left( R(s,a,s') + \gamma \sum_{a' \in \mathcal{A}} \pi(a'|s') Q^\pi(s',a') \right)Qπ(s,a)=s′∈S∑P(s′∣s,a)(R(s,a,s′)+γa′∈A∑π(a′∣s′)Qπ(s′,a′))
最优贝尔曼方程
当策略为最优策略π∗\pi^*π∗时,贝尔曼方程简化为“最优价值函数的递归关系”:
- 最优状态值函数:V∗(s)=maxa∈A∑s′∈SP(s′∣s,a)(R(s,a,s′)+γV∗(s′))V^*(s) = \max_{a \in \mathcal{A}} \sum_{s' \in \mathcal{S}} P(s'|s,a) \left( R(s,a,s') + \gamma V^*(s') \right)V∗(s)=maxa∈A∑s′∈SP(s′∣s,a)(R(s,a,s′)+γV∗(s′))
- 最优动作值函数:Q∗(s,a)=∑s′∈SP(s′∣s,a)(R(s,a,s′)+γmaxa′∈AQ∗(s′,a′))Q^*(s,a) = \sum_{s' \in \mathcal{S}} P(s'|s,a) \left( R(s,a,s') + \gamma \max_{a' \in \mathcal{A}} Q^*(s',a') \right)Q∗(s,a)=∑s′∈SP(s′∣s,a)(R(s,a,s′)+γmaxa′∈AQ∗(s′,a′))
最优贝尔曼方程的关键是“max\maxmax”——最优价值是“选择当前最优动作”后的最大期望回报,这也是贪心策略的数学依据。
贝尔曼方程的应用场景
- 动态规划(DP)算法:如策略迭代(Policy Iteration)和价值迭代(Value Iteration),直接利用贝尔曼方程进行价值函数的迭代更新;
- 时序差分(TD)学习:如TD(0)、SARSA,用“实际经验中的即时奖励 + 下一状态的价值估计”替代贝尔曼方程中的期望,实现无模型(Model-Free)学习;
- Q学习:基于最优贝尔曼方程,通过Q(s,a)←Q(s,a)+α[r+γmaxa′Q(s′,a′)−Q(s,a)]Q(s,a) \leftarrow Q(s,a) + \alpha [r + \gamma \max_{a'} Q(s',a') - Q(s,a)]Q(s,a)←Q(s,a)+α[r+γmaxa′Q(s′,a′)−Q(s,a)]更新动作值函数,学习最优策略。
3.4.4 环境建模(随机环境 + 连续状态空间 + 实战示例)
环境是强化学习的“交互对象”,环境建模的准确性直接决定算法效果。实际场景中,环境通常具有随机性和连续状态空间两大特征,需针对性处理。
1. 随机环境建模:状态转移概率P(s′∣s,a)P(s'|s,a)P(s′∣s,a)
随机环境的核心特征
- 动作的结果不确定:例如“在 windy gridworld( windy网格世界)中,执行‘前进’动作可能因风的影响,实际向右偏移”;
- 需用概率描述转移:P(s′∣s,a)P(s'|s,a)P(s′∣s,a)表示“状态sss执行动作aaa后转移到s′s's′的概率”,所有s′s's′的概率和为1。
示例:Windy Gridworld 环境
网格世界 | 转移规则 |
---|---|
5×10网格,起点(3,0),终点(3,7) | 除列3-5外,执行“上/下/左/右”动作后,位置按动作移动; 列3-5有“向上的风”,执行任意动作后额外向上移动1格(如在(3,3)执行“右”,先到(3,4),再被风吹到(2,4)); 边界处理:若移动后超出网格,位置不变。 |
转移概率建模代码(简化版)
import numpy as npclass WindyGridworld:def __init__(self, width=10, height=5, start=(3,0), goal=(3,7)):self.width = widthself.height = heightself.start = start # 起点状态self.goal = goal # 终点状态self.wind = [0, 0, 0, 1, 1, 1, 2, 2, 1, 0] # 每列的风力(向上为正)self.actions = [(-1,0), (1,0), (0,-1), (0,1)] # 上、下、左、右self.action_names = ["上", "下", "左", "右"]def reset(self):"""重置环境到起点状态"""self.current_state = self.startreturn self.current_statedef step(self, action_idx):"""执行动作,返回(next_state, reward, done)action_idx: 动作索引(0-3对应上/下/左/右)"""# 1. 获取动作方向dx, dy = self.actions[action_idx]x, y = self.current_state# 2. 计算基础移动(动作+风力)new_x = x + dx - self.wind[y] # 风力向上(x减小方向)new_y = y + dy# 3. 边界约束(超出网格则位置不变)new_x = max(0, min(new_x, self.height-1))new_y = max(0, min(new_y, self.width-1))next_state = (new_x, new_y)# 4. 计算奖励与终止状态done = (next_state == self.goal)reward = 0 if done else -1 # 到达终点+0,否则-1(鼓励快速到达)# 5. 更新当前状态self.current_state = next_statereturn next_state, reward, donedef get_transition_prob(self, s, a, s_prime):"""计算状态转移概率P(s'|s,a)"""x, y = sdx, dy = self.actions[a]wind = self.wind[y]# 计算理论上的next_state(无随机性时)expected_x = x + dx - windexpected_y = y + dyexpected_x = max(0, min(expected_x, self.height-1))expected_y = max(0, min(expected_y, self.width-1))expected_s = (expected_x, expected_y)# 本环境无额外随机性,转移概率为1或0return 1.0 if s_prime == expected_s else 0.0# 环境测试
env = WindyGridworld()
state = env.reset()
print(f"初始状态: {state}")# 执行5步动作
for i in range(5):action_idx = np.random.choice(4) # 随机选动作next_state, reward, done = env.step(action_idx)print(f"动作: {env.action_names[action_idx]}, 下一状态: {next_state}, 奖励: {reward}, 终止: {done}")
2. 连续状态空间处理
实际场景中,状态空间常为连续的(如机器人的位置(x,y,z)(x,y,z)(x,y,z)、速度vx,vy,vzv_x,v_y,v_zvx,vy,vz),无法像离散空间那样枚举所有状态,需通过以下方法处理:
方法1:状态离散化(Discretization)
将连续状态划分为有限个离散区间(如将x∈[0,10]x \in [0,10]x∈[0,10]划分为10个区间[0,1),[1,2),...,[9,10][0,1), [1,2), ..., [9,10][0,1),[1,2),...,[9,10]),转化为离散状态空间。
- 优点:简单直接,可复用离散空间算法;
- 缺点:精度损失(区间划分越粗,精度越差)、维度灾难(状态维度增加时,离散区间数指数增长)。
方法2:函数近似(Function Approximation)
用参数化函数(如神经网络)近似价值函数V(s;θ)V(s;\theta)V(s;θ)或Q(s,a;θ)Q(s,a;\theta)Q(s,a;θ),其中θ\thetaθ是函数参数(如神经网络权重)。
- 核心思想:不存储每个状态的价值,而是学习“状态→价值”的映射函数;
- 常用模型:
- 线性模型:V(s;θ)=θTϕ(s)V(s;\theta) = \theta^T \phi(s)V(s;θ)=θTϕ(s)(ϕ(s)\phi(s)ϕ(s)是状态sss的特征向量);
- 非线性模型:深度神经网络(如CNN处理图像状态,MLP处理低维连续状态);
- 优点:泛化能力强,可处理高维连续状态;
- 注意事项:需避免过拟合(如加入正则化、经验回放)。
示例:连续状态空间的函数近似(PyTorch)
以“CartPole(倒立摆)”环境为例,用MLP近似状态值函数V(s;θ)V(s;\theta)V(s;θ):
import torch
import torch.nn as nn
import gym # OpenAI Gym提供经典强化学习环境# 1. 定义价值函数网络(MLP近似V(s;θ))
class ValueNetwork(nn.Module):def __init__(self, state_dim, hidden_dim=[64, 64]):super().__init__()# 状态维度:CartPole的状态是4维(小车位置、速度,摆角、角速度)layers = []input_dim = state_dimfor dim in hidden_dim:layers.append(nn.Linear(input_dim, dim))layers.append(nn.ReLU())input_dim = dimlayers.append(nn.Linear(input_dim, 1)) # 输出状态值V(s)self.net = nn.Sequential(*layers)def forward(self, s):"""输入状态s(batch_size × state_dim),输出价值V(s)"""return self.net(s)# 2. 环境初始化(CartPole是连续状态、离散动作的环境)
env = gym.make('CartPole-v1')
state_dim = env.observation_space.shape[0] # 4维状态
print(f"CartPole状态维度: {state_dim}")# 3. 价值网络初始化
value_net = ValueNetwork(state_dim=state_dim)
print(value_net)# 4. 测试:对随机状态计算价值
random_state = torch.randn(1, state_dim) # 随机生成1个状态
state_value = value_net(random_state)
print(f"随机状态的价值估计: {state_value.item():.4f}")
3. 环境建模的常见问题与应对
问题 | 描述 | 应对策略 |
---|---|---|
模型不确定性 | 环境转移概率PPP或奖励RRR未知或难以精确建模 | 采用无模型(Model-Free)算法(如Q学习、SARSA),直接从经验学习 |
部分可观测性 | 智能体无法获取完整状态(如机器人摄像头视野有限) | 建模为部分可观测马尔可夫决策过程(POMDP),用递归神经网络(RNN)处理历史信息 |
环境动态变化 | 环境参数随时间变化(如火星表面风速变化) | 采用自适应算法(如动态Q学习),定期更新环境模型或价值函数 |
3.4.5 状态值函数学习(方法分类 + PyTorch实现框架)
状态值函数V(s)V(s)V(s)的学习是强化学习的基础,根据是否依赖环境模型(即是否已知PPP和RRR),可分为有模型学习(Model-Based) 和无模型学习(Model-Free) 两类。
1. 状态值函数学习方法分类
类别 | 代表算法 | 核心思想 | 优点 | 缺点 |
---|---|---|---|---|
有模型学习 | 动态规划(DP)- 价值迭代 | 已知PPP和RRR,用贝尔曼方程迭代更新V(s)V(s)V(s) | 收敛稳定,理论保证 | 依赖环境模型,实际场景中PPP和RRR难获取 |
无模型学习 | 蒙特卡洛(MC)学习 | 无PPP和RRR,通过完整 episode(从开始到终止)的回报计算V(s)V(s)V(s) | 无模型,不依赖环境假设 | 需等待 episode 结束才能更新,方差大 |
无模型学习 | 时序差分(TD)学习 | 无PPP和RRR,用“即时奖励 + 下一状态价值估计”更新V(s)V(s)V(s) | 无模型,无需等待 episode 结束,方差小 | 存在偏差(因用估计值更新估计值) |
时序差分(TD)学习:最常用的无模型方法
TD学习结合了MC的无模型优势和DP的迭代更新思想,核心更新公式(以TD(0)为例):
V(st)←V(st)+α[rt+1+γV(st+1)−V(st)]V(s_t) \leftarrow V(s_t) + \alpha \left[ r_{t+1} + \gamma V(s_{t+1}) - V(s_t) \right]V(st)←V(st)+α[rt+1+γV(st+1)−V(st)]
其中:
- α\alphaα:学习率(0<α≤10 < \alpha \leq 10<α≤1),控制每次更新的幅度;
- rt+1+γV(st+1)−V(st)r_{t+1} + \gamma V(s_{t+1}) - V(s_t)rt+1+γV(st+1)−V(st):TD误差(TD Error),衡量当前价值估计与实际经验的差距。
2. 时序差分(TD(0))学习PyTorch实现框架
以“CartPole-v1”环境为例,用MLP近似状态值函数V(s;θ)V(s;\theta)V(s;θ),实现TD(0)学习:
import torch
import torch.nn as nn
import torch.optim as optim
import gym
import numpy as np
import matplotlib.pyplot as plt# 1. 价值网络(MLP近似V(s;θ))
class ValueNetwork(nn.Module):def __init__(self, state_dim, hidden_dim=[64, 64]):super().__init__()self.net = nn.Sequential(nn.Linear(state_dim, hidden_dim[0]),nn.ReLU(),nn.Linear(hidden_dim[0], hidden_dim[1]),nn.ReLU(),nn.Linear(hidden_dim[1], 1) # 输出V(s))def forward(self, s):return self.net(s)# 2. TD(0)学习器
class TD0Learner:def __init__(self, env, value_net, gamma=0.99, alpha=0.001):self.env = envself.value_net = value_net # 价值网络self.gamma = gamma # 折扣因子self.alpha = alpha # 学习率self.optimizer = optim.Adam(value_net.parameters(), lr=alpha)self.loss_fn = nn.MSELoss() # TD误差用MSE损失self.train_losses = [] # 记录训练损失self.episode_rewards = [] # 记录每轮episode的总奖励def select_action(self, s, epsilon=0.1):"""ε-贪心选择动作(CartPole有2个动作:0=左移,1=右移)"""if np.random.random() < epsilon:return np.random.choice(2) # 探索:随机选动作else:# 利用:选择使Q(s,a)最大的动作(此处简化为随机,实际需Q网络)# 注:TD(0)本身是价值学习,动作选择需额外策略,这里用ε-贪心return np.random.choice(2)def train_episode(self, epsilon=0.1):"""训练一个episode"""state, _ = self.env.reset() # 重置环境,获取初始状态state = torch.tensor(state, dtype=torch.float32).unsqueeze(0) # (1, state_dim)total_reward = 0done = Falsewhile not done:# 1. 选择动作并执行action = self.select_action(state, epsilon)next_state, reward, done, _, _ = self.env.step(action)next_state = torch.tensor(next_state, dtype=torch.float32).unsqueeze(0)reward = torch.tensor(reward, dtype=torch.float32).unsqueeze(0)total_reward += reward.item()# 2. 计算TD目标和TD误差with torch.no_grad():# TD目标:r + γ*V(s')(下一状态价值用当前网络估计,无梯度)td_target = reward + self.gamma * self.value_net(next_state)# 当前状态价值估计td_estimate = self.value_net(state)# TD误差损失(MSE(td_estimate, td_target))loss = self.loss_fn(td_estimate, td_target)# 3. 反向传播更新价值网络self.optimizer.zero_grad()loss.backward()self.optimizer.step()# 4. 更新状态state = next_state# 记录损失和奖励self.train_losses.append(loss.item())self.episode_rewards.append(total_reward)return total_rewarddef train(self, num_episodes=1000, epsilon_decay=0.995):"""训练num_episodes轮,ε随训练衰减"""epsilon = 0.5 # 初始探索概率for episode in range(num_episodes):# 训练一轮total_reward = self.train_episode(epsilon)# 衰减εepsilon = max(0.01, epsilon * epsilon_decay)# 每100轮打印进度if (episode + 1) % 100 == 0:avg_reward = np.mean(self.episode_rewards[-100:])avg_loss = np.mean(self.train_losses[-100:])print(f"Episode {episode+1}/{num_episodes} | 平均奖励: {avg_reward:.2f} | 平均损失: {avg_loss:.4f} | ε: {epsilon:.3f}")# 绘制训练曲线self.plot_training_curves()def plot_training_curves(self):"""绘制损失和奖励曲线"""fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))# 奖励曲线(平滑处理,取10轮平均)smoothed_rewards = np.convolve(self.episode_rewards, np.ones(10)/10, mode='valid')ax1.plot(range(len(smoothed_rewards)), smoothed_rewards, 'b-')ax1.set_xlabel('Episode')ax1.set_ylabel('平均奖励(10轮平滑)')ax1.set_title('TD(0)训练奖励曲线')ax1.grid(True, alpha=0.3)# 损失曲线(平滑处理)smoothed_losses = np.convolve(self.train_losses, np.ones(10)/10, mode='valid')ax2.plot(range(len(smoothed_losses)), smoothed_losses, 'r-')ax2.set_xlabel('Step')ax2.set_ylabel('TD误差损失(10步平滑)')ax2.set_title('TD(0)训练损失曲线')ax2.grid(True, alpha=0.3)plt.tight_layout()plt.show()# 3. 训练入口
if __name__ == "__main__":# 初始化环境和网络env = gym.make('CartPole-v1')state_dim = env.observation_space.shape[0]value_net = ValueNetwork(state_dim=state_dim, hidden_dim=[64, 64])# 初始化学习器并训练learner = TD0Learner(env=env,value_net=value_net,gamma=0.99,alpha=0.001)learner.train(num_episodes=1000)# 测试:评估训练后的价值网络print("\n测试:随机状态的价值估计")for _ in range(5):test_state = torch.randn(1, state_dim)test_value = value_net(test_state).item()print(f"状态: {test_state.squeeze().detach().numpy().round(2)}, 价值估计: {test_value:.4f}")
3. 关键实现细节与注意事项
(1)价值网络的输入处理
- 连续状态需转换为张量,并确保维度匹配(如
(batch_size, state_dim)
); - 状态标准化:若状态各维度量级差异大(如位置范围[0,10][0,10][0,10],速度范围[−100,100][-100,100][−100,100]),需先标准化(如Z-score),避免网络训练不稳定。
(2)TD目标的计算
- 用
torch.no_grad()
包裹下一状态价值的计算,避免反向传播时更新“目标侧”的梯度; - 若使用“目标网络”(如DQN中的目标Q网络),可进一步降低训练方差,具体做法是:
- 维护一个与主网络结构相同的目标网络;
- TD目标用目标网络计算:
td_target = reward + gamma * target_value_net(next_state)
; - 定期(如每100步)将主网络权重复制到目标网络。
(3)学习率与ε的调度
- 学习率α\alphaα:初期可设为0.001~0.01,后期逐渐减小(如用
torch.optim.lr_scheduler
); - 探索概率ε\varepsilonε:初期多探索(ε=0.5\varepsilon=0.5ε=0.5),后期多利用(ε\varepsilonε衰减到0.01~0.05),避免陷入局部最优。
(4)训练稳定性保障
- 经验回放(Experience Replay):存储“状态-动作-奖励-下一状态”的经验,随机采样批次更新,减少样本相关性;
- 梯度裁剪:若训练中梯度爆炸,用
torch.nn.utils.clip_grad_norm_(value_net.parameters(), max_norm=1.0)
限制梯度范数。
3.4.6 强化学习算法改进思路(从基础到进阶)
基础强化学习算法(如Q学习、TD学习)在复杂场景(如连续动作、高维状态、稀疏奖励)中存在局限性,需针对性改进。以下是核心改进方向及典型算法。
1. 价值学习的改进:从Q学习到深度Q网络(DQN)
问题:传统Q学习的局限性
- 无法处理高维状态(如图像输入);
- 样本相关性导致训练不稳定(相邻step的样本高度相关)。
改进方案:DQN及其变体
- 核心改进1:用深度神经网络近似Q(s,a):
- 输入:高维状态(如Atari游戏的图像);
- 输出:每个动作的Q值(如4个动作输出4个Q值)。
- 核心改进2:经验回放(Experience Replay):
- 存储经验到回放缓冲区(Replay Buffer);
- 随机采样批次经验更新,打破样本相关性。
- 核心改进3:目标网络(Target Network):
- 维护一个固定周期更新的目标Q网络,计算TD目标时用目标网络,降低训练方差。
进阶变体:
- Double DQN:解决DQN的过估计问题,用主网络选动作,目标网络算价值;
- Dueling DQN:将Q(s,a)分解为“状态值V(s)”和“优势函数A(s,a)”,提高泛化能力。
2. 策略学习的改进:从策略梯度到Actor-Critic
问题:基于价值的算法(如Q学习)的局限性
- 难以处理连续动作空间(需离散化动作,精度损失);
- 策略是价值函数的派生(贪心选择),无法直接优化策略。
改进方案:策略梯度(Policy Gradient)与Actor-Critic
-
策略梯度(如REINFORCE算法):
- 直接参数化策略π(a∣s;θ)\pi(a|s;\theta)π(a∣s;θ)(如用神经网络输出动作概率);
- 目标函数:∇θJ(θ)=Eπ[∑t=0∞γtrt+1∇θlogπ(at∣st;θ)]\nabla_\theta J(\theta) = \mathbb{E}_\pi\left[ \sum_{t=0}^{\infty} \gamma^t r_{t+1} \nabla_\theta \log \pi(a_t|s_t;\theta) \right]∇θJ(θ)=Eπ[∑t=0∞γtrt+1∇θlogπ(at∣st;θ)];
- 优点:可处理连续动作;缺点:方差大,收敛慢。
-
Actor-Critic(AC)算法:
- 结合“策略网络(Actor)”和“价值网络(Critic)”:
- Actor:学习策略π(a∣s;θ)\pi(a|s;\theta)π(a∣s;θ),输出动作;
- Critic:学习价值函数V(s;ϕ)V(s;\phi)V(s;ϕ),评估Actor的动作(计算优势函数A(s,a)=Q(s,a)−V(s)A(s,a) = Q(s,a) - V(s)A(s,a)=Q(s,a)−V(s));
- 优点:用Critic的优势函数降低策略梯度的方差,收敛更快;
- 进阶变体:A2C(Advantage Actor-Critic)、PPO(Proximal Policy Optimization,工业界常用)。
- 结合“策略网络(Actor)”和“价值网络(Critic)”:
3. 探索与利用的改进:从ε-贪心到内在奖励
问题:传统探索策略的局限性
- ε-贪心:随机探索效率低,易重复探索无价值区域;
- UCB:计算复杂度高,不适用于高维状态。
改进方案:
-
内在奖励(Intrinsic Reward):
- 除环境的外在奖励(如找到资源+100)外,增加“探索奖励”(如访问新状态+5),鼓励智能体探索未去过的区域;
- 典型方法:好奇心驱动(Curiosity-Driven)学习,用神经网络预测动作的结果,预测误差作为内在奖励。
-
汤普森采样(Thompson Sampling):
- 基于贝叶斯思想,维护策略参数的概率分布,每次采样一个策略进行探索,根据经验更新分布;
- 优点:探索更有针对性,适用于稀疏奖励场景。
4. 应对连续动作空间:从离散化到策略参数化
问题:离散化动作的局限性
- 连续动作空间(如机器人的力矩控制)无法离散化(精度损失或维度爆炸)。
改进方案:
-
策略网络输出动作分布参数:
- 连续动作常用高斯分布建模:策略网络输出动作的均值μ(s)\mu(s)μ(s)和标准差σ(s)\sigma(s)σ(s),动作a∼N(μ(s),σ(s)2)a \sim \mathcal{N}(\mu(s), \sigma(s)^2)a∼N(μ(s),σ(s)2);
- 示例:DDPG(Deep Deterministic Policy Gradient),用确定性策略(μ(s)\mu(s)μ(s))+ 目标网络,处理连续动作。
-
动作空间裁剪:
- 若动作有物理约束(如力矩范围[−1,1][-1,1][−1,1]),需对网络输出的动作进行裁剪(如用
tanh()
激活函数将输出映射到[−1,1][-1,1][−1,1])。
- 若动作有物理约束(如力矩范围[−1,1][-1,1][−1,1]),需对网络输出的动作进行裁剪(如用
5. 鲁棒性与泛化改进:对抗训练与领域自适应
问题:强化学习算法的泛化能力差
- 在训练环境中表现好,但迁移到相似但不同的环境时性能骤降(如火星探测器在模拟环境训练好,实际火星表面有未知地形)。
改进方案:
-
对抗训练(Adversarial Training):
- 在状态中加入微小扰动,训练策略对扰动的鲁棒性;
- 典型方法:FGSM(Fast Gradient Sign Method)生成对抗样本,增强策略的抗干扰能力。
-
领域自适应(Domain Adaptation):
- 用少量真实环境数据微调模拟环境训练的模型;
- 迁移学习:将模拟环境学到的特征迁移到真实环境,减少真实环境的数据需求。
3.4.7 常见问题与易错点总结
问题类型 | 具体表现 | 解决方案 |
---|---|---|
训练不收敛 | 奖励曲线震荡不上升,损失曲线发散 | 1. 降低学习率;2. 加入经验回放;3. 使用目标网络;4. 状态标准化 |
过估计 | Q值估计远高于实际回报(如DQN) | 1. 使用Double DQN;2. 减小折扣因子γ\gammaγ;3. 增加正则化 |
探索不足 | 智能体陷入局部最优(如探测器一直走同一条路) | 1. 增大初始ε\varepsilonε;2. 加入内在奖励;3. 使用汤普森采样 |
样本效率低 | 需大量episode才能收敛(如百万级step) | 1. 预训练价值网络;2. 加入 demonstrations(示范数据);3. 分层强化学习 |
连续状态不稳定 | 价值估计波动大 | 1. 用更大的经验回放缓冲区;2. 网络加入BatchNorm;3. 降低学习率 |
总结
强化学习是“智能体通过交互试错学习最优策略”的范式,核心在于:
- 数学基础:马尔可夫决策过程(MDP)定义问题,贝尔曼方程提供价值函数的递归框架;
- 核心概念:回报(长期奖励)、策略(动作选择准则)、价值函数(量化状态/动作好坏);
- 关键技术:无模型学习(TD、Q学习)处理实际场景的环境未知问题,函数近似(神经网络)处理高维连续状态;
- 改进方向:从DQN到PPO,从ε-贪到内在奖励,持续解决收敛性、泛化性、样本效率等问题。
实际应用中,需根据任务场景(离散/连续状态、是否有环境模型)选择合适的算法,并通过经验回放、目标网络等技巧保障训练稳定,最终实现智能体的自主决策。