Skip to content

Commit 3228979

Browse files
feat(matplotlib): implement line-loss-training (#2905)
## Implementation: `line-loss-training` - matplotlib Implements the **matplotlib** version of `line-loss-training`. **File:** `plots/line-loss-training/implementations/matplotlib.py` **Parent Issue:** #2860 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20608625949)* --------- 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 faf79ce commit 3228979

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
""" pyplots.ai
2+
line-loss-training: Training Loss Curve
3+
Library: matplotlib 3.10.8 | Python 3.13.11
4+
Quality: 94/100 | Created: 2025-12-31
5+
"""
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
10+
11+
# Data - Simulate training and validation loss over epochs
12+
np.random.seed(42)
13+
epochs = np.arange(1, 51)
14+
15+
# Training loss: exponential decay with small noise
16+
train_loss = 2.5 * np.exp(-0.08 * epochs) + 0.15 + np.random.randn(50) * 0.015
17+
18+
# Validation loss: decays similarly but starts overfitting after epoch 28
19+
val_base = 2.5 * np.exp(-0.065 * epochs) + 0.30
20+
noise = np.random.randn(50) * 0.02
21+
val_loss = val_base + noise
22+
# Clear overfitting after epoch 28: validation loss increases while training keeps dropping
23+
val_loss[28:] = val_loss[28] + np.linspace(0, 0.35, 22) + np.random.randn(22) * 0.015
24+
25+
# Find minimum validation loss epoch for annotation
26+
min_val_epoch = np.argmin(val_loss) + 1
27+
min_val_loss = val_loss[min_val_epoch - 1]
28+
29+
# Create plot
30+
fig, ax = plt.subplots(figsize=(16, 9))
31+
32+
# Plot training and validation loss curves
33+
ax.plot(epochs, train_loss, linewidth=3, color="#306998", label="Training Loss", marker="o", markersize=6)
34+
ax.plot(epochs, val_loss, linewidth=3, color="#FFD43B", label="Validation Loss", marker="s", markersize=6)
35+
36+
# Mark minimum validation loss point (optimal early stopping)
37+
ax.scatter([min_val_epoch], [min_val_loss], s=300, color="#E74C3C", zorder=5, edgecolors="black", linewidth=2)
38+
ax.annotate(
39+
f"Best: Epoch {min_val_epoch}",
40+
xy=(min_val_epoch, min_val_loss),
41+
xytext=(min_val_epoch - 12, min_val_loss + 0.35),
42+
fontsize=16,
43+
arrowprops={"arrowstyle": "->", "color": "black", "lw": 2},
44+
bbox={"boxstyle": "round,pad=0.3", "facecolor": "white", "edgecolor": "black"},
45+
)
46+
47+
# Labels and styling
48+
ax.set_xlabel("Epoch", fontsize=20)
49+
ax.set_ylabel("Cross-Entropy Loss", fontsize=20)
50+
ax.set_title("line-loss-training · matplotlib · pyplots.ai", fontsize=24)
51+
ax.tick_params(axis="both", labelsize=16)
52+
ax.legend(fontsize=16, loc="upper right")
53+
ax.grid(True, alpha=0.3, linestyle="--")
54+
55+
# Set axis limits
56+
ax.set_xlim(0, 52)
57+
ax.set_ylim(0, 2.8)
58+
59+
plt.tight_layout()
60+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library: matplotlib
2+
specification_id: line-loss-training
3+
created: '2025-12-31T00:07:24Z'
4+
updated: '2025-12-31T00:11:39Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20608625949
7+
issue: 2860
8+
python_version: 3.13.11
9+
library_version: 3.10.8
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-loss-training/matplotlib/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-loss-training/matplotlib/plot_thumb.png
12+
preview_html: null
13+
quality_score: 94
14+
review:
15+
strengths:
16+
- Excellent demonstration of overfitting pattern with clear divergence between training
17+
and validation loss
18+
- Optimal early stopping point annotation is well-executed with arrow and styled
19+
bbox
20+
- Color choices (blue and yellow) are colorblind-safe and provide excellent contrast
21+
- Clean KISS structure with proper random seed for reproducibility
22+
- All specification requirements are met including distinct colors, legend, and
23+
loss function labeling
24+
weaknesses:
25+
- Legend position in upper right slightly overlaps with early epoch data points;
26+
consider upper center or outside plot
27+
- Could use matplotlib-specific features like fill_between for confidence intervals
28+
or secondary annotations

0 commit comments

Comments
 (0)