Chapter 06
micrograd lecture first half roughly
NotebookPython 334 cells
In [10]python · cell 1
python
import math
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inlineIn [11]python · cell 2
python
def f(x):
return 3*x**2 - 4*x + 5In [12]python · cell 3
python
f(3.0)Output
20.0
In [15]python · cell 4
python
xs = np.arange(-5, 5, 0.25)
ys = f(xs)
plt.plot(xs, ys)Output
[<matplotlib.lines.Line2D at 0x7f9b98432ee0>]
<Figure size 432x288 with 1 Axes>
In [42]python · cell 5
python
h = 0.000001
x = 2/3
(f(x + h) - f(x))/hOutput
2.999378523327323e-06
In [43]python · cell 6
python
# les get more complex
a = 2.0
b = -3.0
c = 10.0
d = a*b + c
print(d)Output
4.0
In [50]python · cell 7
python
h = 0.0001
# inputs
a = 2.0
b = -3.0
c = 10.0
d1 = a*b + c
c += h
d2 = a*b + c
print('d1', d1)
print('d2', d2)
print('slope', (d2 - d1)/h)Output
d1 4.0 d2 4.0001 slope 0.9999999999976694
In [257]python · cell 8
python
class Value:
def __init__(self, data, _children=(), _op='', label=''):
self.data = data
self.grad = 0.0
self._backward = lambda: None
self._prev = set(_children)
self._op = _op
self.label = label
def __repr__(self):
return f"Value(data={self.data})"
def __add__(self, other):
out = Value(self.data + other.data, (self, other), '+')
def _backward():
self.grad += 1.0 * out.grad
other.grad += 1.0 * out.grad
out._backward = _backward
return out
def __mul__(self, other):
out = Value(self.data * other.data, (self, other), '*')
def _backward():
self.grad += other.data * out.grad
other.grad += self.data * out.grad
out._backward = _backward
return out
def tanh(self):
x = self.data
t = (math.exp(2*x) - 1)/(math.exp(2*x) + 1)
out = Value(t, (self, ), 'tanh')
def _backward():
self.grad += (1 - t**2) * out.grad
out._backward = _backward
return out
def backward(self):
topo = []
visited = set()
def build_topo(v):
if v not in visited:
visited.add(v)
for child in v._prev:
build_topo(child)
topo.append(v)
build_topo(self)
self.grad = 1.0
for node in reversed(topo):
node._backward()
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'
LOutput
Value(data=-8.0)
In [139]python · cell 9
python
from graphviz import Digraph
def trace(root):
# builds a set of all nodes and edges in a 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)
return nodes, edges
def draw_dot(root):
dot = Digraph(format='svg', graph_attr={'rankdir': 'LR'}) # LR = left to right
nodes, edges = trace(root)
for n in nodes:
uid = str(id(n))
# for any value in the graph, create a rectangular ('record') node for it
dot.node(name = uid, label = "{ %s | data %.4f | grad %.4f }" % (n.label, n.data, n.grad), shape='record')
if n._op:
# if this value is a result of some operation, create an op node for it
dot.node(name = uid + n._op, label = n._op)
# and connect this node to it
dot.edge(uid + n._op, uid)
for n1, n2 in edges:
# connect n1 to the op node of n2
dot.edge(str(id(n1)), str(id(n2)) + n2._op)
return dotIn [144]python · cell 10
python
draw_dot(L)Output
<graphviz.graphs.Digraph at 0x7f9bb8244670>
In [145]python · cell 11
python
a.data += 0.01 * a.grad
b.data += 0.01 * b.grad
c.data += 0.01 * c.grad
f.data += 0.01 * f.grad
e = a * b
d = e + c
L = d * f
print(L.data)Output
-7.286496
In [136]python · cell 12
python
def lol():
h = 0.001
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'
L1 = L.data
a = Value(2.0, label='a')
b = Value(-3.0, label='b')
b.data += h
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'
L2 = L.data
print((L2 - L1)/h)
lol()Output
-3.9999999999995595
In [152]python · cell 13
python
plt.plot(np.arange(-5,5,0.2), np.tanh(np.arange(-5,5,0.2))); plt.grid();Output
<Figure size 432x288 with 1 Axes>
In [241]python · cell 14
python
# inputs x1,x2
x1 = Value(2.0, label='x1')
x2 = Value(0.0, label='x2')
# weights w1,w2
w1 = Value(-3.0, label='w1')
w2 = Value(1.0, label='w2')
# bias of the neuron
b = Value(6.8813735870195432, label='b')
# x1*w1 + x2*w2 + b
x1w1 = x1*w1; x1w1.label = 'x1*w1'
x2w2 = x2*w2; x2w2.label = 'x2*w2'
x1w1x2w2 = x1w1 + x2w2; x1w1x2w2.label = 'x1*w1 + x2*w2'
n = x1w1x2w2 + b; n.label = 'n'
o = n.tanh(); o.label = 'o'In [244]python · cell 15
python
draw_dot(o)Output
<graphviz.graphs.Digraph at 0x7f9bc8477bb0>
In [243]python · cell 16
python
o.backward()In [235]python · cell 17
python
topo = []
visited = set()
def build_topo(v):
if v not in visited:
visited.add(v)
for child in v._prev:
build_topo(child)
topo.append(v)
build_topo(o)
topoOutput
[Value(data=6.881373587019543), Value(data=2.0), Value(data=-3.0), Value(data=-6.0), Value(data=0.0), Value(data=1.0), Value(data=0.0), Value(data=-6.0), Value(data=0.8813735870195432), Value(data=0.7071067811865476)]
In [221]python · cell 18
python
o.grad = 1.0In [223]python · cell 19
python
o._backward()In [225]python · cell 20
python
n._backward()In [227]python · cell 21
python
b._backward()In [228]python · cell 22
python
x1w1x2w2._backward()In [230]python · cell 23
python
x2w2._backward()
x1w1._backward()In [200]python · cell 24
python
x1.grad = w1.data * x1w1.grad
w1.grad = x1.data * x1w1.gradIn [198]python · cell 25
python
x2.grad = w2.data * x2w2.grad
w2.grad = x2.data * x2w2.gradIn [196]python · cell 26
python
x1w1.grad = 0.5
x2w2.grad = 0.5In [194]python · cell 27
python
x1w1x2w2.grad = 0.5
b.grad = 0.5In [192]python · cell 28
python
n.grad = 0.5In [187]python · cell 29
python
o.grad = 1.0In [191]python · cell 30
python
1 - o.data**2Output
0.4999999999999999
In [ ]python · cell 31
python
# o = tanh(n)
# do/dn = 1 - o**2In [258]python · cell 32
python
a = Value(3.0, label='a')
b = a + a ; b.label = 'b'
b.backward()
draw_dot(b)Output
<graphviz.graphs.Digraph at 0x7f9b983636d0>
In [259]python · cell 33
python
a = Value(-2.0, label='a')
b = Value(3.0, label='b')
d = a * b ; d.label = 'd'
e = a + b ; e.label = 'e'
f = d * e ; f.label = 'f'
f.backward()
draw_dot(f)Output
<graphviz.graphs.Digraph at 0x7f9ba89cc880>
In [ ]python · cell 34
python
