梁山伯与翠花 2022-02-05 16:13 采纳率: 50%
浏览 80

初次学习遗传算法,代码跑出来,函数值不收敛,请教一下哪里写错了 因该是cross_mutation函数有误,但是我看不出来


import numpy as np
import random as rd
import seaborn as sns
import matplotlib.pyplot as plt


def F(x, y):#目标函数
    return 3*(1-x)**2*np.exp(-(x**2)-(y+1)**2)- 10*(x/5 - x**3 - y**5)*np.exp(-x**2-y**2)- 1/3**np.exp(-(x+1)**2 - y**2)

class GA():
    def __init__(self,lb,ub,fitF):
        self.fitF= fitF#目标函数
        self.lb  = lb#约束下线
        self.ub  = ub#约束上限
        self.size = 2#变量个数
        self.len = 22#基因长度
        self.popsize = 100#种群大小
        self.inti_pop = np.random.randint(0,2,size=(self.popsize,self.len*self.size)).astype('str')#初始化种群2^10=1024   2^22=4194304
        self.x = np.zeros((self.popsize*2,self.size))#记录每个基因产生的X
        self.mutation_P = 0.1#变异概率
        self.cross_P = 0.3#交叉的概率
        self.bestX = None#最优解
        self.bestY = None#最优值
        self.Y_container = []#记录每次的最优值

    def Decode(self,inti_pop):#二进制解码并计算轮盘赌所需的概率值
        for i in range(self.popsize*2):#遍历每一个基因,然后计算对应的X值
            single = inti_pop[i].reshape(self.size,self.len)#每个个体拆分成x1,x2,x3,...,xn
            for j in range(self.size):
                bin_x = ''.join(single[j])
                self.x[i][j] = self.lb[j] + int(bin_x,2)/(2**self.len-1)*(self.ub[j]-self.lb[j])
        x1 =self.x[:,0];x2=self.x[:,1]#因为有两个参数:x,y
        values = self.fitF(x1,x2)
        fitness = values-values.min()+1e-1
        return fitness/fitness.sum()

    def mutation(self,child):#每一个child执行变异
        ind  = rd.randint(0,self.len*2-1)#随机选取变异点    randint包含末位树 是个坑
        child[ind] = str(int(child[ind])^1)#执行变异    python 特殊规则   1^1 = 0 ; 0^1 =1
        return child
##产新种群的策略:先交差变异产生同等popsize的种群,然后从这个种群和之前的种群中轮盘度选择最有的种群 作为新种群,循环操作即可
    def cross_mutation(self):#交叉遗传  一部分不变 ,一部分子代变异   {这里包含了交叉变异遗传}
        chiledren = []
        for i in range(self.popsize):
            child = self.inti_pop[i]#可以看做 father 或者 child
            if rd.random()<self.cross_P:#交叉操作
                ind_mom = self.inti_pop[rd.randint(0,self.popsize-1)]#随机挑选一个作为mom   randint包含末位树 是个坑
                cross_d = rd.randint(0,self.len*self.size)#随机选取交叉点
                child[:cross_d] =  ind_mom[:cross_d]#完成交叉
            if rd.random() < self.mutation_P:  # 按照变异概率进行点位变异
                child = self.mutation(child=child)#执行变异
            chiledren.append(child)
        #交叉变异执行完毕后,新种群与旧种群,结合在一起,等待使用轮盘度挑选下一代种群
        inti_pop = np.vstack((np.array(chiledren),self.inti_pop))
        #执行完毕,轮盘度产生新的pop
        ind = np.random.choice(np.arange(self.popsize*2), size=int(self.popsize), replace=True, p=self.Decode(inti_pop))
        self.inti_pop = inti_pop[ind]

    def run(self,iteration):#循环迭代
        for _ in range(iteration):
            self.cross_mutation()

            a = self.fitF(self.x[:,0],self.x[:,1]).tolist()#计算最后一次的结果值
            ind = a.index(max(a))
            self.bestY = a[ind]
            self.bestX = self.x[ind]
            self.Y_container.append(self.bestY)

pop = GA(lb=[1,3],ub=[-3,3],fitF=F)
pop.run(1000)

plt.plot(pop.Y_container)
plt.show()
print(pop.bestY)

  • 写回答

1条回答 默认 最新

  • youcans_ 人工智能领域优质创作者 2022-02-06 09:18
    关注

    (1)对于 变异 操作的理解不对。一般地,变异是在现有父代的基础上变异。程序中,变异在 交叉后按一定概率进行变异,变异的性能将显著恶化;而且变异概率 0.1 太高了。
    (2)似乎没有 最优值保留机制,虽然理论上并非必要,但实际上最优值保留还是很重要的。
    (3)最关键的,交叉操作是择优交叉而不是随机交叉,例如按照轮盘赌机制选择交叉父本,体验优胜劣汰,程序中好像不是这样做的。

    评论

报告相同问题?

问题事件

  • 创建了问题 2月5日