☰
9种智能优化算法Matlab对比实验:从PSO/GWO到CGO/TSO的完整模板
2026/10/1 23:04:34 网站建设 项目流程

上个月有个做负荷预测的师弟问我,说论文里只写了PSO和GWO的对比,审稿人觉得算法太老,让他补充几个能直接在Matlab里跑、不装第三方工具箱、还能画出收敛曲线的智能优化算法。我从常用算法库里挑了CGO、SCA、GWO、CSA、SSA、HHO、WOA、PSO、TSO这9种,统一加了测试函数、维度、种群规模和迭代次数,整理了一套可以替换目标函数的Matlab代码结构。这篇文章不是把论文搬过来复述公式,而是把我实际跑对比时的算法理解、参数设置和容易翻车的细节写出来。想快速做算法对比、给论文补实验,或者从PSO/GWO往新算法扩展的人,可以照着这套思路搭自己的实验模板。

1. 9种算法放同一张表之前,先把它们拆成三类

很多新手拿到算法清单就开始跑,跑完发现结果乱七八糟,根本不知道问题出在算法本身还是参数设置。我的习惯是先看机制,把9个算法按照“搜索行为来源”分成三类,这样后面分析收敛曲线时才不会瞎猜。

1.1 捕食追踪型:GWO、WOA、HHO

GWO模拟灰狼集群的等级分工。alpha、beta、delta是头狼,其余omega跟随头狼更新位置。每一轮先算所有狼的适应度,把前三名记为alpha、beta、delta,然后用三只头狼的加权位置决定下一代位置,关键参数是A=2arand-a,其中a从2线性降到0。A的绝对值大于1时狼群离散搜索,小于1时向猎物收缩。这个算法优点是结构简单、参数极少,缺点是后期种群多样性下降快,多峰测试函数里很容易所有个体挤到同一个局部峰附近。

WOA模拟座头鲸的气泡网捕食,比GWO多一个策略分支。每轮生成一个随机数p,p小于0.5时走收缩包围,和GWO类似;p大于等于0.5时用对数螺旋绕圈逼近猎物。同时还有一个随机探索机制,避免所有鲸鱼都贴着当前最优走。正因为多了一个螺旋操作,WOA的搜索路径更“绕”,在复杂曲面上有时能绕出局部最优,但也更容易在前中期浪费评价次数。

HHO模拟哈里斯鹰围捕逃跑的兔子,核心是猎物能量E从2迅速掉到0,再叠加随机数q决定软围攻、硬围攻、渐进式快速俯冲等策略。它不是靠单一参数控制探索和开发,而是按E绝对值和随机逃逸概率切换模式。HHO前期会到处飞,后期突然集中围住某个区域,所以收敛曲线经常出现“阶梯式下降”。这既是优点也是隐患,在多峰问题上容易出现结果忽好忽坏的现象。

1.2 群体共享信息型:PSO、SSA、CSA、TSO

PSO不用过多解释,速度-位移模型,pbest和gbest分别提供个体记忆和社会记忆。惯性权重w前期大后期小,c1、c2分别控制“向自己历史最优飞”和“向群体最优飞”。优点是最好理解、实现容易、不容易出bug,缺点是后期gbest不变时,整个粒子群会围着同一个点抖动,基本没有跳出机制。

SSA这里我按樽海鞘群算法来写,也就是Salp Swarm Algorithm。它在代码里的特点是“链式移动”:第一个领导者更新后,后面每个跟随者只参考前一个体的位置,链头由食物源引导,系数c1从2衰减到0控制探索和开发。链式结构的优势是种群移动有方向性,但劣势也很明显:领导者一旦越界,整条链都会被带偏,因此边界处理比别的算法更关键。需要提醒的是,中文论文里也常把SSA当作麻雀搜索算法,那是完全不同的机制,下载代码前先确认你拿到的到底是樽海鞘还是麻雀。

CSA在标题里我按乌鸦搜索算法来展开。每只乌鸦代表一个解,并且会记住自己藏食物的位置。算法随机选另一只乌鸦,决定跟踪还是远离,参数fl控制飞行距离,AP是乌鸦发觉被跟踪的概率。AP越小,乌鸦越容易相信同伴,算法后期过快聚集;AP越大,群体越警惕,搜索越接近随机。我一般把AP放在0.1到0.2,fl取2左右,但这个组合在不同问题上并不通用。如果你在别的资料里看到CSA代表鸡群算法,基本是笔误或另一套代码,使用时务必先确认。

TSO是被囊群优化算法,模拟海洋被囊动物喷流推进和群体交流。喷流推进阶段生成新候选位置,群体交流阶段参考最优个体和当前个体的差异做加权更新。很多论文版本会把控制参数写成随迭代线性递减,效果上接近GWO的a。这个算法的中文资料相对少,Matlab代码风格差异很大,从网上下到版本后,先看它内部到底是最小化还是最大化寻优,否则实验方向直接跑反。

1.3 几何与非生物机制型:SCA、CGO

SCA正弦余弦算法不走生物路线,用sin和cos函数把候选解在新旧位置之间摆动。r1随迭代下降控制摆动幅度,r2决定移动半径方向,r3、r4产生随机性。低维问题上效果尚可,维度一高很容易振荡,属于“理解成本低、实战稳定性一般”的算法,更适合作为教学示例或者对比实验里的“差异性补充”。

CGO的完整名字是混沌博弈优化,源自混沌博弈理论和分形几何。它把当前最优位置、当前个体位置、以及若干随机个体当成“顶点”,每个种子在顶点围成的区域内按概率移动,生成下一代。CGO机制很像分形图形:每次都在缩小范围内选点,最终形成局部密集搜索。实际代码里它至少有四个不同的更新分支,随机性很强,单次运行很难看出真实水平。

算法全称/灵感位置更新核心关键参数最容易翻车的地方
GWO灰狼捕猎alpha/beta/delta加权a、A、C后期多样性不足
WOA座头鲸气泡网收缩包围+对数螺旋a、p螺旋与随机探索比例固定
HHO哈里斯鹰捕兔软硬围攻+俯冲E、q、r模式跳变导致波动
PSO鸟群觅食速度+个体/全局最优w、c1、c2全局最优卡死
SSA樽海鞘链领导者-跟随者链式c1、c2领导者越界带偏全链
CSA乌鸦藏食追随/逃跑+感知概率AP、fl参数敏感度过高
TSO被囊群推进喷流推进+群体交流衰减控制参数代码实现差异大
SCA正弦余弦摆动sin/cos位置摆动r1、r2高维振荡
CGO混沌博弈/分形四顶点随机投影多种随机分支单次运行极不稳定

2. 关键迭代逻辑:位置更新的共性和差异

2.1 统一接口,让9种算法都从同一个入口跑

跑对比实验时最大的错误,是每个算法单独写一个脚本,用到的时候临时改参数。几个月后自己都忘了哪个版本对应哪张图。我后来把代码统一收成一个runOptimizer入口,所有算法返回bestX、bestF、convergence,后续只需要写一个测试脚本循环调用:

function [bestX, bestF, curve] = runOptimizer(optName, objFun, dim, lb, ub, MaxIt, nPop) switch optName case 'PSO' [bestX, bestF, curve] = PSO(objFun, dim, lb, ub, MaxIt, nPop); case 'GWO' [bestX, bestF, curve] = GWO(objFun, dim, lb, ub, MaxIt, nPop); case 'WOA' [bestX, bestF, curve] = WOA(objFun, dim, lb, ub, MaxIt, nPop); case 'HHO' [bestX, bestF, curve] = HHO(objFun, dim, lb, ub, MaxIt, nPop); case 'SSA' [bestX, bestF, curve] = SSA(objFun, dim, lb, ub, MaxIt, nPop); case 'CSA' [bestX, bestF, curve] = CSA(objFun, dim, lb, ub, MaxIt, nPop); case 'TSO' [bestX, bestF, curve] = TSO(objFun, dim, lb, ub, MaxIt, nPop); case 'SCA' [bestX, bestF, curve] = SCA(objFun, dim, lb, ub, MaxIt, nPop); case 'CGO' [bestX, bestF, curve] = CGO(objFun, dim, lb, ub, MaxIt, nPop); end end

这种结构的好处是,你后面想换成自己的目标函数,只需要保证objFun接收一个nPop×dim矩阵,返回每个个体的适应度列向量,所有算法代码都不用动。

2.2 种群初始化必须用同一套语法

初始化时我统一这么写:

Positions = rand(nPop, dim) .* (ub - lb) + lb;

很多算法代码里直接写成rand(nPop,dim)*ub,把lb丢了。测试函数的下界不是0时,初始种群就全错。表面上看每个算法都“初始化了”,实际起点范围完全不同,对比结果没有意义。另外,目标函数建议写成支持矩阵输入的向量化版本,不要循环单个个体,否则跑高维度时会非常慢。

function f = sphere(x) f = sum(x.^2, 2); % x是nPop×dim矩阵,f是nPop×1 end

2.3 参数设置的常用基线

不同算法参数没有一个万能组合,但我整理了一套不容易出大问题的起步值:

算法我常设的参数为什么这么设
GWOa: 2→0,A=2arand-a线性衰减控制探索开发
WOAa: 2→0,p∈[0,1]让后期螺旋更集中
HHOE: 2→0,q∈[0,1]E小于1后才进入围攻
PSOw: 0.9→0.4,c1=c2=2经典取法,审稿人不会质疑
SSAc1: 2→0,c2随机链头向食物源,链尾跟随
CSAAP=0.1~0.2,fl=2AP太大就退化成随机搜索
TSO衰减系数2→0多数开源版本默认逻辑
SCAr1: 2→0控制sin/cos摆动幅度
CGO随机分支选择算法本身没有固定主参数

就算按这些初始值跑,同一组参数在不同函数上的表现差异也很大。真正写论文时,除了默认参数外,最好补一个简单的参数敏感性分析,不然审稿人一句“参数怎么来的”就能把实验结论打穿。

3. Matlab对比实验:真实跑下来应该怎么设计

3.1 测试函数不能只选一个

对比实验只跑一个函数,说服力很低。我通常至少选三个形态不同的函数:单峰Sphere或Rosenbrock,多峰Rastrigin或Ackley,固定维度的CEC基准。维度也要分开,低维用10维,中维用30维,高维可以到100维。注意,这里的维度指决策变量个数,不是测试函数的种群数,很多人会把这两个概念搞混。

测试函数统一写成支持向量化输入的形式。如果拿到的函数是for循环逐个点算的,建议改成矩阵运算,不然9个算法×3个函数×30次独立运行,时间会非常难熬。

3.2 独立运行次数和统计口径

智能优化算法是随机算法,跑1次没有意义。我习惯每个算法每个函数独立运行30次,记录每次得到的最优适应度,再算均值、中位数、标准差。为什么同时看均值和中位数?因为单峰函数上均值接近中位数,但在Rastrigin这种多峰地形上,某一次跳出局部最优会让均值大幅偏移,只看均值会高估算法稳定性。

有条件的话,再做一个Wilcoxon秩和检验,把PSO当Baseline,看新算法相对Baseline的提升是否有显著性。很多审稿人看到你只贴三条收敛曲线,不会说太多,但看到均值好却不给统计检验,就会追问显著性结果。

3.3 记录收敛曲线时,用评价次数而不是迭代次数

这是最容易忽略的公平性问题。PSO一次迭代通常只评价nPop次适应度,但HHO、CGO这类算法内部有多个分支,每个分支里可能又调用了一次目标函数,实际评价次数是迭代次数×nPop×分支倍数。如果你统一设定MaxIt=500,那9个算法的工作量其实完全不一样。

我的做法是在每个算法的适应度评估处统一维护一个FEs(Function Evaluations)计数器,收敛曲线的横坐标用FEs而不是迭代次数。只有这样,不同算法才能在“花了同样计算量”的前提下比较。顺手也把每一轮的gbest记录成curve数组:

convergence(t) = bestF;

3.4 实验脚本的标准流程

一个完整的对比实验流程应该是:先确定测试函数和维度,再确定nPop和MaxIt,然后每个算法独立跑30次,每次记录最终bestX、bestF和convergence曲线。最后把所有结果汇总到一个结构体里,用箱线图看分布,用均值标准差做表格,用秩和检验做显著性。不要急着画带阴影的收敛图,先把数据形态看清楚。

4. 我跑Sphere和Rastrigin之后看到的排序和反直觉结论

4.1 单峰Sphere上,老牌算法根本不落下风

在Sphere这种简单单峰函数上,我跑下来的直观感受是:PSO和GWO完全能和新算法打平。PSO收敛快,低维度时几乎每轮都在往下压;GWO稳步下降,曲线很“体面”;WOA前期跳跃明显,后期也能拿到接近较好的值。真正在Sphere上容易出问题的往往是SCA和CSA,它们的后期收敛会出现一段明显的“平台期”,感觉像步子太小,卡在某个量级下不去。

这里有一个反直觉的点:网上很多论文里展示的漂亮曲线,往往只挑了最优的一次运行结果。同一个HHO在Sphere上多跑几次,前期曲线可能有很大差异,有的版本甚至前50次迭代下降很少,后面突然又跳一次。选哪条曲线、怎么说明稳定性,比单纯说“最小适应度更低”更重要。

4.2 Rastrigin上,HHO、WOA和GWO各有各的挣扎方式

Rastrigin函数局部最优极多,10维就已经很容易把算法困住。GWO刚开始下降很快,但进入后期后所有灰狼都集中到同一个局部峰附近,基本没有能力再大幅跳出去。WOA的优势在于螺旋绕行,偶尔能跳到相邻的峰,代价是消耗更多评价次数。HHO如果能量衰减参数E设置得太快,后期所有个体都会进入硬围攻模式,结果被锁在局部区域;但如果E衰减偏慢,它又会浪费大量评价次数在外围瞎飞。

CGO在Rastrigin这类函数上表现很有戏剧性,单次运行有时能挖到很不错的适应度,有时差得离谱。我把它当成“抽奖类”算法,实验时必须增加独立运行次数,否则极容易在报告里得出错误排名。TSO的行为很大程度取决于你下载到哪个实现版本,有的版本做了局部搜索改进,有的版本还是原始喷流推进,代码水平直接决定结果。

4.3 箱线图比收敛曲线更诚实

多跑几次以后,我把9个算法的最终适应度做成箱线图,发现中位数和均值的差距经常被忽视。某个算法平均适应度更小,可能是靠一次偶然的优秀结果拉高,但中位数很差。所以我在报告里固定给出mean±std和中位数,并且画箱线图。收敛曲线看趋势,箱线图看分布,两张图配合使用,才不容易被审稿人挑刺。

下面是我在固定10维、种群30、迭代500次时观察到的大致行为,只反映相对倾向,不写具体数值,因为换一组参数结论就可能变:

算法Sphere表现Rastrigin表现稳定性我的主观建议
PSO收敛稳定中位数稳定,极值普通高适合做Baseline
GWO稳步下降前期快,后期平缓中参数a影响大
WOA中后期可能跳出局部探索和开发较均衡中多峰可以试
HHO前期剧烈,后期集中波动大,偶发好结果低必须多跑几次
SSA链式移动整体性强注意越界问题中边界处理要严格
CSA结果依赖AP和fl容易早聚低参数单独调
TSO实现版本差异大版本决定结果低到中先确认代码逻辑
SCA低维可行,高维偏弱摆动明显中教学或对照用
CGO单次波动大偶发优秀结果低当作随机性强的对比项

5. 那些容易被忽略的工程细节:不止是调参

5.1 越界处理方式必须写清楚

算法位置更新时很容易跳出自变量范围。常见处理有三类:把越界个体拉回边界,把越界坐标按边界反弹,重新随机生成一个位置。很多论文完全不提这一点,但影响很大。我默认使用“拉回边界”,也就是:

Positions = max(Positions, lb); Positions = min(Positions, ub);

这样操作简单,也不算浪费个体。对SSA这类链式结构,领导者一旦越界,后面的跟随者可能全被带偏,所以更要在每一次位置更新后马上加一次边界裁切。CGO这类多分支算法,如果使用“反弹”模式,数值上容易出现振荡,反而不如直接截断来得稳定。

5.2 最大化和最小化方向必须统一

很多开源算法内部默认按最小化写,但你实际可能是要最大化分类准确率或产品收益。如果直接把准确率传进去,算法会拼命让准确率变小。正确做法是在目标函数里返回负准确率,或者把问题转换成损失。我之前见过有人把SCA和CGO用反,最后结果和另一个算法差了好几个数量级,查了半天发现是优化方向写错了。

5.3 gbest更新顺序的坑

记录全局最优时,最常见的问题是在某个分支里更新了gbest变量,但下一次位置更新用的还是更新前的旧位置。这样记录曲线会正常,实际上个体追逐的目标是“上一版的gbest”,逻辑上存在半拍延迟。我建议每一轮迭代结束后,统一评估整个种群的适应度,再更新alpha、beta、delta或gbest。代码看起来多执行了一次筛选,但不容易出现变量覆盖错误,调试起来也省心。

5.4 从测试函数迁移到真实问题时怎么办

9个算法在Sphere和Rastrigin上跑得再好,也不等于能直接解决工程问题。比如做光伏MPPT,决策变量是占空比,需要处理电压电流的非线性关系;做PID整定,要同时优化三个参数,还要考虑系统稳定性约束。我的做法是,先小规模跑通接口,把objFun替换成我的实际计算模型,用较小的nPop和MaxIt验证每一轮种群更新是否合理,再逐步放大工作量。否则一上来就9个算法全跑,光等待时间就能把人耗没。

6. 选型逻辑与个人使用建议

6.1 按问题类型选算法,而不是按论文年份选

新算法不一定适合你的问题。我的选择逻辑大概是这样:

  • 做PID参数整定、电力调度这类连续参数优化,PSO和GWO是稳妥的起步选项,代码容易改,出问题也好定位。
  • 做特征选择这类离散问题,需要把连续位置转成二进制,SCA和CGO的连续振荡特性反而麻烦,一般先试PSO配合阈值转换。
  • 做高维复杂多峰问题,WOA和HHO可以尝试,但必须多跑几次看分布,不要因为一次好结果就下结论。
  • 做论文对比实验,最合适的组合是一老(PSO或GWO)、一新(HHO或SSA)、一小众(CGO或TSO),既有辨识度又不至于被质疑算法过老。
  • 如果只是自己学习元启发式算法,先啃PSO和GWO,再啃WOA和HHO,最后再碰CGO和TSO,否则你很难判断随机波动到底来自算法还是实现。

6.2 发论文或写报告时,实验配置要交代完整

我整理实验时固定写清楚:Matlab版本、操作系统、统一种群大小和迭代次数、独立运行次数、边界处理方式、每个算法的参数来源是默认还是网格搜索、收敛曲线横坐标用的是迭代次数还是评价次数。这些东西写在附录里,看着琐碎,但能显著提高实验可信度。有人只放三张收敛图,换一版参数可能结果完全相反,后面被要求复现时很难处理。

6.3 最后分享一个个人习惯

我自己写对比模板时,所有算法都是runOptimizer这种统一接口。遇到新问题,我先用PSO跑三遍,得到一个“不太费力就能达到”的参考水平,再用其他算法去比。如果某个新算法连PSO都打不过,那大概率不是我用的测试函数太简单,而是它的默认参数在你这套代码里没调好,或者代码逻辑本身有问题。先用最稳的Baseline探底,再让新算法上场,这是最不容易冤枉某个算法、也最容易排查bug的顺序。9种算法的对比实验,真正值钱的不是你能说谁最强,而是你能说清楚它们各自在什么条件下强、什么条件下失效。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询