Выбор турнира Средняя пригодность не увеличивается? - PullRequest
0 голосов
/ 07 марта 2020

Я пытаюсь реализовать универсальный c алгоритм выбора турнира, при котором физическая подготовка населения в среднем повышается, но моя средняя физическая подготовка не меняется. enter image description here

Буду признателен, если кто-нибудь посмотрит на мой код и посоветует, что я делаю неправильно. Вы можете найти код здесь: 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)])))

Ответы [ 2 ]

1 голос
/ 07 марта 2020

Пара замечаний:

Я подозреваю, что в next_generation вы забыли добавить next_generation в свой список глобальных переменных. Как таковая, эта функция ничего не делает.

Поскольку глобальная переменная rerun никогда не изменяется на False, run_generation вы создаете новый набор индивидуумов каждое поколение вместо вычисления следующего поколения. Единственное место, где rerun обновляется, это form_generation, где rerun - это локальная переменная, а не глобальная переменная, но я подозреваю, что это та же ошибка, что и в предыдущем пункте.

Futhermore, Вы должны проверить, если два родителя разные. Как и сейчас, весьма вероятно, что индивид спаривается с самим собой, в результате чего ребенок становится идентичным своему родителю (за исключением случайной мутации).

И, наконец, вам действительно следует избегать использования глобальные, или, по крайней мере, попытаться использовать их только для глобальных констант. Из-за этого очень трудно следить за ходом программы, и, как вы можете видеть, они являются источником всевозможных ошибок.

1 голос
/ 07 марта 2020

Я взглянул на твой код. В этом пункте, турнирSize - это размер каждой группы, верно?

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

Я оставляю вам один генети c, который я реализовал: https://github.com/anigmo97/MUIARFID/blob/master/CUATRIMESTRE_1A/TIA/PROYECTO/algoritmo_gen%C3%A9tico/geneticos.py

Надеюсь, это поможет.

ВАША РЕАЛИЗАЦИЯ

ИНДИВИДУАЛЬНОЕ ПРЕДСТАВИТЕЛЬСТВО

Теперь ваши индивидуумы (переименование в население) составляют список рода. Ваше население - это диктат с ключом (int) и списком значений целых чисел. Если вы думаете об этом, в основном вы используете dict как список. Я рекомендую вам изменить представление населения следующим образом:

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

TO

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

CHANGING

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)])

ИНДИВИДУАЛЬНАЯ ОЦЕНКА

У вас есть список весов для каждого поколения, поэтому у нас есть список, называемый «весами» с length = 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)

...