Skip to content

Commit 1541452

Browse files
feat(matplotlib): implement contour-decision-boundary (#2977)
## Implementation: `contour-decision-boundary` - matplotlib Implements the **matplotlib** version of `contour-decision-boundary`. **File:** `plots/contour-decision-boundary/implementations/matplotlib.py` **Parent Issue:** #2921 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20612898107)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 7a25f35 commit 1541452

2 files changed

Lines changed: 142 additions & 0 deletions

File tree

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
""" pyplots.ai
2+
contour-decision-boundary: Decision Boundary Classifier Visualization
3+
Library: matplotlib 3.10.8 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-31
5+
"""
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
from sklearn.datasets import make_moons
10+
from sklearn.svm import SVC
11+
12+
13+
# Data - generate synthetic two-moon classification data
14+
np.random.seed(42)
15+
X, y = make_moons(n_samples=200, noise=0.25, random_state=42)
16+
17+
# Train a classifier (SVM with RBF kernel)
18+
classifier = SVC(kernel="rbf", C=1.0, gamma="scale")
19+
classifier.fit(X, y)
20+
21+
# Create mesh grid for decision boundary
22+
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
23+
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
24+
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 200), np.linspace(y_min, y_max, 200))
25+
26+
# Predict class for each point in mesh
27+
Z = classifier.predict(np.c_[xx.ravel(), yy.ravel()])
28+
Z = Z.reshape(xx.shape)
29+
30+
# Create plot
31+
fig, ax = plt.subplots(figsize=(16, 9))
32+
33+
# Plot decision regions with contourf
34+
ax.contourf(xx, yy, Z, alpha=0.4, cmap="coolwarm", levels=[-0.5, 0.5, 1.5])
35+
36+
# Add decision boundary line
37+
ax.contour(xx, yy, Z, colors="white", linewidths=2, levels=[0.5])
38+
39+
# Identify correctly and incorrectly classified points
40+
predictions = classifier.predict(X)
41+
correct = predictions == y
42+
incorrect = ~correct
43+
44+
# Plot training points - correctly classified
45+
class_0_correct = (y == 0) & correct
46+
class_1_correct = (y == 1) & correct
47+
ax.scatter(
48+
X[class_0_correct, 0],
49+
X[class_0_correct, 1],
50+
c="#306998",
51+
s=150,
52+
alpha=0.9,
53+
edgecolors="white",
54+
linewidths=2,
55+
marker="o",
56+
label="Class A (correct)",
57+
zorder=3,
58+
)
59+
ax.scatter(
60+
X[class_1_correct, 0],
61+
X[class_1_correct, 1],
62+
c="#FFD43B",
63+
s=150,
64+
alpha=0.9,
65+
edgecolors="black",
66+
linewidths=2,
67+
marker="o",
68+
label="Class B (correct)",
69+
zorder=3,
70+
)
71+
72+
# Plot incorrectly classified points with X marker
73+
if np.any(incorrect):
74+
class_0_incorrect = (y == 0) & incorrect
75+
class_1_incorrect = (y == 1) & incorrect
76+
if np.any(class_0_incorrect):
77+
ax.scatter(
78+
X[class_0_incorrect, 0],
79+
X[class_0_incorrect, 1],
80+
c="#306998",
81+
s=200,
82+
alpha=0.9,
83+
edgecolors="red",
84+
linewidths=3,
85+
marker="X",
86+
label="Class A (misclassified)",
87+
zorder=4,
88+
)
89+
if np.any(class_1_incorrect):
90+
ax.scatter(
91+
X[class_1_incorrect, 0],
92+
X[class_1_incorrect, 1],
93+
c="#FFD43B",
94+
s=200,
95+
alpha=0.9,
96+
edgecolors="red",
97+
linewidths=3,
98+
marker="X",
99+
label="Class B (misclassified)",
100+
zorder=4,
101+
)
102+
103+
# Labels and styling
104+
ax.set_xlabel("Feature X1", fontsize=20)
105+
ax.set_ylabel("Feature X2", fontsize=20)
106+
ax.set_title("contour-decision-boundary · matplotlib · pyplots.ai", fontsize=24)
107+
ax.tick_params(axis="both", labelsize=16)
108+
ax.legend(fontsize=14, loc="upper left", framealpha=0.9)
109+
ax.grid(True, alpha=0.3, linestyle="--")
110+
111+
plt.tight_layout()
112+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
library: matplotlib
2+
specification_id: contour-decision-boundary
3+
created: '2025-12-31T05:42:26Z'
4+
updated: '2025-12-31T05:56:04Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20612898107
7+
issue: 2921
8+
python_version: 3.13.11
9+
library_version: 3.10.8
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/contour-decision-boundary/matplotlib/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/contour-decision-boundary/matplotlib/plot_thumb.png
12+
preview_html: null
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent implementation of decision boundary visualization meeting all specification
17+
requirements
18+
- Clear visual distinction between correctly classified and misclassified points
19+
using different marker styles (circles vs X)
20+
- Proper use of contourf for class regions with appropriate transparency (alpha=0.4)
21+
- White decision boundary line provides clear separation between regions
22+
- Good marker sizing (s=150/200) and edge colors (white/black/red) for visibility
23+
- Reproducible with fixed random seeds
24+
weaknesses:
25+
- Grid is barely visible despite being enabled - could use slightly higher alpha
26+
or different styling
27+
- Color palette uses coolwarm which is not optimal for colorblind accessibility
28+
- consider using a perceptually uniform colormap
29+
- Could leverage SVM decision_function to show prediction confidence as gradient
30+
rather than hard boundary regions

0 commit comments

Comments
 (0)