美文网首页
DEAP1.2.2(六) 一个GP实例——用于函数发现

DEAP1.2.2(六) 一个GP实例——用于函数发现

作者: B_Selmy | 来源:发表于2018-09-07 15:21 被阅读0次

    (六) GP实例——函数发现
    话不多说直接上代码

    import operator, math, random, numpy
    from deap import gp, tools, base, creator, algorithms
    
    toolbox = base.Toolbox()
    pset = gp.PrimitiveSet("MAIN", 1)
    #define protectedDive function which return their division
    def protectedDiv(left, right):
        try:
            return left / right
        except ZeroDivisionError:
            return 1
    #adding other functions
    pset.addPrimitive(operator.add, 2)
    pset.addPrimitive(operator.sub, 2)
    pset.addPrimitive(operator.mul, 2)
    pset.addPrimitive(protectedDiv, 2)
    pset.addPrimitive(operator.neg, 1)
    pset.addPrimitive(math.cos, 1)
    pset.addPrimitive(math.sin, 1)
    #add random constants which is an int type
    pset.addEphemeralConstant("rand1", lambda: random.randint(-1,1))
    #rename augument x
    pset.renameArguments(ARG0='x')
    
    #creating MinFit 
    creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
    #creating individual
    creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMin)
    
    #import toolbox
    toolbox = base.Toolbox()
    #resigter expr individual population and compile
    toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=2)     #0~3
    toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.expr)
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)
    toolbox.register("compile", gp.compile, pset=pset)
    #define evaluating function
    def evalSymbReg(individual, points):
        # Transform the tree expression in a callable function
        func = toolbox.compile(expr=individual)
        # Evaluate the mean squared error between the expression
        # and the real function : x**4 + x**3 + x**2 + x
        sqerrors = ((func(x) - x**4 - x**3 - x**2 - x)**2 for x in points) #define their differential
        #return the average fitness
        return math.fsum(sqerrors) / len(points),
    
    #register genetic operations(evaluate/selection/mutate/crossover/)
    toolbox.register("evaluate", evalSymbReg, points=[x/10. for x in range(-10,10)]) #the range of points in evaluate function
    toolbox.register("select", tools.selTournament, tournsize=3) 
    toolbox.register("mate", gp.cxOnePoint)\
    #this is expr_mut, if we want to use a GEP, we can mutute the expr at first, then do the expression
    toolbox.register("expr_mut", gp.genFull, min_=0, max_=2)
    toolbox.register("mutate", gp.mutUniform, expr=toolbox.expr_mut, pset=pset)
    #decorating the operator including crossover and mutate, restricting the tree's height and length
    toolbox.decorate("mate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17))
    toolbox.decorate("mutate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17))
    
    def main():
        #Parameter setting
        CXPB = 0.1
        MUPB = 0.1
        GEN = 400
        POP_SIZE = 300 
        #initializing population
        pop = toolbox.population(n = POP_SIZE)
        
        '''start evolution'''
        print('Start evolution')
        #evaluating the fitness
        fitnesses = list(map(toolbox.evaluate, pop))
        #assign fitness values
        for ind, fit in zip(pop, fitnesses):
            ind.fitness.values = fit
        print('Evaluated %i individuals' %len(pop))
        '''The genetic operations'''
        for g in range(GEN):
            #select
            offspring = toolbox.select(pop, len(pop))
            offspring = list(map(toolbox.clone, offspring))
            #crossover
            for child1, child2 in zip(offspring[::2], offspring[1::2]):
                if random.random() < CXPB:
                    toolbox.mate(child1, child2)
                    
                    del child1.fitness.values
                    del child2.fitness.values
            
            #mutation
            for mutant in offspring:
                if random.random() < MUPB:
                    toolbox.mutate(mutant)
                    del mutant.fitness.values
            
            #evaluate the invalid individuals
            invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
            fitnesses = list(map(toolbox.evaluate, invalid_ind))
            for ind, fit in zip(invalid_ind, fitnesses):
                ind.fitness.values = fit
            print('Evaluated %i individuals' %len(invalid_ind))
            
            #update the pop
            pop[:] = offspring
            
            #statistics
            stats = tools.Statistics(key=lambda ind: ind.fitness.values)
            record = stats.compile(pop)
            stats.register("avg", numpy.mean, axis=0)
            stats.register("min", numpy.min, axis=0)
            stats.register("max", numpy.max, axis=0)
            record = stats.compile(pop)
            logbook = tools.Logbook()
            logbook.record(gen=g, evals=30, **record)
            logbook.header = "gen", "avg", "min", "max"
            print(logbook)
            
    
    
        print("-- End of (successful) evolution --")
        
        best_ind = tools.selBest(pop, 1)[0]
        print("Best individual is %s, Best results are %s" % (best_ind, best_ind.fitness.values))
        
            
        
    
    if __name__ == "__main__":
        main()
    

    大部分注释都有写,总结一下这个例子:
    首先,要发现的函数是: f(x) = x^4 - x^3 - x^2 - x, fitness func为 min{sum(func(x) - f(x))^2}/xnum,x in (-1, 1] 间隔0.1。
    接下来首先搭建GP框架
    STEP1. 适应度函数的构建,个体及种群初始化,所用工具包:creator/toolbox
    STEP2. 演化操作定义以及树的size限制
    STEP3. 设定参数(交叉率、变异率、迭代次数以及种群大小),初始化种群并计算适应度
    STEP4. 按照选择、交叉、变异的顺序进行演化操作,在一次演化操作完成后选出无效个体(即适应性不如先前个体的个体,对这些个体的适应度不予修改)
    STEP5. 更新种群,统计当前种群的适应度信息并输出
    STEP6. 当循环结束,输出全局最优解

    注意:在GP这种树结构的算法中,在适应度计算当中,生成的树结构首先要通过toolbox.compile转化为函数,再通过函数进行计算,同时所有的遗传操作均是基于树结构进行的,因此在register这些步骤时候需要使用特定的方法,如gp.cxOnePoint等。

    相关文章

      网友评论

          本文标题:DEAP1.2.2(六) 一个GP实例——用于函数发现

          本文链接:https://www.haomeiwen.com/subject/hpscgftx.html