
简介针对单目标优化问题基于自适应权重与列维飞行策略的改进鲸鱼优化算法代码包在智能优化算法研究领域具有广泛的应用价值尤其适用于神经网络预测、路径规划、图像处理等多种场景可供本科、硕士阶段教研学习也可作为课程设计或毕业设计的算法基准。代码包共包含十二个文件以七个m脚本文件为主涵盖基准算法、改进算法、列维飞行、初始化、测试函数与绘图等模块另有说明文档、结果图片以及自动保存文件整体压缩包仅四百八十二KB体量小巧便于下载整包使用。目前已有四百五十七人参与学习代码基于Matlab 2014a与2019a版本编写运行主程序即可复现改进算法的寻优过程配合测试函数与绘图模块可直观对比不同策略的收敛精度和稳定性。对研究自适应权重、列维飞行策略在鲸鱼算法中的融合效果提供了一套完整的实验支撑与代码参考。1. 改进鲸鱼算法把早熟和收敛慢一起治的自适应权重与Levy飞行先给结论标准鲸鱼优化算法WOA在单目标连续优化上的复现成本很低但它在Rastrigin这类多峰函数上非常容易早熟在Ackley上又经常出现“前半程大步长跑得欢、后半程原地打转”的收敛断层。改进点集中在两处一是给位置更新挂上随迭代递减或随个体排名变化的自适应权重让算法后期敢在全局最优附近精细搜索二是引入Levy飞行的偶发大步长在探索阶段维持跳出局部最优的能力。两个机制一收一放配合标准的精英保留策略就是这类题目最常见的落地实现。这篇博文直接从标准WOA的更新公式讲起把自适应权重和Levy飞行分别改在哪个位置、参数怎么设、基准函数怎么对比讲清楚最后给出可直接运行的MATLAB核心代码。适合刚接触智能优化算法、想快速跑通改进思路并替换成自己目标函数的工程师和学生。2. 标准鲸鱼优化算法WOA的更新公式回顾与A、C参数边界2.1 包围、气泡网螺旋、随机搜索三种更新机制各自在干什么标准WOA的核心是模拟座头鲸的泡泡网捕食行为每个个体在每一代按照概率p选择探索策略或开发策略。三种位置更新机制的数学形式必须先明确因为后续所有改进都是在下面三个式子上做改动。第一个是包围机制。当随机数p小于0.5且|A|小于1时个体向当前全局最优位置收缩逼近更新公式为X(t1) X*(t) - A·D其中D |C·X*(t) - X(t)|。这里的A控制“逼近步长”C控制对最优位置的随机放大或缩小计算方式为A 2a·r - a、C 2rr是[0,1]均匀随机数a从2线性递减到0。第二个是气泡网螺旋更新。当p大于等于0.5时个体沿着对数螺旋线向全局最优靠近公式为X(t1) D·exp(b·l)·cos(2πl) X*(t)其中D |X*(t) - X(t)|b是螺旋形状常数通常取1l是[-1,1]范围的随机数。这个机制只围绕全局最优做局部开发不做任何探索。第三个是随机搜索。当p小于0.5但|A|大于等于1时个体放弃跟随全局最优改为跟随种群中随机选出的一个个体公式为X(t1) X_rand(t) - A·D其中D |C·X_rand(t) - X(t)|。这是标准WOA唯一的全局探索通道但随机选择目标个体的方式非常粗糙很容易让种群在多个局部极值之间反复横跳。2.2 最小可运行的WOA主循环MATLAB代码标准WOA的实现是所有改进版本的地基推荐先跑通下面这段最小代码再往上加东西。代码保留了原始论文的更新逻辑额外做了一处常见工程化处理子代与父代做贪心比较只有适应度变好才替换避免振荡。function [Best_pos, Best_val] WOA(fobj, dim, lb, ub, N, Tmax) % fobj: 目标函数句柄, 输入1×dim向量返回标量 % N: 种群规模, dim: 决策变量维度, lb/ub: 边界(标量或1×dim) X rand(N, dim) .* (ub - lb) lb; % 均匀随机初始化 fit arrayfun((i) fobj(X(i,:)), 1:N); % 初始适应度 [Best_val, idx] min(fit); Best_pos X(idx, :); for t 1:Tmax a 2 - 2 * t / Tmax; % a从2线性衰减到0 for i 1:N A 2 * a * rand - a; % A的取值范围是[-a, a] C 2 * rand; % C的取值范围是[0, 2] p rand(); b 1; l -1 2 * rand(); if p 0.5 if abs(A) 1 D abs(C .* Best_pos - X(i,:)); X_new Best_pos - A .* D; % 包围机制 else r randi(N, 1); D abs(C .* X(r,:) - X(i,:)); X_new X(r,:) - A .* D; % 随机搜索 end else D abs(Best_pos - X(i,:)); X_new D .* exp(b * l) .* cos(2 * pi * l) Best_pos; end X_new min(max(X_new, lb), ub); % 越界裁剪到边界 f_new fobj(X_new); if f_new fit(i) % 贪心保留 X(i,:) X_new; fit(i) f_new; end if f_new Best_val Best_val f_new; Best_pos X_new; end end end end逐行看几个关键点。初始化用rand(N,dim) .* (ub - lb) lb生成均匀分布初始种群这是群智能算法最常见的初始化方式。A 2*a*rand - a让A在[-a,a]内随机波动a随迭代从2降到0所以算法前期A的幅度大、探索能力强后期A趋近于0、所有个体都被拉向全局最优。l -1 2*rand()生成[-1,1]均匀随机数控制螺旋线的绕行位置。这里的arrayfun只是博文演示用的可读写法实际做高维实验时建议把适应度计算改成向量化循环否则N50、Tmax1000、dim30时会有5万次函数调用遇到非向量化目标函数会非常慢。2.3 参数边界表a、A、C、p怎么取值才算合理标准WOA看似只有四个主要参数但每个参数的取值直接决定了改进点要挂在哪。参数取值范围作用阶段对搜索行为的影响a2递减到0全局a大时A幅度大个体容易大范围跳跃a小时所有更新都收敛向局部区域A[-a, a]包围/随机搜索C[0, 2]包围/随机搜索对目标位置距离做随机缩放C1放大距离、C1缩小距离p[0, 1]全局p0.5走包围或随机p≥0.5走螺旋各占50%概率值得注意的坑是很多复现版本把随机搜索写成abs(A) 1才执行这会把探索概率压到极低导致算法退化成纯开发模式。正确做法是保留abs(A) 1分支。另一个常见误会是C只作用于距离D的缩放不会影响A的方向判断两个参数各管各的改进时不要合并它们。标准WOA最大的问题也在这张表里泄漏了|A|的阈值切换和p的50%概率都是固定的没有随种群状态动态变化。改进工作通常从两个方向入手改变步长的尺度自适应权重或者改变跳出机制Levy飞行。3. 自适应权重改进鲸鱼算法的权重公式与MATLAB实现3.1 线性递减权重和基于排序的权重哪个更稳自适应权重的核心思想是给位置更新公式前乘一个随迭代推进而变化的系数w控制“对当前位置的保留程度”和“对最优位置的信任程度”。最常见的两种设计是迭代线性递减和基于适应度排序。迭代线性递减的公式是w w_max - (w_max - w_min) * t / Tmax。它的优点是只有一个参数、复现容易、对大多数基准函数都稳定缺点是种群所有个体共享同一个权重无法区分好个体和差个体。我一般把它作为对比基线。基于排序的权重公式为w_i w_max - (w_max - w_min) * (rank_i - 1) / (N - 1)其中rank_i是第i个个体按适应度好坏排的序号最优个体rank1最差个体rankN。这样做的效果是差个体保留自身位置的比例小被拉到最优附近的速度快好个体保留自身位置的比例大局部精细搜索更充分。缺点是需要额外排序而且要处理适应度相等导致的并列排名。实际做改进时我更推荐排序权重因为它的自适应信息来自种群真实状态而不是简单地按迭代次数线性收窄。迭代权重在Tmax设得过大时后期w会跌到特别小螺旋更新可能直接退化到最优位置附近一个极小的邻域排序权重则不会出现这个问题它始终保留一定的个体差异。3.2 在包围和螺旋更新中挂上权重的两行代码自适应权重挂在哪两个公式上直接决定改进效果。常见的做法是在包围机制中给当前个体乘w在螺旋更新中给全局最优乘w。逻辑上包围阶段个体正在向最优靠拢权重越小、当前个体保留越少、越敢大步走向最优螺旋阶段个体绕着最优转圈权重越小、最优位置被压缩得越狠转圈半径越小后期精细搜索能力越强。% 修改包围机制对当前个体乘自适应权重 w 0.9 - 0.5 * (t / Tmax); % 线性权重, w∈[0.4, 0.9] D abs(C .* Best_pos - X(i,:)); X_new w .* X(i,:) - A .* D; % 原式X_new X(i,:) - A .* D % 修改螺旋更新对全局最优乘自适应权重 D_sp abs(Best_pos - X(i,:)); X_new D_sp .* exp(b * l) .* cos(2 * pi * l) w .* Best_pos;排序权重版本只需把前面的w换成每个个体自己的w_i核心更新公式不变。验证权重改进是否有效应固定相同的初始种群、相同的Tmax和N分别跑标准WOA和权重改进WOA对比30次实验的中位收敛曲线。如果权重真的起作用收敛曲线的中期下降斜率应该更陡而不是只看最终精度。3.3 权重范围与实验设置w_max、w_min到底取多少权重范围取决于你希望算法偏向探索还是开发。w_max接近1时前期个体几乎完全保留自身位置探索性增强w_min接近0时后期几乎直接跳到最优位置开发性增强。经验范围如下。权重策略w_maxw_min适用场景保守线性递减0.90.4多峰函数避免后期权重过小过早收敛激进线性递减0.950.2单峰函数追求收敛速度排序权重0.950.5混合形态函数兼顾个体差异需要注意w的取值范围不能包含负值负权重会让个体向最优的相反方向运动破坏收敛性。另一个容易踩的坑是权重乘错对象把w乘到A或者D上会改变步长的符号和尺度导致算法行为完全失控。我在调试时遇到过类似问题现象是收敛精度比标准WOA还差几个数量级排查后发现权重挂在了A .* D前面而非当前个体或最优个体上。4. Levy飞行生成器Mantegna步长算法与三种嵌入主循环的方式4.1 Levy飞行为什么能跳出局部最优均值小、方差大的数学直觉Levy飞行是一种步长服从Levy分布的随机游走其核心特征是“大多数时候走小步、偶尔走大步”步长的概率密度尾部比高斯分布厚很多。用数学语言说Levy分布的方差发散理论上无界大步长出现的概率比正态分布高一个数量级以上因此它天然适合给优化算法提供偶发的大幅跳跃能力。把它嵌入WOA的逻辑非常直接标准WOA的随机搜索是随机找一个个体做差步长幅度有限而Levy飞行的长尾特性能在探索阶段制造跨越大片搜索区域的跳跃。如果当前个体已经陷入局部最优一次Levy大跳有可能直接把它扔到搜索空间另一端这就是改进算法在Rastrigin这类多峰函数上能拉开差距的根源。但Levy飞行不能无节制使用。如果每一代每个个体都叠加Levy步长算法会退化成纯随机搜索。常见做法是只在使用随机搜索机制时触发或者只对全局最优个体做周期性的Levy扰动。具体用哪种需要看你的目标函数形态。4.2 Mantegna算法的MATLAB实现与beta取1.5的理由实际生成Levy步长最常用的是Mantegna方法它用两个正态随机变量的比值构造Levy分布算法简单、生成速度快。beta参数控制分布尾部厚度beta越小尾部越厚、大跳越频繁。function L levy_flight(n, dim, beta) % Mantegna方法生成Levy分布随机步长 % n: 生成步长个数, dim: 决策变量维度, beta: 通常取1.5 sigma_u (gamma(1 beta) * sin(pi * beta / 2) ... / (gamma((1 beta) / 2) * beta * 2 ^ ((beta - 1) / 2))) ^ (1 / beta); u randn(n, dim) * sigma_u; v randn(n, dim); v(v 0) 1e-12; % 防止v0导致步长无穷大 L u ./ (abs(v) .^ (1 / beta)); endbeta1.5是各类改进文献里最常见的设置。这个值下sigma_u约等于0.697步长分布既保留足够的重尾特征又不会让大步长出现得过于频繁。如果你发现算法后期还在频繁大跳可以把beta提高到1.8左右让步长分布更接近高斯分布如果前期探索严重不足把beta降到1.2会获得更多大跳机会。注意生成的是n×dim的随机矩阵直接叠加到种群矩阵或个体向量上都方便。尺度问题在后面6.3节专门讲这里先记住Levy步长一定要乘一个缩放因子alpha通常取alpha 0.01 .* (ub - lb)否则Levy步长的绝对量级可能超过搜索域几个数量级。4.3 三处嵌入初始化、探索替换、最优扰动嵌入位置修改方式推荐参数效果种群初始化初始解叠加Levy步长再夹逼到边界alpha0.01·(ub-lb), beta1.5初始种群分布更分散多样性强随机搜索替换用Levy步长替换原X_rand - A·D仅A最优个体扰动每隔若干代对全局最优叠加Levy步长每5代一次, alpha0.001·(ub-lb)帮助全局最优逃逸局部极小下面给探索阶段替换的代码片段这是我对标准WOA最常做的第一处改造。if p 0.5 if abs(A) 1 D abs(C .* Best_pos - X(i,:)); X_new w .* X(i,:) - A .* D; else r1 randi(N); r2 randi(N); L levy_flight(1, dim, 1.5); alpha 0.01 * (ub - lb); X_new X(r1,:) alpha .* L .* (X(r2,:) - X(i,:)); end else % 螺旋更新保持不变 end如果你不想改动随机搜索结构也可以只做前两种嵌入初始化时叠Levy步长让初始解铺得更开探索阶段用Levy替换随机个体。两种方式可以独立开关我建议先只开探索阶段的Levy替换跑一轮对比再加初始化叠加逐项验证而不是一次全上。全部改满后如果效果反而变差优先怀疑是Levy步长alpha设置过大导致震荡而不是机制本身的问题。5. 用改进鲸鱼优化算法求解单目标优化问题的完整MATLAB程序与基准测试5.1 把自适应权重和Levy飞行整合进IWOA主函数框架把前面两章的改动拼进一个完整的改进WOA主函数保持函数签名与标准版一致方便直接替换目标和边界参数。这个函数本质上就是给你提供一份可以直接改的骨架。function [Best_pos, Best_val, curve] IWOA_aw_levy(fobj, dim, lb, ub, N, Tmax) % 自适应权重 Levy飞行的改进鲸鱼优化算法 X rand(N, dim) .* (ub - lb) lb; L0 levy_flight(N, dim, 1.5); % 初始化叠加Levy步长 X X 0.01 .* (ub - lb) .* L0; X min(max(X, lb), ub); fit arrayfun((i) fobj(X(i,:)), 1:N); [Best_val, idx] min(fit); Best_pos X(idx, :); curve zeros(1, Tmax); for t 1:Tmax a 2 - 2 * t / Tmax; [~, idx] sort(fit); [~, rank] sort(idx); for i 1:N w 0.95 - 0.45 * (rank(i) - 1) / (N - 1); % 基于排序的自适应权重 A 2 * a * rand - a; C 2 * rand; p rand(); if p 0.5 if abs(A) 1 D abs(C .* Best_pos - X(i,:)); X_new w .* X(i,:) - A .* D; else r1 randi(N); r2 randi(N); L levy_flight(1, dim, 1.5); alpha 0.01 * (ub - lb); X_new X(r1,:) alpha .* L .* (X(r2,:) - X(i,:)); end else D abs(Best_pos - X(i,:)); b 1; l -1 2 * rand(); X_new D .* exp(b * l) .* cos(2 * pi * l) w .* Best_pos; end X_new min(max(X_new, lb), ub); f_new fobj(X_new); if f_new fit(i) X(i,:) X_new; fit(i) f_new; end if f_new Best_val Best_val f_new; Best_pos X_new; end end curve(t) Best_val; end end这个函数把三个改进点都打开初始化Levy叠加、探索阶段Levy替换随机游走、包围与螺旋的自适应权重。我认为它最需要解释的是排序权重的实现方式。sort(fit)得到升序索引sort再作用在索引上得到每个个体对应的排名rank1是最优个体rankN是最差个体。最优个体权重最大为0.95最差个体权重最小为0.5。这样的好处是不需要额外调迭代权重范围种群状态变化时权重自动适应。如果出现收敛精度不升反降的情况建议逐一关闭改进项。先去掉初始化叠加的Levy再照顾探索阶段的Levy最后只保留权重。这种调试习惯能帮你快速定位是哪一处改动引入了负收益。5.2 五个基准函数测试设计与30次独立实验的统计口径验证改进算法是否有效只跑一次实验没有说服力。我建议固定下面这组配置作为基准实验种群规模N50最大迭代次数Tmax500维度dim30独立运行次数runs30记录每次运行的最优值、平均值与标准差。五个基准测试函数如下表。函数搜索范围理论最优值形态特征Sphere[-100, 100]0单峰测试基本收敛能力Rosenbrock[-30, 30]0病态单峰谷底平坦曲折测试精细搜索Rastrigin[-5.12, 5.12]0强多峰局部极值密集测试跳出能力Ackley[-32, 32]0多谷外圈平坦内圈深谷测试勘探-开发平衡Griewank[-600, 600]0多峰变量间强交互测试高维适应性Rastrigin是检验Levy飞行改进有效性的关键函数。它在每个维度上都有大量均匀分布的局部极小标准WOA往往收敛到某个非零局部解后就再也不动而改进WOA依靠探索阶段的Levy跳有概率直接跃过几个波峰落到更优盆地。如果在这类函数上改进算法仍然和标准版打平基本可以断言机制没嵌入对。对比统计口径上记录mean,std,best三列数据并做符号秩和检验判断显著性。表格推荐直接复制下面这个表头格式函数算法最优值平均值标准差成功率(阈值1e-8)成功率的定义是运行30次中最终最优值小于阈值1e-8的次数占比。注意阈值要根据函数特性调整Sphere收敛到1e-15很常见但Rosenbrock在dim30时能收敛到1就非常优秀统一用1e-8会得出误导性结论。5.3 边界处理与收敛曲线绘制要点边界处理上我只用了最保守的clip裁剪。裁剪的副作用是当大量个体越界时它们会被压在边界上导致搜索多样性下降改进WOA加了Levy大步长后越界概率比标准版高更容易出现这个问题。更稳的做法是把越界个体随机重置到边界内部的随机位置牺牲一点收敛速度换取种群多样性。收敛曲线用semilogy画因为改进后的算法经常能把最优值压到1e-10以下线性坐标完全看不出差异。绘制前对所有值做max(curve, eps)保护避免最优值恰为0时log取不到。画30次实验时不要30条线一起画先用median(curve_all, 1)画中位数曲线再画25%到75%分位阴影带图面才干净。6. 收敛曲线验证五步法与把目标函数换成物流配送路径成本6.1 五步法同一随机种子、30次统计、中位数曲线、semilogy、成功率判断你的改进WOA到底有没有效果我习惯按五步做验证缺一步都容易被单次实验的随机性欺骗。第一步是固定rng(0)保证标准WOA和改进WOA使用同一个初始种群这样第一代差异完全由更新机制带来初始随机性不参与干扰。第二步是每个算法独立跑30次人的肉眼容易被单次曲线误导中位数曲线才反映典型行为。第三步是绘制中位数收敛曲线并叠加25%到75%分位区间作为阴影带观察分布宽度。第四步是纵轴必须用semilogy否则Ackley在1e-5以下的收敛过程全被压扁。第五步是统计成功率按目标函数特性设定阈值Rastrigin用1e-8Rosenbrock用1e-2把“最终精度”和“稳定收敛次数”两个维度一起看。这五步走完你才能下结论。很多时候两个算法终值看起来差不多但标准WOA30次里只有5次跌进阈值区间改进WOA却稳定在28次以上这才是改进的真实价值。6.2 从Sphere换到物流配送路径成本函数变量映射与约束处理单目标连续优化的WOA直接解物流配送路径问题是接不上的因为路径决策本质是离散顺序。常见做法是把连续决策变量映射成访问顺序排序x向量的索引得到配送顺序再以总配送成本加上违约束罚项构造适应度函数。function cost vrp_cost(x, demand, dist, capacity) [~, order] sort(x); % 连续变量 - 配送顺序 route_cost 0; load 0; for k 1:length(order) load load demand(order(k)); if load capacity % 超载则累加罚项 route_cost route_cost 1e4 * (load - capacity); load demand(order(k)); end route_cost route_cost dist(order(k)); end cost route_cost; end这个代码的核心是sort把连续编码转为离散顺序同时把容量约束转成罚函数加进总成本。罚项系数10000要远大于正常运输成本否则算法会无视约束换取更短路径。换成实际业务时把dist改成你的距离矩阵索引、demand改成客户需求量即可其余搜索机制不用动。这也是用改进WOA接业务问题时最省事的落地路径。6.3 三个最容易忽略的细节Levy步长爆炸、适应度非向量化、边界重置所有找我要改进WOA代码的人运行后问的问题基本集中在三个地方。第一个是Levy步长爆炸v矩阵中出现接近0的值或者beta太小会导致步长巨大解决方法是v(v0)1e-12并让alpha按0.01*(ub-lb)自动缩放。第二个是适应度非向量化循环调用fobj在Tmax1000、N50时会明显变慢把适应度函数写成矩阵批量运算能快一个数量级。第三个是越界个体直接clip到边界会让边界附近堆积大量个体改成随机重置回搜索域内部更合理。调稳这三点之后你再回头看标准WOA在Rastrigin上卡住的那条平坦曲线、以及改进WOA在后期突然跳变到更低量级的曲线就能直观感受到Levy大跳和自适应权重各自起的作用。改进鲸鱼算法解决的是早熟而不是单纯跑得快把这条主线想清楚参数调试就有方向了。本文还有配套的精品资源点击获取