# @title Auxiliary: Scene 4–5 explanatory figures
def draw_numeric_grid(ax, values, title, *, decimals=2):
limit = max(float(values.abs().max()), 1e-6)
ax.imshow(values.numpy(), cmap=SIGNED_CMAP, vmin=-limit, vmax=limit)
write_grid_values(ax, values, decimals=decimals, threshold=0.55 * limit, fontsize=8)
ax.set_xticks(range(values.shape[1]))
ax.set_yticks(range(values.shape[0]))
ax.set_title(title, fontsize=10, color=COURSE_NAVY)
def export_color_convolution_keyframe(photo_hwc, patch_origin, weights, biases,
contributions, outputs, responses, filter_names):
patch_row, patch_column = patch_origin
fig = plt.figure(figsize=(14.0, 8.5), constrained_layout=True)
grid = fig.add_gridspec(3, 5, height_ratios=(1.35, 1, 1))
image_ax = fig.add_subplot(grid[0, :2])
image_ax.imshow(photo_hwc.numpy())
image_ax.add_patch(Rectangle((patch_column - 0.5, patch_row - 0.5), 3, 3,
fill=False, edgecolor=COURSE_BLUE, linewidth=2.4))
image_ax.set_title("Chelsea RGB input; exact $3\\times3$ patch outlined", color=COURSE_NAVY)
image_ax.set_xticks([]); image_ax.set_yticks([])
response_limit = max(float(responses.abs().max()), 1e-6)
for output_channel in range(2):
ax = fig.add_subplot(grid[0, output_channel + 2])
artist = ax.imshow(responses[output_channel].numpy(), cmap=SIGNED_CMAP,
vmin=-response_limit, vmax=response_limit)
ax.add_patch(Rectangle((patch_column - 0.5, patch_row - 0.5), 1, 1,
fill=False, edgecolor=COURSE_BLUE, linewidth=2))
ax.set_title(f"output {output_channel}: {filter_names[output_channel]}\n"
f"signed response {tuple(responses[output_channel].shape)}",
fontsize=10, color=COURSE_NAVY)
ax.set_xticks([]); ax.set_yticks([])
color_ax = fig.add_subplot(grid[0, 4])
color_ax.axis("off")
fig.colorbar(artist, ax=color_ax, fraction=0.8, label="signed response (not normalized)")
channel_names = ("red", "green", "blue")
for output_channel in range(2):
label_ax = fig.add_subplot(grid[output_channel + 1, 0])
label_ax.axis("off")
label_ax.text(0.02, 0.72, f"output channel {output_channel}", fontsize=13,
fontweight="bold", color=COURSE_NAVY)
label_ax.text(0.02, 0.48, filter_names[output_channel], fontsize=11,
color=COURSE_BLUE, wrap=True)
label_ax.text(0.02, 0.17, "three input-channel slices $\\rightarrow$ one output",
fontsize=9, color=COURSE_GRAY)
for input_channel, channel_name in enumerate(channel_names):
ax = fig.add_subplot(grid[output_channel + 1, input_channel + 1])
draw_numeric_grid(
ax, weights[output_channel, input_channel],
f"{channel_name} slice $W[{output_channel},{input_channel}]$\n"
f"patch contribution {contributions[output_channel, input_channel].item():+.4f}",
decimals=2,
)
total_ax = fig.add_subplot(grid[output_channel + 1, 4])
total_ax.axis("off")
terms = " + ".join(f"{value.item():+.4f}" for value in contributions[output_channel])
total_ax.text(0.5, 0.68, "channel sums + bias", ha="center", color=COURSE_GRAY)
total_ax.text(0.5, 0.47, terms, ha="center", fontsize=9, color=COURSE_NAVY)
total_ax.text(0.5, 0.30, f"+ {biases[output_channel].item():+.3f}",
ha="center", fontsize=10, color=COURSE_NAVY)
total_ax.text(0.5, 0.10, f"= {outputs[output_channel].item():+.4f}",
ha="center", fontsize=14, fontweight="bold", color=COURSE_BLUE)
fig.suptitle("Each output filter has its own RGB slices; every slice contributes",
fontsize=16, fontweight="bold", color=COURSE_NAVY)
return save_static_figure(fig, "04-color-convolution-key-frame")
def export_spatial_controls_keyframes(image, kernel, cases):
fig, axes = plt.subplots(3, 3, figsize=(12.5, 10.0), constrained_layout=True)
colours = (COURSE_BLUE, "#d97706", "#7c3aed")
for row, case in enumerate(cases):
name, response, padding, stride, starts = case
padded = F.pad(image.reshape(1, 1, *image.shape),
(padding, padding, padding, padding))[0, 0]
input_ax, parameter_ax, output_ax = axes[row]
input_ax.imshow(padded.numpy(), cmap="gray", vmin=0, vmax=1)
if padding:
input_ax.add_patch(Rectangle((padding - 0.5, padding - 0.5), 28, 28,
fill=False, edgecolor="#9ca3af", linestyle="--"))
for colour, (start_row, start_column) in zip(colours, starts):
input_ax.add_patch(Rectangle((start_column - 0.5, start_row - 0.5), 3, 3,
fill=False, edgecolor=colour, linewidth=2))
input_ax.set_title(f"{name}: {'padded ' if padding else ''}input {tuple(padded.shape)}")
input_ax.set_xticks([]); input_ax.set_yticks([])
parameter_ax.axis("off")
parameter_ax.text(0.5, 0.78, "$k=3$", ha="center", fontsize=15, color=COURSE_NAVY)
parameter_ax.text(0.5, 0.58, f"$p={padding}$", ha="center", fontsize=15, color=COURSE_NAVY)
parameter_ax.text(0.5, 0.38, f"$s={stride}$", ha="center", fontsize=15, color=COURSE_NAVY)
parameter_ax.annotate("window starts\nmap to output cells", xy=(0.92, 0.5),
xytext=(0.08, 0.5), ha="center", va="center",
arrowprops=dict(arrowstyle="->", color=COURSE_BLUE, lw=2),
color=COURSE_GRAY)
height, width = response.shape
output_ax.set_xlim(-1, 29); output_ax.set_ylim(29, -1); output_ax.set_aspect("equal")
output_ax.add_patch(Rectangle((-0.5, -0.5), width, height,
facecolor="#f3f4f6", edgecolor=COURSE_NAVY, linewidth=2))
output_positions = [(start_row // stride, start_column // stride)
for start_row, start_column in starts]
for colour, (out_row, out_column) in zip(colours, output_positions):
output_ax.add_patch(Rectangle((out_column - 0.5, out_row - 0.5), 1, 1,
facecolor=colour, edgecolor=colour))
output_ax.set_title(f"output grid {height}×{width}\n{height * width} evaluated windows")
output_ax.set_xticks([]); output_ax.set_yticks([])
fig.suptitle("Padding changes the input domain; stride changes which starts are evaluated",
fontsize=15, fontweight="bold", color=COURSE_NAVY)
return save_static_figure(fig, "05-spatial-controls-key-frames")
def export_pooling_window(window, winner, winner_offset, output_index):
fig, axes = plt.subplots(1, 3, figsize=(8.7, 2.8), constrained_layout=True,
gridspec_kw={"width_ratios": (1.2, 0.7, 1.2)})
draw_numeric_grid(axes[0], window, "four signed responses", decimals=3)
axes[0].add_patch(Rectangle((winner_offset[1] - 0.5, winner_offset[0] - 0.5), 1, 1,
fill=False, edgecolor="#d97706", linewidth=3))
axes[1].axis("off")
axes[1].annotate("choose max", xy=(0.95, 0.5), xytext=(0.05, 0.5),
arrowprops=dict(arrowstyle="->", lw=2, color=COURSE_BLUE),
va="center", color=COURSE_GRAY)
axes[2].axis("off")
axes[2].add_patch(Rectangle((0.2, 0.25), 0.6, 0.5, facecolor="#dbe7ff",
edgecolor=COURSE_BLUE, linewidth=2))
axes[2].text(0.5, 0.52, f"{winner.item():+.3f}", ha="center", va="center",
fontsize=17, fontweight="bold", color=COURSE_NAVY)
axes[2].text(0.5, 0.12, f"pooled output {output_index}", ha="center", color=COURSE_GRAY)
fig.suptitle("Max pooling keeps one value and discards the other three",
fontsize=14, fontweight="bold", color=COURSE_NAVY)
return save_static_figure(fig, "05-max-pooling-window")
def export_receptive_field_trace(traced, size, spacing):
fig, ax = plt.subplots(figsize=(11.0, 5.2), constrained_layout=True)
ax.axis("off"); ax.set_xlim(-0.7, 8.8); ax.set_ylim(-0.6, 3.1)
layer_y = {"input": 0.1, "layer1": 1.35, "layer2": 2.55}
for index in range(8):
ax.add_patch(Rectangle((index, layer_y["input"]), 0.72, 0.48,
facecolor="#f3f4f6", edgecolor=COURSE_NAVY))
ax.text(index + 0.36, layer_y["input"] + 0.24, f"$x_{index}$", ha="center", va="center")
for index in range(6):
ax.add_patch(Rectangle((index + 0.5, layer_y["layer1"]), 0.72, 0.48,
facecolor="#dbe7ff", edgecolor=COURSE_BLUE))
ax.text(index + 0.86, layer_y["layer1"] + 0.24, f"$h^1_{index}$", ha="center", va="center")
for index, colour in zip((0, 1), (COURSE_BLUE, "#d97706")):
x = 1.0 + 2 * index
ax.add_patch(Rectangle((x, layer_y["layer2"]), 0.72, 0.48,
facecolor="white", edgecolor=colour, linewidth=2.5))
ax.text(x + 0.36, layer_y["layer2"] + 0.24, f"$h^2_{index}$", ha="center", va="center")
for middle in (2 * index, 2 * index + 1):
middle_x = middle + 0.86
ax.plot([x + 0.36, middle_x], [layer_y["layer2"], layer_y["layer1"] + 0.48],
color=colour, alpha=0.8)
for source in range(middle, middle + 3):
ax.plot([middle_x, source + 0.36], [layer_y["layer1"], layer_y["input"] + 0.48],
color=colour, alpha=0.35)
coords = traced[index]
ax.plot([coords[0] + 0.05, coords[-1] + 0.67], [-0.12, -0.12],
color=colour, linewidth=4)
ax.text(-0.55, 0.35, "input", rotation=90, va="center", color=COURSE_GRAY)
ax.text(-0.05, 1.59, "layer 1\n$k=3,s=1$", ha="right", va="center", color=COURSE_GRAY)
ax.text(0.45, 2.79, "layer 2\n$k=2,s=2$", ha="right", va="center", color=COURSE_GRAY)
ax.text(5.3, 2.75, f"receptive-field size = {size}\nadjacent-output spacing = {spacing}",
color=COURSE_NAVY, fontsize=12)
ax.set_title("Two layer-2 outputs depend on layer 1, then on overlapping input regions",
fontweight="bold", color=COURSE_NAVY)
return save_static_figure(fig, "05-receptive-field-trace")