This commit is contained in:
2019-10-23 16:38:50 +02:00
parent 80319712d0
commit 8511af2e2c
5 changed files with 83 additions and 44 deletions

View File

@@ -14,9 +14,14 @@ class Neural_Network(object):
self.fitness = 0 self.fitness = 0
#weights #weights
if not W1 : if W1 is not None:
self.W1=W1
else :
self.W1 = np.random.randn(self.inputSize, self.hiddenSize) # weights from input to hidden layer self.W1 = np.random.randn(self.inputSize, self.hiddenSize) # weights from input to hidden layer
if not W2 :
if W2 is not None:
self.W2=W2
else :
self.W2 = np.random.randn(self.hiddenSize, self.outputSize) # weights from hidden to output layer self.W2 = np.random.randn(self.hiddenSize, self.outputSize) # weights from hidden to output layer
# self.w1 = [[random.random() for i in range(self.hiddenSize)] for i in range(self.inputSize)] # self.w1 = [[random.random() for i in range(self.hiddenSize)] for i in range(self.inputSize)]
# self.w2 = [[random.random() for i in range(self.outputSize)] for i in range(self.hiddenSize)] # self.w2 = [[random.random() for i in range(self.outputSize)] for i in range(self.hiddenSize)]

31
car.py
View File

@@ -1,4 +1,5 @@
import numpy as np import numpy as np
import random
import pygame import pygame
from brain import Neural_Network from brain import Neural_Network
@@ -9,7 +10,7 @@ IMG = pygame.image.load("car20.png")#.convert()
class Car(pygame.sprite.Sprite): class Car(pygame.sprite.Sprite):
def __init__(self): def __init__(self, brain=None):
pygame.sprite.Sprite.__init__(self) pygame.sprite.Sprite.__init__(self)
self.top_surface = pygame.Surface((CAR_SIZE, CAR_SIZE)) self.top_surface = pygame.Surface((CAR_SIZE, CAR_SIZE))
self.original_image = IMG self.original_image = IMG
@@ -21,9 +22,6 @@ class Car(pygame.sprite.Sprite):
self.rect = self.image.get_rect() self.rect = self.image.get_rect()
self.rect.center = (75, GY -50) self.rect.center = (75, GY -50)
self.speed = 1
self.heading = 0
self.heading_change = 0
self.vision_length = VISION_LENGTH # line liength self.vision_length = VISION_LENGTH # line liength
self.vision_span = VISION_SPAN # degrees self.vision_span = VISION_SPAN # degrees
self.draw_sensors = True self.draw_sensors = True
@@ -41,12 +39,20 @@ class Car(pygame.sprite.Sprite):
self.sensors = [self.left_sensor, self.center_sensor, self.right_sensor] self.sensors = [self.left_sensor, self.center_sensor, self.right_sensor]
self.probes = [self.vision_length] *3 self.probes = [self.vision_length] *3
if brain :
self.brain = brain
else :
self.brain = Neural_Network() self.brain = Neural_Network()
self.reset_car_pos()
self.update_sensors() self.update_sensors()
self.probe_brain() self.probe_brain()
self.run = True self.run = True
def reset_car_pos(self):
self.speed = 1
self.heading = 0
self.heading_change = random.random() * 30
def update_sensors(self): def update_sensors(self):
center = self.rect.center center = self.rect.center
@@ -83,7 +89,8 @@ class Car(pygame.sprite.Sprite):
if dist < 1.2 * self.speed or self.speed < 0.01 : if dist < 1.2 * self.speed or self.speed < 0.01 :
self.run = False self.run = False
self.speed = 0 self.speed = 0
print(f'Car {id(self)} crashed') # print(f'Car {id(self)} crashed')
return
# else : # else :
# self.probes[idx] = self.vision_length * 2 # self.probes[idx] = self.vision_length * 2
@@ -106,13 +113,13 @@ class Car(pygame.sprite.Sprite):
if self.speed < 0.01 : if self.speed < 0.01 :
self.run = False self.run = False
print(f'Car {id(self)} crashed') print(f'Car {id(self)} crashed')
print( # print(
'id', id(self), # 'id', id(self),
'Speed', self.speed, # 'Speed', self.speed,
'heading', self.heading, # 'heading', self.heading,
'throttle', self.throttle, # 'throttle', self.throttle,
'heading change', self.heading_change, # 'heading change', self.heading_change,
) # )
if self.speed : if self.speed :
self.heading += self.heading_change * CAR_STEERING_FACTOR / self.speed self.heading += self.heading_change * CAR_STEERING_FACTOR / self.speed

View File

@@ -10,7 +10,7 @@ def genetic_selection(brains):
# proportionnally to its relative fitness # proportionnally to its relative fitness
wheel = [] wheel = []
for b in brains : for b in brains :
wheel += [b] * b.brains wheel += [b] * b.fitness
tot_fitness = len(wheel) tot_fitness = len(wheel)
@@ -19,7 +19,11 @@ def genetic_selection(brains):
# selection of pool/2 pair of parents to reproduce # selection of pool/2 pair of parents to reproduce
parents_pool = [] parents_pool = []
for _ in range(half_pop): for _ in range(half_pop):
parents_pool.append([round(random.random()*tot_fitness), round(random.random()*tot_fitness)]) parents_pool.append([
wheel[round(random.random()*tot_fitness)],
wheel[round(random.random()*tot_fitness)]
])
return parents_pool
def cross_mutate_genes(p1_gene, p2_gene): def cross_mutate_genes(p1_gene, p2_gene):
@@ -28,15 +32,15 @@ def cross_mutate_genes(p1_gene, p2_gene):
p2_gene = list(p1_gene) p2_gene = list(p1_gene)
for idx,x in enumerate(p2_gene): for idx,x in enumerate(p2_gene):
if random.random() > 0.5 : if random.random() > 0.5 :
choice = p1_gene choice = p1_gene[idx]
else : else :
choice = p2_gene choice = p2_gene[idx]
# Mutation # Mutation
if random.random() < 0.005 : if random.random() < 0.005 :
choice[random.randint(0, len(choice - 1))] = random.random() choice[random.randint(0, len(choice) - 1)] = random.random()
print("Mutation !") print("Mutation !")
child.append(np.array(choice)) child.append(choice)
return child return np.array(child)
def genetic_reproduction(parents_pool): def genetic_reproduction(parents_pool):

39
main.py
View File

@@ -2,13 +2,17 @@
import math import math
import pygame import pygame
import random import random
import time
from car import Car from car import Car
from genetics import genetic_selection, genetic_reproduction
from maps import map1 from maps import map1
from params import CELL_COLOR, screen from params import CELL_COLOR, screen
#https://medium.com/intel-student-ambassadors/demystifying-genetic-algorithms-to-enhance-neural-networks-cde902384b6e #https://medium.com/intel-student-ambassadors/demystifying-genetic-algorithms-to-enhance-neural-networks-cde902384b6e
clock = pygame.time.Clock()
map_lines = map1 map_lines = map1
@@ -19,12 +23,12 @@ all_cars = pygame.sprite.Group()
for x in range(100): for x in range(100):
car = Car() car = Car()
car.heading = x * 30 + 35
all_cars.add(car) all_cars.add(car)
clock = pygame.time.Clock()
running_cars = True def run_round(all_cars):
while running_cars : running_cars = True
while running_cars :
running_cars = False running_cars = False
screen.fill(CELL_COLOR) screen.fill(CELL_COLOR)
all_cars.draw(screen) all_cars.draw(screen)
@@ -39,13 +43,32 @@ while running_cars :
for line in map_lines : for line in map_lines :
pygame.draw.line(screen, (255,255,255), line[0], line[1]) pygame.draw.line(screen, (255,255,255), line[0], line[1])
pygame.display.flip() pygame.display.flip()
clock.tick(24) clock.tick(48)
# for c in all_cars :
# print(f"Car {id(c)} Fitness : {c.brain.fitness})")
print('Collecting brains')
brains = [c.brain for c in all_cars]
print(f"Max fitness = {max([b.fitness for b in brains])}" )
print(f"Avg fitness = {sum([b.fitness for b in brains])/len(brains)}" )
print('selecting')
parents_pool = genetic_selection(brains)
# import ipdb; ipdb.set_trace()
print("breeding")
new_brains = genetic_reproduction(parents_pool)
print(f'building {len(new_brains)} cars with new brains')
all_cars.empty()
for b in new_brains :
all_cars.add(Car(brain=b))
print("Waiting 5 secs before new run")
for x in range(10) :
time.sleep(0.5)
pygame.display.flip()
for c in all_cars :
print(f"Car {id(c)} Fitness : {c.brain.fitness})")
while True : while True :
run_round(all_cars)
pygame.display.flip() pygame.display.flip()
clock.tick(24) clock.tick(24)

View File

@@ -10,7 +10,7 @@ CAR_SIZE = 20
CAR_MAX_SPEED = 7 CAR_MAX_SPEED = 7
CAR_STEERING_FACTOR = 10 CAR_STEERING_FACTOR = 10
VISION_LENGTH = 50 VISION_LENGTH = 50
VISION_SPAN = 25 # degrees VISION_SPAN = 35 # degrees
THROTTLE_POWER = 3 THROTTLE_POWER = 3