2013-12-15 118 views
2

我正在使用DEAP庫來最大化度量,並且我注意到每當我重新啓動算法(應該創建一個二進制值的隨機列表 - 1和0)時,它會產生相同的初始值。如何用DEAP產生不同的隨機結果?

我變得可疑並複製其basic DEAP example here並再次重新運行該算法:

import array, random 
from deap import creator, base, tools, algorithms 

creator.create("FitnessMax", base.Fitness, weights=(1.0,)) 
creator.create("Individual", array.array, typecode='b', fitness=creator.FitnessMax) 

toolbox = base.Toolbox() 

toolbox.register("attr_bool", random.randint, 0, 1) 
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, 10) 
toolbox.register("population", tools.initRepeat, list, toolbox.individual) 

def evalOneMax(individual): 
    return sum(individual), 

toolbox.register("evaluate", evalOneMax) 
toolbox.register("mate", tools.cxTwoPoints) 
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) 
toolbox.register("select", tools.selTournament, tournsize=3) 

population = toolbox.population(n=10) 

NGEN=40 
for gen in range(NGEN): 
    offspring = algorithms.varAnd(population, toolbox, cxpb=0.5, mutpb=0.1) 
    fits = toolbox.map(toolbox.evaluate, offspring) 
    for fit, ind in zip(fits, offspring): 
     ind.fitness.values = fit 
    population = offspring 

上面的代碼正是他們的例子,但與人口和個人尺寸減小到10。我跑的算法5時間,它產生了彼此的確切副本。我還添加了一個print語句得到下面的輸出:

>python testGA.py 
[1, 0, 1, 0, 1, 0, 1, 1, 1, 1] 
Starting the Evolution Algorithm... 
Evaluating Individual: [0, 1, 0, 1, 0, 1, 1, 1, 1, 0] 
Evaluating Individual: [1, 1, 0, 1, 0, 1, 0, 1, 0, 0] 
Evaluating Individual: [0, 0, 1, 0, 0, 1, 1, 0, 0, 1] 
Evaluating Individual: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
Evaluating Individual: [0, 1, 1, 0, 1, 0, 1, 1, 0, 1] 
Evaluating Individual: [1, 0, 1, 1, 1, 0, 0, 1, 0, 0] 
Evaluating Individual: [0, 1, 0, 0, 0, 1, 0, 0, 0, 1] 
Evaluating Individual: [1, 1, 0, 1, 0, 1, 0, 1, 1, 1] 
Evaluating Individual: [1, 1, 1, 1, 0, 0, 1, 0, 0, 0] 
Evaluating Individual: [0, 0, 1, 1, 1, 1, 0, 1, 1, 1] 

這個輸出產生我每次調用該函數的時間 - 在這個順序。它們完全相同。

我讀過,我不應該種子random.randint函數,我測試它通過編寫一個基本的腳本,打印出10個隨機整數範圍爲0到1列表。這工作正常,它只是當我通過DEAP提供它時似乎產生相同的值。

這是正常的嗎?我怎樣才能確保,當我運行算法時,我每次都得到不同的「個人」?

編輯:

很抱歉這麼晚纔回復,這裏是我使用的完整源:

import random, sys 
from deap import creator, base, tools 

class Max(): 

    def __init__(self): 
     creator.create("FitnessMax", base.Fitness, weights=(1.0,)) 
     creator.create("Individual", list, fitness=creator.FitnessMax) 

     INDIVIDUAL_SIZE = 10 

     self.toolbox = base.Toolbox() 
     self.toolbox.register("attr_bool", random.randint, 0, 1) 
     self.toolbox.register("individual", tools.initRepeat, creator.Individual, self.toolbox.attr_bool, n=INDIVIDUAL_SIZE) 
     self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual) 

     self.toolbox.register("mate", tools.cxTwoPoints) 
     self.toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) 
     self.toolbox.register("select", tools.selTournament, tournsize=3) 
     self.toolbox.register("evaluate", self.evaluate) 

     print self.main() 


    def evaluate(self, individual): 
     # Some debug code 
     print 'Evaluating Individual: ' + str(individual) 
     return sum(individual), 

    def main(self): 

     CXPB, MUTPB, NGEN = 0.5, 0.2, 40 
     random.seed(64) 
     pop = self.toolbox.population(n=10) 

     print "Starting the Evolution Algorithm..." 

     fitnesses = list(map(self.toolbox.evaluate, pop)) 
     for ind, fit in zip(pop, fitnesses): 
      ind.fitness.values = fit 

     # ---------------------------------------------------------- 
     # Killing the program here - just want to see the population created 
     sys.exit() 

     print "Evaluated %i individuals" % (len(pop)) 

     for g in range(NGEN): 
      print "-- Generation %i --" % (g) 

      # Select the next genereation individuals 
      offspring = self.toolbox.select(pop, len(pop)) 

      # Clone the selected individuals 
      offspring = list(map(self.toolbox.clone, offspring)) 

      # Apply crossover and mutation on the offspring 
      for child1, child2 in zip(offspring[::2], offspring[1::2]): 
       if random.random() < CXPB: 
        self.toolbox.mate(child1, child2) 
        del child1.fitness.values 
        del child2.fitness.values 

      for mutant in offspring: 
       if random.random() < MUTPB: 
        self.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(self.toolbox.evaluate, invalid_ind) 
      for ind, fit in zip(invalid_ind, fitnesses): 
       ind.fitness.values = fit 

      print "\tEvaluated %i individuals" % (len(pop)) 

      pop[:] = offspring 

      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 "\tMin %s" % (min(fits)) 
      print "\tMax %s" % (max(fits)) 
      print "\tAvg %s" % (mean) 
      print "\tStd %s" % (std) 

class R_Test: 
    def __init__(self): 

     print str([random.randint(0, 1) for i in range(10)]) 


if __name__ == '__main__': 
    #rt = R_Test() 
    mx = Max() 

的R_Test類是有沒有在Python測試隨機生成。我讀here即使沒有在Python中給出種子,也會動態調用種子,我想測試它。

如何我一直在執行上面的代碼一直是這樣:

> python testGA.py 
... the 10 outputs 
> python testGA.py 
... the exact same outputs 
> python testGA.py 
... the exact same outputs 
> python testGA.py 
... the exact same outputs 
> python testGA.py 
... the exact same outputs 

顯然5次不完全是一個艱苦的考驗,但事實證明,所有的10個值是相同的5次連續舉起一面紅旗。

+0

在源代碼中似乎沒有任何對'random.seed'的引用。 – Blender

+0

如果明確調用'random.seed()',會發生什麼?值是否改變了? –

+3

我是DEAP首席開發人員之一。你所觀察到的是不正常的,但我無法用你提供的代碼重現它。你能提出你使用的確切代碼嗎? – CmdNtrf

回答

6

問題是您在主函數中爲隨機數生成器指定了一個種子。只需評論該行:random.seed(64),每次執行程序時都會得到不同的結果。

在DEAP示例文件中,設置了特定的種子,因爲我們也將這些示例用作集成測試。如果在框架基本代碼中進行修改後,示例的輸出不同,我們想知道。它還使我們能夠平衡每個示例所需的時間,並向我們的用戶提供大概的估算值。這些基準的結果可在線獲得,網址爲http://deap.gel.ulaval.ca/speed/

+0

這樣做,我很抱歉,我沒有看到這更早。謝謝。 – cshortt