[学习笔记] 遗传算法入门

遗传算法入门

算法原理

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

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

例子

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

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

求解

\[xsin(10\pi 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()
        
        
posted @ 2019-11-26 20:06  aoru45  阅读(373)  评论(0编辑  收藏  举报