Реализация NEAT для очень простого бесконечного раннера в PygamePython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Реализация NEAT для очень простого бесконечного раннера в Pygame

Сообщение Anonymous »

Я пытаюсь реализовать NEAT в очень простой бесконечной игре-раннере. Я создал игру по учебнику Pygame (). Хотя я внес немало изменений, основная игра осталась прежней. Это простая 2D-игра с бесконечным раннером, в которой вы можете управлять игроком (квадратом), перемещать его влево или вправо и прыгать. Справа появляется ряд других квадратов, и вы получаете очко каждый раз, когда впервые перепрыгиваете через препятствие.
Приносим извинения, если формат вопроса не тот. должно быть, я новичок в этой платформе.
После внедрения NEAT
Фитнесс повышается на очень небольшую величину после первого поколения, но с этого момента оно становится почти полностью случайным. Я провел несколько сеансов по 50 поколений (каждый из 50 размеров популяции) и заметил, что к концу средняя приспособленность популяции, кажется, увеличивается, но вот в чем дело: это совершенно случайно. НС развивается, чтобы выполнять эти случайные действия в цикле, и добивается от этого определенного успеха, и считает, что это правильно. Он не понимает, что ему следует избегать квадратов (препятствий). Некоторые геномы выглядят так, будто понимают, что им нужно избегать препятствий, но они не выбираются, поскольку выбираются более случайные геномы с повторяющимися шаблонами, поскольку они, по чистой случайности?, в конечном итоге получают более высокий показатель приспособленности.
В настоящее время я предоставляю 9 входных данных (хотя я пробовал увеличивать и уменьшать их):
Позиция игрока по x и y.
Расстояние по оси X между позициями игрока и препятствия (для всех 3 препятствия, в любой момент времени может быть только 3 препятствия)
Расстояние x между игроком и позициями препятствия.
Флаг, указывающий, что игрок «безопасен» (он безопасен, когда прыгает и находится над препятствиями).
Вот весь код:
import pygame
import random
import neat
import pickle
import time

pygame.init()

# Colors
white = (255, 255, 255)
black = (0, 0, 0)
green = (0, 255, 0)
red = (255, 0, 0)
orange = (255, 165, 0)
yellow = (255, 255, 0)

# Screen size
WIDTH = 450
HEIGHT = 300

# Screen
screen = pygame.display.set_mode([WIDTH, HEIGHT])
pygame.display.set_caption("ML project")
background = black
fps = 60

font = pygame.font.Font('freesansbold.ttf', 16)
timer = pygame.time.Clock()

# NEAT configuration
def eval_genomes(genomes, config):
global running
for genome_id, genome in genomes:
net = neat.nn.FeedForwardNetwork.create(genome, config)
genome.fitness = 0

player_x = 50
player_y = 200
y_change = 0
x_change = 0
gravity = 1
# obstacles = [300, 450, 600]
ranges = [(300, 320), (400, 450), (500, 600)]
obstacles = [random.randint(start, end) for start, end in ranges]
obstacles_speed = 3
active = True
score = 0
genome_running = True
jump_penalty = 0
last_jump_time = time.time()
jump_delay = 0.35
start_time = time.time()
move_reward = 0
once_only = [True, True, True]
inAir = False
jump_once = True
collision_logged = True

while genome_running:
survival_time = time.time() - start_time
bonus = survival_time * 0.5

timer.tick(fps)
screen.fill(background)

distance_bw0 = obstacles[0] - player_x
distance_bw1 = obstacles[1] - player_x
distance_bw2 = obstacles[2] - player_x

# normalized_neg1_to_1 = 1 - (distance_bw0 / WIDTH)
# normalized_neg1_to_1 = normalized_neg1_to_1 * 2 - 1

# twonormalized_neg1_to_1 = 1 - (distance_bw1 / WIDTH)
# twonormalized_neg1_to_1 = twonormalized_neg1_to_1 * 2 - 1

# threenormalized_neg1_to_1 = 1 - (distance_bw2 / WIDTH)
# threenormalized_neg1_to_1 = threenormalized_neg1_to_1 * 2 - 1

distance_bw0y = 200 - player_y
distance_bw1y = 200 - player_y
distance_bw2y = 200 - player_y

if not active:
instruction_text = font.render('SpaceBar to Start', True, white, black)
screen.blit(instruction_text, (150, 50))
instruction_text = font.render('SpaceBar to jump, left and right keys to move', True, white, black)
screen.blit(instruction_text, (65, 90))

score_text = font.render(f'Score: {score}', True, white, black)
screen.blit(score_text, (180, 240))

score_text = font.render(f'Fitness: {int(genome.fitness)}', True, white, black)
screen.blit(score_text, (180, 260))

score_text = font.render(f'Bonus for time: {round(bonus, 3)}', True, white, black)
screen.blit(score_text, (180, 280))

# score_text = font.render(f'hmm : {obstacles[0]}', True, white, black)
# screen.blit(score_text, (180, 270))

pos_text = font.render(f'Obstacle1x: {distance_bw0} Obstacle2x: {distance_bw1} Obstacle3x: {distance_bw2} ', True, white, black)
screen.blit(pos_text, (10, 50))

pos_text = font.render(f'Obstacle1y: {distance_bw0y} Obstacle2y: {distance_bw1y} Obstacle3y: {distance_bw2y} ', True, white, black)
screen.blit(pos_text, (10, 30))

pos_text = font.render(f'Safe: {"Yes" if inAir else "No"}', True, white, black)
screen.blit(pos_text, (10, 10))

floor = pygame.draw.rect(screen, white, [0, 220, WIDTH, 5])
player = pygame.draw.rect(screen, green, [player_x, player_y, 20, 20])

obstacle0 = pygame.draw.rect(screen, red, [obstacles[0], 200, 20, 20])
obstacle1 = pygame.draw.rect(screen, yellow, [obstacles[1], 200, 20, 20])
obstacle2 = pygame.draw.rect(screen, orange, [obstacles[2], 200, 20, 20])

for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
genome_running = False

if active:
output = net.activate([player_x, player_y, distance_bw0, distance_bw1, distance_bw2, distance_bw0y,
distance_bw1y, distance_bw2y, inAir])
# output = net.activate([player_x, player_y, distance_bw0, distance_bw1, distance_bw2])

current_time = time.time()

if output[0] > 0.5:
if y_change == 0 and (current_time - last_jump_time) > jump_delay:
y_change = 18
last_jump_time = current_time

if output[1] > 0.5 and output[2] < 0.5:
x_change = -4
# genome.fitness += 0.25

elif output[2] > 0.5 and output[1] < 0.5:
x_change = 4
# genome.fitness += 0.25

elif output[3] > 0.5 and output[1] < 0.5 and output[2] < 0.5:
pass

for i in range(len(obstacles)):
obstacles -= obstacles_speed
if obstacles < player_x and once_only:
score += 1
genome.fitness += 1
once_only = False

if obstacles < -20:
obstacles = random.randint(470, 570)
once_only = True

if player.colliderect(obstacle0) or player.colliderect(obstacle1) or player.colliderect(obstacle2) or player_x == 0 or player_x == 430 and collision_logged:
active = False
genome.fitness -= 1
genome.fitness += bonus
genome_running = False
print(f"Collision! Genome {genome_id} fitness: {round(genome.fitness, 3)} Score {score}")
collision_logged = False

# if output[0] < 0.5:
# x_change = 0

# if output[1] < 0.5:
# x_change = 0

if output[0] 200:
player_y = 200
jump_once = True

if player_y == 200 and y_change < 0:
y_change = 0
jump_once = True

if player_y > 170:
inAir = False
else:
inAir = True

pygame.display.flip()

# genome.fitness += jump_penalty
# genome.fitness += move_reward

config_path = "file.txt"
config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction,
neat.DefaultSpeciesSet, neat.DefaultStagnation,
config_path)

p = neat.Population(config)

p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)

winner = p.run(eval_genomes, 50)

with open('winner.pkl', 'wb') as f:
pickle.dump(winner, f)
print("Training completed. Best genome saved.")

pygame.quit()

А вот файл конфигурации:
[NEAT]
fitness_criterion = max
fitness_threshold = 400
pop_size = 20
reset_on_extinction = False

[DefaultStagnation]
species_fitness_func = max
max_stagnation = 20
species_elitism = 2

[DefaultReproduction]
elitism = 2
survival_threshold = 0.2

[DefaultGenome]
# node activation options
activation_default = relu
activation_mutate_rate = 1.0
activation_options = relu

# node aggregation options
aggregation_default = sum
aggregation_mutate_rate = 0.0
aggregation_options = sum

# node bias options
bias_init_mean = 3.0
bias_init_stdev = 1.0
bias_max_value = 30.0
bias_min_value = -30.0
bias_mutate_power = 0.5
bias_mutate_rate = 0.7
bias_replace_rate = 0.1

# genome compatibility options
compatibility_disjoint_coefficient = 1.0
compatibility_weight_coefficient = 0.5

# connection add/remove rates
conn_add_prob = 0.5
conn_delete_prob = 0.5

# connection enable options
enabled_default = True
enabled_mutate_rate = 0.01

feed_forward = True
initial_connection = full_direct

# node add/remove rates
node_add_prob = 0.2
node_delete_prob = 0.2

# network parameters
num_hidden = 1
num_inputs = 9
num_outputs = 4

# node response options
response_init_mean = 1.0
response_init_stdev = 0.0
response_max_value = 30.0
response_min_value = -30.0
response_mutate_power = 0.0
response_mutate_rate = 0.0
response_replace_rate = 0.0

# connection weight options
weight_init_mean = 0.0
weight_init_stdev = 1.0
weight_max_value = 30
weight_min_value = -30
weight_mutate_power = 0.5
weight_mutate_rate = 0.8
weight_replace_rate = 0.1

[DefaultSpeciesSet]
compatibility_threshold = 3.0


Подробнее здесь: https://stackoverflow.com/questions/788 ... -in-pygame
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»