Skip to content

Commit 6e75862

Browse files
manifold mala example done, need to regenerate the data on the same GPU
1 parent 33c4c15 commit 6e75862

1 file changed

Lines changed: 107 additions & 96 deletions

File tree

examples/manifold_mala.py

Lines changed: 107 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,24 @@
1919
from coupled_rejection_sampling.mvn import coupled_mvns, mvn_logpdf
2020
from coupled_rejection_sampling.thorisson import modified_thorisson
2121

22+
2223
JAX_KEY = jax.random.PRNGKey(0)
23-
B = 1_000 # number of parallel coupled chains
24-
K = 50 # number of experiments
25-
CS = np.linspace(0.8, 0.99, 5)
26-
NS = [16, 32, 64]
24+
K = 10_000 # number of experiments
25+
CS = np.linspace(0.8, 0.99, 7)
26+
NS = [4, 8, 16, 32, 64, 128, 256]
2727

2828
ALPHA = 100. # Same wide prior as in mMALA paper
29-
EPS = 0.05
29+
EPS = 1.
3030

31-
RUN = True
31+
RUN = False
3232
PLOT = True
3333

3434
data_path = "data/heart.csv"
3535
save_path = "out/mmala.npz"
3636

3737

3838
def thorisson_sample(C):
39+
@jax.jit
3940
def sampler(key, x_mean, x_chol, y_mean, y_chol):
4041
def p_xy(k, mean, scale):
4142
return mean + scale @ jax.random.normal(k, (mean.shape[0],))
@@ -52,25 +53,26 @@ def p_xy(k, mean, scale):
5253

5354

5455
def rejection_sample(N):
56+
@jax.jit
5557
def sampler(key, x_mean, x_chol, y_mean, y_chol):
5658
X, Y, coupled, _ = coupled_mvns(key, x_mean, x_chol, y_mean, y_chol, N)
5759
return X, Y, coupled
5860

5961
return sampler
6062

6163

64+
@partial(jax.jit, static_argnums=(2,))
6265
def _get_manifold_langevin_discretisation(theta, eps, log_pi):
6366
"""Gets the mean and cholesky covariance of the proposal. This only considers flat manifolds"""
6467
d = theta.shape[0]
6568

6669
# Compute gradient and Fisher information
67-
value, grad = jax.value_and_grad(log_pi)(theta)
70+
grad = jax.grad(log_pi)(theta)
6871
fisher = -jax.hessian(log_pi)(theta)
69-
72+
# id_print(fisher, what="fisher autograd")
7073
# Get sqrt of inverse Fisher
7174
chol_fisher = jlinalg.cholesky(fisher, lower=True)
7275
inv_chol_fisher = jlinalg.solve_triangular(chol_fisher, jnp.eye(d), lower=True)
73-
7476
# Get mean
7577
mean = 0.5 * eps ** 2 * jlinalg.cho_solve((chol_fisher, True), grad)
7678

@@ -101,16 +103,15 @@ def simplified_manifold_mala_step(key, x, y, eps, sampler, log_pi):
101103

102104
x = jax.lax.select(accept_x, x_star, x)
103105
y = jax.lax.select(accept_y, y_star, y)
104-
105106
return x, y, accept_x & accept_y & coupled
106107

107108

108109
@partial(jax.jit, static_argnums=(2, 3, 4))
109110
def sample_coupled_chain(key, eps, sampler, log_pi, D):
110111
key, init_x_key, init_y_key = jax.random.split(key, 3)
111112

112-
x0 = jax.random.normal(init_x_key, (D,))
113-
y0 = jax.random.normal(init_y_key, (D,))
113+
x0 = 0.1 * jax.random.normal(init_x_key, (D,))
114+
y0 = 0.1 * jax.random.normal(init_y_key, (D,))
114115

115116
def cond(carry):
116117
return ~carry[-1]
@@ -120,7 +121,6 @@ def body(carry):
120121
op_key, sample_key = jax.random.split(op_key, 2)
121122
x, y, coupled = simplified_manifold_mala_step(sample_key, x, y, eps, sampler, log_pi)
122123
return op_key, x, y, iteration + 1, coupled
123-
124124
*_, meeting_time, _ = jax.lax.while_loop(cond, body, (key, x0, y0, 0, False))
125125
return meeting_time
126126

@@ -135,59 +135,52 @@ def experiment():
135135

136136
X = np.pad(X, [(0, 0), (0, 1)], constant_values=1)
137137

138-
y = df.values[:, -1].astype(bool)
138+
y = df.values[:, -1].astype(float)
139139

140-
def log_target(theta):
140+
@partial(jax.jit, static_argnames=("return_fisher",))
141+
def log_target(theta, return_fisher=False):
141142
prior = norm.logpdf(theta, 0., ALPHA ** 0.5).sum()
143+
temp = X @ theta
144+
log_lik = jnp.dot(y, temp) - jnp.sum(jax.nn.softplus(temp))
142145

143-
temp = -X @ theta
144-
log_probs_true = -jnp.logaddexp(0, temp)
145-
log_probs_false = temp + log_probs_true
146-
log_lik = jnp.where(y, log_probs_true, log_probs_false)
147-
return prior + jnp.nansum(log_lik)
146+
if not return_fisher:
147+
return log_lik + prior
148148

149-
rejection_meeting_times_res = np.empty((len(NS), K, B))
150-
thorisson_meeting_times_res = np.empty((len(CS), K, B))
149+
rejection_meeting_times_res = np.empty((len(NS), K))
150+
thorisson_meeting_times_res = np.empty((len(CS), K))
151151

152152
rejection_runtime_res = np.empty((len(NS), K))
153153
thorisson_runtime_res = np.empty((len(CS), K))
154154

155-
# Rejection:
156155
rej_key = JAX_KEY
157-
for i, N in enumerate(tqdm.tqdm(NS, leave=False)):
156+
for i, N in enumerate(tqdm.tqdm(NS, leave=True)):
158157
rej_sampler = rejection_sample(N)
159-
rej_experiment_fun = jax.jit(
160-
jax.vmap(lambda op_key: sample_coupled_chain(op_key, EPS, rej_sampler, log_target, dim)))
158+
rej_experiment_fun = jax.jit(lambda op_key: sample_coupled_chain(op_key, EPS, rej_sampler, log_target, dim))
161159

162160
# run it once to compile
163-
batched_keys = jax.random.split(JAX_KEY, B)
164-
block = rej_experiment_fun(batched_keys)
161+
block = rej_experiment_fun(rej_key)
165162
block.block_until_ready()
166-
for k in enumerate(tqdm.trange(K, leave=False)):
163+
for k in range(K):
167164
tic = time.time()
168165
rej_key, subkey = jax.random.split(rej_key)
169-
batched_keys = jax.random.split(subkey, B)
170166

171-
rej_out = rej_experiment_fun(batched_keys)
167+
rej_out = rej_experiment_fun(rej_key)
172168
rej_out.block_until_ready()
173169
rejection_meeting_times_res[i, k] = rej_out
174170
rejection_runtime_res[i, k] = time.time() - tic
175171

176172
thor_key = JAX_KEY
177-
for j, C in enumerate(tqdm.tqdm(CS, leave=False)):
173+
for j, C in enumerate(tqdm.tqdm(CS, leave=True)):
178174
thor_sampler = thorisson_sample(C)
179-
thor_experiment_fun = jax.jit(
180-
jax.vmap(lambda op_key: sample_coupled_chain(op_key, EPS, thor_sampler, log_target, dim)))
175+
thor_experiment_fun = jax.jit(lambda op_key: sample_coupled_chain(op_key, EPS, thor_sampler, log_target, dim))
181176

182177
# run it once to compile
183-
batched_keys = jax.random.split(JAX_KEY, B)
184-
block = thor_experiment_fun(batched_keys)
178+
block = thor_experiment_fun(thor_key)
185179
block.block_until_ready()
186-
for k in tqdm.trange(K):
180+
for k in range(K):
187181
tic = time.time()
188182
thor_key, subkey = jax.random.split(thor_key)
189-
batched_keys = jax.random.split(subkey, B)
190-
thor_out = thor_experiment_fun(batched_keys)
183+
thor_out = thor_experiment_fun(thor_key)
191184
thor_out.block_until_ready()
192185
thorisson_meeting_times_res[j, k] = thor_out
193186
thorisson_runtime_res[j, k] = time.time() - tic
@@ -205,60 +198,78 @@ def log_target(theta):
205198
cmap = plt.get_cmap("tab10")
206199
data = np.load(save_path)
207200

208-
fig, axes = plt.subplots(ncols=2, figsize=(15, 6), sharey=True)
209-
210-
for i, D in enumerate(DS):
211-
axes[0].set_title("Rejection")
212-
axes[0].set_xscale("log")
213-
axes[0].set_yscale("log")
214-
axes[0].plot(data["NS"], data["rejection_meeting_times"][i].mean(-1).mean(-1),
215-
color=cmap(i), label=f"$D={D}$")
216-
axes[0].fill_between(data["NS"],
217-
data["rejection_meeting_times"][i].mean(-1).mean(-1) - 1.96 *
218-
data["rejection_meeting_times"][i].mean(-1).std(-1),
219-
data["rejection_meeting_times"][i].mean(-1).mean(-1) + 1.96 *
220-
data["rejection_meeting_times"][i].mean(-1).std(-1),
221-
color=cmap(i), alpha=0.66)
222-
223-
axes[1].set_title("Thorisson")
224-
axes[1].plot(data["CS"], data["thorisson_meeting_times"][i].mean(-1).mean(-1),
225-
color=cmap(i), label=f"$D={D}$")
226-
axes[1].fill_between(data["CS"],
227-
data["thorisson_meeting_times"][i].mean(-1).mean(-1) - 1.96 *
228-
data["thorisson_meeting_times"][i].mean(-1).std(-1),
229-
data["thorisson_meeting_times"][i].mean(-1).mean(-1) + 1.96 *
230-
data["thorisson_meeting_times"][i].mean(-1).std(-1),
231-
color=cmap(i), alpha=0.66)
232-
axes[1].set_yscale("log")
233-
axes[1].xaxis.set_major_formatter(FormatStrFormatter('%.1f'))
234-
axes[1].legend()
235-
tikzplotlib.save("out/gibbs_meeting_time.tikz")
236-
237-
fig, axes = plt.subplots(ncols=2, figsize=(15, 6), sharey=True)
238-
239-
for i, D in enumerate(DS):
240-
axes[0].set_title("Rejection")
241-
axes[0].set_xscale("log")
242-
axes[0].set_yscale("log")
243-
axes[0].plot(data["NS"], data["rejection_runtime"][i].mean(-1),
244-
color=cmap(i), label=f"$D={D}$")
245-
axes[0].fill_between(data["NS"],
246-
data["rejection_runtime"][i].mean(-1) - 1.96 *
247-
data["rejection_runtime"][i].std(-1),
248-
data["rejection_runtime"][i].mean(-1) + 1.96 *
249-
data["rejection_runtime"][i].std(-1),
250-
color=cmap(i), alpha=0.66)
251-
axes[1].set_title("Thorisson")
252-
axes[1].plot(data["CS"], data["thorisson_runtime"][i].mean(-1),
253-
color=cmap(i), label=f"$D={D}$")
254-
axes[1].fill_between(data["CS"],
255-
data["thorisson_runtime"][i].mean(-1) - 1.96 *
256-
data["thorisson_runtime"][i].std(-1),
257-
data["thorisson_runtime"][i].mean(-1) + 1.96 *
258-
data["thorisson_runtime"][i].std(-1),
259-
color=cmap(i), alpha=0.66)
260-
axes[1].set_yscale("log")
261-
axes[1].xaxis.set_major_formatter(FormatStrFormatter('%.1f'))
262-
axes[1].legend()
263-
264-
tikzplotlib.save("out/gibbs_run_time.tikz")
201+
index = pd.MultiIndex.from_product([["meeting time", "run time (s)"], ["mean", "standard deviation"]])
202+
thorisson_df = pd.DataFrame(columns=data["CS"], index=index)
203+
rejection_df = pd.DataFrame(columns=data["NS"], index=index)
204+
205+
thorisson_df.loc[("meeting time", "mean")] = [f"${v.mean(-1):.1f}$" for v in data["thorisson_meeting_times"]]
206+
thorisson_df.loc[("run time (s)", "mean")] = [f"${v.mean(-1):.1e}$" for v in data["thorisson_runtime"][:, 1:]]
207+
208+
rejection_df.loc[("meeting time", "mean")] = [f"${v.mean(-1):.1f}$" for v in data["rejection_meeting_times"]]
209+
rejection_df.loc[("run time (s)", "mean")] = [f"${v.mean(-1):.1e}$" for v in data["rejection_runtime"][:, 1:]]
210+
211+
212+
thorisson_df.loc[("meeting time", "standard deviation")] = [f"${v.std(-1):.1f}$" for v in data["thorisson_meeting_times"]]
213+
thorisson_df.loc[("run time (s)", "standard deviation")] = [f"${v.std(-1):.1e}$" for v in data["thorisson_runtime"][:, 1:]]
214+
215+
rejection_df.loc[("meeting time", "standard deviation")] = [f"${v.std(-1):.1f}$" for v in data["rejection_meeting_times"]]
216+
rejection_df.loc[("run time (s)", "standard deviation")] = [f"${v.std(-1):.1e}$" for v in data["rejection_runtime"][:, 1:]]
217+
218+
219+
print(rejection_df.to_latex("out/rejection_mmala.tex"))
220+
print(thorisson_df.to_latex("out/thorisson_mmala.tex"))
221+
# for i, D in enumerate(DS):
222+
# axes[0].set_title("Rejection")
223+
# axes[0].set_xscale("log")
224+
# axes[0].set_yscale("log")
225+
# axes[0].plot(data["NS"], data["rejection_meeting_times"][i].mean(-1).mean(-1),
226+
# color=cmap(i), label=f"$D={D}$")
227+
# axes[0].fill_between(data["NS"],
228+
# data["rejection_meeting_times"][i].mean(-1).mean(-1) - 1.96 *
229+
# data["rejection_meeting_times"][i].mean(-1).std(-1),
230+
# data["rejection_meeting_times"][i].mean(-1).mean(-1) + 1.96 *
231+
# data["rejection_meeting_times"][i].mean(-1).std(-1),
232+
# color=cmap(i), alpha=0.66)
233+
#
234+
# axes[1].set_title("Thorisson")
235+
# axes[1].plot(data["CS"], data["thorisson_meeting_times"][i].mean(-1).mean(-1),
236+
# color=cmap(i), label=f"$D={D}$")
237+
# axes[1].fill_between(data["CS"],
238+
# data["thorisson_meeting_times"][i].mean(-1).mean(-1) - 1.96 *
239+
# data["thorisson_meeting_times"][i].mean(-1).std(-1),
240+
# data["thorisson_meeting_times"][i].mean(-1).mean(-1) + 1.96 *
241+
# data["thorisson_meeting_times"][i].mean(-1).std(-1),
242+
# color=cmap(i), alpha=0.66)
243+
# axes[1].set_yscale("log")
244+
# axes[1].xaxis.set_major_formatter(FormatStrFormatter('%.1f'))
245+
# axes[1].legend()
246+
# tikzplotlib.save("out/gibbs_meeting_time.tikz")
247+
#
248+
# fig, axes = plt.subplots(ncols=2, figsize=(15, 6), sharey=True)
249+
#
250+
# for i, D in enumerate(DS):
251+
# axes[0].set_title("Rejection")
252+
# axes[0].set_xscale("log")
253+
# axes[0].set_yscale("log")
254+
# axes[0].plot(data["NS"], data["rejection_runtime"][i].mean(-1),
255+
# color=cmap(i), label=f"$D={D}$")
256+
# axes[0].fill_between(data["NS"],
257+
# data["rejection_runtime"][i].mean(-1) - 1.96 *
258+
# data["rejection_runtime"][i].std(-1),
259+
# data["rejection_runtime"][i].mean(-1) + 1.96 *
260+
# data["rejection_runtime"][i].std(-1),
261+
# color=cmap(i), alpha=0.66)
262+
# axes[1].set_title("Thorisson")
263+
# axes[1].plot(data["CS"], data["thorisson_runtime"][i].mean(-1),
264+
# color=cmap(i), label=f"$D={D}$")
265+
# axes[1].fill_between(data["CS"],
266+
# data["thorisson_runtime"][i].mean(-1) - 1.96 *
267+
# data["thorisson_runtime"][i].std(-1),
268+
# data["thorisson_runtime"][i].mean(-1) + 1.96 *
269+
# data["thorisson_runtime"][i].std(-1),
270+
# color=cmap(i), alpha=0.66)
271+
# axes[1].set_yscale("log")
272+
# axes[1].xaxis.set_major_formatter(FormatStrFormatter('%.1f'))
273+
# axes[1].legend()
274+
#
275+
# tikzplotlib.save("out/gibbs_run_time.tikz")

0 commit comments

Comments
 (0)