|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +Python/NumPy deep learning library (v1.0.0). Pure NumPy, no CUDA or PyTorch. |
| 4 | + |
| 5 | +## Commands |
| 6 | + |
| 7 | +```bash |
| 8 | +# Run all tests (unittest, not pytest) |
| 9 | +python -m unittest discover tests -v |
| 10 | + |
| 11 | +# Run a single test file |
| 12 | +python -m unittest tests.test_layer -v |
| 13 | + |
| 14 | +# Run a single test case |
| 15 | +python -m unittest tests.test_losses.TestLosses.test_mse -v |
| 16 | + |
| 17 | +# Demo scripts |
| 18 | +python main.py |
| 19 | +python examples/multiclass_classification.py |
| 20 | +python examples/siamese_network.py |
| 21 | + |
| 22 | +# Install in editable mode |
| 23 | +pip install -e . |
| 24 | + |
| 25 | +# Install with dev tools (ruff, matplotlib) |
| 26 | +pip install -e ".[dev]" |
| 27 | + |
| 28 | +# Lint |
| 29 | +ruff check nnlib/ tests/ |
| 30 | +``` |
| 31 | + |
| 32 | +## Architecture |
| 33 | + |
| 34 | +All source code lives in `nnlib/`. The public API is re-exported from `nnlib/__init__.py`. |
| 35 | + |
| 36 | +- `nnlib/neural_network.py` — `NeuralNetwork` class: model assembly, `compile()`, `fit()`, `predict()`, `save()/load()` (topology.json + weights.npz) |
| 37 | +- `nnlib/layer.py` — `Dense`, `Dropout`, `BatchNormalization`. Interface: `forward(x) -> (output, cache)`, `backward(d_output, cache) -> (d_input, grads_dict)`, `parameters() -> Dict[str, ndarray]` |
| 38 | +- `nnlib/activations.py` — Stateless activations. Same forward/backward cache pattern. |
| 39 | +- `nnlib/losses.py` — Losses. `BinaryCrossEntropy` and `CategoricalCrossEntropy` accept `from_logits=True`. |
| 40 | +- `nnlib/optimizers.py` — `SGD`, `AdaGrad`, `RMSprop`, `Adam`. Interface: `apply_gradients(list_of_tuples)`. They do not know about `weights`/`biases` names. |
| 41 | +- `nnlib/callbacks.py` — `EarlyStopping`, `ReduceLROnPlateau`, `ModelCheckpoint`, `History`. Uses `logging` module, not `print()`. |
| 42 | +- `nnlib/utils.py` — `train_test_split`, `shuffle_arrays`, `batch_iterator`, `to_categorical`, `normalize`, `standardize`. |
| 43 | +- `examples/siamese_network.py` — Standalone demo, not part of the library API. Imports directly from `nnlib.layer`/`nnlib.activations`. |
| 44 | + |
| 45 | +## Key conventions |
| 46 | + |
| 47 | +- **Layers are stateless w.r.t. trainable state.** Caches are returned from `forward()`, never stored on `self`. This is critical for siamese/shared-weight architectures. |
| 48 | +- **`from_logits=True` is the recommended pattern.** Final layer uses `activation='linear'`, loss applies softmax/sigmoid internally with a numerically stable shortcut. |
| 49 | +- **Persist via `save(dir)`/`load(dir)`** → `topology.json` + `weights.npz`. Do NOT use pickle (`save_model()`). |
| 50 | +- **`build()` is called by `compile()`**, not `fit()`. Shape mismatches fail immediately at compile time. |
| 51 | +- **Parameter interface is generic.** Layers expose `parameters() -> Dict[str, ndarray]` with arbitrary key names. Optimizers consume these without knowing internal structure. |
| 52 | +- **Use `logging`, not `print()`.** Training output goes through `logging.getLogger("neural_network")`. Callbacks use `logging.getLogger("neural_network.callbacks")`. |
| 53 | +- **`requirements.txt` is a redirect.** The real dependency spec is in `pyproject.toml`. `requirements.txt` just points to `pip install -e .`. |
| 54 | + |
| 55 | +## Tests |
| 56 | + |
| 57 | +68 tests using `unittest` (no pytest). Key test files: |
| 58 | + |
| 59 | +- `test_gradient_check.py` — Numerical gradient validation for backprop correctness |
| 60 | +- `test_model.py` — Integration tests + JSON/NPZ persistence roundtrip |
| 61 | +- `test_layer.py` — Includes state isolation test for shared-weight forward calls |
| 62 | +- `test_losses.py` — Covers `from_logits` paths |
| 63 | + |
| 64 | +Run all before pushing. No coverage tool configured. |
0 commit comments