# Domain
x = np.linspace(0, 2 * np.pi, 1000)[:, None]
# Basis functions
feats = np.hstack([np.sin(x), np.cos(x)])
# Random coefficients
rng = np.random.default_rng(42)
coeffs = rng.normal(size=2)
# Angles used for displaying functions
plot_angles = np.linspace(0, 2 * np.pi, 24, endpoint=False)
# Angles used for computing the density curves
density_angles = np.linspace(0, 2 * np.pi, 500)
fig, axes = plt.subplots(
2,
1,
figsize=(10, 6),
constrained_layout=True,
gridspec_kw={"height_ratios": [2, 1]},
)
# --------------------------------------------------------------------
# Top plot: functions
# --------------------------------------------------------------------
cmap = plt.get_cmap("twilight_shifted")
norm = mpl.colors.Normalize(vmin=0, vmax=2 * np.pi)
for angle in plot_angles:
R = np.array([
[np.cos(angle), -np.sin(angle)],
[np.sin(angle), np.cos(angle)],
])
rotated_coeffs = R @ coeffs
axes[0].plot(
x,
feats @ rotated_coeffs,
color=cmap(norm(angle)),
lw=1.5,
alpha=0.9,
)
# Original function
axes[0].plot(
x,
feats @ coeffs,
color="black",
lw=3,
label="Original coefficients",
zorder=10,
)
axes[0].set_title("Functions induced by rotating the coefficient vector")
axes[0].set_ylabel(r"$f(x)$")
axes[0].set_xlim(0, 2 * np.pi)
axes[0].set_xticks([0, np.pi / 2, np.pi, 3 * np.pi / 2, 2 * np.pi])
axes[0].set_xticklabels([])
axes[0].legend()
# Colorbar
sm = mpl.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])
cbar = fig.colorbar(
sm,
ax=axes[0],
pad=0.02,
fraction=0.05,
)
cbar.set_label("Rotation angle")
cbar.set_ticks([0, np.pi / 2, np.pi, 3 * np.pi / 2, 2 * np.pi])
cbar.set_ticklabels(
[r"$0$", r"$\pi/2$", r"$\pi$", r"$3\pi/2$", r"$2\pi$"]
)
# --------------------------------------------------------------------
# Bottom plot: prior densities
# --------------------------------------------------------------------
normal_density = np.empty_like(density_angles)
laplace_density = np.empty_like(density_angles)
for i, angle in enumerate(density_angles):
R = np.array([
[np.cos(angle), -np.sin(angle)],
[np.sin(angle), np.cos(angle)],
])
rotated_coeffs = R @ coeffs
normal_density[i] = np.prod(stats.norm.pdf(rotated_coeffs))
laplace_density[i] = np.prod(stats.laplace.pdf(rotated_coeffs))
axes[1].plot(
density_angles,
normal_density,
color="C0",
lw=2.5,
label="Normal prior",
)
axes[1].plot(
density_angles,
laplace_density,
color="C1",
lw=2.5,
label="Laplace prior",
)
axes[1].set_title("Prior density under coefficient rotation")
axes[1].set_xlabel("Rotation angle")
axes[1].set_ylabel("Joint density")
axes[1].set_xlim(0, 2 * np.pi)
axes[1].set_xticks([0, np.pi / 2, np.pi, 3 * np.pi / 2, 2 * np.pi])
axes[1].set_xticklabels(
[r"$0$", r"$\pi/2$", r"$\pi$", r"$3\pi/2$", r"$2\pi$"]
)
axes[1].legend()
plt.show()