【问题标题】:Tournament Selection Average Fitness not increasing?比赛选择 平均体能没有增加?
【发布时间】:2020-06-20 03:26:11
【问题描述】:

我正在尝试实现一种遗传锦标赛选择算法,在该算法中,人群的平均适应度上升,但我的平均适应度没有改变。

如果有人可以查看我的代码并就我做错了什么提出建议,我将不胜感激。你可以在这里找到代码:https://github.com/Mithycal/tournament-selection-algorithm

寻找适应度的代码:

for i in range(len(individuals)):
            chosen = individuals[i]
            fitness_scores.append(sum(([a * b for a, b in zip(equation_inputs, chosen)])))

【问题讨论】:

    标签: python python-3.x genetic-algorithm tournament


    【解决方案1】:

    我查看了您的代码。 在这一点上,tournamentSize 是每个组的大小对吗?

    for k in range(tournamentSize):
        randchoice = random.sample(list(individuals), 1)[0] #update individual list so values are different??!
        randvalue = individuals.get(randchoice)
        random_individuals.append(randvalue)
        loc = list(individuals).index(randchoice)
        random_fitness_scores.append(fitness_scores[loc])
        print("\n", randchoice, "participates in the tournament")
    print("\n")
    

    如果我记得在这个选择中你想将你的 poblation 分成 N 组个人,然后你想只保留每组中最好的(或 n 个最好的)。

    我建议您将人口表示更改为:

    individuals = [[random.randint(-4,4) for _ in range(number_of_genes)] for i in pop ] # list
    

    所以你可以这样做: score() -> 重新调整个体适应度的自定义函数

    choosen_individuals = []
    #go throw individual jumping tournamentSize each time
    for k in range(0,len(individuals),tournamentSize): 
        tournament_individuals = individuals[k:k+tournamentSize] # current group
        sorted_group = sorted( [ (score(individual),index) for index,individual in enumerate(tournament_individuals)],reverse = True)
        #sorted_group contains a list of tuples (score,individual_position)
        choosen_individuals.append(tournament_individuals[sorted_group[1]]) # saves the best
    

    我要留给你一个我实施的基因: https://github.com/anigmo97/MUIARFID/blob/master/CUATRIMESTRE_1A/TIA/PROYECTO/algoritmo_gen%C3%A9tico/geneticos.py

    希望对你有帮助。

    你的实现

    个人代表

    现在您的个人(重命名为人口)是一个氏族列表。 你的人口是一个带有键(int)和整数值列表的字典。 如果您考虑一下,基本上您使用的是字典,因为它是一个列表。 我建议您更改人口的表示形式,例如:

    {0: [2,-3], 1: [-1,-1]}

    [[2,-3],[-1,-1]]

    变化

    individuals = { i : [random.randint(-4,4) for _ in range(number_of_genes)] for i in pop }
    
    population = []
    for i in range(population_size):
        population.append([random.randint(-4,4) for _ in range(number_of_genes)])
    

    个人评分

    您有每个基因的权重列表,因此我们有一个名为“权重”的列表,长度 = number_of_genes。 (个体长度相同)。

    使用新的表示形式,您的评分可以是:

    def score_individual(individual):
        return sum(([a * b for a, b in zip(weights, individual)]))
    
    def fitness_calc(population):
        fitness_scores = [] #local variable
        for individual in population:
            chosen = list(individuals.values())[i]
            fitness_scores.append(score_individual(individual)) 
        return fitness_scores
    

    人口排序

    def sort_population_by_fitness(population):
         return sorted(population,key=lambda i:score_individual(i),reverse=True)
    

    完整示例

    from random import randint,shuffle
    
    def generate_random_weights(num_weights):
        return [randint(-200,200) for x in range(num_weights)]
    
    
    def generate_population(number_of_gens):
        population = []
        for i in range(population_size):
            population.append([randint(-4, 4) for _ in range(number_of_gens)])
        return population
    
    def score_individual(individual):
        return sum(([a * b for a, b in zip(weights, individual)]))
    
    def fitness_calc(population):
        fitness_scores = [] #local variable
        for individual in population:
            fitness_scores.append(score_individual(individual))
        return fitness_scores
    
    def sort_population_by_fitness(population):
        return sorted(population,key=lambda i:score_individual(i),reverse=True)
    
    def calculate_population_score_avg(population):
        scores = [score_individual(i) for i in population]
        return sum(scores)/len(scores)
    
    def make_tournament_selection(population,group_size):
        shuffle(population)
        choosen_individuals = []
        #go throw individual jumping tournamentSize each time
        for k in range(0, len(population), group_size):
            tournament_individuals = population[k:k + group_size]  # current group
            sorted_group = sort_population_by_fitness(tournament_individuals)
            choosen_individuals.append(sorted_group[0])
            print("---->BEST INDIVIDUAL OF THE GROUP {}".format(score_individual(sorted_group[0])))
        return choosen_individuals
    
    def make_n_best_selection(population,num_individuals_to_keep):
        return sort_population_by_fitness(population)[:num_individuals_to_keep]
    
    
    
    if __name__ =="__main__":
        population_size = 20
        number_of_gens = 10
        weights = generate_random_weights(number_of_gens)
        population = generate_population(number_of_gens)
    
        num_generations = 10
        group_size = 5
        score_avgs_by_generation = []
        for i in range(num_generations):
            # make selection
            #population = make_tournament_selection(population,group_size)
            population = make_n_best_selection(population,5)
            print("BEST SCORE IN GENERATION {} = {}".format(
                i,score_individual(sort_population_by_fitness(population)[0]))
            )
            avg_score = calculate_population_score_avg(population)
            score_avgs_by_generation.append(avg_score)
            print("SCORE AVG  IN GENERATION {} = {}\n\n".format(i, avg_score))
    
            # make crossbreeding
            # make mutations
            # add random individuals to add new genetic load
            population += generate_population(10)
    
    

    【讨论】:

    【解决方案2】:

    几点说明:

    我怀疑在next_generation 中您忘记将next_generation 添加到您的全局列表中。事实上,这个函数没有做任何事情。

    由于全局变量 rerun 从未更改为 False,run_generation 您每一代都会构造一组新个体,而不是计算下一代。唯一更新rerun 的地方是form_generation,其中rerun 是局部变量,而不是全局变量,但我怀疑这与上一点的错误相同。

    此外,您应该检查两个父母是否不同。就像现在一样,一个人很可能会与自己交配,从而产生一个与其父母相同的孩子(除了偶尔的突变)。

    最后,你真的应该尽量避免使用全局变量,或者至少尝试只将它们用于全局常量。它们使跟踪程序的流程变得非常困难,并且正如您所见,它们是各种错误的根源。

    【讨论】:

    • 当我在它为 False 后将 rerun 设置为 True 时,我在图上得到一条直线。并且基因每次都保持不变,每个个体的适应度得分每一代都保持不变。
    • 那是因为你每次都选择得分最高的父母,而不检查它是否已经被选择。除非两个人碰巧得分相同,否则这意味着一个孩子很可能实际上只有一个父母,而不是两个,即得分最高的那个。
    猜你喜欢
    • 1970-01-01
    • 2012-04-18
    • 2013-06-19
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 2015-05-01
    • 2019-02-19
    相关资源
    最近更新 更多