Skip to content

Commit ca19472

Browse files
committed
implemented feedback
1 parent 365bccd commit ca19472

1 file changed

Lines changed: 29 additions & 34 deletions

File tree

solution.py

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ def forward(self, x):
275275
# * However, sampling `z` directly from `mu` and $std$(`logvar`) does not allow for backpropagation (random sampling is not differentiable)
276276
# * To allow for backpropagation, we isolate the non-differentiable random sampling node and sample $\epsilon$ from a Normal distritubion with mean 0 and standard deviation 1
277277
# * We then use this $\epsilon$ to produce `z`: `z` $=$ `mu` $+ \epsilon * e^{logvar/2}$ (here, gradient can flow through `mu` and `logvar`)
278+
#
279+
# ![Reparameterization trick](./assets/Reparameterization_Trick.png)
280+
# Source: [Wikipedia](https://en.wikipedia.org/wiki/Reparameterization_trick#).
281+
#
278282
#
279283
# **The decode function**:
280284
# * Takes in a latent vector `z` and uses an MLP to reconstruct the original sample, reshaping as appropriate.
@@ -509,8 +513,15 @@ def test_vae(w=28, h=28, latent_dim=16, batch_size=8):
509513
# The reconstruction loss
510514
rec_loss = nn.BCELoss(reduction="sum")
511515

516+
# %% [markdown]
517+
#
512518

513519
# The KL loss
520+
# %% tags=["task"]
521+
def kl_loss(mu, logvar):
522+
return ...
523+
524+
# %% tags=["solution"]
514525
def kl_loss(mu, logvar):
515526
# sum over latent dimensions, mean over batch
516527
return torch.mean(-0.5 * torch.sum(1 + logvar - mu**2 - logvar.exp(), dim=1))
@@ -689,7 +700,7 @@ def train_epochs(n, model, loader, optimizer, loss, beta, plot_every=10):
689700

690701
# %%
691702
epochs = 100
692-
train_epochs(epochs, model, train_loader, optimizer, loss, beta = 1);
703+
train_epochs(epochs, model, train_loader, optimizer, loss, beta = 1)
693704

694705
# %% [markdown]
695706
# ### Part A.2.5: Inspect the trained model
@@ -789,7 +800,7 @@ def train_epochs(n, model, loader, optimizer, loss, beta, plot_every=10):
789800
ax[2].set_title("rec 2")
790801
plt.colorbar(im1, shrink = 0.2)
791802

792-
im2 = ax[3].imshow(rec_1 - rec_2, cmap= "Grays")
803+
im2 = ax[3].imshow(rec_1 - rec_2, cmap= "RdBu")
793804
ax[3].set_title("rec 1 - rec 2")
794805
plt.colorbar(im2, shrink = 0.2)
795806

@@ -870,6 +881,8 @@ def view_test_sample(model, loader):
870881

871882
# %% [markdown]
872883
# <div class="alert alert-block alert-info"><h2>Task</h2>
884+
# We will now train two models, `model0` without regularization and `model1` with regularization.
885+
# To acheive this, we set the `beta` parameter for the loss used with `model0` to `0`.
873886
#
874887
# Let's train our first "serious" model.
875888
# * Instantiate a new variational autoencoder model and name it `model0`
@@ -945,12 +958,10 @@ def view_test_sample(model, loader):
945958
model1 = VariationalAutoEncoder(w, h, latent_dim=2).to(device)
946959
optimizer = Adam(model1.parameters(), lr=0.0001) # fresh optimizer
947960
epochs = 1000
948-
beta = 0
961+
beta = # TODO
949962
losses1 = train_epochs(epochs, model1, train_loader, optimizer, loss, beta = beta)
950963

951964

952-
953-
954965
# %% tags=["solution"]
955966
# beta 1
956967
model1 = VariationalAutoEncoder(w, h, latent_dim=2).to(device)
@@ -1089,12 +1100,8 @@ def scatter_digits(ax, mus, lbls, mu_mean=None, alpha=1, CMAP = "tab10"):
10891100

10901101
if mu_mean is not None:
10911102
for d in range(10):
1092-
ax.scatter(*mu_mean[d], s=220, color="white", edgecolors="white", linewidths=3, marker="X", zorder=9)
1093-
ax.scatter(*mu_mean[d], s=80, color=CMAP(d), edgecolors="black", linewidths=0.5, marker="X", zorder=10)
1094-
ax.annotate(str(d), xy=mu_mean[d], fontsize=8, fontweight="bold",
1095-
ha="center", va="bottom", xytext=(0, 5),
1096-
textcoords="offset points", zorder=11,
1097-
bbox=dict(boxstyle="round,pad=0.15", fc="white", ec="none", alpha=0.8))
1103+
ax.scatter(*mu_mean[d], s=100, color="white", edgecolors="white", linewidths=0.4, marker="X", zorder=9)
1104+
ax.scatter(*mu_mean[d], s=70, color=CMAP(d), edgecolors="black", linewidths=0.5, marker="X", zorder=10)
10981105

10991106
ax.legend(title="Digit", markerscale=6, ncol=2, fontsize=7, loc="best")
11001107
ax.set_aspect("equal")
@@ -1110,14 +1117,14 @@ def scatter_with_normal(ax, mus, lbls, rnd_normal, mean, std):
11101117
ax.set_aspect("equal")
11111118

11121119

1113-
def plot_latent_digits(mus_model0, lbls0, mu_mean0, mus_model1, lbls1, mu_mean1):
1120+
def plot_latent_digits(mus_model0, lbls0, mu_mean0, mus_model1, lbls1, mu_mean1, alpha=1, CMAP = "tab10"):
11141121
"""Latent space coloured by digit, with per-class centroids."""
11151122
fig, axes = plt.subplots(1, 2, figsize=(13, 5))
11161123
for ax, mus, lbls, mu_mean, title in [
11171124
(axes[0], mus_model0, lbls0, mu_mean0, "model0: β=0 latent space"),
11181125
(axes[1], mus_model1, lbls1, mu_mean1, "model1: β>0 latent space"),
11191126
]:
1120-
scatter_digits(ax, mus, lbls, mu_mean=mu_mean)
1127+
scatter_digits(ax, mus, lbls, mu_mean=mu_mean, alpha=alpha, CMAP=CMAP)
11211128
ax.set_title(title, fontsize=11)
11221129
ax.set_xlabel("mu₁"); ax.set_ylabel("mu₂")
11231130
fig.suptitle("Latent space — coloured by digit", fontsize=13)
@@ -1203,7 +1210,7 @@ def plot_latent_vs_normal(mus_model0, lbls0, mus_model1, lbls1, rnd_normal,
12031210
#
12041211
# Below we will sample 100 values `z` from `mu` and `logvar`.
12051212
#
1206-
# So each of the 10000 test-image is represented by 100 points – 100000 points in total.
1213+
# So each of the 10000 test-image is represented by 100 points – 1000000 points in total.
12071214

12081215
# %%
12091216
def sample_from_latents(mus, logvars, n_samples=100):
@@ -1340,7 +1347,7 @@ def plot_decision_boundaries(ax, clf, mus, lbls, title, resolution=500, CMAP="ta
13401347

13411348
# Draw crisp decision boundaries
13421349
ax.contour(xx, yy, grid_preds, levels=np.arange(-0.5, 10, 1),
1343-
colors="k", linewidths=0.4, zorder=1)
1350+
colors="k", linewidths=0.4, zorder=10)
13441351

13451352
# Overlay data points
13461353
scatter_digits(ax, mus, lbls)
@@ -1444,6 +1451,11 @@ def gen_mean_numbers(model, mu_mean, title):
14441451
# We can decode points sampled along the straight line between two centroids in latent space. A visualization will be plotted below.
14451452
#
14461453

1454+
# %% [markdown]
1455+
# <div class="alert alert-block alert-warning"><h3>Questions</h3>
1456+
# Can we interpolate and reconstruct the same way with different architectures? (AE, ResNet, UNet, etc...)
1457+
# </div>
1458+
14471459
# %% [markdown]
14481460
# <div class="alert alert-block alert-info"><h2>Task</h2>
14491461
# Run the code below without modifications. You should see reconstructions of interpolated images along the path between the centroids of 0 and 6. <br>
@@ -1656,28 +1668,11 @@ def run_umap(latents, n_components=2, random_state=42, n_neighbors=15, min_dist=
16561668
return mu_2d
16571669

16581670

1659-
def plot_umap(mu_2d, labels,
1660-
cmap='tab10', alpha=0.6, s=10, centers=None, center_labels=None):
1661-
1662-
ticks = np.unique(labels)
1663-
base_cmap = plt.get_cmap(cmap)
1664-
colors_n = base_cmap(np.linspace(0, 1, np.max(ticks) + 1))
1665-
new_cmap = ListedColormap(colors_n)
1666-
1667-
plt.figure(figsize=(10, 8))
1668-
scatter = plt.scatter(mu_2d[:, 0], mu_2d[:, 1], c=labels, cmap=new_cmap, alpha=alpha, s=s)
1669-
plt.colorbar(scatter, ticks=ticks)
1670-
1671-
if centers is not None:
1672-
for i, label in enumerate(center_labels):
1673-
plt.text(centers[i, 0], centers[i, 1], s=str(label), backgroundcolor="white", size='large')
1674-
plt.scatter(centers[:, 0], centers[:, 1], s=50, marker="X", c="k", zorder=10000)
1675-
plt.axis('off')
1676-
16771671

16781672
# %%
16791673
mu_2d_2, mu_means_2d_2 = run_umap(mus2, means = mu_mean2)
1680-
plot_umap(mu_2d_2, lbls2, cmap = "tab10", centers = mu_means_2d_2, center_labels=range(10))
1674+
_, ax = plt.subplots(1, 1, figsize=(10, 8))
1675+
scatter_digits(ax, mu_2d_2, lbls2, mu_means_2d_2, alpha=0.6)
16811676

16821677
# %% [markdown]
16831678
# Clusters look well-separated, but we should verify with logistic regression.

0 commit comments

Comments
 (0)