Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit d6e1f13

Browse files
author
Tanguy Damart
committed
Added rules
1 parent d02e511 commit d6e1f13

File tree

6 files changed

+230
-8
lines changed

6 files changed

+230
-8
lines changed

bluepyopt/deapext/algorithms.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,11 @@ def eaAlphaMuPlusLambdaCheckpoint(
109109
cp_filename(string): path to checkpoint filename
110110
continue_cp(bool): whether to continue
111111
"""
112+
<<<<<<< HEAD
112113

114+
=======
115+
116+
>>>>>>> 7e9c3ea (Added rules)
113117
if cp_filename:
114118
cp_filename_tmp = cp_filename + '.tmp'
115119

@@ -140,6 +144,7 @@ def eaAlphaMuPlusLambdaCheckpoint(
140144
history = deap.tools.History()
141145

142146
invalid_count = _evaluate_invalid_fitness(toolbox, population)
147+
143148
utils.update_history_and_hof(halloffame, history, population)
144149
utils.record_stats(stats,
145150
logbook,
@@ -148,7 +153,7 @@ def eaAlphaMuPlusLambdaCheckpoint(
148153
invalid_count)
149154

150155
stopping_criteria = [MaxNGen(ngen)]
151-
156+
152157
# Begin the generational process
153158
gen = start_gen + 1
154159
stopping_params = {"gen": gen}
@@ -160,7 +165,7 @@ def eaAlphaMuPlusLambdaCheckpoint(
160165
invalid_count = _evaluate_invalid_fitness(toolbox, offspring)
161166
utils.update_history_and_hof(halloffame, history, population)
162167
utils.record_stats(stats, logbook, gen, population, invalid_count)
163-
168+
164169
# Select the next generation parents
165170
parents = toolbox.select(population, mu)
166171

bluepyopt/ephys/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from . import recordings # NOQA
3838
from . import objectivescalculators # NOQA
3939
from . import stimuli # NOQA
40+
from . import rules # NOQA
4041

4142
# TODO create all the necessary abstract methods
4243
# TODO check inheritance structure

bluepyopt/ephys/evaluators.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ def objective_dict(self, objective_array):
116116
def objective_list(self, objective_dict):
117117
"""Convert objective_dict in objective_list"""
118118
objective_list = []
119-
objective_names = [objective.name
120-
for objective in self.fitness_calculator.objectives]
119+
objective_names = [objective.name for objective in self.fitness_calculator.objectives]
120+
121121
for objective_name in objective_names:
122122
objective_list.append(objective_dict[objective_name])
123123

bluepyopt/ephys/objectives.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,52 @@ def calculate_score(self, responses):
127127
score += weight * feature_score
128128

129129
return score
130+
131+
132+
class RuleObjective(bluepyopt.objectives.Objective):
133+
134+
"""Multi rules objective"""
135+
136+
def __init__(self, name, rules=None):
137+
"""Constructor
138+
Args:
139+
name (str): name of this object
140+
rules (list): rule used in the Objective
141+
"""
142+
143+
super(RuleObjective, self).__init__(name)
144+
self.name = name
145+
self.rules = rules
146+
147+
def calculate_scores(self, cell_model):
148+
"""Calculate the scores for the individual rules"""
149+
150+
scores = []
151+
for rule in self.rules:
152+
scores.append(rule.calculate_score(cell_model))
153+
154+
return scores
155+
156+
157+
class SingletonRuleObjective(RuleObjective):
158+
159+
"""Single rule objective"""
160+
161+
def __init__(self, name, rule):
162+
"""Constructor
163+
Args:
164+
name (str): name of this object
165+
rule (EFeature): single rule inside this objective
166+
"""
167+
168+
super(SingletonRuleObjective, self).__init__(name, [rule])
169+
170+
def calculate_score(self, cell_model):
171+
"""Objective score"""
172+
173+
return self.calculate_scores(cell_model)[0]
174+
175+
def __str__(self):
176+
"""String representation"""
177+
178+
return '( %s )' % self.rule[0]

bluepyopt/ephys/objectivescalculators.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2020
"""
2121

22+
from . import objectives
2223

2324
class ObjectivesCalculator(object):
2425

@@ -35,11 +36,25 @@ def __init__(
3536

3637
self.objectives = objectives
3738

38-
def calculate_scores(self, responses):
39+
def calculate_scores(self, responses, cell_model, param_dict):
3940
"""Calculator the score for every objective"""
40-
41-
return {objective.name: objective.calculate_score(responses)
42-
for objective in self.objectives}
41+
42+
scores = {}
43+
44+
cell_model.freeze(param_dict)
45+
46+
for objective in self.objectives:
47+
48+
if issubclass(type(objective), objectives.EFeatureObjective):
49+
scores[objective.name] = objective.calculate_score(responses)
50+
elif issubclass(type(objective), objectives.RuleObjective):
51+
scores[objective.name] = objective.calculate_score(cell_model)
52+
else:
53+
raise Exception('Unknown objective class: {}'.format(type(objective)))
54+
55+
cell_model.unfreeze(param_dict.keys())
56+
57+
return scores
4358

4459
def calculate_values(self, responses):
4560
"""Calculator the value of each objective"""
@@ -48,6 +63,7 @@ def calculate_values(self, responses):
4863
for objective in self.objectives}
4964

5065
def __str__(self):
66+
5167
return 'objectives:\n %s' % '\n '.join(
5268
[str(obj) for obj in self.objectives]) \
5369
if self.objectives is not None else 'objectives:\n'

bluepyopt/ephys/rules.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
"""Rules classes"""
2+
3+
"""
4+
Copyright (c) 2016-2020, EPFL/Blue Brain Project
5+
6+
This file is part of BluePyOpt <https://github.com/BlueBrain/BluePyOpt>
7+
8+
This library is free software; you can redistribute it and/or modify it under
9+
the terms of the GNU Lesser General Public License version 3.0 as published
10+
by the Free Software Foundation.
11+
12+
This library is distributed in the hope that it will be useful, but WITHOUT
13+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14+
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15+
details.
16+
17+
You should have received a copy of the GNU Lesser General Public License
18+
along with this library; if not, write to the Free Software Foundation, Inc.,
19+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20+
"""
21+
import logging
22+
23+
import bluepyopt
24+
import math
25+
26+
logger = logging.getLogger(__name__)
27+
28+
29+
def sigmoid(x):
30+
"""Sigmoid function"""
31+
return 1 / (1 + math.exp(-x))
32+
33+
34+
class Rule():
35+
36+
"""Abstract Rule class"""
37+
38+
name = ""
39+
40+
def __init__(
41+
self,
42+
name=None,
43+
force_max_score=False,
44+
max_score=250
45+
):
46+
"""Constructor
47+
Args:
48+
name (str): name of the eFELFeature object
49+
force_max_score (bool): should the max_score limit be applied to
50+
the score
51+
max_score (float): upper bound for the score
52+
"""
53+
54+
if name:
55+
self.name = name
56+
57+
self.force_max_score = force_max_score
58+
self.max_score = max_score
59+
60+
def _rule(self, cell_model):
61+
return None
62+
63+
def _loss_function(self, value):
64+
return None
65+
66+
def calculate_value(self, cell_model):
67+
"""Calculate rule value"""
68+
69+
if cell_model is None:
70+
rule_value = None
71+
else:
72+
rule_value = self._rule(cell_model)
73+
74+
logger.debug(
75+
'Calculated value for %s: %s',
76+
self.name,
77+
str(rule_value)
78+
)
79+
80+
return rule_value
81+
82+
def calculate_score(self, cell_model):
83+
"""Calculate the score"""
84+
85+
if cell_model is None:
86+
score = self.max_score
87+
else:
88+
score = self._loss_function(self._rule(cell_model))
89+
90+
if self.force_max_score:
91+
score = min(score, self.max_score)
92+
93+
logger.debug('Calculated score for %s: %f', self.name, score)
94+
95+
return score
96+
97+
def __str__(self):
98+
"""String representation"""
99+
100+
return "Rule %s " % (self.name)
101+
102+
103+
class SumConductivityRule(Rule):
104+
105+
"""SumConductivityRule class
106+
107+
Punish high sum of conductivity based on a sigmoid loss function
108+
"""
109+
110+
name = "SumConductivity"
111+
112+
def __init__(
113+
self,
114+
name=None,
115+
force_max_score=False,
116+
max_score=250,
117+
conductivity_target=2.
118+
):
119+
"""Constructor
120+
Args:
121+
name (str): name of the eFELFeature object
122+
force_max_score (bool): should the max_score limit be applied to
123+
the score
124+
max_score (float): upper bound for the score
125+
"""
126+
127+
super(SumConductivityRule, self).__init__(
128+
name=name,
129+
force_max_score=force_max_score,
130+
max_score=max_score
131+
)
132+
133+
self.conductivity_target = conductivity_target
134+
135+
def _rule(self, cell_model):
136+
137+
sum_g = 0
138+
for param in cell_model.params.values():
139+
if param.name[0] == "g":
140+
sum_g += param.value
141+
142+
return sum_g
143+
144+
def _loss_function(self, value):
145+
146+
# Center on conductivity_target
147+
_ = (value / self.conductivity_target) - 1.
148+
149+
# Take the sigmoid
150+
return self.max_score * sigmoid(_)
151+

0 commit comments

Comments
 (0)