Python遗传算法代码实例讲解

目录

实例:

代码讲解:

难度较大的代码:

全部代码:


 

实例:

求解函数的最大值y=xsin(10x)+xsin(2x),自变量取值:0--5,用Python画出的图像如下

(注:此代码好像有一些感觉不对的地方,首先:没有保留那些适应度低的个体

pop = select(pop, fitness)  '''这一行代码,压根就是把适应度低的个体给干没了。'''

 
    for parent in pop:
        child = crossover(parent, pop_copy)
        child = mutate(child)
        parent[:] = child  '''这个for循环,没有对交叉变异后的个体进行适应度筛选啊'''

代码讲解:

'''
1初始化种群:返回一个元素为 二进制的矩阵,每一行代表一个个体,每个个体由二进制数字表示x值
            2:代表二进制,POP_SIZE:矩阵行数,DNA_SIZE:矩阵列数。

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

'''
2,计算适应度并且原则优良种群,(有放回的抽取),循环很多代
   pop:代表二进制种群,translateDNA(pop):将其转化十进制,在计算适应度,在select选择优良种群

'''
F_values = F(translateDNA(pop))  #求函数值
 
fitness = get_fitness(F_values)  #得到使用度,这里例子函数值就是适应度

pop = select(pop, fitness)
#此时的pop是经过筛选的好的总群,也是一个二进制表现方式,里面有很多一样的个体,因为使用放回抓取
'''
3,经过一波筛选后,接下来该交叉变异了,为了得到更好的x值,因为初始化的x值使得个体分布不均匀

'''
    pop_copy = pop.copy() #复制一份优良种群,用于交叉变异
    for parent in pop:
        child = crossover(parent, pop_copy)  #交叉

        child = mutate(child)  #交叉后的种群在进行变异
        parent[:] = child  
        #将child赋值给parent

难度较大的代码:

crossover()   mutate()   parent[:] = child 
'''
crossover
交叉:parent:表示每一个二进制个体,pop:优良的种群,如100个个体
返回交叉后的一个个体,也是二进制表示方式
这个函数的功能就是
parent[cross_points] = pop[i_, cross_points]

'''

def crossover(parent, pop):     # mating process (genes crossover)
    if np.random.rand() < CROSS_RATE:
        i_ = np.random.randint(0, POP_SIZE, size=1) # select another individual from pop
        # 从0-POP_SIZE,随机选择一个数字,


        cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)  
        #array([ True, False, False,  True,  True, False, False,  True,  True,
        #True])
        #随机生成一个10个元素的数组,元素为0和1,在转化成bool型

                                   # choose crossover points
        parent[cross_points] = pop[i_, cross_points]
        #这个语句有难度:
        '''
        将parent为True的元素,将被改变,False的元素不变.将被改变的元素改变成   pop矩阵第 i_                       行里面被选择为true的元素,
        注意,parent的是cross_points,  pop 也是cross_points,必须保持一致,才可以实现交叉生成一个新的个体,这个个体是父母基因的交叉结果
'''
                                   
                                     # mating and produce one child
    return parent     #将新个体返回出去

'''
变异:将交叉后得到的个体,(这个个体不一定就是好的个体,很可能是不好的适应度不高的个体)
进行变异,
核心代码:
child[point] = 1 if child[point] == 0 else 0

'''

def mutate(child):
    for point in range(DNA_SIZE):
        if np.random.rand() < MUTATION_RATE:
            child[point] = 1 if child[point] == 0 else 0
            '''
                point是把child这个个体基因遍历一遍,按照几率进行将0变成1,
注意:并不是将所有的0变成1,而是有几率的 if np.random.rand() < MUTATION_RATE:

'''
    return child

全部代码:

"""
Visualize Genetic Algorithm to find a maximum point in a function.
Visit my tutorial website for more: https://morvanzhou.github.io/tutorials/
"""
import numpy as np
import matplotlib.pyplot as plt

DNA_SIZE = 10            # DNA length
POP_SIZE = 100           # population size
CROSS_RATE = 0.8         # mating probability (DNA crossover)
MUTATION_RATE = 0.003    # mutation probability
N_GENERATIONS = 200
X_BOUND = [0, 5]         # x upper and lower bounds


def F(x): return np.sin(10*x)*x + np.cos(2*x)*x     # to find the maximum of this function


# find non-zero fitness for selection
def get_fitness(pred): return pred + 1e-3 - np.min(pred)


# convert binary DNA to decimal and normalize it to a range(0, 5)
def translateDNA(pop): return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]


def select(pop, fitness):    # nature selection wrt pop's fitness
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
                           p=fitness/fitness.sum())
    return pop[idx]


def crossover(parent, pop):     # mating process (genes crossover)
    if np.random.rand() < CROSS_RATE:
        i_ = np.random.randint(0, POP_SIZE, size=1)                             # select another individual from pop
        cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)   # choose crossover points
        parent[cross_points] = pop[i_, cross_points]                            # mating and produce one child
    return parent


def mutate(child):
    for point in range(DNA_SIZE):
        if np.random.rand() < MUTATION_RATE:
            child[point] = 1 if child[point] == 0 else 0
    return child


pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE))   # initialize the pop DNA

plt.ion()       # something about plotting
x = np.linspace(*X_BOUND, 200)
plt.plot(x, F(x))

for _ in range(N_GENERATIONS):
    F_values = F(translateDNA(pop))    # compute function value by extracting DNA

    # something about plotting
    if 'sca' in globals(): sca.remove()
    sca = plt.scatter(translateDNA(pop), F_values, s=200, lw=0, c='red', alpha=0.5); plt.pause(0.05)

    # GA part (evolution)
    fitness = get_fitness(F_values)
    print("Most fitted DNA: ", pop[np.argmax(fitness), :])
    pop = select(pop, fitness)
    pop_copy = pop.copy()
    for parent in pop:
        child = crossover(parent, pop_copy)
        child = mutate(child)
        parent[:] = child       # parent is replaced by its child

plt.ioff(); plt.show()

猜你喜欢

转载自blog.csdn.net/weixin_42053726/article/details/82722758