美文网首页
DEAP1.2.2文档(三) 基础教程——操作与算法

DEAP1.2.2文档(三) 基础教程——操作与算法

作者: B_Selmy | 来源:发表于2018-09-04 16:37 被阅读0次

    (三) 操作与算法

    在开始复杂的算法之前,我们将会看到一些DEAP的基本操作。首先,我们将会通过创造简单的个体开始(上一节所讲内容),并且通过使用操作符使得它们之间产生联系。然后,我们将会学习如何使用算法和其他工具。

    1. A First Individual
      首先导入需要的模块并且为创建的个体注册不同的函数,就是一些float类型的lists和两个最小优化目标。
    from deap import tools, creator, base
    IND_SIZE = 10 #A single individual has 10 arguments
    
    #creating individuals
    creator.create('MaxFitness', base.Fitness, weights = (1.0,1.0)) #double optimization object
    
    creator.create('Individual', list, fitness = creator.MaxFitness) #creating a list to store individual
    
    toolbox = base.Toolbox()  #called Toolbox
    
    toolbox.register('generating_method', random.random) #define random method
    
    toolbox.register('individual', tools.initRepeat ,creator.Individual, toolbox.generating_method, n = IND_SIZE) #define individual, mode:initRepeat, each individual has 10 arguments
    
    init = toolbox.individual()
    print(init.fitness.valid)
    
    1. Evaluation
      适应值计算是演化算法中最个性化的部分,这是库中唯一你必须自己写的部分。一个典型的适应度函数会采取一个个体作为元素,并且以元组(不可更改,是python的一种数据类型)的形式返回适应度函数。就像核心节所示的一样,适应度值是一个由float类型的数组组成的list,并且拥有验证优先级——即了解某个体是否被重新计算过适应值(即经历了一系列遗传操作)。适应度最终通过设置values与元组连接的集合。例如,下面的对之前创建个体的适应度计算并且将计算结果分配给相应的值。
    def evaluate(individual):
        #do some hard computing on the individual
        a = sum(individual)
        b = len(individual)
        return a, 1. /b
    
    init.fitness.value = evaluate(init) #setting value 
    print(init.fitness.valid)
    print(init.fitness.value)
    

    对于单目标优化问题没有什么不同,适应度函数必须返回一个元组,这是因为单目标优化是多目标优化的一个特例。

    这一节讲的是适应度函数的设计,这个自主性很强,根据优化目标的数量返回相应数目的结果。

    1. Mutation
      下一种的操作符是变异操作。在deap.tools中有许多种不同的变异操作,每一种变异都有它独特的特征,它们可能会适应于不同类型的个体。在阅读文档时要注意选择运算符是为了避免一些我们不想看到的情况(这里应该是指避免出现类似要求最大值而选择具有最小值的个体)。

    变异操作的常规规则是它们只会变异,这就意味着一个独立的拷贝必须要在个体变异之前进行,这是为了对原个体和变异个体进行择优选择。

    为了在init上实现变异操作(这里的例子是gaussian mutation),常用的函数如下

    mutant = toolbox.clone(init)   #define mutant as the clone of init
    #new offspring init2 from mutant by Gaussian mutation
    init2, = tools.mutGaussian(mutant, mu = 0.0, sigma = 0.2, indpb = 0.2)
    del mutant.fitness.values
    

    最后一行删除变异个体的适应度值是因为它们与个体不再相关了(因为变异之后个体的适应度值肯定与之前的值不一致)。如上所述,变异操作只会对一个个体进行变异,并且变异之后的个体与之前的适应度值没有任何关系,下面的代码将会展示init2与mutant实际上是一个个体。

    print(init2 is mutant) #True
    print(mutant is init) #False
    
    1. Crossover
      第二种类型的操作就是交叉操作。同样在tools中有许多种不同的交叉操作方法(deap.tools)。每一种交叉操作也有它独特的特点,并且可以应用在不同类型的个体上。同样选择操作也会避免一些我们不想看到的问题的发生。

    交叉操作的常规规则是这种操作只会发生在兄弟个体间(即在操作前要对进行交叉操作的个体完成配对)。这就意味着一个独立的拷贝必须在个体配对前完成,这是为了保证原始个体被保留或者该个体被其它个体引用。

    让我们运用交叉操作去产生两个被克隆的子代个体

    #clone two children
    child1, child2 = [toolbox.clone(init) for init in (init, init2)]
    #crossover operation
    tools.cxBlend(child1, child2, 0.5)
    del child1.fitness.values
    del child2.fitness.values
    
    1. Selection
      选择是在整个种群中通过可在deap.tools中提供的选择操作完成的。选择运算符通常将可迭代的个体容器和要选择的个体数作为第一个参数。它返回一个包含被选择个体的list,选择过程如下
    #selecting the best one from child1 and child2
    selected = tools.selBest([child1, child2], 2)
    print(child2 in selected) #True
    

    Warning:很重要的一点是选择操作并不会在选择过程中复制任何个体。如果一个个体被选择了两次并且其中的一个被修改过,那么其他的个体也同样会被修改。只有引用的个体会被复制。

    通常情况下整个种群的复制将会在选择之后或者变化之前完成。

    #clone will after the selection
    offspring = [toolbox.clone(ind) for ind in selected]
    
    1. Using the Toolbox
      toolbox(base.Toolbox())是包含所有进化操作的工具箱,从目标初始化到适应度计算。它允许在每个算法中实现简单的构造。toolbox基本上由两种方法组成,register()和unregister(),这两种函数是用来添加和移除工具的。

    这部分的教程将会关注在遗传操作工具的registration上而不是初始化。通常的遗传操作工具的名字包括mate()、mutata()、evaluate()和selected(),然而,任何名字都可以被独特的register。这里会展示它们是如何在toolbox中注册的

    def evaluateInd(individual):
        result = individual **2
        return result
    #def mate method
    toolbox.register('mate', tools.cxTwoPoint)
    #def mutate method
    toolbox.register('mutate', tools.mutGaussian, mu = 0, sigma = 1, indpb = 0.2)
    #def select method
    toolbox.register('select', tools.selTournament, toursize = 3)
    #def evaluate method
    toolbox.register('evalutae', evaluateInd)
    

    使用toolbox作为注册工具可以帮助剩余的算法与操作集合之间保持独立(不必在剩余的代码中频繁调用toolbox以及tools)。使用这一结构可以使得代码可读性更强,同时可以轻松地改变所用的遗传操作方法。

    1. Using the Tools
      当建立一个演化算法时,toolbox是用来确定你要使用的遗传操作方法的,它会调用一些通用的名字。例如,这里有一个十分简单的演化算法
    fitnesses = list(map(toolbox.evaluate, pop))
    for ind, fit in zip(pop, fitnesses):
        ind.fitness.values = fit
    
    toolbox.register('population', tools.initRepeat,list, toolbox.individual)
    pop = toolbox.population(n = 30)
    NGEN = 100 #ITERATION NUMBER
    CXPB = 0.1 #CROSSOVER RATE
    MUPB = 0.1 #MUTATION RATE
    for i in range(NGEN):
        #selection
        offspring = toolbox.select(pop, len(pop)) #select len(pop) individuals from pop
        #clone the selected individuals
        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 individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitness = toolbox.map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitness):
            ind.fitness.values = fit
            
        #the population is entirely replaced by offspring
        pop[:] = offspring
    

    这是一个完整的算法(虽然我也不知道它为啥用不了),它适用于任何的个体和操作,只要操作适合于个体的种类。就像最后一个例子这样,toolbox的使用允许去写一些很接近与伪代码的算法。现在你可以自己觉得你要去做什么了。

    整个流程基本介绍完毕,首先是个体初始化和目标初始化creator.create()。随后使用toolbox.register()完成种群创建、适应度函数定义、遗传算子的选择(交叉+变异)、选择方法(轮盘赌or锦标赛...)。

    1. Tool Decoration
      工具装饰是一个很强力的特征,它可以帮助你在演化过程中去精确地对算法和操作进行控制。一个装饰是指将函数进行包装,这叫做在真实的函数被调用前后做一些初始化和终止工作。例如,在一个有限的区域内,一种应用装饰符的方法是在变异和交叉的过程中保证个体不会越界。下面的定义就是检查是否有个体越界,装饰符是通过三个函数定义的,为了接收最小值和最大值。当变异或者交叉被调用时,边界将会检查它们的运算结果。
    def checkBounds(min, max):
        def decorator(func):
            def wrapper(*args, **kargs):
                offspring = func(*args, **kargs)
                for child in offspring:
                    for i in xrange(len(child)):
                        if child[i] > max:
                            child[i] = max
                        elif child[i] < min:
                            child[i] = min
                return offspring
            return wrapper
        return decorator
    
    toolbox.register("mate", tools.cxBlend, alpha=0.2)
    toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=2)
    
    toolbox.decorate("mate", checkBounds(MIN, MAX))
    toolbox.decorate("mutate", checkBounds(MIN, MAX))
    

    TD就是一个越界判别的运算符,在每一步完成迭代之后可以对新生成的种群进行检查。

    1. Variations
      变化允许建立简单的算法,使用预定义好的小模块。为了使用变化,toolbox一定会建立一个包含所需运算符的集合。例如,在最近展示的完整算法案例中,交叉和变异运算在varAnd()中被重新整合。这个函数要求toolbox包含mate()和mutate()函数,这种变化可以用来简化算法,就像下面这样
    from deap import algorithms
    
    for g in range(NGEN):
        # Select and clone the next generation individuals
        offspring = map(toolbox.clone, toolbox.select(pop, len(pop)))
    
        # Apply crossover and mutation on the offspring
        offspring = algorithms.varAnd(offspring, toolbox, CXPB, MUPB)
    
        # Evaluate the individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit
    
        # The population is entirely replaced by the offspring
        pop[:] = offspring
    
    1. Algorithms
      有许多种可以在algorithm模块中使用的算法,它们十分简单并且可以反映演化算法的基本类型。这些算法使用Toolbox作为定义好的内容。一旦toolbox被设定完成,它们将会去调用这些算法。简单的演化算法需要五个参数,种群、toolbox、交叉率、变异率和种群迭代次数。
    from deap import algorithms
    
    algorithms.eaSimple(pop, toolbox, cxpb=0.5, mutpb=0.2, ngen=50)
    

    理解简单演化算法的最好方法是阅读文档和理解源代码。

    现在你可以在Python中构建自己的演化算法了!

    相关文章

      网友评论

          本文标题:DEAP1.2.2文档(三) 基础教程——操作与算法

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