ARTICLE DETAIL

资讯详情

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

阴阳平衡优化算法改进:小波精英解学习与多角度搜索解析

阴阳平衡优化算法改进:小波精英解学习与多角度搜索解析 做优化算法的人嘴上天天挂着“探索”和“开发”。说句公道话这两个词落到实处很难探索多了收敛太慢开发多了刚找到局部最优就再也出不来了。这几年新提出的元启发式算法一堆大部分就是给老算法换了个“生物外壳”。但阴阳平衡优化算法YYPO不一样它的思路很轻用两个点组把“探索”和“开发”的职责直接掰开分别对应“阳”和“阴”再靠分裂合并机制动态调整两者比例。这个设计在理念上很讨喜不过说实话原始 YYPO 在标准测试函数上的表现并不算惊艳尤其是高维 Rastrigin 这类多峰函数后期很容易停在伪最优。最近我在跟踪一个改进版本基于小波精英解学习和多角度搜索的新型阴阳平衡优化算法。名字很长但拆开就两个技术点一个是用 Morlet 小波给精英解做多尺度扰动另一个是把原来单方向的随机扰动改成多方向并行搜索。我把论文里的思路完整复现了一遍跑了好几个 CEC 基准函数整体效果确实比原版要稳。这篇文章不写论文腔就用我的复现过程来讲清楚YYPO 的底子是什么小波精英解学习到底在学什么多角度搜索怎么落地以及哪些参数是容易翻车的。1. 为什么YYPO值得被改进先看懂阴阳平衡优化器的底子1.1 探索与开发的分工靠两个点组就能完成在讲改进之前得先把原版 YYPO 的机制说清楚。YYPO 和大多数种群算法最大的区别在于它不维护几十上百个个体的种群而是只维护一组很少的“点组”。论文的原始设定里通常只有两个点组起步一个负责大范围探索取名叫“阳”一个负责精细搜索取名叫“阴”。每个点组内部可以只有一个解也可以有一小撮解但实际上算法每次迭代的重点是围绕点组当前那个核心解做扰动然后把好解放进存档。这里有个容易被忽略的设计YYPO 的“更新”不是像遗传算法那样做交叉变异而是对当前点做一维或者多维的随机偏置再生成一个对立解。对立解的意思是以某种方式产生一个和当前解“相反”的候选解目的是扩大覆盖范围。这个机制说白了就是在当前点附近模拟“阴中有阳、阳中有阴”的互补式搜索。和我第一次看到时的直觉差不多这套东西原理不难难的是平衡点怎么找。接下来呢点组如果在一个地方反复找不到更好解步长就会减半相当于把搜索范围缩小如果找到了更好解步长会适度放大。与此同时存档里积累的优秀解一旦达到阈值点组就会分裂一个点组拆成两个分别带上新步长一个偏保守、一个偏激进。点组太多之后又合并回两个。这样的动态调节让 YYPO 用极少的计算资源就能维持探索和开发的交替这种“轻量级”设计在工程上非常友好因为它不需要像粒子群那样维护几十上百个个体的位置和速度也没有遗传算法那种复杂的交叉概率调节实现门槛很低。1.2 原版 YYPO 的短板方向感和后期动力都欠缺我复现原版 YYPO 时最大的体感是算法思路很干净但跑的体验一般。第一个问题是方向感不足。一维扰动本质上只在一个随机轴上试探如果这个轴不是通往全局最优的方向那当前点组的努力基本白费最坏情况下多维扰动也是基于当前点的随机缩放没有利用全局最优解的信息去引导搜索方向。第二个问题是后期动力不足。当步长不断减半后点组会缩在一个很小的邻域里如果这个邻域只是一个局部最优的盆地算法很难自己走出来。这两个短板直接对应标题里的两个改进点。小波精英解学习补的是“后期动力”围绕精英解做多尺度小波扰动既保持小步长精细搜索又靠小波的振荡项有时“冲”出当前盆地多角度搜索补的是“方向感”同一轮迭代里同时从多个方向生成候选解而不是赌一个随机轴。这样理解之后再看改进算法就不觉得名字长了它其实是把 YYPO 天生缺的两块拼图补上去。2. 小波精英解学习给精英解装上“变焦镜头”2.1 为什么用“小波”而不是用高斯噪声或柯西变异熟悉进化算法的朋友对“精英策略”肯定不陌生把每一代最好的一批解留下来或者拿最优解当中心去做扰动。常见的做法是高斯扰动、柯西扰动有时候也用差分进化里的变异算子。这些方法的共同点是扰动的分布是固定的要么尺度固定要么混合但没规律。而小波函数带来的最大增量是“多分辨率”。可以把小波理解成一个自带变焦的扫描探针。一般的高斯扰动相当于拿一把固定焦距的放大镜在当前点附近看一圈小波扰动则不同它的波形由一个振荡项和一个衰减包络组成。尺度参数大的时候包络宽、频率低扫描范围大尺度参数小的时候包络窄、频率高扫描范围小。放在优化语境里就是同一个小波算子既能做大范围粗搜索又能做小范围精搜索关键就看尺度参数对应的当前迭代阶段。那为什么单独选 Morlet 小波我在复现时也对比过 Haar 和墨西哥帽。Haar 是分段常数扰动是不连续的产生候选解的路径有跳变在连续优化问题里不够平滑墨西哥帽小波严格来说是高斯函数的二阶导没有振荡项做局部扰动还行但缺乏周期性“回头”的能力。Morlet 是高斯包络乘上一个余弦振荡项既有局部聚焦特征又有周期搜索的倾向非常适合用来生成围绕精英解的候选解集合。用大白话说高斯扰动只会“一锤子买卖式”地往外推一把而 Morlet 扰动更像在精英解周围来回扫一圈扫的过程中还有可能发现旁边的小洼地。2.2 精英解学习的运作方式从最优解生长出候选解小波精英解学习的核心逻辑就一句让每一个新候选解都从当前全局最优解出发沿着小波函数调制的方向生长出来。我在伪代码里通常这样实现输入精英解 x_best随机参考解 x_rand当前迭代进度 g 输出候选解 x_candidate # 计算当前小波尺度 a前期大、后期小 a a_min (a_max - a_min) * exp(-g / G) # 从精英解出发用Morlet小波生成扰动项 for d 1 to D: u uniform(-2.5, 2.5) psi cos(5 * u / a) * exp(-u * u / 2) # Morlet 小波 x_candidate[d] x_best[d] psi * (x_rand[d] - x_best[d] x_candidate[d] clamp(x_candidate[d], lb[d] ub[d])不用把这个公式当金科玉律它表达的思想更重要扰动项等于小波函数值乘上一个“参考解与精英解的差”。这个差值提供了方向信息小波函数值提供了幅度和振荡信息。尺度 a 初期大psi 的有效范围大候选解可以在距离精英解较远的地方生成后期 a 变小扰动幅度和范围都缩小候选解贴着最优解精细搜索。更妙的是由于余弦项的存在扰动在接近精英解的过程中不是单调逼近而是带一点“扫掠”性质这有助于绕过浅的局部陷阱。这里的“学习”体现在什么地方其实就在于参考解 x_rand 的选择方式。我在复现时发现如果 x_rand 完全随机学习效果一般更好的做法是从存档中随机挑一个历史优秀解或者从当前点组中挑一个和精英解差异较大的成员。这样候选解不是盲目围绕最优解打转而是在最优解和有意义参考解之间做插值式学习。打个比方全班第一名的答案贴在你面前你直接抄未必考得好但你拿着一份考砸了的卷子对着第一名的答案逐题对照找出差异再修正这才是真学习。2.3 一个容易忽略的细节振幅衰减要匹配迭代阶段这个细节我认为是全文最值得写的经验之一。很多改进算法加了小波算子后效果变差不是算子本身不好而是尺度参数 a 的调度没有设计好。我在第一版复现时直接把 a 从 2.5 线性衰减到 0.01结果前期扰动过大很多候选解直接飞出边界后期又过早进入纯局部模式等于没起到增强作用。后来我改成指数型衰减a a_min (a_max - a_min) * exp(-g / G)并且把 a_min 钳制在 0.01 之上a_max 设在 2.5 左右。这样前期衰减快但不至于瞬间结束后期衰减越来越慢给足局部精修时间。用白话讲一开始镜头快速从广角收到标准后面再慢慢从标准收到微距。这样和 YYPO 本身的步长减半机制天然互补两个“缩手”策略叠在一起不会互相打架。3. 多角度搜索把“赌方向”改成“撒渔网”3.1 原生YYPO的方向其实就是单点随机多角度搜索是怎么设计的刚才吐槽过原版 YYPO 的一个问题一维扰动是随机选轴多维扰动是整体随机缩放本质都在“赌方向”。如果这一轮随机出来的方向不是精英解所在方向候选解质量大概率不理想。多角度搜索的思路很直白与其赌一个方向不如一次从好几个方向同时生成候选解然后再评估。方向优先选哪几个我在实验里固定了四个方向作为基础集合方向一面向全局最优解。候选解先从当前点组核心解连到全局最优解取中间偏优的位置。方向二面向存档中的一个随机历史优秀解。这个方向和方向一不一致适合避免所有点组都朝同一个地方挤。方向三面向一个随机正交方向。用一组随机单位向量做 Gram-Schmidt 正交化保证这个方向和当前方向不完全重叠。方向四对立方向。以当前点为参考生成反向候选解模拟“阳离不开阴”的互补逻辑。每个方向生成的候选解数量不必一样我一般按 1:1:1:1 分布。这样一轮迭代下来点组周边有探索型候选、开发型候选、正交补偿候选和对立候选覆盖的几何角度比原版丰富得多。实测下来Rastrigin 这类多峰函数上跳出局部最优的次数明显变多。3.2 多角度和点组分裂机制如何形成“双保险”多角度搜索还和 YYPO 的分裂机制有潜在配合。原版的点组分裂是根据存档积累触发的分裂出来的两个点组分别用不同步长继续搜索。加入多角度搜索后分裂出来的两个点组可以直接继承不同的方向偏好比如新组 A 侧重全局最优方向新组 B 侧重正交随机方向。我在复现时没有改分裂判据只是在分裂初始化时把多角度候选解中的不同方向结果分别分配给了新组效果比随机继承好。这里要提醒一下多角度搜索不是方向越多越好。方向从 1 加到 4 时收益明显加到 8 时计算量涨了一倍性能提升却微乎其微。为什么首先评估开销变大其次存档很快塞满触发分裂频率变高点组数量失控。我建议把方向数控制在一个 D 维空间里比较“稀缺”的量级3 到 5 个方向是性价比最高的区间。3.3 正交方向到底怎么生成才靠谱正交方向这件事写代码五分钟跑偏一小时。如果你直接生成 D 个随机方向然后用 Gram-Schmidt 正交化在高维下会出现数值稳定性问题方向向量之间名义上正交但由于浮点误差正交性很快退化。我后来改用 Hadamard 矩阵或者随机置换单位矩阵的行这样生成的方向本身就保持正交性不需要额外修正。具体做法很简单先生成一个 D×D 的随机正交基比如对随机高斯矩阵做 QR 分解取 Q然后从 Q 里抽几行作为方向向量。这样抽出来的方向天然正交也天然均匀分布在单位球面上。如果有工程预研需求建议直接把这段逻辑固化成工具函数后面所有实验都复用避免在正交分解的细节上反复踩坑。4. 完整算法流程与参数配置参考4.1 总流程把两个改进模块嵌入YYPO主循环把前面几节的思路串起来最终算法的主循环长这样输入最大迭代次数G维数D边界[lb, ub]初始点数N 输出全局最优解 global_best 初始化N2点组P1(阳)、P2(阴)步长r1、r2存档为空 global_best min(f(P1), f(P2)) for g 1 to G: for i 1 to N: # 1. 多角度搜索 生成方向集合全局最优方向、存档方向、正交方向、对立方向 for each direction: 生成候选解 x_cand P_i r_i * lambda * direction 评估所有候选解保留最优者 x_best_c # 2. 小波精英解学习 以 global_best 为中心用小波扰动生成若干学习候选解 合并到候选解池 更新当前点组 P_i 候选池中最好解 更新步长 r_i # 成功则按1.1倍放大失败则乘0.5 if P_i 优于 global_best: global_best P_i # 3. 存档与分裂合并 将本轮优秀解写入存档 if 存档数量 2D 且 N Nmax: 分裂触发把贡献最大的点组一分为二 if N Nmax: 合并最接近的两个点组 return global_best这个主流程和原版 YYPO 保持一致的骨架但把原来的随机扰动替换成了“多角度搜索 小波精英解学习”的组合。在实现时我建议把两个模块写成单独的函数方便做消融实验——你需要知道到底是哪个模块起了作用而不是一上来就叠buff。4.2 小波精英解学习的实现细节与参数对照再给一份可以照着填的伪代码function WaveletEliteLearning(x_best, archive, g, G, D, lb, ub): a 0.01 (2.5 - 0.01) * exp(-g / G) times randint(D / 2, D) x_ref archive[randint(len(archive))] for t 1 to times: u uniform(-2.5, 2.5) psi cos(5 * u / a) * exp(-u * u / 2) x_cand x_best psi * (x_ref - x_best) x_cand clip(x_cand, lb, ub) if f(x_cand) f(x_best): return x_cand return x_best这里有个参数值得专门说times表示学习次数我把它设在 D/2 到 D 之间而不是固定 D是为了避免高维下评估次数爆炸。你可以在 30 维问题上试一下固定 D 次学习其实也就 30 次评估叠加多角度搜索的 4 到 8 个候选解每轮总评估数还算可控。但如果维数上到 100 维times 固定为 D 会让每轮评估量变成 100累计起来就有点吃不消了。建议times randint(D/2, D)或者直接固定为 D/2。4.3 多角度搜索的实现细节与方向向量生成多角度搜索部分我把方向生成和候选解生成分开写function MultiAngleSearch(X_i, r_i, x_best, archive, D, lb, ub): dirs [] # 方向一指向全局最优 if x_best ! X_i: dirs.append(normalize(x_best - X_i)) # 方向二指向存档中的一个随机解 rand_ref archive[randint(len(archive))] if rand_ref ! X_i: dirs.append(normalize(rand_ref - X_i)) # 方向三正交方向从预生成的Q矩阵抽取 dirs.append(Q[randint(D)]) # 方向四对立方向 dirs.append(normalize(center * 2 - X_i)) # center是空间中心或当前最优中心 for d in dirs: lambda_i uniform(0.0, 1.0) x_cand X_i r_i * lambda_i * d x_cand clip(x_cand, lb, ub) 评估并收集 return 候选池中的最优解注意“对立方向”这里的 center 选哪个很有讲究。我对比过两种做法一是以搜索域中心为中心二是以当前全局最优为中心。前者更适合全局早期保持多样性后者在后期能让对立解更有针对性地“反弹”到另一侧。实际用的时候建议根据迭代进度做一个权重切换前半段用搜索域中心后半段用全局最优中心。这个细节在论文里往往一笔带过但实测对表现影响很大。4.4 参数速查表可以直接抄作业参数建议取值备注初始点组数 N2对应阳、阴最大点组数 Nmax4 或 8超过就合并初始步长 r(ub - lb) / 10按变量范围自适应步长放大系数1.1更新成功时步长衰减系数0.5更新失败时小波尺度 a_max2.5初始大尺度小波尺度 a_min0.01最终小尺度多角度方向数3 ~ 54 个基础方向较稳学习次数 timesD/2 ~ D高维时取 D/2存档分裂阈值2D越小分裂越频繁这些数值是我在 30 维 CEC 系列测试函数上调参后的经验值不是理论最优。你可以把它当起点再用自己的问题微调。5. 复现实验基准函数上的表现变化5.1 实验设置与基线选择我复现时选择的测试函数是经典四件套Sphere、Rastrigin、Rosenbrock、Ackley。这里的背景说一下CEC 是进化计算大会推出的标准测试集包含单峰、多峰、旋转、偏移等不同性质的连续优化问题用来检验算法到底擅长什么场景。我的设置是维度 30独立运行 30 次每次最大迭代 1000 代记录平均最优值和收敛轨迹的典型形态。基线选了原版 YYPO参数按原论文建议设置。改进版只替换搜索模块其他设置不变这是为了做严格的消融对比。在正式跑对比之前我建议你先跑一遍原版 YYPO记住它在每个函数上的收敛形态。为什么因为后面看到改进版的曲线只有对照过原版才能分清哪些改进来自小波精英解学习哪些来自多角度搜索。而且这也方便你检查代码是否有逻辑错误。5.2 四个测试函数上的典型现象先说 Sphere。这个函数单峰且平滑原版 YYPO 到后期收敛速度明显放缓因为步长减半机制让它越走越慢。改进版明显改善了尾部收敛原因是小波精英解学习在后期用小尺度高频扰动持续对精英解做微调等效于在不放大步长的情况下保持了微小的搜索活性。从收敛曲线的形态看最后 200 代里改进版还能继续下降原版基本就平了。再看 Rastrigin这是最能体现多角度搜索价值的函数。它充满大量等间距的局部最小值单点随机扰动很容易在某个局部盆地里原地打转。多角度搜索因为同时提供全局最优方向、存档方向、正交方向和对立方向每次迭代都有一定概率产生一个“逃逸方向”的候选解。我在 30 次运行里原版平均有七八次掉在同一个局部最优解上不动改进版明显减少了这种情况虽然不能说每次都能找到全局最优但跳出局部陷阱的概率高了一截。Rosenbrock 是另一个值得说的用例。它的最优点在一个狭长的香蕉形谷底随机方向扰动往往会在谷壁上来回弹跳。改进版里“面向存档方向”和“面向全局最优方向”的候选解会沿着谷底倾斜方向产生实测跑出来的轨迹更顺不容易卡在谷壁。Ackley 则体现的是稳定性原版曲线震荡幅度大改进版加上小波后候选解生成更平滑30 次运行之间的方差明显缩小。5.3 需要泼冷水的部分哪些函数反而没优势改进版不是万能的。在 Schwefel 函数的某些变体上改进版相比原版没什么提升偶尔还因为多角度搜索的额外评估拖慢了单轮速度。在步进函数、离散函数上Morlet 小波的连续性反而容易生成不可行或者低效候选解。所以我建议你在实际工程中先判断目标函数的特性如果它是多峰、连续、有大量局部陷阱的这个改进很有价值如果本身就是单峰平滑或者离散组合优化小波精英解学习的收益很小不如直接上差分进化变体。这个“条件性优势”我觉得特别重要。看论文时作者通常会挑选对自己算法友好的测试集你复现以后一定要自己追加几个“不友好”的测试才能对算法边界有真实认识。我常跟实验室的师弟说复现一篇算法论文最值钱的部分不是跑出和论文一致的好数字而是搞清楚这个算法在什么条件下会失效。6. 复现与调试中的常见问题6.1 迭代中期点组数猛增存档被塞爆我第一版实现时多角度搜索生成候选解的数量从 4 个加到 8 个存档阈值还是用原版的 2D结果不到 100 代点组数量就飙到了上限。排查后发现候选解增多让存档里优秀解变多触发分裂的概率显著提高。调整办法有两个一是把存档阈值从 2D 提到 4D 或 6D二是把方向数降回 4 个。记住一个原则分裂机制是“应急”机制不应该成为每轮都触发的常规动作。6.2 小波尺度参数衰减过快导致后期“死水一潭”这个问题我踩过最深的坑。第一次实验用的线性衰减a 2.5 * (1 - g/G)结果发现最后 300 代几乎没有任何改进。原因是线性衰减在中期就把 a 压到接近 0.01后期小波扰动幅度极小和没加模块一样。改成指数衰减后后期 a 还能维持在一个相对活跃的范围尾部收敛立刻就好了。如果你在实验里发现后期收敛曲线提前变平先检查 a 的衰减曲线而不是急着调步长。6.3 高维下方向正交性退化多角度搜索退化成“多近度搜索”当你把问题维度提高到 50 维甚至 100 维随机生成的方向向量之间会迅速“挤成一团”。这不是玄学是球面上高维随机向量内积趋近于 0、但浮点误差放大的结果。如果发现多角度生成的候选解彼此距离很近说明方向质量已经不行了。解决方法是改用预先生成的正交基QR 分解或 Hadamard 矩阵每轮直接抽基向量而不是现场做 Gram-Schmidt。6.4 怎么判断你的改动是真的有贡献最后给一个方法论建议一定要做消融实验。把改进版拆成三个版本只加小波精英解学习、只加多角度搜索、两个都加。在四个测试函数上分别跑 30 次用 Wilcoxon 秩和检验看显著性。我复现时这样做的最大收益是发现单加小波精英解学习在 Rastrigin 上贡献不大单加多角度搜索在 Sphere 上贡献不大两个都加才是接近“全能”的组合。这句话翻译过来就是标题里那两个技术点是互补的不是重复堆叠。这个算法我前后调了两周。说实话最初吸引我的不是那个长名字而是“用两个点组模拟阴阳平衡”这个轻量设计做完改进复现之后更让我印象深刻的也不是某一次实验跑出了多好的精度而是小波的多尺度特性与多角度方向集合分别补上了 YYPO 在时间和空间两个维度上的盲区。如果你也在做元启发式算法的改进我建议拿到任何新论文、新框架之后别急着抄完整代码先把它拆成模块做消融实验搞清楚每部分的作用边界这个习惯养成了你再看满屏的新算法就不会被名字唬住了。后面我打算把这套组合移植到工程约束优化问题上试试如果有新的踩坑经验我还会再写一篇和大家分享。
返回列表