{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "neural_iris-intro",
      "metadata": {},
      "source": "# Aner Neural: Iris classifier\n\n**Aner Notebook example: compatible installed Aner executable and VS Code extension 0.1.16.** Use the binary and editor versions recommended together by your release; see `docs/INSTALLATION.md` and `docs/VSCODE.md`. Select **`Aner — notebook`** to run the code cell. This notebook uses independent program mode: each code cell runs separately, and variables are not shared between cells. The supplied notebook starts with empty outputs. Jupyter integration is not included.\n\nThe code cell contains the complete, unchanged `examples/neural_iris.aner` program, including its source attribution. Aner executes the program and its numerical operations in its native runtime.\n\nData: Fisher, R. (1936). *Iris* [Dataset]. UCI Machine Learning Repository. [Dataset citation](https://doi.org/10.24432/C56C76), [official UCI source](https://archive.ics.uci.edu/dataset/53/iris), [CC BY 4.0 license](https://creativecommons.org/licenses/by/4.0/). The bundled original UCI records are retained; Aner maps class names to zero based IDs. See `datasets/iris/README.md` and `THIRD_PARTY_DATA.md` supplied with the examples for variant details and complete notices.\n\nThis is a small historical teaching experiment, not a clinical model or generalization benchmark. It uses a fixed stratified split, fits the standardizer only on training rows, and evaluates held out rows after the fixed training schedule. The preserved dataset includes duplicate observations; row partitioning does not establish independent specimens.\n"
    },
    {
      "cell_type": "markdown",
      "id": "neural_iris-topology",
      "metadata": {
        "aner": {
          "block_kind": "image"
        }
      },
      "source": "![Conceptual dense Iris network: four standardized input features feed eight tanh hidden units and then three linear output logits.](attachment:aner-iris-topology.svg)\n\n**Conceptual topology, not a runtime capture.** This authored diagram summarizes the source program’s three layers; it contains no recorded weights, activations, gradients, or training results. The output layer produces logits, with probabilities computed separately for evaluation.\n\nThe diagram is attached to this Markdown cell and displays in the Aner VS Code notebook editor.\n",
      "attachments": {
        "aner-iris-topology.svg": {
          "image/svg+xml": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"780\" height=\"220\" viewBox=\"0 0 780 220\" role=\"img\" aria-labelledby=\"topology-title topology-description\">\n  <title id=\"topology-title\">Iris network: 4 inputs to 8 tanh units to 3 logits</title>\n  <desc id=\"topology-description\">Conceptual dense network topology. Four standardized input features feed eight tanh hidden units, which feed three linear output logits. No runtime values are shown.</desc>\n  <rect width=\"780\" height=\"220\" rx=\"16\" fill=\"#f4f6fa\"/>\n  <g fill=\"none\" stroke=\"#56647a\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n    <path d=\"M242 110 H274 M266 102 L274 110 L266 118\"/>\n    <path d=\"M504 110 H536 M528 102 L536 110 L528 118\"/>\n  </g>\n  <rect x=\"24\" y=\"44\" width=\"208\" height=\"132\" rx=\"18\" fill=\"#e2edff\" stroke=\"#91afe0\"/>\n  <rect x=\"286\" y=\"44\" width=\"208\" height=\"132\" rx=\"18\" fill=\"#e2f1e9\" stroke=\"#8bbda4\"/>\n  <rect x=\"548\" y=\"44\" width=\"208\" height=\"132\" rx=\"18\" fill=\"#eee5f8\" stroke=\"#b19bcf\"/>\n  <g font-family=\"sans-serif\" text-anchor=\"middle\" fill=\"#203047\">\n    <text x=\"128\" y=\"106\" font-size=\"27\" font-weight=\"600\">4 inputs</text>\n    <text x=\"128\" y=\"135\" font-size=\"16\">standardized features</text>\n    <text x=\"390\" y=\"106\" font-size=\"26\" font-weight=\"600\">8 tanh units</text>\n    <text x=\"390\" y=\"135\" font-size=\"16\">dense hidden layer</text>\n    <text x=\"652\" y=\"106\" font-size=\"27\" font-weight=\"600\">3 logits</text>\n    <text x=\"652\" y=\"135\" font-size=\"16\">linear output layer</text>\n  </g>\n</svg>\n"
        }
      }
    },
    {
      "cell_type": "code",
      "id": "neural_iris-source",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": "// Iris classification: native Aner, fixed stratified split, training-only scaling.\n// Data: Fisher, R. (1936). Iris. UCI. https://doi.org/10.24432/C56C76\n// CC BY 4.0: https://creativecommons.org/licenses/by/4.0/\n// Original UCI iris.data retained; runtime class names map to zero-based IDs.\n// Full attribution and variant notes: datasets/iris/README.md.\nimport aner.dataset;\nimport aner.nn;\nimport aner.metrics;\nimport aner.viz;\n\nfn logits(x: Tensor, w1: Tensor, b1: Tensor, w2: Tensor, b2: Tensor) -> Tensor {\n    let hidden = nn.tanh(nn.add_bias(nn.matmul(x, w1), b1));\n    return nn.add_bias(nn.matmul(hidden, w2), b2);\n}\n\nfn main() -> Unit {\n    let flowers = dataset.iris();\n    let split_seed = 2026;\n    let partitions = dataset.split(flowers, 0.2, split_seed);\n    let training = dataset.train(partitions);\n    let testing = dataset.test(partitions);\n\n    // Fit on training rows only; reuse those exact statistics for the test set.\n    let scaler = dataset.fit_standardizer(dataset.features(training));\n    let x_train = dataset.transform(scaler, dataset.features(training));\n    let x_test = dataset.transform(scaler, dataset.features(testing));\n    let y_train = dataset.one_hot(training);\n    let train_labels = dataset.targets(training);\n    let test_labels = dataset.targets(testing);\n\n    var w1 = nn.parameter(nn.random(4, 8, 42, 0.5));\n    var b1 = nn.parameter(nn.zeros(1, 8));\n    var w2 = nn.parameter(nn.random(8, 3, 43, 0.5));\n    var b2 = nn.parameter(nn.zeros(1, 3));\n    let epochs = 2000;\n    let learning_rate = 0.1;\n\n    print(\"Dataset citation\"); print(dataset.citation(flowers));\n    print(\"Dataset license\"); print(dataset.license(flowers));\n    print(\"Dataset version\"); print(dataset.version(flowers));\n    print(\"Dataset SHA256\"); print(dataset.sha256(flowers));\n    print(\"Split seed\"); print(split_seed);\n    print(\"Training rows\"); print(dataset.rows(training));\n    print(\"Test rows\"); print(dataset.rows(testing));\n    print(\"Epochs\"); print(epochs);\n    print(\"Learning rate\"); print(learning_rate);\n    print(\"Initial training cross-entropy\");\n    print(nn.item(nn.cross_entropy(logits(x_train, w1, b1, w2, b2), y_train)));\n\n    var epoch = 0;\n    while epoch < epochs {\n        let scores = logits(x_train, w1, b1, w2, b2);\n        // Pass raw logits to this fused, numerically stable loss.\n        let loss = nn.cross_entropy(scores, y_train);\n        nn.backward(loss);\n        if epoch < 3 || epoch % 100 == 0 { viz.capture(epoch, loss); }\n        w1 = nn.sgd(w1, learning_rate);\n        b1 = nn.sgd(b1, learning_rate);\n        w2 = nn.sgd(w2, learning_rate);\n        b2 = nn.sgd(b2, learning_rate);\n        epoch = epoch + 1;\n    }\n\n    let train_scores = logits(x_train, w1, b1, w2, b2);\n    let final_loss = nn.cross_entropy(train_scores, y_train);\n    nn.backward(final_loss);\n    viz.capture(epochs, final_loss);\n    print(\"Final training cross-entropy\"); print(nn.item(final_loss));\n    print(\"Training accuracy\"); print(metrics.accuracy(nn.argmax(train_scores), train_labels));\n\n    // Evaluate the held-out rows once after the fixed training schedule.\n    let test_scores = logits(x_test, w1, b1, w2, b2);\n    print(\"Test accuracy\"); print(metrics.accuracy(nn.argmax(test_scores), test_labels));\n    let probabilities = nn.softmax(test_scores);\n    let predictions = nn.argmax(probabilities);\n    print(\"First test row class scores (probabilities)\");\n    var class_id = 0;\n    while class_id < dataset.classes(flowers) {\n        print(dataset.class_name(flowers, class_id));\n        print(nn.value(probabilities, 0, class_id));\n        class_id = class_id + 1;\n    }\n    print(\"First test row predicted class ID\"); print(nn.value(predictions, 0, 0));\n    print(\"First test row true class ID\"); print(nn.value(test_labels, 0, 0));\n}\n"
    },
    {
      "cell_type": "markdown",
      "id": "neural_iris-cli",
      "metadata": {},
      "source": "## Run the source file from a terminal\n\nWith Aner installed and available on `PATH`, open a terminal in the folder containing the supplied `examples/` directory and run:\n\n```sh\naner check examples/neural_iris.aner\naner run examples/neural_iris.aner\n```\n\nThe same commands work on Windows when the installed `aner.exe` is on `PATH`. See `docs/INSTALLATION.md` if the command is not found.\n\nExpected observations: source citation/license/version/hash; split seed 2026; 120 training rows and 30 held out rows; 2,000 full batch updates at learning rate 0.1; initial and final training cross entropy; training and test accuracy; and probabilities plus predicted/true IDs for the first test row. The network has four standardized inputs, eight tanh hidden units, and three linear logits. Training uses raw logits for cross entropy; softmax is applied afterward for the displayed probabilities.\n\nTraining loss should decrease for this example. Exact floating point values across different releases and machines are not promised, and the held out result is a teaching observation rather than a performance guarantee. The distributed example starts with a null execution count and no outputs. Running it in VS Code records the actual result.\n\nFor a separate offline training report, choose an output directory that does not already exist and run:\n\n```sh\naner run examples/neural_iris.aner --debug-viz reports/iris-notebook --debug-values\n```\n\nOpen the generated `index.html` in a browser. This separate report is created by the installed Aner command; it is not embedded automatically in the notebook. It records training graph snapshots and bounded values; the held out set is evaluated after training. See `docs/DATASETS.md`, `docs/NEURAL.md`, and `docs/VISUAL_DEBUGGING.md` for the implemented contracts.\n"
    }
  ],
  "metadata": {
    "kernelspec": {
      "name": "aner",
      "display_name": "Aner",
      "language": "aner"
    },
    "language_info": {
      "name": "aner",
      "file_extension": ".aner",
      "mimetype": "text/x-aner"
    },
    "aner": {
      "status": "example",
      "kernel_selector_status": "proposed_not_installed",
      "source_file": "../neural_iris.aner",
      "source_sha256": "b9519d708a617b1a01b3dbcc48f5e34f2c08decf1abe32a599697b0d10d2c60b",
      "execution_mode": "independent-programs"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
