Custom neural made with very loose inspiration from PyTorch.
The main.py file shows an example of usage, but the basic idea is as follows:
import numpy as np
from nn.component.parameter import Linear
from nn.component.activation import ReLU, Identity
from nn.model.mlp import MLP
# Initialize network
model = MLP(Linear(1, 3), ReLU(), Linear(3, 1), Identity()) # The reason for Identity() is because the network
# expects an activation for every Linear layer
f = lambda z: 3 * np.sin(20 * z)
X = np.random.rand(100000, 1)
y = f(X)
losses = []
for i in range(10):
for x, _y in zip(X, y):
# Calculates loss for single data point
loss = model.cost(x, _y)
# Model performs backpropagation and weights updates simultaneously
model.back_prop(x, _y)
losses.append(loss)
print(f"Epoch: {i}, Loss: {losses[-1]}")The following graph shows the network in main.py's approximation of f(X).

The general principle behind backpropagation lies in the chain rule. For example to derive
But this has some issues, as
This swapping of the order is the reason I decided to do the computations in pairs, otherwise it was too confusing.
However, this also changes the shape of the output from a 3D tensor to a matrix,
which means we have to change some of the rest of the equation as well. Each
reuse.