Skip to content

Commit f20b1b6

Browse files
add bbvi
1 parent f571e27 commit f20b1b6

File tree

2 files changed

+103
-18
lines changed

2 files changed

+103
-18
lines changed

bbvi.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,79 @@
11
# posterior inference by black-box variational inference
2+
3+
4+
import autograd.numpy as np
5+
from autograd import grad
6+
import autograd.scipy as scipy
7+
import autograd.scipy.stats.norm as norm
8+
9+
from autograd.misc.optimizers import adam, sgd
10+
11+
def sigmoid(x):
12+
return 0.5*(np.tanh(x/2)+1)
13+
14+
def predict(w, x):
15+
return sigmoid(np.dot(x, w))
16+
17+
def log_sigmoid(x):
18+
a = np.array([np.zeros_like(x), -x])
19+
return -scipy.special.logsumexp(a, axis=0)
20+
21+
def log_joint(w, x, y, alpha=0.1):
22+
log_prior = alpha*np.sum(w**2)
23+
24+
score = np.dot(x, w)
25+
logp0 = log_sigmoid(score)
26+
27+
logp1 = -score + logp0
28+
log_likelihood = np.sum(y*logp0 + (1-y)*logp1, axis=0)
29+
30+
return log_likelihood - log_prior
31+
32+
33+
34+
35+
36+
def bbvi(x, y, params, log_joint, T=25):
37+
''' Perform black-box variational inference
38+
with q = diagonal gaussian
39+
'''
40+
def objective(params, i=0):
41+
D = len(params) // 2
42+
mu, log_sigma2 = params[:D], params[D:]
43+
44+
entropy = 0.5*D*(1 + np.log(2*np.pi)) + np.sum(log_sigma2)
45+
46+
# samples = np.random.randn(T, D) * np.exp(0.5*log_sigma2) + mu
47+
logp = 0
48+
sample = mu + np.random.randn(T, D) * np.exp(0.5*log_sigma2)
49+
50+
for t in range(T):
51+
logp += log_joint(sample[t], x, y)
52+
return -(logp/T + entropy)
53+
54+
gradient = grad(objective)
55+
return objective, gradient
56+
57+
58+
59+
60+
x = np.array([[0.52, 1.12, 0.77],
61+
[0.88, -1.08, 0.15],
62+
[0.52, 0.06, -1.30],
63+
[0.74, -2.49, 1.39]])
64+
65+
y = np.array([True, True, False, True])
66+
67+
x = np.hstack([np.ones(( len(x),1)), x])
68+
69+
params = np.zeros(4+4)
70+
objective, gradient = bbvi(x, y, params, log_joint, T=100)
71+
print (objective(params))
72+
print (params)
73+
print (predict(params[:4], x))
74+
75+
params = adam(gradient, params, step_size=0.01, num_iters=500)
76+
77+
print (objective(params), objective(params))
78+
print (np.exp(params[4:]))
79+
print (predict(params[:4], x))

laplace.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# posterior inference by laplace approximation
2+
from autograd.misc.optimizers import adam, sgd
23
from autograd import grad
34
import autograd.numpy as np
45
import autograd.scipy as scipy
@@ -12,23 +13,25 @@ def predict(w, x):
1213

1314
def log_sigmoid(x):
1415
a = np.array([np.zeros_like(x), -x])
15-
return -scipy.special.logsumexp(a)
16+
return -scipy.special.logsumexp(a, axis=0)
1617

1718
def nll_loss(w, x, y, alpha=None):
1819
score = np.dot(x, w)
1920

20-
logp1 = log_sigmoid(score)
21-
logp0 = -score + logp1
22-
loss = y*logp0 + (1-y)*logp1
23-
reg = alpha*np.dot(w, w) if alpha else 0
24-
return sum(loss) + reg
21+
logp0 = log_sigmoid(score)
22+
23+
logp1 = -score+logp0
24+
25+
loss = -np.sum(y*logp0 + (1-y)*logp1)
26+
reg = alpha*np.sum(w**2) if alpha else 0
27+
return loss + reg
2528

2629
def compute_precision(x, y, w, alpha):
2730
d = np.size(x, 1)
2831
y_hat = predict(w, x)
2932
R = np.diag(y_hat*(1 - y_hat))
30-
precision = alpha * np.eye(d) + x.T.dot(R).dot(x)
31-
return precision + 1e-9*np.eye(d)
33+
precision = 1e-9*np.eye(d) + alpha * np.eye(d) + x.T.dot(R).dot(x)
34+
return precision
3235

3336
def predict_mc(mu, sigma, x, T=100):
3437
ps = []
@@ -44,30 +47,34 @@ def predict_var(mu, sigmainv, x):
4447
kappa = np.sqrt(1 + sigma2_a*np.pi*.125)
4548
return sigmoid(mu_a/kappa)
4649

50+
4751
x = np.array([[0.52, 1.12, 0.77],
4852
[0.88, -1.08, 0.15],
4953
[0.52, 0.06, -1.30],
5054
[0.74, -2.49, 1.39],
5155
[0.52, 1.12, 0.77]])
56+
5257
y = np.array([True, True, False, True, False])
5358

5459

5560
x = np.hstack([np.ones(( len(x),1)), x])
56-
training_loss = lambda w: nll_loss(w, x, y, alpha=1)
61+
training_loss = lambda w, i: nll_loss(w, x, y, alpha=0.1)
5762
g = grad(training_loss)
58-
w = np.array([1, 0, 0, 0], dtype=np.float)
59-
print("Initial loss:", training_loss(w))
60-
for i in range(100):
61-
w -= g(w) * 0.01
62-
print("Trained loss:", training_loss(w))
63+
w = np.array([1, 1, 1, 1], dtype=np.float)
64+
print("Initial loss:", training_loss(w, 0))
65+
#for i in range(100):
66+
# w -= g(w) * 0.01
67+
68+
w = sgd(g, w)
69+
print("Trained loss:", training_loss(w, 0))
6370

6471
pred = predict(w, x) > 0.5
6572

6673
print (y.astype(int))
67-
print (predict(w, x) )
74+
print ('ml', predict(w, x) )
6875

6976

70-
sigmainv = compute_precision(x,y,w,alpha=1)
77+
sigmainv = compute_precision(x,y,w,alpha=0.1)
7178

72-
print (predict_var(w, sigmainv, x))
73-
print (predict_mc(w, np.linalg.inv(sigmainv), x))
79+
print ('var', predict_var(w, sigmainv, x))
80+
print ('mc', predict_mc(w, np.linalg.inv(sigmainv), x))

0 commit comments

Comments
 (0)