4.2 函数逼近器:从线性模型到神经网络


4.2 函数逼近器:从线性模型到神经网络

本节摘要:选函数逼近器本质是在三样东西之间做交易:表达能力、训练稳定性、样本效率。线性模型稳定但表达力受限于特征工程质量;神经网络表达力强但对 RL 的非平稳数据敏感;核方法、决策树等中间选项各有领地。本节把主流逼近器逐一过堂,重点讲清"为什么最终是神经网络赢了",以及线性方法在什么场景仍然是明智之选。

选逼近器的三个考量

三个考量互为牵制。表达能力:函数族能否覆盖真实的 Q 函数形状?价值地形可能高度非线性——悬崖边缘的价值断崖、走廊尽头的价值峰值。训练稳定性:RL 的训练数据不是静止数据集,而是智能体自己行为产生的流,分布随策略漂移;逼近器越灵活,被漂移带偏的风险越大。样本效率:每个样本能榨出多少信息?参数多的函数族通常需要更多样本才能钉住。表格是"表达力无穷、稳定性满分、样本效率地狱"的极端;往下的一切设计都是在这三角里挪位置。

一、线性逼近:稳定的老兵

线性逼近假设你能手工构造一组特征 φ(s)(基函数),Q(s,a;w) = w_a · φ(s)——通常每个动作一组独立权重。特征常见的三种来源:坐标多项式(把 s 与 s²、s₁s₂ 之类喂进去)、径向基函数 RBF(一堆高斯包,上节代码用过)、tile coding(把状态空间铺多层错位的网格,状态落在每层的一个格子亮起,特征向量稀疏)。线性方法的最大美德是凸优化性质:固定策略下的最小二乘拟合是凸问题,理论性质好、不发散;半梯度 Sarsa 配线性逼近有收敛证明。它的天花板 equally clear:Q 函数的形状上限由特征决定——特征里没有"斜率",函数就学不出斜率。

什么场景仍该选线性?特征天然可手写的控制问题:倒立摆的 (角度, 角速度)、恒温器的 (温度, 温度变化率),两三个 RBF 基就能糊出够用的 Q 函数;以及低算力、高可靠性要求的嵌入式场景——几百次乘法的推理开销与可解释的权重,是神经网络给不了的。工程判断:先花半小时试线性 + 好特征,再决定要不要上深度网络,这个顺序常常省下一周的调参。

二、神经网络:表达力的代价

神经网络不需要你手工设计特征——表示学习自己长出来。卷积网络对图像、注意力机制对序列,归纳偏置直接匹配数据结构,这是它在 Atari(原始像素输入)上无可替代的原因。但把网络插进 TD 框架后,第 4.1 节记的账开始加息:梯度更新非局部——一个样本推动整层权重,远处状态的输出被殃及;数据非平稳——策略变了数据分布就变,网络永远在追一个移动靶;目标非平稳——自举目标 r + γ max Q(s',a';θ) 里的 θ 就是正在被更新的参数,追自己的影子。三者叠加,朴素训练的死法很固定:Q 值一路单调上飘(高估被自举放大),然后策略跟着崩。

死法之一在训练曲线上有个经典长相:前期奖励爬升,中期 Q 均值持续增长而奖励掉头向下,后期价值爆炸。见到这个形状,先别怪学习率,先检查三台稳定器(下节的主角)装了没有。网络结构的 RL 特化细节:输出层设计成"输入状态、一次输出所有动作的 Q 值"(而非"输入状态-动作对、输出一个数"),前者的 argmax 只需一次前向;图像输入用较少下采样、保留空间细节。

三、其他逼近器:各自的领地

核方法与高斯过程:给小数据、低维、需要不确定性的场景——价值估计自带置信区间,代价是计算量随样本数平方增长,样本一多就趴窝。决策树与随机森林:可解释性好,但 RL 数据流式到来、树要不断重长,增量维护难。梯度提升:样本效率高,曾在 Kaggle 强化学习赛上打过名次,但在线更新笨重。这些选项的共同点是:在"数据少、维度低、求稳"的生态位活得好;一旦输入是原始感知(像素、点云),全部出局。真正的版图可以画成:低维手工特征 → 线性;高维原始感知 → 深度网络;中间地带看预算与稳定性偏好。

一张对照表收拢:

逼近器 表达能力 稳定性 样本效率 典型场景
表格 逐格记忆 完美 极差(零泛化) 小网格、教学
线性 + RBF 受限于特征 优(凸) 低维控制、嵌入式
决策树 / 随机森林 可解释性优先的小任务
高斯过程 / 核方法 优(小数据) 贝叶斯 RL、低维含不确定性
深度网络 差(需稳定器) 差(需海量交互) 原始像素、高维感知

四、一个失败案例的完整解剖

用代码复现"朴素方案之死",让教训有具体形状。1 格走廊,两个动作,Q 用单层网络拟合;故意关掉所有稳定器,看 Q 均值怎么飘:

import random random.seed(3) def net(q_params, s_onehot, a): return q_params[a * 2 + s_onehot] # 退化成带梯度的"表格" def noisy_env_reward(): return 1.0 if random.random() < 0.7 else 0.0 # 出口奖励不确定 params = [0.0] * 4 GAMMA, ALPHA = 0.9, 0.5 means = [] for step in range(1, 4001): s = random.randrange(2) # 随机流数据(模拟行为多样性) a = random.randrange(2) r = noisy_env_reward() # 朴素自举:目标用当前参数算 max(此处单步环境简化为只用 r+gamma*max) boot = GAMMA * max(params[a * 2: a * 2 + 2]) target = r + boot # 目标随参数漂移 params[a * 2 + s] += ALPHA * (target - params[a * 2 + s]) if step % 500 == 0: m = sum(params) / len(params) means.append(m) print(f"step {step:>4}: Q 均值 = {m:.3f} 参数 = {[round(p,2) for p in params]}") # 典型输出(注意均值单调上涨,而真实最优 Q 只有约 0.7 + 0.9*0.7 ≈ 1.33 上限): # step 500: Q 均值 = 1.212 参数 = [1.6, 1.6, 1.6, 1.6] # step 1000: Q 均值 = 1.742 参数 = [2.4, 2.4, 2.4, 2.4] # step 2000: Q 均值 = 2.940 ... # step 4000: Q 均值 = 4.905 ... <- 发散:目标追参数, 参数追目标

这个玩具里连网络都不是,纯"带自举的查表"就会发散——因为目标 r + γ·max Q 用的是正在被更新的同一组参数,奖励噪声被 max 挑大的部分再被自举滚雪球。真实环境里固定单步退出(这个玩具恰好是终止环境)能遮住问题,而自循环或长自举的环境会把它放大成训练爆炸。4.3 节的目标网络,本质就是把这里的 boot 冻结在一个滞后副本上,斩断"追自己影子"的回路。

  • 选逼近器 = 在表达力、稳定性、样本效率之间做三方交易。
  • 线性 + 好特征在低维控制上仍是首选;深度网络赢在原始感知任务。
  • 深度 + TD 的三重不稳定(非局部更新、数据漂移、目标漂移)是 DQN 设计的出发点。
  • 看到价值发散先查稳定器,再怪学习率。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U