-
Notifications
You must be signed in to change notification settings - Fork 1
/
GeneticAlgo.py
117 lines (95 loc) · 4.32 KB
/
GeneticAlgo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import numpy as np
import random
import SVM
import DataPrep
class GeneticAlgo:
def __init__(self, x, y, num_chromosomes=3, chromosome_mutation_rate=.5):
self.x = np.array(x)
self.y = y
self.param_count = np.shape(self.x)[1]
self.num_chromosomes = num_chromosomes
self.chromosome_svm = [None]*self.num_chromosomes
self.chromosomes = np.zeros((self.num_chromosomes, self.param_count))
self.chromosome_mutation_rate = chromosome_mutation_rate
self.chromosome_data = [None]*self.num_chromosomes
self.chromosome_accuracy = [0.0]*self.num_chromosomes
# set up chromosomes
# 0 - every even gene index
# 1 - every odd gene index
# 2 - every even gene index and indexes divisible by 3
# 3 - every even gene index and indexes divisible by 5 and 7
for i in range(0,self.param_count):
if i%2 == 0:
self.chromosomes[0][i] = 1
self.chromosomes[2][i] = 1
#self.chromosomes[3][i] = 1
if (i+1) % 2 == 0:
self.chromosomes[1][i] = 1
if i % 3 == 0:
self.chromosomes[2][i] = 1
#if i % 5 == 0 or i % 7 == 0:
#self.chromosomes[3][i] = 1
def create_data_from_chromosome(self):
for index, c in enumerate(self.chromosomes):
# get a list of all non zero values. The corresponding parameter will be tested
params = np.nonzero(np.array(c))[0]
self.chromosome_data[index] = self.x[:, params]
return self.chromosome_data
# changes a gene's state in the chromosome
def mutate_chromosomes(self, chromosome):
# random number of mutations to occur
num_to_mutate = int(random.randint(0,self.param_count-1) * self.chromosome_mutation_rate)
for i in range(0,num_to_mutate):
# select a gene to reverse, so 0->1 and 1->0. Genes with a value of 1 will be used in the SVM
pos = random.randint(0, self.param_count-1)
if chromosome[pos] == 0:
chromosome[pos] = 1
else:
chromosome[pos] = 0
return chromosome
# combines two chromosomes and mutates the result
def crossover(self, mom, dad):
# select the position to cut off parent chromosomes for recombination
crossover_pos = int(random.randint(1, self.param_count-1))
# create child chromosome by combining parts from parents
moms_part = mom[: crossover_pos]
dads_part = dad[crossover_pos:]
child = np.append(moms_part, dads_part)
# mutate genes in child
child = self.mutate_chromosomes(child)
return child
def test_chromosomes(self):
self.create_data_from_chromosome()
for index, chromosome in enumerate(self.chromosome_data):
print "Testing chromosome: ", index
svm = SVM.SvmFreeParam(chromosome, self.y)
# increase accuracy so we can select chromosomes easier
self.chromosome_accuracy[index] = svm.optimize_params()*1000
self.chromosome_svm[index] = svm
def create_next_generation(self):
temp_chromosomes = [None]*self.num_chromosomes
max_val = np.sum(self.chromosome_accuracy)
tiers = [None]*self.num_chromosomes
tiers[0] = self.chromosome_accuracy[0]
tiers[1] = self.chromosome_accuracy[1] + tiers[0]
tiers[2] = self.chromosome_accuracy[2] + tiers[1]
#tiers[3] = self.num_chromosomes[3] + tiers[2]
for index, chromosome in enumerate(self.chromosomes):
pos = random.uniform(0, max_val)
i = 0
while pos > tiers[i]:
i += 1
pos = random.uniform(0, max_val)
j = 0
while pos > tiers[j]:
j += 1
temp_chromosomes[index] = self.crossover(self.chromosomes[i], self.chromosomes[j])
def eval(self, num_evolutions):
for i in range(0, num_evolutions):
print "Evolution: ", i
self.test_chromosomes()
self.create_next_generation()
self.test_chromosomes()
max_accuracy_index = self.chromosome_accuracy.index(max(self.chromosome_accuracy))
print "Max accuracy", max(self.chromosome_accuracy)/1000
return self.chromosome_svm[max_accuracy_index]