资讯动态

小策略集下的Minimax Regret:不确定MDP鲁棒决策实战

发布时间:2026/8/30 1:53:35 来源:尧图企业网站定制
在机器人控制、库存管理和算法策略上线这类场景里最让人头疼的往往不是“结果不确定”而是“连估计用的概率都不确定”。标准强化学习通常假设马尔可夫决策过程MDP中的转移概率已知可实际工程中我们拿到的要么是有限样本估计值要么是离线收集的历史数据。模型一换策略就崩这在工业界太常见了。如果要在这种“参数本身不可靠”的环境里做决策一个自然思路是鲁棒 MDP假设真实模型落在一个不确定性集合内然后选一个在最坏情况下表现最好的策略。但“最坏情况最优”也有问题它可能过度保守导致策略在绝大多数常见场景里都偏弱。于是很多研究者开始转向另一个决策标准Minimax Regret也就是最小化最大遗憾。它要回答的不是“最坏情况下我能拿多少”而是“在真实模型未知的前提下我的策略和那个事后诸葛亮最优策略相比还差多少”。这篇文章会讲清楚三件事Minimax Regret 在不确定 MDP 里的目标函数究竟长什么样为什么把候选策略集限制成一个小集合反而有理论价值和工程价值以及如何用一份可运行的 Python 代码骨架把“优化最小最大遗憾”这件事落地到自己的实验里。读完以后你可以直接复用这套流程去验证自己的策略在参数扰动下到底稳不稳。1. 为什么不确定 MDP 需要 Minimax Regret先回到基础问题。一个标准 MDP 可以写成五元组MDP (S, A, P, r, γ)S状态集合A动作集合P(s|s,a)从状态 s 执行动作 a 后转移到状态 s 的概率r(s,a)状态 s 下执行动作 a 得到的即时奖励γ折扣因子常规强化学习会假设 P 是已知的。大多数算法也只是在样本中去估计这个 P然后基于估计结果做规划。问题在于当 P 有误差时最优策略往往会发生剧烈变化。尤其在一些安全敏感任务里一个小的估计偏差可能导致策略完全失效。不确定 MDPUncertain MDP就是为了解决这个问题。它不再假设 P 是一个固定值而是假设真实模型 P* 落在某个集合 U 中这个集合被称为不确定性集合。决策者知道的是P* ∈ U但不知道具体是 U 中的哪一个。在这种设定下有两种常见决策标准。第一种是最小化最坏情况成本也就是 Robust MDP 常用的思路min_{π} max_{P ∈ U} V_P(π)它保证策略在 U 中最差的那个模型里也能达到一定的表现。这种做法在理论上很干净但在实际业务中往往会得到过于保守的策略。因为真实世界里的坏模型通常不会以 100% 概率出现如果你总是按最坏模型去设计策略那在正常工况下就很可能损失性能。第二种就是 Minimax RegretRegret_U(π) max_{P ∈ U} [ V_P(π_P^*) - V_P(π) ]其中π_P^* argmax_{π ∈ Π_all} V_P(π)理解起来很简单如果真实模型是 P那么存在一个“事后最优策略” π_P^*。如果你的策略 π 在这个模型下拿到 80 分而事后最优策略能拿到 100 分差距就是 20。真实模型越未知这个差距越难控制。Minimax Regret 要做的就是选一个策略让“最坏情况下的事后悔恨”尽量小。这个标准的现实意义非常直观。做库存管理时你不会只关心最坏需求下能不能活下来更希望自己的补货策略和“如果早知道真实需求就采用的补货策略”相比损失不至于太大。做动态定价时也一样你既不是纯乐观也不是纯保守而是希望在“模型没猜准”时依然能输得不太难看。所以我的判断是在实际工程决策中Minimax Regret 往往比纯鲁棒优化更符合业务直觉。它天然带着“估值错误后的担责”意识也是分布鲁棒优化和相关领域近几年的研究热点。2. 不确定 MDP 与 Minimax Regret 的核心概念理解 Minimax Regret 之前必须先理解两个概念不确定性集合 U 和策略空间 Π。2.1 不确定性集合 U不确定性集合是鲁棒决策的灵魂。它刻画了“真实模型可能出现在什么位置”。常见构造方式包括集合类型定义特点区间集合每个转移概率落在一个区间内简单直观但忽略了概率之间的相关性范数球以名义模型为中心限制距离控制扰动幅度常见 L1/L2 范数KL 散度球限制与名义模型的 KL 散度适合统计意义上的置信区域数据驱动集合由经验分布周围的置信区间生成更贴合离线数据场景对于实际项目最常用的是“区间集合”和“L1 范数球”。区间集合的好处是便于解释每个参数都能直接看到上下界L1 范数球的好处是理论上容易分析而且在概率单纯形上做投影也方便。值得注意的是不确定性集合并不是越宽越好。集合越宽说明你对模型的信心越低策略也会越保守集合太窄又可能把真实模型排除在外。比较好的做法是用统计置信区间来标定 U 的宽度比如根据历史样本量计算转移概率的置信范围。2.2 策略空间与事后最优策略策略空间是所有可能策略组成的集合。在标准强化学习里策略空间是巨大的可以是所有从状态到动作分布的映射。但在 Minimax Regret 目标中你需要回答一个问题在某个模型 P 下最优策略到底是什么为了定义 regret我们总是需要“事后最优策略”作为参照物。对某个固定模型 P可以求解一个普通 MDP得到 π_P^。这个策略在理论上可以任意复杂但实际计算中我们并不一定需要显式求出它只需要得到它对应的价值函数 V_P^。所以整个 Minimax Regret 问题的内部结构是外循环候选策略 π 内循环不确定性集合中的每个模型 P 参照值每个 P 下的最优价值 V_P^*这个结构和普通强化学习完全不同。普通强化学习只需要优化一个目标函数而 Minimax Regret 需要同时考虑“模型的坏”和“策略的相对损失”。2.3 为什么不能把 min 和 max 直接交换很多读者第一次看到 Minimax Regret 时会想当然地以为它和 Robust MDP 差不多可以直接交换 min 和 max。其实不行。在 Robust MDP 里目标函数是min_π max_P V_P(π)它的最优策略可以理解为“在 U 中挑一个对我不利的模型然后我来防守”。在 Minimax Regret 里目标函数是min_π max_P [ V_P(π_P^*) - V_P(π) ]最坏模型会自动变化。同一个 π 在模型 P1 下可能拿到 90 分在模型 P2 下可能只拿到 60 分而事后最优值的差距也随 P 变化。这意味着即使你找到一个比较保守的策略它也不能只靠“压制坏模型下的价值”来取胜还必须保证在其他模型下不至于损失太多。所以 Minimax Regret 的核心难点恰恰在于策略必须同时兼顾多个候选模型中的表现差异。这也让它在理论上比 Robust MDP 更有意思在计算上更困难。3. “策略集要小”到底在说什么标题里最容易被忽略的是 “Small Sets of Policies”。为什么策略集要小很多人第一反应是少一点策略求解更快。这个理解部分正确但远不是全部。3.1 小策略集的工程动机在实际部署中我们不会把一个神经网络策略直接裸奔上线。更常见的做法是用离线数据训练一批候选策略做评估、审计、灰度然后只放行风险最低的那个。这时候“策略集”就是人工准备好的候选列表Π̂ { π_1, π_2, ..., π_K }K 可以很小比如 5、10、20。这个集合里的每个策略可以是不同风格的人工规则也可以是不同训练阶段产出的模型甚至可以是不同调参组合下的策略。为什么说小策略集是优势因为 Minimax Regret 是一个需要“枚举或近似枚举所有模型-策略组合”的问题。策略空间越大计算代价越高审计难度也越高。当你把候选策略限制成一个小集合时你可以对每个策略做详尽的模型扰动测试甚至可以逐条解释每个策略在哪些模型下表现好、在哪些模型下后悔值高。这对于安全审查和业务解释非常友好。3.2 小策略集里的“包围”问题但小策略集也有一个致命风险如果 Π̂ 里根本没有接近最优的策略那就算你在这个小集合里选了最小遗憾策略它和全局最优策略相比也可能差很远。这就像你只带了三把螺丝刀去维修一台机器如果真正需要的型号不在其中你怎么选都是错。所以小策略集的设计准则不是“少”而是“用尽量少的策略去覆盖不确定性集合中的关键行为模式”。好的候选策略集通常会包含非常保守的策略比如高成本触发维护的策略非常激进的策略比如尽量不干预、靠低动作频率盈利的策略几个中间策略用于覆盖不同的干扰场景。这样定义出来的 Π̂虽然只有几个元素但能撑起一个比较完整的决策边界。3.3 数学上有意义的限制从理论角度“小策略集”也带来了可分析性提升。当 Π̂ 是有限集合Minimax Regret 优化问题就退化为一个有限的枚举问题π^* argmin_{π ∈ Π̂} max_{P ∈ U} [ V_P(π_P^*) - V_P(π) ]这个形式虽然仍然是双层优化但外层的枚举工作量只有 |Π̂| 个候选。真正剩下的难点是内层要在 U 上做 max。如果 U 也是有限集或离散采样集那么整个问题就能用最朴素的方式精确求解。这也是这篇论文标题的策略性所在不追求在全策略空间上求解 Minimax Regret而是把注意力放到“小策略集”上用有限候选策略换取计算可行性。这种思路在工程落地中非常有价值因为先解决“算得动”的问题才有资格谈“算得准”。4. 核心流程从不确定性集到策略选择下面我把整个优化流程拆成五步。这套流程无论你是做 MDP 研究还是做实际强化学习项目都可以复用。4.1 第一步构造不确定性集合 U先根据离线数据或业务经验确定名义转移概率矩阵 P0。然后围绕 P0 构造不确定性集合。如果采用 L1 范数球数学形式是U { P : ||P - P0||_1 ≤ ε, P 满足概率分布条件 }其中 ε 是扰动半径。在代码里你可以通过随机扰动 P0再把每一行归一化生成一组候选转移矩阵import numpy as np def generate_uncertainty_set(P0, eps, K5, seed42): rng np.random.default_rng(seed) nS, nA, _ P0.shape U [] for _ in range(K): P P0.copy() for s in range(nS): for a in range(nA): noise rng.uniform(-eps, eps, nS) row P[s, a] noise row np.maximum(row, 0.0) row row / row.sum() P[s, a] row U.append(P) return U这里需要注意的是噪声不要加得过大否则归一化后的概率离 P0 太远可能超出你的业务容忍范围。4.2 第二步准备候选策略集 Π̂候选策略可以来自多个来源基于规则的经验策略独立训练得到的多个强化学习模型对已有策略做微调后产生的变体。在小策略集模式下建议 K 不超过 10。候选策略必须是确定性策略或者固定分布策略这样你才能在某个固定模型下非常准确地求出价值函数。4.3 第三步计算每个候选模型下的最优价值函数 V_P^这一步其实是在解决一个常规 MDP 规划问题。对 U 中的每个 P使用值迭代或策略迭代求出最优价值函数def optimal_value(P, r, gamma0.95, theta1e-8): nS, nA, _ P.shape V np.zeros(nS) for _ in range(10000): Q np.zeros((nS, nA)) for s in range(nS): for a in range(nA): Q[s, a] r[s, a] gamma * np.dot(P[s, a, :], V) V_new Q.max(axis1) if np.max(np.abs(V_new - V)) theta: return V_new V V_new return V如果你使用的是连续状态或大规模状态空间可以替换为近似动态规划或离线强化学习评估方法但原理相同先得到“事后最优”的基准。4.4 第四步计算每个候选策略在 U 上的遗憾对每个候选策略 π、每个模型 P评估它的价值函数 V_P(π)然后和 V_P^* 做差Regret(π) max_P [ V_P^* - V_P(π) ]这一步是整个流程的核心。如果不确定性集合 U 是连续的无法直接枚举你可以使用采样、梯度优化或轻量级搜索技术来逼近最坏模型。但是“先枚举、后取 max”仍然是解释问题最基础的方式。4.5 第五步选出最小遗憾策略最后在候选策略集 Π̂ 里直接比较每个 π 的 Regret 值取最小的那个作为最终决策。这个流程之所以工程友好是因为每一步都很透明。你可以随时看到某个策略在某个模型下后悔了多少甚至可以画一张“候选策略 × 候选模型”的遗憾热力图让业务方直接参与决策。5. 用 Python 实现一个小型 Minimax Regret 选择器下面我给出一个完整的最小实现。这个例子不是为了演示大规模求解而是为了说明“小策略集 有限不确定性集”下的精确求解流程。运行环境只需要 Python 3.8 和 NumPy。5.1 完整代码假设状态数 S2动作数 A2。状态 0 表示正常状态 1 表示故障动作 0 表示不干预动作 1 表示维修。奖励矩阵按业务习惯设定正常运行有正收益维修有成本故障有惩罚。import numpy as np # 文件路径minimax_regret_mdp.py class MDPValueSolver: def __init__(self, P, r, gamma0.95): self.P P self.r r self.gamma gamma self.nS P.shape[0] self.nA P.shape[1] def evaluate_policy(self, policy, theta1e-8): V np.zeros(self.nS) for _ in range(10000): V_new np.zeros(self.nS) for s in range(self.nS): a policy[s] V_new[s] self.r[s, a] self.gamma * np.dot( self.P[s, a, :], V ) delta np.max(np.abs(V_new - V)) V V_new if delta theta: break return V def optimal_value(self, theta1e-8): V np.zeros(self.nS) for _ in range(10000): Q np.zeros((self.nS, self.nA)) for s in range(self.nS): for a in range(self.nA): Q[s, a] self.r[s, a] self.gamma * np.dot( self.P[s, a, :], V ) V_new Q.max(axis1) if np.max(np.abs(V_new - V)) theta: break V V_new return V def create_demo_uncertainty_set(): # 名义模型正常运行概率较高 P0 np.array([ [[0.90, 0.10], [0.80, 0.20]], [[0.00, 1.00], [0.60, 0.40]] ]) # 扰动模型1维修效果较差 P1 np.array([ [[0.85, 0.15], [0.75, 0.25]], [[0.00, 1.00], [0.40, 0.60]] ]) # 扰动模型2故障率整体偏高 P2 np.array([ [[0.80, 0.20], [0.70, 0.30]], [[0.00, 1.00], [0.50, 0.50]] ]) return [P0, P1, P2] def main(): r np.array([ [10.0, 5.0], [-50.0, -2.0] ]) gamma 0.95 U create_demo_uncertainty_set() # 小策略集3个确定性策略 policies { 不干预: np.array([0, 0]), 总是维修: np.array([1, 1]), 故障才修: np.array([0, 1]) } # 1. 对每个模型计算事后最优价值 best_values [] for P in U: solver MDPValueSolver(P, r, gamma) best_values.append(solver.optimal_value()) # 2. 对每个候选策略计算遗憾 print(候选策略在不同模型下的遗憾) results {} for policy_name, policy in policies.items(): regret_over_models [] for idx, P in enumerate(U): solver MDPValueSolver(P, r, gamma) V_pi solver.evaluate_policy(policy) regret np.max(best_values[idx] - V_pi) regret_over_models.append(regret) print(f{policy_name} 在模型{idx 1}下的遗憾 {regret:.4f}) results[policy_name] max(regret_over_models) # 3. 选择最小遗憾策略 best_policy min(results, keyresults.get) print(\n每个候选策略的最坏遗憾) for name, regret in results.items(): print(f{name}: {regret:.4f}) print(f\n最终选择{best_policy}) if __name__ __main__: main()5.2 关键逻辑解释这段代码分为三个层次。第一个层次是 MDPValueSolver。它封装了策略评估和最优价值求解。这个类是整个流程的底座因为无论哪个候选模型进来都需要用值迭代求出 V_P^* 和 V_P(π)。第二个层次是不确定性集合的构造。这里采用的是“离散枚举”方式。我把 U 拆成了三个显式模型名义模型、维修效果偏差模型、整体故障率偏高模型。这样做的好处是代码直观方便对照验证。第三个层次是遗憾计算与策略选择。对每个候选策略我遍历 U 中的所有模型分别计算遗憾再取最大值作为该策略的“最坏遗憾”。最终在所有候选策略里选择最坏遗憾最小的那个。5.3 运行方式在命令行执行python minimax_regret_mdp.py不需要额外安装第三方库NumPy 是唯一依赖。如果你还没有 NumPypip install numpy6. 运行结果分析与效果验证运行脚本后你会在控制台看到两部分信息每个策略在每个模型下的遗憾以及最终选择结果。6.1 预期结果判断对于上面这个设备维护示例比较符合直觉的结果是单一“不干预”策略会在故障率高的模型下后悔值很大单纯“总是维修”策略会在正常运行为主的模型下后悔值偏大而“故障才修”策略更可能在所有模型下都拿到比较均衡的遗憾。你不需要照搬这个结论关键是判断逻辑是正确的。你应该能看到最终选择的策略恰好是那个在所有候选策略里最坏遗憾最小的一个。6.2 验证方法验证一个 Minimax Regret 决策是否合理可以从三个角度检查。第一检查最优价值函数是否一致。如果某个模型的 V_P^* 明显低于其他模型说明这个模型本身很“差”它的遗憾值天然容易被放大。这是正常的。第二检查候选策略是否存在支配关系。如果某个策略在所有模型下的价值都高于另一个策略那低价值策略不应该被选中。如果有这种情况建议调整候选策略集。第三做敏感性分析。你可以把扰动模型的数量从 3 个扩大到 10 个观察最终选择是否发生变化。如果变化很大说明候选策略集的覆盖度不够需要补充更具差异性的策略。6.3 失败排查如果运行后某个策略的遗憾出现负数几乎可以肯定是价值函数计算逻辑出了问题。遗憾的定义是 V_P^* - V_P(π)其中 V_P^* 是整个策略空间中最优价值因此它一定大于等于 V_P(π)。出现负数多半是值迭代没有收敛或者策略评估时使用了错误的模型参数。另外如果所有候选策略的遗憾都一样说明模型扰动范围太小或者候选策略差异不够大。这时应该放宽 U 的扰动半径或者重新设计策略集。7. 常见问题与排查思路在实际写代码和做实验时下面几个问题出现概率很高。问题现象可能原因排查方式解决方案某项遗憾为负数最优价值函数与策略评估使用了不同模型检查代码中 P 是否被意外修改优先保存原始 P评估时用副本所有策略遗憾几乎一样不确定性集合太小或策略差异太小打印 V_P^* 和 V_P(π) 看差距增大扰动半径重新设计策略集计算时间过长U 中模型数量太多或状态空间过大分析瓶颈在 V_P^* 在线计算使用缓存或先对 U 抽样最终策略在真实环境中表现不佳不确定性集合不贴合真实分布对比真实环境数据与 U 的覆盖范围用统计置信区间重新标定 U候选策略覆盖不足“故障才修”等中间策略缺失查看遗憾热力图加入更多中间策略或随机策略值迭代不收敛折扣因子 γ 过大或奖励尺度异常检查 V 的更新趋势适当降低 γ 或统一奖励数值范围对于第七八节问题最重要的是先搞清楚“到底是算错了还是候选集设计得不好”。把这两个问题分开工作流会清晰很多。8. 工程落地与最佳实践建议Minimax Regret 不只是理论模型。在实际项目中它特别适合那些模型更新频繁、业务方对“策略为什么这么做”要求很高的场景。比如动态定价、库存补货、风控决策、运维调度等。下面是我实际落地这类方案时的几条建议。8.1 用置信区间去校准不确定性集合很多团队做鲁棒优化最大的错误是随便拍一个扰动半径。更好的做法是用转移概率估计的置信区间构造 U。比如名义转移概率是从 1000 条样本估计出来的那方差就比较小如果只有 50 条样本U 就应该更宽。一个简单公式是ε c / sqrt(n)其中 n 是用于估计转移概率的样本数量c 是根据置信水平选择的常数。虽然这个公式比较粗糙但在早期实验中足够用。8.2 候选策略要“风格迥异”而不是“参数微调”小策略集的核心价值是覆盖不确定性。如果你的候选策略之间只是学习率不同那它们大概率会在同一类模型上表现相似。真正应该做的是保证行为风格差异有一个极保守有一个极激进再有几个中间档。这样你才能通过 Minimax Regret看哪种风格在模型的未知扰动中最扛得住。8.3 先离线跑完再考虑在线优化第一次实现时不需要上大规模优化器。用有限离散的 U把所有策略都算一遍先建立“模型-策略-遗憾”三张表。这个表本身就有很大的决策价值。你觉得你理解了模型敏感度之后再考虑把它扩展到连续扰动集和更大策略空间。8.4 保留审计能力工业环境里最终选择的策略不一定是最优遗憾最小也可能是遗憾最小但行为最难解释。这时候建议把“遗憾热力图”附带在决策报告里。业务方关心的是这个策略在哪种模型下最可能后悔后悔会有多大。这些信息恰好是 Minimax Regret 流程里天然产出的不用额外开发。9. 总结值得继续深入的方向这篇内容表面上讲的是一个理论问题不确定 MDP 下如何用小策略集优化 Minimax Regret。实际上它传递的是一套更通用的工程思维当模型不可靠、参数会漂移、上线要审计时应该把问题建模成“和事后最优之间的差距”来优化而不是单点追求最优或单点追求最坏。如果你接下来想往深处走比较有价值的方向有三个。第一个是连续不确定性集合上的 regret 优化从有限枚举过渡到凸优化或在线优化第二个是大规模状态空间下如何用强化学习做策略候选生成让小策略集里的每个成员都更有代表性第三个是数据驱动的不确定性集构造如何从离线数据中精确估计出“足够诚实”的 U。建议先把这篇文章中的最小实现跑一遍把“模型-策略-遗憾”表做出来。你会明显感觉到相比直接训练一个策略然后祈祷模型没估计错这种“先列出后悔上限、再选策略”的路径在真实业务里踏实得多。收藏备用后面做鲁棒策略上线时一定能用上。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价