【问题标题】:Elitism is failing in Genetic Algorithm精英主义在遗传算法中失败了
【发布时间】:2013-01-14 15:10:04
【问题描述】:

我正在尝试运行我用 python 编写的遗传算法。不幸的是,当发生突变时,尽管使用精英主义将最适合的解决方案从上一代传递给新的解决方案,但最适合的解决方案可能比上一代的最适合解决方案更差。像这样:

There are 86825 generations left
Invalid count is:  0
The fittest individual has a fitness of 16.9094. 
The least fit individual has a fitness  of 36.6535
*******************************************************************************
mutation on 107
There are 86824 generations left
Invalid count is:  3
The fittest individual has a fitness of 19.8637. 
The least fit individual has a fitness of 1.1618e+09

我曾尝试实施精英主义,我认为这会避免这种情况发生,但它仍然会发生。我的算法按以下顺序执行:

NUM_GEN = 100000
print "Running Genetic Algorithm for %d generations." % NUM_GEN
gen_count = 0
while gen_count < NUM_GEN:
    #genetic.add_fitness_key()
    genetic.add_fitness_fast()
    fittest_list = np.append(fittest_list, genetic.fittest_fitness)
    least_fit_list = np.append(least_fit_list, genetic.least_fitness)
    genetic.sort_pop()
    genetic.make_new_pop()
    genetic.elitism()
    genetic.population = genetic.new_pop
    print "There are %g generations left" %(NUM_GEN-gen_count) 
    gen_count+=1

调用的函数如下:

def select_parent_from_tournament(self):
    x = random.randint(0, 19)
    player1 = self.population[x]
    y = random.randint(0, 19)
    player2 = self.population[y]
    if player1['fitness'] <= player2['fitness']:
        parent = player1['chrom_list']
    else:
        parent = player2['chrom_list']
    return parent

def crossover(self):
    crossover_point = random.randint(0, self.chromosome_size)*(self.string_length)
    parent1 = self.select_parent_from_tournament()
    parent2 = self.select_parent_from_tournament()
    parent1 = self.mutate(parent1)
    parent2 = self.mutate(parent2)
    child1 = parent1[:crossover_point] + parent2[crossover_point:]
    child2 = parent1[crossover_point:] + parent2[:crossover_point]
    return child1, child2

def mutate(self, chromosome):
    for i in range(len(chromosome)):
        if random.random() < self.mutation_rate:
            print 'mutation on %i' % i
            if chromosome[i] =='0':
                chromosome[i] = '1'
            else:
                chromosome[i] = '0'
    return chromosome

def make_new_pop(self):
    self.new_pop = []
    for i in range(10):
        dictionary1= {}
        dictionary2 = {}
        dictionary1['chrom_list'], dictionary2['chrom_list'] = \
        self.crossover()
        self.new_pop = np.append(self.new_pop, [dictionary1, dictionary2])

def elitism(self):
    r = random.randint(0, 19)
    self.new_pop[r] = self.population[0]

所以我不明白为什么如果发生突变,旧种群中最适合的解决方案不会传递给新种群?

【问题讨论】:

  • 你做过调试吗?
  • 在交叉/变异后,您最适合的个体可能会被摧毁..?
  • @nicholaschris 在我看来,突变不会产生新的染色体,但会修改原来的染色体。如果这是最合适的,那么……
  • @euqinoxel: 你好像应该在 mutate 函数的顶部写应该染色体 = list(chromosome)
  • @Xavier Combelle:据我所知,染色体已经是一个列表,但我可能没有通过排除一些代码来说明这一点。或者还有其他原因我应该写list=list(chromosome) ?谢谢

标签: python genetic-algorithm


【解决方案1】:

在您的交叉方法中,您执行parent1 = self.select_parent_from_tournament(),它返回对原始种群中染色体列表的引用。在那之后,你做一个修改列表的突变(在原始人口中)。只有在突变后,您才能通过child1 = parent1[:crossover_point] + parent2[crossover_point:] 复制子项中的内容。正如@Xavier 建议的那样,您需要从mutation() 中的原始人口中创建元素的物理副本。

实际上,您的mutation() 方法改变了原来的人口。

附带说明,通常交叉和变异是两种不同的操作。此外,文献中的参考文献表明突变概率应保持在非常低的水平。否则它会让你无法收敛。

【讨论】:

  • 谢谢!我在def mutate(self, chromosome) 的正下方添加了chromosome = list(chromosome)。有用。我显然需要更多地了解 python 如何引用对象!
  • @nicholaschris 不用担心 :) 几年前我也遇到过同样的问题。
猜你喜欢
  • 2013-07-26
  • 1970-01-01
  • 2012-07-06
  • 2011-01-11
  • 2012-07-07
  • 2011-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多