{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "name": "aner",
      "display_name": "Aner",
      "language": "aner"
    },
    "language_info": {
      "name": "aner",
      "file_extension": ".aner"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "# Develop a native Aner neural network in Jupyter\n\nSelect the **Aner** kernel after installing `tools/jupyter`. Production is the default. The next cell enables development and clears native variables. Each later cell returns a read only variable table, captured object changes, loss, and an operation topology summary. No Python executes the Aner model.\n\nIris: Fisher (1936), UCI, CC BY 4.0. See the Aner dataset notices.\n",
      "id": "aner-dev-0"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "%aner dev\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "aner-dev-1"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Configure layers, initialization, loss, and optimizer\n",
      "id": "aner-dev-2"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import aner.dataset\n",
        "import aner.nn\n",
        "import aner.ml\n",
        "import aner.dev\n",
        "\n",
        "let split = dataset.iris().split(test: 0.2, seed: 2026)\n",
        "let network = nn.sequential(seed: 42)\n",
        "    .dense(inputs: 4, outputs: 8,\n",
        "           weights: nn.random(4, 8, seed: 7, scale: 0.25),\n",
        "           bias: nn.zeros(1, 8))\n",
        "    .tanh()\n",
        "    .dense(inputs: 8, outputs: 3)\n",
        "let pipeline = ml.classifier(network, standardize: true,\n",
        "                             loss: \"cross_entropy\", optimizer: \"sgd\")\n",
        "print(network.summary())\n",
        "print(pipeline.summary())\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "aner-dev-3"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Partial training\n\n400 full batch SGD updates; initial and final states are captured.\n",
      "id": "aner-dev-4"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "let fitted = pipeline.fit(split.train(), epochs: 400, rate: 0.1)\n",
        "dev.capture(\"Trained model\", fitted)\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "aner-dev-5"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Evaluate held out rows\n\nThe training scaler is reused; this does not fit on the test set.\n",
      "id": "aner-dev-6"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "print(fitted.evaluate(split.test()).summary())\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "aner-dev-7"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Continue from the trained parameters\n\nThe previous fitted model is unchanged; the same scaler is reused.\n",
      "id": "aner-dev-8"
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "let continued = pipeline.warm_start(fitted).fit(split.train(), epochs: 100, rate: 0.1)\n",
        "print(continued.evaluate(split.test()).summary())\n"
      ],
      "execution_count": null,
      "outputs": [],
      "id": "aner-dev-9"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Production\n\nWhen ready, change the first control cell to `%aner prod`, or remove it and restart the kernel, then Run All. Mode changes clear variables; rerun setup. `%aner dev values` opts into bounded raw tensor values. `%aner variables` repeats the last observed variable state without evaluating user code.\n",
      "id": "aner-dev-10"
    }
  ]
}
