天天看点

科学计算之遗传算法python实现遗传算法

科学计算之遗传算法python实现☞1

  • 遗传算法
    • 染色体编码和种群初始化
    • 适应度和选择
    • 选择交配
    • 选择变异
    • 代码主体
    • 目标函数
    • 运行效果

版权声明:本文为威哥哥带你写代码原创文章,有错请评论,转载请注明,谢谢

遗传算法

遗传算法是一种随机自适应的随机搜索算法,从一定程度上反应了达尔文的进化理论"自然选择"和“优胜劣汰”,算法流程并不复杂,大致分为6个部分,分别是染色体编码,种群初始化,适应度评价,选择种群,交配,变异。其中染色体编码相对来说比较复杂,需要将十进制转化为相应的二进制,其中针对不同的精确度需要分析不同的二进制位数,本文主要针对维度为1的函数进行优化,针对高维函数的代码将在下一篇文章中展示。

染色体编码和种群初始化

博主这里的精确度取的0.001,定义域【0,5】,所以需要10个二进制位,种群数量取的100,所以需要生成100个长度为10的二进制编码。

初始化:

def initialize():         
    pop=np.random.randint(2,size=(100,10))
    return pop
           

这里我们可以看看种群(部分)

array([[0, 1, 1, 0, 1, 0, 1, 1, 0, 1],
       [1, 0, 1, 1, 0, 1, 0, 0, 0, 1],
       [0, 1, 1, 1, 1, 1, 1, 0, 1, 1],
       [0, 0, 0, 1, 0, 0, 1, 0, 1, 0],
       [0, 0, 0, 0, 1, 0, 1, 1, 1, 1],
       [1, 0, 1, 0, 0, 1, 0, 1, 0, 1],
       [0, 1, 0, 0, 0, 1, 1, 1, 0, 1],
       [1, 0, 0, 1, 1, 0, 1, 0, 0, 0],
       [1, 1, 1, 0, 0, 0, 1, 0, 1, 1],
       [1, 0, 1, 0, 1, 1, 0, 1, 1, 0],
       [1, 1, 1, 0, 0, 1, 1, 0, 1, 0],
       [0, 1, 1, 0, 0, 0, 1, 0, 1, 0],
       [1, 1, 1, 1, 0, 1, 0, 1, 0, 1],
       [1, 1, 1, 0, 0, 1, 1, 1, 1, 0],
       [1, 1, 0, 0, 0, 1, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 1, 1, 0, 0, 1, 1],
       ........
 
           

如果相应的个体不再定义域内部怎么办?这里就需要用等分的思想稍微转化一下

pop.dot(2**np.arange(10)[::-1])/float(2**10-1)*5 
           

其中5是定义域的长度,等分成2^10-1分,然后乘对应的大小就完成了转换。

适应度和选择

适应度的评估函数用于评估每个染色体的适应值,用于进行优胜劣汰的自然选择,每个染色体的适应度为F(xi)/sum(F(xi));对应的适应度越大则在自然选择过程中的概率也越大。

def fitness(pop):
    for i in range(100):
        pop[i]=F(pop[i])
        if pop[i]<0:
            pop[i]=0
    return pop


def selection(pop,fit,sum_fitness):
    i = np.random.choice(np.arange(100), size=100, replace=True, p=fit/sum_fitness)
           

其中np.random.choice()的用法在这里不做解释,请自行百度。

关于

if pop[i]<0: pop[i]=0

这里是因为后面要算适应度,适应度也即个体被选择的概率,不应该小于0,所以将小于0的元素全部换成0代替。

选择交配

首先这里需要设置一个种群交配概率,博主设置的为0.8,被选择的种群还需要选择交换的DNA片段,这里关于DNA的交换片段可以根据1/2原则进行设置,这里用的是生成0 1随机数然后转化成bool型实现的。

def crossover(parent,pop):             
    if np.random.rand()<0.8:
        i= np.random.randint(0, 100, size=1)     #选择母体进行交配
        point=np.random.randint(0,2,size=10).astype(np.bool)
        parent[point]=pop[i,point]
    return parent
           

选择变异

和交配一样,首先设置一个变异的概率,然后针对不同的个体进行每一个染色体中DNA片段的等概率变异,这里的变异概率设置为0.03

def mutation(m):          
    for i in range(10):
        if np.random.rand()<0.003:
            if m[i]==1:
                [i]=0
            else:
                [i]=1
    return m
           

代码主体

代码总体部分非常简单,设置一个循环即可搞定。流程图为

科学计算之遗传算法python实现遗传算法
pop=selection(pop,fit,sum(fit))
    pop_copy = pop.copy()
    for parent in pop:
        m = crossover(parent,pop_copy)
        m = mutation(m)
           

目标函数

def F(x):                      
    y=5*x+5*np.sin(5*x)+2*np.cos(3*x)
    return y
           

运行效果

科学计算之遗传算法python实现遗传算法

可以看见是逐步向最大值移动的,虽然效率有待提高,不是最终可以针对多为函数的代码版本,这里就不放完整代码了,需要的可以评论留邮箱。