zoukankan      html  css  js  c++  java
  • [学习笔记] 遗传算法入门

    遗传算法入门

    算法原理

    原理很简单,就是模仿自然界适者生存的原理,不断的淘汰不符合条件的个体,通过杂交产生新个体,变异得到新个体等。

    算法的代码其实通过例子超级好理解。

    例子

    我也是通过网络上的博客初步了解遗传算法的,所以当我看懂了之后,就直接自己写来实现了。

    这个例子是这样一个题目:

    求解

    [xsin(10pi x)+2 ]

    在[-1,2]内的最大值。

    写起来别提有多简单!

    首先第一步:

    初始化种群,我的代码中种群我随机在-1到2之间取了100个数。

    第二步:

    就是去选择个体,这里大家都用的轮赌法,而且是重复采样的那种,我试过不重复采样,因为种群数量比较少,所以到后面其实会有bug,导致没办法迭代。

    第三步:

    杂交得到后代,这里我本来是写的随机杂交,并且杂交一定代数,后来发现这样写后果太严重了,不仅适应度不是朝着想要的方向变化,而且种群数量几乎呈指数级别增长。所以想了想,我们既然要适应度朝着提高的方向发展,那么我们就可以把适应度最高的几个拿来杂交,而且我的杂交方法和别的资料也不太一样,我是按照生物里面学的每个位置取父方或母方一位数据来杂交的。最终跑出来了结果。

    还有就是encode和decode也和网上写的不太一样,我没去单独考虑编码限制,而是在杂交生成新物种的时候对新物种的值进行判定,满足在-1到2之间则保存,否则丢掉重新杂交。

    可视化

    代码

    '''
    @Descripttion: This is Aoru Xue's demo, which is only for reference.
    @version: 
    @Author: Aoru Xue
    @Date: 2019-11-26 15:24:03
    @LastEditors: Aoru Xue
    @LastEditTime: 2019-11-26 20:04:21
    '''
    import numpy as np
    import random
    import math
    from matplotlib import pyplot as plt
    # 遗传算法demo
    
    """[遗传算法流程]
    
    1. 初始化
    2. 选择 ->> 
    3. 交叉->> 生成子代
    4. 变异
    """
    
    """[问题]
    解决:f(x) = xsin(10πx) + 2 在[-1,2]内的最大值,精度取0.01。
    """
    class GA():
        def __init__(self,ini_num = 100,mutation_ratio = 0.01):
            self.x = np.array([random.randint(0,300)/100-1. for _ in range(ini_num)])
            self.mutation_ratio = mutation_ratio
        
        def choose(self):
            # 选择之后的新个体
            new_x = []
            # 首先求出转盘概率
            probablity = []
            # 站在上帝视角去评判x的值的适应度如何
            fitness = self.get_fitness()
            # 转化为0-1之间的值
            fitness = fitness / (np.sum(fitness) )
            
            # 转化为累计值
            for idx,fit in enumerate(fitness):
                probablity.append(np.sum(fitness[:idx+1,]))
                  
            # 适者生存的选择过程,选择的概率为其fitness的概率
            for _ in range(int(len(self.x))): # 我这里写的是重复采样
                p = random.random()
                for i in range(len(self.x)):
                    if i ==0:
                        if p < probablity[0]:
                            #if self.x[0] in new_x:
                            #   break
                            new_x.append(self.x[0])
                            break
                       
                    elif p >= probablity[i-1] and p < probablity[i]: # 不是第一个个体的化就满足这个条件
                        #if self.x[i] in new_x:
                        #    break
                        new_x.append(self.x[i])
                        break
                        
            self.x = np.array(new_x)
            
         
        def get_fitness(self):
            return self.x * np.sin(10 * self.x * np.pi) + 2
        @staticmethod
        def encode(x):
            x = math.floor((x+1)*100+0.5)
            return bin(x)
        @staticmethod
        def decode(x):
            return eval(x)/100 -1
        def get_sons(self,idx1,idx2):
    
            father = list(self.encode(self.x[idx1]))[3:]
            mother = list(self.encode(self.x[idx2]))[3:]
            
            # 长度规整
            if len(mother) > len(father):
                for _ in range(len(mother) - len(father)):
                    father.insert(0,'0')
            elif len(father) > len(mother):
                for _ in range(len(father) - len(mother)):
                    mother.insert(0,'0')
            sons = []
            while True:
                son = []
                for i in range(len(father)):
                    
                    p = random.random()
                    if p < self.mutation_ratio:
                        son.append(random.choice(['0','1']))
                    else:
                        son.append(random.choice([mother[i],father[i]]))
                s = self.decode("0b" + "".join(son))
                if len(son) and s>=-1 and s <= 2:
                    sons.append(s)
                    break
            return sons
        def update(self):
            fitness = self.get_fitness()
    
            max_2 = np.argsort(fitness)[-2:]
            num = len(self.x)
            #for _ in range(int(len(self.x) * 0.5)):
            i = max_2[0]
            j = max_2[1]
            
            sons = self.get_sons(i,j)
            self.x = np.concatenate([self.x,sons])
        def avg_fitness(self):
            return np.mean(self.get_fitness())
    if __name__ == "__main__":
        ga = GA()
        iterations = 500
        xs = []
        ys = []
        for _ in range(iterations):
            # 适者生存
            ga.choose()
            # 繁衍下一代
            ga.update()
            xs.append(_)
            ys.append(ga.avg_fitness())
        plt.plot(xs,ys)
        plt.show()
            
            
    
  • 相关阅读:
    day38_css
    day39_css_浮动_display
    day36_html
    线段树模板2 洛谷p3373
    hdu1257 最少拦截系统
    树的重心(DFS)
    树的直径(BFS)
    面向对象复习
    面向对象练习题
    面向对象的交互
  • 原文地址:https://www.cnblogs.com/aoru45/p/11938076.html
Copyright © 2011-2022 走看看