我跨越了2100015秒的距离,为你送上更全面的算法性能评测。
目录
- 往期优质资源
- 1 CVRP数据集
- 2 实验准备
- 2.1 计算机配置
- 2.2 调参方法
- 2.3 参数设定
- 2.4 实验方法
- 3 实验结果
- 3.1 最优解统计
- 3.1.1各数据集上的算法性能对比
- 3.1.2 求解结果汇总
- 3.1.3小结一下
- 3.1.4 还有话说
- 3.2 调参时间统计
- 3.2.1 各数据集上的运算时间对比
- 3.2.2 运算时间汇总
- 3.2.3 小结一下
- 3.3 最优参数统计
- 3.4 最优解路径
- 3.5 调参过程
- 4 结果分析
往期优质资源
-
CVRP系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
MDVRP系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
VRPTW系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
HVRP系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
MDHFVRPTW系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
小编推出第一期、第二期《CVRP算法系列》(基础篇+改进篇)后,后台收到了很多粉丝的留言。大家最关心的问题可归结为以下两点:
- split算法的作用是什么?为什么要采用它?会降低解的质量吗?
- 哪个算法效果最好?有和标准数据集对比吗?结果如何?
今天,小编将通过累计运行 【2100015秒≈35000分钟≈583小时≈24天】 的实验来回答以上问题。
2100015秒!
也许你只需要花费1分钟完成本文的阅读,但只要能帮助到大家就值得!
1 CVRP数据集
网络上关于CVRP问题的标准数据集好像挺多的,但好像可用的又没那么多。小编今天采用的是下边这个网站数据
小编下载了整个CVRP数据集,里面划分了A,B,E,F,G,M,P,V等8个类别(别担心,小编不会都测评)。考虑到时间成本,这里随机从中抽取了11个数据集。参与测评的11个数据集的最优解信息如下。
以上各数据集的数据分布如下:
2 实验准备
2.1 计算机配置
本次采用Python3.8编程实现,电脑配置为 Intel® Core™ i7-9700F CPU @ 3.00GHz 3.00 GHz,24G内存。
2.2 调参方法
元启发式算法的求解效果一方面取决于邻域规则,而另一方面则取决于参数设置。而且同一算法在不同数据集上的最优参数组合也可能是不一样的。
为了尽可能的找到最优的“算法-参数-算例”组合,小编一开始采用的是网格化调参,虽然可以较为精确的找到最优的参数组合,但需要巧妙的设计搜索空间,否则既浪费了计算资源,又没有找到理想结果。尝试了几次后,发现这种方法太耗时耗力,果断放弃!
随后想到了机器学习邻域常用的贝叶斯调参工具,简单来说,贝叶斯调参是建立在高斯过程基础之上的,根据历史搜索结果建立目标函数和参数之间的函数关系,然后预测最优的参数位置,再将预测的参数带入算法计算,重复这个过程,直至逼近最优的拟合关系。贝叶斯调参不仅效果好,而且省事!只需设定每个参数的搜索空间即可。于是经过一番探索,搞成了!以ACO调参为例,给出具体代码如下:
import time
import xlsxwriter
from ACO_CVRP_Advance import run
from bayes_opt import BayesianOptimization
def F(Q,rho,alpha,beta):
res = []
file = f'./{filename}'
for _ in [1,2]:
_, obj = run(filepath=file, Q=Q, tau0=tau0, alpha=alpha, beta=beta, rho=rho,epochs=epochs,
v_cap=v_cap_dict[filename], popsize=popsize)
res.append(obj)
return -min(res)
v_cap_dict = {
'A-n32-k5.csv':100,
'A-n46-k7.csv':100,
'A-n80-k10.csv':100,
'B-n31-k5.csv':100,
'B-n50-k7.csv':100,
'B-n78-k10.csv':100,
'E-n33-k4.csv':8000,
'E-n51-k5.csv':160,
'E-n101-k8.csv':200,
'E-n101-k14.csv':112,
'P-n40-k5.csv':140,
'P-n101-k4.csv':400
}
filename = list(v_cap_dict.keys())[11]
tau0 = 2000
popsize = 100
epochs = 300
start_time = time.time()
rf_bo = BayesianOptimization(f=F,pbounds={'rho':(0.001,0.98),'alpha': (0.001, 5),'beta':(0.001,5),'Q':(1000,2000)})
rf_bo.maximize(n_iter=50, init_points=10)
run_time = time.time() - start_time
sp = rf_bo.space
history_obj = sp.target.tolist()
history_pararm = sp.params.tolist()
贝叶斯调参默认是求最大化,因此这里将目标函数取负数
2.3 参数设定
不同算法在不同算例上的参数搜索空间基本一样,但由于ALNS算法在大规模算例上的求解较为耗时,因此部分算例上做了缩小,这里仅给出其一种搜索空间。
2.4 实验方法
由于元启发式算法具有很大的随机性,相同的参数设置也可能跑出不同的结果,因此设定每组“算法-参数-算例”组合均运行2次,取最好的一组用于反馈贝叶斯。
为了加快进度,早一点分享给大家,这里同时运行3组代码,因此可能会对解的质量及求解时间产生干扰。
3 实验结果
3.1 最优解统计
3.1.1各数据集上的算法性能对比
首先来看看在同一算例上,不同算法的表现如何:
3.1.2 求解结果汇总
以上结果汇总如下:
求解误差如下:
3.1.3小结一下
- 整体来看,在实验范围内8个算法均无法找到已知最优解,最小的求解误差为0.39%(ALNS-A-n32-k5)。
- ALNS算法在各数据集上的表现大多位列第一(B-n31-k5稍逊于ACO)
- ACO算法在各数据集上的表现大多位列第二(在A-n32-k5,B-n31-k5,B-n50-k7三个数据集上稍逊于GA);
- GA算法在各数据集上的表现大多位于第三;
- 其他算法的性能不再一一列举啦
3.1.4 还有话说
虽然根据以上结果来看,基于split算法实现的8个算法并未找到已知最优解(虽然很接近啦),但并不代表就无法找到最优解,一方面小编实现的仅是基本的元启发式算法,还有众多改进版本来提升性能。且,加入启发式规则也是不错的想法。这里以文献[A simple and eBective evolutionary algorithm for the vehicle routing problem] 中的数据来佐证:
以后再慢慢设计改进策略~
3.2 调参时间统计
3.2.1 各数据集上的运算时间对比
除了目标函数外,大家肯定也很关注算法的求解时间如何。这里不再具体去分析某一参数组合下的算法运行时间,而是从整个调参过程的时间消耗来评判。这里根据算例的规模大小进行了排序,尝试去看随着问题规模的增大,算法求解时间的变化趋势,并大致做了数据拟合。
3.2.2 运算时间汇总
各算法在不同数据集上的求解时间汇总如下:
3.2.3 小结一下
整体来看,随着算例规模的增加,各算法的求解时间都呈现出指数增长趋势,ALNS算法和ACO算法的增长速度明显高于其他算法。
3.3 最优参数统计
8个算法在不同数据集上的最优参数组合如下所示,未在调参范围的参数被设置为默认值。
(1)ACO
(2)ALNS
(3)DE
(4)DPSO
(5)GA
(6)QDPSO
(7)SA
(8)TS
可以看出同一算法在不同数据集上的最优参数组合还是有很大差异的。所以说:调参工作是很重要的!
3.4 最优解路径
为了尽快地将优质内容分享给各位读者,这里悄悄偷个懒,仅呈现ACO算法在最优参数组合下的优化结果(ALNS算法实在太耗时啦)。此外,由于算法具有随机性,因此在最优参数组合下,不一定保障能得出上述调参时的结果,但差异不大~。
(1)A-n32-k5
(2)A-n46-k7
(3)A-n80-k10
(4)B-n31-k5
(5)B-n50-k7
(6)B-n78-k10
(7)E-n33-k4
(8)E-n51-k5
(9)E-n101-k8
(10)E-n101-k14
(11)P-n40-k5
(12)P-n101-k4
3.5 调参过程
12套数据集×8套算法=96组结果,实在太多啦,根本分析不完。这里仅以【A-n32-k5】数据集为例,分析使用贝叶斯调参时个别算法的参数探索过程。
(1)ACO
(2)ALNS
(3)DE
(4)DPSO
(5)GA
从上图可以看出,贝叶斯工具会逐渐形成一个高密度采样区,这也是高斯过程的体现(一人之见)。
4 结果分析
好了,估计各位读者也看累了。长话短说,这里对开头读者的问题做以下回答。
问题一:为什么使用split?会影响求解质量吗?
- split方法允许用户采用无车场信息的编码方式(文献中叫做 ‘TSP-like permutation chromosomes’),把容量、时间、里程等约束交给split处理,这样就无需在迭代中反复检查/修复不可行解,便于直接使用各算法的邻域搜索过程。
- 特定的split会建立TSP-like permutation chromosomes’ 与车辆路径集合的唯一映射。反过来思考的话,最优解也对应一个唯一的TSP-like permutation
chromosomes’,因此找到最优的TSP-like permutation
chromosomes’,就可以找到原问题的最优解。这里究竟影响多大,小编暂时无从考证。- 学习过小编分享的算法的读者应该知道,小编推出的各系列VRP问题,都具有类似的代码架构,其最大的区别在于split机制不同,代码具有很强的迁移和扩展性,这也是小编推崇的原因。
问题二:与标准数据集对比如何?
- 上述实验结果大概率代表了目前的代码版本的求解效果:尚无法找到测试数据集的已知最优解,但很接近啦
- 从目标函数来看,ALNS,ACO,GA的效果都是很不错的。兼顾时间的话,ACO和GA可能更占优势。