def neural_network_visualizer(genome, config): """ Download and process given neural network into a display-ready image :param genomes: chosen genome to be visualized :type genomes: neat.Population :param config: configuration of the genome to be visualized :type config: neat.ConfigParameter :return: None """ # Global Variable global neural_net_image visualize.draw_net(config, genome, False, fmt='png', filename='best_neural_net') img = Image.open('best_neural_net.png') img = img.convert("RGBA") datas = img.getdata() # Remove White Pixels (Background) newData = [] for item in datas: if item[0] == 255 and item[1] == 255 and item[2] == 255: newData.append((255, 255, 255, 0)) else: newData.append(item) img.putdata(newData) # Resize resize = True basewidth = 200 current_t = time.time() while resize: wpercent = (basewidth / float(img.size[0])) hsize = int((float(img.size[1]) * float(wpercent))) if hsize < (GAME_WIN_HEIGHT - 200): resize = False img = img.resize((basewidth, hsize), Image.ANTIALIAS) break if current_t - time.time() > 10: break basewidth -= 1 img.save("best_neural_net.png", "PNG") # To Display is Ready neural_net_image = pygame.image.load('best_neural_net.png')
def run_experiment(config_file, trial_id, n_generations, out_dir, view_results=False, save_results=True): """ The function to run the experiment against hyper-parameters defined in the provided configuration file. The winner genome will be rendered as a graph as well as the important statistics of neuroevolution process execution. Arguments: config_file: the path to the file with experiment configuration """ # set random seed seed = int(time.time()) random.seed(seed) # Load configuration. config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, config_file) # Create the population, which is the top-level object for a NEAT run. p = neat.Population(config) # Add a stdout reporter to show progress in the terminal. #p.add_reporter(neat.StdOutReporter(True)) stats = neat.StatisticsReporter() p.add_reporter(stats) # Run for up to N generations. best_genome = p.run(eval_genomes, n=n_generations) # Check if the best genome is a winning Sinle-Pole balancing controller #net = neat.nn.FeedForwardNetwork.create(best_genome, config) # Find best genome complexity complexity = len(best_genome.connections) + len(best_genome.nodes) + 4 # four input nodes # Test if solution was found best_genome_fitness = best_genome.fitness # cart.eval_fitness(net, max_bal_steps=max_balancing_steps_num)# solution_found = (best_genome_fitness >= config.fitness_threshold) if solution_found: print("Trial: %2d\tgeneration: %d\tfitness: %f\tcomplexity: %d\tseed: %d" % (trial_id, p.generation, best_genome_fitness, complexity, seed)) else: print("Trial: %2d\tFAILED\t\tfitness: %f\tcomplexity: %d\tseed: %d" % (trial_id, best_genome_fitness, complexity, seed)) # Visualize the experiment results if save_results: node_names = {-1:'x', -2:'dot_x', -3:'θ', -4:'dot_θ', 0:'action_1', 1:'action_2'} visualize.draw_net(config, best_genome, view=view_results, node_names=node_names, directory=out_dir, fmt='svg') visualize.plot_stats(stats, ylog=False, view=view_results, filename=os.path.join(out_dir, 'avg_fitness.svg')) visualize.plot_species(stats, view=view_results, filename=os.path.join(out_dir, 'speciation.svg')) return solution_found, p.generation, complexity, best_genome_fitness
def neural_network_visualizer(genome, config): """ Download and process given neural network into a display-ready image :param genomes: chosen genome to be visualized :type genomes: neat.Population :param config: configuration of the genome to be visualized :type config: neat.ConfigParameter :return: None """ # Global Variable global neural_net_image node_names = {0: 'Jump', -1: 'Bottom P', -2: 'Top P', -3: 'Bird'} visualize.draw_net(config, genome, False, fmt='png', filename='best_neural_net', node_names=node_names) img = Image.open('best_neural_net.png') img = img.convert("RGBA") datas = img.getdata() # Remove White Pixels (Background) newData = [] for item in datas: if item[0] == 255 and item[1] == 255 and item[2] == 255: newData.append((255, 255, 255, 0)) else: newData.append(item) img.putdata(newData) img.save("best_neural_net.png", "PNG") # To Display is Ready neural_net_image = pygame.image.load('best_neural_net.png')
def run_experiment(config_file, trial_id, n_generations, out_dir, view_results=False, save_results=True): """ The function to run XOR experiment against hyper-parameters defined in the provided configuration file. The winner genome will be rendered as a graph as well as the important statistics of neuroevolution process execution. Arguments: config_file: the path to the file with experiment configuration trial_id: the id of current trial run n_generations: the number of evolutionary generations out_dir: the directory to store experiment outputs view_results: the flag to control whether to view result visualizations save_results: the flag to control whether to save resulting stats into files """ # set random seed seed = int(time.time()) random.seed(seed) # Load configuration. config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, config_file) # Create the population, which is the top-level object for a NEAT run. p = neat.Population(config) # Add a stdout reporter to show progress in the terminal. #p.add_reporter(neat.StdOutReporter(True)) stats = neat.StatisticsReporter() p.add_reporter(stats) # Run for up to n_generations generations. best_genome = p.run(eval_genomes, n_generations) # Check if the best genome is an adequate XOR solver net = neat.nn.FeedForwardNetwork.create(best_genome, config) best_genome_fitness = best_genome.fitness # eval_fitness(net) # Find best genome complexity complexity = len(best_genome.connections) + len( best_genome.nodes) + 2 # two input nodes solution_found = best_genome_fitness > config.fitness_threshold if solution_found: print( "Trial: %2d\tgeneration: %d\tfitness: %f\tcomplexity: %d\tseed: %d" % (trial_id, p.generation, best_genome_fitness, complexity, seed)) else: print("Trial: %2d\tFAILED\t\tfitness: %f\tcomplexity: %d\tseed: %d" % (trial_id, best_genome_fitness, complexity, seed)) # Visualize the experiment results if save_results: node_names = {-1: 'A', -2: 'B', 0: 'A XOR B'} visualize.draw_net(config, best_genome, view=view_results, node_names=node_names, directory=out_dir) visualize.plot_stats(stats, ylog=False, view=view_results, filename=os.path.join(out_dir, 'avg_fitness.svg')) visualize.plot_species(stats, view=view_results, filename=os.path.join(out_dir, 'speciation.svg')) return solution_found, p.generation, complexity, best_genome_fitness
def run(config_path): """ Use given configuration path and variables to start teaching the AI to play the game Then visualize the data with the genome containing highest fitness :param config_path: path to the neural :type config_path: int / range[0 -> 99] :return: None """ # Global Variables global hs_genopt_popopt global gen # ------------------------------------------------------------------------- # Load Configuration # ------------------------------------------------------------------------- config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, config_path) # Create Population p = neat.Population(config) # Add StdOut Reporter (Displays Progress in Terminal) p.add_reporter(neat.StdOutReporter(True)) stats = neat.StatisticsReporter() p.add_reporter(stats) """ Save Population in Generation x x = 3 p.add_reporter(neat.Checkpointer(x)) """ # Handle Generation Count of 0 if hs_genopt_popopt[1] < 1: print('Generations set to 1 instead of 0.') hs_genopt_popopt[1] = 1 # Save HighScore Gen. Option and Pop. Option with Pickle with open(os.path.join("utils", "hs_genopt_popopt.txt"), "wb") as fp: # Save Pickle pickle.dump(hs_genopt_popopt, fp) # Reset Gen Count gen = 0 # Run Up to [Gen. Option] Generations winner = p.run(main_ai, hs_genopt_popopt[1]) # We Save Best Genome # ------------------------------------------------------------------------- # Visualize Neural Network, Statistics, and Species # ------------------------------------------------------------------------- node_names = { 0: 'Jump', -1: 'Bottom Pipe Height', -2: 'Top Pipe Height', -3: 'Bird Height' } visualize.draw_net(config, winner, False, fmt='png', filename='best_neural_net', node_names=node_names) # Only Draw if More Than 1 Gen if hs_genopt_popopt[1] > 1: visualize.plot_stats(stats, ylog=False, view=False) visualize.plot_species(stats, view=False) """ Load and Run Saved Checkpoint
def main_ai(genomes, config): """ Play game for AI :param genomes: use different neural networks to play the game :type genomes: neat.Population[] :param config: use different neural networks to play the game :type config: neat.ConfigParameter :return: None """ # Global Variables global FPS global gen global neural_net_image # ------------------------------------------------------------------------- # AI Systen: Neural Network Display # ------------------------------------------------------------------------- neural_network_visualizer(genomes[0][1], config) # Set Birds "Connected" To Its Genome and NN nets = [] ge = [] birds = [] for _, g in genomes: net = neat.nn.FeedForwardNetwork.create(g, config) nets.append(net) birds.append(Bird(230, 350)) g.fitness = 0 ge.append(g) # Set Variables base = Base(730) pipes = [Pipe(600)] win = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) clock = pygame.time.Clock() # Reset Score and Add One Gen score = 0 gen += 1 # Draw Neural Net Once ge_save = ge[0] # ------------------------------------------------------------------------- # Game: Main Game # ------------------------------------------------------------------------- run = True while run: clock.tick(FPS) # Allow only for FPS Frames per Second for event in pygame.event.get(): if event.type == pygame.QUIT: # Save last iteration node_names = { 0: 'Jump', -1: 'Bottom Pipe Height', -2: 'Top Pipe Height', -3: 'Bird Height' } visualize.draw_net( config, genomes[0][1], False, fmt='png', filename='best_neural_net', node_names=node_names) # Save last iteration # Remove Special Vis Files try: os.remove('speciation.svg') os.remove('avg_fitness.svg') except Exception as e: pass run = False pygame.quit() quit() pipe_ind = 0 if len(birds) > 0: if len(pipes) > 1 and birds[ 0].x > pipes[0].x + pipes[0].PIPE_TOP.get_width(): pipe_ind = 1 else: run = False break # ------------------------------------------------------------------------- # AI Systen: Bird Jump # ------------------------------------------------------------------------- for x, bird in enumerate(birds): bird.move() # Move each bird ge[x].fitness += 0.1 # Inputs: Bird Height, Top Pipe Height, Bottom Pipe Height outputs = nets[x].activate( (bird.y, abs(bird.y - pipes[pipe_ind].height), abs(bird.y - pipes[pipe_ind].bottom))) # TanH Function | y > 0.5 if outputs[0] > 0.5: bird.jump() # ------------------------------------------------------------------------- # System: Pipes # ------------------------------------------------------------------------- add_pipe = False rem = [] for pipe in pipes: for x, bird in enumerate(birds): # Bird / Pipe Collision if pipe.collide(bird): ge[x].fitness -= 2 birds.pop(x) nets.pop(x) ge.pop(x) # ------------------------------------------------------------------------- # AI Systen: Neural Network Display # ------------------------------------------------------------------------- if ge != [] and ge[ 0] != ge_save: # Visualize new alive bird neural_network_visualizer(ge[0], config) ge_save = ge[0] if not pipe.passed and pipe.x < bird.x: pipe.passed = True add_pipe = True # Pipe Outside Screen if pipe.x + pipe.PIPE_TOP.get_width() < 0: rem.append(pipe) # Move Pipes pipe.move() # Add New Pipe and 1 to Score if add_pipe: score += 1 # All birds have same x pos if score == 50: print("Perfect bird out here") for g in ge: g.fitness += 2 pipes.append(Pipe(600)) # Remove Outside Pipes To Not Render Them for r in rem: pipes.remove(r) # ------------------------------------------------------------------------- # System: Base / Top Collision # ------------------------------------------------------------------------- for x, bird in enumerate(birds): if bird.y + bird.img.get_height() >= 730 or bird.y < 0: ge[x].fitness -= 2 birds.pop(x) nets.pop(x) ge.pop(x) # ------------------------------------------------------------------------- # AI Systen: Neural Network Display # ------------------------------------------------------------------------- if ge != [] and ge[0] != ge_save: # Visualize new alive bird neural_network_visualizer(ge[0], config) ge_save = ge[0] # Animate Base base.move() # ------------------------------------------------------------------------- # Draw To Screen # ------------------------------------------------------------------------- draw_window_ai(win, birds, pipes, base, score, gen, len(birds), genomes, config)
def draw_window_ai(win, birds, pipes, base, score, gen, birds_alive, genomes, config): """ Draw game using given parameters (AI Game) :param win: window to draw on :type win: UI.Window :param birds: bird to draw :type birds: Bird[] :param pipes: pipes to draw :type pipes: Pipe[] :param base: base to draw :type base: Base :param score: score to draw :type score: int [0 -> infiniti] :param gen: generations to draw :type gen: int [1 -> 99] :param birds_alive: draw how many birds are alive :type birds_alive: int [1 -> 99] :param genomes: visualize neural net when menu button is pressed :type genomes: neat.Population[] :param config: visualize neural net when menu button is pressed :type config: neat.ConfigParameter :return: None """ # Draw Background win.blit(BG_IMG, (0, 0)) # Draw All Pipes for pipe in pipes: pipe.draw(win) # Draw Current Score text = STAT_FONT.render("Score: " + str(score), 1, (255, 255, 255)) win.blit(text, (WIN_WIDTH - 10 - text.get_width(), 10)) # Draw Current Generation text = STAT_FONT.render("Gen: " + str(gen), 1, (255, 255, 255)) win.blit(text, (10, 10)) # Draw Current Number of Birds Alive text = STAT_FONT.render("Alive: " + str(birds_alive), 1, (255, 255, 255)) win.blit(text, (10, 50)) # Return To Menu if Menu Button Pressed if button2.update(): # Save last iteration node_names = { 0: 'Jump', -1: 'Bottom Pipe Height', -2: 'Top Pipe Height', -3: 'Bird Height' } visualize.draw_net(config, genomes[0][1], False, fmt='png', filename='best_neural_net', node_names=node_names) # Remove Special Vis Files try: os.remove('speciation.svg') os.remove('avg_fitness.svg') except Exception as e: pass # Go Back To Menu menu() # Draw Base and Birds base.draw(win) for bird in birds: bird.draw(win) # Draw Top Neural Network text = STAT_FONT_SMALL.render("Best NN: ", 1, (255, 255, 255)) win.blit(text, (10, WIN_HEIGHT - 70 - neural_net_image.get_height() - text.get_height())) # Draw Neural Network win.blit(neural_net_image, (10, WIN_HEIGHT - 70 - neural_net_image.get_height())) # 70 accounts for base # Update the Current Display pygame.display.update()