Hi there! I'm Shrijith Venkatrama, founder of Hexmos. Right now, I’m building LiveAPI, a tool that makes generating API docs from your code ridiculously easy.
A Sample Dataset and Comparing With Predictions
In the following dataset, we have 4 example inputs/outputs. And each input has 3 numbers.
We use the neural network (MLP object) defined in last post to do some predictions on each input.
xs = [
[2.0, 3.0, -1.0],
[3.0, -1.0, 0.5],
[0.5, 1.0, 1.0],
[1.0, 1.0, -1.0],
]
ys = [1.0, -1.0, -1.0, 1.0] # desired targets
ypred = [n(x) for x in xs]
ypred
When I run this I get some predictions which are either a bit less than required or more:
A Skeleton to Build a Loss Function
Code:
We define a loss variable, and define in the following way:
- Find the difference between actual output vs predicted output
- Square the difference (to remove negative sum)
- Sum all such squares of differences for whole input/output set
loss = sum((yout - ygt)**2 for ygt, yout in zip(ys, ypred))
loss.grad = 1
loss.backward()
n.layers[0].neurons[0].w[0].grad
Once we have the loss node, we can run backward propagation to get gradients for each node.
When we do draw_dot(loss)
we get a huge graph consisting of 4 forward passes corresponding to the 4 examples above and loss on top of those.
Gathering All Neural Network Parameters And Operating On Them
Pay attention to the parameters()
method in each of the classes below - where we collect the various parameters at every level (neuron, layer, MLP) for convenience:
class Neuron:
def __init__(self, nin):
self.w = [Value(random.uniform(-1,1)) for _ in range(nin)]
self.b = Value(random.uniform(-1,1))
def __call__(self, x):
# w * x + b
act = sum((wi * xi for wi, xi in zip(self.w, x)), self.b)
out = act.tanh()
return out
def parameters(self):
return self.w + [self.b]
class Layer:
def __init__(self, nin, nout):
self.neurons = [Neuron(nin) for _ in range(nout)]
def __call__(self, x):
outs = [n(x) for n in self.neurons]
return outs[0] if len(outs) == 1 else outs
def parameters(self):
params = []
for neuron in self.neurons:
params.extend(neuron.parameters())
return params
class MLP:
def __init__(self, nin, nouts):
sz = [nin] + nouts
self.layers = [Layer(sz[i], sz[i+1]) for i in range(len(nouts))]
def __call__(self, x):
for layer in self.layers:
x = layer(x)
return x
def parameters(self):
params = []
for layer in self.layers:
params.extend(layer.parameters())
return params
Now when I do n.parameters()
I get all the parameters in the neural network:
Reference
The spelled-out intro to neural networks and backpropagation: building micrograd - YouTube
Top comments (0)