Skip to content

Instantly share code, notes, and snippets.

@michaelmelanson
Created January 20, 2009 23:49
Show Gist options
  • Save michaelmelanson/49750 to your computer and use it in GitHub Desktop.
Save michaelmelanson/49750 to your computer and use it in GitHub Desktop.
#
# I was learning about Hebbian learning and figured, why not make an artifical neural network
# based on it? Actually, I should have been preparing a presentation on synaptic plasticity, and
# this seemed more interesting. At any rate, here it is.
#
# It doesn't work because of the limitations of Hebb's model, namely that
# at some point the network "discovers" something that sort of works, and from then on it feeds
# back on itself until the synaptic weights enter a positive feedback loop and cascade to
# infinity.
#
# I hereby release the code below into the public domain.
#
import scipy
import math
import pygame
from pygame.locals import *
NEURONS = 100
RATE_MIXING_FACTOR = 0.0001
ACTIVATION_FACTOR = 1.0
MAX_RATE = 0.01
INPUTS = {
'player_x': 10,
'player_y': 20,
'computer_x': 30,
'computer_y': 40
}
OUTPUTS = {
'computer_x': 50,
'computer_y': 60
}
weights = scipy.random.normal(loc=0.0, scale=0.01, size=(NEURONS, NEURONS))
activation = scipy.zeros(NEURONS)
running = True
player_x = 50
player_y = 100
computer_x = 150.0
computer_y = 100.0
learning_rate = 0.1
def sigmoid(x): return 1.0 / (1.0 + math.exp(-x))
def calc_distance():
global computer_x, computer_y
global player_x, player_y
return math.sqrt(math.pow(computer_x - float(player_x), 2) +
math.pow(computer_y - float(player_y), 2))
distance = calc_distance()
def update_player():
global player_x, player_y
keys = pygame.key.get_pressed()
if keys[K_UP]: player_y -= 1
if keys[K_DOWN]: player_y += 1
if keys[K_LEFT]: player_x -= 1
if keys[K_RIGHT]: player_x += 1
def solve_network():
global activation
global weights
new_activation = activation
for i in xrange(NEURONS):
for j in xrange(NEURONS):
if i != j:
new_activation[i] += activation[j] * weights[i,j]
# This is a hack to constrain activation
activation = new_activation / scipy.mean(new_activation)
def train_network():
global weights
# Add some noise to the weights
weights += scipy.random.normal(loc=0.0, scale=0.01, size=(NEURONS,NEURONS))
for i in xrange(NEURONS):
for j in xrange(NEURONS):
if i != j:
weights[i,j] += learning_rate * activation[i] * activation[j]
def update_computer():
global activation
global player_x, player_y
global computer_x, computer_y
global learning_rate
global distance
def mix(n, x):
activation[n] = ((sigmoid(x) * ACTIVATION_FACTOR) +
(activation[n] * (1.0 - ACTIVATION_FACTOR)))
mix(INPUTS['player_x'], float(player_x))
mix(INPUTS['player_y'], float(player_y))
mix(INPUTS['computer_x'], computer_x)
mix(INPUTS['computer_y'], computer_y)
solve_network()
w = 1.0 / (abs(activation[OUTPUTS['computer_x']]) +
abs(activation[OUTPUTS['computer_y']]))
dx = w * activation[OUTPUTS['computer_x']]
dy = w * activation[OUTPUTS['computer_y']]
computer_x += dx
computer_y += dy
old_distance = distance
distance = calc_distance()
if distance < old_distance:
f = 0.01
else:
f = -0.01
learning_rate = (learning_rate * 0.5) + (f * 0.5)
train_network()
global learning_rate, weights
global player_x, player_y
global computer_x, computer_y
print '--------------------------------------------------------'
print 'player:', (player_x, player_y)
print 'computer:', (computer_x, computer_y)
print 'learning rate:', learning_rate
#print 'rate delta:', delta
print 'deltas:', (dx,dy)
print activation
print weights
def update_game():
update_player()
update_computer()
if __name__ == '__main__':
pygame.init()
pygame.display.init()
surface = pygame.display.set_mode((300,200), DOUBLEBUF)
while running:
pygame.event.pump()
update_game()
surface.fill((255,255,255))
pygame.draw.circle(surface, (255,0,0), (int(computer_x), int(computer_y)), 5)
pygame.draw.circle(surface, (0,0,255), (player_x, player_y), 5)
pygame.display.flip()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment