0

我正在尝试实现一种遗传锦标赛选择算法,其中人口的平均适应度上升,但我的平均适应度没有改变。 在此处输入图像描述

如果有人可以查看我的代码并就我做错了什么提出建议,我将不胜感激。你可以在这里找到代码: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)])))
4

2 回答 2

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)

于 2020-03-07T17:38:20.117 回答
1

几点说明:

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

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

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

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

于 2020-03-07T18:31:58.163 回答