ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

多智能体二分包含控制:模糊强化学习与分布式最优控制

多智能体二分包含控制:模糊强化学习与分布式最优控制 简介一份PDF格式的论文与代码详解面向多智能体系统、博弈论与强化学习研究者聚焦高阶非线性多智能体二分包含控制问题。论文基于博弈论与模糊逻辑系统提出图博弈下的自适应模糊最优二分包含控制方法利用积分强化学习求解N玩家博弈纳什均衡并给出同步误差有界性与二分包含达成的理论证明。压缩包仅含1个PDF约627KB内容在理论推导之外附有完整Python复现代码及中文解释涵盖带符号图建模、模糊逻辑系统逼近、IRL评价网络更新、分布式控制策略求解等关键步骤可直接迁移到无人机编队、智能电网等分布式控制场景。已有130人学习适合具备一定多智能体/强化学习基础的研究人员或工程师用于算法验证与二次开发。1. 多智能体二分包含控制在玩什么给“对抗阵营”划出收敛目标多智能体二分包含控制是协同群集运动控制里最容易被误读的一个方向。它要解决的不是让所有智能体聚到同一个位置而是在同一张图上同时存在“队友”和“对手”两类边时把跟随者分成两个阵营分别收敛到各自领导者的凸包里。这类场景在博弈对抗、异构编队、集群对峙里很常见。加上系统本身是非线性的高阶积分器链控制器设计就不是加一个比例项能解决的。常用做法是把博弈论和模糊强化学习组合起来用非零和博弈定义每个智能体的最优目标让模糊系统在线逼近未知非线性再用时序差分方法迭代求解分布式最优控制律。这篇笔记会把整套链路从符号图建模写到可复现的策略迭代代码包括参数设置和排错路径给正在做多智能体系统分布式控制的人一条能踩实的技术路线。2. 二分包含控制的理论底座符号图、凸包和结构平衡判定在动手写强化学习之前先把符号图这层地基打牢。二分包含控制里最容易翻车的地方恰恰不是代码而是符号图本身不符合结构平衡条件导致后边所有坐标变换全部失效。2.1 先看懂“二分”符号图里为什么小于零的是对手普通一致性控制里邻接矩阵的非对角元是非负权重边的意义是“我参考你、我朝你靠近”。二分包含控制把边的取值范围放开到正负两类正边代表合作、负边代表对抗。一个跟随者同时连接正负两类邻居时它不能对两边都执行“靠近”必须按边的正负关系把自己划到某个阵营里去。这里的“二分”是一个严格图论概念节点集合必须能被剖成两个阵营使得正边只连接同阵营节点负边只连接不同阵营节点。这种图叫结构平衡的符号图。如果不满足就不存在一个一致的阵营划分收敛目标本身就是矛盾的。实际场景里最常见的是两个阵营的领导者各自形成凸包跟随者按边的符号归属到其中一个凸包这就是“二分包含控制”中的“包含”二字。2.2 符号拉普拉斯与坐标翻转把二分问题转成普通包含控制符号图可以直接构造符号拉普拉斯矩阵 Ls D − A其中 D 是绝对值度对角阵A 是带符号的邻接矩阵。结构平衡的符号图有一个非常实用的性质存在一个对角矩阵 G diag(v1, v2, …)vi 取值 1 或 −1使得 G·A·G 的所有非对角元都变成非负。vi 的符号就是阵营标识。这个性质直接给出工程技巧对负阵营的状态做坐标翻转 z_i vi·x_i。翻转之后整个符号图退化成普通非负图二分包含控制就变成了标准的多领导者包含控制。负边的作用此时才真正清楚它不是让系统朝反方向发散而是让负阵营的跟随者在翻转坐标里朝同一个凸包收敛。很多实现里控制律、代价函数、模糊基函数全部写对了就是漏了这一步坐标翻转结果仿真里跟随者全部跑到凸包对称位置去。翻转之后把符号拉普拉斯按跟随者和领导者分块得到 L1 和 L2。结构平衡且每个连通分量至少存在一个领导者时L1 是非奇异 M 矩阵这是包含控制收敛的基本判定条件。写代码时我会先检查这个条件再进入策略迭代。2.3 结构平衡检测能写进代码的判定步骤结构平衡检测不依赖特征值用图遍历染色最可靠。特征值判据在浮点误差下很容易误判特别是图规模不大时。下面这个函数就是给符号图做二染色检测。import numpy as np def sign_balanced(Adj): 检测符号图是否结构平衡。 返回 (True, color) 时color 为 1/-1 阵营标签 返回 (False, None) 时需要调整负边或重新定义阵营。 n Adj.shape[0] color np.zeros(n, dtypeint) for s in range(n): if color[s] ! 0: continue color[s] 1 stack [s] while stack: u stack.pop() for v in range(n): if Adj[u, v] ! 0: # 负边要求两端阵营相反正边要求相同 target -color[u] if Adj[u, v] 0 else color[u] if color[v] 0: color[v] target stack.append(v) elif color[v] ! target: return False, None return True, color逻辑说明从任意未染色节点出发假设它属于正阵营按边的符号逐个约束邻居阵营。如果某个邻居已经被染成相反颜色说明图里存在无法调和的负环结构平衡不成立。参数方面Adj 是方阵对角元必须为 0非对角元只保留 −1、0、1 三类值不要使用任意大权重否则后边强化学习里误差量级会失控。实际使用中我会先用这个函数检查图再算 L1 的逆是否非负。如果结构平衡检查不通过最直接的修复是把某个导致矛盾的最小负环中的一条边改成正边或者重新定义哪些节点属于哪个阵营而不是强行调控制参数。3. 建模与代价设计高阶非线性系统、T-S模糊和博弈目标理论层确认之后接下来要回答“控制对象到底长什么样”和“最优目标怎么定义”。这两个问题不解决强化学习算法无从落地。3.1 高阶系统状态空间积分器链的建模方式标题里“高阶系统”指的是每个智能体不是一阶积分器而是 m 阶积分器链。第 i 个跟随者的状态记为 x_i ∈ R^m满足x_i1 的导数是 x_i2x_i2 的导数是 x_i3一直到最高阶 x_im 的导数为 f_i(x_i) u_i。这里的 f_i 是未知非线性项u_i 是控制输入。这种模型的麻烦在于分布式最优控制要让整个状态向量收敛到领导者凸包对应分量的范畴而不只是稳住最高阶。位置进入凸包但速度不进入误差函数照样不为零。代价函数必须把每一阶状态都放进去否则收敛后控制效果是残缺的。仿真里推进动力学的写法如下。def dynamics_step(X, u_arr, dt, nonlinear_func): X: 形状 (nF, m)当前所有跟随者状态 u_arr: 形状 (nF,)这一步的控制量 nonlinear_func: 每个智能体的非线性项签名 f(x_i) X_next np.zeros_like(X) for i in range(X.shape[0]): x X[i] f nonlinear_func(x) dx np.zeros_like(x) dx[:-1] x[1:] # 低阶状态是高一阶状态的导数 dx[-1] f u_arr[i] # 最高阶由非线性和控制共同驱动 X_next[i] x dt * dx return X_next逻辑说明这一句dx[:-1] x[1:]就是高阶积分器链的压缩写法m 个状态分量之间是逐级求导关系。最高阶分量关心的是 f_i 和 u_i。如果系统状态是多维的状态向量和输入都需要按维度扩展但推导结构不变。dt 建议取 0.001~0.01太大时欧拉积分会掩盖策略迭代的收敛过程造成“看着在收敛、一换初值就崩”。3.2 T-S模糊模型与模糊基函数把非线性变成凸组合非线性项 f_i 未知强化学习需要逼近的是值函数和控制策略而不是去建模 f_i。模糊系统在这里承担函数逼近器角色本质是用一组局域线性模型去近似全局值函数。对每个状态误差 ε_i定义 M 条模糊规则每条规则的作用域是一个高斯隶属度函数。把所有规则的隶属度归一化得到模糊基函数向量 φ(ε_i)。用这个向量表示第 i 个智能体的值函数与策略后系统就在每个局部区间里近似成线性系统策略迭代的矩阵运算才有效。模糊基函数生成代码def fuzzy_basis(z, centers, sigmas): z: 当前误差向量形状 (d,) centers: (M, d)每条规则在各维上的中心 sigmas: (M, d)每条规则在各维上的宽度 返回归一化模糊基函数形状 (M,) M centers.shape[0] mu np.ones(M) for l in range(M): for k in range(z.shape[0]): mu[l] * np.exp(-0.5 * ((z[k] - centers[l, k]) / sigmas[l, k]) ** 2) s mu.sum() if s 1e-8: return mu # 所有隶属度几乎为零返回原值便于排查 return mu / s逻辑说明高斯隶属度对每维误差单独计算后相乘得到这条规则对当前状态的激活强度。归一化保证所有规则的激活强度之和为 1这样任意误差点都被“凸组合”到各条局部规则上。参数方面centers 一般按误差范围的均匀网格布置比如误差区间是 [-3, 3]每维放 5 个中心sigmas 取相邻中心距离的 0.5~0.7 倍太小会导致规则之间没有过渡太大则所有规则都同时激活失去了局部建模的意义。3.3 博弈型代价函数Nash均衡和局部信息约束为什么单智能体强化学习不够因为每个智能体的代价函数都依赖邻居误差而邻居误差里又包含邻居策略的影响。第 i 个智能体优化自身代价时实际是在和邻居玩一个非零和微分博弈。每个智能体都想在给定邻居策略的前提下做到局部最优所有人同时最优的状态就是 Nash 均衡点。第 i 个智能体的代价函数写成J_i ∫ (ε_i^T Q_i ε_i R_i u_i^2) dt这里的 ε_i 是符号图邻居误差它把队友、对手的信息都折叠进来。代码里每步的即时代价是def local_cost(eps, u, Q, R): # eps 是第 i 个智能体相对邻居的加权误差 # u 是第 i 个智能体的控制输入 return eps Q eps R * u * u逻辑说明第一项惩罚“没有进入凸包”的误差第二项惩罚控制能耗。Q 和 R 的比值决定了系统愿意花多大力气去追凸包。博弈视角下R 不能设得太大否则每个智能体都“躺平”最终收敛到凸包外R 设得太小则所有智能体都在激烈对抗策略迭代容易震荡。我一般从 R1.0 起步观察控制曲线是否出现高频抖动再微调。关键点ε_i 的构造必须和坐标翻转后的非负图一致。如果对负阵营做过 z_i −x_i那么误差计算也要在 z 坐标下进行不能在原坐标里同时使用符号邻接矩阵和强化学习更新这是代码里最隐蔽的坑。4. 用模糊策略迭代实现分布式最优控制核心代码与参数落地这一节把前面几部分焊到一起。策略迭代采用 Critic-Actor 架构Critic 用模糊基函数近似值函数Actor 用同一组基函数生成控制策略。每个智能体只使用邻居信息更新自己的权重符合分布式约束。4.1 初始化模块符号图、状态和模糊基函数参数初始化阶段要把图、状态、模糊基函数、初始控制策略全部定好。初始控制策略不能从零开始必须先用一个稳定的本地反馈把系统带到允许域内否则强化学习会一直在危险区域试探。nF, nL 6, 4 # 跟随者 6 个领导者 4 个 m 2 # 状态阶数演示高阶结构用二阶 Adj np.zeros((nF nL, nF nL)) # 这里填入你的符号邻接矩阵例如 Adj[0, 6] 1 表示跟随者0连接领导者0的正边 # Adj[1, 7] -1 表示跟随者1连接领导者1的负边 ok, color sign_balanced(Adj) if not ok: raise ValueError(符号图结构不平衡请先修正图) X np.random.uniform(-2, 2, (nF, m)) # 跟随者初始状态 XL np.random.uniform(-1, 1, (nL, m)) # 领导者初始状态 K0 np.array([2.0, 1.5]) # 初始本地稳定反馈增益 W np.zeros((nF, M)) # Critic 权重 Theta np.copy(W) # Actor 权重初始从 Critic 的保守值开始 centers, sigmas build_centers_sigmas(m, M, low-3.0, high3.0)逻辑说明sign_balanced要在所有后续工作之前执行这是为了确认坐标翻转存在。X的初始范围应该覆盖模糊基函数的主要区间如果初始状态范围远超 centers 覆盖范围Actor 在最初的几步会输出很不可控的控制量。K0是一个简单的本地状态反馈它不解决博弈问题只是把系统约束在合理区间让强化学习能采集到有效数据。M 是模糊规则数取 5 到 7 比较合适规则太少逼近精度不够太多则参数辨识困难训练方差变大。4.2 Critic-Actor策略迭代主循环主循环的核心就是四件事计算邻居误差、推进动力学、更新 Critic、更新 Actor。下面这个循环是能直接嵌进仿真框架的版本。dt, T_total 0.01, 30.0 gamma 0.98 alpha_c, alpha_a 0.05, 0.01 Q np.diag([1.0, 0.3]) R 1.0 for step in range(int(T_total / dt)): # 根据当前策略计算控制量 u_arr np.zeros(nF) for i in range(nF): eps compute_eps(i, X, XL, Adj) phi fuzzy_basis(eps, centers, sigmas) u_arr[i] -np.dot(Theta[i] * phi, eps) # 推进动力学 X_next dynamics_step(X, u_arr, dt, nonlinear_func) XL_next leader_reference((step 1) * dt) # 用一步转移数据更新 Critic 和 Actor for i in range(nF): eps compute_eps(i, X, XL, Adj) eps_next compute_eps(i, X_next, XL_next, Adj) phi fuzzy_basis(eps, centers, sigmas) phi_next fuzzy_basis(eps_next, centers, sigmas) V_now W[i] phi V_next W[i] phi_next cost local_cost(eps, u_arr[i], Q, R) td cost gamma * V_next - V_now W[i] alpha_c * td * phi # Actor 沿近似梯度方向更新学习率必须小于 Critic Theta[i] - alpha_a * td * phi * eps X, XL X_next, XL_next逻辑说明compute_eps是按邻接矩阵权重把邻居状态差异累加起来正边直接减负边在坐标翻转后也直接减和普通非负图一致。td是时序差分误差它表示当前值函数估计和真实代价之间的偏差。Critic 用td * phi做梯度下降本质是把值函数往真实回报方向拉。Actor 更新时把td当作优势估计误差越大越往减少当前策略的方向调整。参数说明gamma是折扣因子分布式控制里建议 0.95~0.99太大会让 TD 学习对远期回报过度敏感步数一长就会出现梯度方差爆炸太小则控制器只关注眼前误差收敛后存留较大稳态误差。alpha_c和alpha_a的关系很关键Actor 一定要比 Critic 慢否则策略更新超前于值函数估计整个迭代必然发散。4.3 关键参数表与收敛日志判断实际调试时我习惯每 500 步打印一次平均邻居误差范数和控制能量并根据趋势决定是否终止训练。参数建议值设置理由折扣因子 gamma0.98在收敛速度与稳态精度之间折中太大太长视、太小太短视Critic 学习率 alpha_c0.05太大导致 TD 更新震荡太小收敛极慢Actor 学习率 alpha_a0.01必须明显小于 Critic保证策略改进在可信估值上进行误差权重 Qdiag([1.0, 0.3])位置权重高于速度权重量纲差异要先归一化控制权重 R1.0控制量抖动时增大收敛太慢时减小模糊规则数 M每维 5 个中心规则太多参数辨识困难太少逼近误差大基函数宽度 sigma中心间距的 0.6 倍保证相邻规则有足够重叠又不至于完全耦合收敛日志里最值得看的是 TD 误差均值。如果 TD 误差持续下降但邻居误差迟迟不降问题大概率出在代价权重配比上而不是训练不充分如果 TD 误差在中途突然跳高通常因为状态跑出了模糊基函数覆盖范围这时候先调初始反馈增益不要急着调学习率。第 5 章的避坑记录基本就是这些现象在真实项目里的变形下面展开写。5. 避坑记录符号图翻车、策略发散、凸包误差不降的排查路径这一章是血泪经验汇总。每次调试崩掉最后几乎都能落到下面五个原因里。5.1 结构平衡判定没通过负边控制全在“追反”现象跟随者没有进入领导者凸包反而跑到凸包关于原点对称的位置或者两个阵营的跟随者轨迹交叉振荡。原因符号图本身不是结构平衡图存在含奇数条负边的环阵营划分不存在。此时后边的坐标翻转 G 矩阵根本构造不出来负边的作用变成“镜像排斥”而不是“翻转后的同向吸引”。解决先用 2.3 节的sign_balanced检查整张图。如果返回 False检查邻接矩阵里哪些负边组成了奇数负环把其中一条边改为正边或删除再重跑初始化。不要在控制器里强行补偿图结构不成立任何控制增益都救不回来。5.2 策略迭代数值发散TD误差越跑越大现象训练前几千步误差还在下降突然 TD 误差爆炸式增长控制量呈现指数型上升很快超出物理执行器限幅。原因初始策略不满足“容许控制”条件。策略迭代类算法对初始控制很敏感如果初始策略连基本的稳定性都不保证值函数估计就会发散。另一个常见原因是 Actor 学习率大于 Critic策略更新跨过值函数的有效区域。解决先用本地 LQR 或极点配置给定一个保守稳定的 K0冻结 Actor只训练 Critic 500~1000 步确保持续在线逐步处于“价值被稳定估计”状态。之后再把 Actor 学习率调到 Critic 的三分之一以下。我一般会保存每 50 步的参数快照发散就直接退回上一份快照这是最靠谱的后悔药。5.3 模糊基函数在边界位置归零仿真中途出现 NaN现象某一步后控制量变成 NaN整个仿真数据全部作废。。注意这里不要用感叹号。原因状态误差跑出模糊基函数覆盖范围所有高斯隶属度都接近 0归一化分母趋近 0。基函数输出失去意义Actor 输出失控几分钟后数值溢出。解决给误差状态加限幅例如eps np.clip(eps, -3, 3)。更合理的做法是在初始化模糊基函数之前先用原始反馈控制跑一段仿真统计误差的实际动态范围再把 centers 和 sigmas 按这个范围来布置。固定的 −3 到 3 只适合状态被初始反馈约束得很好的情况。5.4 高阶状态没做量纲归一化位置收敛了速度还在飘现象从凸包距离指标看位置误差已经很小但速度分量始终压不到目标范围训练时间长到无法接受。原因高阶积分器链里位置、速度、加速度的量纲和数值尺度差异很大模糊基函数各维共用同一个 sigma等于让速度维度一直在“模糊地带”里更新。解决对每个状态维度单独计算 centers 和 sigmas比如位置维度的区间是 ±3速度维度是 ±1.5加速度维度可能是 ±5不能用一个标量参数糊弄。Q 矩阵也要按量纲归一化速度权重通常设置为位置权重的 0.1 到 0.5。5.5 非零和博弈的 R 权重过小系统进入极限环现象跟随者最终在凸包边缘来回穿梭轨迹形成不衰减的振荡控制量频率很高但误差平均值不再下降。原因R 设置过于接近 0每个智能体都把“追凸包”放在绝对优先位置博弈里各方同时过度激进系统进入类似极限环的振荡。这是非零和博弈特有的问题单智能体强化学习里不常见。解决把 R 从 1.0 起步观察振荡再逐步下调。如果 R 已经到 0.1 以下还在振先回到参数快照检查 Q 矩阵是否给得过大。控制权重与误差权重的关系在博弈场景下要保守不要追求单步最优“队友之间的妥协”本身就是博弈解的一部分。6. 验证与调参凸包距离指标、批量统计和模糊基函数参数经验验证二分包含控制成功与否不能只看最终那几帧轨迹得定义可量化的指标。对每个跟随者计算它到目标阵营领导者凸包的距离凸包内距离记为 0凸包外距离取到凸包边缘的最短距离。二维场景下可以直接用 Delaunay 判断点是否在凸包内。from scipy.spatial import Delaunay def point_in_hull(pt, hull_pts): try: tri Delaunay(hull_pts) return tri.find_simplex(pt) 0 except Exception: return True # 凸包退化时保守放行需要配合距离指标使用逻辑说明find_simplex返回该点在 Delaunay 剖分中的位置非负代表在凸包内。注意这个函数只做包含判定不做距离度量。如果点在凸包外还要单独计算它到每个凸包顶点的距离取最小值作为近似距离。严格做法是用二次规划算点到凸包的真实距离但收敛判据场景下顶点距离已经够用。批量验证我一般这样设计随机生成 30 组初始条件每组包含不同的跟随者初始位置和领导者参考轨迹相位固定同一组超参数分别跑一次完整仿真。取最后 500 个时间步的平均凸包距离作为该次实验的指标。30 次里至少有 28 次指标低于 0.05才认为这套参数有统计上的稳定效果。调模糊基函数参数时我获得的经验是“宁宽勿密”。M 从 5 开始如果收敛速度不理想先加 sigma 的重叠而不是加规则数。规则数增加到 9 以上后Critic 权重向量维数变高分布式环境里每个智能体拿到的数据量有限参数辨识会进入玄学区间。另一个容易忽略的点是领导者参考轨迹不能太激进如果领导者本身在高速机动跟随者的误差向量快速扫过整个状态空间模糊基函数只在部分区域被激活其他规则形同没训练。我一般让领导者轨迹是低速正弦或斜坡等误差指标稳定后再把轨迹速度逐步拉起来。这套方法能跑通的关键是先在普通包含控制协议上把图、坐标翻转、凸包判定全部验证一遍再开强化学习。直接跳到策略迭代会让符号图错误和模糊逼近误差混在一起排查时非常痛苦。我现在的习惯是一直保留一份“冻结策略的纯 Critic 模式”每个阶段都先固化一边再调另一边。希望帮到你。本文还有配套的精品资源点击获取
返回列表