大规模优化在2025年仍然是一个高活跃度的研究方向,但每年能让人眼前一亮的算法其实不多。SEVC(Space-Embedded variable decomposition and space Compression,空间嵌入的变量分解与空间压缩)是我今年花了两周时间复现并实测过的一种新算法,发表在SCI二区期刊,定位非常清晰:面向大规模优化,用"变量分解+空间压缩"两条腿走路。这篇文章我不打算复述论文摘要,而是从复现者的视角,把它的原理拆开、把关键参数讲透、把实测数据和踩过的坑全部放出来。如果你正在用协同进化框架处理1000维以上的问题,或者在找对比算法跑基准实验,这篇应该能帮你省下不少时间。
1. 为什么大规模优化需要"分解"和"压缩"这两板斧
1.1 维度灾难不是课本吓唬人,是真实存在的拦路虎
当决策变量维度涨到1000维以上时,进化算法的表现会断崖式下降。原因有两个层面。
第一是搜索空间体积爆炸。假设每个变量有100个离散取值,一个10维问题的搜索空间是10^20个组合,1000维就是10^2000。暴力采样在超高维空间里基本失效——这就是所谓的"维度灾难"。更麻烦的是,在高维空间里,任意两个随机点的相对距离都趋向于相同,种群的多样性信息被稀释到几乎没有区分度,选择压力形同虚设。
第二是变量之间的耦合关系。大规模问题里,变量往往不是独立的,有的是可分离结构(变量互不影响),有的是部分不可分离(存在变量子集内部强耦合)。经典进化算法把整个D维向量当成一个个体来进化,一来协调这么多变量的工作量大,二来一旦变量间存在复杂的相互作用,交叉变异算子很容易破坏已经找到的有利组合。
于是就有了协同进化(Cooperative Coevolution,CC)框架:把大规模问题拆成若干子问题,各自优化再拼回去。这个框架的难点不在"拆"这个动作,而在"怎么拆"。随机分组(DECC-G)虽然简单,但会把相互作用的变量拆到不同组,导致子问题内部永远无法收敛到最优;而精确检测变量交互关系通常需要O(D²)甚至更高的函数评估开销。SEVC解决的就是这个矛盾:既要把交互变量拆到同一组,又不能让分组成本高到无法接受。
1.2 先澄清一个误区:"空间压缩"到底压缩什么
标题里提到空间压缩,很多人第一反应是Windows里压缩C盘卷。最近"c盘压缩卷压缩空间非常小怎么办"这个话题又上了热榜,讨论的是磁盘分区里可用压缩空间太小的问题。Windows压缩卷时,页面文件、休眠文件这类不可移动文件挡在卷的尾部,系统只能把卷收缩到"安全线"为止,所以你经常看到"可用压缩空间只有几个GB"的提示。这里的核心约束是:不能把系统文件排除在分区之外,否则系统就崩了。
优化算法里的"空间压缩"思路惊人地相似。你可以把搜索边界往里收,把每一维变量的取值范围压缩到当前最优解附近的一个窄区间,这样局部搜索效率会大幅提升。但问题是:如果压缩得太狠,把包含全局最优解的区域排除在边界之外,那算法就永远找不到它了。SEVC的压缩策略本质上就是在回答一个问题:如何在不"压崩系统"的前提下,尽量把搜索空间收缩到有希望的区域。它不像磁盘压缩那样受物理文件位置限制,而是受种群分布信息的限制——压缩依据来自当前种群在每维上的标准差,这是一个很自然的自适应机制,我后面会详细展开。
1.3 SEVC在整个算法版图里的坐标
搞清楚SEVC的位置,才能判断它值不值得复现。
当前主流的LSGO(大规模全局优化)路线大概分三派。第一派是以DECC-G、DECC-DG为代表的协同进化分组派,核心是把变量分解后逐个击破;第二派是改进变异策略的流派,比如CCPSO2用粒子群配合尺度因子,SHADE-ILS用自适应差分进化加局部搜索;第三派是这两年兴起的代理模型辅助派,用高斯过程或径向基函数拟合高维目标函数,减少真实评估次数。
SEVC属于第一派的深度改良。它的创新点在于:分组的依据不再是固定的原始搜索空间,而是每次循环中已经压缩过的空间——这就是"空间嵌入"的含义。相当于分组和压缩两个模块形成了一个反馈闭环:压缩改变了空间,空间改变了分组,分组优化后又产生新的种群分布,再次驱动压缩。这个设计逻辑在论文里花了很大篇幅论证,我复现下来的感受是:它确实比"先分组再优化、分组一次用到底"的做法更能适应问题结构的变化。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. SEVC核心机制拆解:变量分解如何做、空间压缩怎么用
2.1 空间嵌入的变量分解:从差分分组到"当前空间分组"
变量分解最经典的算法是差分分组(Differential Grouping,DG)。原理很直观:对于两个变量xi和xj,如果它们相互独立,那么在某个基点上分别扰动xi和xj产生的目标函数变化,应该近似等于同时扰动两者产生的变化;如果两者有交互,同时扰动的效果会明显偏离单独扰动效果之和。用公式表达就是:
Δ_i = |f(x_base + δ·e_i) - f(x_base)|
Δ_j = |f(x_base + δ·e_j) - f(x_base)|
Δ_ij = |f(x_base + δ·e_i + δ·e_j) - f(x_base)|
如果|Δ_ij - Δ_i - Δ_j| > ε,就判定xi和xj之间存在交互,应该分到同一组。
DG家族的各种变体(DG2、DG3等)主要改进的是基点的选取和阈值ε的自适应,它们有一个共同点:分组在整个优化过程开始时做一次,之后不再更新。这在问题结构固定时没有问题,但问题在于"分组"和"搜索进度"是脱节的——初期空间范围很大,检测到的交互关系是基于全局视角的;随着搜索推进,最优解附近的局部交互结构可能已经和全局结构不一样了。
SEVC的做法是:每轮循环都在当前压缩后的搜索空间里重新做一次分解。因为空间边界收缩了,基点周围采样的扰动更能反映局部区域的真实交互关系,分组结果自然更贴合当前搜索阶段的实际需求。这个"边压缩边重新划分"的设计,是它和传统CC框架最本质的区别。
再说说阈值ε的设定。这个参数决定了两变量之间多强的相互作用才算"交互"。ε设太大,真实的交互会被漏掉,强耦合变量被拆散,子问题退化成单变量优化,收敛速度看似很快但结果其实是错的;ε设太小,检测会把噪声当成交互,所有变量被分到一个超大组里,又退化回了不分解的状态。SEVC论文里的建议是ε=1e-3,我实测下来在CEC2013基准上这个值合理,但如果目标函数是病态缩放(ill-scaled)的,1e-3会失效,这个问题我在第5部分会展开讲。
2.2 空间压缩:用种群的"离散程度"决定边界收缩幅度
SEVC的空间压缩模块是整篇论文里我觉得最有实用价值的部分。它的做法非常朴素但有效:
对于每一维变量i,在每轮子问题优化结束后,计算当前种群在该维度上的标准差σ_i,然后以当前全局最优解x*_i为中心,把该维度的搜索边界更新为:
L_i = max(L_global_i, x*_i - α_i·σ_i)
U_i = min(U_global_i, x*_i + α_i·σ_i)
其中α_i是一个随循环次数衰减的系数。初始时α比较大(比如6~8),保证种群还有足够的探索空间;随着循环进行,α逐步缩小到1~2左右,搜索范围被压缩到最优解附近很小的邻域内。
这里有两个设计细节值得琢磨。
第一,为什么用标准差而不是用当前种群的最小最大值?因为min-max对离群点太敏感。假设种群里有几个个体还停留在远方的劣质区域,它们的坐标会让max-min范围很大,压缩等于没压缩。标准差天然对离群点不敏感,是一个更稳健的"种群收敛程度"指标。
第二,压缩边界需要裁剪回全局边界。如果直接把边界设成x*_i ± α_i·σ_i,有可能超出原始搜索范围,必须裁剪到[L_global, U_global]。这一点初学者最容易漏。我在初版实现里就是忘了裁剪,导致某些维度边界越走越宽,压缩变成了"扩张",算法表现自然一塌糊涂。
2.3 分解-压缩-再分解的闭环逻辑
把分解和压缩放到一起看,SEVC的整体循环是:
初始化解空间和种群 → 在当前空间内做变量分解 → 对每个变量分组做子优化 → 根据种群分布压缩空间 → 回到第一步重新分解 → 循环直到评估次数耗尽。
这个闭环的核心逻辑是:压缩后的空间让分组更精准,精准的分组让子优化更彻底,更彻底的优化让种群更快收敛,收敛的种群又让压缩边界更紧凑。每一轮循环都在做"分辨率升级"。
但闭环也有副作用:如果某些维度在早期就被错误地压缩到了局部最优附近,那么后续再怎么重新分组,也很难跳出这个局部区域,因为空间边界已经被锁死了。SEVC论文里提到了一种缓解机制:当某维度的压缩范围小于初始范围的某个比例(比如1%)时,对该维度做一个随机扩张扰动,重新放宽边界。这个"防锁死"机制在实际测试中非常重要,我在复现时亲测,不加这个机制,在f8、f10这类多模态大规模函数上会明显早熟。
3. 从论文到代码:SEVC伪代码解读与关键实现
3.1 主循环框架:一个可直接抄的Python骨架
根据我的复现理解,SEVC的主循环可以写成下面这个伪代码。注意这里我是按论文思路结合工程习惯重写过的,不是论文原封不动的版本,但核心逻辑保持一致。
python复制import numpy as np
def sevc(f, lb, ub, D, NP=50, max_fes=3000000,
epsilon=1e-3, alpha0=6.0, decay=0.9):
# 初始化
L = np.array(lb, dtype=float)
U = np.array(ub, dtype=float)
P = np.random.uniform(L, U, size=(NP, D))
fit = np.array([f(ind) for ind in P])
fes = NP
x_best = P[np.argmin(fit)].copy()
f_best = fit.min()
cycle = 0
while fes < max_fes:
# 1) 在当前压缩空间内做变量分解
groups = decompose_in_current_space(f, P, x_best, epsilon)
# 2) 对每个分组做子优化
for g in groups:
budget = alloc_budget(len(g), len(groups), max_fes - fes)
P, fit, x_best, f_best, used = optimize_group(
f, P, fit, g, x_best, budget, L, U)
fes += used
# 3) 空间压缩
sigma = np.std(P, axis=0)
alpha = alpha0 * (decay ** cycle)
new_L = np.maximum(np.array(lb), x_best - alpha * sigma)
new_U = np.minimum(np.array(ub), x_best + alpha * sigma)
# 4) 防锁死:压缩过度的维度做随机扩张
ratio = (new_U - new_L) / (np.array(ub) - np.array(lb))
stuck = ratio < 0.01
if stuck.any():
new_L[stuck] = np.array(lb)[stuck]
new_U[stuck] = np.array(ub)[stuck]
L, U = new_L.copy(), new_U.copy()
cycle += 1
return x_best, f_best
这个骨架非常简洁,但把所有关键环节都覆盖了。实际复现时,最耗时的不是主循环,而是decompose_in_current_space和optimize_group这两个模块的实现质量。
3.2 两个核心模块的细节实现
变量分解模块,我建议用"扰动传播"方式实现而不是两两全检测。两两检测是O(D²)的开销,在1000维下意味着约50万次函数评估——这个成本在单次循环里还能接受,但如果每轮循环都做,总评估次数就爆炸了。更经济的方式是:先检测每个变量是否是"活跃变量"(即单独扰动它会带来明显函数变化),只对活跃变量做两两交互检测。非活跃变量直接并入一个独立的默认组即可。
python复制def decompose_in_current_space(f, P, x_best, epsilon, delta=1e-5):
D = len(x_best)
base = x_best.copy()
f_base = f(base)
# 先检测每个变量的单独贡献
active = []
single_change = {}
for i in range(D):
pert = np.zeros(D)
pert[i] = delta * (U[i] - L[i]) # 扰动幅度按当前空间边界缩放
fi = f(base + pert)
single_change[i] = abs(fi - f_base)
if single_change[i] > epsilon:
active.append(i)
# 对活跃变量做两两交互检测
parent = list(range(D))
def find(x):
while parent[x] != x:
parent[x] = parent[parent[x]]
x = parent[x]
return x
def union(a, b):
ra, rb = find(a), find(b)
if ra != rb:
parent[ra] = rb
for idx_i in range(len(active)):
i = active[idx_i]
for idx_j in range(idx_i + 1, len(active)):
j = active[idx_j]
pert_ij = np.zeros(D)
pert_ij[i] = delta * (U[i] - L[i])
pert_ij[j] = delta * (U[j] - L[j])
f_ij = f(base + pert_ij)
interaction = abs(f_ij - f_base - single_change[i] - single_change[j])
if interaction > epsilon:
union(i, j)
# 收集分组
groups = {}
for i in active:
groups.setdefault(find(i), []).append(i)
return list(groups.values())
注意这里扰动幅度delta要乘以当前空间边界宽度,这是"空间嵌入"的一个具体体现:在压缩后的空间里,扰动也应该按压缩后的尺度来。我在初版实现里忽略了这一点,直接用固定delta,结果压缩几轮之后扰动尺度相对边界显得太大,分组检测失去了意义。
子优化模块,我选的是SaNSDE(带自适应策略池的差分进化)。为什么不用CMA-ES?因为SEVC的子问题分组大小可能差异很大,大部分组都是单变量或少量变量,CMA-ES在这种小分组上开销太大、收益有限;SaNSDE的自适应变异策略对不同类型的组都有不错的兜底能力,而且是CC框架里被反复验证过的搭配。每个组分配的评估次数(budget)按组内变量数占全体活跃变量数的比例来分配,这是DECC论文里就被验证过的分配策略。
3.3 参数敏感性:哪些参数决定算法生死
我把复现过程中重点调试的参数整理成了下面的表,每个参数都标注了它对结果的影响方向。
| 参数 | 作用 | 典型值 | 设置过大 | 设置过小 |
|---|---|---|---|---|
| ε(交互阈值) | 判定变量是否交互 | 1e-3 | 漏检交互,拆散强耦合变量 | 把噪声当交互,分组过大 |
| δ(扰动步长) | 分组检测时的扰动幅度 | 1e-5×边界宽度 | 扰动超出局部线性区,误判 | 扰动小于浮点误差,检测失效 |
| α0(初始压缩系数) | 控制第一轮压缩的边界宽度 | 6~8 | 压缩太慢,收敛进展缓慢 | 压缩过快,容易丢掉全局最优区域 |
| decay(衰减率) | 控制α随循环的收缩速度 | 0.9 | 边界长期过大,后期收敛慢 | 边界迅速锁死,提前早熟 |
| 防锁死阈值 | 触发随机扩张的最小比例 | 0.01 | 频繁扩张,失去压缩意义 | 维度被永久锁死在局部区域 |
这几个参数里,ε和α0是最关键的两个。ε直接决定分解质量,α0直接决定压缩的安全边际。我在实验里把α0从8改到2,在CEC2013的f8上结果差了将近两个数量级——这个参数不是调优问题,是安全问题,设小了真的会把全局最优点排除在搜索空间之外。
4. 性能实测:我在CEC2013 LSGO基准上的复现数据
4.1 测试环境与实验设置
我的复现实验全部在以下环境完成:Python 3.10 + NumPy 1.24,单机跑,CPU是i7-12700,没有并行化。基准函数用CEC2013 Large-Scale Global Optimization(LSGO)的15个测试函数,全部统一到1000维,最大评估次数设为3×10^6,每个算法独立跑25次取中位数。种群规模NP=50,子优化器用SaNSDE,分组阈值ε=1e-3。
这里强调一下:复现论文结果时,评价口径必须和原论文一致。CEC2013的官方指标是误差值(f(x) - f(x*),x*是已知全局最优),很多新手直接拿目标函数值对比,这是错的,因为每个函数的全局最优值不同,没有可比性。
4.2 与主流大规模优化算法的对比结果
我选了对标算法:DECC-DG(差分分组+CC)、CCPSO2(粒子群协同进化)、MOS(多级协同进化),都是LSGO领域公认的强基线。以下是部分有代表性的函数结果(单位:误差值,越小越好,数据为25次运行中位数)。
| 函数 | 特征描述 | SEVC | DECC-DG | CCPSO2 | MOS |
|---|---|---|---|---|---|
| f1 | 完全可分离 | 0.00E+00 | 0.00E+00 | 3.22E-12 | 0.00E+00 |
| f3 | 部分可分离(7个组) | 2.14E+02 | 1.99E+03 | 1.45E+04 | 7.66E+02 |
| f6 | 部分可分离(100个组) | 4.03E-02 | 2.50E+01 | 3.23E+01 | 1.01E+00 |
| f8 | 完全不可分离(重叠) | 6.18E+05 | 2.01E+07 | 5.43E+07 | 1.15E+06 |
| f15 | 完全不可分离 | 3.77E+04 | 1.70E+06 | 2.27E+06 | 1.39E+05 |
可以清楚看到两个规律。
第一,对于完全可分离函数(f1),所有算法都能收敛到接近0,这个没什么好说的,是协同进化框架的基本盘。真正拉开差距的是部分可分离和完全不可分离的函数。
第二,在f3、f6这类部分可分离函数上,SEVC比分组精确度同样很高的DECC-DG高了一个数量级。这部分优势主要来自空间压缩——DECC-DG分组后子优化器只在一个固定的大空间里跑,而SEVC的子优化器跑在压缩后的窄空间里,同样的评估次数能找到更优的解。在f8这种完全不可分离的重叠函数上,SEVC也明显好于DECC-DG和CCPSO2,但要弱于MOS——我的理解是MOS的分层策略对这种结构更友好,SEVC的空间压缩在重叠变量上容易过早收缩。
4.3 消融实验:拆掉分解或压缩,性能掉多少
为了验证SEVC的两个组件各自贡献了多少,我做了三组消融:SEVC-NoComp(去掉空间压缩,只在原始空间里分组优化)、SEVC-NoDec(去掉变量分解,所有变量当成一个大组优化)、以及完整SEVC。结果如下。
| 函数 | 完整SEVC | SEVC-NoComp | SEVC-NoDec |
|---|---|---|---|
| f1 | 0.00E+00 | 0.00E+00 | 2.54E+02 |
| f3 | 2.14E+02 | 5.87E+03 | 9.32E+05 |
| f6 | 4.03E-02 | 9.80E+01 | 6.40E+03 |
| f8 | 6.18E+05 | 5.31E+06 | 9.02E+07 |
结论很直接:拆掉任何一个组件,性能都大幅下降。去掉空间压缩后,部分可分离函数上的结果差一到两个数量级,证明压缩模块是SEVC精度提升的主要来源;去掉变量分解后,几乎所有函数都崩了,证明分解是协同进化算法的地基,没有地基上面的压缩再漂亮也白搭。这两个组件是"乘法关系"而不是"加法关系",这个结论我想特别强调给做算法改进研究的朋友:以后在这个框架上做改进,不要只盯着一个模块,两边的协同作用才是算法真正的护城河。
5. 复现踩坑实录:五个让结果"假性优秀"的坑
5.1 分组阈值ε设错,分解等于没分解
我一开始图省事,直接在论文给的ε=1e-3上跑,结果在某些函数上表现特别好,在另一些函数上表现特别差。后来排查发现:目标函数有尺度差异。对于值域在10^6量级的函数,1e-3的阈值几乎检测不出任何交互,所有变量被拆成单变量组,算法退化成了"按坐标轴逐维爬山",在可分离函数上反而很快,但在非可分函数上一塌糊涂。这种"假性优秀"最迷惑人,因为你在f1上看到漂亮的收敛曲线,以为算法没问题,实际上只是函数结构恰好匹配了错误的分组。
解决方法是给ε加上自适应机制:每轮分组前,先采样一批扰动计算函数值变化幅度的基线,把ε设为这个基线的某个比例(比如1%)。这样无论目标函数值域怎么变,ε都能自动缩放到合适的量级。
5.2 空间压缩在非可分问题上会"压过头"
完全不可分离的函数(比如f8这种重叠函数)是所有空间压缩方法的天敌。因为变量之间强耦合,单看某一维度的标准差并不能代表这个方向真实的最优区间,压缩边界可能落在错误的位置上。我的实测里,f8上如果不加防锁死机制,多次运行都会收敛到5×10^7级别,而加了防锁死后中位数降到6×10^5。
所以我的建议是:如果你的目标函数已知是重叠结构或者完全不可分离,最好弱化压缩强度,把α0调大、衰减率调小,甚至按维度关闭压缩。SEVC论文里也提到这一点,但写得比较隐晦,实际调参时会花不少时间才能悟到。
5.3 FES口径不一致,对比全是空谈
这是复现论文时最容易犯的低级错误。很多论文写"总评估次数3×10^6",但这个次数是否包含了分组检测阶段的函数评估?不同论文口径不同。DECC-DG和其他基于差分分组的算法,分组检测会消耗大量FES,如果论文没有明确说明,你很难公平对比。
我自己在统计FES时,把分组检测和子优化的评估次数一起计入总FES。一开始我测试SEVC,结果显示它比DECC-DG好一个数量级,结果发现是我只统计了子优化的FES而DECC-DG的复现代码计入了检测开销,相当于我让SEVC多跑了一倍资源。统一口径之后再测,差距缩回到合理范围。
5.4 压缩频率与早熟收敛的拉扯
压缩多久做一次?这也是一个隐藏的坑。SEVC论文里的设计是每个循环周期做一次压缩,但循环周期长度是有讲究的。如果压缩太频繁,种群还来不及在子优化中充分收敛,标准差σ_i偏大,压缩边界几乎不收缩,等于没压缩;如果压缩太少,σ_i可能已经趋于0,一次压缩就把边界缩到非常小,跳过中间过渡区域,直接锁死。
我实验后确定的经验值是:每个循环周期里,所有分组合计消耗约10%~15%的总FES,然后做一次压缩。这样能给种群足够的收敛时间,也不会让压缩来得太突然。
5.5 高维下协方差矩阵的数值灾难
虽然不是SEVC本身的坑,但做大规模优化迟早会遇到。如果子优化器选的是CMA-ES这类依赖协方差矩阵的算法,在组内维度超过50时,协方差矩阵更新会出现严重的数值不稳定。具体表现是最优解突然跳变、收敛曲线出现"断崖式上升"。我最终没有在主实验里用CMA-ES,也是因为这个问题。如果非要在大分组上用CMA-ES,建议加上矩阵条件数检查,条件数超过1e12就重置协方差矩阵,别硬算。
6. 实战应用与改造思路:SEVC不止能跑基准函数
6.1 什么样的问题适合用SEVC
从实测结果反推,SEVC的优势区间是:变量数1000以上、目标函数可分离或部分可分离、评估预算有限。这类问题在工程里并不少见——大规模神经网络超参数搜索(可分离性中等)、风电场布局优化(空间位置变量部分耦合)、大规模流水线调度(工序变量之间确实存在交互)。
不适合SEVC的是这样几类问题:一是变量间强重叠耦合的(f8那种),压缩机制会变成负资产,不如直接用MOS这类专门为重叠结构设计的算法;二是目标函数极度不光滑、噪声很大的,分组检测会被噪声完全淹没,ε自适应也救不回来;三是维度其实不高的(一两百维),空间压缩带来的增益有限,反而引入额外参数负担。
6.2 两个值得一试的改造方向
我复现完SEVC之后,自己动手做了两个小改造,效果都还不错,分享出来供参考。
第一个改造是嵌入代理模型。SEVC的分组检测阶段消耗了大量FES在对真实目标函数的调用上,而检测只需要知道"交互强度",不需要精确值。我在检测阶段用RBF代理模型替代真实函数,把检测FES占比从15%降到了3%左右,省下的FES全部投入子优化阶段,在f6上误差又降了30%。代价是代理模型的训练质量会波动,需要在ε上留出更多余量。
第二个改造是并行化子优化。SEVC的各个分组在每一轮循环中是相互独立的(各组优化时固定其他组变量为当前最优解),天然可以并行。我用multiprocessing把多个分组的子优化分散到多核上,由于每组评估次数差异大,做了个简单的动态负载均衡:先跑组大的,同时把小的组派给空闲核心。实测4核并行下,相同FES的墙钟时间缩短了3倍左右,性能无损失。
6.3 最后说点实在的
这篇论文能在SCI二区发表,靠的不是某个惊艳的单点技巧,而是把两个成熟思路(分组协同进化和动态搜索空间调整)拧成了一个自洽的闭环,并且在基准上验证了协同增益。这种"思路朴素但工程完整"的论文风格,恰恰是复现价值最高的——你不会像复现某些花哨算法那样被各种黑科技卡住,而是能通过复现真正理解一个框架的运转逻辑。
我给想上手SEVC的朋友一个建议:不要一开始就冲1000维,先在200维的CEC2013子集上把分组检测和空间压缩单独调通,再合并跑完整流程。我第一周就是直接跑1000维,结果每次调试都要等半小时以上,效率极低;改成200维调试后,单次实验秒级完成,参数敏感性一目了然,上1000维之后只花了半天就稳住了结果。
复现算法最重要的是理解它每一步设计背后的权衡。SEVC的分解是耗费FES换分组准确率,压缩是承担局部最优风险换收敛速度,防锁死机制是牺牲一部分压缩强度换跳出能力——每一个模块都是一笔明码标价的交易。把这三笔交易的账算清楚,你不仅复现了这个算法,以后自己设计算法时也知道该怎么"记账"。
