化計(jì)算基準(zhǔn)測(cè)試集完整指南與避坑經(jīng)驗(yàn))
簡(jiǎn)介面向進(jìn)化計(jì)算與智能優(yōu)化領(lǐng)域的研究者、工程師及高校學(xué)生這份測(cè)試集匯總了CEC2010、CEC2013、CEC2014、CEC2015、CEC2017等歷屆單目標(biāo)實(shí)參數(shù)優(yōu)化競(jìng)賽的基準(zhǔn)問(wèn)題可用于驗(yàn)證和對(duì)比各類(lèi)新穎優(yōu)化算法的尋優(yōu)能力與收斂性能。壓縮包內(nèi)共516個(gè)文件大小約89.73MB其中txt文件提供測(cè)試數(shù)據(jù)與評(píng)價(jià)指標(biāo)m文件為MATLAB函數(shù)實(shí)現(xiàn)cpp與mexw64分別對(duì)應(yīng)C源碼和編譯后的可執(zhí)行程序另有rar與zip作為配套打包數(shù)據(jù)。資源涵蓋不同年份的競(jìng)賽測(cè)試集內(nèi)容涉及多類(lèi)復(fù)雜度不同的目標(biāo)函數(shù)、旋轉(zhuǎn)矩陣生成器及粒子群等參考實(shí)現(xiàn)適合系統(tǒng)評(píng)估算法魯棒性、開(kāi)展消融實(shí)驗(yàn)或撰寫(xiě)論文時(shí)構(gòu)建對(duì)比基線。目前已有1994人學(xué)習(xí)下載對(duì)于需要快速獲取標(biāo)準(zhǔn)單目標(biāo)優(yōu)化測(cè)試平臺(tái)的學(xué)習(xí)者具有實(shí)用參考價(jià)值。1. 從 CEC2010 到 CEC2017算法論文里那排“黑匣子”數(shù)字到底從哪兒來(lái)很多人在復(fù)現(xiàn)論文時(shí)會(huì)遇到同一個(gè)尷尬對(duì)比表里某個(gè)算法在 CEC2017 上贏了一片自己拿同一份改進(jìn)代碼去跑結(jié)果差出一大截。多數(shù)情況不是算法造假而是測(cè)試集調(diào)用方式出了問(wèn)題。CEC2010、CEC2013、CEC2014、CEC2015、CEC2017 這五套測(cè)試集是進(jìn)化計(jì)算領(lǐng)域公開(kāi)的“標(biāo)準(zhǔn)考題”覆蓋大規(guī)模優(yōu)化、單目標(biāo)實(shí)參數(shù)優(yōu)化、混合函數(shù)與組合函數(shù)等不同難度的場(chǎng)景。它們存在的意義是讓不同算法在統(tǒng)一維度、統(tǒng)一評(píng)價(jià)預(yù)算、統(tǒng)一誤差口徑下正面交鋒。這篇文章從五套測(cè)試集各考什么講起最后落到怎么把測(cè)試集裝進(jìn)自己的算法框架、避開(kāi)那些讓結(jié)果整體翻車(chē)的坑。2. 五套測(cè)試集各自考什么從 1000 維大規(guī)模壓測(cè)到混合函數(shù)陷阱2.1 CEC2010面向大規(guī)模優(yōu)化的極端壓測(cè)CEC2010 是五套里最特殊的一套它把維度直接推到 1000 維甚至更高普通粒子群算法、差分進(jìn)化在這么高的維度里幾乎寸步難行。20 個(gè)測(cè)試函數(shù)里大約一半屬于可分離函數(shù)另一半是不可分離函數(shù)不可分離問(wèn)題往往還疊加了旋轉(zhuǎn)矩陣。旋轉(zhuǎn)的作用是懲罰那些只會(huì)沿坐標(biāo)軸方向搜索的算子比如經(jīng)典的“逐維變異”策略一旦函數(shù)被旋轉(zhuǎn)獨(dú)立維度上的探索優(yōu)勢(shì)就消失了。選 CEC2010 做實(shí)驗(yàn)的人目標(biāo)通常是驗(yàn)證大規(guī)模優(yōu)化算法比如協(xié)同進(jìn)化、分而治之、變量分組這一類(lèi)方法。如果你手頭的方法只能在 30 維上展示效果直接套到 CEC2010 上大概率會(huì)得到很難看的曲線這是測(cè)試集的設(shè)計(jì)意圖而不是代碼 bug。CEC2010 的另一個(gè)特點(diǎn)是不少函數(shù)帶數(shù)據(jù)文件依賴(lài)后面的章節(jié)會(huì)單獨(dú)講這個(gè)坑。我一般會(huì)把 CEC2010 當(dāng)作“壓力測(cè)試場(chǎng)”先跑通 100 維確認(rèn)算法沒(méi)有結(jié)構(gòu)性缺陷再上 1000 維。這樣做的好處是能區(qū)分“算法本身退化”和“實(shí)現(xiàn)細(xì)節(jié)出錯(cuò)”避免一開(kāi)始就被高維下的數(shù)值誤差干擾判斷。2.2 CEC2013 與 CEC2014單目標(biāo)優(yōu)化的分水嶺與精度門(mén)檻CEC2013 包含 28 個(gè)函數(shù)維度常用 10、30、50函數(shù)從單峰到多峰再到組合函數(shù)逐步過(guò)渡。它的一個(gè)重要價(jià)值是把“旋轉(zhuǎn)”和“移位”全面引入很多函數(shù)的最優(yōu)解位置不再是坐標(biāo)原點(diǎn)。這意味著沿襲舊習(xí)慣把初始種群中心放在 0 的代碼可能在問(wèn)題還沒(méi)開(kāi)始迭代時(shí)就已經(jīng)偏離了最優(yōu)區(qū)域。CEC2014 在 CEC2013 基礎(chǔ)上做了進(jìn)一步升級(jí)常用函數(shù)數(shù)量為 30 個(gè)結(jié)構(gòu)上分為單峰、簡(jiǎn)單多峰、混合函數(shù)和組合函數(shù)四類(lèi)?;旌虾瘮?shù)Hybrid把多個(gè)子函數(shù)按權(quán)重拼起來(lái)不同區(qū)域的曲率差異很大組合函數(shù)Composition更是把多個(gè)局部最優(yōu)以加權(quán)方式融合形成非常崎嶇的適應(yīng)性景觀。很多在 CEC2013 上表現(xiàn)不錯(cuò)的算子到了 CEC2014 的組合函數(shù)上會(huì)頻繁陷入停滯這是測(cè)試集有意制造的難度梯度。做通用單目標(biāo)優(yōu)化方向的話CEC2013 和 CEC2014 幾乎是繞不開(kāi)的對(duì)照基準(zhǔn)。審稿人更認(rèn) CEC2014因?yàn)樗?CEC2013 更難函數(shù)多樣性也更高但 CEC2013 的簡(jiǎn)單函數(shù)可以幫助定位算法缺陷比如某個(gè)算法在旋轉(zhuǎn)多峰函數(shù)上突然失效通常說(shuō)明算子的坐標(biāo)軸依賴(lài)太強(qiáng)。2.3 CEC2015 與 CEC2017學(xué)習(xí)優(yōu)化與邊界約束下的檢驗(yàn)粒度CEC2015 的常用函數(shù)數(shù)量是 15 個(gè)主題偏向“學(xué)習(xí)優(yōu)化”它和 CEC2014 的函數(shù)結(jié)構(gòu)有相近之處但更強(qiáng)調(diào)算法對(duì)問(wèn)題特征的適應(yīng)能力。很多研究者在對(duì)比時(shí)會(huì)跳過(guò) CEC2015理由是它不夠主流可如果你想做跨任務(wù)遷移、在線參數(shù)自適應(yīng)這類(lèi)方向CEC2015 反而是很有說(shuō)服力的選擇。它不要求算法在每個(gè)函數(shù)上都拿第一但要求算法在多個(gè)函數(shù)之間保持穩(wěn)定的遷移效果。CEC2017 則是目前使用頻率最高的單目標(biāo)測(cè)試集之一常用函數(shù)數(shù)量為 29 個(gè)維度選擇甚至擴(kuò)展到了 100 維。和 CEC2014 相比CEC2017 的混合函數(shù)與組合函數(shù)重新作了設(shè)計(jì)邊界約束也更嚴(yán)格超界個(gè)體如果處理不當(dāng)誤差會(huì)被明顯放大。它在論文中的角色更像是“最后的關(guān)卡”前面測(cè)試集都能過(guò)再用 CEC2017 檢驗(yàn)算法是否具備在實(shí)際約束下的競(jìng)爭(zhēng)力。CEC2017 有一個(gè)讓很多人措手不及的細(xì)節(jié)官方給出的函數(shù)編號(hào)并不是從 1 到 30 連續(xù)排列的個(gè)別編號(hào)被廢棄后實(shí)際可用的函數(shù)數(shù)量是 29 個(gè)。后面排查章節(jié)我會(huì)重點(diǎn)講它這里先記住跑 CEC2017 之前一定要先打印一遍函數(shù)索引清單。2.4 橫向選型依據(jù)同一算法在不同測(cè)試集上的定位差異測(cè)試集常見(jiàn)函數(shù)數(shù)量常用維度測(cè)驗(yàn)重點(diǎn)使用頻率CEC201020100 / 1000大規(guī)模全局優(yōu)化專(zhuān)項(xiàng)方向CEC20132810 / 30 / 50基礎(chǔ)單目標(biāo)實(shí)參數(shù)優(yōu)化較高CEC20143010 / 30 / 50復(fù)雜單目標(biāo)優(yōu)化很高CEC20151510 / 30 / 50學(xué)習(xí)優(yōu)化與遷移中等CEC20172910 / 30 / 50 / 100高難度混合與組合函數(shù)很高這張表不是用來(lái)背的而是幫你回答“該拿哪套測(cè)試集做對(duì)比”。做大規(guī)模算法選 CEC2010做改進(jìn)型算子的消融實(shí)驗(yàn)優(yōu)先 CEC2014做最終對(duì)比加上 CEC2017做自適應(yīng)或遷移學(xué)習(xí)再補(bǔ) CEC2015。常見(jiàn)錯(cuò)誤是把五套測(cè)試集成在一個(gè)結(jié)果表里橫向比勝負(fù)它們的預(yù)算、維度、函數(shù)構(gòu)造都不一樣這么做只會(huì)讓結(jié)論失去意義。3. 把測(cè)試集跑進(jìn)自己的算法框架目錄結(jié)構(gòu)、最小調(diào)用與結(jié)果記錄3.1 官方源碼包里的常見(jiàn)文件結(jié)構(gòu)與數(shù)據(jù)依賴(lài)拿到任何一套官方發(fā)布?jí)嚎s包先別急著把文件復(fù)制進(jìn)工程目錄。常見(jiàn)做法是先把壓縮包解壓到一個(gè)固定目錄保持原有的 C 源碼、Matlab 接口、數(shù)據(jù)文件三部分結(jié)構(gòu)不動(dòng)。CEC2010 尤其依賴(lài)外部數(shù)據(jù)文件移位和旋轉(zhuǎn)矩陣都是從文件讀入的路徑寫(xiě)錯(cuò)或者文件缺失時(shí)函數(shù)不會(huì)立刻報(bào)錯(cuò)而是返回一堆錯(cuò)誤數(shù)值這個(gè)現(xiàn)象會(huì)直接污染整個(gè)實(shí)驗(yàn)結(jié)果。我自己通常會(huì)在項(xiàng)目里單獨(dú)建一個(gè) benchmark 目錄里面按套件名稱(chēng)分子目錄benchmarks/ ├── cec2010/ │ ├── data/ │ └── src/ ├── cec2013/ │ └── src/ ├── cec2014/ │ └── src/ ├── cec2015/ │ └── src/ └── cec2017/ └── src/這樣做的最大好處是隔離數(shù)據(jù)依賴(lài)。C 源碼編譯產(chǎn)物放在同一套目錄下Matlab 腳本單獨(dú)保留Python 封裝統(tǒng)一從 src 目錄加載共享庫(kù)所有數(shù)據(jù)文件路徑都通過(guò)配置文件指定不散落在實(shí)驗(yàn)?zāi)_本里亂引用。參數(shù)說(shuō)明只有一點(diǎn)無(wú)論用絕對(duì)路徑還是相對(duì)路徑必須在實(shí)驗(yàn)開(kāi)始前用腳本校驗(yàn)數(shù)據(jù)文件是否完整別等跑完 30 次才發(fā)現(xiàn)某套數(shù)據(jù)沒(méi)加載。3.2 最小調(diào)用流程用 Python 封裝官方 C 函數(shù)并自動(dòng)記錄結(jié)果官方代碼多以 C 或 Matlab 形式發(fā)布常見(jiàn)做法是把 C 代碼編譯成共享庫(kù)再寫(xiě)一層 Python 封裝。函數(shù)簽名因版本而異但骨架幾乎一致傳入自變量向量、函數(shù)編號(hào)、維度返回函數(shù)值。下面這一段是典型的封裝結(jié)構(gòu)我通常在寫(xiě)算法之前先把它跑通。import numpy as np class CECBenchmark: def __init__(self, suite, func_id, dim, max_fes, runs30): self.suite suite # CEC2010 / CEC2014 / CEC2017 self.func_id func_id # 官方函數(shù)編號(hào) self.dim dim self.max_fes max_fes self.runs runs # 常見(jiàn)做法把編譯好的共享庫(kù)加載為 Python 模塊 self.lib load_cec_library(suite) def evaluate(self, x): # 先做邊界裁剪防止算法生成越界個(gè)體 x np.clip(x, -100.0, 100.0) val self.lib.cec_func(x.tolist(), self.func_id, self.dim) return float(val) def run_algorithm(self, optimizer): best float(inf) fes 0 # 初始化解這里用均勻分布示例 x np.random.uniform(-100.0, 100.0, self.dim) while fes self.max_fes: x, fes optimizer.step(self, fes) best min(best, self.evaluate(x)) fes 1 return best邏輯說(shuō)明evaluate 方法承擔(dān)邊界裁剪和函數(shù)調(diào)用兩個(gè)職責(zé)收到的 x 先被映射回定義域再交給官方函數(shù)。run_algorithm 把評(píng)價(jià)預(yù)算統(tǒng)一成 FES這樣不同算法之間只比函數(shù)評(píng)價(jià)次數(shù)不比自己說(shuō)了算的迭代次數(shù)。參數(shù)說(shuō)明func_id 必須是官方給出的函數(shù)編號(hào)CEC2017 尤其要注意編號(hào)不能空想否則會(huì)調(diào)用到不存在的函數(shù)max_fes 通常是維度乘以 10000比如 30 維就是 300000 次評(píng)價(jià)。3.3 通用參數(shù)總表維度、maxFES、運(yùn)行次數(shù)與初始范圍參數(shù)常見(jiàn)取值說(shuō)明維度10 / 30 / 50 / 100CEC2010 用 100 或 1000其它常用 30maxFESD * 10000大多數(shù)單目標(biāo)測(cè)試集按維度線性放大獨(dú)立運(yùn)行次數(shù)25 ~ 30少于 20 次很難做顯著性檢驗(yàn)初始化范圍按官方定義域CEC2013 起多為 [-100, 100]誤差統(tǒng)計(jì)口徑f_best - f_opt小于 1e-8 時(shí)記為 0這里的每項(xiàng)都會(huì)直接影響結(jié)果表。維度越高預(yù)算越大但算法收斂速度也被同步考驗(yàn)運(yùn)行次數(shù)少了單次隨機(jī)波動(dòng)會(huì)掩蓋真實(shí)差異初始化范圍寫(xiě)錯(cuò)相當(dāng)于在錯(cuò)誤區(qū)域里找最優(yōu)解。官方報(bào)告通常會(huì)在每個(gè)測(cè)試集的說(shuō)明文檔里寫(xiě)明約定值拿到套件之后第一步就是確認(rèn)這些參數(shù)而不是沿用上一次實(shí)驗(yàn)的老配置。4. 評(píng)測(cè)算法不能只跑一遍統(tǒng)計(jì)口徑、預(yù)算上限與結(jié)果判讀4.1 maxFES 為什么比迭代次數(shù)更適合當(dāng)評(píng)價(jià)預(yù)算很多以“迭代次數(shù)”為終止條件的實(shí)驗(yàn)存在一個(gè)隱患種群大小不同一次迭代消耗的 FES 完全不同。種群 10 和種群 100 各自迭代 1000 代前者只評(píng)價(jià)了 10000 次后者評(píng)價(jià)了 100000 次放到同一張收斂圖里比較是不公平的。maxFES 把比較單位統(tǒng)一成“函數(shù)評(píng)價(jià)次數(shù)”無(wú)論內(nèi)部怎么變異、怎么選擇每個(gè)算法消耗的總預(yù)算完全一致。用墻鐘時(shí)間比較更不公平不同機(jī)器、不同編碼實(shí)現(xiàn)的底層性能差距會(huì)影響結(jié)論。我一般會(huì)把 maxFES 直接寫(xiě)進(jìn)配置常量而不是寫(xiě)進(jìn)代碼邏輯。這樣無(wú)論是做維度實(shí)驗(yàn)還是跨測(cè)試集實(shí)驗(yàn)預(yù)算都一目了然也方便后續(xù)復(fù)現(xiàn)論文時(shí)快速對(duì)齊參數(shù)。4.2 30 次獨(dú)立運(yùn)行的底線均值、標(biāo)準(zhǔn)差、最好值與“達(dá)標(biāo)率”單次運(yùn)行結(jié)果沒(méi)有意義這是測(cè)試集使用里最容易被忽略的一句話。進(jìn)化算法是隨機(jī)算法同一個(gè)函數(shù)同一次實(shí)驗(yàn)跑兩遍結(jié)果可能差幾個(gè)數(shù)量級(jí)。常見(jiàn)做法是對(duì)每個(gè)函數(shù)獨(dú)立運(yùn)行 30 次記錄每次的全局最優(yōu)值再算均值、標(biāo)準(zhǔn)差和最好值。def summarize(best_list, opt): errors [] for b in best_list: e b - opt if e 0: e 0.0 # 數(shù)值誤差可能導(dǎo)致略小于最優(yōu)值 if e 1e-8: e 0.0 # 官方常見(jiàn)精度閾值視為達(dá)到最優(yōu) errors.append(e) return { mean: np.mean(errors), std: np.std(errors), best: np.min(errors), rate: np.mean(np.array(errors) 0.0), }這段代碼里最關(guān)鍵是 1e-8 的判斷。對(duì)數(shù)坐標(biāo)畫(huà)圖時(shí)真正的 0 會(huì)被 log 吃掉所以官方普遍約定誤差小于 1e-8 時(shí)按 0 處理。返回的 rate 是“達(dá)到最優(yōu)的比例”在組合函數(shù)上經(jīng)常比均值更能反映算法穩(wěn)定性。參數(shù)說(shuō)明opt 取官方文檔給出的全局最優(yōu)值不要用自己算法找到的最好值代替否則每個(gè)算法都有自己的參照物結(jié)果完全不可比。4.3 收斂曲線與顯著性檢驗(yàn)從“分?jǐn)?shù)高一點(diǎn)”到“結(jié)論可靠”只看均值表容易得出錯(cuò)誤結(jié)論因?yàn)榫笛谏w了不同運(yùn)行的波動(dòng)。正確做法是同時(shí)記錄每條獨(dú)立運(yùn)行的收斂軌跡也就是每次評(píng)價(jià)后當(dāng)前最優(yōu)值的序列然后取多條曲線的中位數(shù)或平均值畫(huà)圖。誤差軸用 log 坐標(biāo)曲線越低代表相同預(yù)算下找到的解越精確。兩條曲線的差距可能只是隨機(jī)波動(dòng)這時(shí)需要顯著性檢驗(yàn)兜底。常見(jiàn)做法是對(duì)同一個(gè)函數(shù)上的兩組 30 次誤差結(jié)果做 Wilcoxon 或 Mann-Whitney 檢驗(yàn)。比如使用 scipy 計(jì)算 p 值p 小于 0.05 才敢說(shuō)這個(gè)函數(shù)上有差異。需要注意每次運(yùn)行要使用不同的隨機(jī)數(shù)序列且兩組結(jié)果相互獨(dú)立不能把同一次運(yùn)行的日志拆成兩份來(lái)對(duì)比。from scipy.stats import mannwhitneyu # errors_A 與 errors_B 是同一個(gè)函數(shù)上的兩組獨(dú)立誤差序列 u_stat, p_value mannwhitneyu(errors_A, errors_B)邏輯說(shuō)明這里做的是雙尾檢驗(yàn)判斷兩組誤差是否來(lái)自同一分布。p 值大于 0.05 時(shí)哪怕均值差了 10 倍也不應(yīng)該寫(xiě)進(jìn)“顯著優(yōu)于”的結(jié)論里。參數(shù)說(shuō)明樣本量 30 時(shí)檢驗(yàn)結(jié)果相對(duì)可靠少于 15 則會(huì)因?yàn)槊舾行圆蛔愣茈y出現(xiàn)顯著差異。4.4 一套測(cè)試集怎么規(guī)劃實(shí)驗(yàn)矩陣規(guī)劃實(shí)驗(yàn)別一上來(lái)就五套全跑。維度、函數(shù)數(shù)量、獨(dú)立運(yùn)行次數(shù)相乘后計(jì)算量會(huì)膨脹得很快。以 CEC2017 為例29 個(gè)函數(shù)乘以 50 維再乘以 30 次運(yùn)行加上 3 個(gè)對(duì)比算法就是 29 * 30 * 3 次完整優(yōu)化過(guò)程每次都要跑到 50 萬(wàn)次函數(shù)評(píng)價(jià)總耗時(shí)很可能以天為單位。常見(jiàn)做法是分兩階段先用 10 維把所有算法跑通確認(rèn)實(shí)現(xiàn)和統(tǒng)計(jì)腳本沒(méi)有問(wèn)題再上 30 維做正式對(duì)比只有針對(duì)大規(guī)模方向的論文才追加 100 維或 CEC2010。這樣既控制了實(shí)驗(yàn)周期也避免在最后提交結(jié)果時(shí)發(fā)現(xiàn)某個(gè)函數(shù)的邊界處理不一致導(dǎo)致整批結(jié)果作廢。后悔藥在實(shí)驗(yàn)里是沒(méi)有的寧可前期多花半天規(guī)劃也不要后期重跑一周。5. 五套測(cè)試集使用中的高頻踩坑與排查這些坑大多來(lái)自測(cè)試集被當(dāng)成“黑匣子”不讀官方說(shuō)明只憑舊代碼的慣性傳參。下面每一條都是能直接影響結(jié)論的硬傷排查順序從函數(shù)編號(hào)、邊界、數(shù)據(jù)文件、跨套對(duì)比到統(tǒng)計(jì)口徑剛好對(duì)應(yīng)一條完整實(shí)驗(yàn)鏈。5.1 現(xiàn)象CEC2017 里的編號(hào)失蹤結(jié)果表出現(xiàn)空洞現(xiàn)象是代碼按 1 到 30 循環(huán)跑測(cè)試函數(shù)結(jié)果表里有些編號(hào)永遠(yuǎn)沒(méi)有數(shù)據(jù)或者某些編號(hào)的函數(shù)值異常離譜。原因是官方發(fā)布的可測(cè)試函數(shù)清單并不連續(xù)CEC2017 的編號(hào)中有一個(gè)被廢棄實(shí)際可用函數(shù)數(shù)量為 29 個(gè)。如果程序默認(rèn)連續(xù)編號(hào)就會(huì)把原來(lái)的編號(hào)映射到錯(cuò)誤函數(shù)上后續(xù)全部統(tǒng)計(jì)都失去意義。排查辦法是跑實(shí)驗(yàn)前先打印一遍函數(shù)索引清單。解決代碼里加一條斷言valid_ids [i for i in range(1, 31) if i ! 2] for func_id in valid_ids: run_one_benchmark(func_id)這段代碼把廢棄編號(hào)顯式排除避免循環(huán)里隱式跳過(guò)帶來(lái)的困惑。每次換測(cè)試集時(shí)都要重新檢查一次官方清單因?yàn)椴煌准木幪?hào)規(guī)則并不相同。5.2 現(xiàn)象所有函數(shù)都在 [-100, 100] 初始化但最優(yōu)解永遠(yuǎn)找不到現(xiàn)象是簡(jiǎn)單單峰函數(shù)能收斂復(fù)雜組合函數(shù)無(wú)論怎么調(diào)參都停在同一個(gè)誤差量級(jí)上不再下降。原因是很多測(cè)試集把全局最優(yōu)值的位置做了平移最優(yōu)解不在定義域中心甚至離中心很遠(yuǎn)。如果初始化按照“0 附近對(duì)稱(chēng)分布”的舊習(xí)慣來(lái)寫(xiě)初始種群根本沒(méi)覆蓋到最優(yōu)區(qū)域附近后續(xù)進(jìn)化算子再?gòu)?qiáng)也很難跨越巨大的函數(shù)值落差。解決方法是嚴(yán)格按官方定義域做均勻采樣并且每次 evaluate 前對(duì)越界個(gè)體做裁剪。注意裁剪不能解決初始化偏移問(wèn)題它只是保證傳給測(cè)試集函數(shù)的值永遠(yuǎn)合法x np.random.uniform(-100.0, 100.0, self.dim) x np.clip(x, -100.0, 100.0)參數(shù)說(shuō)明定義域不是自己發(fā)明的以對(duì)應(yīng)測(cè)試集的官方文檔為準(zhǔn)。不同測(cè)試集之間哪怕維度一樣定義域也可能不同跨套件復(fù)用初始化代碼前務(wù)必核對(duì)。5.3 現(xiàn)象CEC2010 結(jié)果在不同機(jī)器上不一致數(shù)據(jù)文件缺失卻不報(bào)錯(cuò)現(xiàn)象是同一份代碼在同一臺(tái)機(jī)器上連續(xù)跑兩次結(jié)果一致?lián)Q成另一臺(tái)機(jī)器后某些函數(shù)的值明顯偏離而且日志里沒(méi)有任何異常提示。原因是 CEC2010 的旋轉(zhuǎn)和移位數(shù)據(jù)依賴(lài)外部文件文件讀取路徑寫(xiě)的是相對(duì)路徑時(shí)工作目錄改變就會(huì)靜默加載失敗。有些實(shí)現(xiàn)會(huì)把文件內(nèi)容當(dāng)成二進(jìn)制隨機(jī)數(shù)據(jù)讀出函數(shù)還能繼續(xù)計(jì)算但返回的已經(jīng)是徹底錯(cuò)誤的值。排查方法是在實(shí)驗(yàn)啟動(dòng)前校驗(yàn)數(shù)據(jù)文件大小和內(nèi)容。常見(jiàn)做法是把數(shù)據(jù)目錄路徑顯式傳入初始化函數(shù)并在加載后打印文件的哈希值import hashlib digest hashlib.md5(open(data_path, rb).read()).hexdigest() assert digest EXPECTED_DIGEST, 數(shù)據(jù)文件不完整這里校驗(yàn)的是數(shù)據(jù)文件一致性防止不同實(shí)驗(yàn)環(huán)境下靜默出錯(cuò)。如果再不同機(jī)器上跑同組實(shí)驗(yàn)建議集中生成一次結(jié)果文件而不是分散在多臺(tái)機(jī)器上入庫(kù)避免環(huán)境差異混進(jìn)結(jié)論。5.4 現(xiàn)象拿 CEC2014 的誤差橫向?qū)Ρ?CEC2017 的均值結(jié)論站不住現(xiàn)象是結(jié)果表里把兩個(gè)測(cè)試集的誤差均值放在同一列然后寫(xiě)“算法在 CEC2017 上的表現(xiàn)優(yōu)于 CEC2014”沒(méi)有標(biāo)注維度、預(yù)算或運(yùn)行次數(shù)差異。原因是五套測(cè)試集的問(wèn)題構(gòu)造、函數(shù)數(shù)量、預(yù)算規(guī)則都不一樣它們之間沒(méi)有統(tǒng)一的難度標(biāo)尺。CEC2014 和 CEC2017 即使維度相同函數(shù)景觀也完全不同跨套件比較均值沒(méi)有數(shù)學(xué)意義。解決方法是把每個(gè)測(cè)試集的實(shí)驗(yàn)結(jié)果分開(kāi)呈現(xiàn)同一測(cè)試集內(nèi)部做算法對(duì)比??缣准幻枋鏊惴ㄟm用性比如“在大規(guī)模測(cè)試集上保持競(jìng)爭(zhēng)力”而不是斷言誰(shuí)比誰(shuí)強(qiáng)。參數(shù)說(shuō)明對(duì)比表必須包含測(cè)試集名稱(chēng)、函數(shù)編號(hào)、維度、maxFES、運(yùn)行次數(shù)五個(gè)字段缺任何一項(xiàng)讀者都無(wú)法復(fù)現(xiàn)。5.5 現(xiàn)象只跑一次就寫(xiě)“顯著更優(yōu)”復(fù)現(xiàn)時(shí)結(jié)果反轉(zhuǎn)現(xiàn)象是實(shí)驗(yàn)報(bào)告里寫(xiě)某個(gè)算法在十幾個(gè)函數(shù)上優(yōu)于對(duì)比算法但獨(dú)立復(fù)現(xiàn)時(shí)優(yōu)勢(shì)函數(shù)數(shù)量明顯減少。原因是單次運(yùn)行的隨機(jī)性。進(jìn)化算法的初始種群、變異算子的隨機(jī)數(shù)序列都會(huì)影響最終結(jié)果單次運(yùn)行的勝負(fù)很可能是運(yùn)氣。解決方法是把運(yùn)行次數(shù)提高到 25 到 30 次并且記錄每次運(yùn)行的隨機(jī)數(shù)種子保證可復(fù)現(xiàn)。種子本身不參與結(jié)果篩選只是當(dāng)別人質(zhì)疑結(jié)果時(shí)可以按相同種子重跑驗(yàn)證rng np.random.default_rng(seed) x rng.uniform(-100.0, 100.0, self.dim)這里的 seed 按運(yùn)行序號(hào)生成比如第 k 次運(yùn)行使用 seed1000k。這樣既滿(mǎn)足隨機(jī)性要求又讓每條日志都具備追溯能力。真正值得寫(xiě)進(jìn)論文的結(jié)論必須同時(shí)通過(guò)均值對(duì)比和顯著性檢驗(yàn)。6. 進(jìn)階技巧先用 10 維跑通全流程再用收斂曲線和統(tǒng)計(jì)檢驗(yàn)為算法迭代把關(guān)無(wú)論目標(biāo)是寫(xiě)論文還是調(diào)生產(chǎn)算法我建議把“10 維全流程驗(yàn)證”變成固定動(dòng)作。先用 10 維跑一小批函數(shù)不追求結(jié)果好看只驗(yàn)證函數(shù)編號(hào)映射、邊界裁剪、開(kāi)銷(xiāo)記錄三個(gè)環(huán)節(jié)是否正確。10 維跑一輪只要幾十秒30 維要幾分鐘用低成本先排除結(jié)構(gòu)性 bug比在高維跑一天后發(fā)現(xiàn)數(shù)據(jù)文件路徑錯(cuò)了要?jiǎng)澦愕枚唷E芡牝?yàn)證之后最重要的產(chǎn)出不是最終誤差表而是收斂曲線。每次評(píng)價(jià)結(jié)束后記錄當(dāng)前最優(yōu)值最終畫(huà)成 log 誤差曲線曲線形狀能直接暴露算法問(wèn)題如果多峰函數(shù)上曲線突然變平說(shuō)明算法早熟如果組合函數(shù)上曲線下降非常慢說(shuō)明算子缺乏跳出局部最優(yōu)的能力。這些信息都比一個(gè)均值數(shù)字更值得分析。import matplotlib.pyplot as plt plt.semilogy(gen_list, err_list_a, label算法A) plt.semilogy(gen_list, err_list_b, label算法B) plt.xlabel(FES) plt.ylabel(best error) plt.legend()這里的 gen_list 是記錄點(diǎn)的評(píng)價(jià)次數(shù)序列err_list 是對(duì)應(yīng)時(shí)刻的最優(yōu)誤差。畫(huà)圖時(shí)用中位數(shù)曲線而不是均值曲線因?yàn)閭€(gè)別異常運(yùn)行會(huì)把均值拉高中位數(shù)更能代表算法的典型表現(xiàn)。參數(shù)說(shuō)明曲線末端要對(duì)齊到同一 maxFES否則兩條曲線長(zhǎng)度不統(tǒng)一視覺(jué)對(duì)比就沒(méi)有意義。最后再補(bǔ)一句我自己一直沿用的習(xí)慣每次換測(cè)試集先花十分鐘讀官方參數(shù)表再跑一個(gè) 10 維函數(shù)做冒煙測(cè)試。這兩步看起來(lái)慢實(shí)際上省掉的是幾天重跑實(shí)驗(yàn)的時(shí)間。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取