锦标赛选择平均健身不增加?
Tournament Selection Average Fitness not increasing?
我正在尝试实施一种遗传锦标赛选择算法,人口的平均适应度在上升,但我的平均适应度没有改变。
如果有人能看一下我的代码并就我做错了什么提出建议,我将不胜感激。您可以在此处找到代码: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)])))
我已经查看了您的代码。
在这一点上,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")
如果我没记错的话,在这个选择中你想把你的遗传分成 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)
几点说明:
我怀疑您在 next_generation
中忘记将 next_generation
添加到您的全局变量列表中。事实上,这个函数没有做任何事情。
由于全局变量 rerun
永远不会更改为 False,run_generation
您每一代都构建了一组新的个体,而不是计算下一代。唯一更新 rerun
的地方是在 form_generation
中,其中 rerun
是局部变量,而不是全局变量,但我怀疑这是与前一点相同的错误。
此外,您应该检查两个 parent 是否不同。就像现在一样,一个个体很可能会与自己交配,从而产生与其 parent 相同的 child(除了偶尔的突变)。
最后,您真的应该尽量避免使用全局变量,或者至少尝试只将它们用于全局常量。它们使遵循程序流程变得非常困难,正如您所见,它们是各种错误的根源。
我正在尝试实施一种遗传锦标赛选择算法,人口的平均适应度在上升,但我的平均适应度没有改变。
如果有人能看一下我的代码并就我做错了什么提出建议,我将不胜感激。您可以在此处找到代码: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)])))
我已经查看了您的代码。 在这一点上,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")
如果我没记错的话,在这个选择中你想把你的遗传分成 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)
几点说明:
我怀疑您在 next_generation
中忘记将 next_generation
添加到您的全局变量列表中。事实上,这个函数没有做任何事情。
由于全局变量 rerun
永远不会更改为 False,run_generation
您每一代都构建了一组新的个体,而不是计算下一代。唯一更新 rerun
的地方是在 form_generation
中,其中 rerun
是局部变量,而不是全局变量,但我怀疑这是与前一点相同的错误。
此外,您应该检查两个 parent 是否不同。就像现在一样,一个个体很可能会与自己交配,从而产生与其 parent 相同的 child(除了偶尔的突变)。
最后,您真的应该尽量避免使用全局变量,或者至少尝试只将它们用于全局常量。它们使遵循程序流程变得非常困难,正如您所见,它们是各种错误的根源。