ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

遗传算法的Python实现(通俗易懂)

2021-04-07 19:30:17  阅读:204  来源: 互联网

标签:10 DNA Python pop print 通俗易懂 np 遗传算法 size


遗传算法的Python实现

一.手工实现

1.导入依赖库

import numpy as np

2.定义全局变量

pop_size = 10  # 种群数量
PC=0.6 # 交叉概率
PM=0.01 #变异概率
X_max=5    #最大值
X_min=0     #最小值
DNA_SIZE=10  #DNA长度与保留位数有关,2**10 当前保留3位小数点
N_GENERATIONS=1000

3.定义遗传算法核心函数

a.目标函数

"""
求解的目标表达式为:
y = 10 * math.sin(5 * x) + 7 * math.cos(4 * x)
x=[0,5]
"""
def aim(x):return 10*np.sin(5*x)+7*np.cos(4*x)

b.解码函数

def decode(pop):
   return   pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) *(X_max-X_min)/ float(2**DNA_SIZE-1) +X_min

我们的种群采取二进制的编码方式,通过这个函数将二进制解码为【X_min,X_max】之间的数。
公式可参考:
在这里插入图片描述

c.适应度计算函数

def fitnessget(pred):
    return pred + 1e-3 - np.min(pred)

一般来说,如果拟合在x的定义域内值域为非负的函可以直接将aim函数作为适应度函数,但是这里我们要拟合的函数包含负数情况,故我们要对其处理变为非负。

d.自然选择函数(轮盘赌)

def select(pop, fitness):           
    # print(abs(fitness))
    # print(fitness.sum())
    idx = np.random.choice(np.arange(pop_size), size=pop_size, replace=True,p=fitness/fitness.sum())
    # print(idx)
    return pop[idx]

轮盘赌算法是比较常用的算法,直白点就是撞大运,适应度高的个体有更大的几率被选择
在这里插入图片描述
假设我们初始4个个体,通过这个函数,我们从4个初始个体中按照权重选择了4个个体
在这里插入图片描述
在这里插入图片描述
虽然我们的个体总量没有发生变化,但适应度高的个体被更多的保留了下来,迭代下去,我们就会得到所谓的纯种个体组成的种群。可是我们并不想要纯种个体,我们想到适应度最高的个体,而纯种个体并不是最优个体,所以我们需要让他们交配。

e.交叉函数

def change(parent, pop):
    if np.random.rand() < PC:    #交叉
        i_ = np.random.randint(0, pop_size, size=1)
        # print(parent)
        cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)
        # print(np.where(cross_points==True))
        # print(cross_points)
        parent[cross_points] = pop[i_, cross_points]
        # print(parent)
    return parent 

我们之所以选择二进制的形式编码,就是因为二进制编码可以很好地模拟染色体的交叉。
即又0——>1,1——>0。但是在一个较小的种群中交配,就是我们所说的近亲间的结婚,子代会有可能继承父代的缺点,所以需要变异。

f.变异函数

def variation(child,pm):                  #变异
    for point in range(DNA_SIZE):
        if np.random.rand() < pm:
            child[point] = 1 if child[point] == 0 else 0
    # print(child)
    return child

至此,遗传算法的全部过程已经结束,不难看出,遗传算法最精髓最重要的地方,便是随机性,虽然每一步操作都充满了随机性,可最终我们仍然会得到最优个体,这是遗传算法的魅力,也是大自然设计的魅力。

4.开始拟合

pop = np.random.randint(2, size=(pop_size, DNA_SIZE))


# print(pop)
for i in range(N_GENERATIONS):
    #解码
    # print(pop)
    X_value= decode(pop)
    
    #获取目标函数值
    F_values = aim(X_value)
    
    #获取适应值
    fitness = fitnessget(F_values)
    # print(fitness)
    if(i==0):
        max=np.max(F_values)
        max_DNA = pop[np.argmax(F_values), :]
        
    if(max<np.max(F_values)):
        max=np.max(F_values)
        max_DNA=pop[np.argmax(F_values), :]
        
    if (i % 10 == 0):
        print("Most fitted value and X: \n",
              np.max(F_values), decode(pop[np.argmax(F_values), :]))
    #选择
    pop = select(pop,fitness)
    # print(pop)
    pop_copy = pop.copy()
    # print(pop_copy)
    for parent in pop:
        # print(parent)
        child = change(parent,pop_copy)
        child = variation(child,PM)
        # print(child)
        parent[:] = child
print("目标函数最大值为:",max)
print("其DNA值为:",max_DNA)
print("其X值为:",decode(max_DNA))

理解了算法的本质后,再看代码自然不会有太大的难度,这里不过多解释了

5.思考

在前面的实现中,我侧重了染色体的交叉,得到了一个不错的结果,如果我们修改全局变量

pop_size = 50  # 种群数量
PC=0.01 # 交叉概率
PM=0.99 #变异概率
X_max=5    #最大值
X_min=0     #最小值
DNA_SIZE=10  #DNA长度与保留位数有关,2**10 当前保留3位小数点
N_GENERATIONS=1000

即完全依靠变异来进化,也是可以获得很好的结果的呢,这充分说明了遗传算法的核心便是随机!

二.使用第三方库

pip install scikit-opt

这是个功能很强大效果很好的进化算法的第三方库官方文档,大家自行参考官方源码
这里给出最简单的实现

import numpy as np
def schaffer(p):
    '''
    This function has plenty of local minimum, with strong shocks
    global minimum at (0,0) with value 0
    '''
    x= p[0]
    
    return 5*np.sin(np.log(x))
   
from sko.GA import GA
ga = GA(func=schaffer, n_dim=1, size_pop=100, max_iter=800, 
lb=0, ub=10, precision=1e-7)
best_x, best_y = ga.run()
print('best_x:', best_x, '\n', 'best_y:', best_y)
import pandas as pd
import matplotlib.pyplot as plt
x = np.arange(0,10,0.01)
y = 5*np.sin(np.log(x))
plt.plot(x,y)
plt.show()

在这里插入图片描述
在这里插入图片描述
短短20行代码便能实现~

三.总结

进化计算的算法熟练后可以运用到设置深度学习网络的参数,进化计算还有很大的发展空间。

标签:10,DNA,Python,pop,print,通俗易懂,np,遗传算法,size
来源: https://blog.csdn.net/weixin_45906434/article/details/115486146

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有