codex/kernel-quadratic-xor-feature-separation.py

kernel-quadratic-xor-feature-separation.py
"""Draw an original XOR square and its quadratic feature slice.

Tested with Python 3.14, matplotlib 3.10.7 and numpy 2.3.5.
Run from _media: MPLBACKEND=Agg MPLCONFIGDIR=/tmp/codex-wiki-matplotlib
python3 ../kernel-quadratic-xor-feature-separation.py
"""

from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Patch


def main():
    points = np.array([[1, 1], [1, -1], [-1, 1], [-1, -1]])
    labels = -points[:, 0] * points[:, 1]
    features = np.column_stack(
        [points[:, 0] ** 2, np.sqrt(2) * points[:, 0] * points[:, 1], points[:, 1] ** 2]
    )
    assert np.array_equal(labels, [-1, 1, 1, -1])
    assert np.all(features[:, 2] == 1)
    np.testing.assert_allclose(-features[:, 1] / np.sqrt(2), labels)

    positive, negative = "#147d92", "#be4b27"
    plt.rcParams.update({"font.size": 12, "axes.spines.top": False, "axes.spines.right": False})
    fig, (left, right) = plt.subplots(1, 2, figsize=(10.8, 5.3), facecolor="white")
    fig.subplots_adjust(left=0.08, right=0.97, bottom=0.23, top=0.83, wspace=0.33)
    fig.suptitle("A product feature separates the XOR square", fontsize=17, y=0.96)

    grid = np.linspace(-1.6, 1.6, 241)
    xx, yy = np.meshgrid(grid, grid)
    left.contourf(xx, yy, -xx * yy, levels=[-3, 0, 3], colors=[negative, positive], alpha=0.09)
    left.plot([-1, 1], [-1, 1], "--", color=negative, alpha=0.55, linewidth=1.6)
    left.plot([-1, 1], [1, -1], "--", color=positive, alpha=0.55, linewidth=1.6)
    left.axhline(0, color="#59636c", linewidth=1)
    left.axvline(0, color="#59636c", linewidth=1)
    left.scatter([0], [0], color="#222222", s=20, zorder=4)
    left.annotate("shared midpoint", (0, 0), xytext=(0.15, 0.32), fontsize=10,
                  arrowprops={"arrowstyle": "->", "color": "#555555"})
    for index, (point, label) in enumerate(zip(points, labels), 1):
        color, marker = (positive, "o") if label == 1 else (negative, "s")
        left.scatter(*point, c=color, marker=marker, s=105, edgecolors="white", linewidths=1.1, zorder=5)
        left.annotate(rf"$p_{index}$: {label:+d}", point, xytext=(0, 14 if point[1] > 0 else -25),
                      textcoords="offset points", ha="center", color=color, fontsize=11)
    left.set(title="Input plane: no affine separator", xlabel=r"$x_1$", ylabel=r"$x_2$",
             xlim=(-1.6, 1.6), ylim=(-1.6, 1.6), xticks=[-1, 0, 1], yticks=[-1, 0, 1])
    left.set_aspect("equal")

    right.axhspan(0, 2.05, color=negative, alpha=0.09)
    right.axhspan(-2.05, 0, color=positive, alpha=0.09)
    right.axhline(0, color="#333333", linewidth=1.8)
    right.text(0.37, 0.12, r"separator: $\phi_2=0$", fontsize=11)
    for indices, color, marker, vertical in [([0, 3], negative, "s", np.sqrt(2)),
                                              ([1, 2], positive, "o", -np.sqrt(2))]:
        right.scatter(1, vertical, c=color, marker=marker, s=120, edgecolors="white", linewidths=1.1, zorder=5)
        names = ", ".join(rf"$p_{i+1}$" for i in indices)
        right.annotate(names + " coincide\n" + rf"$y={labels[indices[0]]:+d}$", (1, vertical),
                       xytext=(15, 0), textcoords="offset points", va="center", fontsize=11, color=color)
    right.set(title=r"Feature slice: $\phi_3=x_2^2=1$", xlabel=r"$\phi_1=x_1^2$",
              ylabel=r"$\phi_2=\sqrt{2}\,x_1x_2$", xlim=(0.25, 1.9), ylim=(-2.05, 2.05),
              xticks=[1], yticks=[-np.sqrt(2), 0, np.sqrt(2)],
              yticklabels=[r"$-\sqrt{2}$", "0", r"$\sqrt{2}$"])
    right.set_box_aspect(1)
    fig.legend(handles=[Patch(color=positive, label="+1: signs differ"),
                        Patch(color=negative, label="−1: signs agree")],
               loc="lower center", bbox_to_anchor=(0.5, 0.105), ncol=2, frameon=False)
    fig.text(0.5, 0.055, r"$\phi(x)=(x_1^2,\sqrt{2}\,x_1x_2,x_2^2)$     "
             r"$f(x)=-\phi_2/\sqrt{2}=-x_1x_2$", ha="center", fontsize=13)
    fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=115, facecolor="white", transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()