{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "concise-diabetes-intro",
      "metadata": {},
      "source": "# Aner: Pima Diabetes classifier, step by step\n\nUse a current native Aner executable that includes the bundled Titanic and Pima Diabetes loaders, and the compatible Aner VS Code extension supplied for that executable. An older binary does not gain new datasets by opening this file. Open the project folder and this `.anernb` file in **Aner Notebook**. If needed, set **Aner › Notebook: Executable** (`aner.notebook.executable`) to the full executable path. If asked for a kernel, choose **`Aner — notebook`**.\n\nRun code cells from top to bottom, or choose **Run All**. This notebook saves **Shared variables** and **Dev** mode: later cells reuse the same native dataset, split, network, fitted model, and results. If you change data, splitting, topology, or training settings, choose **Aner: Restart Notebook Session**, then **Run All** for a fresh experiment. Saving the notebook preserves source and outputs, not live variables or a model checkpoint.\n\nAfter a cell completes, choose **Inspector** (or the cell's **Dev · Inspector** action) to inspect typed variables and recorded loss. After the training cell, use **Aner: Open Development Training Report** for captured computation topology and available gradients. To include bounded raw tensor values in inspection, enable `aner.notebook.developmentValues` before rerunning. These are completed cell observations; edits can make them stale, and a later cell may retain the training report as historical. The preprocessing cell also prints every learned center and scale explicitly.\n\nSource: Smith, J. W., et al. (1988), *Using the ADAP learning algorithm to forecast the onset of diabetes mellitus*; original owners: National Institute of Diabetes and Digestive and Kidney Diseases. Aner pins the historical [OpenML dataset 37, version 1](https://www.openml.org/search?type=data&id=37) Pima Indians Diabetes copy: **768 rows**, **eight numeric predictors**, and two classes (`tested_negative = 0`, `tested_positive = 1`). This is a binary classification dataset. Feature order is `pregnancies`, `glucose`, `blood_pressure`, `skin_thickness`, `insulin`, `bmi`, `diabetes_pedigree`, `age`.\n\nThe source zeros in glucose, blood pressure, skin thickness, insulin, and BMI are commonly treated as missing measurement placeholders. **This example leaves every zero unchanged** and fits standardization only; it does not impute. Zero pregnancies remains valid. An imputation policy would need to be explicit and fitted only on training rows.\n\nThe original data were withdrawn from UCI and mlbench over reported informed consent concerns; see the current [mlbench source status notice](https://github.com/cran/mlbench/blob/master/man/SynthDiabetes.Rd). The OpenML historical copy is not evidence that withdrawal has been reversed. See `datasets/diabetes/README.md` and `THIRD_PARTY_DATA.md` in the Aner project for source metadata and attribution. This is a teaching/implementation example; it makes no clinical use or accuracy claim.\n\n## 1. Load the dataset\n\nLoad all bundled source rows and original numeric values. No CSV preparation or network download is needed. Loading does not standardize, impute, remove rows, or interpret zeros.\n"
    },
    {
      "cell_type": "code",
      "id": "concise-diabetes-load",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "import aner.dataset\n",
        "import aner.nn\n",
        "import aner.ml\n",
        "\n",
        "let diabetes = dataset.load(\"diabetes\")\n",
        "print(\"Loaded rows, predictors, classes\")\n",
        "print(dataset.rows(diabetes))\n",
        "print(dataset.cols(diabetes))\n",
        "print(dataset.classes(diabetes))\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "concise-diabetes-split-note",
      "metadata": {},
      "source": "## 2. Split before fitting\n\nCreate a seeded, stratified 80/20 split **before fitting anything**. The 614 training rows are used for fitting; the 154 held out rows are reserved for the final evaluation.\n"
    },
    {
      "cell_type": "code",
      "id": "concise-diabetes-split",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "let split = diabetes.split(test: 0.2, seed: 2026)\n",
        "let training = split.train()\n",
        "let testing = split.test()\n",
        "print(\"Training rows\")\n",
        "print(training.rows())\n",
        "print(\"Held-out test rows\")\n",
        "print(testing.rows())\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "concise-diabetes-topology-note",
      "metadata": {},
      "source": "## 3. Declare the classifier and preprocessing\n\n8 inputs → 12 dense units → tanh → two raw class logits. Seed `42` fixes initialization, independently of split seed `2026`. The plan uses cross entropy, Adam, and CPU Float64 with the preserve policy. `standardize: true` declares preprocessing; it learns no statistics until `fit` receives the training partition.\n"
    },
    {
      "cell_type": "code",
      "id": "concise-diabetes-topology",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "let network = nn.sequential(seed: 42)\n",
        "    .dense(inputs: 8, outputs: 12, initialization: \"xavier\")\n",
        "    .tanh()\n",
        "    .dense(inputs: 12, outputs: 2, initialization: \"xavier\")\n",
        "let pipeline = ml.classifier(network, standardize: true,\n",
        "    loss: \"cross_entropy\", optimizer: \"adam\")\n",
        "    .on(device: \"cpu\", precision: \"Float64\", policy: \"preserve\")\n",
        "print(network.summary())\n",
        "print(pipeline.summary())\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "concise-diabetes-fit-note",
      "metadata": {},
      "source": "## 4. Fit on training rows only\n\nFit column centers, population scales, and model parameters from `training` only. Keep the fixed teaching configuration of **400 epochs** at learning rate **0.01**; held out results do not choose these settings. `fit` returns a fitted snapshot containing the learned scaler and trained classifier. After this cell completes, Inspector shows the fitted model and recorded training loss; the Development Training Report shows captured topology and available gradients.\n"
    },
    {
      "cell_type": "code",
      "id": "concise-diabetes-fit",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "let fitted = pipeline.fit(training, epochs: 400, rate: 0.01)\n",
        "print(\"Final training loss\")\n",
        "print(fitted.training_loss())\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "concise-diabetes-preprocessing-note",
      "metadata": {},
      "source": "## 5. Inspect the preprocessing fitted on training data\n\n`training_center` and `training_scale` are detached tensors with one value per input feature, in the source feature order above. The printed values are the statistics actually learned from training rows. Keep these variables visible in Inspector; enable `aner.notebook.developmentValues` and rerun if you want bounded raw tensor previews. Held out rows never contribute to these centers or scales.\n"
    },
    {
      "cell_type": "code",
      "id": "concise-diabetes-preprocessing",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "let training_center = ml.center(fitted)\n",
        "let training_scale = ml.scale(fitted)\n",
        "print(\"pregnancies: training center, population scale\")\n",
        "print(nn.value(training_center, 0, 0))\n",
        "print(nn.value(training_scale, 0, 0))\n",
        "print(\"glucose: training center, population scale\")\n",
        "print(nn.value(training_center, 0, 1))\n",
        "print(nn.value(training_scale, 0, 1))\n",
        "print(\"blood_pressure: training center, population scale\")\n",
        "print(nn.value(training_center, 0, 2))\n",
        "print(nn.value(training_scale, 0, 2))\n",
        "print(\"skin_thickness: training center, population scale\")\n",
        "print(nn.value(training_center, 0, 3))\n",
        "print(nn.value(training_scale, 0, 3))\n",
        "print(\"insulin: training center, population scale\")\n",
        "print(nn.value(training_center, 0, 4))\n",
        "print(nn.value(training_scale, 0, 4))\n",
        "print(\"bmi: training center, population scale\")\n",
        "print(nn.value(training_center, 0, 5))\n",
        "print(nn.value(training_scale, 0, 5))\n",
        "print(\"diabetes_pedigree: training center, population scale\")\n",
        "print(nn.value(training_center, 0, 6))\n",
        "print(nn.value(training_scale, 0, 6))\n",
        "print(\"age: training center, population scale\")\n",
        "print(nn.value(training_center, 0, 7))\n",
        "print(nn.value(training_scale, 0, 7))\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "concise-diabetes-evaluation-note",
      "metadata": {},
      "source": "## 6. Evaluate held out rows\n\nEvaluate once on `testing`, reusing the fitted training scaler without refitting preprocessing or updating model parameters. The summary includes held out results and workflow provenance; the retained `evaluation` variable is available in Inspector after this cell completes. This is a demonstration, not an accuracy target.\n"
    },
    {
      "cell_type": "code",
      "id": "concise-diabetes-evaluation",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "let evaluation = fitted.evaluate(testing)\n",
        "print(evaluation.summary())\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "concise-diabetes-rerun-note",
      "metadata": {},
      "source": "## Repeat a clean experiment\n\nTo edit and rerun the workflow, choose **Aner: Restart Notebook Session** and **Run All**. Then inspect the new completed cell values and training report. The matching plain source example is `examples/neural_diabetes_concise.aner`; both versions use the same dataset, split seed, initialization, preprocessing, loss, optimizer, precision, and fixed training settings. This downloaded notebook contains no saved results.\n"
    }
  ],
  "metadata": {
    "kernelspec": {
      "name": "aner",
      "display_name": "Aner",
      "language": "aner"
    },
    "language_info": {
      "name": "aner",
      "file_extension": ".aner"
    },
    "aner": {
      "execution_mode": "persistent-session",
      "runtime_mode": "development"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
