This repository has been archived by the owner on Jul 19, 2022. It is now read-only.
forked from alpecli/predlig
-
Notifications
You must be signed in to change notification settings - Fork 0
/
evolutionary.py
157 lines (121 loc) · 5.18 KB
/
evolutionary.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
from wrapper import *
from deap import base
from deap import creator
from deap import tools
from operator import attrgetter
import copy
import numpy as np
import random
from classifier import *
class EvolutionaryFeatureSelection(WrapperFeatureSelection):
def __init__(self, number_variables, classifier, classifier_params, metric, records, classes, folds, pop_number, gen_number, crossover_rate, mutation_rate, selected_crossover = "generational_mode", ss_gap = 10, selection_function = "roulette", selection_parameters = {}, linear_normalization_generation = None):
self.number_variables = number_variables
self.classifier = ParallelClassifier(classifier, classifier_params, metric)
self.records = records
self.classes = classes
self.folds = folds
self.pop_number = pop_number
self.pop = None
self.gen_number = gen_number
self.current_generation = 0
self.crossover_rate = crossover_rate
self.mutation_rate = mutation_rate
self.selected_crossover = selected_crossover
self.ss_gap = ss_gap
self.crossover_functions = {"generational_mode": self.generational_mode_crossover,
"steady_state_mode": self.steady_state_crossover}
self.selection_function = selection_function
self.selection_parameters = selection_parameters
self.selection_functions = {"tournament": tools.selTournament,
"roulette": tools.selRoulette,
"random": tools.selRandom}
self.linear_normalization_generation = linear_normalization_generation
self.best_solution = None
self.offspring = []
creator.create("FitnessMulti", base.Fitness, weights=(0.7, -0.3,))
creator.create("Individual", list, fitness=creator.FitnessMulti)
self.toolbox = base.Toolbox()
# Attribute generator
self.toolbox.register("attr_bool", random.randint, 0, 1)
# Structure initializers
self.toolbox.register("individual", tools.initRepeat, creator.Individual,
self.toolbox.attr_bool, self.number_variables)
self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual)
self.toolbox.register("evaluate", self.evalMulti)
self.toolbox.register("mate", tools.cxTwoPoint)
self.toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
self.toolbox.register("select", self.selection_functions[self.selection_function], **self.selection_parameters)
def evalMulti(self, individual):
count = 0
subvar = list()
for i in individual:
if i == 1:
subvar.append(count)
count += 1
if len(subvar) == 0:
return 0, 100,
else:
r = self.records[:, subvar]
score = self.classifier.get_final_score(r, self.classes, self.folds)
return score, sum(individual),
def first_solutions_generation(self):
return (self.current_generation == 0)
def reached_stopping_criteria(self):
return (self.current_generation >= self.gen_number)
def generate_initial_possible_solutions(self):
self.pop = self.toolbox.population(n=self.pop_number)
fitnesses = list(map(self.toolbox.evaluate, self.pop))
for ind, fit in zip(self.pop, fitnesses):
ind.fitness.values = fit
self.current_generation = 1
self.offspring[:] = self.pop
def generate_new_possible_solutions(self):
if self.linear_normalization_generation != None:
if self.gen_number - self.current_generation <= self.linear_normalization_generation:
self.toolbox.register("select", tools.selRandom)
self.crossover_functions[self.selected_crossover]()
self.current_generation += 1
def evaluate_possible_solutions(self):
invalid_ind = [ind for ind in self.offspring if not ind.fitness.valid]
fitnesses = map(self.toolbox.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit
if self.offspring != []:
self.pop[:] = self.offspring
self.steady_state_crossover()
self.best_solution = tools.selBest(self.pop, 1)[0]
def steady_state_crossover(self):
self.offspring = list(map(self.toolbox.clone, self.pop))
lista1 = list(self.offspring)
children = []
parents = tools.selRandom(self.offspring, self.ss_gap)
for parent1, parent2 in zip(parents[::2], parents[1::2]):
child1, child2 = self.toolbox.clone(parent1), self.toolbox.clone(parent2)
self.toolbox.mate(child1, child2)
if random.random() < self.mutation_rate:
self.toolbox.mutate(child1)
if random.random() < self.mutation_rate:
self.toolbox.mutate(child2)
del child1.fitness.values
del child2.fitness.values
children.append(child1)
children.append(child2)
for child in children:
self.offspring.remove(tools.selRandom(self.offspring, 1)[0])
self.offspring.append(child)
def generational_mode_crossover(self):
# Select the next generation individuals
self.offspring = self.toolbox.select(self.pop, len(self.pop))
# Clone the selected individuals
self.offspring = list(map(self.toolbox.clone, self.offspring))
for child1, child2 in zip(self.offspring[::2], self.offspring[1::2]):
if random.random() < self.crossover_rate:
self.toolbox.mate(child1, child2)
del child1.fitness.values
del child2.fitness.values
for mutant in self.offspring:
if random.random() < self.mutation_rate:
self.toolbox.mutate(mutant)
del mutant.fitness.values
if __name__ == "__main__":
F = EvolutionaryFeatureSelection()