Skip to content

Commit 86d6cc6

Browse files
Started the reflected max example
1 parent 6e75862 commit 86d6cc6

2 files changed

Lines changed: 63 additions & 64 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
""" This algorithm implements Algorithm 4 of Maximal Couplings of the Metropolis-Hastings
2+
Algorithm to compare with our method in the manifold MALA case. It is however coded in a fairly generic manner, so I
3+
felt like putting it in the main code.
4+
"""
5+
import jax
6+
import jax.numpy as jnp
7+
8+
from coupled_rejection_sampling.utils import logsubexp
9+
10+
11+
def reflection_coupled_mh(kernel, kernel_log_density):
12+
def r_xy_fn(x, y, x_prime):
13+
log_p_x_zp = kernel_log_density(x_prime, x)
14+
log_p_y_zp = kernel_log_density(x_prime, y)
15+
return logsubexp(log_p_x_zp, log_p_y_zp)
16+
17+
def tr_xy_fn(x, y, x_prime):
18+
y_refl = _transport_fn(x, y, x_prime)
19+
r_xy_xp = r_xy_fn(x, y, x_prime)
20+
r_yx_yp = r_xy_fn(y, y, y_refl)
21+
return logsubexp(r_xy_xp, r_yx_yp)
22+
23+
24+
def _residual(x, y):
25+
def cond(carry):
26+
return ~carry[-1]
27+
28+
def body(carry):
29+
op_key, y_prop, _ = carry
30+
next_key, subkey1, subkey2 = jax.random.split(op_key)
31+
y_prop, accepted_y = kernel(subkey2, y)
32+
33+
def if_accepted(_):
34+
log_u = jnp.log(jax.random.uniform(subkey1))
35+
log_p_y_yp = kernel_log_density(y_prop, y)
36+
log_p_res_y_yp = tr_xy_fn(y, x, y_prop)
37+
accept = log_u < log_p_res_y_yp - log_p_y_yp
38+
return y_prop, accept
39+
40+
return jax.lax.cond(accepted_y, lambda _: (y_prop, False), if_accepted, None)
41+
42+
def step(key, x, y):
43+
subkey1, subkey2, subkey3 = key
44+
x_prime, accepted_x = kernel(subkey1, x)
45+
46+
47+
48+
def _transport_fn(x, y, x_prime):
49+
r_curr = jnp.linalg.norm(y - x)
50+
e = jax.lax.select(r_curr < 1e-8, jnp.zeros_like(x), (y - x) / r_curr)
51+
x_diff = x_prime - x
52+
eta = x_diff - 2 * e * e.dot(x_diff)
53+
y = x + eta
54+
return y

examples/manifold_mala.py

Lines changed: 9 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,13 @@
1010
import jax.scipy.linalg as jlinalg
1111
import numpy as np
1212
import pandas as pd
13-
import tikzplotlib
1413
import tqdm.auto as tqdm
1514
from jax.scipy.stats import norm
1615
from matplotlib import pyplot as plt
17-
from matplotlib.ticker import FormatStrFormatter
1816

1917
from coupled_rejection_sampling.mvn import coupled_mvns, mvn_logpdf
2018
from coupled_rejection_sampling.thorisson import modified_thorisson
2119

22-
2320
JAX_KEY = jax.random.PRNGKey(0)
2421
K = 10_000 # number of experiments
2522
CS = np.linspace(0.8, 0.99, 7)
@@ -121,6 +118,7 @@ def body(carry):
121118
op_key, sample_key = jax.random.split(op_key, 2)
122119
x, y, coupled = simplified_manifold_mala_step(sample_key, x, y, eps, sampler, log_pi)
123120
return op_key, x, y, iteration + 1, coupled
121+
124122
*_, meeting_time, _ = jax.lax.while_loop(cond, body, (key, x0, y0, 0, False))
125123
return meeting_time
126124

@@ -208,68 +206,15 @@ def log_target(theta, return_fisher=False):
208206
rejection_df.loc[("meeting time", "mean")] = [f"${v.mean(-1):.1f}$" for v in data["rejection_meeting_times"]]
209207
rejection_df.loc[("run time (s)", "mean")] = [f"${v.mean(-1):.1e}$" for v in data["rejection_runtime"][:, 1:]]
210208

209+
thorisson_df.loc[("meeting time", "standard deviation")] = [f"${v.std(-1):.1f}$" for v in
210+
data["thorisson_meeting_times"]]
211+
thorisson_df.loc[("run time (s)", "standard deviation")] = [f"${v.std(-1):.1e}$" for v in
212+
data["thorisson_runtime"][:, 1:]]
211213

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-
214+
rejection_df.loc[("meeting time", "standard deviation")] = [f"${v.std(-1):.1f}$" for v in
215+
data["rejection_meeting_times"]]
216+
rejection_df.loc[("run time (s)", "standard deviation")] = [f"${v.std(-1):.1e}$" for v in
217+
data["rejection_runtime"][:, 1:]]
218218

219219
print(rejection_df.to_latex("out/rejection_mmala.tex"))
220220
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)