差分进化算法
1.1 概述
-
差分进化算法(Differential Evolution, DE)是有Kenneth Price和Rainer Storn在尝试解决切比雪夫多项式拟合问题时提出的。
-
是近年来最为流行的进化算法,性能非常优秀!在连续优化问题领域效果出类拔萃,而蚁群算法在组合问题、离散问题优化上极其优秀。
-
在进化计算领域的知名学术会议IEEE CEC中的多节优化竞赛中,改进的DE算法排名前列。
1.2 算法步骤
-
变异操作
-
交叉操作
-
选择操作
变异操作生成变异个体,然后进行交叉操作生成实验个体,然后进行选择
-
变异操作(DE区别于其他算法最重要的特征)
-
是区别于其他进化算法的重要特征,生成变异个体V
-
DE/rand/1
-
,其中
为差分向量,角标r表示当前个体为随机个体,
为基向量,DE/rand/1 中的 1 表示只有一个差分向量
-
将 r2 和 r3 向量做差,然后通过 F 进行缩放,将缩放后的向量差和基向量 r1 相加,生成变异个体 V
-
-
DE/rand/2
-
,其中
和
为差分向量,r为随机个体,基向量随机选,2表示有两个差分向量,多一个差分向量导致扰动更强,随机更好,全局搜索能力强
-
-
DE/best/1, 开采力强,局部搜索能力强
-
DE/best/2
-
DE/current-to-best/1
-
-
交叉操作
-
对目标个体和变异个体进行咋交,交换维度上的信息来生成实验个体 U,增加种群的多样性
-
二项式交叉(简记为 bin)和指数较差(简记为 exp)
-
二项式交叉(均匀交叉):
,其中 CR 为交叉概率,表示 U 中某个基因来自于 V 的概率。二项式交叉要求保证 U 中至少有一个基因来自于 V,所以设置参数
为
内的整数,其中 D 为个体基因维度,也就是向量的维度,使第 j 个基因必须来自于 V。
-
指数交叉(不常用):
, <>表示求余操作
-
-
选择操作
-
从目标个体 X 和实验个体 U 中选出较优的一个进入下一代
-
一对一选择(One-to-one selection)
-
1.3 代码部分
1.3.1 规定模型基础参数
D = 2 # x 向量维度
F = 0.5 # 缩放率
CR = 0.9 # 变异率
LOW = [-3, -2] # 上界
UP = [3, 2] # 下界
PS = 30 # 种群大小
MaxFEs = 5E3 # ? 最大函数评估数
1.3.2 初始化种群
FEs = 0 # ? 当前函数评估数
pop :List[indi] = [] # 种群
for i in range(PS): # 初始化种群
x = np.random.rand(2) # 生成当前个体的 x
pop.append(indi(x, six_hump_camel_back(x))) # 将当前个体的 fitness 求出,并将个体存入种群数组
FEs += PS # ? 函数评估数加 PS
1.3.3 DE 算法迭代
while FEs<= MaxFEs: # 当当前评估数不超过最大评估数时,进行差分进化算法
for i in range(PS): # 遍历整个种群
trialindi = pop[i].clone() # 将当前个体的深拷贝存储到变量中
# * DE/rand/1
r = random.sample(range(PS-1), 3) # 随机选三个除了 i 以外的数字,作为选出的三个个体的索引
for j in range(3): # 选择方法使用 sample 先从 [0, PS-1) 中不重复的随机选择三个数字
if r[j]>=i: # 再将三个数字中,超过当前个体 i 的数字进行 +1
r[j] += 1 # 实现避免选择到第 i 个个体的效果
v = pop[r[0]].x + F * (pop[r[1]].x - pop[r[2]].x) # * :math:`V_i(t)=X_{r1}(t)+F \cdot (X_{r2}(t)-X_{r3}(t))`
# * bin
jrand = random.randint(1, D) # * 随机 [1, D] 的整数作为 rand_j,因为 bin 交叉必须保证 U 有至少一个基因来自于 V
u = np.array([(pop[i].x[j], v[j])[random.random()<CR or jrand==j] for j in range(D)]) # 交叉操作,使用特殊的三目运算写法实现交叉
# * selection
u_fitness = six_hump_camel_back(u) # 求出 U 的适应度
if u_fitness<pop[i].fitness: # 实验个体 U 和 当前个体 X 优胜劣汰
pop[i] = indi(u, u_fitness)
FEs += PS # 评估数 +PS
1.3.4 寻找最优个体
# 找出 DE 算法后的种群内的最有适应度个体
best_index = 0
for i in range(PS):
if pop[i].fitness < pop[best_index].fitness:
best_index = i