资讯动态

多目标强化学习与规划实战指南:从调参困境到帕累托前沿

发布时间:2026/10/21 5:06:43 来源:尧图企业网站定制
多目标强化学习与规划这个方向我最早接触是因为一个实际需求训练一个智能体同时兼顾跑得快和能耗低两个指标结果发现传统的单目标强化学习根本没法处理——奖励函数里两个目标的权重怎么调都不对调高速度权重能耗就爆表调高能耗权重智能体干脆躺平不动了。后来翻了不少资料才找到这篇《A Practical Guide to Multi-Objective Reinforcement Learning and Planning》读完之后很多困惑迎刃而解。这篇文章我反复读了几遍也把里面的方法在实际项目中做了验证下面把我对这篇指南的理解和实操心得完整梳理出来。1. 为什么单目标强化学习在多目标场景下会失效1.1 从一个怎么调权重都不对的案例说起先说说我踩过的坑。当时的需求是让一个移动智能体在模拟环境中从A点走到B点要求同时优化两个目标到达时间尽量短、能量消耗尽量低。按照惯常做法我把奖励函数设计成R -w1 * time - w2 * energy然后开始调w1和w2。调参过程非常痛苦。当w11, w20.1时智能体确实跑得快但能耗高得离谱几乎全程加速再急刹当w10.1, w21时智能体学会了磨洋工慢悠悠地走能耗是低了但到达时间完全不可接受。中间试了十几组权重要么偏向一边要么两边都不理想。这个问题的本质在于单目标强化学习通过标量化把多个目标压缩成一个标量奖励这个压缩过程会丢失目标之间的权衡信息。你用一组权重训练出来的策略只能对应帕累托前沿上的一个点或者一个很小的区域想要覆盖不同的偏好就得重新训练。更麻烦的是权重和实际表现之间的关系往往是非线性的你以为调了权重就能精确控制权衡实际上根本不是那么回事。1.2 标量化方法的根本局限标量化方法也就是把多目标加权求和变成单目标之所以在多目标场景下力不从心核心原因有三个。第一帕累托前沿的形状可能非凸。如果帕累托前沿是非凸的那么线性加权的方法根本无法覆盖前沿上的某些区域。这不是调参能解决的问题而是方法本身的数学局限。打个比方就像你用一根直尺去贴合一条弯曲的曲线无论怎么摆放直尺总有一些弯曲的部分贴不上。第二权重与偏好之间没有直观对应关系。你设w10.7, w20.3以为意味着70%重视目标一30%重视目标二但实际训练出来的策略可能完全不是这个比例。因为奖励的尺度不同、梯度动态不同权重的实际效果很难预测。第三每次改变偏好都需要重新训练。在实际应用中决策者往往需要在不同偏好下查看不同的方案。比如给我看看最省能量的方案再给我看看最快到达的方案有没有折中的。如果每换一个偏好就要重新训练一次模型计算成本和时间成本都不可接受。这篇指南明确指出多目标强化学习的核心目标不是找到一个最优解而是找到一组代表帕累托前沿的策略集合让决策者可以根据实际需求从中选择。这个思路的转变非常关键。1.3 多目标强化学习的问题形式化在正式进入方法之前有必要把问题定义说清楚。多目标强化学习通常建模为多目标马尔可夫决策过程MOMDP可以用一个元组来表示MOMDP (S, A, P, R, γ)其中 S 是状态空间A 是动作空间P 是状态转移概率γ 是折扣因子。和标准MDP的区别在于奖励 R 不再是一个标量而是一个向量R(s, a) [r1, r2, ..., rn]每个分量对应一个优化目标。智能体的目标是找到一个策略 π使得在多个目标上的累积回报向量 V^π [V1^π, V2^π, ..., Vn^π] 尽可能好。但尽可能好在多目标场景下需要重新定义——这里用的是帕累托支配的概念如果策略 π1 在所有目标上都不差于 π2且至少在一个目标上严格优于 π2则称 π1 帕累托支配 π2。不被任何其他策略支配的策略称为帕累托最优策略。所有帕累托最优策略对应的回报向量集合构成帕累托前沿。理解这几个概念是读懂后续方法的基础。我一开始觉得这些定义很抽象但当你真正面对两个方案各有优劣、无法直接比较的情况时帕累托支配的概念就非常自然了。2. 这篇指南覆盖的核心方法体系2.1 基于单策略的方法一次训练一个偏好指南中首先介绍的是单策略方法Single-Policy Methods。这类方法的目标是给定一个偏好向量训练出一个对应的最优策略。听起来和标量化方法差不多但关键区别在于它们通常能更好地处理非凸帕累托前沿。代表性的方法包括加权切比雪夫方法不是简单的线性加权而是最小化与理想点之间的切比雪夫距离。这种方法可以覆盖非凸前沿的部分区域。加权范数方法通过调整范数参数来控制对不同目标的重视程度。约束优化方法把一个目标作为主目标其他目标作为约束条件。这类方法的优点是实现相对简单可以直接复用现有的单目标强化学习算法比如PPO、DQN等只需要修改奖励的计算方式。但缺点也很明显每换一个偏好就需要重新训练一次。我在实际项目中的体会是如果你的应用场景中偏好是固定的比如产品上线后就是速度优先能耗其次那么单策略方法完全够用而且实现成本最低。但如果你需要给决策者展示多种方案单策略方法就不太合适了。2.2 基于多策略的方法一次训练多个偏好多策略方法Multi-Policy Methods是这篇指南的重点也是多目标强化学习最有价值的方向。这类方法的目标是一次训练得到一个策略集合能够覆盖帕累托前沿的不同区域。常见的多策略方法包括外层循环方法在训练过程中不断调整偏好向量每次用不同的偏好训练一个策略最终得到一个策略集合。可以理解为多次运行单策略方法但共享部分计算。多目标Q学习维护一个Q值向量而不是标量Q值通过帕累托支配关系来更新。多目标策略梯度方法直接优化策略参数使得策略能够适应不同的偏好输入。条件网络方法训练一个以偏好向量为输入的神经网络输出对应的策略。这样一次训练就能覆盖多个偏好。条件网络方法是我个人最推荐的方向。它的核心思想很直观把偏好向量作为网络的额外输入网络学会根据不同的偏好输出不同的动作。训练时每次从偏好空间中随机采样一个偏好向量然后按照这个偏好来计算奖励并更新网络。训练完成后你只需要改变输入的偏好向量就能得到不同的策略行为不需要重新训练。这里有一个实操中的关键细节偏好采样的策略会显著影响最终策略集合的质量。如果只在偏好空间的几个固定点上采样训练出来的策略集合可能覆盖不全。我通常采用的方法是在训练初期使用均匀采样保证覆盖面在训练后期逐渐聚焦到帕累托前沿附近的偏好区域提高精度。2.3 规划方法在多目标场景下的适配指南中还有一个重要章节专门讨论多目标规划Multi-Objective Planning。规划和强化学习的区别在于规划通常假设环境模型已知或者可以学习到然后通过搜索或动态规划来找到最优策略。在多目标场景下规划方法需要处理的核心问题是如何在一个状态上维护多个帕累托最优值。标准的值迭代或策略迭代算法需要被扩展使得每个状态维护的不是一个标量值而是一个帕累托前沿集合。具体来说多目标值迭代的更新规则大致是这样的对于每个状态 s 对于每个动作 a 计算 Q(s,a) R(s,a) γ * V(s) 其中 V(s) 是一个帕累托前沿集合 将所有动作的 Q(s,a) 集合合并取帕累托前沿 更新 V(s) 为合并后的帕累托前沿这个过程的计算复杂度比单目标值迭代高不少因为帕累托前沿集合的大小可能随着迭代增长。实际实现时通常需要做剪枝去掉被支配的值控制集合大小。指南中提到了几种剪枝策略包括精确剪枝只保留帕累托最优的值计算量较大但结果精确。近似剪枝允许一定程度的支配换取计算效率。聚类剪枝将相近的值合并减少集合大小。我在一个小规模规划任务中试过精确剪枝状态空间不大的时候完全可行。但状态空间一大帕累托前沿集合就会爆炸这时候必须用近似方法。2.4 方法选择速查表为了帮助大家快速判断哪种方法适合自己的场景我整理了一个对照表方法类型适用场景训练成本偏好灵活性实现难度线性标量化偏好固定、帕累托前沿凸低无低加权切比雪夫偏好固定、前沿可能非凸低无低外层循环多策略偏好数量有限中低中多目标Q学习离散动作、小规模中中中条件网络连续动作、偏好多变高高高多目标规划模型已知、状态空间小低高中这张表是我根据指南内容和自己的实操经验总结的不一定适用于所有情况但可以作为一个初步的选型参考。3. 实操中最容易踩的五个坑3.1 奖励尺度不统一导致训练不稳定这是我最开始做多目标强化学习时踩的第一个坑。两个目标的奖励数量级差了很多倍——速度相关的奖励在0到1之间能耗相关的奖励在0到1000之间。结果训练出来的策略几乎完全被能耗目标主导速度目标形同虚设。解决方案在计算多目标奖励之前先对每个目标的奖励做归一化。常用的方法包括最小-最大归一化把每个目标的奖励缩放到[0, 1]区间。标准化减去均值、除以标准差。基于经验的归一化用训练过程中观察到的奖励范围来动态调整。我通常用的是最小-最大归一化简单直接。但要注意归一化的参数需要在训练前估计好或者用滑动窗口动态更新。如果归一化参数估计不准反而会引入新的问题。3.2 偏好采样策略不当导致覆盖不全前面提到过偏好采样的问题这里展开说一下。我见过不少实现偏好向量只在几个固定值上采样比如[0.1, 0.9]、[0.5, 0.5]、[0.9, 0.1]。这样训练出来的策略集合只能覆盖帕累托前沿上的三个点中间的区域完全是空的。正确的做法是在偏好空间中进行连续采样。对于两个目标的情况可以从Dirichlet分布中采样对于更多目标可以用单纯形上的均匀采样。训练过程中可以逐渐缩小采样范围聚焦到帕累托前沿附近的区域。还有一个细节偏好向量通常需要满足归一化条件即所有分量之和为1。这是为了保证不同偏好之间的可比性。如果你的实现中没有做归一化可能会导致某些偏好被系统性地忽略。3.3 帕累托前沿的可视化与评估被忽视多目标强化学习的一个独特之处在于你很难用一个数字来评价策略的好坏。单目标强化学习可以直接看累积奖励但多目标场景下你需要看整个帕累托前沿的质量。指南中提到了几个评估指标超体积帕累托前沿与参考点围成的体积越大越好。分布均匀性前沿上的点是否均匀分布。覆盖范围前沿是否覆盖了所有可能的权衡区域。我在实际项目中的做法是训练过程中定期计算超体积指标用它来监控训练进展。同时把帕累托前沿画出来直观地检查分布情况。很多时候数字指标看起来不错但画出来一看前沿上有一大块空白区域这就是采样策略需要调整的信号。3.4 条件网络的偏好输入方式有讲究如果你选择条件网络方法偏好向量的输入方式会显著影响效果。常见的做法有几种直接拼接把偏好向量直接拼接到状态向量后面一起输入网络。超网络用一个小的网络根据偏好向量生成主网络的参数。条件归一化用偏好向量来调制网络中间层的归一化参数。我试过直接拼接和条件归一化两种方式。直接拼接实现简单但在偏好维度较高时效果会下降。条件归一化的效果更好但实现复杂度也更高。指南中建议如果偏好维度不超过4维直接拼接通常够用如果维度更高建议考虑条件归一化或超网络。3.5 训练不收敛时的排查思路多目标强化学习的训练比单目标更容易出现不收敛的情况。我总结了一个排查清单检查奖励归一化不同目标的奖励尺度是否统一检查偏好采样偏好向量是否覆盖了足够的范围是否做了归一化检查网络结构偏好向量的输入方式是否合理网络容量是否足够检查超参数学习率、折扣因子、批量大小是否适合多目标场景检查帕累托前沿训练过程中帕累托前沿是否在持续改善如果停滞不前可能是探索不足。这个清单我基本每次调试都会过一遍能解决大部分常见问题。4. 从零实现一个多目标强化学习Demo4.1 环境选择与任务定义为了让大家能快速上手我用一个简单的连续控制任务来演示。这个任务是一个简化的移动智能体场景智能体在一个二维平面上移动需要同时优化两个目标——到达目标点的速度和路径的平滑度。环境的具体设定如下状态空间智能体的位置(x, y)和速度(vx, vy)共4维。动作空间二维加速度(a_x, a_y)范围[-1, 1]。目标一尽快到达目标点奖励为距离的负值。目标二路径尽量平滑奖励为加速度变化量的负值。这个任务足够简单可以在普通电脑上快速训练同时又能体现多目标权衡的核心特点。4.2 条件网络的核心实现下面是条件网络的核心代码结构用PyTorch实现import torch import torch.nn as nn class PreferenceConditionedNetwork(nn.Module): def __init__(self, state_dim, action_dim, pref_dim, hidden_dim256): super().__init__() # 偏好编码器 self.pref_encoder nn.Sequential( nn.Linear(pref_dim, 64), nn.ReLU(), nn.Linear(64, 64), nn.ReLU() ) # 主网络输入为状态 偏好编码 self.backbone nn.Sequential( nn.Linear(state_dim 64, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), ) # 策略头输出动作均值和对数标准差 self.mean_head nn.Linear(hidden_dim, action_dim) self.log_std_head nn.Linear(hidden_dim, action_dim) def forward(self, state, preference): pref_feat self.pref_encoder(preference) x torch.cat([state, pref_feat], dim-1) feat self.backbone(x) mean self.mean_head(feat) log_std self.log_std_head(feat).clamp(-20, 2) return mean, log_std这个网络的关键设计点偏好编码器把偏好向量映射到一个64维的特征空间而不是直接拼接。这样做的好处是网络可以学习偏好之间的非线性关系。对数标准差裁剪把log_std限制在[-20, 2]之间防止标准差过大或过小导致训练不稳定。共享主干状态和偏好特征在主干网络中融合让网络能够学习到在不同偏好下同样的状态应该采取不同的动作。4.3 多目标奖励的计算与归一化奖励计算和归一化的实现如下class MultiObjectiveReward: def __init__(self, reward_dim2): self.reward_dim reward_dim # 用滑动窗口估计每个目标的奖励范围 self.running_min np.full(reward_dim, np.inf) self.running_max np.full(reward_dim, -np.inf) self.alpha 0.01 # 滑动窗口更新系数 def update_stats(self, reward_vec): self.running_min (1 - self.alpha) * self.running_min \ self.alpha * np.minimum(self.running_min, reward_vec) self.running_max (1 - self.alpha) * self.running_max \ self.alpha * np.maximum(self.running_max, reward_vec) def normalize(self, reward_vec): range_ self.running_max - self.running_min 1e-8 return (reward_vec - self.running_min) / range_ def scalarize(self, reward_vec, preference): # 加权切比雪夫标量化 normalized self.normalize(reward_vec) weighted preference * normalized return np.min(weighted) 0.1 * np.sum(weighted)这里用的是加权切比雪夫标量化而不是简单的线性加权。公式中的0.1 * np.sum(weighted)是一个小的正则项用来在切比雪夫距离相同的情况下优先选择各目标更均衡的解。这个技巧在指南中也有提到实测下来对帕累托前沿的分布均匀性有改善。4.4 训练循环与偏好采样训练循环的核心逻辑def train_episode(env, network, optimizer, reward_calc, pref_sampler): state env.reset() log_probs [] rewards [] preferences [] # 采样一个偏好向量 pref pref_sampler.sample() done False while not done: state_tensor torch.FloatTensor(state).unsqueeze(0) pref_tensor torch.FloatTensor(pref).unsqueeze(0) mean, log_std network(state_tensor, pref_tensor) std log_std.exp() dist torch.distributions.Normal(mean, std) action dist.sample() log_prob dist.log_prob(action).sum(dim-1) next_state, reward_vec, done, _ env.step(action.detach().numpy()[0]) reward_calc.update_stats(reward_vec) log_probs.append(log_prob) rewards.append(reward_vec) preferences.append(pref) state next_state # 计算标量化后的回报 scalar_rewards [reward_calc.scalarize(r, p) for r, p in zip(rewards, preferences)] # 计算折扣回报并更新网络 returns compute_returns(scalar_rewards, gamma0.99) loss compute_policy_loss(log_probs, returns) optimizer.zero_grad() loss.backward() optimizer.step() return loss.item()偏好采样器的实现class PreferenceSampler: def __init__(self, dim2, focus_ratio0.0): self.dim dim self.focus_ratio focus_ratio # 聚焦采样的比例 def sample(self): if np.random.random() self.focus_ratio: # 聚焦采样在偏好空间中心附近采样 pref np.random.dirichlet(np.ones(self.dim) * 5) else: # 均匀采样覆盖整个偏好空间 pref np.random.dirichlet(np.ones(self.dim)) return preffocus_ratio这个参数控制聚焦采样的比例。训练初期设为0保证均匀覆盖训练后期可以逐渐增加到0.5左右提高帕累托前沿附近的精度。4.5 训练结果与帕累托前沿分析训练完成后我通常会用一组均匀分布的偏好向量来评估策略集合然后画出帕累托前沿。评估的代码大致如下def evaluate_pareto_front(network, env, reward_calc, n_points20): front [] for i in range(n_points): # 生成均匀分布的偏好 w i / (n_points - 1) pref np.array([w, 1 - w]) # 用该偏好运行一个episode total_reward np.zeros(2) state env.reset() done False while not done: state_tensor torch.FloatTensor(state).unsqueeze(0) pref_tensor torch.FloatTensor(pref).unsqueeze(0) with torch.no_grad(): mean, _ network(state_tensor, pref_tensor) action mean.numpy()[0] state, reward_vec, done, _ env.step(action) total_reward reward_vec front.append((pref, total_reward)) return front把结果画出来之后你会看到一条曲线横轴是目标一的累积回报纵轴是目标二的累积回报。理想情况下这条曲线应该是平滑的、覆盖范围广的。如果曲线上有明显的断点或者聚集说明偏好采样或者网络结构需要调整。我在实际测试中发现条件网络方法在偏好维度为2时效果很好帕累托前沿覆盖均匀。但当偏好维度增加到4时直接拼接的方式开始出现覆盖不全的问题需要改用条件归一化或者增加网络容量。5. 多目标强化学习的实际应用场景5.1 资源调度中的多目标权衡多目标强化学习在资源调度领域有天然的应用场景。比如在一个计算集群中调度任务需要同时优化任务完成时间、资源利用率和能耗。这三个目标之间往往存在冲突提高资源利用率可能会延长某些任务的完成时间降低能耗可能会牺牲性能。用多目标强化学习的方法可以训练一个调度策略集合让运维人员根据当前的业务需求选择合适的策略。比如在业务高峰期选择完成时间优先的策略在业务低谷期选择能耗优先的策略。这种灵活性是单目标方法无法提供的。5.2 推荐系统中的多目标优化推荐系统是另一个典型的多目标场景。一个推荐策略需要同时考虑用户点击率、停留时长、多样性和新鲜度等多个指标。这些指标之间也存在权衡过度追求点击率可能导致推荐内容同质化影响用户体验。条件网络方法在这里特别适用因为推荐系统的偏好可能会根据用户群体、时间段、业务目标等因素动态变化。训练一个条件网络然后根据实时需求调整偏好向量比维护多个单目标模型要高效得多。5.3 机器人控制中的多目标规划在机器人控制中多目标规划的应用也很广泛。比如机械臂的运动规划需要同时优化运动时间、能量消耗和轨迹平滑度。多目标规划方法可以在已知环境模型的情况下直接计算出帕累托最优的轨迹集合供上层决策模块选择。指南中提到的多目标值迭代和策略迭代方法在小规模机器人控制任务中是可行的。但对于高维状态空间还是需要结合函数逼近的方法这时候多目标强化学习的方法就更合适。5.4 不同场景下的方法选择建议根据我的经验不同应用场景下方法选择的建议如下应用场景推荐方法理由偏好固定、实时性要求高线性标量化 单目标RL实现简单、推理快偏好多变、需要在线切换条件网络一次训练、灵活切换环境模型已知、状态空间小多目标规划精确、无需训练离散动作、小规模多目标Q学习直接、可解释连续动作、大规模条件网络 策略梯度可扩展、表达能力强这个表只是一个大致的参考实际选择还需要考虑计算资源、训练时间、部署环境等因素。6. 关于这篇指南的阅读建议与延伸方向6.1 怎么读这篇指南效率最高这篇指南的内容比较全面从问题定义到方法体系再到实际案例都有覆盖。如果你的时间有限我建议的阅读顺序是先读问题定义部分搞清楚MOMDP、帕累托支配、帕累托前沿这几个核心概念。这是后续所有内容的基础。再读方法分类部分了解单策略方法和多策略方法的区别以及各自的适用场景。然后读你感兴趣的具体方法如果你做的是连续控制重点看条件网络和多目标策略梯度如果你做的是规划问题重点看多目标值迭代和策略迭代。最后读案例和实验部分看看别人是怎么在实际问题中应用这些方法的有哪些经验教训。不要试图一次把所有方法都搞懂。多目标强化学习本身就是一个比较新的方向很多方法还在发展中。先掌握一两种核心方法在实际项目中用起来然后再逐步扩展。6.2 值得进一步探索的方向指南中提到的几个方向我觉得很有潜力多目标探索策略在单目标强化学习中探索和利用的平衡已经是一个难题。在多目标场景下这个问题更加复杂因为你需要同时探索多个目标方向。目前这方面的研究还比较少是一个值得关注的方向。多目标离线强化学习离线强化学习是近几年的热点但多目标离线强化学习的工作还不多。如何从固定的数据集中学习帕累托前沿是一个很有实际意义的问题。多目标强化学习的可解释性在实际应用中决策者不仅需要看到方案还需要理解为什么某个方案是帕累托最优的。如何提高多目标强化学习策略的可解释性是一个值得探索的方向。与大规模模型的结合条件网络的思想和大规模预训练模型有相似之处——都是通过条件输入来控制模型行为。如何把多目标强化学习和大规模模型结合是一个有趣的方向。6.3 我个人的几点体会最后分享几点我在学习和实践多目标强化学习过程中的个人体会。第一不要被数学公式吓到。多目标强化学习的数学基础确实比单目标复杂一些但核心思想其实很直观不是找一个最优解而是找一组各有优劣的解。理解了这一点很多公式就变得容易理解了。第二从简单场景开始。不要一上来就搞高维、多目标、复杂环境的任务。先用一个简单的二维目标、低维状态的任务把流程跑通理解每个环节的作用然后再逐步增加复杂度。第三可视化非常重要。多目标强化学习的结果很难用一个数字来评价必须通过帕累托前沿的可视化来检查。我养成了一个习惯每次训练完都画一下帕累托前沿看看分布是否均匀、覆盖是否完整。这个习惯帮我发现了很多问题。第四多目标强化学习不是万能的。如果你的问题中各个目标之间没有真正的冲突或者偏好是固定不变的那么单目标方法可能更简单有效。多目标强化学习的价值在于处理真正的多目标权衡问题不要为了用而用。这篇指南我读了好几遍每次都有新的收获。它最大的价值在于把多目标强化学习和规划这个相对分散的研究领域做了一个系统的梳理让初学者能够快速建立整体认知。如果你也在做相关的工作建议把它放在手边遇到具体问题时翻一翻对应的章节会有不少启发。

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

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

免费获取报价 →
↑