遗传算法相关知识

目录

准备工作

初始化种群 

解码、归一化以及相关知识(逐步解释)

总代码


 定义适应度函数


  • 准备工作

import numpy as np

DNA_SIZE = 10            # DNA length
POP_SIZE = 100           # population size,种群中个体数目
CROSS_RATE = 0.8         # mating probability (DNA crossover),0.8的概率进行交叉配对
MUTATION_RATE = 0.003    # mutation probability,变异强度
N_GENERATIONS = 200      #迭代次数
X_BOUND = [0, 5]         # x upper and lower bounds,指定x的取值范围
  • 初始化种群 

pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE))   # initialize the pop DNA
#生成一个元素大小在0-2之间但不包括2,1000行10列的矩阵
np.random.randint——————生成矩阵。举个例子:
a = np.random.randint(10, size = (5, 5))
b = np.random.randint(10, size = (5, 3))
print(a)
print(b)

输出结果:
[[5 8 6 3 7]
 [4 9 2 7 8]
 [6 2 6 6 4]
 [0 8 0 6 6]
 [5 1 4 6 2]]
[[2 4 7]
 [9 5 2]
 [9 5 4]
 [3 4 2]
 [1 5 9]]
  • 解码、归一化以及相关知识(逐步解释)

def translateDNA(pop):
    return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]
#np.arange(DNA_SIZE)                从0开始,步长为1,输出[0 1 2 3 4 5 6 7 8 9],不包括10
#np.arange(DNA_SIZE)[::-1]          把[0 1 2 3 4 5 6 7 8 9]倒过来,得到[9 ... 0]
#2 ** np.arange(DNA_SIZE)[::-1]     [512 256 128  64  32  16   8   4   2   1]
#pop.dot(2 ** np.arange(DNA_SIZE)[::-1])
#                                   pop与[512 256 128  64  32  16   8   4   2   1]点乘,即:计算各个2进制编码的DNA转变为10进制表达
#X_BOUND[1]                         5
#float(2**DNA_SIZE-1) * X_BOUND[1]  将上边转化得到DNA10进制表达式,归一化到0-5

a.dot(b) 与 np.dot(a,b)效果相同,都是实现点乘的功能。

np.arange————生成一个数组。举个例子:

x=np.arange(0,np.pi/2,0.1)
y=np.sin(x)
print(x)
print(y)

总代码

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),0.8的概率进行交叉配对
MUTATION_RATE = 0.003    # mutation probability,变异强度
N_GENERATIONS = 200      #迭代次数
X_BOUND = [0, 5]         # x upper and lower bounds,指定x的取值范围

pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE))   # initialize the pop DNA
#生成一个元素大小在0-2之间但不包括2,1000行10列的矩阵

def translateDNA(pop):
    return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]
#np.arange(DNA_SIZE)                从0开始,步长为1,输出[0 1 2 3 4 5 6 7 8 9],不包括10
#np.arange(DNA_SIZE)[::-1]          把[0 1 2 3 4 5 6 7 8 9]倒过来,得到[9 ... 0]
#2 ** np.arange(DNA_SIZE)[::-1]     [512 256 128  64  32  16   8   4   2   1]
#pop.dot(2 ** np.arange(DNA_SIZE)[::-1])
#                                   pop与[512 256 128  64  32  16   8   4   2   1]点乘,即:计算各个2进制编码的DNA转变为10进制表达
#X_BOUND[1]                         5
#/float(2**DNA_SIZE-1) * X_BOUND[1]  /(2^10-1) * 5,将10进制的DNA归一化到0-5(得到表现型)

def F(x):
    return np.sin(10*x)*x + np.cos(2*x)*x     # 需要求解的函数y=sin(10*x)*x + cos(2*x)*x
# 也相当于把之前的表现型转化为适应度了,然后再通过get_fitness()函数,将适应度转化的都大于0

def get_fitness(pred):
    return pred + 1e-3 - np.min(pred)
# 这个是真正的适应度函数!!
# 调用函数的时候pred为F!!
# 经过这一波操作,get_fitness函数输出的值就非负了,后边用pred/max(pred)算每个pred的被选概率
# xe-y            表示有y个0构成的0.000……000x
# 1e-3            即0.001,加一个极小量,防止pred等于0
# pred            可能是随便打的,abcd都行,到时候调用这个函数的时候再往里填数
# np.min(pred)    取一个pred的最小值

def select(pop, fitness):    # 选择函数,根据适应度确定每个DNA被选中的概率
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,p=fitness/fitness.sum())
# np.arange(POP_SIZE)  生成一个0-99的数列,arrange生成的是数组,randint生成的是矩阵
# size=100             从前边的数列里取100个数,每个数被选到的概率为p,之前对pred的非负处理在这里就显得很关键了
# replace              表示抽样后是否放回,这里为True表示有放回,那么一个数就有可能被选中多次
# p                    就是选它的比例,按比例来选择适应度高的,也会保留一些适应度低的,因为也可能后面产生更好的变异
    return pop[idx]    #把生成的idx序列返回给pop

#繁衍,交叉父母的基因
def crossover(parent, pop):     # mating process (genes crossover)
    if np.random.rand() < CROSS_RATE: #np.random.rand()  随机生成一个0-1之间的数
        i_ = np.random.randint(0, POP_SIZE, size=1)                           #给i_随机赋一个0-100间的数
        cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)
        # np.random.randint(0, 2, size=DNA_SIZE)  得到一个长为10的随机数列,例如:[0 0 1 0 0 1 1 0 0 1]
        # np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)   将得到的随机数列进行布尔化(非0用ture表示,0用false表示),得到[False False  True False False  True  True False False  True]
        parent[cross_points] = pop[i_, cross_points]
    #生成布尔数组可以组合应用多个布尔条件,使用&(和),|(或)之类的布尔算数运算符,python的关键字and和or在布尔型数组中无效
    #parent[cross_points]     即在parent列表中取出cross_points为True地方的值!!!!parent列表在哪里生成了??
    #【母亲是pop的i_索引行DNA,选出母亲对应在cross_points为TRUE的地方的值】赋给【父亲DNA对应在cross_points选出为TRUE的地方的值】。
    return parent

#繁衍,有变异的基因会出现
#将某些 DNA 中的 0 变成 1, 1 变成 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
    return child

plt.ion()       # 开启图像交互模式
x = np.linspace(*X_BOUND, 200)
# linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
# X_BOUND = [0, 5],要产生200个样本点
# 把[0,5]分成200份,输出一个200个元素的数组。
plt.plot(x, F(x))
# plt.plot()是直接出图像,不需要plt.show()。
# plt.plot(x, y) = 输出一个由(x1,y1)...(x200,y200)组成的图像,即横坐标为x,纵坐标为y。


#接下来的就是遗传算法的主函数
for _ in range(N_GENERATIONS): #迭代次数200次
    F_values = F(translateDNA(pop)) #将归一化到0-5的DNA传入到F函数

    # 画图
    if 'sca' in globals(): sca.remove()  #remove():移除列表中某个值s
    sca = plt.scatter(translateDNA(pop), F_values, s=200, lw=0, c='red', alpha=0.5)
    #plt.scatter()  是一个画图函数,调用方式:plt.scatter(x轴,y轴,s=散点大小,lw=?,c=颜色,alpha: 散点的透明度)。即画一个F_values的函数图像
    plt.pause(0.05) #plt.pause()  暂停模式,这里表示输出的每张图显示0.5秒
    # GA part (evolution)
    fitness = get_fitness(F_values) #计算适应度
    print("Most fitted DNA: ", pop[np.argmax(fitness), :])
    pop = select(pop, fitness) #这里根据fitness,选出一个新的population
    pop_copy = pop.copy()# 备个份
    for parent in pop: #这里parent为遍历pop,一次为其中一行,而这里的pop是从原pop中按适应度概率有放回的选出了POP_SIZE行
        child = crossover(parent, pop_copy)#繁衍
        child = mutate(child) #进行变异
        parent[:] = child       # 宝宝变大人,[:]  即让 child集合 = parent集合

plt.ioff()  #关闭图像交互模式
plt.show()  #在plt.show()之前一定不要忘了加plt.ioff(),如果不加,界面会一闪而过,并不会停留。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值