参考资料《智能优化算法及其matlab实例第二版》
第一次写博客,格式什么的不太清楚,大家见谅。
遗传算法
学习过程中,为了加深自己理解,在matlab源码的基础上采用Python进行改写,功能一致,对其实现过程进行了修改。个人认为这个版本的代码对初学者更为友好。
遗传算法的基本概念本文简单介绍,重点在于给出实现代码。
简而言之,遗传算法就是一个小世界。我们需要为这个世界创造规则。
种群:所有个体的集合,我们会在最初的设定中,给出种群的数目,这个数量就是一次迭代中所有存活的个体数。
个体:染色体的携带者,现实世界中的个体是鲜活的,明确的,但是在遗传算法中,它可能就表现为一段二进制变量,或者是一些实数变量,这个会跟我们选取的染色体表现方式有关。在本例中选取0、1编码的方式刻画染色体。
染色体:每一个个体携带的编码,通常适应度函数会把染色体的信息作为输入以此评估个体的优劣,在遗传算法中个体和染色体的概念比较相似,有时理解为一个也ok的,只要不影响编写代码。
适应度函数:评估个体好坏的函数,适者生存,适应度函数就是选出“适者”的函数。每一个特定问题对应不同的生存法则,所以适应度函数都不一样。
迭代次数:可以理解为这个世界存在的时间,我们会预设一个迭代次数的最大值,算法迭代次数达到最大值时,种群进化过程结束。
复制、交叉、变异:参考生物意义上的概念,都是针对染色体的操作。
代码部分
直接附上代码,代码复制后可以直接运行。
import numpy as np
import matplotlib.pyplot as plt
# import math as mt
import seaborn as sns
sns.set_style('darkgrid')
x=np.arange(0,10,0.02)
y=x+10*np.sin(5*x)+7*np.cos(4*x)
plt.plot(x,y) #画原函数
plt.title('Primitive function')
plt.xlabel('x',fontsize = 10)
plt.ylabel('y',fontsize = 10)
plt.savefig('pic1',bbox_inches = 'tight',pad_inches = 0,dpi =350)
plt.close()
def funcl(x):
y=y=x+10*np.sin(5*x)+7*np.cos(4*x)
return y
#%%
NP=50 #初始化种群数
L=20 #二进制位串长度
Pc=0.8 #交叉率
Pm=0.3 #变异率
G=100 #最大遗传代数
Xs=10 #上限
Xx=0 #下限
f=np.random.randint(0,high=2,size=(NP,L)) #生成随机初始种群
fit=np.zeros((1,100))[0].tolist()
x=np.zeros((1,100))[0].tolist()
trace=[]
xtrace=[]
#%%遗传算法循环
for i in range(G):
print(i)
nf=f
for M in range(0,NP,2):
p=np.random.rand() #交叉
if p<Pc:
q=np.random.randint(0,high=2,size=(1,L))[0].tolist()
for j in range(L):
if q[j]==1:
temp=nf[M+1][j]
nf[M+1][j]=nf[M][j]
nf[M][j]=temp
j=1
while j<=(NP*Pm):
h=np.random.randint(1,high=NP) #变异
for k in range(round(L*Pm)):
g=np.random.randint(1,high=L)
nf[h][g]=(not nf[h][g])+0 #取反操作,python和matlab不一样
j+=1
#交叉变异结束之后,新一代nf加上前代f共2*NP个个体进行筛选
newf=np.vstack((f,nf))
for j in range(newf.shape[0]):
U=newf[j]
m=0
for k in range(L):
m=U[k]*(2**(k-1))+m #将二进制解码为定义域范围内十进制
x[j]=Xx+m*(Xs-Xx)/(2**(L-1))
fit[j]=funcl(x[j]) #适应度函数
maxfit=max(fit)
minfit=min(fit)
if maxfit==minfit:
break
rr=fit.index(maxfit)
fbest=f[rr]
xbest=x[rr]
Fit=(np.array(fit)-minfit)/(maxfit-minfit)
sum_Fit=sum(Fit) #概率筛选复制操作(不是简单的复制,我们是根据适应函数给导向的)
Pfit=Fit/sum_Fit
indexnf=np.arange(0,100).tolist()
ng=[]
for dex in range(NP):
ng.append(np.random.choice(indexnf,p=Pfit))
for j in range(NP):
f[j]=newf[ng[j]]
f[0]=fbest
trace.append(maxfit)
xtrace.append(xbest)
plt.plot(trace,color='green', marker='o',linewidth=2, markersize=3)
plt.xlabel('Number of iterations',fontsize = 10)
plt.ylabel('maxyvalue',fontsize = 10)
plt.savefig('pic3',bbox_inches = 'tight',pad_inches = 0,dpi =350)
plt.close()
plt.plot(xtrace,color='m', marker='o',linewidth=2, markersize=3)
plt.xlabel('Number of iterations',fontsize = 10)
plt.ylabel('Corresponding xvalue',fontsize = 10)
plt.savefig('pic2',bbox_inches = 'tight',pad_inches = 0,dpi =350)
plt.close()
简单介绍一下代码内容:
我们的目标是对这个函数求最大值: f(x) = x+10sin(5x)+7cos(4x)
它的图像长这样:
估计应该是7到8之间的那个点最大,然后,就开始遗传算法了。与参考资料源码不同的是,我们生成的第一代种群数目是50,先经过了交叉和变异,得到50个新的个体,加上原来的50个,就一共是100了,再对这100个进行筛选复制的过程,选出50个作为下一代,迭代次数为100次。下面是算法得到的结果。第一张是收敛得到的x的值,第二张是maxy的值。