机器学习复习Day11——月球着陆器(强化学习)
---
type: note
title: 月球着陆器编程作业(DQN)
date: 2026-09-02
description: C3W3 强化学习,Deep Q-Learning(DQN)。①Ex1 建 Q 网络 + target Q 网络(Input(8)→Dense(64,relu)→Dense(64,relu)→Dense(4,linear)),optimizer=Adam。②Ex2 compute_loss:y_targets = rewards + γ·maxQ'·(1−done) 用布尔算术省略 if/else 判断。核心:状态连续多、穷举不完 → Q 表建不出来 → 用神经网络逼近 Q(s,a)。
---
# 2026-09-02 学习笔记
## 笔记区(学的时候随手记)
### 核心观点
**一个 C 强化学习 + 月球着陆器(DQN),干的就一件事:让神经网络替代理一张"建不出来"的 Q 表,来学"怎么把飞船安全降落在月面"。**
月球着陆器 = 教会 agent 在模拟环境里通过不断尝试,学会从状态选动作拿高分。状态是模拟器每步实时给的读数(8 维:位置/速度/角度/角速度/两腿触地),动作是 4 个(不喷/右喷/主喷/左喷),奖励是落地/坠毁/触地等回馈的分数,目标拿到 ≥200 分算通关。
- **最该先搞明白的一件事**:为什么不用 Q 表?——因为**状态是连续的、维度又是 8 个**,穷举不完所有状态组合,表物理上装不下。那就改用一个**神经网络当"近似函数"**,给它状态直接输出 Q 值。
### 关键方法/流程
- **Ex1 建 Q 网络 + target 网络**:结构相同,都是
`Input(8) → Dense(64, relu) → Dense(64, relu) → Dense(4, linear)`,输出 4 个动作各自的 Q 值。
- **Ex2 `compute_loss`(核心 3 行)**:
```python
max_qsa = tf.reduce_max(target_q_network(next_states), axis=-1)
y_targets = rewards + gamma * max_qsa * (1 - done_vals)
loss = MSE(y_targets, q_values)
```
- `max_qsa`:取"下一步"4 个动作里最大的 Q(用 target 网络算,让目标变化慢一点、学得稳)
- `y_targets`:Bellman 公式的"目标值"。`(1-done_vals)` 是布尔算术——回合结束(True=1→0)就只剩 `rewards`,没结束(False=0→1)就加上"下一步的最优"
- `loss`:`MSE` 算 `y_targets` 与 Q 网络预测 `q_values` 的距离,梯度下降去逼近它
### 实战记录
**① 为什么用神经网络逼近 Q 而非建表**
> Q 表会更新但真正症结是**连续状态穷举不完、表装不下**,所以改用网络逼近。
**② `(1 - done_vals)` 精华**
> 相当于是 if/else,True 返回的是 1,那(1 - done_vals)就等于 0,我 y 刚刚好等于回报,False 返回 0,y 就等于 rewards + gamma \* max_qsa 了,相当于是省略了判断。
---
## 代码逐段展开
### Ex1 建 Q 网络 + target 网络 — 干什么
`Input(state_size)` 声明输入形状(8 维状态),两个 `Dense(64, relu)` 学非线性,最后一个 `Dense(4, linear)` 输出 4 个动作的 Q 值。
```python
q_network = Sequential([
Input(shape=state_size), # ← 注意:大写 I
Dense(units=64, activation="relu"),
Dense(units=64, activation="relu"),
Dense(units=num_actions, activation="linear"),
])
target_q_network = Sequential([ # 结构与 q_network 完全一样
Input(shape=state_size),
Dense(units=64, activation="relu"),
Dense(units=64, activation="relu"),
Dense(units=num_actions, activation="linear"),
])
optimizer = Adam(learning_rate=ALPHA)
```
逐行解释:
- `Input(shape=state_size)`:**大写 `Input`**,Keras 的输入层。`state_size=(8,)`,8 维状态。
- `state_size = env.observation_space.shape`:作业里从环境拿到的观测维度。
- `num_actions` = 4(不喷/右喷/主喷/左喷)。
- 两个 `Dense(64, relu)`:64 个神经元、relu 激活,学非线性映射。
- 最后 `Dense(4, linear)`:输出 4 个数,对应 4 个动作的 Q 值,用 `linear`(不压值域,直接当 Q 值)。
- `optimizer = Adam(learning_rate=ALPHA)`:优化器,`ALPHA=1e-3` 学习率。
### Ex2 `compute_loss` — 算 Bellman 目标损失
```python
def compute_loss(experiences, gamma, q_network, target_q_network):
states, actions, rewards, next_states, done_vals = experiences
max_qsa = tf.reduce_max(target_q_network(next_states), axis=-1)
y_targets = rewards + gamma * max_qsa * (1 - done_vals)
q_values = q_network(states)
q_values = tf.gather_nd(q_values, tf.stack([tf.range(q_values.shape[0]),
tf.cast(actions, tf.int32)], axis=1))
loss = MSE(y_targets, q_values)
return loss
```
逐行解释:
- `states, actions, rewards, next_states, done_vals = experiences`:解包一批经验(状态/动作/奖励/下一状态/结束标记)。
- `max_qsa = tf.reduce_max(target_q_network(next_states), axis=-1)`:用 **target 网络**预测"下一步"4 个动作的 Q,取最大的一格(axis=-1 沿每个样本求最大)。
- `y_targets = rewards + gamma * max_qsa * (1 - done_vals)`:Bellman 目标值。
- 回合结束(done=True=1)→ `(1-1)=0` → 那截乘 0 → `y=rewards`,不再加"下一步"(因为已结束)。
- 未结束(done=False=0)→ `(1-0)=1` → 保留 → `y=rewards + γ·maxQ'`,加上"下一步最优"。
- **省略 if/else**:布尔算术一次算整批。
- `q_values = q_network(states)`:Q 网络预测当前状态的 4 个动作值。
- `q_values = tf.gather_nd(q_values, ...)`:按实际采取的动作,**从 4 个里挑出对应的那一个**(`tf.range` 样本索引 + `tf.cast(actions, int32)` 作为列索引,拼成坐标去
## 线索区(学完后合上材料,自问自答)
**Q: 为什么月球着陆器用「神经网络逼近 Q」而不是建一张「Q 表」?**
A: 状态是连续的、维度又多(8 维连续数),所有状态组合穷举不完,表物理上装不下。所以不存表,改让神经网络当"近似函数",输入状态直接输出 Q 值。这就是 DQN 和普通 Q 表的区别。连续维度多、要找到最佳、表装不下。
**Q: `y_targets` 里 `(1 - done_vals)` 是干嘛的?为什么结束时要乘 0?**
A: 布尔算术。done=True=1 → (1-1)=0 → 那截被乘没,y=rewards(回合结束,没有下一步最优可加);done=False=0 → (1-0)=1 → 保留,y=rewards+γ·maxQ'。用减法代替 if/else,一次对整批样本算。
**Q: 为什么用 target 网络算 max_qsa,而不是直接用 Q 网络?**
A: 目标值一直在变会震荡。单独一个 target 网络让目标变化慢一点,学得稳。
**Q: 为什么最后一层用 linear 不用 relu/sigmoid?**
A: 输出的是 Q 值(要当数值比较大小),不是概率。linear 不压值域,直接输出。
---
## 总结(50 字以内)
月球着陆器 DQN:连续状态多、穷举不完 → 用神经网络逼近 Q(s,a)。Ex1 建 Q 网络+target,Ex2 算 Bellman 目标损失,`1−done` 用布尔算术省略 if/else。
---
## 复习卡片
| 概念 | 一句话 | 我的场景 |
| -------------- | ---------------------------------- | ------------------ |
| DQN vs Q 表 | 连续状态穷举不完 → 网络逼近 Q | 月球着陆器 |
| 状态/动作/奖励 | 模拟器读数 / 4 喷气 / 落地回馈 | 8 维状态、4 动作 |
| y_targets | rewards + γ·maxQ'·(1−done) | Bellman 目标值 |
| 1−done | 布尔算术省 if/else | 结束只留 rewards |
| 目标网络 | 单独 Q 让目标变化慢,稳 | 防震荡 |
| tf.gather_nd | 按动作从 4 个 Q 挑对应一个 | 需要预测的那格 |
- `loss = MSE(y_targets, q_values)`:目标值 vs 预测值的均方误差,用来反向传播更新 Q 网络。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)