{"spec_id":"learning-curve-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nlearning-curve-basic: Model Learning Curve\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-10\n\"\"\"\n\n# ruff: noqa: C408\n\nimport os\nimport sys\n\n\n# Avoid import shadowing: remove current directory from path before importing plotly\n_current_dir = os.path.dirname(os.path.abspath(__file__))\nif _current_dir in sys.path:\n    sys.path.remove(_current_dir)\nif \"\" in sys.path:\n    sys.path.remove(\"\")\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nGRID = \"rgba(26,26,23,0.10)\" if THEME == \"light\" else \"rgba(240,239,232,0.10)\"\n\n# Okabe-Ito palette (first series always #009E73)\nTRAIN_COLOR = \"#009E73\"  # bluish green\nVAL_COLOR = \"#C475FD\"  # vermillion\n\n# Data - Simulate learning curve data from cross-validation\nnp.random.seed(42)\n\n# Training set sizes (10 different sizes)\ntrain_sizes = np.array([50, 100, 200, 400, 600, 800, 1000, 1500, 2000, 3000])\n\n# Simulate 5-fold cross-validation scores\nn_folds = 5\nn_sizes = len(train_sizes)\n\n# Training scores: start high, decrease slightly with more data\ntrain_scores = np.zeros((n_folds, n_sizes))\nfor i, size in enumerate(train_sizes):\n    base_score = 0.96 - 0.04 * np.log10(size / 50)\n    train_scores[:, i] = base_score + np.random.normal(0, 0.01, n_folds)\n\n# Validation scores: start low, improve with more data, converge toward training\nvalidation_scores = np.zeros((n_folds, n_sizes))\nfor i, size in enumerate(train_sizes):\n    improvement = 0.20 * (1 - np.exp(-size / 800))\n    base_score = 0.68 + improvement\n    validation_scores[:, i] = base_score + np.random.normal(0, 0.02, n_folds)\n\n# Calculate means and standard deviations\ntrain_mean = train_scores.mean(axis=0)\ntrain_std = train_scores.std(axis=0)\nvalidation_mean = validation_scores.mean(axis=0)\nvalidation_std = validation_scores.std(axis=0)\n\n# Create figure\nfig = go.Figure()\n\n# Training score band (±1 std)\ntrain_band_color = f\"rgba({int(TRAIN_COLOR[1:3], 16)}, {int(TRAIN_COLOR[3:5], 16)}, {int(TRAIN_COLOR[5:7], 16)}, 0.2)\"\nfig.add_trace(\n    go.Scatter(\n        x=np.concatenate([train_sizes, train_sizes[::-1]]),\n        y=np.concatenate([train_mean + train_std, (train_mean - train_std)[::-1]]),\n        fill=\"toself\",\n        fillcolor=train_band_color,\n        line=dict(color=\"rgba(255,255,255,0)\"),\n        showlegend=False,\n        hoverinfo=\"skip\",\n        name=\"Training ±1 std\",\n    )\n)\n\n# Training score line\nfig.add_trace(\n    go.Scatter(\n        x=train_sizes,\n        y=train_mean,\n        mode=\"lines+markers\",\n        name=\"Training Score\",\n        line=dict(color=TRAIN_COLOR, width=4),\n        marker=dict(size=12, color=TRAIN_COLOR),\n        hovertemplate=\"<b>Training Score</b><br>Size: %{x}<br>Score: %{y:.3f}<extra></extra>\",\n    )\n)\n\n# Validation score band (±1 std)\nval_band_color = f\"rgba({int(VAL_COLOR[1:3], 16)}, {int(VAL_COLOR[3:5], 16)}, {int(VAL_COLOR[5:7], 16)}, 0.2)\"\nfig.add_trace(\n    go.Scatter(\n        x=np.concatenate([train_sizes, train_sizes[::-1]]),\n        y=np.concatenate([validation_mean + validation_std, (validation_mean - validation_std)[::-1]]),\n        fill=\"toself\",\n        fillcolor=val_band_color,\n        line=dict(color=\"rgba(255,255,255,0)\"),\n        showlegend=False,\n        hoverinfo=\"skip\",\n        name=\"Validation ±1 std\",\n    )\n)\n\n# Validation score line\nfig.add_trace(\n    go.Scatter(\n        x=train_sizes,\n        y=validation_mean,\n        mode=\"lines+markers\",\n        name=\"Validation Score\",\n        line=dict(color=VAL_COLOR, width=4),\n        marker=dict(size=12, color=VAL_COLOR),\n        hovertemplate=\"<b>Validation Score</b><br>Size: %{x}<br>Score: %{y:.3f}<extra></extra>\",\n    )\n)\n\n# Layout\nfig.update_layout(\n    title=dict(\n        text=\"learning-curve-basic · plotly · anyplot.ai\", font=dict(size=28, color=INK), x=0.5, xanchor=\"center\"\n    ),\n    xaxis=dict(\n        title=dict(text=\"Training Set Size\", font=dict(size=22, color=INK)),\n        tickfont=dict(size=18, color=INK_SOFT),\n        gridcolor=GRID,\n        gridwidth=1,\n        showgrid=True,\n        linecolor=INK_SOFT,\n    ),\n    yaxis=dict(\n        title=dict(text=\"Accuracy Score (0-1)\", font=dict(size=22, color=INK)),\n        tickfont=dict(size=18, color=INK_SOFT),\n        gridcolor=GRID,\n        gridwidth=1,\n        showgrid=True,\n        linecolor=INK_SOFT,\n        range=[0.60, 1.02],\n    ),\n    legend=dict(\n        font=dict(size=18, color=INK_SOFT),\n        x=0.98,\n        y=0.02,\n        xanchor=\"right\",\n        yanchor=\"bottom\",\n        bgcolor=ELEVATED_BG,\n        bordercolor=INK_SOFT,\n        borderwidth=1,\n    ),\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    margin=dict(l=100, r=80, t=100, b=100),\n)\n\n# Save as PNG and HTML\nfig.write_image(f\"plot-{THEME}.png\", width=1600, height=900, scale=3)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}