基于灰狼优化算法的VMD参数自动寻优Matlab实现

📅 发布时间:2026/9/9 3:08:27
基于灰狼优化算法的VMD参数自动寻优Matlab实现 先说个可能很多人都有过的经历在Matlab里手动调变分模态分解VMD的参数K从3试到8alpha从500试到4000跑一个下午最后分解出来的模态要么混叠要么直接“吞掉”了某个有效成分。这种调参方式不仅浪费时间而且换一组信号之前的参数就废了。后来我把灰狼优化算法GWO和VMD结合做了这个GWO_VMD自动寻优方案专门用来解决惩罚因子alpha和模态数K的选择问题效果比我预想的好很多这篇就把完整的Matlab实现、原理和踩过的坑都写出来。GWO_VMD的思路其实不复杂把VMD的参数组合当成灰狼种群中的个体位置用包络熵这类评价指标作为适应度函数让灰狼算法在搜索空间里自动找到使分解效果最好的那组参数。适合正在做信号分解、故障诊断、特征提取或者被VMD参数折磨过的同学参考。1. 手动调参 VMD 的真实痛点与引入优化的切入点1.1 为什么说 K 和 alpha 直接决定分解成败VMD变分模态分解相比EMD最大的优势是它有一个严谨的数学框架把信号分解问题转化为变分问题的求解。但框架严密的代价就是参数敏感模态数K决定了把信号分成几条分量惩罚因子alpha决定了每个模态的带宽约束强度。这两个参数要是没配对好后果很直观。K设小了多个频率成分挤在同一个模态里后续做包络谱分析时特征频率混在一起K设大了一个真实成分被拆成多个虚假模态出现严重的过分解。alpha也是一样这个参数在频域里控制模态围绕中心频率的紧凑程度alpha过大会让模态被“压扁”丢失有效频带的信息alpha过小又会让模态之间出现大幅重叠。手动调参最尴尬的点在于K和alpha并不是独立的。某个K值配合某个alpha区间效果很好换一个K值原本合适的alpha可能完全不适用。所以手动调的是一场二维搜索每次都要重新跑一遍完整的VMD然后肉眼观察频谱图和包络谱效率极低而且结论很难迁移到下一组信号。1.2 试过的“土办法”有哪些各自卡在哪里在没有做GWO_VMD之前很多人会用下面的思路尝试找参数。第一是网格搜索法。把K设成2到10alpha设成500到4000步长取500那就是9乘8一共72组参数每组都跑一遍VMD并算指标。看起来还行但问题是网格搜索的步长如果太粗很容易错过最优区域。把步长加密到100那计算量成倍增长而且本质上是在用蛮力信号一换就得重来。第二是根据经验公式粗设。比如有文献说alpha取2000附近效果比较稳定K根据频谱峰值个数估计。这个方法在平稳信号上有一定效果但一旦信号中包含噪声、冲击成分、调幅调频特征频谱峰值个数本身就很难数经验值经常失灵。第三是用中心频率观察法。先固定alpha从K2开始逐次增加观察分解得到的中心频率是否出现接近的重复值以此判断K是否过大。这个方法需要反复运行VMD而且没有约束alpha的机制alpha不合适时中心频率的分布规律也会被干扰。这些方法的本质问题都一样它们是单向的、静态的没有把K和alpha当成一个联合优化问题来处理。而GWO_VMD把参数选择变成了一个智能寻优过程在搜索空间中同时调整K和alpha用适应度函数自动评价每组参数的表现这正好补上了土办法的短板。2. 惩罚因子 alpha 在 VMD 数学模型里到底干了什么2.1 拉格朗日函数中的 alpha带宽的紧箍咒要真正理解GWO_VMD在优化什么就必须从VMD的数学模型出发搞清楚alpha在其中的角色。VMD的目标是把实值信号f(t)分解成K个模态u_k(t)每个模态都有一个对应的中心频率ω_k。从数学上讲要求解的是这样一个约束变分问题最小化所有模态的带宽之和同时保证模态之和等于原始信号。对模态带宽的度量方式是先对每个模态做希尔伯特变换得到解析信号再乘以一个指数项把频谱搬移到基带最后求梯度时间导数的L2范数。为了求解这个带约束的优化问题VMD引入了拉格朗日乘子λ和二次惩罚项。这里的关键就是二次惩罚项的权重正是惩罚因子alpha。惩罚项的值等于alpha乘以“模态之和与原始信号的残差”的平方。所以说alpha在数学上的角色是平衡“信号重构精度”和“模态带宽紧凑度”的权重系数。alpha越大算法越倾向于让模态之和严格逼近原始信号也就是减小重构误差与此同时带宽惩罚在代价函数中的相对占比也会变化进而影响每个模态的频带宽度。可以把它理解成一个类似L2正则化的系数——约束越强解的形态越受限制。2.2 频域更新公式看 alpha 对模态分离的影响VMD用交替方向乘子法ADMM迭代求解。每次迭代中模态在频域里的更新公式有一个非常标志性的形式每个模态的新频谱等于“原始信号频谱减去其他所有模态频谱再加上拉格朗日项的一半”再除以“1 2alpha(ω - ω_k)的平方”。这个分母是理解alpha作用的核心。当频率ω远离中心频率ω_k时差值的平方会变大如果alpha很大分母就变得非常大对应频率处的分量会被强烈抑制。这就形成了一个以ω_k为中心、宽度由alpha控制的带通特性。alpha越大分母衰减越快模态的频带越窄模态之间的频率重叠越少但代价是部分有效信息可能会被“削掉”。alpha越小分母衰减越平缓模态的频带越宽包含的信息更多但不同模态之间容易出现频谱重叠也就是常说的模态混叠。2.3 alpha 过大/过小在时频图中的实际表现把alpha的影响落到实际信号上看会直观很多。我用一组仿真信号做过测试信号由50Hz、120Hz和280Hz三个正弦分量叠加白噪声构成采样率1000Hz。alpha取500时120Hz分量和280Hz分量的频谱尾部明显拖尾两个模态的频带有交叠希尔伯特谱上能看到交叉污染。alpha取3000时每个模态的频谱非常“瘦”50Hz分量几乎被压成一根线谱但320Hz附近的一个弱调制成分完全丢了因为这个成分本来就在280Hz模态的频带边缘被惩罚项滤掉了。alpha取2000左右时三个主分量都分解得很干净重构误差也小。这说明alpha存在一个相对合理的区间而这个区间与信号本身的频谱结构密切相关。手动搜索这个区间性价比很低而把它交给GWO让它根据适应度函数自动逼近是更聪明的做法。3. 灰狼优化算法凭什么适合 VMD 参数寻优3.1 GWO 的核心机制一句话讲清灰狼优化算法是Mirjalili在2014年提出的元启发式优化算法模拟的是灰狼种群在捕猎时的等级制度和协作行为。整个狼群被划分为四个等级alpha狼头狼对应最优解、beta狼第二优、delta狼第三优以及omega狼剩余个体。优化过程中每只狼的位置代表一个候选解狼群通过追踪alpha、beta、delta三只头狼的位置来更新自己的位置。每次迭代时狼群先评估所有个体的适应度把最好的三个解记为alpha、beta、delta然后其余狼根据这三只头狼的位置重新定位形成“包围-猎杀”的动态过程。3.2 三头狼的领导机制与勘探-开发平衡GWO的搜索行为由两个关键系数控制系数A和系数C。系数A的取值范围是[-2a, 2a]其中a在迭代过程中从2线性递减到0。当|A|大于1时狼群偏离猎物的方向执行全局搜索这就是勘探exploration当|A|小于1时狼群向猎物方向收敛执行局部搜索这就是开发exploitation。C的取值是[0, 2]之间的随机数它为猎物位置添加随机权重目的是在搜索过程中引入随机性避免算法过早陷入局部最优。三头狼共同决定位置更新的好处在于它不像粒子群那样只跟着全局最优走而是综合了三个优秀解的方向信息。在VMD参数寻优这个场景里这意味着即使某个参数组合在初期表现不错但只要不是全局最优算法仍有能力跳出它的吸引域去探索更合适的K和alpha组合。3.3 相对其他元启发式算法GWO 在 VMD 场景的优势VMD参数量不大通常就是K、alpha有时加上tau。这个优化问题的维度很低但每个参数的适应度函数也就是VMD分解加包络熵计算计算成本相对高。这意味着优化算法本身要轻量、收敛要快、不能有太多额外的计算开销。在几个常用算法里遗传算法GA需要设置交叉率、变异率编码解码过程也比较繁琐粒子群PSO容易陷入局部最优在低维问题上表现不差但稳定性一般鲸鱼算法WOA收敛速度不错但参数控制的勘探开发转换偏快在VMD这类计算代价高的适应度函数上并不占优。GWO胜在结构简单、需要手动设置的超参数极少主要就是种群数量、迭代次数三头狼机制天然兼顾勘探与开发收敛精度和稳定性的平衡在低维问题上表现得很出色。它不需要像GA那样处理二进制编码也不需要像PSO那样调惯性权重和学习因子只需提供搜索边界和适应度函数就能跑起来这种“开箱即用”的属性对工程调试非常友好。4. 适应度函数怎么选GWO_VMD 的“指挥棒”4.1 包络熵最常用信号稀疏性的度量GWO_VMD中的适应度函数决定了算法朝哪个方向“进化”。如果适应度函数设计得不合理优化器再强也白搭。目前使用最广的指标是包络熵Envelope Entropy。包络熵的计算过程是对分解得到的模态信号做希尔伯特变换求出解析信号的幅值包络再对包络做归一化得到一组概率分布最后计算这组分布的信息熵。包络熵越小说明包络信号越稀疏也就是包络里有明显的冲击周期成分包络熵越大说明包络越杂乱接近随机噪声。在机械故障诊断场景中滚动轴承、齿轮箱的故障信号往往表现为周期性冲击这种信号解调后的包络谱上有明显的特征频率峰值包络熵天然偏小。所以如果某个参数组合能让VMD分解出的模态具有最小的包络熵就可以认为它找到了与故障冲击匹配度最高的模态。4.2 排列熵、信息熵、谱峭度指标的选择逻辑包络熵不是唯一的选择针对不同信号类型需要考虑不同的适应度函数。排列熵Permutation Entropy通过比较时间序列相邻点的顺序模式来度量信号的复杂度和随机性它的优势是对幅值变化不敏感适合处理带有强噪声的微弱故障信号。如果信号中噪声占比极高包络熵的区分度可能会下降此时排列熵会更合适。信息熵Shannon Entropy直接对信号幅值的概率分布计算熵值计算最简单但缺点是对频率结构的反映不灵敏容易出现不同参数组合的适应度值非常接近的情况。谱峭度Spectral Kurtosis能在每个频带中度量信号偏离高斯分布的程度对于识别瞬态冲击特征非常有效。不过谱峭度计算量偏大而且对参数变化比较敏感优化过程容易震荡。我的经验是如果信号是典型故障冲击特征用包络熵如果信号噪声很重考虑排列熵或包络熵与排列熵的加权组合如果只是做一般的周期性成分分离信息熵也够用。4.3 适应度函数对优化结果的敏感性适应度函数的选择会直接影响GWO搜索到的参数组合。同样的仿真信号我把适应度函数从包络熵换成信息熵算法最终给出的K值可能完全不一样。有一个比较典型的例子一个由三种正弦加白噪声构成的仿真信号用包络熵做适应度函数时GWO倾向选择K4、alpha1800左右的参数因为此时某个模态包络最稀疏但用信息熵时算法可能会选择K7和更大的alpha因为信息熵更关注幅值分布的均匀性更多模态意味着每个模态的幅值分布更集中信息熵更小。所以设计GWO_VMD时一定要先想明白你的信号里最关心什么特征包络熵适合解调分析排列熵适合强噪声环境谱峭度适合瞬态冲击。目标函数选错后面的优化再精确也没有意义。5. GWO_VMD 的 Matlab 完整实现从初始化到收敛5.1 测试信号与评估函数准备下面进入实操环节。整套代码的核心是把VMD的调用封装成一个可被GWO反复调用的函数。为了便于演示我用一个仿真信号来做测试三个正弦分量加白噪声采样率1000Hz。%% GWO_VMD 主程序示例 % 清空环境 clear; clc; close all; %% 生成仿真测试信号 fs 1000; % 采样频率 1000 Hz t (0 : 1/fs : 1 - 1/fs); % 1s 时长 N length(t); f1 50; f2 120; f3 280; % 三个频率分量 x1 1.5 * sin(2 * pi * f1 * t); x2 1.0 * sin(2 * pi * f2 * t); x3 0.6 * sin(2 * pi * f3 * t); noise 0.3 * randn(N, 1); signal x1 x2 x3 noise; %% GWO 参数配置 SearchAgents_no 15; % 灰狼种群数量 Max_iteration 20; % 最大迭代次数 dim 2; % 优化变量个数[K, alpha] lb [2, 500]; % 参数下限K 最小为 2alpha 最小为 500 ub [10, 4000]; % 参数上限K 最大为 10alpha 最大为 40005.2 灰狼种群初始化的两个易错点初始化灰狼种群就是在搜索边界内随机生成一组参数组合但有两个细节直接影响后续性能。第一个细节是K必须取整数。模态数K在VMD中是一个离散值而灰狼位置更新是基于连续坐标运算的。如果直接把连续位置传给VMDMatlab会出现运行错误或得到意外的分解结果。正确的做法是在计算适应度之前用round函数取整但注意不能破坏位置更新本身的连续性否则GWO的搜索行为会退化。第二个细节是种群数量不能太小。有些同学为了省时间把种群设为5结果GWO很容易收敛到局部最优。参考经验是种群数量取10到20比较稳妥对于VMD这种适应度函数计算较慢的场景15只狼配合20次迭代是一个性价比较高的组合。%% 初始化灰狼种群位置 Alpha_pos zeros(1, dim); Alpha_score inf; Beta_pos zeros(1, dim); Beta_score inf; Delta_pos zeros(1, dim); Delta_score inf; % 随机初始化种群位置 Positions zeros(SearchAgents_no, dim); for i 1 : SearchAgents_no for j 1 : dim Positions(i, j) lb(j) rand * (ub(j) - lb(j)); end end Convergence_curve zeros(1, Max_iteration);5.3 边界处理与离散化边界处理是另一个容易被忽略的细节。迭代过程中灰狼的位置更新可能把某个变量的值推到这个区间之外。如果不处理这个边界越界问题下一次适应度计算时会报错——比如K变成0或负数。%% GWO 主循环 for it 1 : Max_iteration for i 1 : SearchAgents_no % 边界约束 Flag4ub Positions(i, :) ub; Flag4lb Positions(i, :) lb; Positions(i, :) (Positions(i, :) .* ~(Flag4ub Flag4lb)) ub .* Flag4ub lb .* Flag4lb; % 离散化和参数映射 K_current round(Positions(i, 1)); alpha_current Positions(i, 2); % 计算适应度 fitness VMD_fitness(signal, K_current, alpha_current, fs); % 更新 alpha/beta/delta 狼 if fitness Alpha_score Alpha_score fitness; Alpha_pos Positions(i, :); elseif fitness Beta_score Beta_score fitness; Beta_pos Positions(i, :); elseif fitness Delta_score Delta_score fitness; Delta_pos Positions(i, :); end end注意这里的边界处理逻辑越界位置被拉回边界值。这是一种简单而有效的方式实测下来比“把越界个体重新随机生成”的收敛效果好因为拉回边界保留了种群的搜索方向信息。5.4 调用 VMD 与计算包络熵的接口封装适应度函数的封装是整套代码最核心的桥梁它把GWO和VMD连接起来。我在这里直接调用开源的VMD函数Dragomiretskiy公开的vmd.m然后计算包络熵。%% 适应度函数VMD分解 包络熵计算 function fitness VMD_fitness(signal, K, alpha, fs) % VMD 参数设置 tau 0; % 噪声容忍度无噪声时为0 DC 0; % 不将第一模态视为直流分量 init 1; % 中心频率初始化为均匀分布 tol 1e-7; % 收敛容差 % 调用 VMD 分解 [u, ~] VMD(signal, alpha, tau, K, DC, init, tol); % 计算每个模态的包络熵取最小值作为适应度 K_actual size(u, 1); env_entropy zeros(K_actual, 1); for k 1 : K_actual % 希尔伯特变换求包络 analytic hilbert(u(k, :)); envelope abs(analytic); % 包络归一化得到概率分布 p envelope / sum(envelope); % 计算香农熵 p(p 0) []; env_entropy(k) -sum(p .* log(p)); end % 取最小包络熵作为该参数组合的适应度 fitness min(env_entropy); end这里有个重要的工程细节为什么取所有模态包络熵的最小值而不是平均值或者总和原因在于故障诊断的实际需求。故障特征通常只出现在某一个或某两个模态中而不是均匀分布在所有模态里。如果取平均值算法可能为了让整体熵值变小而刻意让所有模态都分解得很“平缓”反而掩盖了最具故障特征的那个模态。取最小值则引导算法去寻找那个包络最稀疏、冲击特征最明显的模态这更符合工程直觉。5.5 主循环中的位置更新与参数映射完成适应度评估后就进入GWO的核心位置更新。这一步先把收敛因子a从2线性衰减到0然后根据alpha、beta、delta三只头狼的位置计算新位置。%% 更新收敛因子 a a 2 - it * (2 / Max_iteration); %% 更新每只灰狼的位置 for i 1 : SearchAgents_no for j 1 : dim % 根据 alpha 狼更新 r1 rand(); r2 rand(); A1 2 * a * r1 - a; C1 2 * r2; D_alpha abs(C1 * Alpha_pos(j) - Positions(i, j)); X1 Alpha_pos(j) - A1 * D_alpha; % 根据 beta 狼更新 r1 rand(); r2 rand(); A2 2 * a * r1 - a; C2 2 * r2; D_beta abs(C2 * Beta_pos(j) - Positions(i, j)); X2 Beta_pos(j) - A2 * D_beta; % 根据 delta 狼更新 r1 rand(); r2 rand(); A3 2 * a * r1 - a; C3 2 * r2; D_delta abs(C3 * Delta_pos(j) - Positions(i, j)); X3 Delta_pos(j) - A3 * D_delta; % 综合三头狼的方向更新位置 Positions(i, j) (X1 X2 X3) / 3; end end Convergence_curve(it) Alpha_score; fprintf(迭代次数: %d, 最优适应度: %.4f, 最优K: %d, 最优alpha: %.2f\n, ... it, Alpha_score, round(Alpha_pos(1)), Alpha_pos(2)); end %% 输出最终结果 fprintf(GWO_VMD 寻优完成: K %d, alpha %.2f\n, round(Alpha_pos(1)), Alpha_pos(2));运行结束后把Alpha_pos中的K和alpha带入VMD就能得到GWO优化的分解结果。配合收敛曲线绘制可以直观观察算法是否收敛、收敛速度快不快。6. 实验结果对比GWO_VMD 与手动选参的差距6.1 仿真信号分解模态中心频率定位精度对比我用上面的仿真信号跑了完整的GWO_VMD流程。三个频率分量分别是50Hz、120Hz和280Hz白噪声幅值0.3。GWO_VMD最终收敛到K4、alpha1950左右。用这个参数做VMD得到的四个模态中心频率分别为49.8Hz、119.5Hz、279.2Hz和约395Hz。前三个模态分别对应仿真信号中的三个主要频率带第四个模态主要捕捉了残剩的噪声成分。对比手动调参的典型结果固定K4、alpha2000时效果接近但中心频率的偏差稍大且第四个模态中包含了一部分120Hz模态的拖尾成分。这是因为手动选择alpha时没有针对这组信号做精细化搜索而GWO在搜索过程中根据包络熵反馈不断修正参数使模态分离更干净。6.2 收敛曲线解读为什么 20 次迭代够用GWO-VMD的收敛曲线在仿真信号上表现得很有特点。前5次迭代适应度值从初始的4.8左右快速下降到4.3附近之后下降速度明显放缓大约15次迭代后稳定在4.1左右。这个收敛速度对工程应用来说完全可以接受。VMD加上包络熵计算一次大约需要0.2到0.5秒取决于信号长度和K值15只狼、20次迭代大约是300次适应度评估总体耗时在1到3分钟之间。如果信号更长比如10万点每次VMD计算时间会显著增加此时可以考虑把种群数量降到10迭代次数降到15并通过提前终止条件加速。GWO算法的空间复杂度很低不需要存储历史种群内存占用非常友好。6.3 一组接近实际的运行结果数值为了让大家对结果有直观概念这里放一组我在相同仿真信号上跑出的具体数值方法Kalpha最小包络熵中心频率误差总和运行时间手动经验值420004.321.8 Hz约3分钟含人工分析网格搜索步长500415004.251.2 Hz约12分钟GWO_VMD419504.180.7 Hz约1.5分钟注意这里的“运行时间”对网格搜索和手动调参来说其实只算了机器跑数的时间如果算上人工检查频谱图、调整参数的时间效率差距更大。GWO_VMD在分解质量更低的包络熵、更精确的中心频率估计和运行效率上都有明显优势。7. 踩过的坑与优化细节收敛慢、alpha 溢出、局部最优7.1 K 与 alpha 的搜索边界设置逻辑搜索边界直接决定了GWO能搜索的解空间范围。边界设得太小最优解可能在范围之外边界设得太大搜索空间稀疏收敛变慢还可能收敛到不合理的参数区域。对于K常规设置为2到10。K1时VMD退化为原始信号没有分解意义K太大时过分解明显计算量也爆炸。对于alpha我的建议范围是500到4000。alpha低于500时模态带宽过宽几乎一定混叠高于4000时部分模态会被过度压缩可能丢失有效特征。不过这个范围需要根据信号特性调整。如果信号中模态的频率非常接近alpha的上限可以适当提高如果信号频带较宽alpha下限可以降低。7.2 模态混叠的隐患VMD 对噪声容限的敏感度VMD对噪声的敏感度高于很多人的预期。当信号中噪声较强时VMD会倾向于把噪声单独分解成一个高频模态或者在原有频率模态中掺入噪声成分。GWO在寻优过程中会怎么处理噪声的影响呢取决于适应度函数。用包络熵时算法为了寻找包络最稀疏的模态可能会把噪声模态的包络熵算进去导致适应度评价不稳定。实测中发现当噪声方差超过信号幅值的0.5倍时需要把适应度计算改为“各模态包络熵加权求和”或者对模态先做带通滤波再计算包络熵。另外VMD自带的tau参数在强噪声场景下可以设置成非零值它能调节对噪声的容忍度GWO也可以把tau加入优化变量不过这会增加搜索维度需要加大种群数量。7.3 种群规模与迭代次数的性价比权衡关于GWO的种群规模和迭代次数我的看法是不要盲目追求大。VMD的适应度函数计算成本不低种群翻倍意味着计算时间直接翻倍。在K和alpha两个变量的场景下15只狼、20次迭代基本能覆盖有效搜索。如果发现收敛曲线最后还在明显下降说明迭代次数不够可以增加到30。如果收敛曲线很早进入平台期说明种群多样性不足可以适当提高种群数量或者尝试不同的随机种子。还有一个技巧是多次运行取最优。GWO虽然稳定但毕竟是随机算法初始种群不同会导致最终结果有轻微波动。我通常的做法是连续运行3次取包络熵最小的结果。每次运行由于收敛快总耗时也在可接受范围内。7.4 Matlab 中 VMD 工具代码的兼容性与集成问题最后说一下Matlab代码集成时的几个兼容性问题。VMD的公开实现基于较多矩阵运算需要Matlab 2016b以上版本才能顺畅运行。如果你的Matlab版本比较旧建议升级或者改用手写循环实现。另外VMD函数的调用格式在不同版本中略有差异。公开版本的标准调用是[u, u_hat, omega] VMD(signal, alpha, tau, K, DC, init, tol)其中u是分解后的模态矩阵u_hat是频域表示omega是中心频率数组。有些同学下载的版本可能把前两个输出参数顺序对调集成到GWO框架时很容易因为维度不匹配报错。如果你在运行fitnness函数时遇到“错误使用 矩阵维度必须一致”这类问题通常是信号是行向量而u的维度是K×N导致的转置问题。在调用VMD之前统一用signal signal(:)把输入变成列向量能避免至少一半的兼容性问题。还有一个很多人忽略的点VMD函数是基于乘子交替方向法迭代求解的对初始中心频率的设定init参数比较敏感。GWO_VMD中我建议把init设为1让中心频率均匀初始化这样可以保证同一组参数每次运行结果一致不会因为VMD自身的随机性干扰GWO的适应度评价。综合来看GWO_VMD不是多高深的技术它就是在一个成熟优化算法和成熟分解算法之间搭了一座桥。真正让这套方案能够落地的是对alpha在VMD中的数学角色有清晰认识对适应度函数有合理设计以及在Matlab实现里处理好K取整、边界约束、信号转置这些看似不起眼却致命的细节。做完这一步后续无论是做故障特征提取还是信号降噪都能在一套可靠参数的基础上继续推进而不是停留在没完没了的手动试错里。