DEAP-Overviewhtml
DEAP是一個python遺傳算法框架,這裏是它的簡介。DEAP documentation
今天整理一下DEAP的概覽,大致瞭解一下它的流程。初學,不嚴謹,僅做爲本身的備忘學習筆記。python
The first thing to do is to think of the appropriate type for your problem.This is done with the creator module.
第一件事就是思考你問題的合適類型(是什麼樣的優化問題,最小值?最大值?單目標?多目標?)。在creator
模塊中能夠實現。redis
For example, the following creates a FitnessMin class for a minimization problem and an Individual class that is derived from a list with a fitness attribute set to the just created fitness.
例如,下面爲一個最小化問題建立一個FitnessMin
類和個體類,它來自於剛剛建立的適應度帶有fitness屬性值集合的列表。算法
from deap import base, creator creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) creator.create("Individual", list, fitness=creator.FitnessMin)
That’s it. More on creating types can be found in the Creating Types tutorial.
更多關於建立類型的問題能夠在Creating Types tutorial查看。spring
Once the types are created you need to fill them with sometimes random values, sometime guessed ones. Again, DEAP provides an easy mechanism to do just that.
一旦這些類型被建立,你就須要用一些隨機的值來填充它們,有時是猜想值。一樣的, DEAP極大的提供了這樣的一個簡單的機制來作這件事兒。api
The Toolbox is a container for tools of all sorts including initializers that can do what is needed of them. The following takes on the last lines of code to create the initializers for individuals containing random floating point numbers and for a population that contains them.toolbox
是一個工具容器,可用來包含各類「初始化體」(能夠作它們須要的事兒)。如下是以代碼來建立包含隨機浮點數的初始化和我的人口包含他們最後的線。下面最後幾行代碼用來建立「初始化體」,爲包含那些隨機值的「個體」和包含它們的種羣。app
import random from deap import tools IND_SIZE = 10 toolbox = base.Toolbox() toolbox.register("attribute", random.random) toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attribute, n=IND_SIZE) toolbox.register("population", tools.initRepeat, list, toolbox.individual) #是吧,建立的individual放入了population中
This creates functions to initialize populations from individuals that are themselves initialized with random float numbers. The functions are registered in the toolbox with their default arguments under the given name.
這將建立函數來初始化種羣(來自那些用隨機浮點數初始化而成的個體們)。這些函數在給定名字的默認參數下被「註冊到」toolbox中,框架
register
感受這個單詞在這兒的理解能夠看作是「建立」的意思,而後toolbox
中就有了toolbox.individual
。具體理解,還得看後面的詳細介紹。toolbox
貌似和function
有關,裏邊的第一個參數就是函數名。由於在Algorithm
步驟裏時,出現了這樣的用法toolbox.population()
。
More initialization methods are found in the Creating Types tutorial and the various Examples.
更多初始化的方法能夠在 Creating Types tutorial和Examples中查看。dom
toolbox.register("mate", tools.cxTwoPoint)
Operators
都在toolbox模塊裏,要給每一個算子選擇合適算法。在Operator裏邊能夠給每一個步驟的算子分別選擇合適的算法。ide
In addition you must create your evaluation function. This is how it is done in DEAP.
就是這個評價功能函數得本身寫,其實,也就是適應度函數了!
Note also that fitness values must be iterable, that is why we return a tuple in the evaluate function.
就是注意評價函數返回值必須是可迭代的。
def evaluate(individual): return sum(individual), toolbox.register("mate", tools.cxTwoPoint) toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1) toolbox.register("select", tools.selTournament, tournsize=3) toolbox.register("evaluate", evaluate)
Now that everything is ready, we can start to write our own algorithm. It is usually done in a main function. For the purpose of completeness we will develop the complete generational algorithm.
如今一切具有,咱們能夠開始寫本身的算法了。一般在主函數裏邊寫。完整性的目的,咱們將開發完整的分代算法。
def main(): pop = toolbox.population(n=50) CXPB, MUTPB, NGEN = 0.5, 0.2, 40 # Evaluate the entire population fitnesses = map(toolbox.evaluate, pop) for ind, fit in zip(pop, fitnesses): ind.fitness.values = fit for g in range(NGEN): # Select the next generation individuals offspring = toolbox.select(pop, len(pop)) # Clone the selected individuals offspring = map(toolbox.clone, offspring) # Apply crossover and mutation on the offspring 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 for mutant in offspring: if random.random() < MUTPB: 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] fitnesses = 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 return pop
縱觀整個步驟,能夠發現DEAP
在實現GA過程當中的思路通常是很清晰的。
肯定Types
--creator
建立,選好解決問題的類型
初始化Initialization
--toolbox
註冊個體啊,種羣啊等等函數。
Operator
--算子選擇,交叉,變異,選擇,進化等等。每一個算子都有不一樣的算法,能夠選擇的!
Algorithms
--算法就是具體將上面註冊的函數啊,等等應用結合起來,編寫流程。
# This file is part of DEAP. # # DEAP is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 of # the License, or (at your option) any later version. # # DEAP is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with DEAP. If not, see <http://www.gnu.org/licenses/>. # example which maximizes the sum of a list of integers # each of which can be 0 or 1 import random from deap import base from deap import creator from deap import tools creator.create("FitnessMax", base.Fitness, weights=(1.0,)) #這裏這個base.Fitness是幹嗎的??? creator.create("Individual", list, fitness=creator.FitnessMax) #這裏的list,fitness是參數,幹嗎的??? toolbox = base.Toolbox() #base是個很基本的類啊!!!看來很重要 # Attribute generator: define 'attr_bool' to be an attribute ('gene') # which corresponds to integers sampled uniformly # from the range [0,1] (i.e. 0 or 1 with equal # probability) toolbox.register("attr_bool", random.randint, 0, 1) #包含了0,1的隨機整數。不明白這裏是幹嗎的??? # Structure initializers: define 'individual' to be an individual # consisting of 100 'attr_bool' elements ('genes') toolbox.register("individual", tools.initRepeat, creator.Individual, #tools.initRepeat是幹嗎的??? toolbox.attr_bool, 100) # define the population to be a list of 'individual's toolbox.register("population", tools.initRepeat, list, toolbox.individual) # the goal ('fitness') function to be maximized 注意!!!這裏就定義了咱們的適應度fitness函數啦!!!由於咱們要解決的就是求和問題 # 只要返回一個值給咱們的這個適應度函數啊!利用自帶的sum函數! # 這裏取名爲evalOneMax是由於這裏的適應度函數就是咱們後面要用來評價的依據,evaluate def evalOneMax(individual): return sum(individual), #---------- # Operator registration #---------- # register the goal / fitness function # 這裏的toolbox register語句的理解:註冊了一個函數evaluae依據的是後面的evalOneMax 理通了!!! toolbox.register("evaluate", evalOneMax) # 瞧瞧,這裏的交叉函數,尼瑪,crossover不用,非得用個mate,還覺得是華爲mate呢!你看,這裏的交叉算子採用的函數,也是已經停供的,能夠選擇的 # register the crossover operator toolbox.register("mate", tools.cxTwoPoint) # register a mutation operator with a probability to # flip each attribute/gene of 0.05 toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) # operator for selecting individuals for breeding the next # generation: each individual of the current generation # is replaced by the 'fittest' (best) of three individuals # drawn randomly from the current generation. toolbox.register("select", tools.selTournament, tournsize=3) #這裏選擇的tournsize又是什麼意思呢? #---------- def main(): random.seed(64) # hash(64)is used # random.seed方法的做用是給隨機數對象一個種子值,用於產生隨機序列。 # 對於同一個種子值的輸入,以後產生的隨機數序列也同樣。 # 一般是把時間秒數等變化值做爲種子值,達到每次運行產生的隨機系列都不同 # create an initial population of 300 individuals (where # each individual is a list of integers) pop = toolbox.population(n=300) #定義了300個個體的種羣!!! # CXPB is the probability with which two individuals # are crossed # # MUTPB is the probability for mutating an individual # # NGEN is the number of generations for which the # evolution runs 進化運行的代數!果真,運行40代以後,就中止計算了 CXPB, MUTPB, NGEN = 0.5, 0.2, 40 print("Start of evolution") # Evaluate the entire population fitnesses = list(map(toolbox.evaluate, pop)) for ind, fit in zip(pop, fitnesses): ind.fitness.values = fit print(" Evaluated %i individuals" % len(pop)) #這時候,pop的長度仍是300呢 # Begin the evolution 開始進化了哈!!!注意注意注意!就是一個for循環裏了!40次--代數 for g in range(NGEN): print("-- Generation %i --" % g) # Select the next generation individuals offspring = toolbox.select(pop, len(pop)) # Clone the selected individuals offspring = list(map(toolbox.clone, offspring)) # Apply crossover and mutation on the offspring for child1, child2 in zip(offspring[::2], offspring[1::2]): # cross two individuals with probability CXPB if random.random() < CXPB: toolbox.mate(child1, child2) # fitness values of the children # must be recalculated later del child1.fitness.values del child2.fitness.values for mutant in offspring: # mutate an individual with probability MUTPB if random.random() < MUTPB: 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] fitnesses = map(toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit print(" Evaluated %i individuals" % len(invalid_ind)) # The population is entirely replaced by the offspring pop[:] = offspring # Gather all the fitnesses in one list and print the stats fits = [ind.fitness.values[0] for ind in pop] length = len(pop) mean = sum(fits) / length sum2 = sum(x*x for x in fits) std = abs(sum2 / length - mean**2)**0.5 print(" Min %s" % min(fits)) print(" Max %s" % max(fits)) print(" Avg %s" % mean) print(" Std %s" % std) print("-- End of (successful) evolution --") best_ind = tools.selBest(pop, 1)[0] print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values)) if __name__ == "__main__": main()