遗传算法:收敛问题

Genetic algorithm: problem of convergence

我试图用遗传算法找到一个最大问题的解决方案,但它没有收敛,相反最大适应度越来越低。我不明白为什么它不起作用;我尝试自己执行这些函数并且它们起作用了,我不确定主函数中的调用 though.the 一个最大的问题是当你有一个长度为 m 的二进制个体 (1/0) 的人口 N ,并且您想优化种群,以便生成至少一个仅包含 1 的个体(在我的例子中为 0)

这是我的代码:

import random

def fitness(individual):
    i = 0
    for m in individual:
        if m == 0:
            i += 1
    return i

def selection(pop):
    chosen = []
    for i in range(len(pop)):
        aspirants = []
        macs = []
        for j in range(3):
            aspirants.append(random.choice(pop))
        if fitness(aspirants[0]) > fitness(aspirants[1]):
            if fitness(aspirants[0]) > fitness(aspirants[2]):
                macs = aspirants[0]
            else: macs = aspirants[2]
        else:
            if fitness(aspirants[1]) > fitness(aspirants[2]):
                macs = aspirants[1]
            else: macs = aspirants[2]
        chosen.append(macs)
    return chosen

def crossover(offspring):
    for child1, child2 in zip(offspring[::2], offspring[1::2]):
        if random.random() < 0.7:
            child1[50:100], child2[50:100]=child2[50:100], child1[50:100]

def mutate(offspring):
    for mut in offspring:
        if random.random() < 0.3:
            for i in range(len(mut)):
                if random.random() < 0.05:
                    mut[i] = type(mut[i])(not mut[i])

def gen_individ():
    ind = []
    for s in range(100):
        ind.append(random.randint(0, 1))
    return ind

def gen_pop():
    pop = []  
    for s in range(300):
        pop.append(gen_individ())
    return pop

g = 0
popul = gen_pop()
print("length of pop = %i "% len(popul))
fits = []
for k in popul:
    fits.append(fitness(k))    
print("best fitness before = %i"% max(fits))
while(max(fits) < 100 and g < 100):   
    g += 1
    offspring = []
    offspring = selection(popul)
    crossover(offspring)
    mutate(offspring)
    popul.clear()
    popul[:] = offspring
    fits.clear()
    for k in popul:
    fits.append(fitness(k))
print("lenght of pop = %i "% len(popul))
print("best fitness after = %i"% max(fits))  
print("generation : %i"%g)

问题似乎是在您的所有功能中,您总是只修改相同的个体而不是创建副本。例如,在 selection 函数中,您重复 select 三者中最好的(以一种相当复杂的方式),然后插入多个 references 到相同的列表进入 chosen 列表。稍后,当你 mutate 其中任何一个时,你会改变所有引用。最后你甚至可能只得到 N 对同一个列表的引用,此时显然没有更多实际的 selection 可以发生。

相反,您应该创建列表的副本。这可能发生在不同的地方:在您的主要方法中,在 mutaterecombine 中,或者在下一次迭代的 selection 中。我把它放到selection里,主要是因为这个功能也可以通过其他方式改进:

def selection(pop):
    chosen = []
    for i in range(len(pop)):
        # a lot shorter
        aspirants = random.sample(pop, 3)
        macs = max(aspirants, key=fitness)
        # create COPIES of the individual, not multiple references
        chosen.append(macs[:])
    return chosen

有了这个,你应该每次都获得 100 的质量。