遗传进化算法
遗传进化算法,简称遗传算法或进化算法(Genetic Algorithm GA),GA的主要思想是通过模拟自然界生物的繁殖和自然选择来达到不断优化,从而得到较优解的过程.遗传算法的流程如下图所示,其中对遗传物质的定义和描述,个体的适应度度量方法,以及交配和突变策略是较为主要的步骤.
图1 遗传算法流程图
第一步,其中输入数据主要输入种群数量,DNA长度,异变率,繁衍代数这些算法的通用参数,在各个问题中,也可能定义一些问题相关的参数.
第二步,生成初代样本,大多数的问题的初代的样本可以采用随机生成,当然,在一些问题上,也可以采用一些特殊生成函数或规则来生成,具体问题具体分析.
第三步,进入循环,循环的过程主要分为选择,交配,和异变.
第四部,选择,在该部,我们需要计算出所有个体的适应度fitness,并通过这项参数来选择能适应环境的一定数量的样本来进行繁衍,选择规则应该是与fitness正相关的,个体越适应环境,越应该被选择,最简单的办法就是择优选择,完全按照fitness进行排序,选取前n个个体.但是这种规则好像一点也也不给后面得人机会,我们希望给予即使在此代不是很优秀的人一定的机会使得他的基因可以传递下去,因为其后代也有非常适合环境的可能性.因此我们在构造选择函数是可以采用一些诸如正太分布的函数或是其他的办法来给予劣势者一些机会.
第五步,交配,交配规则的大体思路是选取父亲的一段基因和母亲的另一段基因结合,产生新个体.交配规则根据具体的问题要具体分析,但需要注意的是子代必须从父母双方都要继承一定的基因来保证传代的关系.
第六步,异变,新的个体的所有基因有一定概率发生基因突变,用此来平衡进化方向不会因为过度的选择而导致趋向一个较优解就停止,有更大的机会逼近最优解.
最后传代结束后输出种群的最优者,我们认为该个体是这个问题的一个较优解.并且这个较优解在一定精度内可以近似认为是最优解.
下面我们通过一个例子来理解遗传算法.构造函数公式如公式1,我们使用遗传算法来求函数值较高的x值.f(x)的图像如图2.
图2 f(x)图像
在该问题中,我们主要思考的几个问题就是基因该如何定义?fitness如何度量?交配和突变规则如何定义?
首先也是最重要的就是基因如何表达.在本例中基因所蕴含的信息是x的值.我们使用十位二进制来表达[0,5)之内的数,则对于单个个体来说,基因与性状的关系如图3所示.我们用十位二进制即0-1023范围内的整数来代表[0,5)内的数,精度是1/1024,在本问题中这个精度足够,如果要求更高的精度可以增加基因长度.
其次是适应度度量.在本例中函数f(x)就可以表达fitness.当然这是由于我们的问题本身就是模拟函数,在模拟其他问题是,我们可能需要定义fitness的方法或者函数.
最后是交配规则和突变规则,由于我们的基因是10位二进制序列,交配规则就可以定义为从父亲取前5位,母亲取后5位,而突变规则即对每位概率取反(即0变为1,1变为0)即可.
在种群数量为100,繁衍代数为200,突变率0.003,交配率为0.8的情况下,最后实验结果为3.2991202346,我们在图像上发现其确实是与函数最高值非常接近的值.证明实验结果有效.
图3 基因表达过程
以下为实现代码,实现语言为python,工具包主要为numpy.py(矩阵计算)和matplotlib.py(画图)
import matplotlib.pyplot as plt
import numpy as np
DNA_size=10
X_BOUND=[0,5]
cross_rate=0.8
mutation_rate=0.003
pop_size=100
N_GENERATIONS=200
class GA(object):
def __init__(self, DNA_size, DNA_bound, cross_rate, mutation_rate, pop_size,n_generations):
self.DNA_size = DNA_size
DNA_bound[1] += 1
self.DNA_bound = DNA_bound
self.cross_rate = cross_rate
self.mutate_rate = mutation_rate
self.pop_size = pop_size
self.pop = np.random.randint(*DNA_bound, size=(pop_size, self.DNA_size)) #.repeat(pop_size, axis=0)
# print(self.translateDNA(self. pop))
self.n_generations=n_generations
# 模拟函数
def F(self,x): return np.sin(10 * x) * x + np.cos(2 * x) * x
# DNA翻译
def translateDNA(self, pop):
# convert binary DNA to decimal and normalize it to a range(0, 5)
return pop.dot(2 ** np.arange(self.DNA_size)[::-1]) / float(2 ** self.DNA_size - 1) * X_BOUND[1]
# 适配
def get_fitness(self,product):
return product + 1e-3 - np.min(product)
# 选择
def select(self,fitness):
idx = np.random.choice(np.arange(self.pop_size), size=self.pop_size, replace=True,
p=fitness / fitness.sum())
return self.pop[idx]
# 交配
def crossover(self,parent, pop): # mating process (genes crossover)
if np.random.rand() < self.cross_rate:
i_ = np.random.randint(0, self.pop_size, size=1) # select another individual from pop
cross_points = np.random.randint(0, 2, size=self.DNA_size).astype(np.bool) # choose crossover points
parent[cross_points] = pop[i_, cross_points] # mating and produce one child
return parent
# 突变
def mutate(self, child):
for point in range(self.DNA_size):
if np.random.rand() < self.mutate_rate:
child[point] = 1 if child[point] == 0 else 0
return child
# 进化
def evolve(self):
plt.ion() # something about plotting
x = np.linspace(*X_BOUND, 200)
plt.plot(x, self.F(x))
for _ in range(self.n_generations):
F_values = self.F(self.translateDNA(self.pop)) # compute function value by extracting DNA
# something about plotting
if 'sca' in locals():
sca.remove()
sca = plt.scatter(self.translateDNA(self.pop), F_values, s=200, lw=0, c='red', alpha=0.5);
plt.pause(0.05)
# GA part (evolution)
fitness = self.get_fitness(F_values)
print("Most fitted DNA: ", self.pop[np.argmax(fitness), :])
print(self.translateDNA(self.pop[np.argmax(fitness), :]))
self.pop = self.select(fitness)
pop_copy = self.pop.copy()
for parent in self.pop:
child = self.crossover(parent, pop_copy)
child = self.mutate(child)
parent[:] = child # parent is replaced by its child
plt.ioff();
plt.show()
ga=GA(DNA_size=10,
DNA_bound=[0,1],
cross_rate=0.8,
mutation_rate=0.05,
pop_size=100,n_generations=N_GENERATIONS)
ga.evolve()
微生物遗传算法
微生物遗传算法的主要思想认为某些生物的进化过程是不不要淘汰掉劣势生物的,如微生物,他们会通过一种基因感染的方式来传播自己的基因.主要思路是用对抗和感染的方式替换掉经典遗传算法中的交配和选择的过程.对抗感染的思路如下:
选取N对个体,每对个体进行比赛,通过fitness的度量可以决定出一个胜利者winner和失败者loser,我们不对winner进行操作,但对于loser,我们取winner的一段基因植入loser中,然后再进行突变,并把winner和loser放回样本池中.微生物遗传算法认为这种方式比经典遗传算法能更加高效和快速的进化.
相关论文为外国教授Inman Harvey的《The Microbial Genetic Algorithm》一文.
最后,本文主要是观看莫烦python的遗传算法教学视频及我个人的理解而写的,本人才疏学浅,难免有些纰漏,推荐大家去B站,微博或者是油管关注莫烦,这篇论文也可以在他的空间中下载.
莫烦的github教学地址传送门==>https://morvanzhou.github.io/tutorials/machine-learning/evolutionary-algorithm/