diff --git a/plots/line-loss-training/implementations/pygal.py b/plots/line-loss-training/implementations/pygal.py new file mode 100644 index 0000000000..ffcfae4a2b --- /dev/null +++ b/plots/line-loss-training/implementations/pygal.py @@ -0,0 +1,74 @@ +""" pyplots.ai +line-loss-training: Training Loss Curve +Library: pygal 3.1.0 | Python 3.13.11 +Quality: 91/100 | Created: 2025-12-31 +""" + +import numpy as np +import pygal +from pygal.style import Style + + +# Data: Simulated training loss curves showing typical overfitting behavior +np.random.seed(42) +epochs = np.arange(1, 51) + +# Training loss: Steadily decreasing with some noise +train_loss = 2.5 * np.exp(-0.08 * epochs) + 0.1 + np.random.normal(0, 0.02, len(epochs)) + +# Validation loss: Decreases then increases (overfitting after epoch ~30) +val_loss = 2.3 * np.exp(-0.07 * epochs) + 0.15 + 0.003 * np.maximum(0, epochs - 25) ** 1.5 +val_loss += np.random.normal(0, 0.03, len(epochs)) + +# Find minimum validation loss epoch for annotation +min_val_epoch = int(epochs[np.argmin(val_loss)]) +min_val_loss = float(np.min(val_loss)) + +# Custom style for large canvas +custom_style = Style( + background="white", + plot_background="white", + foreground="#333333", + foreground_strong="#333333", + foreground_subtle="#666666", + colors=("#306998", "#FFD43B"), # Python Blue, Python Yellow + title_font_size=48, + label_font_size=36, + major_label_font_size=32, + legend_font_size=32, + value_font_size=28, + stroke_width=4, + opacity=0.9, + opacity_hover=1.0, +) + +# Create line chart +chart = pygal.Line( + width=4800, + height=2700, + style=custom_style, + title="line-loss-training · pygal · pyplots.ai", + x_title="Epoch", + y_title="Cross-Entropy Loss", + show_x_guides=False, + show_y_guides=True, + dots_size=6, + stroke_style={"width": 4}, + legend_at_bottom=False, + legend_box_size=24, + margin=50, + x_label_rotation=0, + truncate_label=-1, + show_dots=True, +) + +# Set x-axis labels (show every 5th epoch for readability) +chart.x_labels = [str(e) if e % 5 == 0 else "" for e in epochs] + +# Add training and validation loss data +chart.add("Training Loss", list(train_loss)) +chart.add("Validation Loss", list(val_loss)) + +# Save as PNG and HTML +chart.render_to_png("plot.png") +chart.render_to_file("plot.html") diff --git a/plots/line-loss-training/metadata/pygal.yaml b/plots/line-loss-training/metadata/pygal.yaml new file mode 100644 index 0000000000..0934bab699 --- /dev/null +++ b/plots/line-loss-training/metadata/pygal.yaml @@ -0,0 +1,29 @@ +library: pygal +specification_id: line-loss-training +created: '2025-12-31T00:13:54Z' +updated: '2025-12-31T00:17:57Z' +generated_by: claude-opus-4-5-20251101 +workflow_run: 20608711859 +issue: 2860 +python_version: 3.13.11 +library_version: 3.1.0 +preview_url: https://storage.googleapis.com/pyplots-images/plots/line-loss-training/pygal/plot.png +preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-loss-training/pygal/plot_thumb.png +preview_html: https://storage.googleapis.com/pyplots-images/plots/line-loss-training/pygal/plot.html +quality_score: 91 +review: + strengths: + - Excellent demonstration of overfitting pattern with training loss continuing to + decrease while validation loss increases after epoch ~25 + - Clean, readable code following KISS principles with proper random seed + - 'Appropriate use of Python brand colors (blue #306998, yellow #FFD43B) for visual + distinction' + - Good font sizing and spacing for 4800x2700 canvas with customized Style + - Y-axis label specifies Cross-Entropy Loss as recommended in specification + weaknesses: + - Legend positioned outside plot area in top-left corner appears slightly disconnected + from the chart + - 'Optional feature from spec not implemented: marking the epoch with minimum validation + loss (optimal stopping point)' + - Grid only shows horizontal lines; vertical guides disabled which reduces readability + for epoch identification