Skip to content

Commit fa939e3

Browse files
Added softplus activation.
Rescaled some activation functions to have most of their "interesting" behavior confined to [-1, 1]x[-1, 1]. Renamed genome compatibility parameters for clarity. Fixed bug in StatisticsReporter.get_average_fitness. Added TODO comments. Updated XOR config file to look more like re-saved version.
1 parent 08b1abb commit fa939e3

File tree

6 files changed

+64
-46
lines changed

6 files changed

+64
-46
lines changed

examples/xor/xor2_config

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,65 +3,76 @@
33
# The `NEAT` section specifies parameters particular to the NEAT algorithm
44
# or the experiment itself. This is the only required section.
55
[NEAT]
6-
pop_size = 150
7-
max_fitness_threshold = 0.95
6+
max_fitness_threshold = 0.99
7+
pop_size = 1000
88
reset_on_extinction = False
99

1010
[DefaultGenome]
11-
num_inputs = 2
12-
num_hidden = 0
13-
num_outputs = 1
14-
initial_connection = full
15-
feed_forward = 0
16-
# genome compatibility options
17-
compatibility_threshold = 3.0
18-
disjoint_coefficient = 1.0
19-
weight_coefficient = 0.5
20-
# connection add/remove rates
21-
conn_add_prob = 0.5
22-
conn_delete_prob = 0.25
23-
# node add/remove rates
24-
node_add_prob = 0.1
25-
node_delete_prob = 0.05
2611
# node activation options
2712
activation_default = sigmoid
28-
activation_options = sigmoid
2913
activation_mutate_rate = 0.0
14+
activation_options = sigmoid
15+
3016
# node aggregation options
3117
aggregation_default = sum
32-
aggregation_options = sum
3318
aggregation_mutate_rate = 0.0
19+
aggregation_options = sum
20+
3421
# node bias options
3522
bias_init_mean = 0.0
3623
bias_init_stdev = 1.0
37-
bias_replace_rate = 0.1
38-
bias_mutate_rate = 0.7
39-
bias_mutate_power = 0.5
4024
bias_max_value = 30.0
4125
bias_min_value = -30.0
26+
bias_mutate_power = 0.5
27+
bias_mutate_rate = 0.7
28+
bias_replace_rate = 0.1
29+
30+
# genome compatibility options
31+
compatibility_disjoint_coefficient = 1.0
32+
compatibility_threshold = 3.0
33+
compatibility_weight_coefficient = 0.5
34+
35+
# connection add/remove rates
36+
conn_add_prob = 0.5
37+
conn_delete_prob = 0.5
38+
39+
# connection enable options
40+
enabled_default = True
41+
enabled_mutate_rate = 0.01
42+
43+
feed_forward = False
44+
initial_connection = full
45+
46+
# node add/remove rates
47+
node_add_prob = 0.2
48+
node_delete_prob = 0.2
49+
50+
# network parameters
51+
num_hidden = 0
52+
num_inputs = 2
53+
num_outputs = 1
54+
4255
# node response options
4356
response_init_mean = 5.0
4457
response_init_stdev = 0.1
45-
response_replace_rate = 0.1
46-
response_mutate_rate = 0.2
47-
response_mutate_power = 0.1
4858
response_max_value = 30.0
4959
response_min_value = -30.0
60+
response_mutate_power = 0.1
61+
response_mutate_rate = 0.2
62+
response_replace_rate = 0.1
63+
5064
# connection weight options
51-
weight_max_value = 30
52-
weight_min_value = -30
5365
weight_init_mean = 0.0
5466
weight_init_stdev = 1.0
67+
weight_max_value = 30
68+
weight_min_value = -30
69+
weight_mutate_power = 0.5
5570
weight_mutate_rate = 0.8
5671
weight_replace_rate = 0.1
57-
weight_mutate_power = 0.5
58-
# connection enable options
59-
enabled_default = True
60-
enabled_mutate_rate = 0.01
6172

6273
[DefaultStagnation]
63-
species_fitness = median
64-
max_stagnation = 10
74+
species_fitness_func = max
75+
max_stagnation = 20
6576

6677
[DefaultReproduction]
6778
elitism = 2

neat/activations.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,34 @@
33

44

55
def sigmoid_activation(z):
6-
z = max(-60.0, min(60.0, z))
6+
z = max(-60.0, min(60.0, 5.0 * z))
77
return 1.0 / (1.0 + math.exp(-z))
88

99

1010
def tanh_activation(z):
11-
z = max(-60.0, min(60.0, z))
11+
z = max(-60.0, min(60.0, 2.5 * z))
1212
return math.tanh(z)
1313

1414

1515
def sin_activation(z):
16-
z = max(-60.0, min(60.0, z))
16+
z = max(-60.0, min(60.0, 5.0 * z))
1717
return math.sin(z)
1818

1919

2020
def gauss_activation(z):
21-
z = max(-60.0, min(60.0, z))
22-
return math.exp(-0.5 * z**2) / math.sqrt(2 * math.pi)
21+
z = max(-3.4, min(3.4, z))
22+
return math.exp(-5.0 * z**2)
2323

2424

2525
def relu_activation(z):
2626
return z if z > 0.0 else 0.0
2727

2828

29+
def softplus_activation(z):
30+
z = max(-60.0, min(60.0, 5.0 * z))
31+
return 0.2 * math.log(1 + math.exp(z))
32+
33+
2934
def identity_activation(z):
3035
return z
3136

@@ -88,6 +93,7 @@ def __init__(self):
8893
self.add('sin', sin_activation)
8994
self.add('gauss', gauss_activation)
9095
self.add('relu', relu_activation)
96+
self.add('softplus', softplus_activation)
9197
self.add('identity', identity_activation)
9298
self.add('clamped', clamped_activation)
9399
self.add('inv', inv_activation)

neat/genes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def distance(self, other, config):
9292
d = abs(self.bias - other.bias) + abs(self.response - other.response)
9393
if self.activation != other.activation:
9494
d += 1.0
95-
return d * config.weight_coefficient
95+
return d * config.compatibility_weight_coefficient
9696

9797

9898
# TODO: Do an ablation study to determine whether the enabled setting is
@@ -110,5 +110,5 @@ def distance(self, other, config):
110110
d = abs(self.weight - other.weight)
111111
if self.enabled != other.enabled:
112112
d += 1.0
113-
return d * config.weight_coefficient
113+
return d * config.compatibility_weight_coefficient
114114

neat/genome.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class DefaultGenomeConfig(object):
2020
ConfigParameter('num_hidden', int),
2121
ConfigParameter('feed_forward', bool),
2222
ConfigParameter('compatibility_threshold', float),
23-
ConfigParameter('disjoint_coefficient', float),
24-
ConfigParameter('weight_coefficient', float),
23+
ConfigParameter('compatibility_disjoint_coefficient', float),
24+
ConfigParameter('compatibility_weight_coefficient', float),
2525
ConfigParameter('conn_add_prob', float),
2626
ConfigParameter('conn_delete_prob', float),
2727
ConfigParameter('node_add_prob', float),
@@ -298,7 +298,7 @@ def distance(self, other, config):
298298
node_distance += n1.distance(n2, config)
299299

300300
max_nodes = max(len(self.nodes), len(other.nodes))
301-
node_distance = (node_distance + config.disjoint_coefficient * disjoint_nodes) / max_nodes
301+
node_distance = (node_distance + config.compatibility_disjoint_coefficient * disjoint_nodes) / max_nodes
302302

303303
# Compute connection gene differences.
304304
connection_distance = 0.0
@@ -317,7 +317,7 @@ def distance(self, other, config):
317317
connection_distance += c1.distance(c2, config)
318318

319319
max_conn = max(len(self.connections), len(other.connections))
320-
connection_distance = (connection_distance + config.disjoint_coefficient * disjoint_connections) / max_conn
320+
connection_distance = (connection_distance + config.compatibility_disjoint_coefficient * disjoint_connections) / max_conn
321321

322322
distance = node_distance + connection_distance
323323
compatible = distance < config.compatibility_threshold

neat/stagnation.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from neat.six_util import iteritems
55

66
# TODO: Add a method for the user to change the "is stagnant" computation.
7+
# TODO: Add a mechanism to prevent stagnation of the top N species.
78

89

910
class DefaultStagnation(object):

neat/statistics.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def get_average_fitness(self):
3131
avg_fitness = []
3232
for stats in self.generation_statistics:
3333
scores = []
34-
for fitness in stats.values():
35-
scores.extend(fitness)
34+
for species_stats in stats.values():
35+
scores.extend(species_stats.values())
3636
avg_fitness.append(mean(scores))
3737

3838
return avg_fitness

0 commit comments

Comments
 (0)