Skip to content

Commit 4d4810b

Browse files
committed
modAL.acquisition functions refactored
1 parent 1d7e73b commit 4d4810b

File tree

6 files changed

+51
-27
lines changed

6 files changed

+51
-27
lines changed

examples/bayesian_optimization.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from sklearn.gaussian_process import GaussianProcessRegressor
55
from sklearn.gaussian_process.kernels import Matern
66
from modAL.models import BayesianOptimizer
7-
from modAL.acquisition import PI, EI, UCB, max_PI, max_EI, max_UCB
7+
from modAL.acquisition import optimizer_PI, optimizer_EI, optimizer_UCB, max_PI, max_EI, max_UCB
88

99

1010
# generating the data
@@ -24,12 +24,12 @@
2424
kernel = Matern(length_scale=1.0)
2525

2626
tr = 0.1
27-
PI_tr = partial(PI, tradeoff=tr)
27+
PI_tr = partial(optimizer_PI, tradeoff=tr)
2828
PI_tr.__name__ = 'PI, tradeoff = %1.1f' % tr
2929
max_PI_tr = partial(max_PI, tradeoff=tr)
3030

3131
acquisitions = zip(
32-
[PI_tr, EI, UCB],
32+
[PI_tr, optimizer_EI, optimizer_UCB],
3333
[max_PI_tr, max_EI, max_UCB],
3434
)
3535

modAL/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .models import ActiveLearner, Committee, CommitteeRegressor
2-
from .acquisition import PI, EI, UCB, max_PI, max_EI, max_UCB
2+
from .acquisition import PI, EI, UCB, optimizer_PI, optimizer_EI, optimizer_UCB, max_PI, max_EI, max_UCB
33
from .uncertainty import classifier_uncertainty, classifier_margin, classifier_entropy, \
44
uncertainty_sampling, margin_sampling, entropy_sampling
55
from .disagreement import vote_entropy, consensus_entropy, KL_max_disagreement, \
@@ -8,7 +8,7 @@
88

99
__all__ = [
1010
'ActiveLearner', 'Committee', 'CommitteeRegressor',
11-
'PI', 'EI', 'UCB', 'max_PI', 'max_EI', 'max_UCB',
11+
'PI', 'EI', 'UCB', 'optimizer_PI', 'optimizer_EI', 'optimizer_UCB', 'max_PI', 'max_EI', 'max_UCB',
1212
'classifier_uncertainty', 'classifier_margin', 'classifier_entropy',
1313
'uncertainty_sampling', 'margin_sampling', 'entropy_sampling',
1414
'vote_entropy', 'consensus_entropy', 'KL_max_disagreement',

modAL/acquisition.py

+22-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,20 @@
1212
from modAL.utils.selection import multi_argmax
1313

1414

15-
def PI(optimizer, X, tradeoff=0):
15+
def PI(mean, std, max_val, tradeoff):
16+
return ndtr((mean - max_val - tradeoff)/std)
17+
18+
19+
def EI(mean, std, max_val, tradeoff):
20+
z = (mean - max_val - tradeoff) / std
21+
return (mean - max_val - tradeoff)*ndtr(z) + std*norm.pdf(z)
22+
23+
24+
def UCB(mean, std, beta):
25+
return mean + beta*std
26+
27+
28+
def optimizer_PI(optimizer, X, tradeoff=0):
1629
"""
1730
Probability of improvement acquisition function for Bayesian optimization.
1831
@@ -35,10 +48,10 @@ def PI(optimizer, X, tradeoff=0):
3548
mean, std = optimizer.predict(X, return_std=True)
3649
std = std.reshape(-1, 1)
3750

38-
return ndtr((mean - optimizer.max_val - tradeoff)/std)
51+
return PI(mean, std, optimizer.max_val, tradeoff)
3952

4053

41-
def EI(optimizer, X, tradeoff=0):
54+
def optimizer_EI(optimizer, X, tradeoff=0):
4255
"""
4356
Expected improvement acquisition function for Bayesian optimization.
4457
@@ -60,12 +73,11 @@ def EI(optimizer, X, tradeoff=0):
6073
"""
6174
mean, std = optimizer.predict(X, return_std=True)
6275
std = std.reshape(-1, 1)
63-
z = (mean - optimizer.max_val - tradeoff)/std
6476

65-
return (mean - optimizer.max_val - tradeoff)*ndtr(z) + std*norm.pdf(z)
77+
return EI(mean, std, optimizer.max_val, tradeoff)
6678

6779

68-
def UCB(optimizer, X, beta=1):
80+
def optimizer_UCB(optimizer, X, beta=1):
6981
"""
7082
Upper confidence bound acquisition function for Bayesian optimization.
7183
@@ -88,7 +100,7 @@ def UCB(optimizer, X, beta=1):
88100
mean, std = optimizer.predict(X, return_std=True)
89101
std = std.reshape(-1, 1)
90102

91-
return mean + beta*std
103+
return UCB(mean, std, beta)
92104

93105

94106
def max_PI(optimizer, X, tradeoff=0, n_instances=1):
@@ -117,7 +129,7 @@ def max_PI(optimizer, X, tradeoff=0, n_instances=1):
117129
X[query_idx]: numpy.ndarray of shape (n_instances, n_features)
118130
The instances from X chosen to be labelled.
119131
"""
120-
pi = PI(optimizer, X, tradeoff=tradeoff)
132+
pi = optimizer_PI(optimizer, X, tradeoff=tradeoff)
121133
query_idx = multi_argmax(pi, n_instances=n_instances)
122134

123135
return query_idx, X[query_idx]
@@ -149,7 +161,7 @@ def max_EI(optimizer, X, tradeoff=0, n_instances=1):
149161
X[query_idx]: numpy.ndarray of shape (n_instances, n_features)
150162
The instances from X chosen to be labelled.
151163
"""
152-
ei = EI(optimizer, X, tradeoff=tradeoff)
164+
ei = optimizer_EI(optimizer, X, tradeoff=tradeoff)
153165
query_idx = multi_argmax(ei, n_instances=n_instances)
154166

155167
return query_idx, X[query_idx]
@@ -182,7 +194,7 @@ def max_UCB(optimizer, X, beta=1, n_instances=1):
182194
X[query_idx]: numpy.ndarray of shape (n_instances, n_features)
183195
The instances from X chosen to be labelled.
184196
"""
185-
ucb = UCB(optimizer, X, beta=beta)
197+
ucb = optimizer_UCB(optimizer, X, beta=beta)
186198
query_idx = multi_argmax(ucb, n_instances=n_instances)
187199

188200
return query_idx, X[query_idx]

modAL/models.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ class BayesianOptimizer(BaseLearner):
410410
>>> from sklearn.gaussian_process import GaussianProcessRegressor
411411
>>> from sklearn.gaussian_process.kernels import Matern
412412
>>> from modAL.models import BayesianOptimizer
413-
>>> from modAL.acquisition import PI, EI, UCB, max_PI, max_EI, max_UCB
413+
>>> from modAL.acquisition import optimizer_PI, optimizer_EI, optimizer_UCB, max_PI, max_EI, max_UCB
414414
>>>
415415
>>> # generating the data
416416
>>> X = np.linspace(0, 20, 1000).reshape(-1, 1)
@@ -423,12 +423,12 @@ class BayesianOptimizer(BaseLearner):
423423
>>> kernel = Matern(length_scale=1.0)
424424
>>>
425425
>>> tr = 0.1
426-
>>> PI_tr = partial(PI, tradeoff=tr)
426+
>>> PI_tr = partial(optimizer_PI, tradeoff=tr)
427427
>>> PI_tr.__name__ = 'PI, tradeoff = %1.1f' % tr
428428
>>> max_PI_tr = partial(max_PI, tradeoff=tr)
429429
>>>
430430
>>> acquisitions = zip(
431-
... [PI_tr, EI, UCB],
431+
... [PI_tr, optimizer_EI, optimizer_UCB],
432432
... [max_PI_tr, max_EI, max_UCB],
433433
... )
434434
>>>

tests/core_tests.py

+18-6
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,19 @@ def test_make_query_strategy(self):
126126

127127

128128
class TestAcquisitionFunctions(unittest.TestCase):
129-
def test_PI(self):
129+
def test_acquisition_functions(self):
130+
for n_samples in range(1, 100):
131+
mean, std = np.random.rand(100, 1), np.random.rand(100, 1)
132+
modAL.acquisition.PI(mean, std, 0, 0)
133+
modAL.acquisition.EI(mean, std, 0, 0)
134+
modAL.acquisition.UCB(mean, std, 0)
135+
136+
mean, std = np.random.rand(100, ), np.random.rand(100, )
137+
modAL.acquisition.PI(mean, std, 0, 0)
138+
modAL.acquisition.EI(mean, std, 0, 0)
139+
modAL.acquisition.UCB(mean, std, 0)
140+
141+
def test_optimizer_PI(self):
130142
for n_samples in range(1, 100):
131143
mean = np.random.rand(n_samples, 1)
132144
std = np.random.rand(n_samples, 1)
@@ -142,10 +154,10 @@ def test_PI(self):
142154

143155
np.testing.assert_almost_equal(
144156
ndtr((mean - max_val - tradeoff)/std),
145-
modAL.acquisition.PI(optimizer, np.random.rand(n_samples, 2), tradeoff)
157+
modAL.acquisition.optimizer_PI(optimizer, np.random.rand(n_samples, 2), tradeoff)
146158
)
147159

148-
def test_EI(self):
160+
def test_optimizer_EI(self):
149161
for n_samples in range(1, 100):
150162
mean = np.random.rand(n_samples, 1)
151163
std = np.random.rand(n_samples, 1)
@@ -164,10 +176,10 @@ def test_EI(self):
164176

165177
np.testing.assert_almost_equal(
166178
true_EI,
167-
modAL.acquisition.EI(optimizer, np.random.rand(n_samples, 2), tradeoff)
179+
modAL.acquisition.optimizer_EI(optimizer, np.random.rand(n_samples, 2), tradeoff)
168180
)
169181

170-
def test_UCB(self):
182+
def test_optimizer_UCB(self):
171183
for n_samples in range(1, 100):
172184
mean = np.random.rand(n_samples, 1)
173185
std = np.random.rand(n_samples, 1)
@@ -183,7 +195,7 @@ def test_UCB(self):
183195

184196
np.testing.assert_almost_equal(
185197
true_UCB,
186-
modAL.acquisition.UCB(optimizer, np.random.rand(n_samples, 2), beta)
198+
modAL.acquisition.optimizer_UCB(optimizer, np.random.rand(n_samples, 2), beta)
187199
)
188200

189201
def test_selection(self):

tests/example_tests/bayesian_optimization.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from sklearn.gaussian_process import GaussianProcessRegressor
44
from sklearn.gaussian_process.kernels import Matern
55
from modAL.models import BayesianOptimizer
6-
from modAL.acquisition import PI, EI, UCB, max_PI, max_EI, max_UCB
6+
from modAL.acquisition import optimizer_PI, optimizer_EI, optimizer_UCB, max_PI, max_EI, max_UCB
77

88

99
# generating the data
@@ -17,12 +17,12 @@
1717
kernel = Matern(length_scale=1.0)
1818

1919
tr = 0.1
20-
PI_tr = partial(PI, tradeoff=tr)
20+
PI_tr = partial(optimizer_PI, tradeoff=tr)
2121
PI_tr.__name__ = 'PI, tradeoff = %1.1f' % tr
2222
max_PI_tr = partial(max_PI, tradeoff=tr)
2323

2424
acquisitions = zip(
25-
[PI_tr, EI, UCB],
25+
[PI_tr, optimizer_EI, optimizer_UCB],
2626
[max_PI_tr, max_EI, max_UCB],
2727
)
2828

0 commit comments

Comments
 (0)