Skip to content

Commit 25e270a

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

2 files changed

Lines changed: 133 additions & 0 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
""" pyplots.ai
2+
line-loss-training: Training Loss Curve
3+
Library: plotly 6.5.0 | Python 3.13.11
4+
Quality: 92/100 | Created: 2025-12-31
5+
"""
6+
7+
import numpy as np
8+
import plotly.graph_objects as go
9+
10+
11+
# Data - Simulated neural network training history
12+
np.random.seed(42)
13+
epochs = np.arange(1, 101)
14+
15+
# Training loss: starts high, decreases with noise, eventually plateaus
16+
train_loss = 2.5 * np.exp(-0.05 * epochs) + 0.15 + np.random.normal(0, 0.02, len(epochs))
17+
train_loss = np.maximum(train_loss, 0.1) # Ensure positive
18+
19+
# Validation loss: follows training initially, then diverges (overfitting after epoch ~60)
20+
val_loss = 2.5 * np.exp(-0.045 * epochs) + 0.25 + np.random.normal(0, 0.03, len(epochs))
21+
# Add overfitting effect: validation loss starts increasing after epoch 60
22+
overfitting_effect = np.where(epochs > 60, 0.008 * (epochs - 60), 0)
23+
val_loss = val_loss + overfitting_effect
24+
val_loss = np.maximum(val_loss, 0.15)
25+
26+
# Find minimum validation loss epoch for annotation
27+
min_val_epoch = epochs[np.argmin(val_loss)]
28+
min_val_loss = np.min(val_loss)
29+
30+
# Create figure
31+
fig = go.Figure()
32+
33+
# Training loss curve
34+
fig.add_trace(
35+
go.Scatter(
36+
x=epochs,
37+
y=train_loss,
38+
mode="lines",
39+
name="Training Loss",
40+
line=dict(color="#306998", width=3),
41+
hovertemplate="Epoch %{x}<br>Training Loss: %{y:.4f}<extra></extra>",
42+
)
43+
)
44+
45+
# Validation loss curve
46+
fig.add_trace(
47+
go.Scatter(
48+
x=epochs,
49+
y=val_loss,
50+
mode="lines",
51+
name="Validation Loss",
52+
line=dict(color="#FFD43B", width=3),
53+
hovertemplate="Epoch %{x}<br>Validation Loss: %{y:.4f}<extra></extra>",
54+
)
55+
)
56+
57+
# Mark minimum validation loss point
58+
fig.add_trace(
59+
go.Scatter(
60+
x=[min_val_epoch],
61+
y=[min_val_loss],
62+
mode="markers+text",
63+
name="Best Epoch",
64+
marker=dict(color="#E74C3C", size=16, symbol="star"),
65+
text=[f"Best: Epoch {min_val_epoch}"],
66+
textposition="top center",
67+
textfont=dict(size=16, color="#E74C3C"),
68+
hovertemplate="Best Epoch: %{x}<br>Min Val Loss: %{y:.4f}<extra></extra>",
69+
)
70+
)
71+
72+
# Update layout
73+
fig.update_layout(
74+
title=dict(text="line-loss-training · plotly · pyplots.ai", font=dict(size=28), x=0.5, xanchor="center"),
75+
xaxis=dict(
76+
title=dict(text="Epoch", font=dict(size=22)),
77+
tickfont=dict(size=18),
78+
gridcolor="rgba(128, 128, 128, 0.3)",
79+
gridwidth=1,
80+
showgrid=True,
81+
range=[0, 105],
82+
),
83+
yaxis=dict(
84+
title=dict(text="Cross-Entropy Loss", font=dict(size=22)),
85+
tickfont=dict(size=18),
86+
gridcolor="rgba(128, 128, 128, 0.3)",
87+
gridwidth=1,
88+
showgrid=True,
89+
),
90+
legend=dict(
91+
font=dict(size=18),
92+
x=0.75,
93+
y=0.95,
94+
bgcolor="rgba(255, 255, 255, 0.8)",
95+
bordercolor="rgba(128, 128, 128, 0.3)",
96+
borderwidth=1,
97+
),
98+
template="plotly_white",
99+
margin=dict(l=100, r=80, t=100, b=100),
100+
plot_bgcolor="white",
101+
)
102+
103+
# Save as PNG and HTML
104+
fig.write_image("plot.png", width=1600, height=900, scale=3)
105+
fig.write_html("plot.html", include_plotlyjs="cdn")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library: plotly
2+
specification_id: line-loss-training
3+
created: '2025-12-31T00:05:54Z'
4+
updated: '2025-12-31T00:10:32Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20608572889
7+
issue: 2860
8+
python_version: 3.13.11
9+
library_version: 6.5.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-loss-training/plotly/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-loss-training/plotly/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/line-loss-training/plotly/plot.html
13+
quality_score: 92
14+
review:
15+
strengths:
16+
- Excellent implementation of overfitting visualization with validation loss diverging
17+
after epoch 60
18+
- Clean, readable code with proper seed for reproducibility
19+
- Good use of Plotly hover templates showing epoch and loss values on hover
20+
- Appropriate color scheme (blue/yellow) with good accessibility
21+
- Best epoch marker with star symbol effectively highlights the optimal stopping
22+
point
23+
- HTML output enabled for full interactivity
24+
weaknesses:
25+
- Legend background slightly blends with grid lines in upper right area
26+
- Star marker for best epoch could be larger (size 16 is adequate but not prominent)
27+
- Could utilize Plotly-specific features like vertical line annotation at best epoch
28+
or shaded overfitting region

0 commit comments

Comments
 (0)