本节摘要:医疗、金融、工业控制里,让未训练的智能体在线试错的代价是事故,不是日志里的一行失败记录。离线强化学习(Offline RL)只许用一份固定数据集训练,训练全程与环境零交互。核心障碍是分布偏移:策略一旦偏出数据集覆盖的动作区域,Q 值靠外推凭空膨胀,贪心策略会一头扎向这些虚假高分。解法是一个统一思想——保守:只在数据支持的区域相信外推。本节讲清病根、代表性药方(BCQ、CQL)与选型判断。
先把问题说狠一点。前七章的一切算法(DQN、PPO)都以"可以反复调用环境"为前提,这条前提在真实世界大量场景里不成立:医疗方案的试错以健康为代价,自动驾驶的试错以安全为代价,推荐系统的新策略试错直接烧真实流量。可每个领域又都囤着海量历史数据——医生的治疗记录、司机的驾驶日志、平台的用户行为流水。离线强化学习的问题陈述因此极简:**只有数据集 D = {(s, a, r, s')},不许再问环境,学一个好策略。**它与传统批模式(batch RL)、"从日志学习"是同义的不同叫法。
一个有用的基准对照是行为克隆(⟦undefined⟧ 节的主角):直接监督学习地模仿数据里的 (s → a) 映射。BC 简单稳定,但只能学到数据策略的水平,且误差会累积(自己偏了没人拉回来)。离线 RL 的野心高一级:从次优甚至多策略混杂的数据里,提炼出比数据来源更强的策略——这正是它难的原因,也是它值钱的原因。
回忆 Q-Learning 的目标 r + γ max Q(s',·)。在线训练时,max 指向的动作下一刻就会被尝试,真实回报会纠正错误的乐观;离线训练时,数据集里没出现的动作永远得不到纠正,而神经网络的性质恰恰是"对没见过的输入也会给出确定输出"——没被数据惩罚过的 (s, a) 组合,Q 网络凭训练分布的外推随口报价,且报价普遍虚高(没有负样本拉低它)。max 挑的就是这些虚高报价。于是训练循环:max 抓住外推高分 → 目标被抬高 → 回归把整片 Q 都顶高 → max 抓更高的——雪球滚成发散。更糟的是学出的策略会系统性偏爱"数据里几乎没出现过"的动作,部署时暴露在真实环境里即刻翻车。
一个可动手的小实验复现这个病。环境:两臂老虎机,数据集只记录了大量臂 0 与极少臂 1 的经验,臂 1 真实更差但样本少:
import random random.seed(2) # 造离线数据集:臂0 500 条(真均值 0.5),臂1 仅 3 条(真均值 0.4) data = [(0, random.gauss(0.5, 0.2)) for _ in range(500)] data += [(1, r) for r in (random.gauss(0.4, 0.2) for _ in range(3))] # 朴素表格式 Q 估计 + "外推膨胀"模拟:未见组合按样本量打折地悲观……不,朴素法不悲观 Q = {} for a in (0, 1): rs = [r for aa, r in data if aa == a] Q[a] = sum(rs) / len(rs) # 3 条样本的标准误是 sigma/sqrt(3) ≈ 0.115,均值的抽签运气可能把臂1 顶到 0.6+ for trial in range(5): small = [random.gauss(0.4, 0.2) for _ in range(3)] print(f"臂1 三样本的一次抽签均值: {sum(small)/3:.3f}") print(f"臂0 的 Q: {Q[0]:.3f}(500 条, 标准误 0.009, 稳定)") # 典型输出: # 臂1 三样本的一次抽签均值: 0.612 # 臂1 三样本的一次抽签均值: 0.295 # ...(五次里有两三次高于 0.5)
小样本臂的均值估计方差巨大,好运气抽签会让它在 max 比较里胜出——在线场景下这个错误下一秒就被纠正,离线场景下它直接写进最终策略。这个玩具把"外推膨胀"的机制缩印到了能看清的尺寸;神经网络的连续外推只是把同一机制放大到任意动作区域。
统一的药方思想一句话:**别相信数据不支持的东西。**具体实现分两副面孔。
**面孔一:约束动作,别出数据圈。**代表 BCQ:学一个生成模型枚举"数据里可能出现过的动作",Q 评估只在名单内进行——外推区域直接不进门。等价于把 max 的候选集从全动作空间缩到数据支持集。实现要点是生成模型的覆盖度:名单漏了好动作就永远错过,名单混进坏动作又退化回原病。
**面孔二:压低分布外动作的 Q 值,别乱报高价。**代表 CQL(保守 Q 学习):在标准 TD 损失外加一项正则,专门压低"数据没采样到的动作"的 Q 值,让 Q 在数据分布内贴合真实、在分布外系统性悲观:
L_CQL = L_TD + α · E_{sD, a任意} [ Q(s,a) ] − E_{s,a~D} [ Q(s,a) ]
读法:第一项把"任意动作"(尤其分布外的)的 Q 往下拽,第二项把"数据里真实发生过的"的 Q 往上托,α 控制悲观程度。悲观不会丢失最优性——真动作数据里出现过、会被托住;虚高动作没数据撑腰、被压下去——max 再也抓不到稻草。α 是核心旋钮:太小保守不足(外推膨胀复发),太大退化成行为克隆(什么都悲观到不敢选)。IQL 是另一条务实路线:完全避开动作查询,用 expectile 回归从数据里直接估"更好的价值",连 max 都不显式做,工程上最省心。
离线评估是落地时最容易被忽略的一环:没有环境,怎么知道学得好不好?常见做法是拟合一个离线策略评估器(重要性采样或双倍稳健估计量),或先在仿真器里做离线训练的全流程验证再上真实系统——这一步的成本预算要在项目一开始就留出来。
三副药方里 IQL 最值得单独展开,因为它干脆绕开了"查询分布外动作"这个危险动作。做法分两步。第一步,学两个价值函数:V(s) 用 expectile 回归拟合"数据里能见到的较好水平"(expectile 参数 τ 取 0.7 到 0.9,τ 越大越偏乐观侧),Q(s,a) 用普通 TD 回归到 r + γV(s')。第二步,策略提取:对数据里出现过的 (s,a),用加权回归逼近"Q 减 V 为正的动作"——优势越大的动作权重越高,等价于在数据支持范围内做一次软贪心。全程没有任何一处对数据外动作取 max 或显式估值,外推膨胀无从发生。它的代价与边界同样清楚:τ 偏低时策略退化到接近行为克隆,偏高时又悄悄回到"高估数据内的罕见动作";策略提取只能在数据覆盖的动作里挑,真正的好动作若从没在数据里出现过,IQL 与 BC 一样无能为力。工程上它的吸引力在实现简单与超参少——多数离线项目的第一版都值得从 IQL 起步,跑通全链路后再按需换 CQL 系。