Created
September 30, 2013 17:03
-
-
Save lesguillemets/6766833 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# encoding:utf-8 | |
import random | |
class Neuron(object): | |
# 神経細胞体 class. | |
# i) synapse からの入力を受けることができ, | |
# ii) ある間にうけた入力の総和が threshold を超えれば | |
# iii) 発火し,本人から出ていく synapse に伝達される. | |
# Neuron 同士の結合情報は Synapse class, NSystem class に任せ, | |
# Neuron class から能動的に特定のシナプスに情報を与えることはない. | |
# ... はずだったが, | |
# postsnapses に PostNeuron を '持つ' ことに. | |
def __init__(self, threshold = 1): | |
self.threshold = threshold | |
self.inputstack = 0 | |
self.isfiring = False | |
self.wasfiring = False | |
self.isalive = True | |
self.postsynapses = [] | |
def getinput(self, x): | |
# 大きさ x の入力を受ける. | |
# 入力は self.inputstack に蓄えられ,'1 世代' の入力となる | |
self.inputstack += x | |
def update(self): | |
self.wasfiring = self.isfiring | |
self.isfiring = self.doesfire() | |
self.clear() | |
def add_synapse(postneuron, x): | |
self.postsnapses.append(Synapse(postneuron, x)) | |
def clear(self): | |
# inputstack を空に.次の'世代'の入力を受けられる | |
self.inputstack = 0 | |
def doesfire(self): | |
# 発火するか | |
return self.inputstack >= self.threshold | |
def __repr__(self): | |
return int(self.isfiring) | |
def __str__(self): | |
return str(int(self.isfiring)) | |
class Synapse(object): | |
# シナプス class. | |
# 結合元 neuron に保持され, 結合先 neuron を保持する. | |
# pre-synaptic cell の fire に対し, | |
# {x <- R | -limit <= x <= limit } を満たす出力を | |
# post-synaptic cell に与える. | |
# 両端が active になるとき LTPratio を x に乗じる形での学習を行う. | |
# active な入力を受けても出力先が active にならなかった場合は逆を行う. | |
def __init__(self, postn, x, | |
limit = 2, LTPratio = 1.1, forgetratio = 0.95, isactive = True): | |
self.postn = postn | |
self.x = x | |
self.limit = 2 | |
self.isactive = True | |
self.LTPratio = LTPratio | |
self.forgetratio = forgetratio | |
def givefire(self): | |
if self.isactive: | |
self.postn.getinput(self.x) | |
def LTP(self): | |
# this function doesn't check if LTP can occur or not. | |
# because Synapse class doesn't know whether | |
# its postneuron fires or not. | |
self.x *= self.LTPratio | |
if not -self.limit > self.x: | |
self.x = -self.limit | |
elif self.x < self.limit: | |
self.x = self.limit | |
def reverseLTP(self): | |
self.x /= self.LTPratio | |
def forgetalittle(self): | |
self.x *= self.forgetratio | |
class NSystem(object): | |
def __init__(self, number_of_neurons, inneurons, outneurons): | |
# number_of_neurons :: Int, inneurons :: [Int], outneurons :: [Int] | |
self.neurons = [] # neurons in the system | |
self.inneurons = [] # neurons to (conveniently) receive input from us. | |
self.outneurons = [] # neurons from which we get output. | |
self.n_of_neurons = number_of_neurons | |
for i in xrange(number_of_neurons): | |
self.neurons.append(Neuron()) | |
for n in inneurons: | |
self.inneurons.append( self.neurons[n] ) | |
for n in outneurons: | |
self.outneurons.append( self.neurons[n] ) | |
def init_perfect(self): | |
# good luck memory | |
self.synapses = [] | |
for (i, preneuron) in enumerate(self.neurons): | |
self.synapses.append([]) | |
for (j, postneuron) in enumerate(self.neurons): | |
self.synapses[i].append( | |
Synapse(preneuron, postneuron, random.random())) | |
for i in xrange(self.n_of_neurons): | |
self.synapses[i][i].isactive = False | |
def step(self): | |
# if a neuron is firing, its postsynapses gives fire. | |
for neuron in self.neurons: | |
if neuron.isfiring: | |
for synapse in neuron.postsynapses: | |
synapse.givefire() | |
# updates the states of the neurons. | |
for neuron in self.neurons: | |
neuron.update() | |
# LTP: for each synapse, | |
# if the two neurons at its ends is/was firing, | |
# let its LTP occur. | |
# preneuron.wasfiring and not postneuron.isfiring | |
# -> reversed LTP (LTD). | |
for neuron in self.neurons: | |
if neuron.wasfiring: | |
for synapse in neuron.postsynapses: | |
if synapse.postn.isfiring: | |
synapse.LTP() | |
else: | |
synapse.reverseLTP() | |
def give_stimulus(self, xs): | |
for (x,n) in zip(xs, self.inneurons): | |
n.getinput(x) | |
def get_output(self): | |
output = [] | |
for (i,n) in enumerate(self.outneurons): | |
output.append((i, str(n))) | |
return output | |
def example1(): | |
""" | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment