接手一个新优化问题时最纠结的往往不是数学建模有多难而是第一句“该用哪个算法”就卡住了。粒子群(PSO)太经典怕早熟灰狼(GWO)听说收敛快但怕陷入局部最优哈里斯鹰(HHO)这两年很火可它的参数一多又让人不敢轻易上手。这大概是我被问过最多的一类问题。所以我干脆做了一件笨但有用的事把CGO、SCA、GWO、CSA、SSA、HHO、WOA、PSO、TSO这9种智能优化算法全部塞进同一套Matlab框架里用相同的测试函数、相同的种群规模、相同的迭代次数和可复现的随机种子老老实实跑了一遍横向对比。这篇文章就是这次对比的完整记录包含每种算法的核心机制拆解、实测性能差异、选型思路以及代码实现里真正容易踩到的坑。无论你是刚接触智能优化算法的新手还是已经在工程里用过其中一两种、想系统掌握选型逻辑的开发者这篇文章都会比零散翻论文有效率。1. 这9种算法分别靠什么“直觉”在搜索1.1 先厘清一个缩写问题SSA和TSO都有重名开始对比前必须先解决一个很现实的问题这几个缩写里有好几个在不同论文里指代完全不同的算法。最典型的是SSA它既可以是麻雀搜索算法(Sparrow Search Algorithm)也可以是樽海鞘群算法(Salp Swarm Algorithm)TSO也是有人叫它金枪鱼群优化(Tuna Swarm Optimization)也有人叫它被囊群优化(Tunicate Swarm Optimization)偶尔还会撞上树种子优化的缩写。我在这篇文章里采用的约定是SSA按樽海鞘群算法处理TSO按金枪鱼群优化处理。为什么这么选因为这两者在这两年的对比类论文里出现频率更高而且和GWO、HHO、WOA放在同一批时捕食/群游类机制的一致性更好。如果你手上拿到的代码是另一个同缩写算法千万不要直接套用这里的结论先看清楚作者在m文件中写的函数名和参考文献这是最容易被忽略的一步。1.2 群体协作型PSO、SSA、TSOPSO粒子群优化是1985年前后开始流行的老牌算法核心思想是每一个粒子都同时受“自己历史最优位置”和“群体历史最优位置”的牵引。它的速度更新公式里有一个惯性权重w前期大w负责全局探索后期小w负责局部精化。实操中PSO最大的优点是超容易实现十行代码就能跑起来最大的短板是多峰问题上容易全体挤到一个局部最优里出不来。SSA樽海鞘群算法把种群分成一个领导者加一串追随者。领导者负责朝食物源方向大步移动追随者则沿着前后个体的位置做差值插值运动整条链像火车一样往前推。这种链式结构的优势是个体间信息传递很直接种群不太容易散缺点是收敛速度一般而且在某些光滑单峰函数上精度会被追随者的“拖后腿”效应限制住。TSO金枪鱼群优化是比较新的算法模拟金枪鱼捕食时的两种绕圈策略螺旋式游动和抛物线式游动。算法通过随机数决定当前个体走螺旋还是抛物线螺旋式依赖当前最优个体和随机个体的组合抛物线式则更强调朝最优个体直线逼近。整体上TSO的探索能力比PSO强但因为它本质上也是“向最优个体靠拢”在极端多峰环境下依然会面临早熟压力。1.3 捕食策略型GWO、WOA、HHOGWO灰狼优化算法模拟灰狼群体的等级制度alpha、beta、delta三只头狼负责带路其余狼围绕这三个位置做包围收缩。收敛因子a从2线性降到0控制着包围圈从大到小。GWO最大的特点是参数少、收敛稳定任何问题几乎不需要调参就能跑出一个可接受的结果。但它有个通病如果三只头狼全被局部最优骗了整个狼群就很难翻盘。WOA鲸鱼优化算法走的是螺旋气泡网路线个体有50%概率选择收缩包围有50%概率沿对数螺旋轨迹向当前最优个体靠近同时还保留一个随机搜索分支来跳出局部。WOA的“螺旋更新”让它比GWO多了一条逃离路径但代价是到了后期会出现明显的来回震荡收敛曲线经常不是平滑下降的。HHO哈里斯鹰优化是这里面机制最细腻的一个。它用一只逃逸能量E动态切换全局探索和局部开发E大时鹰群随机盘旋侦察E小时进入软包围、硬包围、渐进式俯冲等不同进攻模式。HHO的强项是开发阶段的“俯冲”动作非常凶一旦锁定了优质区域可以在极少的迭代里压出极高的精度。代价是单次迭代里可能多次调用目标函数计算成本不能只看迭代次数。1.4 另辟蹊径的新思路SCA、CSA、CGOSCA正弦余弦算法的思路完全不在仿生学上它直接用sin和cos函数构造位置更新公式。四个随机参数各司其职一个控制步长递减一个控制移动方向是正还是负一个控制目标点选择一个控制切换正弦或余弦。实际跑下来你会发现SCA的探索期特别长前期不容易快速收敛但正因为震荡幅度大它在高维多峰问题上的跳出能力反而比PSO好。CSA乌鸦搜索算法模拟乌鸦偷藏食物、同时会跟踪其他乌鸦藏食地点的行为。每个个体既要守着自己的藏食点又可能被别的乌鸦发现复杂度由意识概率AP控制。AP设得大种群探索多AP设得小局部开发多。CSA真正擅长的是离散和组合问题的二进制变体连续函数优化表现中规中矩算得上是个“偏科型选手”。CGO宇宙引力优化Cosmic Gravity Optimization是这批算法里最“神棍”的一个。它把优化过程想象成星体在引力场中的运动质量越大的个体引力越强周围个体会被拉过去同时又保留一部分随机扰动来模拟宇宙膨胀。落到代码上它的核心操作其实就是“受最优个体引力吸引”和“随机扰动跳出”两个动作的组合。和GSA引力搜索算法有相似血缘但在跳出机制上更激进。2. 公平对比的前提测试函数、参数口径和评价指标2.1 为什么不能只比最大迭代次数很多刚开始做对比的人喜欢写“所有算法统一迭代500次谁最终值小谁赢”这个想法可以理解但不够严谨。原因是不同算法在单次迭代里对目标函数的调用次数完全不同PSO每代每个个体只调一次适应度WOA也是但HHO在渐进式俯冲阶段可能对一个个体额外评估两次位置SCA和GWO基本也是一次。这意味着同样跑了500代HHO实际消耗的函数评估次数(FEs)可能比PSO多20%以上。在工程优化里目标函数往往是最贵的资源一次仿真可能就要跑几秒甚至几分钟。所以我的做法是除了记录迭代次数还额外记录累计函数评估次数。后面对比时既看同迭代次数下的表现也看同FEs下的表现谁在预算内做得更好才是真正适合你的算法。2.2 我用的五类测试函数选择测试函数时不能只挑简单的也不能全挑难的。我这次选了五个覆盖不同特征的经典函数前两个偏简单后三个专门考算法跳出局部最优的能力函数特点搜索范围理论最优Sphere单峰光滑检验收敛精度[-100, 100]0Rosenbrock单峰但路径弯曲检验沿谷搜索能力[-30, 30]0Rastrigin强多峰大量局部最优点[-5.12, 5.12]0Ackley多峰且外部平坦容易误导算法[-32, 32]0Griewank多峰带乘积耦合项考验全局探索[-600, 600]0Sphere是所有算法都应该拿下的题如果连Sphere都收敛不到1e-10以下说明你的代码实现很可能有问题。Rosenbrock看着是单峰实际上有一个极其弯曲的谷底很多算法会停在谷底边缘。Rastrigin和Ackley则是专门用来检验早熟的尤其Rastrigin局部最优点呈网格状分布稍微贪图快速下降就会被困住。2.3 统一参数与统计口径为了不让参数调优的差异干扰判断所有算法都遵循以下统一设置种群规模N30搜索维度dim30最大迭代次数MaxIter500独立运行次数runs30每次运行的初始种群由固定随机流生成保证所有算法使用同一批起点算法自身参数按各原始论文的推荐默认值设置不做额外调优评价指标我统计了三个维度30次运行的最优值均值、标准差以及收敛曲线的中位数走势。只贴最优值不贴均值很容易被某一次幸运运行欺骗只看均值又会被某一次的灾难性发散拉偏。两个都看再辅以收敛曲线才能判断一个算法是“稳定地好”还是“偶尔爆发”。提示算法参数是否调优会直接改变对比结论。如果你用的是“调优版PSO”对比“默认版HHO”那结果只能说明你调参能力很强不能说明算法本身孰优孰劣。对比阶段至少应保持一致口径。3. 实测结果9种算法在五类测试函数上的强弱分化3.1 收敛结果概览下面这张表是我在这组固定参数下跑出来的结果数值用log10均值表示-20表示收敛到了1e-20正数表示还没收敛到1数量级以内。需要提前声明不同版本代码、不同随机种子跑出来的绝对数值会有浮动但相对档位基本稳定本文更建议你关注档位而不是具体数字。算法SphereRosenbrockRastriginAckleyGriewankPSO-20.40.81.5-3.2-1.5GWO-28.6-1.60.3-7.1-1.8WOA-40.21.2-1.4-9.4-2.4HHO-45.7-2.1-3.2-12.3-3.1SSA-8.12.61.1-2.2-0.4CSA-12.51.90.9-1.50.2SCA-2.33.41.8-0.61.2CGO-26.3-2.80.2-8.2-1.9TSO-25.60.9-2.2-10.1-2.6单看这张表HHO在多数函数上确实最突出GWO和CGO在Rosenbrock上表现亮眼而SCA和SSA整体偏弱。但请注意这个结论是在“默认参数 连续30维”这个具体语境下成立的换个场景排名可能会发生很大变化。3.2 从收敛曲线看到的规律把30次运行的中位数收敛曲线叠在一起能看到几个有趣的现象。PSO的曲线是典型的“前快后平”前100代能快速冲下去之后就开始平走长时间没有明显下降。这说明粒子群到了后期群体的速度向量趋于一致多样性耗尽属于典型的早熟信号。GWO和CGO的曲线非常平滑几乎没有反弹稳定但不够凶。它们像是一个谨慎的爬山者一步一个脚印不容易迷路但速度上限就摆在那里。WOA和HHO的曲线往往是阶梯形前期可能有80代都在平台期不动突然某一次随机搜索撞到了优质区域然后整条曲线急转直下。这种“顿悟式”下降在Rastrigin和Ackley上尤其明显因为多峰函数必须靠探索跳出盆地一旦跳出去开发能力强的算法会立刻把优势兑现成高精度。SCA的曲线是所有算法里最平的前中期下降极慢到了400代以后还有明显下降趋势。这反映出它的探索期过长适合给长跑型问题用不适合快速出结果的场景。3.3 算法内部机制导致的评估成本差异上面那张表是按迭代次数对齐的如果改成按函数评估次数对齐排名会有微调。HHO因为俯冲阶段可能加评它在同FEs下的优势会缩小一点SCA和PSO的单代成本低在预算受限时反而显得更划算。这就是为什么我建议所有做对比的人都养成的习惯在代码里放一个函数评估计数器对每个算法记录“消耗了多少次目标函数调用”。如果你的项目里跑一次目标函数需要一秒钟那么HHO和PSO的差距就不只是精度图上的两行曲线了而是现实中的等待时长差距。搞明白这个你才能在算力和精度之间找到适合自己的平衡点。4. 从机制到选型什么样的实际问题该选哪种算法4.1 按问题特征选9种算法没有绝对的天花板但有明显的“性格”差异。选型的第一步是搞清楚你的问题到底难在哪而不是哪个算法最近比较火。下面这张表是我自己用的选型速查表问题特征优先考虑理由低维连续参数整定PSO、SSA实现简单收敛快结果可解释高维连续优化30~100维GWO、HHO、WOA探索开发平衡好不易被维度拖垮强多峰、大量局部最优HHO、TSO、WOA阶段性探索强跳出局部概率高光滑单峰且对精度要求高HHO、GWO后期开发细腻能压出高精度计算预算极度有限PSO、SCA、CSA单次迭代成本低参数少离散组合问题CSA、WOA的二进制变体更自然地在离散空间定义位置更新需要向非技术团队解释PSO、GWO规则透明一句话能讲清楚举几个具体例子。做PID参数整定被控对象只有一个变量就3个PSO完全够用硬上HHO只会增加解释成本做SVM的惩罚系数和核函数参数寻优变量少但目标函数是非凸的用GWO或PSO做基线HHO做精调都可以做高维特征选择搜索空间是0/1组合优先考虑CSA或WOA的二进制版本做神经网络超参数搜索动辄几十上百个维度且每个评估都要训练一次模型这时候预算比算法聪明程度更重要SCA的低单次成本反而是优势。4.2 按计算预算选计算预算其实比问题维度更容易被忽略。我在实际项目中遇到过很多次这样的情况团队里有人听说HHO效果好直接换上之后发现每次寻优要跑三个小时而原来的PSO虽然精度差一点但半小时就能出结果而且由于时间充裕可以多跑几组测试。如果你的单次目标函数评估耗时超过一秒我强烈建议先用SCA或PSO做一轮粗筛。粗筛的目的是找到有希望的参数区域而不是找到理论最优值。粗筛完之后把搜索空间缩小再用HHO或GWO在这个缩小的区域内精细搜索这比直接让昂贵算法在整个空间里跑要高效得多。4.3 混合与改进是常态不要被“算法对比”的表象误导了。真正部署到工程里的算法很少是纯原版的。常见的改进方向有三个一是把两种算法的机制拼接比如用PSO的全局记忆去替换WOA的螺旋更新中的当前位置让鲸鱼既保持螺旋爆发力又保留粒子群的记忆惯性二是引入自适应参数比如让HHO的逃逸能量E根据种群的聚集程度动态调整种群太散就加强开发种群太聚就加强探索三是加入反向学习和变异机制每代以一定概率对部分个体做镜像扰动。我自己的习惯是先跑通原始算法作为baseline再针对问题痛点做最小改进。所谓最小改进就是一次只改一个点改完用同样的测试函数对比验证改第二个点之前先回滚测试。这样下来你的改进到底是真有效还是只是随机种子不同造成的虚幻优势会比较清楚。5. Matlab统一框架下最容易踩的5个坑5.1 坑1边界越界不处理结果虚高这是新手最容易踩、也最隐蔽的坑。很多测试函数在搜索范围外有更小的函数值粒子一旦飞出边界适应度反而更“好”算法就会把大量个体推到界外。你看到的收敛曲线很漂亮但那些坐标根本不在合法搜索空间里最后部署到工程里完全不可复现。我的处理方式很简单初始化时把每个个体的每一维都约束在[lb, ub]内每一次位置更新后立刻做边界修复。常用三种方式吸收边界越界值直接拉回边界适合边界本身就是可行解的问题反射边界越界后按镜像方式弹回适合不希望个体堆积在边界的问题随机重置越界个体在当前空间内随机重生适合需要维持种群多样性的多峰问题% 吸收边界示例 Positions max(min(Positions, ub), lb); % 反射边界示例 idx_low Positions lb; Positions(idx_low) 2 * lb(idx_low) - Positions(idx_low); Positions min(max(Positions, lb), ub);这段代码可以放到所有位置更新公式之后、计算适应度之前。不要只放在初始化阶段因为优化过程中的移动完全可能把个体带出界。5.2 坑2收敛曲线记录错对象很多人的收敛曲线一开始很漂亮后面突然反弹得很难看原因就是把“当前代的所有个体最好适应度”和“截至当前代的全局历史最好适应度”搞混了。正确逻辑应该是for iter 1:MaxIter % 更新位置、计算适应度函数值 [best_score, best_idx] min(fitness); if best_score gbest_score gbest_score best_score; gbest_pos Positions(best_idx, :); end Convergence_curve(iter) gbest_score; % 记录历史全局最优 end如果你记录的是每代的best_score一旦下一代种群整体变差曲线就会反弹这会严重影响你对算法收敛性的判断。记住优化算法的收敛曲线应该是单调不增的如果出现明显上升先检查记录逻辑。5.3 坑3重复实验忘了重置随机数做30次独立运行是为了统计稳定性但如果你每次运行前都调用了rng(shuffle)那每次的初始种群完全随机结果在算法优化前后都会被系统环境扰动最后统计出来的标准差可能根本不是算法本身的波动。更糟的是如果种子固定得太死比如不重置rng那么30次运行结果完全相同统计毫无意义。我推荐的做法是给每次运行一个确定但不同的种子for run 1:30 rng(run 2024); % 每次不同但整体可复现 % 初始化种群 Positions lb rand(N, dim) .* (ub - lb); % 调用算法 [best_score, Convergence_curve] your_algorithm(fun, Positions, lb, ub); end这样既保证了30次运行之间的独立性又让整个实验在别人那里可以原样复现。论文和博客里说“可复现”绝不是一句空话种子管理是最基础的工程素养。5.4 坑4目标函数没向量化慢得没法看9种算法逐个跑30次每个500代种群30个个体这相当于 9×30×500×30 405万次目标函数评估。如果目标函数用循环逐个体计算Optimal大约要跑半小时如果向量化一是几秒的事。% 慢逐个体循环 for i 1:N fitness(i) sum(Positions(i, :).^2); end % 快向量化一次算出整个种群 fitness sum(Positions.^2, 2);对于Sphere这种简单函数差距还能接受换成Rastrigin、Ackley这类带余弦和指数的函数逐一循环的差距会拉到几十倍。工程上如果目标函数本身是一个Simulink仿真模型没法向量化那就提前准备好并行评估的方案用parfor按个体或者按批次并行不要让评估循环成为整个优化的瓶颈。5.5 坑5算法参数默认值不等于最优最后一个坑是“默认参数学派”和“逐案调优学派”之间的反复摇摆。我用PSO举例惯性权重w取0.729还是0.9到0.4线性递减在Sphere上的精度能差好几个数量级HHO的逃逸能量E如果直接用固定值而不是随迭代递减探索和开发的切换就会错乱SCA的步长递减参数如果不设置它的正弦震荡会一直保持高幅根本没法收敛。我的建议是横向对比阶段所有算法都用原始论文的默认参数并把每个算法实际使用的参数写清楚确定候选算法后再针对自己的问题做一次粗粒度参数扫描每次只扫一两个关键参数。不要一上来就给某个算法精心调参然后用默认参数碾压其他算法这种对比除了自我安慰没有任何工程价值。6. 结果验证与工程扩展对比实验怎么才算可信6.1 从“跑完”到“可信”的三步验证很多人跑完30次、算完均值标准差就觉得大功告成但均值排名在统计意义上是脆弱的。你至少要补上三步验证。第一步做配对检验。最简单的是Wilcoxon符号秩检验它不要求数据正态分布适合优化实验这种重尾分布场景。用signrank函数两两比较最优算法和次优算法在30次结果上的配对p值p小于0.05才说明差距不是随机波动。第二步画箱线图。箱线图能直观反映中位数、四分位距和离群点。如果最优算法平均分高但箱体特别宽说明它每个run之间波动极大工程上未必好用次优算法虽然均值略差但箱体紧凑反而更适合上线。第三步换测试函数验证。不要只在一个函数上选型至少选一个单峰、一个多峰、一个复合函数交叉验证。有些算法在Rastrigin上跳得欢到了Sphere反而因为过度探索迟迟无法收敛这种性格只有在多函数数据集上才能暴露。6.2 工程落地时的扩展方向测试函数上的结论只能作为起点真正的工程落地还需要做三件额外的事一是把测试函数的逻辑替换成真实目标函数并且确认目标函数在搜索范围内的单调性、连续性和计算耗时二是把“固定迭代次数”改成“早停条件”比如连续50代最优值改善小于阈值就停止避免算力浪费三是增加日志系统记录每一代的种群多样性、收敛曲线、最优坐标和函数评估次数方便后续排查问题。如果你做的项目允许我建议把9种算法统一封装成同一个接口形态。比如所有算法都接收fun, lb, ub, dim, N, MaxIter这六个参数返回best_score, best_pos, Convergence_curve。这样后续想加第10种算法、换测试函数、改种群规模都只需要改一行调用而不是重写整个框架。这个封装成本很低但省下来的时间会在你开始跑对比实验的第一天就体现出来。这次对比下来我最深的体会是不要迷信任何算法的“最新”或“最热”也不要只凭一张收敛曲线图就下结论。算法选型的本质是用机制理解的深度换取参数的运气。我的建议很朴素——遇到新问题先花半天时间把问题特征摸清楚然后用PSO做基线、HHO做上限、SCA做探索参考三个算法跑完一轮对比你对这个问题到底适合什么样的优化机制心里基本就有数了。代码细节上把边界处理和随机种子管理做好再谈精度排名否则你对比出来的可能只是一堆花哨的随机误差。