1. 完整流水线总览
核心任务:把一张 87 × 58 像素的深度图编码成一个 32D 的隐向量 depth_latent,让下游策略网络能直接用这个紧凑表征来理解前方地形,而不必处理原始的几千个像素。
核心观点
把 5046 像素压成 32D 不是"单一网络在算",而是三段流水线协作:
- CNN 段:从原始像素中找"局部视觉概念"(边缘、角、平地……)
- MLP 段:把分散在各位置的局部信息融合压缩成全局表征
- GRU 段:累积过去多步深度信息,时序平滑
机器人前方的相机看到了下面这样一片场景。每个像素的值 = 那条光线击中障碍物的距离(米)。
机器人前方的深度图(示意)— 每个像素是个距离数值
关键挑战:网络拿到的不是这张图片,而是 5046 个原始数字。它必须自己学会"哪些数字组合在一起意味着'有障碍'"。这就是 CNN 要解决的事。
3. 第 1 层 Conv2d(1→32, k=5):找 32 种局部 pattern
Conv2d 卷积层就像一组 32 个放大镜。每个放大镜是一个 5×5 的小窗口,里面存着一个"我要找的 pattern"。这个放大镜会在整张图上从左到右、从上到下滑动一遍,每滑到一个位置就检查"这块区域是不是匹配我要找的 pattern"。
3.1 单个放大镜在干什么
放大镜定义"上方有负权重、下方有正权重" → 在"上远下近"的位置激活强
3.2 32 个放大镜并行扫一遍,产生 32 张激活图
每个放大镜在整张图扫一遍,产生一张激活图。32 个放大镜 = 32 张激活图。
Conv2d 这一层做了什么
把"5046 个原始距离数字"翻译成"32 种基础视觉概念,在图中哪里出现"。这一步是 "原始像素 → 局部 pattern 检测"。
放大镜里的具体数值(权重)是网络训出来的 —— 没人告诉它"放大镜 #1 该长成水平边缘检测器",是 PPO/DAgger 的梯度自动塑造出来的。
4. 第 2 层 MaxPool2d(2):缩小图,保留最强信号
MaxPool 比 Conv 简单得多 —— 它没有任何参数,纯粹是个"取最大值"的操作。每 2×2 块只保留最大值,于是图缩小一半。
MaxPool 这一层做了什么
- 省计算:图变小一半,后续运算量也减半
- 平移容忍:障碍偏一两个像素,下采样后激活图几乎不变
- 保留强信号:"只要 2×2 内有匹配点,就算这块匹配了"
5. 第 3 层 Conv2d(32→64, k=3):组合 pattern 找更复杂的概念
这一层和第 1 层结构一样,但作用对象不同:它不是在原始深度图上找 pattern,而是在前面 32 张激活图的组合上找更高级的 pattern。
第 2 层 Conv2d 做了什么
把"32 种基础视觉概念的空间分布"组合成"64 种更高级的概念"。CNN 越深的层 = 越抽象的语义。这就像人类视觉皮层的层级处理:V1 找边缘 → V2 找形状 → V4 找物体。
输出 shape: (64, 25, 39) —— 64 个通道,每个通道是 25×39 的激活图。
5.1 25 和 39 是怎么算出来的
6. 第 4 层 Flatten:从图像 → 一维向量
Flatten 是个纯 reshape 操作,没有参数、不学习。它把 (64, 25, 39) 的 3D 张量按顺序排成一根 62400 维的长向量。
7. 第 5/6 层 Linear:全局信息压缩
到了 Linear 层,数据已经是 62400 维向量,**包含了所有空间位置上 64 种高级概念的激活强度**。Linear 做的事是把这些散布在各位置的信息融合成一个全局摘要。
7.1 Linear(62400 → 128) 在干什么
7.2 Linear(128 → 32) 最终压缩
再来一次 Linear,把 128 维压成 32 维。这一步是最后的"语义提炼":
MLP 这两层做了什么
把 CNN 提取出的"分布在各空间位置的高级视觉特征"(62400 维)融合压缩成对决策有用的紧凑表征(32 维)。这一步是从"视觉感知"过渡到"决策准备"的桥梁。
参数量主要集中在 Linear(62400→128) 这一层(~800 万),是整个 DepthEncoder 最重的部分。
8. RecurrentDepthBackbone:时序融合
到目前为止我们处理的都是单帧深度图。但机器人是连续运动的,多帧深度图含有时序信息(比如障碍物接近的速度),单帧丢失这部分。所以最后加一段 GRU 做时序融合。
8.1 RecurrentDepthBackbone 的内部结构
8.2 GRU 的核心思想:一个会记忆的盒子
GRU 这一段做了什么
- 时序平滑:单帧深度的瞬态噪声(某像素跳一下)被多帧融合后平均掉
- 运动感知:通过对比当前 vs 上一帧,隐含编码出"障碍物接近速度"
- 记忆持续:即便某一帧深度严重受干扰,GRU hidden state 还保存着前几帧的"理解",行为不会跳变
实战中:你训练完后跑 play,机器人在某些复杂地形下能展示出"提前预判"的行为 —— 这就是 GRU 时序记忆的功劳。
9. 参数量对比:为什么不能用纯 MLP 处理深度图
有人会问:MLP 理论上能逼近任何函数,为什么处理深度图不直接用 MLP?答案是参数量爆炸 + 没有空间归纳偏置。
9.1 为什么 CNN 参数少还更有效
| 纯 MLP 的问题 | CNN 的优势 |
| 每个像素位置都有独立权重,不共享 |
同一个 5×5 放大镜在所有位置共享权重 |
| 把 5046 个像素当 5046 个独立数字处理,不知道哪两个像素是邻居 |
卷积只看局部 5×5 邻域,天然利用空间结构 |
| 图像稍微平移,激活模式完全不同,必须重新学 |
权重共享 + 局部感受野 → translation invariance,平移后输出几乎不变 |
| 需要海量数据才能学到"边缘"这种基本概念 |
归纳偏置自带"局部 pattern 假设",少量数据就能学好 |
10. 类比:人类视觉皮层的层级处理
DepthEncoder 的"CNN + MLP + GRU"架构和人类视觉系统的处理方式高度同构。这不是巧合 —— CNN 本身就是从视觉皮层研究里得到灵感。
设计哲学的同构
无论是人脑还是机器学习网络,处理高维感知信号的最有效方式都是"低级特征 → 局部组合 → 全局抽象 → 时序整合"这条流水线。这是一个被生物进化和机器学习研究双重验证的好结构。
12. 一句话回顾
| 层 | 做的事 | 类比 |
Conv2d(1→32, k=5) | 在原始深度图上扫 32 种局部 pattern | V1 检测边缘 |
MaxPool2d(2) | 缩小图,保留强信号 | 视觉信息粗略化 |
Conv2d(32→64, k=3) | 组合低级 pattern 成 64 种高级概念 | V2/V4 组合形状 |
Flatten | 把 3D 张量摊平成 1D 向量 | 接口转换 |
Linear(62400→128) | 全局信息融合压缩 | 高级皮层抽象 |
Linear(128→32) | 最终对接 Actor 期待格式 | 决策准备 |
combination_mlp + GRU + output_mlp | 融合本体观测 + 时序累积 → 32D depth_latent | 短时记忆 + 决策 |
本文聚焦 DepthEncoder 的内部机制
评论区
使用 GitHub 账号登录后即可评论(由 GitHub Discussions 驱动)