# 强化学习

## Q-learning

**核心更新公式**  
$$
\boxed{Q(s,a) \gets Q(s,a) + \alpha\left[r + \gamma\,\max_{a'}Q(s',a') - Q(s,a)\right]}
$$
- $s$：当前状态  
- $a$：当前动作  
- $r$：执行 $a$ 后获得的即时奖励  
- $s'$：执行后到达的新状态  
- $\alpha\in(0,1]$：学习率，决定“这次新信息”对旧值的影响力度  
- $\gamma\in[0,1)$：折扣因子，衡量对“后续奖励”的重视程度  
- $\max_{a'}Q(s',a')$：新状态下可选动作的最大估值，表示“后续能拿到的最大预期回报”  

---

### 一般示例

**环境设定**  

- 状态集合：$\{S_1, S_2\}$  
- 动作集合：$\{a_1, a_2\}$  
- 转移与奖励：  
  - 在 $S_1$ 选 $a_1$ → 获得 $r=5$，转到 $S_2$  
  - 在 $S_1$ 选 $a_2$ → 获得 $r=0$，转到 $S_2$  
  - 在 $S_2$ 选 $a_1$ → 获得 $r=0$，转到 $S_1$  
  - 在 $S_2$ 选 $a_2$ → 获得 $r=1$，转到 $S_1$  

**超参数**：$\alpha=0.5$，$\gamma=0.9$  
**初始化**：所有 $Q(s,a)=0$  

在 Q-Learning 里，智能体并不是“纯随机”地走，也不是“一开始就全凭 Q 表拿最高值”——而是常用一种叫 **$\epsilon$-greedy** 的策略来平衡：  

- **探索（Exploration）**：以概率 $\epsilon$（比如 10%）随机选一个动作，帮助智能体发现还没试过、可能更优的路径；  
- **利用（Exploitation）**：以概率 $1-\epsilon$（比如 90%）选当前状态下 Q 值最高的动作，利用已有经验最大化回报。  

下面按序进行 3 步“试—错”更新，并在表格中展示每一步后的 $Q$ 值。

| 步骤 | 状态 $s$ | 动作 $a$ | 奖励 $r$ | 到达 $s'$ |               $\max_{a'}Q(s',a')$                |               更新后 $Q(s,a)$                |                          当前 Q 表                           |
| :--: | :------: | :------: | :------: | :-------: | :----------------------------------------------: | :------------------------------------------: | :----------------------------------------------------------: |
| 初始 |    —     |    —     |    —     |     —     |                        —                         |                      —                       | $Q(S_1,a_1)=0,\;Q(S_1,a_2)=0$   $Q(S_2,a_1)=0,\;Q(S_2,a_2)=0$ |
|  1   |  $S_1$   |  $a_1$   |    5     |   $S_2$   |                        0                         |             $0+0.5\,(5+0-0)=2.5$             | $Q(S_1,a_1)=2.5,\;Q(S_1,a_2)=0$   $Q(S_2,a_1)=0,\;Q(S_2,a_2)=0$ |
|  2   |  $S_2$   |  $a_2$   |    1     |   $S_1$   | $到达S_1状态后选择最优动作：$$\max\{2.5,0\}=2.5$ |       $0+0.5\,(1+0.9\cdot2.5-0)=1.625$       | $Q(S_1,a_1)=2.5,\;Q(S_1,a_2)=0$   $Q(S_2,a_1)=0,\;Q(S_2,a_2)=1.625$ |
|  3   |  $S_1$   |  $a_1$   |    5     |   $S_2$   |             $\max\{0,1.625\}=1.625$              | $2.5+0.5\,(5+0.9\cdot1.625-2.5)\approx4.481$ | $Q(S_1,a_1)\approx4.481,\;Q(S_1,a_2)=0$   $Q(S_2,a_1)=0,\;Q(S_2,a_2)=1.625$ |

- **第1步**：从 $S_1$ 选 $a_1$，立即回报5，更新后 $Q(S_1,a_1)=2.5$。  
- **第2步**：从 $S_2$ 选 $a_2$，回报1，加上对 $S_1$ **后续最优值**的 $0.9$ 折扣，得到 $1+0.9\times2.5=3.25$，更新后 $Q(S_2,a_2)=1.625$。  
- **第3步**：再一次在 $S_1$ 选 $a_1$，这次考虑了 $S_2$ 的最新估值，最终把 $Q(S_1,a_1)$ 提升到约 4.481。

---

通过这样一步步的“试—错 + 贝尔曼更新”，Q-Learning 能不断逼近最优 $Q^*(s,a)$，从而让智能体在每个状态都学会选出长期回报最高的动作。

训练结束后，表里每个状态 $s$ 下各动作的 Q 值都相对准确了，我们就可以直接读表来决策：  
$$
\pi(s) = \arg\max_a Q(s,a)
$$
即“在状态 $s$ 时，选 Q 值最高的动作”。  

| 状态 \ 动作 | $a_1$ | $a_2$ |
| ----------- | ----- | ----- |
| $S_1$       | 4.481 | 0     |
| $S_2$       | 0     | 1.625 |



## DQN

核心思想：用深度神经网络近似 Q 函数来取代表格，在高维输入上直接做 Q-learning，并通过 **经验回放（写进缓冲区 + 随机抽样训练”）** + **目标网络（Target Network）** 两个稳定化技巧，使 **时序差分（TD ）学习**在非线性函数逼近下仍能收敛。

**TD 学习** = 用“即时奖励 + 折扣后的未来估值”作为目标，通过 TD 误差持续修正当前估计。



### 训练过程

#### 1. 初始化

1. **主网络（Online Network）**  
   - 定义一个 Q 网络 $Q(s,a;\theta)$，随机初始化参数 $\theta$。

2. **目标网络（Target Network）**  
   - 复制主网络参数，令 $\theta^- \leftarrow \theta$。  
   - 目标网络用于计算贝尔曼目标值，短期内保持不变。

3. **经验回放缓冲区（Replay Buffer）**  
   - 创建一个固定容量的队列 $\mathcal{D}$，用于存储交互样本 $(s,a,r,s')$。

4. **超参数设置**  
   - 学习率 $\eta$  
   - 折扣因子 $\gamma$  
   - ε-greedy 探索率 $\epsilon$（初始值）  
   - 最小训练样本数阈值 $N_{\min}$  
   - 每次训练的小批量大小 $B$  
   - 目标网络同步频率 $C$（梯度更新次数间隔）

---

#### 2. 与环境交互并存储经验

在每个时间步 $t$：  

1. **动作选择**  
   $$
   a_t = 
     \begin{cases}
       \text{随机动作} & \text{以概率 }\epsilon,\\
       \arg\max_a Q(s_t,a;\theta) & \text{以概率 }1-\epsilon.
     \end{cases}
   $$

2. **环境反馈**  
   执行动作 $a_t$，得到奖励 $r_t$ 和下一个状态 $s_{t+1}$。  （**需预先定义奖励函数**）

3. **存入缓冲区**  
   将元组 $(s_t, a_t, r_t, s_{t+1})$ 存入 Replay Buffer $\mathcal{D}$。  
   如果 $\mathcal{D}$ 已满，则丢弃最早的样本。

---

#### 3. 批量随机采样并训练

当缓冲区样本数 $\ge N_{\min}$ 时，每隔一次或多次环境交互，就进行一次训练更新：

1. **随机抽取小批量**  
   从 $\mathcal{D}$ 中随机采样 $B$ 条过往经验：  
   $$
     \{(s_i, a_i, r_i, s'_i)\}_{i=1}^B
   $$

2. **计算贝尔曼目标**  
   对每条样本，用**目标网络** $\theta^-$ 计算：  
   $$
   y_i = r_i + \gamma \max_{a'}Q(s'_i, a'; \theta^-)
   $$
   算的是：当前获得的即时奖励 $r_i$，加上“到了下一个状态后，做最优动作所能拿到的最大预期回报”  

3. **预测当前 Q 值**  
   将当前状态-动作对丢给**主网络** $\theta$，得到预测值：  
   $$
   \hat Q_i = Q(s_i, a_i;\theta)
   $$
   算的是：在当前状态 $s_i$、选了样本里那个动作 $a_i$ 时，网络**现在**估计的价值  

4. **构造损失函数**  
   均方误差（MSE）损失：  
   $$
   L(\theta) = \frac{1}{B}\sum_{i=1}^B\bigl(y_i - \hat Q_i\bigr)^2
   $$

5. **梯度下降更新主网络**  
   $$
     \theta \gets \theta - \eta \nabla_\theta L(\theta)
   $$

---

#### 4. 同步/软更新目标网络

- **硬同步（Fixed Target）**：  
  每做 $C$ 次梯度更新，就执行  
  $$
    \theta^- \gets \theta
  $$

- **（可选）软更新**：  
  用小步长 $\tau\ll1$ 平滑跟踪：  
  $$
    \theta^- \gets \tau \theta + (1-\tau) \theta^-.
  $$

---

#### 5. 重复训练直至收敛

- 重复步骤 2-4 直至满足终止条件（如最大回合数或性能指标）。  
- 训练过程中可逐步衰减 $\epsilon$（ε-greedy），从更多探索过渡到更多利用。



### 示例

#### 假设设定

- **动作空间**：两个动作 $\{a_1,a_2\}$。  

- **状态向量维度**：2 维，记作 $s=(s_1,s_2)$。  

- **目标网络结构**（极简线性网络）：  
  $$
  Q(s;\theta^-) = W^-s + b^-,
  $$

  - $W^-$ 是 $2\times2$ 的权重矩阵  （行数为动作数，列数为状态向量维数）
  - $b^-$ 是长度 2 的偏置向量  

- **网络参数**（假定已初始化并被冻结）：
  $$
    W^- =
    \begin{pmatrix}
      0.5 & -0.2\\
      0.1 & \;0.3
    \end{pmatrix},\quad
    b^- = \begin{pmatrix}0.1\\-0.1\end{pmatrix}.
  $$

- 折扣因子 $\gamma=0.9$。

#### 样本数据

假设我们抽到的一条经验是  
$$
(s_i,a_i,r_i,s'_i) = \bigl((0.0,\;1.0),\;a_1,\;2,\;(1.5,\,-0.5)\bigr).
$$

- 当前状态 $s_i=(0.0,1.0)$，当时选了动作 $a_1$ 并得到奖励 $r_i=2$。  
- 到达新状态 $s'_i=(1.5,-0.5)$。

#### 计算过程

1. **前向计算目标网络输出**  
   $$
   Q(s'_i;\theta^-) 
     = W^-\,s'_i + b^-
     = 
     \begin{pmatrix}
       0.5 & -0.2\\
       0.1 & \;0.3
     \end{pmatrix}
     \begin{pmatrix}1.5\\-0.5\end{pmatrix}
     +
     \begin{pmatrix}0.1\\-0.1\end{pmatrix}
     =
     \begin{pmatrix}
       0.5\cdot1.5 + (-0.2)\cdot(-0.5) + 0.1 \\[4pt]
       0.1\cdot1.5 + \;0.3\cdot(-0.5) - 0.1
     \end{pmatrix}
     =
     \begin{pmatrix}
       0.75 + 0.10 + 0.1 \\[3pt]
       0.15 - 0.15 - 0.1
     \end{pmatrix}
     =
     \begin{pmatrix}
       0.95 \\[3pt]
      -0.10
     \end{pmatrix}.
   $$
   因此，
   $$
     Q(s'_i,a_1;\theta^-)=0.95,\quad
     Q(s'_i,a_2;\theta^-)= -0.10.
   $$

2. **取最大值**  
   $$
     \max_{a'}Q(s'_i,a';\theta^-)
     = \max\{0.95,\,-0.10\}
     = 0.95.
   $$

3. **计算目标 $y_i$**  
   $$
     y_i
     = r_i + \gamma \times 0.95
     = 2 + 0.9 \times 0.95
     = 2 + 0.855
     = 2.855.
   $$

---

这样，我们就得到了 **DQN** 中训练主网络时的"伪标签"  
$y_i=2.855$，后续会用它与主网络预测值 $Q(s_i,a_i;\theta)$ 计算均方误差，进而更新 $\theta$。



## 改进DQN：

#### 一、构造 n-step Transition

1. **维护一个长度为 n 的滑动队列**  

   - 每步交互（状态 → 动作 → 奖励 → 新状态）后，都向队列里添加这条"单步经验"。  
   - 当队列中积累到 n 条经验时，就可以合并成一条"n-step transition"了。

2. **合并过程（一步一步累加）**  

   - **起始状态**：取队列里第 1 条记录中的状态 $s_t$  

   - **起始动作**：取第 1 条记录中的动作 $a_t$  

   - **累积奖励**：把队列中前 n 条经验的即时奖励按折扣因子 $\gamma$ 一步步加权累加：  
     $$
     G_t^{(n)} = r_t + \gamma\,r_{t+1} + \gamma^2\,r_{t+2} + \cdots + \gamma^{n-1}r_{t+n-1}
     $$

3. **形成一条新样本**  
   最终你得到一条合并后的样本：
   $$
   \bigl(s_t,\;a_t,\;G_t^{(n)},\;s_{t+n},\;\text{done}_{t+n}\bigr)
   $$
   然后把它存入主 Replay Buffer。  
   **接着**，把滑动队列的最早一条经验丢掉，让它向前滑一格，继续接收下一步新经验。

#### 二、批量随机采样与训练

1. **随机抽取 n-step 样本**  

   - 训练时，不管它是来自哪一段轨迹，都从 Replay Buffer 里随机挑出一批已经合好的 n-step transition。  
   - 每条样本就封装了"从 $s_t$ 出发，执行 $a_t$，经历 n 步后所累积的奖励加 bootstrap"以及到达的末状态。

2. **计算训练目标**  

   对于每条抽出的 n-step 样本  
   $(s_t,a_t,G_t^{(n)},s_{t+n},\text{done}_{t+n})$，  

   - 如果 $\text{done}_{t+n}=\text{False}$，则  
     $$
       y = G_t^{(n)} + \gamma^n\,\max_{a'}Q(s_{t+n},a';\theta^-);
     $$

   - 如果 $\text{done}_{t+n}=\text{True}$，则  
     $$
     y = G_t^{(n)}.
     $$

3. **主网络给出预测**  

   - 把样本中的起始状态-动作对 $(s_t,a_t)$ 丢给在线的 Q 网络，得到当前估计的 $\hat{Q}(s_t,a_t)$。

4. **更新网络**  

   - 用"目标值 $y$"和"预测值 $\hat{Q}$"之间的平方差，构造损失函数。  
   - 对损失做梯度下降，调整在线网络参数，使得它的预测越来越贴近那条合并后的真实回报。



## VDN

**核心思路**：将团队 Q 函数写成各智能体局部 Q 的线性和 $Q_{tot}=\sum_{i=1}^{N}\tilde{Q}_i$，在训练时用全局奖励反传梯度，在执行时各智能体独立贪婪决策。



CTDE 指 *Centralized Training, Decentralized Execution* —— **在训练阶段使用集中式的信息或梯度（可以看到全局状态、联合奖励、各智能体的隐藏变量等）来稳定、加速学习；而在执行阶段，每个智能体只依赖自身可获得的局部观测来独立决策**。

采用 CTDE 的好处：

部署高效、可扩展：运行时每个体只需本地观测，无需昂贵通信和同步，适合**大规模**或通信受限场景。

降低非平稳性：每个智能体看到的“环境”里不再包含 **其他正在同时更新的智能体**——因为所有参数其实在**同一次**反向传播里被一起更新，整体策略变化保持同步；对单个智能体而言，环境动态就不会呈现出随机漂移。

避免“懒惰智能体”：只要某个行动对团队回报有正贡献，它在梯度里就能拿到正向信号，不会因为某个体率先学到高收益行为而使其他个体“无所事事”。



### 核心公式与训练方法

1. **值分解假设**
   $$
   Q\bigl((h_1,\dots,h_d),(a_1,\dots,a_d)\bigr)\;\approx\;\sum_{i=1}^{d}\,\tilde{Q}_i(h_i,a_i)
   $$

   其中 $h_i$ 为第 $i$ 个智能体的历史观测，$a_i$ 为其动作。每个 $\tilde{Q}_i$ 只使用局部信息；训练时通过对联合 $Q$ 的 TD 误差求梯度，再"顺着求和"回传到各 $\tilde{Q}_i$ 。这样既避免了为各智能体手工设计奖励，又天然解决了联合动作空间呈指数爆炸的问题。

2. **Q-learning 更新**
   $$
   Q_{t+1}(s_t,a_t)\;=\;(1-\eta_t)\,Q_{t}(s_t,a_t)\;+\;\eta_t\bigl[r_t+\gamma\max_{a}Q_{t}(s_{t+1},a)\bigr]
   $$

   论文沿用经典 DQN 的 Q-learning 目标，对 **联合 Q 值** 计算 TD 误差，然后按上式更新；全局奖励 $r_t$ 会在反向传播时自动分摊到各 $\tilde{Q}_i$ 。

### 训练过程

使用LSTM:**让智能体在**「只有局部、瞬时观测」**的环境中**记住并利用过去若干步的信息。

#### 1. 初始化  

|        组件        |                             说明                             |
| :----------------: | :----------------------------------------------------------: |
|    **在线网络**    | 为每个智能体 $i=1\ldots d$ 建立局部 $Q$ 网络 $\widetilde Q_i(h^i,a^i;\theta_i)$。最后一层是 **值分解层**：把所有 $\widetilde Q_i$ 相加得到联合 $Q=\sum_i\widetilde Q_i$ |
|    **目标网络**    | 为每个体复制参数：$\theta_i^- \leftarrow \theta_i$，用于计算贝尔曼目标。 |
| **经验回放缓冲区** | 存储元组 $(h_t, \mathbf a_t, r_t, o_{t+1}) \rightarrow \mathcal D$，其中 $\mathbf a_t=(a_t^1,\dots,a_t^d)$。 |
|     **超参数**     | Adam 学习率 $1\times10^{-4}$，折扣 $\gamma$，BPTT 截断长度 8，Eligibility trace $\lambda=0.9$ ；小批量 $B$、目标同步周期 $C$、$\varepsilon$-greedy 初始值等。 |

> **网络骨架**：Linear (32) → ReLU → LSTM (32) → Dueling (Value + Advantage) 头产生 $\widetilde Q_i$ 。  

---

#### 2. 与环境交互并存储经验  

0. **局部隐藏状态更新（获得 $h_t^i$）**  
   - **采样观测**  
     $o_t^i \in \mathbb R^{3\times5\times5}$（RGB × 5 × 5 视野）  
   - **线性嵌入 + ReLU**  
     $x_t^i = \mathrm{ReLU}(W_o\,\text{vec}(o_t^i)+b_o),\; W_o\!\in\!\mathbb R^{32\times75}$  
   - **递归更新 LSTM**  
     $h_t^i,c_t^i = \text{LSTM}_{32}(x_t^i,\;h_{t-1}^i,c_{t-1}^i)$  
     （初始 $h_0^i,c_0^i$ 置零；执行期只用本体状态即可）  

1. **动作选择（分散执行）**  
   $$
     a_t^i=\begin{cases}
       \text{随机动作}, & \text{概率 } \varepsilon,\\
       \arg\max_{a}\widetilde Q_i(h_t^i,a;\theta_i), & 1-\varepsilon.
     \end{cases}
   $$

2. **环境反馈**：执行联合动作 $\mathbf a_t$，获得单条 **团队奖励** $r_t$ 以及下一组局部观测 $o_{t+1}^i$。  

   - **重要**：此处不要直接把 $h_{t+1}^i$ 写入回放池，而是存下 $(h_t^i, a_t^i, r_t, o_{t+1}^i)$。  
     之后在训练阶段再用同样的“Step 0” 方式，离线地把 $o_{t+1}^i\rightarrow h_{t+1}^i$。  
     这样可避免把梯度依赖塞进经验池。  

3. **写入回放池**：$(h_t, \mathbf a_t, r_t, o_{t+1}) \rightarrow \mathcal D$。

---

#### 3. 批量随机采样并联合训练  

对缓冲区达到阈值后，每次更新步骤：

1. **采样** $B$ 条长度为 $L$ 的序列。  

   - 假设抽到第 $k$ 条序列的第一个索引是 $t$。

   - 依次取出连续的 $(h_{t+j}, a_{t+j}, r_{t+j}, o_{t+j+1}), j=0, \ldots, L-1$。

   - 先用存储的 $o_{t+j+1}$ 离线重放"Step 0"得到 $h_{t+j+1}$，这样序列就拥有 $(h_{t+j}, h_{t+j+1})$ 

    

2. **前向计算**  
   $$
   \hat Q_i^{(k)} = \widetilde Q_i(h^{i,(k)}_t,a^{i,(k)}_t;\theta_i),
     \quad
     \hat Q^{(k)}=\sum_{i}\hat Q_i^{(k)} .
   $$

3. **贝尔曼目标（用目标网络）**  
   $$
   y^{(k)} = r^{(k)} + \gamma \sum_{i}\max_{a}\widetilde Q_i(h^{i,(k)}_{t+1},a;\theta_i^-).
   $$

4. **损失**  
   $$
     L=\frac1B\sum_{k=1}^{B}\bigl(y^{(k)}-\hat Q^{(k)}\bigr)^2 .
   $$

5. **梯度反传（自动信用分配）**  
   因为 $\hat Q=\sum_i\widetilde Q_i$，对每个 $\widetilde Q_i$ 的梯度系数恒为 1，  
   整个 **团队 TD 误差** 直接回流到各体网络，无需个体奖励设计 。

6. **参数更新**：$\theta_i \leftarrow \theta_i-\eta\nabla_{\theta_i}L$。

---

#### 4. 同步 / 软更新目标网络  

- **硬同步**：每 $C$ 次梯度更新后执行 $\theta_i^- \leftarrow \theta_i$。  
- **软更新**：可选 $\theta_i^- \leftarrow \tau\theta_i+(1-\tau)\theta_i^-$。

---

#### 5. 重复直到收敛  

持续循环步骤 2–4，逐步衰减 $\varepsilon$。  
训练完成后，**每个体只需本地 $\widetilde Q_i$ 就能独立决策**，与中心最大化 $\sum_i\widetilde Q_i$ 等价 。



