北辰 - 强化学习
type: channel
link: http://www.bcblog.com.cn/tag/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/
items: DDPG 算法
items: Actor-Critic
items: 不同系统在PyTorch中使用GPU加速对比
items: Policy Gradient Algorithm
items: DQN
items: TD Algorithm

DDPG 算法
type: item
date: 2024-12-13T19:17:00+08:00
description: 创建时间: 2024/12/2 12:45:16作者: 蜡笔大新笔记类型: 强化学习简介DDPG（Deep Deterministic Policy Gradient）是一种基于 Actor-Critic 结构的深度强化学习算法。传统的 Q-Learning 只能处理离散状态和动作，DQN 能处理连续状态和离散动作，而[font color="Red"]DDPG则解决了在连续状态和动作空间下的强化学习问题[/font]。DDPG 与梯度策略算法系列中的 REINFORCE 算法有所不同：REINFORCE 提供随机策略，而 DDPG 提供确定性策略（Deterministic Policy）。具体来说，非确定性策略 $\pi_\theta$﻿ 输出每个动作的概率（对于连续动作则是概率分布曲线），可以通过 $\epsilon$﻿ 策略或选择最高概率的动作来决策；而确定性策略则直接输出具体动作，记作 $a=\mu_\theta (s)$﻿。由于 DDPG 的确定性特征限制了其探索能力，因此算法中添加了随机噪声来增强探索。网络Actor与传统 Actor-Critic 算法中的 Actor 类似，DDPG 中的 Actor 也是一个神经网络，区别在于神经网络和激活函数的设置不一样。DDPG 的 Actor 通常最后一层直接输出一个具体值，对于连续动作空间，可能会使用特定的激活函数限制输出范围，例如：Tanh 激活函数：限制输出在 [-1, 1]。线性输出：直接输出在连续范围内的值。最后会输出一个网络认为的价值期望最高的动作，输出维度等于动作空间的维度。CriticDDPG 的 Critic 网络与 DQN 的 Q 网络和传统 AC 的 Critic 网络有明显区别。DQN 的 Q 网络输入状态后输出所有动作的 Q 值，这种方式只适用于离散动作问题，无法处理连续动作空间。传统 AC 算法中的 Critic 使用神经网络来估计状态的 V 值。而 DDPG 的 Critic 则采用神经网络同时接收状态和动作作为输入，用于预估 Q 值。更新网络参数更新的时间节点主要是在经验池满了之后，随机采样经验池的经验进行更新，通过这种机制能够有效减少样本的时间相关性，避免模型过度依赖于某些特定的样本，使得训练数据更具多样性，增强了策略在不同场景中的泛化能力，提升模型的训练稳定性。ActorActor 网络主要使用神经网络输出当前状态下价值期望最高的动作，其优化的目标就是最大化 Critic 网络的 Q 值，更新主要是通过 Critic 网络输出的 Q 值进行梯度上升。CriticCritic 网络的损失函数是当前 Q 值和目标 Q 值的均方误差（MSE）。其更新目标是最小化这个均方误差，通过梯度下降来更新参数。MSE公式$$ L(\theta^Q) = \frac{1}{N} \sum_{i=1}^N \left( Q_{\text{target}, i} - Q(s_i, a_i|\theta^Q) \right)^2 $$目标 Q 值的计算$$ Q_{\text{target}, i} = r_i + \gamma (1 - \text{done}_i) Q'(s'_i, \mu'(s'_i|\theta^{\mu'})|\theta^{Q'}) $$这个公式其实就是贝尔曼公式的变种。[scode type="blue" size=""]其中：$Q_{\text{target}, i}$ 表示目标网络的 Q 值。从当前状态 $s_i$ 和动作 $a_i$ 开始，未来累积奖励的估计值。$r_i$ 表示智能体在当前状态 $s_i$ 执行动作 $a_i$ 后，从环境中获得的奖励$\gamma$ 表示折扣因子$done_i$ 表示当前状态是否是终止状态（0代表未终止，1代表终止）$\mu'(s'_i|\theta^{\mu'})$ 代表目标 Actor 网络根据 $\theta^{Q'}$ 软更新参数 $\theta^{Q}$ 的情况下，根据下一个状态 $s'_i$ 生成的动作 $Q{\prime}(s{\prime}_i, a{\prime}|\theta^{Q{\prime}})$ 表示目标 Critic 网络根据下一个状态和下一个动作生成的 Q 值[/scode]至此，重新梳理一下整个目标 Q 值的计算：获取当前状态 $s_t$ 和当前动作 $a_t$当前状态 $s_t$ 执行当前动作 $a_t$，获取下一个状态 $s_{t+1}$将下一个状态 $s_{t+1}$ 输入进目标 Actor 网络，获取下一个动作 $a_{t+1}$将下一个状态 $s_{t+1}$ 和下一个动作 $a_{t+1}$ 输入进目标 Critic 网络，获取 Q 值将目…

Actor-Critic
type: item
date: 2024-11-25T18:31:00+08:00
description: 创建时间: 2024年11月13日 11:23作者: 蜡笔大新笔记类别: 强化学习标签: 强化学习, 深度强化学习, 策略梯度算法状态: 完成简介之前提到的 DQN 系列算法属于基于值函数的方法来训练模型，而 PG 系列算法则属于基于策略梯度的方法。PG 系列通常采用蒙特卡洛方法计算 G 值，并通过梯度上升更新参数。科学家们考虑将策略与时序差分（TD）方法相融合，使得无需沿着整个路径更新到结束状态再回溯就能更新当前状态。这类似于 TD 算法的思想：边前进边更新 Q 值，同时更新策略。这种方法被称为 Actor-Critic 算法。许多前沿算法都是基于 AC 进行改进的，可以说这种思想既重要又实用。与DQN的结构有些相似，AC算法也拥有两个网络，分别是Actor网络和Critic网络，接下来将分别进行介绍。Actor网络Actor网络负责与环境交互，并在 Critic 价值函数的指导下用策略梯度学习一个更好的策略。Critic网络通过 Actor 与环境交互收集的数据学习一个价值函数，这个价值函数会用于判断在当前状态什么动作是好的，什么动作不是好的，进而帮助 Actor 进行策略更新。而更新的策略则与之前的PG算法很像，都是通过梯度上升算法更新参数。TD-Error时序差分残差（TD-Error）是强化学习中用来衡量当前状态与预期状态的差异的指标。反映了当前状态与预期状态的差异，通常被用来更新策略网络的参数，使得策略能够更快地朝着最优策略的方向学习。$$ \delta_t = r_t + \gamma V(s_{t+1}) - V(s_t) $$其中：$\delta_t$ 是在时间步 t 的TD误差$r_t$ 是在时间步 t 获得的即时奖励$\gamma$ 是折扣因子$V(s_t)$ 是状态 $s_t$ 的估计值函数$V(s_{t+1})$ 是下一个状态 $s_{t+1}$ 的估计值函数[font color="Orange"]TD-Error需要与优势函数做出一定区别。[/font][scode type="blue" size=""]优势函数用于衡量特定动作 a 在某个状态 s 中的好坏程度。给定状态值函数 V(s) 和动作值函数 Q(s, a) ，优势函数定义为：$$ A(s, a) = Q(s, a) - V(s) $$其实很好理解，Q值是执行动作的总奖励期望，而V值是到达状态后的总奖励期望（所有动作Q值的平均数），因此如果A>0，说明这个动作的期望在平均之上；反之则比平均更差。而TD-Error的公式与优势函数其实是可以互相转化的，即 $Q=\gamma * V(S’)+r$ 。但是需要区别的是他们的含义不同。优势函数说明这个动作在该状态下是否比平均策略更优，因此是一个相对的衡量标准。而TD-Error评价当前状态值估计与“实际“观测值的偏差。它更强调一种“矫正”效果，反映当前价值估计的准确性，并直接用于更新价值函数或策略。[/scode]更新TD-Error： $\delta_t = r_t + \gamma V(s_{t+1}) - V(s_t)$ 就可以看作“真实”值和预测值之间的差异：如果 “真实”值 > 预测值（即 $\delta_t$ > 0 ），说明模型低估了当前状态的价值。为了修正这一低估，模型会增加 $V(s_t)$ 的估计值，使得预测更接近真实值。并且差得越多，更新的幅度越大。如果 “真实”值 < 预测值（即 $\delta_t$ < 0 ），则模型高估了当前状态的价值。模型将减小 $V(s_t)$ 的估计值，调低预测以贴合真实值。误差越大，调整幅度也越大。[scode type="blue" size=""]$r_t + \gamma V(s_{t+1})$ 表示更好的价值估计，因为结合了实际观测到的即时奖励和对未来价值的估计，因此实际使用时可以理解为"真实"值。$V(s_t)$ 表示预测值：$V(s_t)$ 是模型根据当前参数对状态 $s_t$ 的价值估计。[/scode]具体而言，损失函数通常使用MSE最小化TD-Error，并通过梯度上升更新Actor的参数，通过梯度下降更新Critic的参数。实际代码中会统一使用梯度下降方便实现（给梯度上升加负号）。流程Actor根据当前状态生成策略。Actor是策略网络，它基于当前状态 $s_t$ 生成一个策略 $\pi(a|s_t)$ 。通常，策略会给出每个动作的概率分布。Actor可以：选择概率最高的动作（贪婪策略）根据概率分布随机采样一个动作（通常是探索时使用的方式）执行动作，获取奖励和下一个状态。从环境中执行Actor选出的动作 $a_t$ ，得到即时奖励 $r_t$ 和下一个状态 $s_{t+1}$ 。Critic计算价值估计并生成TD-Err…

不同系统在PyTorch中使用GPU加速对比
type: item
date: 2024-11-14T17:18:00+08:00
description: 介绍根据PyTorch在2022年推出的文章来看，M系列芯片的mac已经可以使用GPU加速训练。pytorch使用起来也非常方便，和cuda类似：torch.backends.mps.is_available()torch.device("mps")实验使用PyTorch官方的MNIST例子，即手写数字识别。对比了一下不同系统下CPU和GPU加速的对比效果。实验均采用Batch=64，Epoch=5的参数。实验一（Mac M4）芯片：M4实验二（Mac M1）芯片：M1实验三（Win）CPU：AMD R7-5800HGPU：RTX3060 Laptop 130w结论通过实验可以看出，苹果的M4芯片相较于M1芯片进步异常明显，使用GPU（mps）加速可以非常显著的提升训练和测试的速度。而相较于笔记本的3060显卡，mps加速竟然比cuda加速还要快。但是，由于是PyTorch官方推出的案例，难免会进行特殊优化。在强化学习的学习中，并没有发现mps比cpu快很多，甚至还不如cpu正常跑，可能与批次等参数的设置也有关，有待后续继续实验。代码import argparse import time import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torchvision import datasets, transforms from torch.optim.lr_scheduler import StepLR import matplotlib.pyplot as plt class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 32, 3, 1) self.conv2 = nn.Conv2d(32, 64, 3, 1) self.dropout1 = nn.Dropout(0.25) self.dropout2 = nn.Dropout(0.5) self.fc1 = nn.Linear(9216, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = self.conv1(x) x = F.relu(x) x = self.conv2(x) x = F.relu(x) x = F.max_pool2d(x, 2) x = self.dropout1(x) x = torch.flatten(x, 1) x = self.fc1(x) x = F.relu(x) x = self.dropout2(x) x = self.fc2(x) output = F.log_softmax(x, dim=1) return output def train(model, device, train_loader, optimizer, epoch): model.train() for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = F.nll_loss(output, target) loss.backward() optimizer.step() def test(model, device, test_loader): model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) test_loss += F.nll_loss(output, target, reduction='sum').item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) accuracy = 100. * correct / len(test_loader.dataset) …

Policy Gradient Algorithm
type: item
date: 2024-11-05T16:51:00+08:00
description: 创建时间: 2024年11月5日 16:51作者: 蜡笔大新笔记类别: 强化学习标签: Deep Reinforcement Learning, Policy Optimization, Reinforcement Learning状态: 完成基本原理PG算法，全称为策略梯度算法（Policy Gradient Algorithm），是强化学习中的一种重要方法。它直接对策略进行优化，而不是通过值函数间接优化策略。这种方法在连续动作空间和高维动作空间中特别有效。PG算法的核心思想是通过梯度上升的方式直接优化策略函数。它通过估计策略梯度来更新策略参数，使得期望回报最大化。这种方法允许智能体在每个状态下学习一个概率分布，用于选择最优动作。之前提到的 Sarsa、Q-Learning 和 DQN 算法都是基于价值的方法，也就是先计算每个状态对应的动作的 Q 值，再选择 Q 值最大的动作执行。而 Policy Gradient 是一种更加直接的方式，它直接计算每个状态对应的动作的概率。这样做的优点就是它可以在一个连续区间内选取动作。如果用一句话来表达策略梯度的直观解释，那就是“如果动作使得最终回报变大，那么增加这个动作出现的概率，反之，减少这个动作出现的概率”。这句话表达了两个含义：我们考虑的是动作对于回报的影响，没有考虑状态或者其他因素。我们调整的是动作出现的概率，而没有给某个动作打分，这区别于Value-based类的算法。理解PG算法不同于之前提到的基于价值类的算法，PG更多需要从整体和宏观网络的角度去理解。不再通过每个状态-动作对去更新，而是类似蒙特卡洛的思想，通过大量实验去逼近最终结果。总体的思路是：从初始状态开始，按照当前策略选择动作，直到到达终止状态。这构成一条完整的轨迹。从终止状态往回计算总的奖励和，作为这条路径的总奖励。当完成了一定数量的路径后，将批量投入训练，具体则是梯度上升算法更新参数 $\theta$ ，目标是使总的期望奖励函数变得最大，从而得到最优策略。我们将策略学习的目标函数定义为：$$ J(\theta) = \mathbb{E}_{s_0}[V^{\pi_\theta}(s_0)] $$核心公式$$ \begin{align*}\nabla_\theta J(\theta) &\propto \sum_{s \in S} v^{\pi_\theta}(s) \sum_{a \in A} Q^{\pi_\theta}(s, a) \nabla_\theta \pi_\theta(a|s) \\&= \sum_{s \in S} v^{\pi_\theta}(s) \sum_{a \in A} \pi_\theta(a|s) Q^{\pi_\theta}(s, a) \frac{\nabla_\theta \pi_\theta(a|s)}{\pi_\theta(a|s)} \\&= \mathbb{E}_{\pi_\theta} [Q^{\pi_\theta}(s, a) \nabla_\theta \log \pi_\theta(a|s)]\end{align*} $$解释：$\nabla_\theta J(\theta)$：这是目标函数$J(θ)$关于策略参数$θ$的梯度。$v^{\pi_\theta}(s)$：这是在状态$s$下，按照策略$π_θ$行动的值函数。$\nabla_\theta \pi_\theta(a|s)$：这是策略$π_θ$在状态$s$下选择动作$a$的概率关于参数$θ$的梯度。$\pi_\theta(a|s)$：这是在状态$s$下选择动作$a$的概率。需要注意的是，因为上式中期望 $\mathbb{E}$ 的下标是 $\pi_\theta$ ，所以策略梯度算法为在线策略（on-policy）算法，即必须使用当前策略采样得到的数据来计算梯度。直观理解一下策略梯度这个公式，可以发现在每一个状态下，Q值越高则整个期望越大，因此可以认为梯度的修改是让策略更多地去采样到带来较高Q值的动作，更少地去采样到带来较低Q值的动作。优势PG算法具有以下优势：适用于连续动作空间：不需要离散化动作空间，可以直接在连续空间中操作。可以学习随机策略：这在某些环境中非常有用，特别是在部分可观察环境中。收敛性好：在理论上，PG算法可以保证收敛到至少一个局部最优解。代码在CartPole-v0环境中，使用梯度策略方法中最基本的算法之一的REINFORCE算法训练模型。import gym import torch import torch.nn.functional as F import numpy as np import matplotlib.pyplot as plt from tqdm import tqd…

DQN
type: item
date: 2024-10-24T13:53:00+08:00
description: 创建时间: 2024年10月24日 13:53作者: 蜡笔大新笔记类别: 强化学习标签: Deep Reinforcement Learning, Experience Replay, Q-Learning状态: 完成传统Q-Learning的一些问题在Q-Learning中，需要反复更新Q-table，最终通过贪心算法根据Q表选取相应的动作。而这通常会带来一些问题，比如动作和状态维度过高之后，Q-table的维度也会非常高，带来计算和存储的巨大压力。DQN介绍DQN（Deep Q-Network）是一种结合了 深度学习 和 Q-Learning 的强化学习算法，它通过深度神经网络来近似 Q 值函数，从而能够处理高维状态空间问题。优点DQN 使用一个 深度神经网络（DNN） 来代替传统 Q-Learning 中的 Q 表格，将状态作为输入，通过神经网络输出对应每个动作的 Q 值。这使得 DQN 能够处理复杂和高维的状态空间，比如在图像、视频帧等环境下的强化学习问题。[scode type="blue" size=""]简而言之，模型不再需要去额外存储表格，而是通过训练得到一个函数，输入状态，就能输出每个动作的Q值。[/scode]传统的Q-Learning很适合格子游戏。因为格子游戏中的每一个格子就是一个状态，但在现实生活中，很多状态并不是离散而是连续的。通过函数的形式就可以很好的解决连续的状态问题，比如驾驶的方向等。训练经验回放DQN 引入了一个非常重要的技术：经验回放，它的作用是打破样本之间的时间相关性，并使得神经网络的训练更加稳定。[scode type="blue" size=""]经验，即四元组：状态、动作、奖励、下一个状态。[/scode]在训练过程中，DQN 会从这个 经验池 中随机抽取样本来训练神经网络，从而减少数据之间的相关性，提升训练稳定性。模型DQN引入了目标网络（Target网络）与主体网络，它们是互相隔离的。目标网络的参数每隔一段时间才会从当前网络复制，而不是每步都更新。这样设计的目标主要是为了网络稳定，避免发散。或者以操作系统举例，主网络就是Beta测试版，Target网络就是Latest稳定版。稳定版会每隔一段时间或条件向测试版偏移。损失函数DQN 的训练目标是通过最小化当前 Q 值和目标 Q 值之间的误差来优化模型。常用的误差函数是 均方误差（MSE, Mean Squared Error）：$$ L(\theta)= [y-Q(s,a)]^2 $$其中：$y=Q(s_t, a_t) + \alpha \left[ r_t + \gamma \max_{a'} Q(s_{t+1}, a') - Q(s_t, a_t) \right]$，即贝尔曼公式，由目标DQN计算。$Q(s,a)$：当前 Q 值，由 当前DQN 网络预测。仍然分两个网络来讲：当前DQN：输出 $Q(s,a)$目标DQN：选取目标网络下下一个状态Q最大的动作，将其收益、Q值等代入贝尔曼公式输出y值。[scode type="blue" size=""]目标DQN的 $y$ 值可以理解为理论上的“正确值”，类似于有监督学习下打的标签。它与当前DQN输出的值做比较，通过MSE计算误差，如果误差越小，那说明当前网络距离真实模型的误差越小，而整个神经网络的最终目标就是让这个误差尽可能的小。[/scode]输入输出DQN接受当前状态，并且能输出一个包含所有动作Q值的向量，每个动作的顺序在定义网络结构的时候就已经确定了，并在整个训练和使用过程中保持不变。神经网络的输出层有固定数量的节点，每个节点对应一个特定的动作⁠。例如，在CartPole-v0环境中，动作空间只有两个动作（向左推和向右推）⁠。DQN的输出层就会有两个节点，可能表示为：第一个节点（索引0）：向左推的Q值第二个节点（索引1）：向右推的Q值动作选择当输入状态后，网络会输出包含所有动作Q值的向量。选择动作主要有两种策略：贪婪策略（Greedy Policy）：在大多数情况下，DQN会选择Q值最高的动作。这就是所谓的利用（exploitation）。ε-贪婪策略（ε-greedy Policy）：为了平衡探索和利用，DQN通常会采用ε-贪婪策略。具体来说：以ε的概率随机选择一个动作（探索）以1-ε的概率选择Q值最高的动作（利用）代码CartPole-v0CartPole-v0 是OpenAI Gym中的一个经典控制问题环境。在这个环境中：一个杆子通过一个非驱动关节连接到一个可以左右移动的小车上。系统开始时杆子是垂直的，目标是通过左右移动小车来保持杆子直立。每个时间步，agent可以选择向左或向右推车。每次成功保持杆子直立的时间步骤都会获得+1的奖励。当杆子倾斜超过15度，或者小车移…

TD Algorithm
type: item
date: 2024-10-23T19:04:00+08:00
description: 创建时间: 2024年10月23日 19:04作者: 蜡笔大新笔记类别: 强化学习标签: Q-Learning, Reinforcement Learning, Temporal Difference Learning状态: 完成简介TD算法，全称为"时间差分算法"（Temporal Difference Algorithm），是强化学习中的一种重要算法。它结合了动态规划和蒙特卡洛方法的优点，广泛应用于各种学习和决策问题。核心思想TD算法的核心思想是通过比较连续时间步骤的预测来学习。它使用当前估计和下一时间步的奖励来更新价值函数，而不需要等待整个序列完成。与其相反的蒙特卡洛方法，则是需要一直往前探索到结束，再往回走反馈奖励总和。[scode type="blue" size=""]TD有点类似动态规划算法（DP），都利用状态转移方程（贝尔曼公式）。而区别主要在于，TD是不需要环境模型的，可以自由探索环境，不断用前方的奖励训练自身模型；而DP需要知道完整的模型，需要对整个状态空间进行迭代，DP方法在状态空间较大时计算代价高昂。[/scode]主要特点在线学习：TD算法可以在每个时间步更新估计，无需等待整个序列结束。自举：TD算法使用估计来更新估计，这种自举方法使其能够快速学习。模型无关：TD算法不需要环境模型，可以直接从经验中学习。变体TD算法有多种变体，包括：Q-learning：一种off-policy TD控制算法SARSA：一种on-policy TD控制算法TD(λ)：结合了多步预测的TD算法Q- Learning在强化学习中，有两个核心概念：Q值和V值。Q值表示在某个状态下执行这个动作后，直到最终状态所获得的期望累积奖励；V值代表从这个状态开始，经过一系列决策到达最终状态的期望累积奖励。Q值和V值可以互相转化：一个状态的V值是其所有动作Q值的平均值；一个动作的Q值是下一个状态的V值加上当前动作的即时奖励。Q-learning是一种基于Q值的强化学习算法，主要思想是通过不断更新Q表来学习最佳策略。Q值状态 (State, s): 系统或环境的当前状况。动作 (Action, a): 在某个状态下，代理可以执行的行为选择。奖励 (Reward, r): 执行某个动作后，代理从环境中获得的反馈信号，通常用于衡量该动作的好坏。Q-Tablea1a2s1q(s1,a1)q(s1,a2)s2q(s2,a1)q(s2,a2)s3q(s3,a1)q(s3,a2)具体算法每个“状态-动作对”都拥有自己的Q值，而Q-Learning的核心就是在于不断维护、更新这个Q-Table。具体的算法步骤可以参考下图，主要步骤即为通过贪心算法更新 $[S_t, A_t]$状态-动作对下的q值，贪心算法是选取 $S_{t+1}$的状态下Q值最大的动作，利用奖励R反推。递推公式为贝尔曼公式：$$ Q(s_t, a_t) \leftarrow Q(s_t, a_t) + \alpha \left[ r_t + \gamma \max_{a'} Q(s_{t+1}, a') - Q(s_t, a_t) \right] $$其中：$s_t$ 是当前状态$a_t$ 是当前动作$r_t$ 是在执行动作后获得的奖励$s_{t+1}$ 是下一个状态$a'$ 是未来可能的动作$\alpha$ 是学习率（Learning Rate），控制每次更新Q值的步长。$\gamma$ 是折扣因子（Discount Factor），表示未来奖励的权重（0到1之间的数）。高 $\gamma$ 值意味着未来奖励更重要。[scode type="blue" size=""]当初始化时，Q-Table所有Q值都为0，更新的时候会直接用奖励值。[/scode]SarsaSarsa与Q-Learning很相似，区别是：Q-Learning选取的是下一个状态下最大Q值的动作；而Sarsa选取的仍是前一个动作，即 $A_t$ 。Q-learning是一种离线策略（off-policy）算法，它学习的是最优策略，不管当前正在执行的是什么策略，因此更倾向于探索；Sarsa是一种在线策略（on-policy）算法，它学习的是当前正在执行的策略，因此更保守。举例状态 (State) \动作（Action）动作A1动作A2S15[font color="Green"]9[/font]S2[font color="Green"]3[/font]2S3[font color="Green"]7[/font]1通过上述Q表，我们可以清晰的看出在每个状态下采取不同动作的奖励期望值，我们只需要在每个状态下选取收益最大的动作即可。代码环境悬崖漫步环境要求一个智能体从起点出发，避开悬崖行走，最终到达目标位置。智能体在每一…