neural-network-study 0.5.2

A toy neural network library for educational purposes
Documentation
# agent.md

This file is a working guide for future coding agents in this repository.

## Project Snapshot

- Language: Rust (`edition = 2024`)
- Crate type: library + binaries
- Purpose: educational neural network implementation with matrix math and interactive demos

## Repo Layout

- `src/matrix.rs`: matrix type + core linear algebra operators
- `src/nn.rs`: neural network implementation and NN unit tests
- `src/lib.rs`: public exports (`Matrix`, `NeuralNetwork`, `ActivationFunction`, `NeuralNetworkError`)
- `src/bin/decision_boundary_playground.rs`: generates `target/decision-boundary-playground.html`
- `src/bin/flappy_evolution_playground.rs`: evolutionary flappy demo + model checkpoint/report
- `src/bin/depth_benchmark_playground.rs`: ring/spiral depth comparison + HTML report
- `src/main.rs`: minimal binary entrypoint

## Neural Network Design (Current)

- `NeuralNetwork` supports arbitrary depth via:
  - `layer_sizes: Vec<usize>`
  - `weights: Vec<Matrix>` with shape `(layer_sizes[i + 1], layer_sizes[i])`
  - `biases: Vec<Matrix>` with shape `(layer_sizes[i + 1], 1)`
- Constructor:
  - `NeuralNetwork::new(layer_sizes: Vec<usize>, rng: Option<&mut StdRng>)`
  - Requires at least 2 layers (`input`, `output`)
  - Rejects zero-sized layers
- Initialization:
  - Xavier-style range per layer pair: `sqrt(6 / (fan_in + fan_out))`
  - Biases start at zero
- Activation:
  - Single global activation function for all non-input layers
  - Derivative functions are applied to already-activated outputs
- Training:
  - SGD-style update
  - Error starts as `target - output`
  - Reverse pass updates all layers from output to input-adjacent
- Mutation:
  - Applies across all weights/biases
  - Mutated values sampled from `[-1.0, 1.0)`

## Compatibility Notes

- Architecture and serialized JSON are now layer-stack based.
- Old one-hidden-layer checkpoints are not backward compatible unless a migration layer is introduced.
- Flappy metadata now includes `layer_sizes` instead of only `hidden_size`.

## Fast Validation Commands

- Format:
  - `cargo fmt`
- Full test suite:
  - `cargo test`
- Run decision boundary demo:
  - `cargo run --bin decision_boundary_playground`
- Run flappy demo quickly:
  - `cargo run --bin flappy_evolution_playground -- --generations 1 --population 5`

## Testing Expectations

When changing `src/nn.rs`, preserve or extend tests for:

- Constructor validation (layer counts and nonzero sizes)
- Forward pass correctness for deep and no-hidden architectures
- Backprop behavior across all layers
- Mutation edge cases (`0.0`, `1.0`)
- Serde round-trip prediction stability
- Learning smoke tests (OR/XOR and perceptron linearly separable case)

## Pitfalls and Guardrails

- Keep matrix dimensions explicit in any new logic.
- Avoid introducing per-layer activation unless intentionally redesigning API.
- If you change serialization shape again, update both demos and any checkpoint/load paths.
- The depth benchmark trains tanh outputs against -1/1 targets and maps outputs to probabilities for evaluation. Keep the training and reporting conventions consistent.
- Prefer deterministic seeded tests for training behavior.

## Suggested Workflow for Future Changes

1. Inspect impacted call sites with `rg`.
2. Implement minimal code change with clear invariants.
3. Add/adjust unit tests in `src/nn.rs`.
4. Run `cargo fmt && cargo test`.
5. If demo integration is touched, run both binaries once.