{"spec_id":"learning-curve-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nlearning-curve-basic: Model Learning Curve\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-10\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\nfrom lets_plot import ggsave\n\n\nLetsPlot.setup_html()\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\"\n\n# Okabe-Ito palette (first series always #009E73)\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\"]\n\n# Data - Simulate learning curve for a model showing slight overfitting pattern\nnp.random.seed(42)\n\n# Training set sizes (10 different sizes)\ntrain_sizes = np.array([50, 100, 200, 400, 600, 800, 1000, 1200, 1400, 1600])\n\n# Simulate 5 cross-validation folds\nn_folds = 5\nn_sizes = len(train_sizes)\n\n# Training scores: Start high, stay high (model fits training data well)\ntrain_scores_mean = 0.99 - 0.15 * np.exp(-train_sizes / 200)\ntrain_scores = np.zeros((n_folds, n_sizes))\nfor i in range(n_folds):\n    noise = np.random.randn(n_sizes) * 0.01\n    train_scores[i] = train_scores_mean + noise\n\n# Validation scores: Start lower, improve with more data (learning effect)\n# Show a gap with training that narrows as data increases\nvalidation_scores_mean = 0.65 + 0.20 * (1 - np.exp(-train_sizes / 500))\nvalidation_scores = np.zeros((n_folds, n_sizes))\nfor i in range(n_folds):\n    noise = np.random.randn(n_sizes) * 0.02\n    validation_scores[i] = validation_scores_mean + noise\n\n# Calculate means and standard deviations\ntrain_mean = np.mean(train_scores, axis=0)\ntrain_std = np.std(train_scores, axis=0)\nval_mean = np.mean(validation_scores, axis=0)\nval_std = np.std(validation_scores, axis=0)\n\n# Create DataFrames for plotting\ndf_train = pd.DataFrame(\n    {\n        \"Training Set Size\": train_sizes,\n        \"Score\": train_mean,\n        \"Lower\": train_mean - train_std,\n        \"Upper\": train_mean + train_std,\n        \"Type\": \"Training Score\",\n    }\n)\n\ndf_val = pd.DataFrame(\n    {\n        \"Training Set Size\": train_sizes,\n        \"Score\": val_mean,\n        \"Lower\": val_mean - val_std,\n        \"Upper\": val_mean + val_std,\n        \"Type\": \"Validation Score\",\n    }\n)\n\ndf = pd.concat([df_train, df_val], ignore_index=True)\n\n# Plot\nplot = (\n    ggplot(df, aes(x=\"Training Set Size\", y=\"Score\", color=\"Type\", fill=\"Type\"))\n    + geom_ribbon(aes(ymin=\"Lower\", ymax=\"Upper\"), alpha=0.2, color=\"rgba(0,0,0,0)\")\n    + geom_line(size=2)\n    + geom_point(size=4)\n    + scale_color_manual(values=IMPRINT[:2])\n    + scale_fill_manual(values=IMPRINT[:2])\n    + scale_y_continuous(limits=[0.55, 1.02])\n    + scale_x_continuous(limits=[0, 1700], breaks=list(range(0, 1800, 200)))\n    + labs(\n        x=\"Training Set Size (samples)\",\n        y=\"Accuracy Score (0-1)\",\n        title=\"learning-curve-basic · letsplot · anyplot.ai\",\n        color=\"\",\n        fill=\"\",\n    )\n    + theme_minimal()\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        panel_grid_major=element_line(color=INK_SOFT, size=0.3),\n        panel_grid_minor=element_blank(),\n        axis_title=element_text(color=INK, size=20),\n        axis_text=element_text(color=INK_SOFT, size=16),\n        axis_line=element_line(color=INK_SOFT),\n        plot_title=element_text(color=INK, size=24),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        legend_text=element_text(color=INK_SOFT, size=16),\n        legend_title=element_text(color=INK),\n        legend_position=\"bottom\",\n    )\n    + ggsize(1600, 900)\n)\n\n# Save as PNG (scale 3x = 4800 x 2700 px) and HTML\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=3)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}