遗传算法
智能算法简介
智能算法是智能技术领域的一个分支。智能算法出现的原因是,人们在知识新陈代谢速度快和知识繁杂的社会里,需要用高效的数据挖掘工具从各类数据中提取有用的信息和知识,以便于提高生产效率降低生产成本。以前这些工作都是人来操作的,但后来出现了一些模仿人脑力劳动的的算法出现减少了人类的工作量,这些算法被称为智能算法,智能算法都有一个显著的特征——机械性。常用的智能算法有遗传算法、粒子群算法、蚁群算法、模拟退火算法、神经网络算法等等,今天我们介绍遗传算法。
什么是遗传算法
遗传算法是一类借鉴生物界的进化规律(适者生存、优胜劣汰的遗传机制)演化而来的随机化搜索方法;是模拟达尔文进化论和孟德尔遗传学机理的计算模型。主要特点是直接对结构对象进行操作,不存在求导和函数连续性的限定;具有更好的全局寻优能力;采用概率化的寻优方法,能自动获取和指导优化的搜索空间,自适应地调整搜索方向,不需要确定的规则。遗传算法由编码、适应度评估和遗传运算三部分组成,其中遗传运算又包括染色体的复制、变异、交叉等。
遗传算法的实现
1、编码
遗传算法的编码有浮点编码和二进制编码两种,我们介绍二进制编码规则(因为二进制编码方便染色体进行遗传、变异和突变等操作)。设某个参数的取值范围为 (L,U),使用长度为k的二进制编码表示该参数,则此时的对应关系为:
2、解码
解码的目的是为了将不直观的二进制数据还原成十进制。个体的二进制编码对应的解码公式如下所示
遗传算法的编码和解码过程在宏观上可以对应生物的基因型和表现型,微观上可以对应基因的转录和翻译。
3、交配
“交配运算”是使用单点或多点进行交叉的算子。首先随机产生一个或多个交配点的位置,然后两个个体在交配点互换部分基因编码从而形成子个体。例如,染色体S1=0100101和染色体S2=1010010交换后三位的基因,则会形成两个子个体S3=0100010和S4=1010101
4、突变
“突变运算”是使用基本的位运算进行基因突变。为了避免算法在迭代过程中种群过早收敛,对于二进制的基因编码组成的个体种群,实行基因码的小几率翻转。例如染色体S=1101101,将其第四位上的1变成0得到S’=1100101,S’可以看做原染色体通过变异产生的子染色体。
5、个体适应度评估
进化论中的适应度,是表示某一个体对环境的适应能力,也表示该个体繁殖后代的能力。遗传算法的适应度函数也叫评价函数,是用来判断群体中的个体的优劣程度的指标,它是根据所求问题的目标函数来进行评估的。
遗传算法在搜索进化过程中一般不需要其他外部信息,仅用评估函数来评估个体或解的优劣,并作为以后进行遗传操作的依据。由于遗传算法中,适应度函数要比较排序并在此基础上计算选择该利率,所以适应度函数的值要取正值。
6、复制
复制运算是根据个体的适应度大小决定下代遗传的可能性,设个体i的适应度为 fi,则个体i被选取的概率为
若个体适应度高,则被选取的几率大,它的基因在种群中扩散的概率就会比较大。个体复制几率比较小的个体,在遗传的过程中会逐渐被淘汰。
遗传算法的python实现
import numpy as np
import random
from math import *
bounds=[-2,2] #一维变量的取值范围
precision=0.0001 #运算精度
bounds_begin ,bounds_end = bounds[0] ,bounds[1]
#计算满足所需精度需要至少多少染色体
BitLength=ceil(log((bounds_end-bounds_begin)/precision ,2))
popsize=50 #初始种群大小
Generationmax=200 #最大代数
pcrossover=0.9 #交配概率
pmutation=0.09 #变异概率
#产生初始种群
population = np.rint(np.random.rand(popsize,BitLength))
def func(x):
"""
目标函数: y=200exp(-0.05x)*sin(x) x∈[-2,2]
参数:x 自变量
返回值:y 因变量
"""
y = 200*exp(-0.05*x)*sin(x)
return y
def fitnessfun(population):
"""
计算种群适应度和累计概率函数 fitnessfun()
参数:population 种群的染色体
返回值:[Fitvalue,cumsump] 适应度和累计概率
"""
popsize=population.shape[0]
Fitvalue=[]
for i in range(0,popsize):
x=0
for j in range(BitLength-1,-1,-1):
x += population[i,j]*2**j
xx=bounds_begin + x*(bounds_end-bounds_begin)/(2**BitLength-1)
y=func(x)+230 #保证适应度为正值
Fitvalue.append(y)
#计算选择概率
fsum=sum(Fitvalue)
Perpopulation=[item/fsum for item in Fitvalue]
#计算累计概率
cumsump=[Perpopulation[0]]
for i in range(1,popsize):
cumsump.append(cumsump[i-1]+Perpopulation[i])
return [Fitvalue,cumsump]
def IfCroIfMut(mutorcro):
"""
根据概率判断是否应该发生交叉或变异
轮盘赌算法
"""
test=np.zeros(100)
l=round(100*mutorcro)
for i in range(l):test[i]=1
n=random.randint(0,99)
return test[n]
def mutation(snew,pmutation):
"""
变异函数,使染色体发生变异
参数:snew,pmutation 种群染色体,变异概率
返回值:snnew 变异后的染色体
"""
BitLength=snew.shape[0]
snnew=snew
pmm=IfCroIfMut(pmutation)
if pmm:
chb=random.randint(0,BitLength-1)
snnew[chb]=1-snew[chb]
return snnew
def crossover(population,seln,pc):
"""
交叉函数,使得两个染色体进行交叉
参数:population,seln,pc 种群染色体,交叉个体,交叉概率
返回值:交叉后的染色体
"""
BitLength=population.shape[1]
pcc=IfCroIfMut(pc)
if pcc:
chb=random.randint(0,BitLength-1)
aappend1 = population[seln[0],0:chb]
aappend2 = population[seln[1],chb:]
bappend1 = population[seln[1],0:chb]
bappend2 = population[seln[1],chb:]
a = np.append(aappend1,aappend2)
b = np.append(bappend1,bappend2)
else:
a=population[seln[0],:]
b=population[seln[1],:]
a1=a.reshape(1,a.shape[0])
b1=b.reshape(1,b.shape[0])
return np.append(a1,b1,axis=0)
def Selection(population,cumsump):
"""
新种群选择操作
"""
i_,j_=np.random.rand(1,2)[0,0],np.random.rand(1,2)[0,1]
prand1=[item - i_ for item in cumsump]
prand2=[item - j_ for item in cumsump]
i,j = 0,0
while prand1[i]<0 : i = i+1
while prand2[j]<0 : j = j+1
return [i,j]
#计算适应度,返回适应度Fitvalue和累计概率cumsump
[Fitvalue , cumsump] = fitnessfun(population)
Generation=1
ymax=[]
xmax=[]
ymean=[]
scnew=np.empty(shape=[0,16])
while Generation < Generationmax + 1:
scnew=[]
flag=1
for j in range(0,popsize,2):
#选择操作
seln=Selection(population,cumsump)
#交叉操作
scro=crossover(population,seln,pcrossover)
a=mutation(scro[0,:],pmutation)
b=mutation(scro[1,:],pmutation)
a1=a.reshape(1,a.shape[0])
b1=b.reshape(1,b.shape[0])
if flag == 1:
flag -=1
scnew=np.append(a1,b1,axis=0)
else:
scnew=np.append(scnew,a1,axis=0)
scnew=np.append(scnew,b1,axis=0)
population=scnew #产生了新的种群
[Fitvalue,cumsup]=fitnessfun(population)
fmax,index=np.max(Fitvalue),np.argmax(Fitvalue)
fmean=np.mean(Fitvalue)
ymax.append(fmax)
ymean.append(fmean)
x=0
for j in range(BitLength-1,-1,-1):
x += population[index,j]*2**j
xx=bounds_begin + x*(bounds_end-bounds_begin)/(2**BitLength-1)
xmax.append(xx)
Generation += 1
print(func(xx))
欢迎关注公众号 : 数学算法实验室
算法与人工智能