简介:面向进化计算、群智能与单目标实参数优化研究的 CEC 系列基准测试集,汇集 2010、2013、2014、2015 和 2017 多届测试问题,适合算法研究者、研究生及工程技术人员复现实验、调参与横向比较算法收敛性能,也可作为新算法验证与教学演示的基础材料,并降低重复搭建实验环境的成本。压缩包共 516 个文件、约 89.73MB,以 txt 数据与说明为主,并包含 MATLAB 函数、C++ 源码、MEX 组件以及若干 zip/rar 子包,覆盖数据读取、函数实现和实验运行等环节。已有 1997 人学习或下载,在相关实验社区具备一定参考基础。使用者可借此搭建单目标基准测试流程,理解旋转矩阵、数据生成与主脚本的组织方式,掌握基准函数调用和结果对比思路,并为后续扩展到动态、小生境组合或约束优化等复杂场景提供可复用的测试底稿。
1. 选测试集比调算法更容易出错:先给结论
同一套算法,换一组 CEC 测试集,排名从第一掉到中游。这种情况我在三个不同的复现里都见过。CEC 测试集不是一组可以随便混用的函数文件,2010 到 2017 每一届的设计目标、维度设定、最优值计算标准都不一样。拿 2017 的函数去验证大规模优化,或者用 2014 的误差去跟 2013 的曲线对比,结论基本不可信。这篇把五个年份的差异拆开,给出按研究问题选型的判断顺序,再给一套能直接照抄的评测流水线和统计方法。刚做算法对比的新手,能照着跑出第一张可信的表;已经发过几轮实验的熟手,可以重点看第 4、5 章的评估次数对齐和最优值取值。
2. 五个年份的测试集差在哪:从设计目标到函数构成
选型之前先搞清楚一件事:这五套不是同一个东西的五个版本,而是针对不同研究问题设计的五组题目。把它们当版本号看,是最常见的误解。
2.1 代际演进:每一届都在修上一届的漏洞
2010 那一届的核心议题是大规模全局优化。变量一多,大量算法直接失效,所以函数设计的重点放在可分性上:一部分函数完全可分,一部分按组可分,一部分变量之间存在重叠交互。这个思路很直接——先看你敢不敢处理“变量之间有关系”的情况。
2013 把这件事做得更细。分组方式多了几种变体,重叠结构也更复杂,同时统一了旋转和偏移的处理,让那些靠“沿坐标轴逐个搜索”吃饭的算法不再有优势。2013 这一年还有另一套单目标实参数优化的题目,两套包的命名很像,拿之前一定看清楚是哪一个,用错了包写出来的实验结论没有任何意义。
2014 转向单目标通用性能评测。函数按难度分成单峰、多峰、混合、复合四段,前段用来快速筛掉明显不行的算法,后段用来区分头部算法。复合函数是把几个子函数拼在一起,搜索过程中会在不同盆地之间跳,专门用来检验算法的阶段切换能力。
2015 的定位更偏学习型和迁移场景,题目数量比 2014 少,组织方式也不一样,函数之间还带上了任务相关性。这套东西直接混进 2014 的结果表里对比,方法上说不通。
2017 是在 2014 的框架上又加了一层难度,混合与复合部分的构造更复杂,维度设置也更灵活。这一年被引用得最多,但同时也有很多细节问题——后面会讲。
提示:判断一套函数属于哪一届,不要看文件名里的年份数字,打开定义文件核对维度、函数编号和最优值表,三个都对上才算数。
2.2 函数分组与难度来源对照
我一般按“难度从哪来”给这几套函数分类,而不是按年份背函数编号。难度来源无非这么几种:偏移让最优点不在原点附近,旋转让变量之间产生依赖,条件数放大了搜索方向上的差异,复合结构制造多个局部盆地,重叠分组让“分块优化”的策略失效。
| 年份 | 核心定位 | 函数组织方式 | 常见评测维度 | 典型误用 |
|---|---|---|---|---|
| 2010 | 大规模全局优化 | 按可分性分组,含重叠结构 | 100 / 500 / 1000 | 拿小维度结果冒充大规模结论 |
| 2013 | 大规模优化 + 单目标两套 | 多种分组变体,统一旋转偏移 | 1000 / 2000 | 两套包拿混,报告里不写清楚 |
| 2014 | 单目标通用性能 | 单峰/多峰/混合/复合四段 | 10 / 30 / 50 / 100 | 只跑前段单峰函数就下结论 |
| 2015 | 学习型 / 迁移场景 | 题目带任务相关性 | 10 / 30 | 与 2014 结果直接混排 |
| 2017 | 单目标高难度评测 | 四段结构,复合部分更复杂 | 10 / 30 / 50 / 100 | 不说明就默认包含有争议的函数 |
这张表里最关键的一列是“典型误用”。选型选错,通常不是不知道有哪几套,而是知道有哪几套,却把评测维度或者函数子集配错了。1000 维的大规模结果和 30 维的单目标结果放在一张表里比收敛精度,数字上看着都是科学计数法,含义完全不同。
还有一点容易被忽略:同一届里,前段函数和后段函数的“信息量”是不一样的。前段单峰函数在大多数算法上都能收敛到很小的误差,排名差异主要来自后段。如果你的实验只跑到中段就停了,等于把最有区分度的部分扔掉了。我见过不少初稿,表格里误差一列全是 1e-8 量级,看着漂亮,实际上什么也没说明。
2.3 维度、评估预算与最优值计算标准
这三个参数必须在一开始就固定下来,中途改任何一个,前面跑的结果全部作废。
维度方面,大规模集我一般用 1000 维作为主战场,需要看扩展性再补 2000 维;单目标集用 10、30、50 三档,50 维以上就能看出算法在高维下的退化趋势。别一上来就冲 100 维,先确认 30 维的结果能复现,再往上加。
评估预算方面,单目标集常见做法是取维度的 10000 倍,也就是 30 维给 30 万次评估;大规模集通常按百万级给,1000 维给到 3×10^6 这个量级。这里最容易出问题的是“不同算法给了不同预算”或者“预算没随维度放大”。后者会导致高维结果看起来特别差,其实只是评估次数不够。具体数值以你手上那份定义文档为准,不要凭记忆写死。
最优值计算标准方面,误差统一用 f(x) 减去官方给出的最优值,结果出现负数就截断为 0。官方最优值必须从定义文件里读,不能拿你搜索到的最小值当基准。用搜索最小值当基准,等于自己给自己发合格证,跑出来的误差永远是 0 附近,这种结果审稿人一眼就能看出来。
注意:维度、评估预算、最优值这三项,建议直接写进实验配置文件的头部注释里,跑完一批实验再回头核对一遍。血泪经验是,中途换过一次最优值来源,整批数据重跑了三天。
3. 按研究问题选型:四类场景的参考
3.1 大规模优化:2010 和 2013 的分工
如果你的研究问题是“变量维度上去之后算法还能不能打”,主力应该放在 2013 的大规模集上,2010 作为补充。
理由是 2013 的分组结构更丰富,重叠方式更多,能把“只会分块优化”的算法筛出来。2010 的价值在于它的可分性划分非常干净,完全可分、部分可分、强交互三档分得很清楚,适合做消融实验:你先在完全可分的函数上确认算法没写错,再逐步过渡到强交互函数,看性能在哪一档开始掉。这个递进过程能帮你定位问题出在搜索策略还是变量交互建模上。
实操上,我一般这么排:先用 2010 的完全可分函数做正确性验证,误差应该能压到很低;再用 2013 的中段函数看分组策略是否有效;最后上 2013 的后段重叠函数,这一档最能拉开差距。三档跑完,算法的能力边界基本就清楚了。
还有一点,大规模集的单次运行时间可能是小维度单目标的几十倍。别一开始就设 51 次独立运行,先用 5 次跑通流程,确认内存和耗时能接受,再放大到正式次数。我踩过这个坑:1000 维、51 次运行、5 个算法,跑了一整个周末才发现其中一个算法的结果文件写串了目录。
3.2 通用单目标性能:2014 和 2017 的取舍
这两套是引用最广的,也是最容易选错的。
2014 的优势是“共识度高”。函数结构清楚,四段划分明确,社区里积累的对比数据多,你报出来的结果别人容易找到参照。如果你的工作重点在算法机制本身,不需要靠测试集的新颖性来支撑创新点,选 2014 更稳妥。
2017 的优势是“区分度大”。复合部分的构造更复杂,头部算法之间的差距更明显,适合你已经有一个调得比较成熟的算法、需要证明它在高难度场景下仍然占优的情况。代价是细节问题多:其中有个别函数在部分维度下表现异常,不少公开实现默认跳过它,只报剩下的函数。你要么跟着跳过并在实验设置里写清楚,要么保留但说明理由,最忌讳的是不声不响地少报一个函数——横向对比时对方按 30 个算,你按 29 个算,均值就没法比。
我的判断顺序是:先问自己“需不需要跟已有工作做严格对比”。需要,选 2014;不需要,且算法在高难度复合函数上有明显优势,选 2017。两边都想覆盖,就两套都跑,但结果表必须分开呈现,不能混在一张表里算平均排名。
3.3 补 2015 的时机
2015 这套东西不是必选项。它的定位比较特殊,题目组织方式跟前后几届都不兼容,独立跑一套的成本不低。
什么情况下值得补?两种情况。一是你的算法本身涉及知识迁移、多任务或者跨问题复用,那这套题目跟你的研究问题是对口的,不跑反而说不过去。二是审稿人明确要求你补充跨场景验证,那它比硬凑其他年份更合适。
什么情况下不值得补?你的算法是纯单目标搜索策略,跟迁移、学习没关系的,硬跑 2015 只会得到一堆解释不清的数字。这种情况下,把 2014 和 2017 跑扎实,比多凑一套更有说服力。
3.4 一张可以直接对照的选型表
| 你的研究问题 | 主力测试集 | 补充测试集 | 建议维度 | 说明 |
|---|---|---|---|---|
| 高维下的搜索效率 | 2013 大规模 | 2010 大规模 | 1000 | 先用 2010 做正确性验证 |
| 通用单目标性能 | 2014 | 2017 | 10/30/50 | 需要严格对比时以 2014 为主 |
| 高难度复合场景 | 2017 | 2014 | 30/50 | 有争议函数要写明处理方式 |
| 迁移 / 多任务 | 2015 | 2014 | 10/30 | 结果表单独呈现 |
| 约束处理 | 对应年份的约束子集 | — | 按定义文档 | 包名相近,注意区分 |
选型说到底就一句话:先确定你要回答的问题,再去找能回答这个问题的题目。反过来做,先跑了一堆数据再想“这些数据能说明什么”,大概率要重跑。
4. 把评测跑成可复现的流水线:目录、驱动与统计
选完测试集,接下来的问题是怎么跑。这一步做不好,前面选型再准也没用。
4.1 目录与命名:让结果能追溯
我见过太多实验结果目录长这样:result/,result2/,result_final/,result_final_真的final/。三个月后自己都不知道哪个是哪个。
我的做法是按“测试集 / 维度 / 算法 / 运行编号”四层组织,文件名里带上评估预算和随机种子:
exp/ cec2017/ d30/ algo_a/ fes300k_seed01.csv fes300k_seed02.csv algo_b/ ... d50/ cec2013/ d1000/这样做的直接好处是,任何一个结果文件都能从路径反推出全部实验条件。写论文做表的时候,脚本按路径扫一遍就能聚合,不用手工整理。另一个好处是出错时好定位:如果某个算法的所有结果都异常,问题在算法侧;如果某个维度的所有算法都异常,问题在配置侧。
配置文件和代码要一起进版本管理。别只提交代码不提交配置,跑出来的数字对不上时,你连当时用的评估预算是多少都查不到。
4.2 统一驱动脚本
下面这段是驱动骨架,不涉及具体算法实现,只固定评测口径。函数加载部分按你手上的库替换,重点是那几个固定参数。
# benchmark_driver.py # 统一评测驱动:加载函数 -> 多次独立运行 -> 记录误差 -> 落 CSV import csv import numpy as np def evaluate(func, x): # 边界处理必须与对比对象一致,这里用裁剪;改用反弹要在报告里注明 x = np.clip(x, func.lb, func.ub) return func(x) def run_trial(func, dim, max_fes, seed): rng = np.random.default_rng(seed) # 初始种群,规模按算法自行调整,这里只示意 pop = rng.uniform(func.lb, func.ub, size=(20, dim)) fitness = np.array([evaluate(func, p) for p in pop]) fes = len(pop) while fes < max_fes: # 算法主体在这里,产出新解 new_pop new_pop = pop # 占位:替换为实际搜索步骤 new_fit = np.array([evaluate(func, p) for p in new_pop]) fes += len(new_pop) # 贪心选择,仅作流程示意 pop = new_pop if new_fit.min() < fitness.min() else pop fitness = np.minimum(fitness, new_fit) best = fitness.min() # 误差口径:f(x) - f*,负值截断 return max(best - func.fstar, 0.0) def main(): results = [] for seed in range(1, 26): # 25 次独立运行 for dim in (10, 30, 50): max_fes = 10000 * dim # 预算随维度放大 for fid in range(1, 31): # 函数编号,按定义文档核对 func = load_function(fid, dim) # 替换为你的加载函数 err = run_trial(func, dim, max_fes, seed) results.append([fid, dim, seed, max_fes, err]) with open("result.csv", "w", newline="") as f: w = csv.writer(f) w.writerow(["fid", "dim", "seed", "max_fes", "error"]) w.writerows(results)几个参数的含义要说清楚。max_fes是评估次数上限,按维度的 10000 倍给,保证不同维度下的预算口径一致;seed从 1 开始连续取值,不要用时间戳,否则复现时对不上;func.fstar是从定义文件读出来的官方最优值,不能现场取最小值;np.clip是边界处理,具体用裁剪还是反弹,要跟对比对象保持一致。运行次数我习惯用 25 次,够做非参数检验,又不至于让大规模集的耗时失控。
代码里最值得注意的是fes的累计方式。它统计的是函数评估次数,不是迭代代数。有些算法一次迭代评估一个解,有些一次评估一整个种群,按代数对齐预算会让后者实际拿到的评估次数多出几十倍。
4.3 误差归一化与评估次数对齐
跨函数聚合结果时,误差的量级差异很大。有的函数误差在 1e+3 量级,有的在 1e-6 量级,直接求平均会被大量级函数主导。常见做法有两步:先对每个函数单独做排名,再对排名做聚合;或者对误差取对数后再聚合,但要在图注里注明变换方式。
评估次数对齐是另一个易错点。两个算法,一个报的是“达到目标精度所需评估次数”,一个报的是“固定预算下的最终误差”,这两个指标不能直接比。要么统一成固定预算下的误差,要么统一成达到精度所需的评估次数,选一种,全篇一致。
注意:聚合前先检查有没有负误差。截断逻辑写错的话,负值会把平均值拉低,看起来算法表现异常好。
4.4 统计检验与结果呈现
只报均值和标准差是不够的。25 次运行的结果差异可能很大,均值相同、分布完全不同的情况很常见。
我一般做三件事。第一,对每个函数做两两的秩和检验,显著性水平取 0.05,报告 p 值或者用符号标注。第二,用 Friedman 检验给出算法的整体排名,这个比逐函数的胜负计数更能反映综合表现。第三,做多重比较校正,函数数量多的时候不校正会把偶然差异当成显著差异。
结果表长这样比较清楚:
| 函数 | 算法 A 均值 | 算法 B 均值 | p 值 | 显著性 |
|---|---|---|---|---|
| F1 | 1.2e-08 | 3.4e-09 | 0.012 | A 劣于 B |
| F8 | 4.5e+01 | 4.1e+01 | 0.310 | 无差异 |
符号标注比写“优于”更省地方,但一定要在图注里解释符号含义。表格里同时给均值和显著性,读者能自己判断差异是不是实质性的。
5. 避坑与排查:五个让结论反转的细节
这一章全部来自实际出过问题的地方,按“现象、原因、解决”写。
5.1 五条具体记录
现象:实验结果好得离谱,误差一列几乎全是 0。原因:最优值取成了搜索到的最小值,等于自己跟自己比。解决:从定义文件读官方最优值,写死进配置;跑完抽查一个函数,手算一次误差核对量级。
现象:30 维能复现,1000 维结果差得没法看。原因:评估预算没有随维度放大,或者内存不够导致种群被悄悄截断。解决:把预算写成维度的函数,跑之前在日志里打印实际评估次数;大规模实验先用 5 次运行试水。
现象:2017 的结果跟别人的对不上,均值差一截。原因:函数子集不一致,对方跳过了有争议的那个函数,你全跑了。解决:在实验设置里明确写了跑多少个函数、跳过了哪个、为什么跳过,横向对比时先对齐口径再比数字。
现象:两个算法排名忽上忽下,换个种子就反过来。原因:运行次数太少,没做统计检验就下结论。解决:独立运行次数提到 25 次以上,加秩和检验;排名结论只在显著的前提下写。
现象:函数难度明显偏低,算法轻易收敛。原因:旋转矩阵或者偏移向量没加载成功,函数退化成了可分版本。解决:加载后先做一次自检,用固定种子在原点附近采样,看函数值是否符合预期量级;这一步花五分钟,能省掉一次整批重跑。
6. 最后落在一套最小可复现流程上
如果只记一件事,记这个顺序:定问题、选测试集、固定三个参数、跑通单函数、再放大。
具体执行时,我通常这样走一遍。第一步,用一句话写下研究问题,比如“验证某策略在高维强交互场景下的有效性”,写不出来就先别跑。第二步,按第 3 章的表选一套主力测试集和一套补充测试集,不要贪多。第三步,把维度、评估预算、最优值来源三个参数写进配置文件头部,同时确认包名没拿错——尤其是 2013 那种一年两套题的年份。第四步,只挑一个函数、一个维度、一个种子,跑通全流程,检查误差量级是否合理。第五步,放大到 5 次运行,看结果波动;波动过大先查随机数生成和边界处理,而不是急着调算法。第六步,正式跑 25 次,做统计检验,结果按第 4 章的目录结构归档。
这套流程听起来笨,但它能保证你在任何一步出错时都知道错在哪。评测这件事最怕的不是算法不够好,而是花了三周跑出来的数据,最后发现最优值口径跟对比对象不一致。
还有一个习惯值得养:每跑完一批实验,把配置、代码版本号、结果目录路径写进一个实验记录文件,三行就够。当时觉得多余,等三个月后要复现某张图的时候,这就是后悔药。
从那以后我每次碰新的测试集,都强制先把最优值、维度、评估预算三个数写进记录模板,再开跑。这个习惯没让我跑得更快,但让我少重跑了至少两次整批实验。希望帮到你。
本文还有配套的精品资源,点击获取