之前我们手动实现了 遗传算法。交叉进化算法也是进化算法的一种,他具有参数少,易实现的优点(经测试,由于算法特性,暂时不能像遗传算法一样拟合图片),我们将通过拟合函数来介绍交叉进化算法
依赖包
我们用random来生成随机数,matplotlib画图,同时设置rcParams来保证正常显示中文标签
from random import randint, random
import matplotlib.pyplot as plt
import numpy as np
import os
plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
超参数
我们用max_group表示种群中个体数;savePath来确定图像保存位置;feature即特征数,即函数由几个参数构成;F0为初始变异算子,后续会根据labda进行调整,后续的正在的变异算子F由F0和labda得出
其关系式为
:
λ
=
e
1
−
G
m
G
m
+
1
−
G
F
=
F
0
×
2
λ
其中
G
m
为最大迭代次数,
G
为当前迭代次数
第一次迭代
F
的值接近
2
F
0
,
随后逐渐接近
F
0
其关系式为: \\ \lambda=e^{1- \frac{G_m}{G_m + 1 -G}} \\ F=F0 \times2 ^{\lambda} \\ 其中G_m为最大迭代次数,G为当前迭代次数 \\ 第一次迭代F的值接近2F0, 随后逐渐接近F0
其关系式为:λ=e1−Gm+1−GGmF=F0×2λ其中Gm为最大迭代次数,G为当前迭代次数第一次迭代F的值接近2F0,随后逐渐接近F0
max_group = 50 # 种群中个体数
savePath = "./plt_image"
features = 2 # 个体特征数
F0 = 0.5 # 初始变异算子
CR = 0.1 # 交叉算子
epochs = 100
lower_range = -6
upper_range = 6
labda = np.e ** (1 - epochs / (epochs + 1))
bestScore = 0
bestOne = None
待优化的函数
为了便于后续的类封装,我们在优化时只使用func作为优化的函数,f函数仅用于画图
def f(x, y):
return np.sin(np.sqrt(x ** 2 + y ** 2))
def func(x):
X = x.reshape(-1, features).copy()
return np.sin(np.sqrt(X[:, 0] ** 2 + X[:, 1] ** 2))
初始化
生成族群
这时我们应该注意生成矩阵的形状和范围应满足条件
groups = np.random.rand(max_group,features) * (upper_range - lower_range) + lower_range # 随机生成族群
算法主体
变异
v = []
def variation(g):
global groups
for i in range(max_group):
r1 = randint(0, max_group - 1)
while r1 == i:
r1 = randint(0, max_group - 1)
r2 = randint(0, max_group - 1)
while r2 == i or r2 == r1:
r2 = randint(0, max_group - 1)
r3 = randint(0, max_group - 1)
while r3 == i or r3 == r1 or r3 == r2:
r3 = randint(0, max_group - 1)
x1 = groups[r1]
x2 = groups[r2]
x3 = groups[r3]
labda = np.e * (1 - epochs / (epochs + 1 - g))
F = F0 * 2 ** labda
v.append(x1 + F * (x2 - x3))
交叉
交叉所满足的关系式为
u
i
,
G
+
1
=
(
u
1
i
,
G
+
1
,
u
2
i
,
G
+
1
,
⋅
⋅
⋅
,
u
D
i
,
G
+
1
)
u_{i,G+1}=(u_{1i,G+1},u_{2i,G+1}, \cdot \cdot \cdot , u_{Di,G+1})
ui,G+1=(u1i,G+1,u2i,G+1,⋅⋅⋅,uDi,G+1)
u
j
i
,
G
+
1
=
{
v
j
i
,
G
+
1
,
r
a
n
d
b
(
j
)
≤
C
R
或
j
=
r
n
b
r
(
i
)
x
j
i
,
G
+
1
,
r
a
n
d
b
(
j
)
>
C
R
且
j
≠
r
n
b
r
(
i
)
u_{ji, G+1}=\begin{cases} v_{ji, G+1}, & {randb(j) \leq CR或j=rnbr(i)} \\ x_{ji,G+1}, & {randb(j) > CR且j \not= rnbr(i)} \end{cases}
uji,G+1={vji,G+1,xji,G+1,randb(j)≤CR或j=rnbr(i)randb(j)>CR且j=rnbr(i)
(
i
=
1
,
2
,
⋅
⋅
⋅
,
N
P
,
j
=
1
,
2
,
⋅
⋅
⋅
,
D
)
(i=1, 2, \cdot \cdot \cdot,NP, j=1, 2,\cdot \cdot \cdot, D )
(i=1,2,⋅⋅⋅,NP,j=1,2,⋅⋅⋅,D)
其中v为变异向量,x为原本的向量,u为实验向量,NP为种群最多容纳的个体数,D为每个个体的特征数。randb(j) 为随机生成的概率值,与CR做比较。rnbr(i)为随机的下标,与当前个体下标做对比
u = [] # 选择种群
def cross():
r = randint(0, max_group - 1)
for i in range(max_group):
cr = random()
if cr <= CR or i == r:
u.append(v[i])
else:
u.append(groups[i])
选择
通过比较相同位置的实验向量和原族群向量(即原本的向量),较好的将会替换掉原族群对应的向量,同时要注意边界约数
bestPath = []
def select():
global bestScore
global bestOne
for i in range(max_group):
s1 = func(u[i].copy())
s2 = func(groups[i].copy())
if s1 > s2 and s1 > bestScore:
groups[i] = u[i]
for j in range(len(groups[i])):
if groups[i][j] < lower_range:
groups[i][j] = lower_range
if groups[i][j] > upper_range:
groups[i][j] = upper_range
bestScore = s1
bestOne = groups[i]
bestPath.append(bestOne.copy())
画图
在正式将各个组件组装起来之前,我们先构建一个画图函数,来直观的观察拟合过程
def plt_image(cur):
if not os.path.exists(savePath):
os.mkdir(savePath)
x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 25, c=Z)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_title('寻优过程')
if bestOne is not None:
ax.plot3D(bestPath[:, 0], bestPath[:, 1], func(bestPath), c="r")
plt.savefig(os.path.join(savePath, str(cur) + '.png'))
plt.show()
交叉进化并调用
def Alternative_Evolutionary():
for i in range(epochs):
global v
v = []
variation()
global u
u = []
cross()
select()
global bestScore
global bestOne
print("Epoch : ", i, " Score : ", bestScore)
Alternative_Evolutionary()
bestPath = np.array(bestPath)
plt_image(0)
拟合效果
由于初始化(生成随机数)不同,所以每次运行的结果不会完全相同,但是最终的bestScore总是相似的
代码
上述的所有代码按顺序执行就是完整代码
如果需要类封装后的代码可以从下面下载
GitHub地址:
https://github.com/AiXing-w/Python-Intelligent-Optimization-Algorithms
CSDN地址:
https://download.csdn.net/download/DuLNode/84048830