零、从这个栏目说起

为什么要每天学一个新知识,主要是出于两点,一点是我觉得学校里真的很少教这些东西,当然也可能是教了我也没听课。现有的大一大二课程中,排除大一打基础的 AI 引论 / AI 基础,剩下的大二专业课其实教的都不深,基本上都把注意力放在传统方法上。但是如果传统方法真的那么重要那么好用,要新方法干啥呢,我能理解这个打基础的行为,但是现在真的发展太快了。另一点是来自于可信机器学习这门课,当时有一项作业是模拟打榜,具体来说是写一个防御系统以抵抗对模型的攻击,要求在 2 个 epoch 下微调 ResNet,然后比较防御成功率。如果单纯用课上教的知识,结果是被其他人薄纱,而效果最好的那些人往往提出了一些超出课堂知识的方法。这让我觉得我确实有必要逐步学习一些新知识了。

因此从今天开始,我下定决心尽量一天一更,就着眼于一项我挖掘到的我比较陌生的内容,然后认真学一学。

还是得介绍一下我的更新思路。我会从我刷到的最感兴趣的话题开始,但是这个问题可能是源于某个更早的我不了解的源头,所以我还得追根溯源到我学习的开头。其实我是需要学习 GRPO 算法,然后发现它的前身是 PPO,并且归根结底还是一个强化学习算法。所以我第一期先介绍强化学习,第二期再把 PPO 学明白,第三期就学 GRPO。

一、强化学习基础

我整个大二好像没碰过强化学习,都忘的差不多了。

1. 强化学习问题的概念

先定义一下强化学习的问题:有一个智能体,它可以感知环境影响环境获得奖励,它的最终目标就是,在训练中学习到一个策略,以最大化自己的奖励。想象一下:现在有一个智能体(agent),它一开始处在一个复杂不确定的环境(environment)中。它能做的只有两件事:做出动作(action)$a_t$,然后获得环境反馈的状态(state)$s_{t+1}$ 和奖励(reward)$r_{t+1}$。在不断的交互中,智能体尝试获得最大的收益(return)。

强化学习也是一种基本的机器学习方法,对标的是监督学习和非监督学习。我觉得从监督学习这种给出样本和标签;再到非监督学习只给样本不给标签;最后到强化学习,一开始啥都不给;其实是逐步削减了模型能获得的信息量,从而狠狠压力模型去更努力的学习。大家现在越来越卷,对大家的要求越来越高,这何尝不是一种强化学习呢。

2. 相关术语

策略就是智能体根据当前状态,决定动作的原则。可以是确定性的,记为 $\mu:a_t=\mu(s_t)$,也可以是随机的,表示为 $\pi:a_t\sim\pi(\cdot\vert s_t)$。很明显,强化学习的最终目标就是制定策略。

状态转移是环境在当前状态下,接受智能体的动作,会改变成什么状态。可以用状态密度函数表示:$p(s’\vert s,a)$。这个对于智能体一般是未知的。

回报记为 $U_t$,可以定义成 $U_t=R_t+R_{t+1}+\cdots$,也就是自 $t$ 时刻以来的奖励总和。不过未来的奖励其实可以降低点权重,也就是定义成 $U_t=R_t+\gamma R_{t+1}+\gamma^2 R_{t+2}+\cdots$,其中 $\gamma$ 为折扣率(discounted return),一般是不超过 1 的正实数。

在制定策略的时候,很重要的一点是,因为我们希望最大化奖励,但我们又不能确切地知道未来的奖励是多少,所以需要能够大概估计出奖励,也就是价值函数(value function)。价值函数也有两种分类:状态价值函数是衡量状态的价值,即在策略 $\pi$ 之下,状态 $s_t$ 的好坏;动作价值函数是衡量动作的价值,即在策略 $\pi$ 和状态 $s_t$ 之下,动作 $a_t$ 的好坏。

3. 探索 vs 开采

强化学习的核心矛盾就在于,到底应该探索(Exploration)未知领域,还是应该开采(Exploitation)已知的最佳策略。一些常见的算法有:

  • $\epsilon-$ 贪心策略:大部分时间选择最优动作(即开采),以 $\epsilon$ 的概率完全随机地选择一个动作。
  • 上置信界算法(Upper Confidence Bound, UCB):给每个动作打分:\(score(a)=Q(a)+c\sqrt{\frac{\ln t}{N_t(a)}}\) 其中:

    • $Q(a)$ 是当前动作的平均奖励;
    • $N_t(a)$ 是 $a$ 被选了多少次;
    • $c$ 是平衡参数,一般取 $\sqrt{2}$;
    • $t$ 是时间步。

    可以看出,被选择的次数越少,后面这个值就越大,越被鼓励选择。每一次我们都计算每个动作的分数,选分数最大的动作。

这两个是 AI 引论学过的,纯当回顾了。请注意,选择探索和开采的根本,都是已知每个动作的奖励。因此,准确设定价值函数仍然是我们的核心问题。

二、基础的强化学习方法

我们从 Q-learning 和 SARSA 这两种方法起步。

1. Q-learning

Q-learning 是基于动作价值函数 $Q(s,a)$ 的算法。其核心是,每次根据当前的 $Q$ 执行动作,根据反馈的状态以及奖励信号更新 $Q$ 值,如此循环。很明显,这个算法的核心就是:到底怎么更新 $Q$ 值,才能保证这样优化下的 $Q$ 能正确反映动作价值呢?

核心公式是这样的:

\[Q(s,a)\leftarrow Q(s,a)+\alpha[r+\gamma\max_{a'}Q(s',a')-Q(s,a)]\]

其中:

  • $Q(s,a)$ 是我们需要更新的 $Q$ 值;
  • $\alpha$ 是学习率;
  • $r$ 是执行 $a$ 后获得的奖励;
  • $\gamma$ 是折扣因子;
  • $s’$ 是执行 $a$ 后的状态;
  • $a’$ 是遍历 $a$ 的下一个动作。

由 Bellman 方程可以证明上述 $Q$ 值能够实现最优,Bellman 方程就是动态规划的核心原理。数学这一块我们就跳过了。总之,首先我们初始化 $Q$ 全为 $0$,然后按照上述公式,每做一次动作 $a$ 后,就更新 $Q$ 表即可。

那有人就问了,这么超模的算法,还能保证最优?注意这个最优是有条件的:

  • 状态和动作必须是有限集;
  • 可以无限次访问每个状态-动作对
  • 学习率要满足一定条件;
  • $0<\gamma<1$。

在 Q-learning 中,在更新当前 Q 值时,它直接选择了下一个状态中 Q 值最大的那个动作 $a’$,而压根不管你下一步实际会做什么。这种现象叫离策略,也就是行为策略目标策略分离了。所谓行为策略就是智能体实际执行的动作,目标策略就是更新 Q 值的策略。

2. SARSA

与 Q-learning 相反,SARSA 就是一种同策略算法,它的名字源自于其更新过程涉及的状态-动作序列:$S,A,R,S’,A’$。更新公式和 Q-learning 很像:

\[Q(s,a)\leftarrow Q(s,a)+\alpha[r+\gamma Q(s',a')-Q(s,a)]\]

唯一的改变是把理论最大值改成了实际下一步动作的 Q 值。因为更新 Q 值的策略和实际选择动作的策略是同一个,所以叫做同策略

3. 实操环节

上述两种算法都是更新 Q 值的算法,不涉及选择动作。实际上,需要将选择动作和更新 Q 值搭配使用。

下面,我们考虑一个 $4\times4$ 的网格世界,智能体需要从左上角 $(0,0)$ 走到右下角 $(3,3)$,也就是原点在左上角的坐标系。每次智能体有四种行动选择:上下左右,如果走出边界则留在原地。到达目标时获得奖励 $10$,否则奖励为 $-1$。

首先实现 Q-learning。我们初始化一个 Q 表,包括 16 个状态对应四个动作,一共 64 个元素,初始全为 $0$。假设现在的状态是 $s_t$:

  • 首先需要根据 Q 值做出行动 $a_t$,这里我们用 $\epsilon-$ 贪心策略,有 $1-\epsilon$ 的概率按照 $Q(s_t,a_t)$ 最大的 $a_t$ 行动,$\epsilon$ 的概率随机往一个方向走。
  • 行动后,获得新状态 $s_{t+1}$,奖励 $r_{t+1}$,此时使用 Q-learning 算法更新 $Q(s_t,a_t)$ 的值。

然后实现 SARSA,整体的操作和上述差不多,不过需要使用 $\epsilon-$ 贪心算法贪出两步:$a_t$ 和 $a_{t+1}$,再更新 $Q(s_t,a_t)$。但是注意了,下一次要更新的就是 $Q(s_{t+1},a_{t+1})$,就只用多贪一步了。

三、深度强化学习算法

把深度学习应用到强化学习中,也就是使用深度神经网络提取复杂的环境特征。深度强化学习的算法家族主要分为三大类:基于价值(Value-Based)、基于策略(Policy-Based)、以及两者结合的演员-评论家(Actor-Critic)方法。

1. DQN

基于价值的算法核心是用深度神经网络学习动作价值函数 $Q(s,a)$,只要学出准确的函数,每一步贪心就完事了。深度 Q 网络(DQN) 是里程碑的工作,它于 2015 年发布在 Nature 上,算是深度强化学习算法的先河。

下面我们逐步思考 DQN 是怎么设计出来的。首先,神经网络的目标就是设计出一个带参数的网络 $Q$,输入状态 $s$ 和动作 $a$,输出其价值。为了实现这一点,我们得对这个神经网络的参数进行梯度下降,损失函数是什么呢,我们回顾一下 Q-learning 的公式:

\[Q(s,a)\leftarrow Q(s,a)+\alpha[r+\gamma\max_{a'}Q(s',a')-Q(s,a)]\]

我们自然希望后面这个式子为 $0$,这样说明 $Q$ 已经准确了。那么设定均方误差就是:

\[Loss=[y-Q(s,a;\theta)]^2\]

其中 $y=r+\gamma\max_{a’}Q(s’,a’;\theta)$。求出误差后,反向传播更新 $\theta$ 即可。

根据上述损失函数的设定,我们有了初始的算法:

  • 初始 $Q=0$;
  • 每次进行行动 $a_t$,获得状态-行动对 $(s_t,a_t,r_{t+1},s_{t+1})$;
  • 前向传播求出 $y$;
  • 求出损失值 $Loss$;
  • 反向传播更新 $\theta$;
  • 再次使用 $(s_{t+1},a_{t+1},r_{t+2},s_{t+2})$ 进行上述循环。

是不是很简单?然而,现在有三个致命问题:

  • 梯度下降假设训练样本之间是独立同分布的,然而显然这里的训练数据有很强的相关性;
  • 监督学习的标签 $y$ 是固定的,现在的 $y$ 是高度与 $\theta$ 相关的,这导致目标一直在移动,极易导致 $Q$ 值发生指数级发散;
  • Q-learning 方法本身用最大价值的下一步行动去估计,这会带来偏高的噪声,不过在查表方法下能够控制该噪声有界;而引入梯度下降后,这个噪声会被导入梯度中,导致梯度爆炸。

如何解决呢,DQN 的伟大之处正在下面两个设计!

i. Experience Replay

经验回放旨在解决训练样本的相关性问题。思路倒是很简单,你说相邻的样本的相关性太强,那我不取相邻的不就好了嘛。因此,先让智能体随便多走个几百步,把这些状态-行动对全部存入一个经验池(Replay Buffer)中。然后,从这个经验池中随机抽取一小批数据去训练。

ii. Target Network

目标网络旨在解决目标值不断移动的问题。这个思路也简单,现在的问题是每算一次损失都会马上调整参数,那我不这么做不就好了吗,我复制一个相同的网络,现在有两个网络:在线网络 $Q$ 和目标网络 $Q_{target}$,参数是一模一样的。我们每次把样本同样塞进两个网络中,同样前向传播。不同的是,我们保证目标网络的目标不变,也就是保持它的参数不变,且让它前向传播,这样能保证 $y$ 始终不变,同时对在线网络反向传播,实时更新参数。但是也不能一直这样,因为最初的 $y$ 不准确,它本质也得变化,因此我们每过固定的回合数(比如 1000 步)就把在线网络的参数传给目标网络,更新一下 $y$。

iii. 完整运行流程

现在我们整合原始算法、经验回放、目标网络,得到最终的 DQN 算法:

  1. 获取经验池:反复动一定次数,获取状态-行动对,构成经验池;
  2. 随机采样:随机抽取一批历史数据;
  3. 目标网络前向传播:求出目标值 $y$;
  4. 在线网络反向传播:更新在线网络的参数;
  5. 定期同步:反复执行 2-4 步,一定次数后将在线网络的参数传给目标网络。

这个算法完美解决了前两个问题!虽然解决方法都挺好想出来的,不过真正有价值的部分是提出原始算法的缺陷,大家要知道,把神经网络直接引入进来,结果效果不佳,这是很难解决的事情。在大家的实践中,也经常会碰到这种问题:如何解释一个理应完美,实际却不尽人意的现象?解决这种问题,才是科研的真谛啊。

话又说回来,第三个问题不是还没解决吗?后续有针对的双 DQN 算法,这个就由大家自行学习了。

2. REINFORCE 算法

基于策略的方法直接将策略视作一个神经网络,通过优化策略参数直接最大化期望回报。策略本质上也就是个概率函数 $\pi(a\vert s)$ 而已,给它加个参数:$\pi(a\vert s;\theta)$。

REINFORCE 算法就是这方面的一个代表性算法,它的参数更新公式是:

\[\theta\leftarrow\theta+\alpha\cdot G_t\cdot\nabla_\theta\log\pi_\theta(A_t|S_t)\]

看起来好复杂,其实就是很简单的梯度下降:

  • $\nabla_\theta\log\pi_\theta(A_t\vert S_t)$ 就是下降方向,表示沿着哪个向量方向调,才能使在 $S_t$ 的情况下尽可能选到 $A_t$,这跟奖励多少没关系;
  • $G_t$ 就是步长,表示从时刻 $t$ 开始到回合结束,所获得的总奖励;
  • $\alpha$ 就是学习率。

简单总结,就是我先尽力帮你做 $A_t$,要是赢钱了($G_t>0$),就多这么做;如果亏了,就少这么做。

完整的工作流程和 Q-learning 不一样,不是每走一步就更新,而是等整局结束一起更新。具体如下:

  1. 打一整把:用当前策略 $\pi_\theta$ 一路打完一整把游戏,记录每一步的 $(S_t,A_t,R_{t+1})$;
  2. 计算每一步的回报:$G_t=R_t+\gamma R_{t+1}+\gamma^2R_{t+2}+\cdots$;
  3. 更新参数:用上述公式更新;
  4. 用新策略重复执行步骤 1-3。

这个方法的优点很明显:直接学习策略,用最直白最不绕弯子的方法得到最优策略,就不用担心 Q 值准不准了。但实际上压根没几个人会用这个方法,因为它的缺点也太致命:

  • 方差极高:打一整把的随机性太大了!
  • 样本利用率极低:打一整把都只更新一次参数!

那么如何优化这种方法呢,且待下节分解~

3. 演员-评论家方法

演员,就是一个策略网络,负责生成动作;评论家,就是一个价值网络,负责评估价值。它结合了两种方法的优势,价值网络限制了策略网络的方差,策略网络能给价值网络提供灵活性和随机性。它的工作流程是:

  1. 演员根据状态 $s$ 和策略,执行动作 $a$;
  2. 环境反馈奖励 $r$ 和新状态 $s’$;
  3. 评论家计算误差,更新价值网络。

四、总结

我们简单回顾了强化学习的基本知识,了解了强化学习的两个核心:选择动作,评估价值。后来又将神经网络引入强化学习,使其能处理更复杂的环境。

Leave a comment