{"spec_id":"curve-bias-variance-tradeoff","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// curve-bias-variance-tradeoff: Bias-Variance Tradeoff Curve\n// Library: highcharts 12.6.0 | JavaScript 22.23.2\n// Quality: 91/100 | Created: 2026-08-24\n\nconst t = window.ANYPLOT_TOKENS;\nconst hexToRgba = (hex, alpha) => {\n  const n = parseInt(hex.slice(1), 16);\n  return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${alpha})`;\n};\n\n// --- Data (theoretical curves, deterministic) -------------------------------\n// Model complexity stands in for e.g. polynomial degree or tree depth.\nconst N = 60;\nconst complexity = Array.from({ length: N }, (_, i) => 1 + (i * 14) / (N - 1));\n\nconst biasSquared = complexity.map((c) => 6 / (1 + c));\nconst variance = complexity.map((c) => 0.018 * c * c);\nconst irreducibleValue = 0.5;\nconst irreducibleError = complexity.map(() => irreducibleValue);\nconst totalError = complexity.map(\n  (_, i) => biasSquared[i] + variance[i] + irreducibleValue,\n);\n\nlet optimalIdx = 0;\ntotalError.forEach((v, i) => {\n  if (v < totalError[optimalIdx]) optimalIdx = i;\n});\nconst optimalComplexity = complexity[optimalIdx];\nconst lastIdx = N - 1;\n\n// [x, y] pairs so each value lands at its real complexity coordinate.\nconst asPairs = (ys) => complexity.map((x, i) => [x, ys[i]]);\n\n// --- Chart -------------------------------------------------------------------\nHighcharts.chart(\"container\", {\n  chart: {\n    type: \"spline\",\n    backgroundColor: \"transparent\",\n    animation: false,\n    spacingRight: 110,\n    style: { fontFamily: \"inherit\" },\n  },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: {\n    text: \"curve-bias-variance-tradeoff · javascript · highcharts · anyplot.ai\",\n    style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" },\n  },\n  subtitle: {\n    text: \"Total Error = Bias² + Variance + Irreducible Error\",\n    style: { color: t.inkSoft, fontSize: \"14px\" },\n  },\n  xAxis: {\n    min: 1,\n    max: 15,\n    lineColor: t.inkSoft,\n    tickColor: t.inkSoft,\n    gridLineColor: t.grid,\n    title: {\n      text: \"Model Complexity\",\n      style: { color: t.inkSoft, fontSize: \"16px\" },\n    },\n    plotBands: [\n      {\n        from: 1,\n        to: optimalComplexity,\n        color: t.grid,\n        label: {\n          text: \"Underfitting zone\",\n          align: \"center\",\n          verticalAlign: \"bottom\",\n          y: -12,\n          style: { color: t.inkSoft, fontSize: \"13px\" },\n        },\n      },\n      {\n        from: optimalComplexity,\n        to: 15,\n        color: hexToRgba(t.amber, 0.1),\n        label: {\n          text: \"Overfitting zone\",\n          align: \"center\",\n          verticalAlign: \"bottom\",\n          y: -12,\n          style: { color: t.inkSoft, fontSize: \"13px\" },\n        },\n      },\n    ],\n    plotLines: [\n      {\n        value: optimalComplexity,\n        color: t.inkSoft,\n        width: 1.5,\n        dashStyle: \"ShortDash\",\n        zIndex: 4,\n        label: {\n          text: `Optimal complexity ≈ ${optimalComplexity.toFixed(1)}`,\n          rotation: 0,\n          align: \"center\",\n          y: 20,\n          style: { color: t.inkSoft, fontSize: \"13px\" },\n        },\n      },\n    ],\n  },\n  yAxis: {\n    min: 0,\n    title: {\n      text: \"Prediction Error\",\n      style: { color: t.inkSoft, fontSize: \"16px\" },\n    },\n    gridLineColor: t.grid,\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n  },\n  legend: { enabled: false },\n  tooltip: { enabled: false },\n  plotOptions: {\n    series: {\n      animation: false,\n      marker: { enabled: false },\n      lineWidth: 3,\n      enableMouseTracking: false,\n      dataLabels: {\n        enabled: true,\n        crop: false,\n        overflow: \"allow\",\n        align: \"left\",\n        x: 8,\n        y: 2,\n        style: { fontSize: \"14px\", fontWeight: \"600\", textOutline: \"none\" },\n        formatter: function () {\n          return this.point.index === lastIdx ? this.series.name : null;\n        },\n      },\n    },\n  },\n  series: [\n    {\n      name: \"Bias²\",\n      data: asPairs(biasSquared),\n      color: t.palette[0],\n      dataLabels: { style: { color: t.palette[0] } },\n    },\n    {\n      name: \"Variance\",\n      data: asPairs(variance),\n      color: t.palette[1],\n      dataLabels: { style: { color: t.palette[1] } },\n    },\n    {\n      name: \"Irreducible Error\",\n      data: asPairs(irreducibleError),\n      color: t.inkSoft,\n      dashStyle: \"Dash\",\n      lineWidth: 2,\n      dataLabels: {\n        style: { color: t.inkSoft },\n        align: \"left\",\n        x: 10,\n        y: -10,\n        formatter: function () {\n          return this.point.index === 0 ? this.series.name : null;\n        },\n      },\n    },\n    {\n      name: \"Total Error\",\n      data: asPairs(totalError),\n      color: t.ink,\n      lineWidth: 4,\n      zIndex: 3,\n      dataLabels: { style: { color: t.ink } },\n    },\n    {\n      type: \"scatter\",\n      name: \"Optimal complexity\",\n      data: [[optimalComplexity, totalError[optimalIdx]]],\n      color: t.ink,\n      marker: {\n        enabled: true,\n        symbol: \"circle\",\n        radius: 7,\n        fillColor: t.ink,\n        lineColor: t.pageBg,\n        lineWidth: 2,\n      },\n      dataLabels: { enabled: false },\n      zIndex: 5,\n    },\n  ],\n});\n"}