|
NeuralNetwork 1.7.0
From-scratch backpropagation neural network in C
|
A dependency-free neural network library written from scratch in C — including convolutional networks — that trains a **~99.3%-accurate MNIST digit classifier** and beats classical baselines on time-series forecasting, with no libraries, no frameworks, just C99 and the standard math library.
The engine implements the pieces that make a network actually work: dense and convolutional / max-pooling layers, configurable activations (sigmoid / tanh / ReLU + softmax), MSE and cross-entropy losses, SGD-with-momentum and Adam, mini-batch training, principled weight initialisation (Xavier / He), and L2 weight decay. The convolutional backprop is verified against finite-difference gradients, and everything is tested, benchmarked, and CI-checked on Linux, macOS and Windows.
Every number here is produced by code in this repo and checked by CI — no hand-waving.
| Model | Test accuracy |
|---|---|
| CNN + data augmentation (conv8 → pool → conv16 → pool → dense128 → 10) | **~99.3%** |
| CNN (no augmentation) | ~99.1% |
MLP (784-128-10, ReLU + softmax, Adam) | ~97.9% |
All pure C99, no dependencies. The MLP trains in ~110 s; the CNN reaches 99.1% in ~10 epochs and 99.3% with --augment (random pixel shifts), using a learning-rate decay schedule.
CI trains fast subsets of both every push and fails if accuracy drops below its floor, so these numbers can't silently rot. The CNN's backprop is verified against finite-difference gradients (cnn_gradient_check) in the test suite.
The same convolutional engine on 3-channel 32x32 colour photos (a much harder problem than digits) — conv16 → pool → conv32 → pool → dense128 → 10:
| Metric | Value |
|---|---|
| Test accuracy | **~72%** (12 epochs, augmentation) |
| Input | 3x32x32 RGB |
Multi-channel convolution is the same code path as MNIST — only the input shape changes.
The same loader and trainer, pointed at a different and harder dataset with zero code changes, reaches **~88.6%** — proof the engine isn't overfit to one benchmark:
Forecasting annual sunspot activity from the prior 30 years (evaluation 1955–1979). The network beats both a naive baseline and a linear autoregression:
| Model | Eval RMSE |
|---|---|
| Neural net (open-loop) | 0.129 |
| Linear AR baseline | 0.141 |
| Naive / persistence | 0.198 |

cnn_save / cnn_load)rand()); fixed seed → fixed result-Wall -Wextra -Wpedantic-DNEURALNET_ENABLE_OPENMP=ON); gradients stay bit-identical to the serial buildexit(); errors are returnedYou need a C99 compiler. Either build system works.
Options: -DNEURALNET_WARNINGS_AS_ERRORS=ON, -DNEURALNET_ENABLE_SANITIZERS=ON, -DNEURALNET_ENABLE_COVERAGE=ON, -DNEURALNET_BUILD_EXAMPLES=OFF.
See ./neuralnet --help for the full flag list (learning rate, momentum, seed, split, etc.).
Each non-input neuron computes an activation of the weighted sum of the previous layer's outputs plus a bias. Training minimises the loss by gradient descent: the output error term is ‘act’(out)·(target−out)for MSE, or simply(out−target)for softmax + cross-entropy; hidden errors are back-propagated through the downstream weights. SGD applies Δw = eta·grad + alpha·Δw_prev`; Adam keeps per-weight first/second moment estimates for an adaptive step. Weights start from an activation-matched scheme (Xavier or He), and inputs are scaled into the activation's responsive range.

Further reading: https://en.wikipedia.org/wiki/Backpropagation
Browse the generated API reference at **https://bikebrainz.github.io/NeuralNetwork/** (built from source with Doxygen on every push to main).
See CONTRIBUTING.md. CI enforces builds (no warnings), tests, sanitizers, Valgrind, clang-tidy, cppcheck, clang-format, coverage, and the MNIST / Fashion-MNIST / CIFAR-10 accuracy floors.
Originally written by Dean Urschel; reworked into a configurable, tested, benchmarked, cross-platform library by Gavin Chase.
[MIT](LICENSE)