Building neural networks from first principles β no magic, no black boxes.
A hands-on implementation of computation graphs, manual derivative calculations, and backpropagation using pure calculus and the chain rule.
Most deep learning tutorials hand you PyTorch or TensorFlow and say "trust the .backward() call."
This project does the opposite.
Every gradient is computed by hand, every node in the computation graph is explicitly differentiated, and every chain rule application is written out in code. The goal is to build genuine intuition for how automatic differentiation actually works under the hood β before letting any framework do it for you.
"Everything became much clearer when I started ignoring full-page dense derivations and just started writing code." β Andrej Karpathy
This branch is the mathematical core of the project. It implements:
- A
Valueclass that wraps scalars and tracks operations to form a computation graph - Manual derivative formulas for each operation node using calculus rules
- Local gradients for direct parentβchild relationships
- Chain rule propagation to carry gradients backwards through indirect dependencies
- Numerical gradient verification β comparing analytical derivatives against finite differences to catch errors
- The foundation for automatic differentiation (
autograd) built from scratch
Each scalar in the network is a Value node. When you perform operations on Value objects, they silently record the computation graph β who produced whom, and which operation was used.
a = Value(2.0, label='a')
b = Value(-3.0, label='b')
c = Value(10.0, label='c')
e = a*b; e.label = 'e'
d = e + c; d.label = 'd'
f = Value(-2.0, label='f')
L = d * f; L.label = 'L'This builds a directed acyclic graph (DAG) of operations β exactly what modern autograd engines use internally.
For each node, the local gradient (how much the node's output changes with respect to each of its inputs) is derived analytically using calculus rules:
| Operation | Local Gradient |
|---|---|
z = a + b |
βz/βa = 1, βz/βb = 1 |
z = a * b |
βz/βa = b, βz/βb = a |
z = a ** n |
βz/βa = n Β· aβΏβ»ΒΉ |
z = tanh(a) |
βz/βa = 1 β tanhΒ²(a) |
z = exp(a) |
βz/βa = exp(a) |
z = a / b |
βz/βa = 1/b, βz/βb = βa/bΒ² |
No approximations. No finite differences. Pure calculus.
The chain rule is what makes backpropagation possible. For any intermediate node e in the graph:
dL/da = (dL/de) Β· (de/da)
In code, this means every node multiplies the gradient flowing in from its children by its own local gradient, then passes the result upstream to its parents.
This accumulation (using +=) is critical β a single node can feed multiple downstream paths, so gradients from all paths must be summed.
To validate that our analytical derivatives are correct, we compare them against numerical derivatives computed via finite differences:
df/dx β (f(x + h) - f(x)) / h where h β 0
If the analytical and numerical gradients match (within floating point tolerance), the implementation is correct. This is a standard technique used in industry to unit-test gradient implementations.
NeuralNetworkBasics/
β
βββ init.ipynb # All concepts: Value class, computation graph, manual backprop & gradient verification
βββ README.md
Everything lives in a single self-contained notebook β no scattered scripts, no dependencies to wire up. Open it and run top to bottom.
pip install numpy matplotlib jupytergit clone https://github.com/FazalHussain/NeuralNetworkBasics.git
cd NeuralNetworkBasics
git checkout feature/manual_derivative_calculation_for_each_node
jupyter notebook init.ipynbFor a node Z that depends on y, which depends on x:
Derivative Calculation
π References: Chain Rule β Wikipedia Β· Derivative β Wikipedia
This project follows the philosophy of learning by building. The recommended progression:
1. Understand scalar derivatives
2. Build the Value class
3. Construct a small expression graph
4. Derive local gradients manually
5. Apply chain rule backwards
6. Verify with numerical gradients
7. Generalize β autograd engine β (next milestone)
This project is deeply inspired by Andrej Karpathy's legendary lecture series on building neural networks from scratch:
πΊ The spelled-out intro to neural networks and backpropagation: building micrograd
Karpathy's micrograd project demonstrates that a complete autograd engine β capable of training real neural networks β can be implemented in under 100 lines of Python. This repository walks through the same ideas with additional annotation, manual derivation steps, and verification tooling.
-
Valueclass with computation graph tracking - Manual derivative calculation for each operation node
- Chain rule propagation (manual backpropagation)
- Numerical gradient verification
- Generalized
backward()pass (topological sort) - Neuron, Layer, and MLP classes built on top of
Value - Training a small classifier end-to-end
- Visualization of computation graphs
Syed Fazal Hussain Naqvi Senior Android Engineer & Technical Lead Β· AI Engineering Enthusiast
"To understand backpropagation, you must first understand differentiation. To understand differentiation, you must write it out yourself."
β Star this repo if it helped you understand the math behind neural networks.