Skip to content

Commit 3a09e13

Browse files
committed
Initial commit of @mojones ANN evolution code
1 parent 3ae9409 commit 3a09e13

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

ann_evolve.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
"""
2+
Training ANN strategies.
3+
4+
Original code by Martin Jones @mojones:
5+
https://gist.github.com/mojones/b809ba565c93feb8d44becc7b93e37c6
6+
"""
7+
8+
from __future__ import division
9+
10+
import copy
11+
import random
12+
from statistics import mean, pstdev
13+
14+
import axelrod
15+
16+
17+
def evolve(starting_weights, mutation_rate, mutation_distance, generations,
18+
bottleneck, starting_pop, output_file):
19+
20+
current_bests = starting_weights
21+
22+
for generation in range(generations):
23+
24+
with open(output_file, "a") as output:
25+
26+
weights_to_copy = [x[1] for x in current_bests]
27+
28+
copies = []
29+
30+
for w1 in weights_to_copy:
31+
for w2 in weights_to_copy:
32+
crossover = random.randrange(len(w1))
33+
new_weights = copy.deepcopy(
34+
w1[0:crossover]) + copy.deepcopy(w2[crossover:])
35+
copies.append(new_weights)
36+
37+
for c in copies:
38+
for i in range(len(c)):
39+
if random.random() < mutation_rate:
40+
c[i] = c[i] * (
41+
1 + (random.uniform(-1, 1) * mutation_distance))
42+
43+
population = copies + weights_to_copy
44+
45+
# map the population to get a list of (score, weights) tuples
46+
# this list will be sorted by score, best weights first
47+
results = score_all_weights(population)
48+
49+
current_bests = results[0:bottleneck]
50+
51+
# get all the scores for this generation
52+
scores = [score for score, table in results]
53+
54+
for value in [generation, results[0][1], results[0][0],
55+
mean(scores), pstdev(scores), mutation_rate,
56+
mutation_distance]:
57+
output.write(str(value) + "\t")
58+
output.write("\n")
59+
60+
mutation_rate *= 0.99
61+
mutation_distance *= 0.99
62+
63+
return (current_bests)
64+
65+
66+
def get_random_weights(number):
67+
return [random.uniform(-1, 1) for _ in range(number)]
68+
69+
70+
def score_single(my_strategy_factory, other_strategy_factory, iterations=200,
71+
debug=False):
72+
if other_strategy_factory.classifier['stochastic']:
73+
repetitions = 10
74+
else:
75+
repetitions = 1
76+
all_scores = []
77+
for _ in range(repetitions):
78+
me = my_strategy_factory()
79+
other = other_strategy_factory()
80+
me.set_tournament_attributes(length=iterations)
81+
other.set_tournament_attributes(length=iterations)
82+
83+
g = axelrod.Game()
84+
for _ in range(iterations):
85+
me.play(other)
86+
# print(me.history)
87+
iteration_score = sum([g.score(pair)[0] for pair in
88+
zip(me.history, other.history)]) / iterations
89+
all_scores.append(iteration_score)
90+
91+
92+
def split_weights(weights, input_values, hidden_layer_size):
93+
number_of_input_to_hidden_weights = input_values * hidden_layer_size
94+
number_of_hidden_bias_weights = hidden_layer_size
95+
number_of_hidden_to_output_weights = hidden_layer_size
96+
97+
input2hidden = []
98+
for i in range(0, number_of_input_to_hidden_weights, input_values):
99+
input2hidden.append(weights[i:i + input_values])
100+
101+
hidden2output = weights[
102+
number_of_input_to_hidden_weights:number_of_input_to_hidden_weights + number_of_hidden_to_output_weights]
103+
bias = weights[
104+
number_of_input_to_hidden_weights + number_of_hidden_to_output_weights:]
105+
106+
return (input2hidden, hidden2output, bias)
107+
108+
109+
def score_all_weights(population):
110+
return sorted(pool.map(score_weights, population), reverse=True)
111+
112+
113+
def _score_weights(weights):
114+
in2h, h2o, bias = split_weights(weights, input_values, hidden_layer_size)
115+
return (score_for(lambda: ANN(in2h, h2o, bias), strategies), weights)
116+
117+
118+
score_weights = _score_weights
119+
120+
121+
def score_for(my_strategy_factory, other_strategies=strategies, iterations=200,
122+
debug=False):
123+
my_scores = map(
124+
lambda x: score_single(my_strategy_factory, x, iterations, debug=debug),
125+
other_strategies)
126+
my_average_score = sum(my_scores) / len(my_scores)
127+
return (my_average_score)

run.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,17 @@
44

55
python lookup_evolve.py -p 1 -s 1 -g 100000 -k 10 -u 0.1 -b 10 -i 4 -o evolve1-1.csv
66

7+
python lookup_evolve.py -p 1 -s 2 -g 100000 -k 20 -u 0.1 -b 20 -i 2 -o evolve1-2.csv
8+
9+
python lookup_evolve.py -p 2 -s 1 -g 100000 -k 20 -u 0.1 -b 20 -i 2 -o evolve2-1.csv
10+
11+
12+
13+
python lookup_evolve.py -p 1 -s 1 -g 100000 -k 10 -u 0.1 -b 10 -i 4 -o evolve1-1.csv
14+
15+
python lookup_evolve.py -p 1 -s 1 -g 100000 -k 10 -u 0.1 -b 10 -i 4 -o evolve1-1.csv
16+
17+
18+
19+
720
python lookup_evolve.py -p 3 -s 3 -g 100000 -k 20 -u 0.001 -b 20 -i 4 -o evolve3-3.csv

0 commit comments

Comments
 (0)