-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathacquisition_functions.py
162 lines (141 loc) · 6.32 KB
/
acquisition_functions.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
158
159
160
161
162
import torch
import numpy as np
from scipy import stats
def predictions_from_pool(
model, X_pool: np.ndarray, T: int = 100, training: bool = True
):
"""Run random_subset prediction on model and return the output
Attributes:
X_pool: Pool set to select uncertainty,
T: Number of MC dropout iterations aka training iterations,
training: If False, run test without MC dropout. (default=True)
"""
random_subset = np.random.choice(range(len(X_pool)), size=2000, replace=False)
with torch.no_grad():
outputs = np.stack(
[
torch.softmax(
model.estimator.forward(X_pool[random_subset], training=training),
dim=-1,
)
.cpu()
.numpy()
for _ in range(T)
]
)
return outputs, random_subset
def uniform(
model, X_pool: np.ndarray, n_query: int = 10, T: int = 100, training: bool = True
):
"""Baseline acquisition a(x) = unif() with unif() a function
returning a draw from a uniform distribution over the interval [0,1].
Using this acquisition function is equivalent to choosing a point
uniformly at random from the pool.
Attributes:
X_pool: Pool set to select uncertainty,
n_query: Number of points that randomly select from pool set,
training: If False, run test without MC dropout. (default=True)
"""
query_idx = np.random.choice(range(len(X_pool)), size=n_query, replace=False)
return query_idx, X_pool[query_idx]
def shannon_entropy_function(
model, X_pool: np.ndarray, T: int = 100, E_H: bool = False, training: bool = True
):
"""H[y|x,D_train] := - sum_{c} p(y=c|x,D_train)log p(y=c|x,D_train)
Attributes:
model: Model that is ready to measure uncertainty after training,
X_pool: Pool set to select uncertainty,
T: Number of MC dropout iterations aka training iterations,
E_H: If True, compute H and EH for BALD (default: False),
training: If False, run test without MC dropout. (default=True)
"""
outputs, random_subset = predictions_from_pool(model, X_pool, T, training=training)
pc = outputs.mean(axis=0)
H = (-pc * np.log(pc + 1e-10)).sum(
axis=-1
) # To avoid division with zero, add 1e-10
if E_H:
E = -np.mean(np.sum(outputs * np.log(outputs + 1e-10), axis=-1), axis=0)
return H, E, random_subset
return H, random_subset
def max_entropy(
model, X_pool: np.ndarray, n_query: int = 10, T: int = 100, training: bool = True
):
"""Choose pool points that maximise the predictive entropy.
Using Shannon entropy function.
Attributes:
model: Model that is ready to measure uncertainty after training,
X_pool: Pool set to select uncertainty,
n_query: Number of points that maximise max_entropy a(x) from pool set,
T: Number of MC dropout iterations aka training iterations,
training: If False, run test without MC dropout. (default=True)
"""
acquisition, random_subset = shannon_entropy_function(
model, X_pool, T, training=training
)
idx = (-acquisition).argsort()[:n_query]
query_idx = random_subset[idx]
return query_idx, X_pool[query_idx]
def bald(
model, X_pool: np.ndarray, n_query: int = 10, T: int = 100, training: bool = True
):
"""Choose pool points that are expected to maximise the information
gained about the model parameters, i.e. maximise the mutal information
between predictions and model posterior. Given
I[y,w|x,D_train] = H[y|x,D_train] - E_{p(w|D_train)}[H[y|x,w]]
with w the model parameters (H[y|x,w] is the entropy of y given w).
Points that maximise this acquisition function are points on which the
model is uncertain on average but there exist model parameters that produce
disagreeing predictions with high certainty. This is equivalent to points
with high variance in th einput to the softmax layer
Attributes:
model: Model that is ready to measure uncertainty after training,
X_pool: Pool set to select uncertainty,
n_query: Number of points that maximise bald a(x) from pool set,
T: Number of MC dropout iterations aka training iterations,
training: If False, run test without MC dropout. (default=True)
"""
H, E_H, random_subset = shannon_entropy_function(
model, X_pool, T, E_H=True, training=training
)
acquisition = H - E_H
idx = (-acquisition).argsort()[:n_query]
query_idx = random_subset[idx]
return query_idx, X_pool[query_idx]
def var_ratios(
model, X_pool: np.ndarray, n_query: int = 10, T: int = 100, training: bool = True
):
"""Like Max Entropy but Variational Ratios measures lack of confidence.
Given: variational_ratio[x] := 1 - max_{y} p(y|x,D_{train})
Attributes:
model: Model that is ready to measure uncertainty after training,
X_pool: Pool set to select uncertainty,
n_query: Number of points that maximise var_ratios a(x) from pool set,
T: Number of MC dropout iterations aka training iterations,
training: If False, run test without MC dropout. (default=True)
"""
outputs, random_subset = predictions_from_pool(model, X_pool, T, training)
preds = np.argmax(outputs, axis=2)
_, count = stats.mode(preds, axis=0)
acquisition = (1 - count / preds.shape[1]).reshape((-1,))
idx = (-acquisition).argsort()[:n_query]
query_idx = random_subset[idx]
return query_idx, X_pool[query_idx]
def mean_std(
model, X_pool: np.ndarray, n_query: int = 10, T: int = 100, training: bool = True
):
"""Maximise mean standard deviation
Given: sigma_c = sqrt(E_{q(w)}[p(y=c|x,w)^2]-E_{q(w)}[p(y=c|x,w)]^2)
Attributes:
model: Model that is ready to measure uncertainty after training,
X_pool: Pool set to select uncertainty,
n_query: Number of points that maximise mean std a(x) from pool set,
T: Number of MC dropout iterations aka training iterations,
training: If False, run test without MC dropout. (default=True)
"""
outputs, random_subset = predictions_from_pool(model, X_pool, T, training)
sigma_c = np.std(outputs, axis=0)
acquisition = np.mean(sigma_c, axis=-1)
idx = (-acquisition).argsort()[:n_query]
query_idx = random_subset[idx]
return query_idx, X_pool[query_idx]