// Pima Indians Diabetes: Smith et al. (1988), historical OpenML 37 v1 copy.
// See datasets/diabetes/README.md and THIRD_PARTY_DATA.md for source status.
// Educational classification example; no accuracy or clinical-use claim.
import aner.dataset
import aner.nn
import aner.ml

// 1. Load all 768 rows and 8 numeric predictors, with 2 outcome classes.
// Preserve source zeros, including missing-measurement placeholders.
// This example fits standardization only; it does not replace or impute zeros.
let diabetes = dataset.load("diabetes")
print("Diabetes: rows, features, classes")
print(dataset.rows(diabetes))
print(dataset.cols(diabetes))
print(dataset.classes(diabetes))

// 2. Split first: seeded, stratified 80/20 train/test views (614/154 rows).
let split = diabetes.split(test: 0.2, seed: 2026)
print("Training rows, held-out test rows")
print(dataset.rows(split.train()))
print(dataset.rows(split.test()))

// 3. Declare preprocessing and an 8 -> 12 -> 2 classifier with raw logits.
// standardize: true fits column means/scales ONLY when fit receives training rows.
let network = nn.sequential(seed: 42)
    .dense(inputs: 8, outputs: 12, initialization: "xavier")
    .tanh()
    .dense(inputs: 12, outputs: 2, initialization: "xavier")
let pipeline = ml.classifier(network, standardize: true,
    loss: "cross_entropy", optimizer: "adam")
    .on(device: "cpu", precision: "Float64", policy: "preserve")

// 4. Fit preprocessing and train on training rows only, for a fixed horizon.
// The fitted model owns these training-fitted statistics and model parameters.
let fitted = pipeline.fit(split.train(), epochs: 400, rate: 0.01)
print("Training-fitted pregnancies mean, scale")
print(nn.value(ml.center(fitted), 0, 0))
print(nn.value(ml.scale(fitted), 0, 0))

// 5. Evaluate the held-out test once; reuse the fitted scaler without refitting.
// Test rows do not choose parameters, preprocessing, or the training horizon.
print(fitted.evaluate(split.test()).summary())
