Metadata-Version: 2.4
Name: propgrad
Version: 0.1.1
Summary: A lightweight and mathematically robust scalar autograd engine.
Author: Shubham Phapale
Author-email: shubhamphapale10@gmail.com
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: license-file
Dynamic: requires-python
Dynamic: summary

# propgrad

A robust and strictly dependency-free scalar Autograd engine, built as an advanced evolution of [micrograd](https://github.com/karpathy/micrograd). 

propgrad implements reverse-mode autodiff over a dynamically constructed DAG, operating purely on scalars to break down complex mathematical operations into granular steps. Alongside the engine sits a minimal PyTorch-like neural network library capable of building deep Multi-Layer Perceptrons (MLPs) for non-linear classification. 

### Installation

```bash
pip install propgrad
```

### Example usage

Evaluating an expression and backpropagating gradients via the chain rule:

```python
from propgrad.engine import Value

x = Value(2.5)
y = Value(-1.5)
z = Value(0.5)

a = x * y + z
b = a**2 - y
c = b.relu()
d = c / 2.0
e = d.exp()

print(f'{e.data:.4f}') # prints 416.2350 (forward pass)
e.backward()
print(f'{x.grad:.4f}') # prints 2029.1456 (de/dx)
print(f'{y.grad:.4f}') # prints -3590.0269 (de/dy)
```

### Neural Networks

You can rapidly construct deep architectures using the `propgrad.nn` module. Here is a minimal example of evaluating a 3-layer network and computing its gradients:

```python
from propgrad.engine import Value
from propgrad.nn import MLP

# Build a network: 3 inputs, two 4-node hidden layers, and 1 output
model = MLP(nin=3, nouts=[4, 4, 1])

# Perform a forward pass
inputs = [Value(2.0), Value(-1.5), Value(0.5)]
prediction = model(inputs)

# Backpropagate gradients to all parameters
prediction.backward()
```

### Training a neural net

The `demo.ipynb` notebook provides a full walkthrough of training an MLP binary classifier using SVM "Max-Margin" loss, L2 regularization, and Gradient Descent. 

The demo trains a 2-layer network with two 16-node hidden layers to successfully learn a strict non-linear decision boundary on the **Concentric Circles** dataset:

![Concentric Circles MLP](https://raw.githubusercontent.com/ShubhamPhapale/propgrad/main/circles_mlp.png)

### Tracing / visualization

propgrad intentionally omits visualization dependencies to remain tiny. However, you can easily trace the DAG yourself using `graphviz`.

```python
from graphviz import Digraph

def draw_dot(root, filename='graph'):
    nodes, edges = set(), set()
    def build(v):
        if v not in nodes:
            nodes.add(v)
            for child in v._prev:
                edges.add((child, v))
                build(child)
    build(root)
    
    dot = Digraph(format='svg', graph_attr={'rankdir': 'LR'})
    for n in nodes:
        uid = str(id(n))
        dot.node(name=uid, label="{ data %.4f | grad %.4f }" % (n.data, n.grad), shape='record')
        if n._op:
            dot.node(name=uid + n._op, label=n._op)
            dot.edge(uid + n._op, uid)
    for n1, n2 in edges:
        dot.edge(str(id(n1)), str(id(n2)) + n2._op)
    dot.render(filename)

# Usage example for a single 3D neuron:
# n = Neuron(3)
# y = n([Value(2.0), Value(-1.5), Value(0.5)])
# y.backward()
# draw_dot(y, 'neuron')
```

![3D Neuron](https://raw.githubusercontent.com/ShubhamPhapale/propgrad/main/neuron.svg)

### Running tests

Install PyTorch to run the unit tests (used as the reference for gradient correctness):

```bash
python3 -m pytest
```

### License

MIT
