Skip to content

Commit ab41036

Browse files
IZNN neurons no longer have a simulation time step member; this value is now passed to the Neuron.advance method and the IzNetwork.advance method.
Added common IZNN neuron parameter sets to the iznn module for convenience. Comment & docstring edits.
1 parent 250036a commit ab41036

File tree

4 files changed

+52
-46
lines changed

4 files changed

+52
-46
lines changed

examples/xor/xor2_parallel.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
inter-process communication.
77
88
If your evaluation function is what's taking up most of your processing time
9-
(and you should probably check by using a profiler while running
10-
single-process), you should see a significant performance improvement by
11-
evaluating in parallel.
9+
(and you should check by using a profiler while running single-process),
10+
you should see a significant performance improvement by evaluating in parallel.
1211
1312
This example is only intended to show how to do a parallel experiment
1413
in neat-python. You can of course roll your own parallelism mechanism

examples/xor/xor2_spiking.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
xor_inputs = ((0, 0), (0, 1), (1, 0), (1, 1))
1111
xor_outputs = (0, 1, 1, 0)
1212

13+
# Use fast spiking neurons.
14+
neuron_params = iznn.FAST_SPIKING_PARAMS
1315
# Maximum amount of simulated time (in milliseconds) to wait for the network to produce an output.
1416
max_time = 50.0
15-
# Parameters for "fast spiking" Izhikevich neurons, simulation time step 0.25 millisecond.
16-
iz_params = [0.1, 0.2, -65.0, 2.0, 0.25]
17+
# Use a simulation time step of 0.25 millisecond.
18+
dt = 0.25
1719

1820

1921
def compute_output(t0, t1):
@@ -31,9 +33,8 @@ def compute_output(t0, t1):
3133

3234

3335
def simulate(genome):
34-
# Create a network of Izhikevich neurons based on the given genome.
35-
net = iznn.create_phenotype(genome, *iz_params)
36-
dt = iz_params[-1]
36+
# Create a network of "fast spiking" Izhikevich neurons.
37+
net = iznn.create_phenotype(genome, **neuron_params)
3738
sum_square_error = 0.0
3839
simulated = []
3940
for inputData, outputData in zip(xor_inputs, xor_outputs):
@@ -51,7 +52,7 @@ def simulate(genome):
5152
num_steps = int(max_time / dt)
5253
for j in range(num_steps):
5354
t = dt * j
54-
output = net.advance()
55+
output = net.advance(dt)
5556

5657
# Capture the time and neuron membrane potential for later use if desired.
5758
for i, n in net.neurons.items():
@@ -103,8 +104,9 @@ def run():
103104
winner = pop.statistics.best_genome()
104105
print('\nBest genome:\n{!s}'.format(winner))
105106
print('\nBest network output:')
106-
net = iznn.create_phenotype(winner, *iz_params)
107-
dt = iz_params[-1]
107+
108+
# Create a network of "fast spiking" Izhikevich neurons, simulation time step 0.25 millisecond.
109+
net = iznn.create_phenotype(winner, **neuron_params)
108110
for inputData, outputData in zip(xor_inputs, xor_outputs):
109111
neuron_data = {}
110112
for i, n in net.neurons.items():
@@ -115,12 +117,10 @@ def run():
115117
net.set_inputs(inputData)
116118
t0 = None
117119
t1 = None
118-
v0 = None
119-
v1 = None
120120
num_steps = int(max_time / dt)
121121
for j in range(num_steps):
122122
t = dt * j
123-
output = net.advance()
123+
output = net.advance(dt)
124124

125125
# Capture the time and neuron membrane potential for later use if desired.
126126
for i, n in net.neurons.items():

neat/iznn/__init__.py

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,17 @@
99
http://www.izhikevich.org/publications/spikes.pdf
1010
"""
1111

12+
REGULAR_SPIKING_PARAMS = {'a': 0.02, 'b': 0.20, 'c': -65.0, 'd': 8.00}
13+
INTRINSICALLY_BURSTING_PARAMS = {'a': 0.02, 'b': 0.20, 'c': -55.0, 'd': 4.00}
14+
CHATTERING_PARAMS = {'a': 0.02, 'b': 0.20, 'c': -50.0, 'd': 2.00}
15+
FAST_SPIKING_PARAMS = {'a': 0.10, 'b': 0.20, 'c': -65.0, 'd': 2.00}
16+
THALAMO_CORTICAL_PARAMS = {'a': 0.02, 'b': 0.25, 'c': -65.0, 'd': 0.05}
17+
RESONATOR_PARAMS = {'a': 0.10, 'b': 0.25, 'c': -65.0, 'd': 2.00}
18+
LOW_THRESHOLD_SPIKING_PARAMS = {'a': 0.02, 'b': 0.25, 'c': -65.0, 'd': 2.00}
19+
1220

1321
class Neuron(object):
14-
def __init__(self, bias, a, b, c, d, time_step_msec=1.0):
22+
def __init__(self, bias, a, b, c, d):
1523
"""
1624
a, b, c, d are the parameters of this model.
1725
a: the time scale of the recovery variable.
@@ -20,20 +28,19 @@ def __init__(self, bias, a, b, c, d, time_step_msec=1.0):
2028
d: after-spike reset of the recovery variable.
2129
2230
The following parameters produce some known spiking behaviors:
23-
Regular spiking: a = 0.02, b = 0.2, c = -65.0, d = 8.0
24-
Intrinsically bursting: a = 0.02, b = 0.2, c = -55.0, d = 4.0
25-
Chattering: a = 0.02, b = 0.2, c = -50.0, d = 2.0
26-
Fast spiking: a = 0.1, b = 0.2, c = -65.0, d = 2.0
27-
Thalamo-cortical: a = 0.02, b = 0.25, c = -65.0, d = 0.05
28-
Resonator: a = 0.1, b = 0.25, c = -65.0, d = 2.0
29-
Low-threshold spiking: a = 0.02, b = 0.25, c = -65, d = 2.0
31+
Regular spiking: a = 0.02, b = 0.2, c = -65.0, d = 8.0
32+
Intrinsically bursting: a = 0.02, b = 0.2, c = -55.0, d = 4.0
33+
Chattering: a = 0.02, b = 0.2, c = -50.0, d = 2.0
34+
Fast spiking: a = 0.1, b = 0.2, c = -65.0, d = 2.0
35+
Thalamo-cortical: a = 0.02, b = 0.25, c = -65.0, d = 0.05
36+
Resonator: a = 0.1, b = 0.25, c = -65.0, d = 2.0
37+
Low-threshold spiking: a = 0.02, b = 0.25, c = -65.0, d = 2.0
3038
"""
3139
self.a = a
3240
self.b = b
3341
self.c = c
3442
self.d = d
3543
self.bias = bias
36-
self.dt_msec = time_step_msec
3744

3845
# Membrane potential (millivolts).
3946
self.v = self.c
@@ -44,9 +51,9 @@ def __init__(self, bias, a, b, c, d, time_step_msec=1.0):
4451
self.output = 0.0
4552
self.current = self.bias
4653

47-
def advance(self):
54+
def advance(self, dt_msec):
4855
"""
49-
Advances simulation time by 1 ms.
56+
Advances simulation time by the given time step in milliseconds.
5057
5158
v' = 0.04 * v^2 + 5v + 140 - u + I
5259
u' = a * (b * v - u)
@@ -59,9 +66,9 @@ def advance(self):
5966
# TODO: The need to catch overflows indicates that the current method is
6067
# not stable for all possible network configurations and states.
6168
try:
62-
self.v += 0.5 * self.dt_msec * (0.04 * self.v ** 2 + 5 * self.v + 140 - self.u + self.current)
63-
self.v += 0.5 * self.dt_msec * (0.04 * self.v ** 2 + 5 * self.v + 140 - self.u + self.current)
64-
self.u += self.dt_msec * self.a * (self.b * self.v - self.u)
69+
self.v += 0.5 * dt_msec * (0.04 * self.v ** 2 + 5 * self.v + 140 - self.u + self.current)
70+
self.v += 0.5 * dt_msec * (0.04 * self.v ** 2 + 5 * self.v + 140 - self.u + self.current)
71+
self.u += dt_msec * self.a * (self.b * self.v - self.u)
6572
except OverflowError:
6673
# Reset without producing a spike.
6774
self.v = self.c
@@ -97,18 +104,19 @@ def __init__(self, neurons, inputs, outputs, connections):
97104
self.currents = [0.0] * (1 + max_node)
98105

99106
def set_inputs(self, inputs):
107+
"""Assign input voltages and reset currents to zero."""
100108
assert len(inputs) == len(self.inputs)
101109
for i, v in zip(self.inputs, inputs):
102110
self.currents[i] = 0.0
103111
self.neurons[i].current = 0.0
104112
self.neurons[i].output = v
105113

106114
def reset(self):
107-
# Reset all neurons.
115+
"""Reset all neurons to their default state."""
108116
for i, n in self.neurons.items():
109117
n.reset()
110118

111-
def advance(self):
119+
def advance(self, dt_msec):
112120
# Initialize all non-input neuron currents to the bias value.
113121
for i, n in self.neurons.items():
114122
if i not in self.inputs:
@@ -121,12 +129,12 @@ def advance(self):
121129
for i, n in self.neurons.items():
122130
if i not in self.inputs:
123131
n.current = self.currents[i]
124-
n.advance()
132+
n.advance(dt_msec)
125133

126134
return [self.neurons[i].output for i in self.outputs]
127135

128136

129-
def create_phenotype(genome, a, b, c, d, time_step_msec=1.0):
137+
def create_phenotype(genome, a, b, c, d):
130138
""" Receives a genome and returns its phenotype (a neural network) """
131139

132140
neurons = {}
@@ -135,7 +143,7 @@ def create_phenotype(genome, a, b, c, d, time_step_msec=1.0):
135143
for ng in genome.node_genes.values():
136144
# TODO: It seems like we should have a separate node gene implementation
137145
# that optionally encodes more (all?) of the Izhikevich model parameters.
138-
neurons[ng.ID] = Neuron(ng.bias, a, b, c, d, time_step_msec)
146+
neurons[ng.ID] = Neuron(ng.bias, a, b, c, d)
139147
if ng.type == 'INPUT':
140148
inputs.append(ng.ID)
141149
elif ng.type == 'OUTPUT':

tests/test_iznn.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,26 @@
55

66

77
def test_basic():
8-
n = iznn.Neuron(10, 0.02, 0.2, -65.0, 8.0)
8+
n = iznn.Neuron(10, **iznn.REGULAR_SPIKING_PARAMS)
99
spike_train = []
1010
for i in range(1000):
1111
spike_train.append(n.v)
12-
n.advance()
12+
n.advance(0.25)
1313

1414

1515
def test_network():
16-
neurons = {0: iznn.Neuron(0, 0.02, 0.2, -65.0, 8.0),
17-
1: iznn.Neuron(0, 0.02, 0.2, -65.0, 8.0),
18-
2: iznn.Neuron(0, 0.02, 0.2, -65.0, 8.0)}
16+
neurons = {0: iznn.Neuron(0, **iznn.INTRINSICALLY_BURSTING_PARAMS),
17+
1: iznn.Neuron(0, **iznn.CHATTERING_PARAMS),
18+
2: iznn.Neuron(0, **iznn.FAST_SPIKING_PARAMS),
19+
3: iznn.Neuron(0, **iznn.LOW_THRESHOLD_SPIKING_PARAMS)}
1920
inputs = [0, 1]
2021
outputs = [2]
2122
connections = [(0, 2, 0.123), (1, 2, 0.234)]
2223

2324
net = iznn.IzNetwork(neurons, inputs, outputs, connections)
2425
net.set_inputs([1.0, 0.0])
25-
net.advance()
26-
net.advance()
26+
net.advance(0.25)
27+
net.advance(0.25)
2728

2829

2930
def test_iznn_evolve():
@@ -35,8 +36,6 @@ def test_iznn_evolve():
3536

3637
# Maximum amount of simulated time (in milliseconds) to wait for the network to produce an output.
3738
max_time = 50.0
38-
# Parameters for "fast spiking" Izhikevich neurons, simulation time step 0.25 millisecond.
39-
iz_params = [0.1, 0.2, -65.0, 2.0, 0.25]
4039

4140
def compute_output(t0, t1):
4241
'''Compute the network's output based on the "time to first spike" of the two output neurons.'''
@@ -53,8 +52,8 @@ def compute_output(t0, t1):
5352

5453
def simulate(genome):
5554
# Create a network of Izhikevich neurons based on the given genome.
56-
net = iznn.create_phenotype(genome, *iz_params)
57-
dt = iz_params[-1]
55+
net = iznn.create_phenotype(genome, **iznn.THALAMO_CORTICAL_PARAMS)
56+
dt = 0.25
5857
sum_square_error = 0.0
5958
simulated = []
6059
for inputData, outputData in zip(xor_inputs, xor_outputs):
@@ -72,7 +71,7 @@ def simulate(genome):
7271
num_steps = int(max_time / dt)
7372
for j in range(num_steps):
7473
t = dt * j
75-
output = net.advance()
74+
output = net.advance(dt)
7675

7776
# Capture the time and neuron membrane potential for later use if desired.
7877
for i, n in net.neurons.items():
@@ -125,7 +124,7 @@ def eval_fitness(genomes):
125124

126125
# Verify network output against training data.
127126
print('\nBest network output:')
128-
net = iznn.create_phenotype(winner, *iz_params)
127+
net = iznn.create_phenotype(winner, **iznn.RESONATOR_PARAMS)
129128
sum_square_error, simulated = simulate(winner)
130129

131130
repr(winner)

0 commit comments

Comments
 (0)