DE
算法流程
- 初始化参数和种群
- 变异
- 交叉
- 适应度值计算
- 选择
- 未达到条件 继续2-5
DE-差分进化算法,与GA(简单遗传算法)思想大致相同,个人觉得主要的差别在于DE利用了个体之间的协同性,引入了差分向量的概念。
差分向量
只是用了一个差向量,可以使用2个或者3个,个人测试效果差异不大。
V[i, :] = BEST_X + SIGMA * (X[r[0], :] - X[r[1], :])
解释:此处的基量我使用了类似于精英保留策略的方法,将当前代适应度值最好的个体单独拿出来,以供给种群的其他个体进行参考变异。这个操作更好的为种群个体的进化指明了方向,但是也一定程度上的减少了随机性。
交叉操作
再根据变异的结果进行交叉,交叉的对象是上一代的个体和对应的变异后的变异个体。具体交叉的则是每个个体在各个维度上的分量Xij。以一定的概率进行分配,因为此处利用了BEST_X保留的策略,所以我在分配的时候倾向于尽量多的保留原来的Xij,即原来个体在某个维度上的分量,有利于快速收敛。
# 至少有一个分量对U[i,j]作出了贡献
# CR调小 有利于往BEST_X的方向进化
if np.random.random() > CR or j == jRand:
U[i, j] = X[i, j]
else:
U[i, j] = V[i, j]
计算适应度值和选择操作
# 变异的种子表现更好
if FITS[i] >= FITS_U[i]:
X[i, :] = U[i, :]
FITS[i] = FITS_U[i]
# 是否比BEST_X适应度值更小
if FITS_U[i] < Func(BEST_X):
BEST_X = U[i, :]
结果
对Rastrigr函数进行优化:
迭代次数平均在1000次左右
有问题希望可以提出,多多交流~
已经更新其他相关的进化算法(GA、ES、CMA-ES、EP等)~
import numpy as np
"""
基本差分进化算法 de
"""
MAX_GENERATION = 2000 # 最大迭代次数
GENERATION = 0 # 当前代数
BOUND_X = [-5.12, 5.12] # 上下界
L = 30 # 种子的维度
N = 200 # 种群规模
SIGMA = 0.333 # 缩放因子
CR = 0.1 # 交叉概率
BEST_X = 0
FITS = np.zeros(N)
FITS_U = np.zeros(N)
V = np.zeros((N, L))
U = np.zeros((N, L))
E = 1e-15
T = 30
G = np.zeros(T)
# 目标函数
def Func(x):
return np.sum(x[:] ** 2 - 10 * np.cos(2 * np.pi * x[:]) + 10)
if __name__ == '__main__':
for k in range(T):
GENERATION = 0 # 当前代数
BEST_X = 0
FITS = np.zeros(N)
FITS_U = np.zeros(N)
V = np.zeros((N, L))
U = np.zeros((N, L))
# 1、初始化
X = (BOUND_X[1] - BOUND_X[0]) * np.random.random((N, L)) + BOUND_X[0]
# 找出随机生成的最好的种子
for i in range(N):
FITS[i] = Func(X[i])
# 找出最好的种子 适应度值最小
BEST_X = X[np.argmin(FITS)]
while GENERATION < MAX_GENERATION:
if Func(BEST_X) < E:
print(GENERATION)
break
# 2、变异
for i in range(N):
r = np.random.randint(1, N, 2)
# 变异向量V[i, :]
# 变异向量的基使用每次适应度值最好的个体BEST_X
# V[i, :] = BEST_X + SIGMA * (X[r[0], :] - X[r[1], :]) + SIGMA * (X[r[2], :] - X[r[3], :])
# V[i, :] = BEST_X + SIGMA * ((X[r[0], :] - X[r[1], :]) + (X[r[2], :] - X[r[3], :]))
# SIGMA过大 无法收敛
# SIGMA过小 早熟
V[i, :] = BEST_X + SIGMA * (X[r[0], :] - X[r[1], :])
# print(V)
# 3、交叉操作
for i in range(N):
jRand = np.floor(np.random.random() * L)
for j in range(L):
# 至少有一个分量对U[i,j]作出了贡献
# CR调小 有利于往BEST_X的方向进化
if np.random.random() > CR or j == jRand:
U[i, j] = X[i, j]
else:
U[i, j] = V[i, j]
# 4、计算适应度值+选择操作
for i in range(N):
FITS[i] = Func(X[i])
FITS_U[i] = Func(U[i])
# 变异的种子表现更好
if FITS[i] >= FITS_U[i]:
X[i, :] = U[i, :]
FITS[i] = FITS_U[i]
# 是否比BEST_X适应度值更小
if FITS_U[i] < Func(BEST_X):
BEST_X = U[i, :]
GENERATION += 1
print("最优值:", Func(BEST_X))
if GENERATION == MAX_GENERATION:
print("当前次未能收敛")
G[k] = GENERATION
print("代数:", G)
print("平均代数:", np.mean(G))