基因表达式编程(GEP)自学 第【5】天 Python 实现(代码)

目录

  • 1. 基因表达式编程 GEP Python 代码实现【★★★★★】
  • 2. 评估函数(绝对误差)
  • 3. 适应度计算、评估操作
    • 3.1. Environment 类:
    • 3.2. Chromosome 类
    • 3.3. Gene 类
  • 4. 输出测试
  • 5. 代码实现整合:

1. 基因表达式编程 GEP Python 代码实现【★★★★★】

今天将用python实现GEP算法中,适应度计算、评估操作
【PS:注意结合前边内容,今天的内容比较复杂,特别是如何将基因转换为逆波兰式,如何将样本数据代入运算都有一定难度,本次的内容就不涉及选择,复制,变异等的内容】

基因表达式编程(GEP)自学 第【1】天 Python 实现
基因表达式编程(GEP)自学 第【2】天 Python 实现
基因表达式编程(GEP)自学 第【3】天 Python 实现
基因表达式编程(GEP)自学 第【4】天 Python 实现(代码)

2. 评估函数(绝对误差)

基因表达式编程(GEP)自学 第【5】天 Python 实现(代码)_第1张图片

def evalFunction(C_value, T_value, maxFitness_flag=False,M=100,DataCount=10,):
    '''
    :param C_value:         表示染色体,样本输出值
    :param T_value:         表示染色体,样本真实值
    :param maxFitness_flag: 用于是否为最大适应度值
    :param M:               M 常数
    :param DataCount:       数据的个数
    :return:
    '''

    if maxFitness_flag:
        return M*DataCount
    sum_fitness = 0
    for i in range(len(C_value)):
        if not math.isfinite(C_value[i][0]):
            sum_fitness += 0
            pass
        result = M - abs(C_value[i][0] - T_value[i][0])
        if result < 0: result = 0
        sum_fitness = result + sum_fitness
    fitness = sum_fitness
    return fitness

【PS:其中,这里计算出来的绝对误差,即使适应度差的,但也可能遗传其基因给后代,只是概率极低。这里将其设置为1,如果,你其他想法,也可付出实践。】
#即使适应度差的,但也可能遗传其基因给后代,只是概率极低

3. 适应度计算、评估操作

3.1. Environment 类:

其中定义函数 run 用于调用执行GEP主要操作

def run(self, inputsOutputs, evalFunction,generationCount=200,M=100,DataCount=10):
        '''
        :param inputsOutputs:   保存输入与输出集合
        :param evalFunction:    适应度函数
        :param generationCount: 执行代数
        :return:
        generation:             表示第几代种群
        i_chromosome            用于保存当代种群第i条染色体
        C_valueList             表示染色体,样本输出值
        fitness                 保存当前染色体的适应度
        maxFitness_flag=True    为True,返回的maxFitness:M*DataCount
        '''
        generation = 0
        while True:
            generation += 1
            for i in range(len(self.population)):
                C_valueList = []
                i_chromosome = self.population[i]
                #计算每个染色体对应的 C_value
                for inputs in inputsOutputs[0]:
                    C_valueList.append(i_chromosome.eval(inputs))
                #evalFunction 进行适应度评估
                fitness = evalFunction(C_valueList, inputsOutputs[1], M=M, DataCount=DataCount,)
                print("[",i,"] ","   Fitness=",fitness)
                if fitness == evalFunction([], [], maxFitness_flag=True,M=M,DataCount=DataCount,):
                    print("*" * 46, "  完美解  ", "*" * 46)
                    i_chromosome.printChromosome()
                    return i_chromosome
            # 繁衍代数大于generationCount退出
            if generation >= generationCount:
                return 0
                

3.2. Chromosome 类

def eval(self, inputs):
        '''
        :param inputs:      样本输入值
        :return:            returnValues
        '''
        returnValues = []
        #基因赋值运算、结果保存在returnValues
        for gene in self.genes:
            #将终结值赋予对应的数值,如 a:1 ,b:2
            evalInputs = {terminal: value for (terminal, value) in list(zip(gene.genome.terminals, inputs))}
            returnValues.append(gene.eval(evalInputs))

        #连接函数运算、最终结果保存在returnValues
        homeoticReturnValues = []
        if len(self.homeotics) > 0:
            outputs = {index: output for (index, output) in list(zip(range(0, len(self.genes)), returnValues))}
            for homeotic in self.homeotics:
                homeoticReturnValues.append(homeotic.eval(outputs))
            returnValues = homeoticReturnValues
        return returnValues

3.3. Gene 类

def eval(self, inputs):
        '''
        对精英进行赋值运算评估
        :param inputs:      参数输入值
        :return:
        '''
        elementLayers = self.orderStack()
        evalStack = self.tranformRPN(elementLayers)
        return self.evalStack(evalStack, inputs)

    #例子【'+':2,'-':2,'*':2,'a':0,'a':0,'a':0,'a':0】
    #首先,取出一个符号'+',即arity初始为:arity=1
    #然后,保存该符号的arity数值。由'+':2得arity=2,同时将取出得'+'在elementLayers保存
    #循环,此时arity=2,取出2个符号即'-','*'。
    #根据'-','*'得到max_arity数值,max_arity=4
    #以此类推直到max_arity=0。
    #这其实就模拟树,一层一层得取出。
    #【【'+':2】,【'-':2,'*':2】,【'a':0,'a':0,'a':0,'a':0】】
    def orderStack(self):
        elementLayers = []
        gene = self.head + self.tail
        arity = 1
        while arity > 0:
            elementList = []
            for i in range(arity):
                elementList.append(gene.pop(0))
            arity = 0
            for i_element in elementList:
                arity += self.genome.symbols()[i_element]
            elementLayers.append(elementList)
        # print(elementLayers)
        return elementLayers

    #用递归实现逆波兰式的装转变
    def tranformRPN(self, elementLayers, layerIndex = 0):
        '''
        :param elementLayers:    orderStack输出的层次结构
        :param layerIndex:       几层用于递归调用
        :return:
        '''
        stack = []
        for i in range(self.genome.symbols()[elementLayers[layerIndex][0]]):
            stack =  stack + self.tranformRPN(elementLayers, layerIndex + 1)
        stack.append(elementLayers[layerIndex].pop(0))
        return stack

    #inputs=['a':1,'b':3]已赋值,取值运算
    def evalStack(self, stack, inputs):
        '''
        :param stack:       为逆波兰式
        :param inputs:      参数输入值
        :return:returnStack     保存最后的运算结果
        '''
        returnStack = []
        for symbol in stack:
            if symbol in inputs.keys():
                returnStack.append(inputs[symbol])
            else:
                self.genome.functions[symbol][0](returnStack)
        return returnStack[0]

4. 输出测试

【PS:随机种子设置为10】

random.seed(10)
if __name__=='__main__':

    #---------------操作数设置 Begin--------------#
    genome = Genome()
    genome.functions.update(Genome.linker_set)
    genome.terminals = ['a','b']
    genome.symbols()
    my_link_genome=Genome()
    my_link_genome.functions.update(Genome.linker_set)
    #----------------操作数设置 end---------------#


    #---------------种群初始化 Begin--------------#
    environment = Environment()
    environment.init(populationSize=20,numGenes=3,numHomeotics=1,headLength=4,homeoticHeadLength=5,genome=genome,link_genome=my_link_genome)
    environment.setRates(homeoticRate=0.5, mutationRate=0.044,ISTranspositionRate=0.1,
                         RISTranspositionRate=0.1, geneTranspositionRate=0.1,onePointRecombinationRate=0.3,
                         twoPointRecombinationRate=0.3, geneRecombinationRate=0.1)
    ##----------输出测试----------##
    #----------------种群初始化 end---------------#

    #---------------Run Begin--------------#
    M=100
    DataCount=10
    generationCount=0
    inputsOutputs=GenerateData(DataCount=DataCount)
    result=environment.run(inputsOutputs,evalFunction,M=M,generationCount=generationCount)
    #----------------Run end---------------#

输出结果:

0
0 :['-', '+', '/', '/', 'a', 'a', 'b', 'b', 'b']:['-', 'a', '/', '*', 'a', 'a', 'b', 'a', 'b']:['*', '*', '/', '/', 'b', 'b', 'b', 'a', 'b']:['-', '/', 2, 2, '-', 1, 2, 1, 0, 2, 0]:
1 :['/', '-', '*', 'a', 'b', 'a', 'b', 'b', 'b']:['+', 'b', 'a', '*', 'a', 'a', 'b', 'a', 'a']:['-', '*', 'a', 'b', 'a', 'a', 'a', 'b', 'b']:['-', 2, 2, '+', '/', 0, 0, 1, 1, 1, 1]:
2 :['-', '*', '-', 'a', 'a', 'a', 'b', 'b', 'b']:['+', 'b', '-', '-', 'b', 'b', 'b', 'b', 'a']:['/', 'b', '+', '*', 'b', 'a', 'a', 'b', 'b']:['/', '-', '/', 2, '/', 2, 0, 2, 2, 1, 2]:
3 :['*', '/', '+', '-', 'b', 'b', 'b', 'a', 'b']:['+', '/', '/', 'b', 'a', 'b', 'a', 'b', 'a']:['/', 'a', '+', '+', 'b', 'a', 'a', 'a', 'b']:['/', '/', 2, '/', 2, 2, 1, 1, 2, 1, 2]:
4 :['/', '*', 'b', 'a', 'a', 'a', 'b', 'a', 'a']:['*', '+', '*', '/', 'a', 'b', 'a', 'a', 'a']:['+', 'b', '/', '-', 'b', 'b', 'a', 'b', 'a']:['/', '-', '/', '-', '+', 2, 1, 1, 2, 2, 2]:
5 :['-', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a']:['*', 'a', '/', '/', 'a', 'a', 'b', 'a', 'a']:['*', '*', '/', '/', 'a', 'b', 'b', 'b', 'b']:['/', '/', 1, '*', '*', 2, 1, 1, 1, 1, 2]:
6 :['*', 'b', 'a', 'b', 'b', 'b', 'a', 'b', 'a']:['-', 'a', '*', 'b', 'b', 'a', 'b', 'b', 'b']:['/', '-', '*', '+', 'a', 'a', 'a', 'b', 'a']:['*', 2, 0, '+', '/', 0, 1, 2, 0, 2, 2]:
7 :['-', 'b', 'b', 'a', 'a', 'a', 'b', 'b', 'b']:['/', '+', 'a', '*', 'a', 'a', 'b', 'a', 'b']:['*', '*', '+', '-', 'b', 'b', 'b', 'b', 'a']:['/', '/', 2, 2, '*', 2, 2, 1, 1, 0, 0]:
8 :['+', '-', '+', '-', 'a', 'b', 'b', 'b', 'a']:['+', '*', '-', '+', 'a', 'a', 'b', 'a', 'b']:['/', 'a', '/', '+', 'b', 'a', 'b', 'a', 'a']:['-', 2, '/', 2, '*', 0, 0, 0, 2, 2, 1]:
9 :['/', 'b', 'b', '/', 'a', 'b', 'a', 'a', 'a']:['*', 'b', '*', 'b', 'b', 'a', 'b', 'b', 'a']:['/', 'b', '-', 'b', 'b', 'a', 'a', 'b', 'a']:['/', '-', '*', '*', '+', 0, 2, 2, 2, 0, 0]:
10 :['/', '+', 'b', '/', 'b', 'a', 'a', 'b', 'b']:['/', '+', '-', '-', 'b', 'a', 'a', 'a', 'b']:['/', '+', '-', '+', 'a', 'a', 'a', 'a', 'a']:['-', '+', 1, '/', 1, 2, 0, 2, 1, 0, 2]:
11 :['/', 'b', '/', 'a', 'b', 'b', 'b', 'a', 'a']:['-', '/', '/', 'b', 'b', 'a', 'a', 'b', 'b']:['+', '/', '+', '-', 'b', 'a', 'b', 'a', 'a']:['-', 1, 0, 2, '*', 0, 2, 1, 2, 2, 1]:
12 :['*', '+', 'b', '+', 'a', 'a', 'a', 'a', 'a']:['/', '/', '-', '+', 'b', 'a', 'b', 'b', 'b']:['/', 'b', '-', '+', 'b', 'a', 'b', 'a', 'b']:['*', '+', '/', 0, '/', 0, 1, 2, 1, 0, 1]:
13 :['/', 'a', 'a', '/', 'a', 'b', 'b', 'a', 'a']:['+', 'b', '*', 'a', 'a', 'b', 'a', 'a', 'a']:['/', '*', '/', '-', 'b', 'a', 'a', 'a', 'b']:['-', '*', '-', 1, '-', 2, 1, 2, 2, 2, 0]:
14 :['-', '-', '/', '-', 'b', 'b', 'a', 'a', 'a']:['-', 'b', '/', '/', 'a', 'a', 'a', 'b', 'a']:['+', '/', 'b', '-', 'a', 'b', 'b', 'b', 'a']:['+', '/', '*', '*', '+', 1, 2, 1, 2, 2, 2]:
15 :['+', 'b', '*', '/', 'a', 'a', 'b', 'b', 'a']:['/', '-', '+', '/', 'a', 'a', 'b', 'b', 'a']:['/', '/', '/', '-', 'b', 'a', 'b', 'b', 'b']:['/', 0, 1, '-', '/', 0, 0, 1, 1, 2, 1]:
16 :['-', 'b', 'a', '/', 'a', 'b', 'b', 'b', 'a']:['*', '*', 'a', '-', 'a', 'a', 'a', 'a', 'b']:['+', '-', '+', '-', 'b', 'b', 'a', 'a', 'a']:['*', 1, '/', '/', 2, 1, 0, 1, 2, 2, 1]:
17 :['*', '-', '*', '+', 'a', 'a', 'a', 'b', 'b']:['/', 'a', '/', 'b', 'b', 'b', 'b', 'a', 'a']:['-', 'b', 'b', '*', 'b', 'b', 'b', 'b', 'a']:['+', '-', 0, 2, '*', 1, 0, 0, 2, 2, 1]:
18 :['-', '-', '-', '/', 'b', 'b', 'a', 'b', 'a']:['-', '+', '/', '+', 'b', 'b', 'a', 'a', 'a']:['-', '/', '/', 'b', 'a', 'b', 'a', 'b', 'b']:['+', 1, 1, 2, 2, 1, 1, 2, 0, 0, 2]:
19 :['-', 'b', 'a', 'b', 'a', 'a', 'a', 'b', 'a']:['/', 'b', 'a', '*', 'b', 'b', 'a', 'b', 'a']:['+', '/', 'a', '+', 'b', 'a', 'a', 'a', 'a']:['-', '-', '*', 1, 1, 1, 1, 2, 1, 0, 1]:

[ 0 ]     Fitness= 580.3166666666667
[ 1 ]     Fitness= 609
[ 2 ]     Fitness= 237.7
[ 3 ]     Fitness= 624.6833333333333
[ 4 ]     Fitness= 1
[ 5 ]     Fitness= 645.9166666666667
[ 6 ]     Fitness= 645.9166666666667
[ 7 ]     Fitness= 609.0497442713691
[ 8 ]     Fitness= 617.7087123960696
[ 9 ]     Fitness= 625.2666666666667
[ 10 ]     Fitness= 651.25
[ 11 ]     Fitness= 569.0833333333334
[ 12 ]     Fitness= 1
[ 13 ]     Fitness= 724.0
[ 14 ]     Fitness= 692.4166666666666
[ 15 ]     Fitness= 525.3071428571429
[ 16 ]     Fitness= 609.0
[ 17 ]     Fitness= 363.0
[ 18 ]     Fitness= 709.4999999999999
[ 19 ]     Fitness= 577.1319444444443

进程已结束,退出代码0

5. 代码实现整合:

为了方便演示,我将每个类整合到一个py文件上,GEP-5 适应度计算、评估实现

本文作者:九重!
本文链接:https://blog.csdn.net/weixin_43798572/article/details/122834003
关于博主:评论和私信会在第一时间回复。或者直接私信我。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【点赞】【收藏】一下。您的鼓励是博主的最大动力!

你可能感兴趣的:(GEP,python,开发语言,后端)