{"spec_id":"learning-curve-basic","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nlearning-curve-basic: Model Learning Curve\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-05-10\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pygal\nfrom pygal.style import Style\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nIMPRINT = (\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data - Simulating sklearn's learning_curve output\nnp.random.seed(42)\n\n# Training set sizes\nn_samples_total = 1000\ntrain_sizes_pct = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0])\ntrain_sizes = (train_sizes_pct * n_samples_total).astype(int)\n\n# Simulate cross-validation folds (5 folds)\nn_folds = 5\nn_sizes = len(train_sizes)\n\n# Training scores: start high, remain high (slight overfitting pattern)\ntrain_scores_base = 0.95 - 0.05 * np.exp(-train_sizes / 200)\ntrain_scores_std_vals = 0.02 * np.exp(-train_sizes / 300)\ntrain_scores = np.array(\n    [train_scores_base[i] + np.random.randn(n_folds) * train_scores_std_vals[i] for i in range(n_sizes)]\n).T\n\n# Validation scores: start lower, converge towards training (gap shows variance)\nval_scores_base = 0.65 + 0.25 * (1 - np.exp(-train_sizes / 400))\nval_scores_std_vals = 0.04 * np.exp(-train_sizes / 500) + 0.01\nval_scores = np.array(\n    [val_scores_base[i] + np.random.randn(n_folds) * val_scores_std_vals[i] for i in range(n_sizes)]\n).T\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(val_scores, axis=0)\nval_std = np.std(val_scores, axis=0)\n\n# Custom style for 4800x2700 canvas with theme-adaptive colors\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=IMPRINT,\n    title_font_size=28,\n    label_font_size=22,\n    major_label_font_size=18,\n    legend_font_size=16,\n    value_font_size=14,\n    stroke_width=4,\n)\n\n# Create XY chart for learning curve\nchart = pygal.XY(\n    width=4800,\n    height=2700,\n    style=custom_style,\n    title=\"learning-curve-basic · pygal · anyplot.ai\",\n    x_title=\"Training Set Size (samples)\",\n    y_title=\"Accuracy Score\",\n    show_dots=True,\n    dots_size=8,\n    stroke_style={\"width\": 4},\n    show_x_guides=False,\n    show_y_guides=True,\n    legend_at_bottom=False,\n    range=(0.6, 1.02),\n    xrange=(50, 1050),\n    x_labels=[100, 200, 300, 400, 500, 600, 700, 800, 900, 1000],\n    margin=80,\n)\n\n# Prepare data points as (x, y) tuples\ntrain_points = [(int(train_sizes[i]), round(train_mean[i], 3)) for i in range(n_sizes)]\nval_points = [(int(train_sizes[i]), round(val_mean[i], 3)) for i in range(n_sizes)]\n\n# Add upper/lower bounds for confidence bands (±1 std)\ntrain_upper = [(int(train_sizes[i]), round(train_mean[i] + train_std[i], 3)) for i in range(n_sizes)]\ntrain_lower = [(int(train_sizes[i]), round(train_mean[i] - train_std[i], 3)) for i in range(n_sizes)]\nval_upper = [(int(train_sizes[i]), round(val_mean[i] + val_std[i], 3)) for i in range(n_sizes)]\nval_lower = [(int(train_sizes[i]), round(val_mean[i] - val_std[i], 3)) for i in range(n_sizes)]\n\n# Add main learning curves\nchart.add(\"Training Score\", train_points, stroke_style={\"width\": 5})\nchart.add(\"Validation Score\", val_points, stroke_style={\"width\": 5})\n\n# Add confidence bounds as secondary lines (thinner, dashed, no legend)\nchart.add(None, train_upper, show_dots=False, stroke_style={\"width\": 2, \"dasharray\": \"8, 4\"})\nchart.add(None, train_lower, show_dots=False, stroke_style={\"width\": 2, \"dasharray\": \"8, 4\"})\nchart.add(None, val_upper, show_dots=False, stroke_style={\"width\": 2, \"dasharray\": \"8, 4\"})\nchart.add(None, val_lower, show_dots=False, stroke_style={\"width\": 2, \"dasharray\": \"8, 4\"})\n\n# Save as HTML (interactive) and PNG\nchart.render_to_file(f\"plot-{THEME}.html\")\nchart.render_to_png(f\"plot-{THEME}.png\")\n"}