zerotohero/notebooks/01b_mircograd.ipynb

2360 lines
170 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 142,
"id": "672d74cf-2fad-4493-9e3d-7ac2286dbfee",
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"id": "e7295cd8-1f33-40d2-aca5-e226e5b945ba",
"metadata": {},
"source": [
"Let's define a function f"
]
},
{
"cell_type": "code",
"execution_count": 143,
"id": "07a0fdd9-e9c4-4a28-9201-99429a638573",
"metadata": {},
"outputs": [],
"source": [
"def f(x):\n",
" return 3*x**2 - 4*x + 5"
]
},
{
"cell_type": "code",
"execution_count": 144,
"id": "67093e12-40d4-4abd-a81d-2f7f63881e19",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"20.0"
]
},
"execution_count": 144,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f(3.0)"
]
},
{
"cell_type": "markdown",
"id": "ec1297be-8d68-4d59-af98-39e45eb9857b",
"metadata": {},
"source": [
"We can also plot it for a range of values"
]
},
{
"cell_type": "code",
"execution_count": 145,
"id": "0a3f756f-886b-455d-b1f2-53060088dce9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x13257cd0250>]"
]
},
"execution_count": 145,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"xs = np.arange(-5, 5, 0.25)\n",
"ys = f(xs)\n",
"plt.plot(xs, ys)"
]
},
{
"cell_type": "markdown",
"id": "5c9cb820-159e-420d-b0d0-a8706e19f9d5",
"metadata": {},
"source": [
"Now, what's a derivate?\n",
"> It is sensitivity of the function to the change of the output with respect to the input.\n",
"\n",
"In simpler terms, (f(x+h) - f(x))/h, where h tends to zero. This gives us the slope."
]
},
{
"cell_type": "code",
"execution_count": 146,
"id": "7866b622-e10c-4003-844f-9044e7bdc080",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3.0000002482211127e-05"
]
},
"execution_count": 146,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"h = 0.00001\n",
"x = 2/3\n",
"(f(x+h) - f(x))/h"
]
},
{
"cell_type": "markdown",
"id": "4f027e6d-d889-4827-867e-335a96c20045",
"metadata": {},
"source": [
"Let's define a function with mupltiple inputs"
]
},
{
"cell_type": "code",
"execution_count": 147,
"id": "a3bcd24a-4a48-4d85-8d49-3fb751589b40",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4.0\n"
]
}
],
"source": [
"a = 2.0\n",
"b = -3.0\n",
"c = 10.0\n",
"\n",
"d = a*b + c\n",
"print(d)"
]
},
{
"cell_type": "code",
"execution_count": 148,
"id": "78dcb378-190f-4421-8d95-af79cdf05b18",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"d1 4.0\n",
"d2 3.999699999999999\n",
"slope -3.000000000010772\n"
]
}
],
"source": [
"h = 0.0001\n",
"a = 2.0\n",
"b = -3.0\n",
"c = 10.0\n",
"\n",
"d1 = a*b + c\n",
"a += h\n",
"d2 = a*b + c\n",
"\n",
"print('d1', d1)\n",
"print('d2', d2)\n",
"print('slope', (d2 - d1)/h) # By the good old derivation (wrt to a), we know that this will be b"
]
},
{
"cell_type": "code",
"execution_count": 149,
"id": "9fb1208f-1a1e-4fdb-a290-a7d0e8a5050a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"d1 4.0\n",
"d2 4.0002\n",
"slope 2.0000000000042206\n"
]
}
],
"source": [
"h = 0.0001\n",
"a = 2.0\n",
"b = -3.0\n",
"c = 10.0\n",
"\n",
"d1 = a*b + c\n",
"b += h\n",
"d2 = a*b + c\n",
"\n",
"print('d1', d1)\n",
"print('d2', d2)\n",
"print('slope', (d2 - d1)/h) # By the good old derivation (wrt to b), we know that this will be a"
]
},
{
"cell_type": "code",
"execution_count": 150,
"id": "e7bfb7ef-4c16-44c6-afce-ac20ab858b4f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"d1 4.0\n",
"d2 4.0001\n",
"slope 0.9999999999976694\n"
]
}
],
"source": [
"h = 0.0001\n",
"a = 2.0\n",
"b = -3.0\n",
"c = 10.0\n",
"\n",
"d1 = a*b + c\n",
"c += h\n",
"d2 = a*b + c\n",
"\n",
"print('d1', d1)\n",
"print('d2', d2)\n",
"print('slope', (d2 - d1)/h) # By the good old derivation (wrt to c), we know that this will be 1"
]
},
{
"cell_type": "markdown",
"id": "ad332637-3dbe-4630-bb5a-d5a76e935a9b",
"metadata": {},
"source": [
"The NN will be mathematically very large expressions. We now start by building the data structures for this. Let's start by making the `Value` object from mircograd"
]
},
{
"cell_type": "code",
"execution_count": 167,
"id": "e11f7575-00be-44a4-9bde-ae9288b1922a",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"class Value:\n",
"\n",
" def __init__(self, data, _children=(), _op='', label=''): # Define a empty tuple `children` to keep the pointers of other Value objects\n",
" # Define a empty set `op` to keep track of what created that Value object\n",
" self.data = data\n",
" self.grad = 0.0 # this is the derivative of Value wrt to its nodes; initalized as 0 (we assume at the beginning that every Value doesn't impact the output)\n",
" self._backward = lambda: None # for a leaf node, this should be nothing.\n",
" self._prev = set(_children) # This will be a empty set when we define a new Value object (a, b, c)\n",
" self._op = _op\n",
" self.label = label\n",
"\n",
" def __repr__(self):\n",
" return f\"Value(data={self.data})\"\n",
"\n",
" def __add__(self, other): # a.__add__(b)\n",
" other = other if isinstance(other, Value) else Value(other) # if other is NOT a Value obj, just make one\n",
" out = Value(self.data + other.data, (self, other), '+') # Since self.data and other.data is python floating point number,\n",
" # the addition is according to whatever is defined in the python kernel\n",
" def _backward():\n",
" self.grad += 1.0 * out.grad\n",
" other.grad += 1.0 * out.grad\n",
" out._backward = _backward\n",
" \n",
" return out\n",
"\n",
" def __radd__(self, other): # other + self\n",
" return self + other\n",
" \n",
" def __mul__(self, other): # a.__mul__(b) # You can't name it mult or multi, because we are defining magic methods for the Value object\n",
" other = other if isinstance(other, Value) else Value(other) # if other is NOT a Value obj, just make one\n",
" out = Value(self.data * other.data, (self, other), '*')\n",
"\n",
" def _backward():\n",
" self.grad += other.data * out.grad\n",
" other.grad += self.data * out.grad\n",
" out._backward = _backward\n",
" \n",
" return out\n",
"\n",
" def __pow__(self, other):\n",
" assert isinstance(other, (int, float)) # other is only int or float\n",
" out = Value(self.data**other, (self, ), f'**{other}')\n",
"\n",
" def _backward():\n",
" self.grad += other * self.data**(other-1) * out.grad\n",
" out._backward = _backward\n",
"\n",
" return out\n",
"\n",
" def __rmul__(self, other): # other * self\n",
" return self*other\n",
"\n",
" def __truediv__(self, other): # self / other\n",
" return self * other**-1\n",
"\n",
" def __neg__(self): # -self\n",
" return self * -1\n",
"\n",
" def __sub__(self, other): # self - other\n",
" return self + (-other)\n",
" \n",
" def tanh(self):\n",
" x = self.data\n",
" t = (math.exp(2*x) - 1)/(math.exp(2*x) + 1)\n",
" out = Value(t, (self, ), 'tanh')\n",
"\n",
" def _backward():\n",
" self.grad += (1 - t**2) * out.grad\n",
" out._backward = _backward\n",
" \n",
" return out\n",
"\n",
" def exp(self):\n",
" x = self.data\n",
" out = Value(math.exp(x), (self, ), 'exp')\n",
"\n",
" def _backward():\n",
" self.grad += out.data * out.grad\n",
" out._backward = _backward\n",
" \n",
" return out\n",
" \n",
" def backward(self):\n",
" \n",
" topo = []\n",
" visited = set()\n",
" def build_topo(v):\n",
" if v not in visited:\n",
" visited.add(v)\n",
" for child in v._prev:\n",
" build_topo(child)\n",
" topo.append(v)\n",
" build_topo(self)\n",
" \n",
" self.grad = 1.0\n",
" \n",
" for node in reversed(topo):\n",
" node._backward()"
]
},
{
"cell_type": "code",
"execution_count": 152,
"id": "cdf24235-ee48-4675-bb65-bd78d1ae201e",
"metadata": {},
"outputs": [],
"source": [
"# imported from mircograd's codebase\n",
"\n",
"from graphviz import Digraph\n",
"\n",
"def trace(root):\n",
" # builds a set of all nodes and edges in a graph\n",
" nodes, edges = set(), set()\n",
" def build(v):\n",
" if v not in nodes:\n",
" nodes.add(v)\n",
" for child in v._prev:\n",
" edges.add((child, v))\n",
" build(child)\n",
" build(root)\n",
" return nodes, edges\n",
"\n",
"def draw_dot(root):\n",
" dot = Digraph(format='svg', graph_attr={'rankdir': 'LR'}) # LR = left to right\n",
" \n",
" nodes, edges = trace(root)\n",
" for n in nodes:\n",
" uid = str(id(n))\n",
" # for any value in the graph, create a rectangular ('record') node for it\n",
" dot.node(name = uid, label = \"{%s | data %.4f | grad %.4f}\" % (n.label, n.data, n.grad), shape='record')\n",
" if n._op:\n",
" # if this value is a result of some operation, create an op node for it\n",
" dot.node(name = uid + n._op, label = n._op)\n",
" # and connect this node to it\n",
" dot.edge(uid + n._op, uid)\n",
"\n",
" for n1, n2 in edges:\n",
" # connect n1 to the op node of n2\n",
" dot.edge(str(id(n1)), str(id(n2)) + n2._op)\n",
"\n",
" return dot"
]
},
{
"attachments": {
"34f0ebc5-cb10-4db9-b7a9-9f501a3732da.webp": {
"image/webp": "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"
}
},
"cell_type": "markdown",
"id": "4eff7563-3a93-493d-8788-bb055a23d07a",
"metadata": {},
"source": [
"Let's look at another backpropagation using a neuron\n",
"\n",
"![neuron_model.webp](attachment:34f0ebc5-cb10-4db9-b7a9-9f501a3732da.webp)\n",
"\n",
"activation function is usually sigmoid or tanh [[more here]](https://en.wikipedia.org/wiki/Activation_function)"
]
},
{
"cell_type": "code",
"execution_count": 153,
"id": "29f8a9d0-16a6-49e3-b1db-52084db2ce24",
"metadata": {},
"outputs": [],
"source": [
"# inputs x1,x2\n",
"x1 = Value(2.0, label='x1')\n",
"x2 = Value(0.0, label='x2')\n",
"# weights w1,w2\n",
"w1 = Value(-3.0, label='w1')\n",
"w2 = Value(1.0, label='w2')\n",
"# bias of the neuron\n",
"b = Value(6.8813735870195432, label='b')\n",
"# x1*w1 + x2*w2 + b\n",
"x1w1 = x1*w1; x1w1.label = 'x1*w1'\n",
"x2w2 = x2*w2; x2w2.label = 'x2*w2'\n",
"x1w1x2w2 = x1w1 + x2w2; x1w1x2w2.label = 'x1*w1 + x2*w2'\n",
"n = x1w1x2w2 + b; n.label = 'n'\n",
"o = n.tanh(); o.label = 'output'\n",
"o.backward()"
]
},
{
"cell_type": "code",
"execution_count": 154,
"id": "1a1bdc0d-23e1-44bc-8b8e-1e88cdb64b2c",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Generated by graphviz version 13.1.0 (20250701.0955)\n",
" -->\n",
"<!-- Pages: 1 -->\n",
"<svg width=\"1594pt\" height=\"210pt\"\n",
" viewBox=\"0.00 0.00 1594.00 210.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 206)\">\n",
"<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-206 1590.25,-206 1590.25,4 -4,4\"/>\n",
"<!-- 1315738898448 -->\n",
"<g id=\"node1\" class=\"node\">\n",
"<title>1315738898448</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"668.25,-82.5 668.25,-118.5 939,-118.5 939,-82.5 668.25,-82.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"720.88\" y=\"-95.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x1*w1 + x2*w2</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"773.5,-83 773.5,-118.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"815.62\" y=\"-95.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data &#45;6.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"857.75,-83 857.75,-118.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"898.38\" y=\"-95.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738897168+ -->\n",
"<g id=\"node9\" class=\"node\">\n",
"<title>1315738897168+</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"1002\" cy=\"-127.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1002\" y=\"-122.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">+</text>\n",
"</g>\n",
"<!-- 1315738898448&#45;&gt;1315738897168+ -->\n",
"<g id=\"edge10\" class=\"edge\">\n",
"<title>1315738898448&#45;&gt;1315738897168+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M939.14,-118.99C947.95,-120.21 956.31,-121.36 963.87,-122.4\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"963.16,-125.83 973.55,-123.73 964.12,-118.9 963.16,-125.83\"/>\n",
"</g>\n",
"<!-- 1315738898448+ -->\n",
"<g id=\"node2\" class=\"node\">\n",
"<title>1315738898448+</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"605.25\" cy=\"-100.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"605.25\" y=\"-95.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">+</text>\n",
"</g>\n",
"<!-- 1315738898448+&#45;&gt;1315738898448 -->\n",
"<g id=\"edge1\" class=\"edge\">\n",
"<title>1315738898448+&#45;&gt;1315738898448</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M632.73,-100.5C639.73,-100.5 647.79,-100.5 656.52,-100.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"656.39,-104 666.39,-100.5 656.39,-97 656.39,-104\"/>\n",
"</g>\n",
"<!-- 1315738898960 -->\n",
"<g id=\"node3\" class=\"node\">\n",
"<title>1315738898960</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"2.25,-165.5 2.25,-201.5 195.75,-201.5 195.75,-165.5 2.25,-165.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"18.5\" y=\"-178.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">w2</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"34.75,-166 34.75,-201.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"74.62\" y=\"-178.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 1.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"114.5,-166 114.5,-201.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"155.12\" y=\"-178.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.0000</text>\n",
"</g>\n",
"<!-- 1315738896848* -->\n",
"<g id=\"node13\" class=\"node\">\n",
"<title>1315738896848*</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"261\" cy=\"-128.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"261\" y=\"-123.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">*</text>\n",
"</g>\n",
"<!-- 1315738898960&#45;&gt;1315738896848* -->\n",
"<g id=\"edge13\" class=\"edge\">\n",
"<title>1315738898960&#45;&gt;1315738896848*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M172.12,-165.01C180.9,-162.35 189.7,-159.5 198,-156.5 208.09,-152.86 218.82,-148.27 228.47,-143.88\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"229.86,-147.09 237.45,-139.69 226.9,-140.75 229.86,-147.09\"/>\n",
"</g>\n",
"<!-- 1315738898512 -->\n",
"<g id=\"node4\" class=\"node\">\n",
"<title>1315738898512</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"3.75,-110.5 3.75,-146.5 194.25,-146.5 194.25,-110.5 3.75,-110.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"18.5\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x2</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"33.25,-111 33.25,-146.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"73.12\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"113,-111 113,-146.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"153.62\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738898512&#45;&gt;1315738896848* -->\n",
"<g id=\"edge9\" class=\"edge\">\n",
"<title>1315738898512&#45;&gt;1315738896848*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M194.46,-128.5C204.21,-128.5 213.66,-128.5 222.21,-128.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"222.12,-132 232.12,-128.5 222.12,-125 222.12,-132\"/>\n",
"</g>\n",
"<!-- 1315738899088 -->\n",
"<g id=\"node5\" class=\"node\">\n",
"<title>1315738899088</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"711.75,-137.5 711.75,-173.5 895.5,-173.5 895.5,-137.5 711.75,-137.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"723.12\" y=\"-150.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"734.5,-138 734.5,-173.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"774.38\" y=\"-150.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 6.8814</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"814.25,-138 814.25,-173.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"854.88\" y=\"-150.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738899088&#45;&gt;1315738897168+ -->\n",
"<g id=\"edge12\" class=\"edge\">\n",
"<title>1315738899088&#45;&gt;1315738897168+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M895.91,-142.48C919.97,-139.05 944.58,-135.55 963.93,-132.79\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"964.34,-136.26 973.75,-131.39 963.35,-129.33 964.34,-136.26\"/>\n",
"</g>\n",
"<!-- 1315731070736 -->\n",
"<g id=\"node6\" class=\"node\">\n",
"<title>1315731070736</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1374.75,-109.5 1374.75,-145.5 1586.25,-145.5 1586.25,-109.5 1374.75,-109.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1400\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">output</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1425.25,-110 1425.25,-145.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1465.12\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.7071</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1505,-110 1505,-145.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1545.62\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 1.0000</text>\n",
"</g>\n",
"<!-- 1315731070736tanh -->\n",
"<g id=\"node7\" class=\"node\">\n",
"<title>1315731070736tanh</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"1311.75\" cy=\"-127.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1311.75\" y=\"-122.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">tanh</text>\n",
"</g>\n",
"<!-- 1315731070736tanh&#45;&gt;1315731070736 -->\n",
"<g id=\"edge2\" class=\"edge\">\n",
"<title>1315731070736tanh&#45;&gt;1315731070736</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1339.17,-127.5C1346.27,-127.5 1354.43,-127.5 1363.17,-127.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1362.99,-131 1372.99,-127.5 1362.99,-124 1362.99,-131\"/>\n",
"</g>\n",
"<!-- 1315738897168 -->\n",
"<g id=\"node8\" class=\"node\">\n",
"<title>1315738897168</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1065,-109.5 1065,-145.5 1248.75,-145.5 1248.75,-109.5 1065,-109.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1076.38\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">n</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1087.75,-110 1087.75,-145.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1127.62\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.8814</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1167.5,-110 1167.5,-145.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1208.12\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738897168&#45;&gt;1315731070736tanh -->\n",
"<g id=\"edge11\" class=\"edge\">\n",
"<title>1315738897168&#45;&gt;1315731070736tanh</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1249.01,-127.5C1257.39,-127.5 1265.52,-127.5 1272.98,-127.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1272.95,-131 1282.95,-127.5 1272.95,-124 1272.95,-131\"/>\n",
"</g>\n",
"<!-- 1315738897168+&#45;&gt;1315738897168 -->\n",
"<g id=\"edge3\" class=\"edge\">\n",
"<title>1315738897168+&#45;&gt;1315738897168</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1029.28,-127.5C1036.42,-127.5 1044.61,-127.5 1053.32,-127.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1053.06,-131 1063.06,-127.5 1053.06,-124 1053.06,-131\"/>\n",
"</g>\n",
"<!-- 1315738897680 -->\n",
"<g id=\"node10\" class=\"node\">\n",
"<title>1315738897680</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1.5,-55.5 1.5,-91.5 196.5,-91.5 196.5,-55.5 1.5,-55.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"16.25\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x1</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"31,-56 31,-91.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"70.88\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 2.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"110.75,-56 110.75,-91.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"153.62\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad &#45;1.5000</text>\n",
"</g>\n",
"<!-- 1315738897872* -->\n",
"<g id=\"node15\" class=\"node\">\n",
"<title>1315738897872*</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"261\" cy=\"-73.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"261\" y=\"-68.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">*</text>\n",
"</g>\n",
"<!-- 1315738897680&#45;&gt;1315738897872* -->\n",
"<g id=\"edge7\" class=\"edge\">\n",
"<title>1315738897680&#45;&gt;1315738897872*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M196.76,-73.5C205.77,-73.5 214.47,-73.5 222.4,-73.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"222.25,-77 232.25,-73.5 222.25,-70 222.25,-77\"/>\n",
"</g>\n",
"<!-- 1315738909968 -->\n",
"<g id=\"node11\" class=\"node\">\n",
"<title>1315738909968</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"0,-0.5 0,-36.5 198,-36.5 198,-0.5 0,-0.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"16.25\" y=\"-13.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">w1</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"32.5,-1 32.5,-36.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"74.62\" y=\"-13.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data &#45;3.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"116.75,-1 116.75,-36.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"157.38\" y=\"-13.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 1.0000</text>\n",
"</g>\n",
"<!-- 1315738909968&#45;&gt;1315738897872* -->\n",
"<g id=\"edge6\" class=\"edge\">\n",
"<title>1315738909968&#45;&gt;1315738897872*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M168.91,-36.94C178.74,-39.93 188.67,-43.15 198,-46.5 207.96,-50.07 218.58,-54.47 228.18,-58.68\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"226.54,-61.78 237.1,-62.67 229.4,-55.39 226.54,-61.78\"/>\n",
"</g>\n",
"<!-- 1315738896848 -->\n",
"<g id=\"node12\" class=\"node\">\n",
"<title>1315738896848</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"326.25,-110.5 326.25,-146.5 540,-146.5 540,-110.5 326.25,-110.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"352.62\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x2*w2</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"379,-111 379,-146.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"418.88\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"458.75,-111 458.75,-146.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"499.38\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738896848&#45;&gt;1315738898448+ -->\n",
"<g id=\"edge8\" class=\"edge\">\n",
"<title>1315738896848&#45;&gt;1315738898448+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M540.42,-111.01C549.89,-109.45 559,-107.95 567.21,-106.6\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"567.75,-110.05 577.05,-104.98 566.62,-103.15 567.75,-110.05\"/>\n",
"</g>\n",
"<!-- 1315738896848*&#45;&gt;1315738896848 -->\n",
"<g id=\"edge4\" class=\"edge\">\n",
"<title>1315738896848*&#45;&gt;1315738896848</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M288.21,-128.5C296,-128.5 305.08,-128.5 314.82,-128.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"314.55,-132 324.55,-128.5 314.55,-125 314.55,-132\"/>\n",
"</g>\n",
"<!-- 1315738897872 -->\n",
"<g id=\"node14\" class=\"node\">\n",
"<title>1315738897872</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"324,-55.5 324,-91.5 542.25,-91.5 542.25,-55.5 324,-55.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"350.38\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x1*w1</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"376.75,-56 376.75,-91.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"418.88\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data &#45;6.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"461,-56 461,-91.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"501.62\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738897872&#45;&gt;1315738898448+ -->\n",
"<g id=\"edge14\" class=\"edge\">\n",
"<title>1315738897872&#45;&gt;1315738898448+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M542.35,-90.68C551.12,-92.07 559.54,-93.4 567.19,-94.62\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"566.59,-98.07 577.02,-96.18 567.69,-91.15 566.59,-98.07\"/>\n",
"</g>\n",
"<!-- 1315738897872*&#45;&gt;1315738897872 -->\n",
"<g id=\"edge5\" class=\"edge\">\n",
"<title>1315738897872*&#45;&gt;1315738897872</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M288.21,-73.5C295.29,-73.5 303.43,-73.5 312.17,-73.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"312.01,-77 322.01,-73.5 312.01,-70 312.01,-77\"/>\n",
"</g>\n",
"</g>\n",
"</svg>\n"
],
"text/plain": [
"<graphviz.graphs.Digraph at 0x132582733d0>"
]
},
"execution_count": 154,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"draw_dot(o)"
]
},
{
"cell_type": "code",
"execution_count": 155,
"id": "7d33e845-75ed-4aec-9310-0f55e866e065",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=3.0)"
]
},
"execution_count": 155,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a = Value(2.0)\n",
"a + 1"
]
},
{
"cell_type": "markdown",
"id": "59924a5f-ae4c-4d0f-b45d-611b32ba6df7",
"metadata": {},
"source": [
"Let's add this QoL improvement."
]
},
{
"cell_type": "code",
"execution_count": 156,
"id": "5ec7a25c-1540-47d3-aefc-eea6cfac8e8a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Value(data=4.0)\n",
"Value(data=4.0)\n"
]
}
],
"source": [
"print(a * 2)\n",
"print(2 * a)"
]
},
{
"cell_type": "code",
"execution_count": 157,
"id": "048d58a9-e70d-45b7-885f-e34317323283",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=54.598150033144236)"
]
},
"execution_count": 157,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a = Value(4.0)\n",
"a.exp()"
]
},
{
"cell_type": "markdown",
"id": "8830493e-47d3-44dd-957f-9c84a9fafa99",
"metadata": {},
"source": [
"a / b\n",
"a * 1/b\n",
"a * b**-1\n",
"\n",
"so, let's implement n**k and have a spl case for division"
]
},
{
"cell_type": "code",
"execution_count": 158,
"id": "c75d090e-6f68-41d8-b874-fd72a5c2303a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=125.0)"
]
},
"execution_count": 158,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"z = Value(5.0)\n",
"z**3"
]
},
{
"cell_type": "code",
"execution_count": 159,
"id": "ff12ee1b-b022-4790-81dd-b88527719e29",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=0.5)"
]
},
"execution_count": 159,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a = Value(4.0)\n",
"b = Value(8.0)\n",
"a / b"
]
},
{
"cell_type": "code",
"execution_count": 160,
"id": "b313cee1-dd94-40bc-a414-ac6475443585",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=-4.0)"
]
},
"execution_count": 160,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a = Value(4.0)\n",
"b = Value(8.0)\n",
"a - b"
]
},
{
"cell_type": "code",
"execution_count": 161,
"id": "7079d013-6e83-4b81-b1d1-d4860d0bf3e7",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
"<!-- Generated by graphviz version 13.1.0 (20250701.0955)\n",
" -->\n",
"<!-- Pages: 1 -->\n",
"<svg width=\"2957pt\" height=\"236pt\"\n",
" viewBox=\"0.00 0.00 2957.00 236.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 232)\">\n",
"<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-232 2953,-232 2953,4 -4,4\"/>\n",
"<!-- 1315738821136 -->\n",
"<g id=\"node1\" class=\"node\">\n",
"<title>1315738821136</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"2214,-108.5 2214,-144.5 2394.75,-144.5 2394.75,-108.5 2214,-108.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2223.88\" y=\"-121.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\"> </text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"2233.75,-109 2233.75,-144.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2273.62\" y=\"-121.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 4.8284</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"2313.5,-109 2313.5,-144.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2354.12\" y=\"-121.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.1464</text>\n",
"</g>\n",
"<!-- 1315738812816* -->\n",
"<g id=\"node28\" class=\"node\">\n",
"<title>1315738812816*</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"2674.5\" cy=\"-153.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2674.5\" y=\"-148.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">*</text>\n",
"</g>\n",
"<!-- 1315738821136&#45;&gt;1315738812816* -->\n",
"<g id=\"edge27\" class=\"edge\">\n",
"<title>1315738821136&#45;&gt;1315738812816*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2394.96,-133.07C2472.25,-138.74 2580.03,-146.64 2636.17,-150.76\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2635.59,-154.23 2645.82,-151.47 2636.1,-147.25 2635.59,-154.23\"/>\n",
"</g>\n",
"<!-- 1315738821136+ -->\n",
"<g id=\"node2\" class=\"node\">\n",
"<title>1315738821136+</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"1929.75\" cy=\"-126.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1929.75\" y=\"-121.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">+</text>\n",
"</g>\n",
"<!-- 1315738821136+&#45;&gt;1315738821136 -->\n",
"<g id=\"edge1\" class=\"edge\">\n",
"<title>1315738821136+&#45;&gt;1315738821136</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1957.25,-126.5C2007.51,-126.5 2119.07,-126.5 2202.03,-126.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2202.02,-130 2212.02,-126.5 2202.02,-123 2202.02,-130\"/>\n",
"</g>\n",
"<!-- 1315738816592 -->\n",
"<g id=\"node3\" class=\"node\">\n",
"<title>1315738816592</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1.5,-165.5 1.5,-201.5 196.5,-201.5 196.5,-165.5 1.5,-165.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"16.25\" y=\"-178.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x1</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"31,-166 31,-201.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"70.88\" y=\"-178.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 2.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"110.75,-166 110.75,-201.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"153.62\" y=\"-178.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad &#45;1.5000</text>\n",
"</g>\n",
"<!-- 1315738816144* -->\n",
"<g id=\"node9\" class=\"node\">\n",
"<title>1315738816144*</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"261\" cy=\"-128.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"261\" y=\"-123.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">*</text>\n",
"</g>\n",
"<!-- 1315738816592&#45;&gt;1315738816144* -->\n",
"<g id=\"edge15\" class=\"edge\">\n",
"<title>1315738816592&#45;&gt;1315738816144*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M172.12,-165.01C180.9,-162.35 189.7,-159.5 198,-156.5 208.09,-152.86 218.82,-148.27 228.47,-143.88\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"229.86,-147.09 237.45,-139.69 226.9,-140.75 229.86,-147.09\"/>\n",
"</g>\n",
"<!-- 1315738816912 -->\n",
"<g id=\"node4\" class=\"node\">\n",
"<title>1315738816912</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"2.25,-55.5 2.25,-91.5 195.75,-91.5 195.75,-55.5 2.25,-55.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"18.5\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">w2</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"34.75,-56 34.75,-91.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"74.62\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 1.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"114.5,-56 114.5,-91.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"155.12\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.0000</text>\n",
"</g>\n",
"<!-- 1315738814800* -->\n",
"<g id=\"node22\" class=\"node\">\n",
"<title>1315738814800*</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"261\" cy=\"-73.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"261\" y=\"-68.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">*</text>\n",
"</g>\n",
"<!-- 1315738816912&#45;&gt;1315738814800* -->\n",
"<g id=\"edge14\" class=\"edge\">\n",
"<title>1315738816912&#45;&gt;1315738814800*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M195.84,-73.5C205.14,-73.5 214.15,-73.5 222.32,-73.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"222.13,-77 232.13,-73.5 222.13,-70 222.13,-77\"/>\n",
"</g>\n",
"<!-- 1315738812496 -->\n",
"<g id=\"node5\" class=\"node\">\n",
"<title>1315738812496</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1992.75,-163.5 1992.75,-199.5 2178,-199.5 2178,-163.5 1992.75,-163.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2002.62\" y=\"-176.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\"> </text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"2012.5,-164 2012.5,-199.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2052.38\" y=\"-176.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 6.8284</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"2092.25,-164 2092.25,-199.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2135.12\" y=\"-176.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad &#45;0.1036</text>\n",
"</g>\n",
"<!-- 1315738827216**&#45;1 -->\n",
"<g id=\"node15\" class=\"node\">\n",
"<title>1315738827216**&#45;1</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"2304.38\" cy=\"-181.5\" rx=\"27.81\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2304.38\" y=\"-176.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">**&#45;1</text>\n",
"</g>\n",
"<!-- 1315738812496&#45;&gt;1315738827216**&#45;1 -->\n",
"<g id=\"edge19\" class=\"edge\">\n",
"<title>1315738812496&#45;&gt;1315738827216**&#45;1</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2178.4,-181.5C2208.64,-181.5 2240.63,-181.5 2264.67,-181.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2264.62,-185 2274.62,-181.5 2264.62,-178 2264.62,-185\"/>\n",
"</g>\n",
"<!-- 1315738812496+ -->\n",
"<g id=\"node6\" class=\"node\">\n",
"<title>1315738812496+</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"1929.75\" cy=\"-181.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1929.75\" y=\"-176.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">+</text>\n",
"</g>\n",
"<!-- 1315738812496+&#45;&gt;1315738812496 -->\n",
"<g id=\"edge2\" class=\"edge\">\n",
"<title>1315738812496+&#45;&gt;1315738812496</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1957.16,-181.5C1964.2,-181.5 1972.25,-181.5 1980.8,-181.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1980.79,-185 1990.79,-181.5 1980.79,-178 1980.79,-185\"/>\n",
"</g>\n",
"<!-- 1315738825808 -->\n",
"<g id=\"node7\" class=\"node\">\n",
"<title>1315738825808</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1681.5,-191.5 1681.5,-227.5 1866.75,-227.5 1866.75,-191.5 1681.5,-191.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1691.38\" y=\"-204.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\"> </text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1701.25,-192 1701.25,-227.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1741.12\" y=\"-204.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 1.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1781,-192 1781,-227.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1823.88\" y=\"-204.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad &#45;0.1036</text>\n",
"</g>\n",
"<!-- 1315738825808&#45;&gt;1315738812496+ -->\n",
"<g id=\"edge24\" class=\"edge\">\n",
"<title>1315738825808&#45;&gt;1315738812496+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1867.15,-192.73C1875.89,-191.13 1884.36,-189.59 1892.08,-188.18\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1892.45,-191.67 1901.66,-186.44 1891.19,-184.79 1892.45,-191.67\"/>\n",
"</g>\n",
"<!-- 1315738816144 -->\n",
"<g id=\"node8\" class=\"node\">\n",
"<title>1315738816144</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"324,-110.5 324,-146.5 542.25,-146.5 542.25,-110.5 324,-110.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"350.38\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x1*w1</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"376.75,-111 376.75,-146.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"418.88\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data &#45;6.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"461,-111 461,-146.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"501.62\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738813264+ -->\n",
"<g id=\"node20\" class=\"node\">\n",
"<title>1315738813264+</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"605.25\" cy=\"-100.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"605.25\" y=\"-95.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">+</text>\n",
"</g>\n",
"<!-- 1315738816144&#45;&gt;1315738813264+ -->\n",
"<g id=\"edge25\" class=\"edge\">\n",
"<title>1315738816144&#45;&gt;1315738813264+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M542.35,-110.69C551.12,-109.24 559.54,-107.86 567.19,-106.6\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"567.72,-110.06 577.02,-104.98 566.58,-103.15 567.72,-110.06\"/>\n",
"</g>\n",
"<!-- 1315738816144*&#45;&gt;1315738816144 -->\n",
"<g id=\"edge3\" class=\"edge\">\n",
"<title>1315738816144*&#45;&gt;1315738816144</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M288.21,-128.5C295.29,-128.5 303.43,-128.5 312.17,-128.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"312.01,-132 322.01,-128.5 312.01,-125 312.01,-132\"/>\n",
"</g>\n",
"<!-- 1315738819984 -->\n",
"<g id=\"node10\" class=\"node\">\n",
"<title>1315738819984</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"3.75,-0.5 3.75,-36.5 194.25,-36.5 194.25,-0.5 3.75,-0.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"18.5\" y=\"-13.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x2</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"33.25,-1 33.25,-36.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"73.12\" y=\"-13.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"113,-1 113,-36.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"153.62\" y=\"-13.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738819984&#45;&gt;1315738814800* -->\n",
"<g id=\"edge26\" class=\"edge\">\n",
"<title>1315738819984&#45;&gt;1315738814800*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M168.91,-36.94C178.74,-39.93 188.67,-43.15 198,-46.5 207.96,-50.07 218.58,-54.47 228.18,-58.68\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"226.54,-61.78 237.1,-62.67 229.4,-55.39 226.54,-61.78\"/>\n",
"</g>\n",
"<!-- 1315738827984 -->\n",
"<g id=\"node11\" class=\"node\">\n",
"<title>1315738827984</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1681.5,-81.5 1681.5,-117.5 1866.75,-117.5 1866.75,-81.5 1681.5,-81.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1691.38\" y=\"-94.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\"> </text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1701.25,-82 1701.25,-117.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1743.38\" y=\"-94.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data &#45;1.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1785.5,-82 1785.5,-117.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1826.12\" y=\"-94.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.1464</text>\n",
"</g>\n",
"<!-- 1315738827984&#45;&gt;1315738821136+ -->\n",
"<g id=\"edge22\" class=\"edge\">\n",
"<title>1315738827984&#45;&gt;1315738821136+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1867.15,-115.67C1875.89,-117.21 1884.36,-118.7 1892.08,-120.05\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1891.2,-123.45 1901.66,-121.74 1892.41,-116.56 1891.2,-123.45\"/>\n",
"</g>\n",
"<!-- 1315738861968 -->\n",
"<g id=\"node12\" class=\"node\">\n",
"<title>1315738861968</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1683.75,-136.5 1683.75,-172.5 1864.5,-172.5 1864.5,-136.5 1683.75,-136.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1693.62\" y=\"-149.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\"> </text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1703.5,-137 1703.5,-172.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1743.38\" y=\"-149.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 5.8284</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1783.25,-137 1783.25,-172.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1823.88\" y=\"-149.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.0429</text>\n",
"</g>\n",
"<!-- 1315738861968&#45;&gt;1315738821136+ -->\n",
"<g id=\"edge16\" class=\"edge\">\n",
"<title>1315738861968&#45;&gt;1315738821136+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1864.93,-138.13C1874.48,-136.39 1883.76,-134.7 1892.14,-133.17\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1892.64,-136.64 1901.85,-131.4 1891.39,-129.75 1892.64,-136.64\"/>\n",
"</g>\n",
"<!-- 1315738861968&#45;&gt;1315738812496+ -->\n",
"<g id=\"edge17\" class=\"edge\">\n",
"<title>1315738861968&#45;&gt;1315738812496+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1864.93,-170.28C1874.48,-171.96 1883.76,-173.59 1892.14,-175.07\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1891.39,-178.49 1901.85,-176.77 1892.61,-171.59 1891.39,-178.49\"/>\n",
"</g>\n",
"<!-- 1315738861968exp -->\n",
"<g id=\"node13\" class=\"node\">\n",
"<title>1315738861968exp</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"1618.5\" cy=\"-154.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1618.5\" y=\"-149.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">exp</text>\n",
"</g>\n",
"<!-- 1315738861968exp&#45;&gt;1315738861968 -->\n",
"<g id=\"edge4\" class=\"edge\">\n",
"<title>1315738861968exp&#45;&gt;1315738861968</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1645.91,-154.5C1653.62,-154.5 1662.54,-154.5 1672.01,-154.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1671.82,-158 1681.82,-154.5 1671.82,-151 1671.82,-158\"/>\n",
"</g>\n",
"<!-- 1315738827216 -->\n",
"<g id=\"node14\" class=\"node\">\n",
"<title>1315738827216</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"2430.75,-161.5 2430.75,-197.5 2611.5,-197.5 2611.5,-161.5 2430.75,-161.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2440.62\" y=\"-174.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\"> </text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"2450.5,-162 2450.5,-197.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2490.38\" y=\"-174.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.1464</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"2530.25,-162 2530.25,-197.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2570.88\" y=\"-174.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 4.8284</text>\n",
"</g>\n",
"<!-- 1315738827216&#45;&gt;1315738812816* -->\n",
"<g id=\"edge23\" class=\"edge\">\n",
"<title>1315738827216&#45;&gt;1315738812816*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2611.93,-164.08C2620.54,-162.6 2628.89,-161.16 2636.53,-159.85\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2637.11,-163.3 2646.37,-158.16 2635.92,-156.4 2637.11,-163.3\"/>\n",
"</g>\n",
"<!-- 1315738827216**&#45;1&#45;&gt;1315738827216 -->\n",
"<g id=\"edge5\" class=\"edge\">\n",
"<title>1315738827216**&#45;1&#45;&gt;1315738827216</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2332.57,-181.25C2354.68,-181.04 2387.33,-180.74 2419.22,-180.44\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2418.96,-183.94 2428.93,-180.35 2418.9,-176.94 2418.96,-183.94\"/>\n",
"</g>\n",
"<!-- 1315738814224 -->\n",
"<g id=\"node16\" class=\"node\">\n",
"<title>1315738814224</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"0,-110.5 0,-146.5 198,-146.5 198,-110.5 0,-110.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"16.25\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">w1</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"32.5,-111 32.5,-146.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"74.62\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data &#45;3.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"116.75,-111 116.75,-146.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"157.38\" y=\"-123.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 1.0000</text>\n",
"</g>\n",
"<!-- 1315738814224&#45;&gt;1315738816144* -->\n",
"<g id=\"edge13\" class=\"edge\">\n",
"<title>1315738814224&#45;&gt;1315738816144*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M198.14,-128.5C206.61,-128.5 214.8,-128.5 222.29,-128.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"222.29,-132 232.29,-128.5 222.29,-125 222.29,-132\"/>\n",
"</g>\n",
"<!-- 1315738820432 -->\n",
"<g id=\"node17\" class=\"node\">\n",
"<title>1315738820432</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1066.5,-164.5 1066.5,-200.5 1247.25,-200.5 1247.25,-164.5 1066.5,-164.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1076.38\" y=\"-177.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\"> </text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1086.25,-165 1086.25,-200.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1126.12\" y=\"-177.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 2.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1166,-165 1166,-200.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1206.62\" y=\"-177.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.2203</text>\n",
"</g>\n",
"<!-- 1315738813840* -->\n",
"<g id=\"node24\" class=\"node\">\n",
"<title>1315738813840*</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"1311.75\" cy=\"-154.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1311.75\" y=\"-149.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">*</text>\n",
"</g>\n",
"<!-- 1315738820432&#45;&gt;1315738813840* -->\n",
"<g id=\"edge21\" class=\"edge\">\n",
"<title>1315738820432&#45;&gt;1315738813840*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1247.69,-166.05C1256.94,-164.35 1265.93,-162.71 1274.08,-161.22\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1274.67,-164.67 1283.87,-159.42 1273.41,-157.78 1274.67,-164.67\"/>\n",
"</g>\n",
"<!-- 1315738828624 -->\n",
"<g id=\"node18\" class=\"node\">\n",
"<title>1315738828624</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"711.75,-137.5 711.75,-173.5 895.5,-173.5 895.5,-137.5 711.75,-137.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"723.12\" y=\"-150.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">b</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"734.5,-138 734.5,-173.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"774.38\" y=\"-150.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 6.8814</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"814.25,-138 814.25,-173.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"854.88\" y=\"-150.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738813392+ -->\n",
"<g id=\"node26\" class=\"node\">\n",
"<title>1315738813392+</title>\n",
"<ellipse fill=\"none\" stroke=\"black\" cx=\"1002\" cy=\"-127.5\" rx=\"27\" ry=\"18\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1002\" y=\"-122.45\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">+</text>\n",
"</g>\n",
"<!-- 1315738828624&#45;&gt;1315738813392+ -->\n",
"<g id=\"edge18\" class=\"edge\">\n",
"<title>1315738828624&#45;&gt;1315738813392+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M895.91,-142.48C919.97,-139.05 944.58,-135.55 963.93,-132.79\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"964.34,-136.26 973.75,-131.39 963.35,-129.33 964.34,-136.26\"/>\n",
"</g>\n",
"<!-- 1315738813264 -->\n",
"<g id=\"node19\" class=\"node\">\n",
"<title>1315738813264</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"668.25,-82.5 668.25,-118.5 939,-118.5 939,-82.5 668.25,-82.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"720.88\" y=\"-95.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x1*w1 + x2*w2</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"773.5,-83 773.5,-118.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"815.62\" y=\"-95.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data &#45;6.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"857.75,-83 857.75,-118.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"898.38\" y=\"-95.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738813264&#45;&gt;1315738813392+ -->\n",
"<g id=\"edge20\" class=\"edge\">\n",
"<title>1315738813264&#45;&gt;1315738813392+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M939.14,-118.99C947.95,-120.21 956.31,-121.36 963.87,-122.4\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"963.16,-125.83 973.55,-123.73 964.12,-118.9 963.16,-125.83\"/>\n",
"</g>\n",
"<!-- 1315738813264+&#45;&gt;1315738813264 -->\n",
"<g id=\"edge6\" class=\"edge\">\n",
"<title>1315738813264+&#45;&gt;1315738813264</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M632.73,-100.5C639.73,-100.5 647.79,-100.5 656.52,-100.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"656.39,-104 666.39,-100.5 656.39,-97 656.39,-104\"/>\n",
"</g>\n",
"<!-- 1315738814800 -->\n",
"<g id=\"node21\" class=\"node\">\n",
"<title>1315738814800</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"326.25,-55.5 326.25,-91.5 540,-91.5 540,-55.5 326.25,-55.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"352.62\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">x2*w2</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"379,-56 379,-91.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"418.88\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.0000</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"458.75,-56 458.75,-91.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"499.38\" y=\"-68.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738814800&#45;&gt;1315738813264+ -->\n",
"<g id=\"edge12\" class=\"edge\">\n",
"<title>1315738814800&#45;&gt;1315738813264+</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M540.42,-90.37C549.89,-91.87 559,-93.32 567.21,-94.62\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"566.63,-98.07 577.05,-96.18 567.72,-91.16 566.63,-98.07\"/>\n",
"</g>\n",
"<!-- 1315738814800*&#45;&gt;1315738814800 -->\n",
"<g id=\"edge7\" class=\"edge\">\n",
"<title>1315738814800*&#45;&gt;1315738814800</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M288.21,-73.5C296,-73.5 305.08,-73.5 314.82,-73.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"314.55,-77 324.55,-73.5 314.55,-70 314.55,-77\"/>\n",
"</g>\n",
"<!-- 1315738813840 -->\n",
"<g id=\"node23\" class=\"node\">\n",
"<title>1315738813840</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1374.75,-136.5 1374.75,-172.5 1555.5,-172.5 1555.5,-136.5 1374.75,-136.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1384.62\" y=\"-149.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\"> </text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1394.5,-137 1394.5,-172.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1434.38\" y=\"-149.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 1.7627</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1474.25,-137 1474.25,-172.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1514.88\" y=\"-149.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.2500</text>\n",
"</g>\n",
"<!-- 1315738813840&#45;&gt;1315738861968exp -->\n",
"<g id=\"edge11\" class=\"edge\">\n",
"<title>1315738813840&#45;&gt;1315738861968exp</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1555.93,-154.5C1564.27,-154.5 1572.37,-154.5 1579.81,-154.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1579.75,-158 1589.75,-154.5 1579.75,-151 1579.75,-158\"/>\n",
"</g>\n",
"<!-- 1315738813840*&#45;&gt;1315738813840 -->\n",
"<g id=\"edge8\" class=\"edge\">\n",
"<title>1315738813840*&#45;&gt;1315738813840</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1339.12,-154.5C1346.26,-154.5 1354.45,-154.5 1363.14,-154.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1362.86,-158 1372.86,-154.5 1362.86,-151 1362.86,-158\"/>\n",
"</g>\n",
"<!-- 1315738813392 -->\n",
"<g id=\"node25\" class=\"node\">\n",
"<title>1315738813392</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"1065,-109.5 1065,-145.5 1248.75,-145.5 1248.75,-109.5 1065,-109.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1076.38\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">n</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1087.75,-110 1087.75,-145.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1127.62\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.8814</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"1167.5,-110 1167.5,-145.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"1208.12\" y=\"-122.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 0.5000</text>\n",
"</g>\n",
"<!-- 1315738813392&#45;&gt;1315738813840* -->\n",
"<g id=\"edge28\" class=\"edge\">\n",
"<title>1315738813392&#45;&gt;1315738813840*</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1249.01,-143.6C1257.84,-145.16 1266.4,-146.67 1274.19,-148.04\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1273.42,-151.46 1283.88,-149.75 1274.64,-144.57 1273.42,-151.46\"/>\n",
"</g>\n",
"<!-- 1315738813392+&#45;&gt;1315738813392 -->\n",
"<g id=\"edge9\" class=\"edge\">\n",
"<title>1315738813392+&#45;&gt;1315738813392</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M1029.28,-127.5C1036.42,-127.5 1044.61,-127.5 1053.32,-127.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"1053.06,-131 1063.06,-127.5 1053.06,-124 1053.06,-131\"/>\n",
"</g>\n",
"<!-- 1315738812816 -->\n",
"<g id=\"node27\" class=\"node\">\n",
"<title>1315738812816</title>\n",
"<polygon fill=\"none\" stroke=\"black\" points=\"2737.5,-135.5 2737.5,-171.5 2949,-171.5 2949,-135.5 2737.5,-135.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2762.75\" y=\"-148.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">output</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"2788,-136 2788,-171.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2827.88\" y=\"-148.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">data 0.7071</text>\n",
"<polyline fill=\"none\" stroke=\"black\" points=\"2867.75,-136 2867.75,-171.5\"/>\n",
"<text xml:space=\"preserve\" text-anchor=\"middle\" x=\"2908.38\" y=\"-148.7\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">grad 1.0000</text>\n",
"</g>\n",
"<!-- 1315738812816*&#45;&gt;1315738812816 -->\n",
"<g id=\"edge10\" class=\"edge\">\n",
"<title>1315738812816*&#45;&gt;1315738812816</title>\n",
"<path fill=\"none\" stroke=\"black\" d=\"M2701.92,-153.5C2709.02,-153.5 2717.18,-153.5 2725.92,-153.5\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"2725.74,-157 2735.74,-153.5 2725.74,-150 2725.74,-157\"/>\n",
"</g>\n",
"</g>\n",
"</svg>\n"
],
"text/plain": [
"<graphviz.graphs.Digraph at 0x132582502d0>"
]
},
"execution_count": 161,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# inputs x1,x2\n",
"x1 = Value(2.0, label='x1')\n",
"x2 = Value(0.0, label='x2')\n",
"# weights w1,w2\n",
"w1 = Value(-3.0, label='w1')\n",
"w2 = Value(1.0, label='w2')\n",
"# bias of the neuron\n",
"b = Value(6.8813735870195432, label='b')\n",
"# x1*w1 + x2*w2 + b\n",
"x1w1 = x1*w1; x1w1.label = 'x1*w1'\n",
"x2w2 = x2*w2; x2w2.label = 'x2*w2'\n",
"x1w1x2w2 = x1w1 + x2w2; x1w1x2w2.label = 'x1*w1 + x2*w2'\n",
"n = x1w1x2w2 + b; n.label = 'n'\n",
"# Let's define tanh using exp and divide and subtract\n",
"e = (2*n).exp()\n",
"o = (e - 1) / (e + 1) \n",
"#---\n",
"o.label = 'output'\n",
"o.backward()\n",
"draw_dot(o)"
]
},
{
"cell_type": "markdown",
"id": "c817b8f7-a9e5-4193-a759-27973d83868d",
"metadata": {},
"source": [
"Now let's look at the same thing in pytorch"
]
},
{
"cell_type": "code",
"execution_count": 162,
"id": "961afc05-1958-41e0-b434-40d8b0a148e3",
"metadata": {},
"outputs": [],
"source": [
"import torch"
]
},
{
"cell_type": "code",
"execution_count": 163,
"id": "67c41ab6-8b5d-4908-a868-0d63c196ae5f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.7071066904050358\n",
"---\n",
"x2 0.5000001283844369\n",
"w2 0.0\n",
"x1 -1.5000003851533106\n",
"w1 1.0000002567688737\n"
]
}
],
"source": [
"x1 = torch.Tensor([2.0]).double() ; x1.requires_grad = True # This is false by default because no one needs to see gradients on the input layer\n",
"x2 = torch.Tensor([0.0]).double() ; x2.requires_grad = True\n",
"w1 = torch.Tensor([-3.0]).double() ; w1.requires_grad = True\n",
"w2 = torch.Tensor([1.0]).double() ; w2.requires_grad = True\n",
"b = torch.Tensor([6.8813735870195432]).double() ; b.requires_grad = True\n",
"n = x1*w1 + x2*w2 + b\n",
"o = torch.tanh(n)\n",
"\n",
"print(o.data.item())\n",
"o.backward()\n",
"\n",
"print('---')\n",
"print('x2', x2.grad.item())\n",
"print('w2', w2.grad.item())\n",
"print('x1', x1.grad.item())\n",
"print('w1', w1.grad.item())"
]
},
{
"cell_type": "markdown",
"id": "43f61380-db69-4b53-9a87-e6121fe2eae1",
"metadata": {},
"source": [
"Let's now build the a neural net library (multi-layer perceptron) in mircograd"
]
},
{
"cell_type": "code",
"execution_count": 175,
"id": "9399d558-a3c6-44ae-8b3c-a995d750f20e",
"metadata": {},
"outputs": [],
"source": [
"import random\n",
"class Neuron:\n",
"\n",
" def __init__(self, nin): # nin is number of inputs\n",
" self.w = [Value(random.uniform(-1,1)) for _ in range(nin)]\n",
" self.b = Value(random.uniform(-1,1))\n",
"\n",
" def __call__(self, x):\n",
" # w * x + b\n",
" act = sum((wi * xi for wi, xi in zip(self.w, x)), self.b)\n",
" out = act.tanh()\n",
" return out\n",
"\n",
" def parameters(self):\n",
" return self.w + [self.b]\n",
"\n",
"class Layer:\n",
"\n",
" def __init__(self, nin, nout): # nin is the number of inputs on each neuron, nout is the number of neurons in the layer\n",
" self.neurons=[Neuron(nin) for _ in range(nout)]\n",
"\n",
" def __call__(self, x):\n",
" outs = [n(x) for n in self.neurons]\n",
" return outs[0] if len(outs) == 1 else outs # QoL \n",
"\n",
" def parameters(self):\n",
" return [p for neuron in self.neurons for p in neuron.parameters()]\n",
" # params = []\n",
" # for neuron in self.neurons:\n",
" # ps = neurons.parameters()\n",
" # params.extend(ps)\n",
" # return params\n",
"\n",
"class MLP:\n",
"\n",
" def __init__(self, nin, nouts): # nout is the list of the numbers of neurons in each layer\n",
" sz = [nin] + nouts\n",
" self.layers = [Layer(sz[i], sz[i+1]) for i in range(len(nouts))]\n",
"\n",
" def __call__(self, x):\n",
" for layer in self.layers:\n",
" x = layer(x)\n",
" return x\n",
"\n",
" def parameters(self):\n",
" return [p for layer in self.layers for p in layer.parameters()]\n",
"\n",
"# x = [2.0, 3.0,]\n",
"# n = Layer(2, 3) # three 2-dimensional neutrons in this Layer\n",
"# n(x)"
]
},
{
"attachments": {
"ee0672be-bf08-4422-b9a4-24bd40eea517.jpg": {
"image/jpeg": "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"
}
},
"cell_type": "markdown",
"id": "b7f37088-3ee3-466b-974b-bdf7a1df0d25",
"metadata": {},
"source": [
"![images.jpg](attachment:ee0672be-bf08-4422-b9a4-24bd40eea517.jpg)\n",
"\n",
"Now let's define a layer and a MLP (multi-layer perceptron)"
]
},
{
"cell_type": "markdown",
"id": "7e885e5c-3de4-4d81-89c5-02423da45778",
"metadata": {},
"source": [
"Let's train a NN! (finally!) This is a simple binary classifer NN"
]
},
{
"cell_type": "code",
"execution_count": 240,
"id": "58ab19a9-8f0f-41a5-b270-95f31a1127e4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=0.5295324547878887)"
]
},
"execution_count": 240,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = [2.0, 3.0, -1.0]\n",
"n = MLP(3, [4, 4, 1]) # implementing the example image\n",
"n(x)"
]
},
{
"cell_type": "code",
"execution_count": 184,
"id": "78f114fb-4736-458e-9eb0-3e03405dc63c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"41"
]
},
"execution_count": 184,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(n.parameters())"
]
},
{
"cell_type": "code",
"execution_count": 177,
"id": "e095ac0b-5aa5-4224-a2d7-67a5af1c9742",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Value(data=0.07700064719309661),\n",
" Value(data=0.6874724332729629),\n",
" Value(data=-0.7191542943909137),\n",
" Value(data=-0.12016611563222777)]"
]
},
"execution_count": 177,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# when we feed the first inputs, we should get the first output (1.0) and so on.\n",
"\n",
"xs = [\n",
" [2.0, 3.0, -1.0],\n",
" [3.0, -1.0, 0.5],\n",
" [0.5, 1.0, 1.0],\n",
" [1.0, 1.0, -1.0],\n",
"]\n",
"ys = [1.0, -1.0, -1.0, 1.0] # desired targets\n",
"ypred = [n(x) for x in xs]\n",
"ypred"
]
},
{
"cell_type": "markdown",
"id": "c9676e56-fff4-4d14-8120-955a9a9622ee",
"metadata": {},
"source": [
"We want `ypred` to go as close to as `ys`. We do this (and in deep learning) by calculating a single number for perfomance called the *loss*. We are going to implement a mean-square loss"
]
},
{
"cell_type": "code",
"execution_count": 178,
"id": "584c98fa-5fef-4310-88b1-3638b41821e8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=5.033137455307795)"
]
},
"execution_count": 178,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"loss = sum((yout - ygt)**2 for ygt, yout in zip(ys, ypred))\n",
"loss"
]
},
{
"cell_type": "code",
"execution_count": 179,
"id": "7e1b37ad-e268-4cbb-8f98-fa7e5daf44c8",
"metadata": {},
"outputs": [],
"source": [
"loss.backward()"
]
},
{
"cell_type": "code",
"execution_count": 180,
"id": "4768716a-2ff9-4e50-b7c1-fff9691b2ef5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.7368026977666375"
]
},
"execution_count": 180,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n.layers[0].neurons[0].w[0].grad # this is now NOT zero!"
]
},
{
"cell_type": "code",
"execution_count": 185,
"id": "1eb237df-ca08-4e5f-b22f-1c6d4d10341e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"-0.32973208920024066"
]
},
"execution_count": 185,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"n.layers[0].neurons[0].w[0].data"
]
},
{
"cell_type": "code",
"execution_count": 187,
"id": "fcfcb22d-b973-45b5-aee4-78d7d22e6d5b",
"metadata": {},
"outputs": [],
"source": [
"for p in n.parameters():\n",
" p.data += -0.01 * p.grad # negative sign because we want to minimise the loss. We think of grad as a vector pointing towards increased loss. This is gradient descent.\n",
" # https://en.wikipedia.org/wiki/Gradient_descent#An_analogy_for_understanding_gradient_descent"
]
},
{
"cell_type": "markdown",
"id": "033750e6-d9ca-4ce7-9582-e5a2841f953a",
"metadata": {},
"source": [
"Let's look at the new loss (It has decreased)"
]
},
{
"cell_type": "code",
"execution_count": 189,
"id": "a78061fa-fca6-4a04-9a15-ebe3908dc021",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=3.7015356808242585)"
]
},
"execution_count": 189,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ypred = [n(x) for x in xs]\n",
"loss = sum((yout - ygt)**2 for ygt, yout in zip(ys, ypred))\n",
"loss"
]
},
{
"cell_type": "markdown",
"id": "5922cb79-0965-4f6b-b6c4-e30253cc57cb",
"metadata": {},
"source": [
"Let backprop this loss and update the weights"
]
},
{
"cell_type": "code",
"execution_count": 190,
"id": "3bd72e52-5dec-4e1b-84d5-b7435f90d19f",
"metadata": {},
"outputs": [],
"source": [
"loss.backward()"
]
},
{
"cell_type": "code",
"execution_count": 191,
"id": "3dd28be9-dc33-415b-bf2c-3da6c8d59160",
"metadata": {},
"outputs": [],
"source": [
"for p in n.parameters():\n",
" p.data += -0.01 * p.grad # negative sign because we want to minimise the loss. We think of grad as a vector pointing towards increased loss. This is gradient descent.\n",
" # https://en.wikipedia.org/wiki/Gradient_descent#An_analogy_for_understanding_gradient_descent"
]
},
{
"cell_type": "markdown",
"id": "c2b0b435-a7c0-4ab2-b907-55709bfb7342",
"metadata": {},
"source": [
"Now let's find the new loss"
]
},
{
"cell_type": "code",
"execution_count": 192,
"id": "8cc95aa5-ecb4-4a24-b631-1daf8e9f7b78",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Value(data=3.193172494954373)"
]
},
"execution_count": 192,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ypred = [n(x) for x in xs]\n",
"loss = sum((yout - ygt)**2 for ygt, yout in zip(ys, ypred))\n",
"loss"
]
},
{
"cell_type": "markdown",
"id": "3faa653d-3787-4ab3-9abc-ea8df46153a1",
"metadata": {},
"source": [
"So the flow is forward pass -> backward pass -> update"
]
},
{
"cell_type": "code",
"execution_count": 241,
"id": "f530b51e-9e4b-47b2-9fb0-335c48c3c424",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Step # 0 6.063052689312497\n",
"Step # 1 3.4913909241492496\n",
"Step # 2 1.2084297159180784\n",
"Step # 3 0.4656671369410741\n",
"Step # 4 0.24785984660117516\n",
"Step # 5 0.17205836536367008\n",
"Step # 6 0.13140359668124182\n",
"Step # 7 0.10607370364195885\n",
"Step # 8 0.08881662744244229\n",
"Step # 9 0.07632247962333527\n",
"Step # 10 0.06686857143197884\n",
"Step # 11 0.05947134159212191\n",
"Step # 12 0.05352900687658706\n",
"Step # 13 0.04865302737738714\n",
"Step # 14 0.04458150502268218\n",
"Step # 15 0.04113156601356174\n",
"Step # 16 0.03817169980897338\n",
"Step # 17 0.03560494239910917\n",
"Step # 18 0.0333582524439753\n",
"Step # 19 0.031375575848589486\n",
"Step # 20 0.02961318784557092\n",
"Step # 21 0.028036486100278167\n",
"Step # 22 0.026617733994873168\n",
"Step # 23 0.025334441397667242\n",
"Step # 24 0.024168182466436462\n",
"Step # 25 0.023103718921689623\n",
"Step # 26 0.022128340591535754\n",
"Step # 27 0.021231362959825167\n",
"Step # 28 0.020403739813356792\n",
"Step # 29 0.01963776138740571\n",
"Step # 30 0.0189268167944545\n",
"Step # 31 0.01826520532701045\n",
"Step # 32 0.017647985303954276\n",
"Step # 33 0.017070852033527407\n",
"Step # 34 0.016530038559047344\n",
"Step # 35 0.016022234379549593\n",
"Step # 36 0.015544518462321941\n",
"Step # 37 0.015094303701612632\n",
"Step # 38 0.014669290606996854\n",
"Step # 39 0.014267428481870884\n",
"Step # 40 0.01388688271714819\n",
"Step # 41 0.013526007106099663\n",
"Step # 42 0.013183320304248127\n",
"Step # 43 0.01285748572855482\n",
"Step # 44 0.012547294324111991\n",
"Step # 45 0.01225164973260155\n",
"Step # 46 0.011969555481211223\n",
"Step # 47 0.011700103878302559\n",
"Step # 48 0.011442466356546074\n",
"Step # 49 0.011195885048268026\n",
"Step # 50 0.010959665413551208\n",
"Step # 51 0.01073316977087405\n",
"Step # 52 0.010515811604061303\n",
"Step # 53 0.010307050539087767\n",
"Step # 54 0.01010638790062819\n",
"Step # 55 0.009913362771829845\n",
"Step # 56 0.009727548492106068\n",
"Step # 57 0.009548549537221928\n",
"Step # 58 0.009375998733897512\n",
"Step # 59 0.009209554767852004\n",
"Step # 60 0.00904889994987455\n",
"Step # 61 0.008893738209305405\n",
"Step # 62 0.008743793288391685\n",
"Step # 63 0.008598807114459579\n",
"Step # 64 0.008458538329820275\n",
"Step # 65 0.00832276096187455\n",
"Step # 66 0.008191263218074911\n",
"Step # 67 0.00806384639228904\n",
"Step # 68 0.007940323870742451\n",
"Step # 69 0.007820520227127632\n",
"Step # 70 0.007704270397693438\n",
"Step # 71 0.007591418928192805\n",
"Step # 72 0.007481819285496838\n",
"Step # 73 0.007375333227492005\n",
"Step # 74 0.0072718302255883925\n",
"Step # 75 0.007171186934788122\n",
"Step # 76 0.0070732867068092455\n",
"Step # 77 0.006978019142241778\n",
"Step # 78 0.0068852796781358255\n",
"Step # 79 0.006794969207796124\n",
"Step # 80 0.00670699372988889\n",
"Step # 81 0.006621264024259348\n",
"Step # 82 0.006537695352119681\n",
"Step # 83 0.006456207178497548\n",
"Step # 84 0.006376722915042138\n",
"Step # 85 0.006299169681467748\n",
"Step # 86 0.0062234780840792975\n",
"Step # 87 0.006149582009970493\n",
"Step # 88 0.006077418435616704\n",
"Step # 89 0.0060069272487023664\n",
"Step # 90 0.005938051082127848\n",
"Step # 91 0.005870735159236637\n",
"Step # 92 0.0058049271493877865\n",
"Step # 93 0.005740577033077032\n",
"Step # 94 0.005677636975877802\n",
"Step # 95 0.005616061210537649\n",
"Step # 96 0.005555805926620974\n",
"Step # 97 0.005496829167141412\n",
"Step # 98 0.0054390907316724645\n",
"Step # 99 0.005382552085468513\n",
"Step # 100 0.005327176274165607\n",
"Step # 101 0.005272927843666831\n",
"Step # 102 0.005219772764848314\n",
"Step # 103 0.005167678362751362\n",
"Step # 104 0.005116613249951687\n",
"Step # 105 0.005066547263821784\n",
"Step # 106 0.005017451407423288\n",
"Step # 107 0.00496929779378706\n",
"Step # 108 0.004922059593356691\n",
"Step # 109 0.004875710984387967\n",
"Step # 110 0.00483022710611221\n",
"Step # 111 0.004785584014485676\n",
"Step # 112 0.004741758640360024\n",
"Step # 113 0.00469872874992065\n",
"Step # 114 0.004656472907251062\n",
"Step # 115 0.004614970438891062\n",
"Step # 116 0.004574201400266073\n",
"Step # 117 0.004534146543873533\n",
"Step # 118 0.004494787289119742\n",
"Step # 119 0.004456105693708702\n",
"Step # 120 0.004418084426490032\n",
"Step # 121 0.004380706741680469\n",
"Step # 122 0.004343956454378153\n",
"Step # 123 0.004307817917295212\n",
"Step # 124 0.0042722759986379205\n",
"Step # 125 0.004237316061069736\n",
"Step # 126 0.004202923941695134\n",
"Step # 127 0.00416908593300756\n",
"Step # 128 0.0041357887647473605\n",
"Step # 129 0.004103019586619787\n",
"Step # 130 0.004070765951825515\n",
"Step # 131 0.0040390158013597155\n",
"Step # 132 0.00400775744903826\n",
"Step # 133 0.003976979567211711\n",
"Step # 134 0.003946671173131104\n",
"Step # 135 0.003916821615930658\n",
"Step # 136 0.0038874205641950834\n",
"Step # 137 0.003858457994081638\n",
"Step # 138 0.0038299241779675714\n",
"Step # 139 0.0038018096735966287\n",
"Step # 140 0.0037741053136988835\n",
"Step # 141 0.003746802196060106\n",
"Step # 142 0.003719891674018089\n",
"Step # 143 0.0036933653473650166\n",
"Step # 144 0.003667215053634969\n",
"Step # 145 0.003641432859758701\n",
"Step # 146 0.00361601105406707\n",
"Step # 147 0.0035909421386263116\n",
"Step # 148 0.003566218821889728\n",
"Step # 149 0.0035418340116498666\n",
"Step # 150 0.003517780808277683\n",
"Step # 151 0.003494052498234713\n",
"Step # 152 0.0034706425478457192\n",
"Step # 153 0.0034475445973193913\n",
"Step # 154 0.003424752455006112\n",
"Step # 155 0.0034022600918815187\n",
"Step # 156 0.0033800616362457997\n",
"Step # 157 0.0033581513686285923\n",
"Step # 158 0.003336523716890975\n",
"Step # 159 0.003315173251514751\n",
"Step # 160 0.0032940946810716405\n",
"Step # 161 0.003273282847863682\n",
"Step # 162 0.0032527327237279312\n",
"Step # 163 0.0032324394059978774\n",
"Step # 164 0.0032123981136149104\n",
"Step # 165 0.003192604183383576\n",
"Step # 166 0.0031730530663640144\n",
"Step # 167 0.0031537403243963964\n",
"Step # 168 0.003134661626750936\n",
"Step # 169 0.003115812746899099\n",
"Step # 170 0.003097189559400266\n",
"Step # 171 0.003078788036899308\n",
"Step # 172 0.0030606042472306025\n",
"Step # 173 0.003042634350623824\n",
"Step # 174 0.0030248745970078003\n",
"Step # 175 0.0030073213234078264\n",
"Step # 176 0.0029899709514333668\n",
"Step # 177 0.0029728199848519754\n",
"Step # 178 0.00295586500724621\n",
"Step # 179 0.002939102679750448\n",
"Step # 180 0.002922529738863839\n",
"Step # 181 0.002906142994337289\n",
"Step # 182 0.0028899393271306856\n",
"Step # 183 0.002873915687438391\n",
"Step # 184 0.0028580690927797886\n",
"Step # 185 0.002842396626152884\n",
"Step # 186 0.002826895434248074\n",
"Step # 187 0.0028115627257202106\n",
"Step # 188 0.0027963957695165496\n",
"Step # 189 0.0027813918932584844\n",
"Step # 190 0.0027665484816751626\n",
"Step # 191 0.002751862975086844\n",
"Step # 192 0.002737332867936595\n",
"Step # 193 0.002722955707367939\n",
"Step # 194 0.0027087290918473375\n",
"Step # 195 0.002694650669829513\n",
"Step # 196 0.002680718138464186\n",
"Step # 197 0.0026669292423429185\n",
"Step # 198 0.002653281772284076\n",
"Step # 199 0.0026397735641553854\n",
"Step # 200 0.0026264024977318504\n",
"Step # 201 0.0026131664955885165\n",
"Step # 202 0.0026000635220264513\n",
"Step # 203 0.0025870915820308447\n",
"Step # 204 0.0025742487202602853\n",
"Step # 205 0.002561533020065842\n",
"Step # 206 0.0025489426025392856\n",
"Step # 207 0.002536475625589039\n",
"Step # 208 0.002524130283043393\n",
"Step # 209 0.0025119048037794776\n",
"Step # 210 0.0024997974508777603\n",
"Step # 211 0.0024878065208007068\n",
"Step # 212 0.002475930342594991\n",
"Step # 213 0.0024641672771165517\n",
"Step # 214 0.0024525157162775986\n",
"Step # 215 0.002440974082314912\n",
"Step # 216 0.0024295408270786777\n",
"Step # 217 0.002418214431341317\n",
"Step # 218 0.0024069934041255226\n",
"Step # 219 0.002395876282050965\n",
"Step # 220 0.0023848616286989387\n",
"Step # 221 0.0023739480339946685\n",
"Step # 222 0.0023631341136063117\n",
"Step # 223 0.002352418508360469\n",
"Step # 224 0.002341799883673461\n",
"Step # 225 0.0023312769289979738\n",
"Step # 226 0.002320848357284638\n",
"Step # 227 0.0023105129044579276\n",
"Step # 228 0.002300269328906075\n",
"Step # 229 0.002290116410984435\n",
"Step # 230 0.0022800529525321095\n",
"Step # 231 0.002270077776401008\n",
"Step # 232 0.00226018972599765\n",
"Step # 233 0.0022503876648364727\n",
"Step # 234 0.002240670476104961\n",
"Step # 235 0.0022310370622400065\n",
"Step # 236 0.0022214863445151186\n",
"Step # 237 0.0022120172626381566\n",
"Step # 238 0.0022026287743595026\n",
"Step # 239 0.0021933198550899\n",
"Step # 240 0.0021840894975282666\n",
"Step # 241 0.0021749367112986412\n",
"Step # 242 0.0021658605225963992\n",
"Step # 243 0.0021568599738431664\n",
"Step # 244 0.002147934123350419\n",
"Step # 245 0.0021390820449913844\n",
"Step # 246 0.00213030282788102\n",
"Step # 247 0.0021215955760638706\n",
"Step # 248 0.0021129594082095427\n",
"Step # 249 0.002104393457315599\n",
"Step # 250 0.0020958968704177764\n",
"Step # 251 0.0020874688083069564\n",
"Step # 252 0.002079108445253255\n",
"Step # 253 0.0020708149687364515\n",
"Step # 254 0.002062587579183047\n",
"Step # 255 0.002054425489709562\n",
"Step # 256 0.0020463279258717145\n",
"Step # 257 0.0020382941254198286\n",
"Step # 258 0.0020303233380597743\n",
"Step # 259 0.00202241482521953\n",
"Step # 260 0.0020145678598212833\n",
"Step # 261 0.002006781726058751\n",
"Step # 262 0.001999055719179698\n",
"Step # 263 0.00199138914527338\n",
"Step # 264 0.001983781321063024\n",
"Step # 265 0.0019762315737029182\n",
"Step # 266 0.001968739240580211\n",
"Step # 267 0.00196130366912113\n",
"Step # 268 0.0019539242166017054\n",
"Step # 269 0.0019466002499626315\n",
"Step # 270 0.0019393311456283979\n",
"Step # 271 0.0019321162893303435\n",
"Step # 272 0.001924955075933836\n",
"Step # 273 0.0019178469092690424\n",
"Step # 274 0.001910791201965695\n",
"Step # 275 0.001903787375291321\n",
"Step # 276 0.0018968348589930967\n",
"Step # 277 0.0018899330911432088\n",
"Step # 278 0.0018830815179874684\n",
"Step # 279 0.0018762795937972963\n",
"Step # 280 0.001869526780724939\n",
"Step # 281 0.0018628225486617025\n",
"Step # 282 0.0018561663750993143\n",
"Step # 283 0.00184955774499431\n",
"Step # 284 0.0018429961506351163\n",
"Step # 285 0.0018364810915121475\n",
"Step # 286 0.0018300120741906545\n",
"Step # 287 0.0018235886121860377\n",
"Step # 288 0.0018172102258421216\n",
"Step # 289 0.001810876442211629\n",
"Step # 290 0.001804586794939505\n",
"Step # 291 0.00179834082414832\n",
"Step # 292 0.001792138076326316\n",
"Step # 293 0.001785978104217711\n",
"Step # 294 0.0017798604667150894\n",
"Step # 295 0.0017737847287542753\n",
"Step # 296 0.0017677504612111706\n",
"Step # 297 0.001761757240800724\n",
"Step # 298 0.0017558046499780197\n",
"Step # 299 0.0017498922768413362\n",
"Step # 300 0.0017440197150370828\n",
"Step # 301 0.001738186563666814\n",
"Step # 302 0.0017323924271959753\n",
"Step # 303 0.0017266369153644931\n",
"Step # 304 0.0017209196430992434\n",
"Step # 305 0.0017152402304281022\n",
"Step # 306 0.0017095983023958218\n",
"Step # 307 0.0017039934889815072\n",
"Step # 308 0.0016984254250177687\n",
"Step # 309 0.0016928937501113808\n",
"Step # 310 0.0016873981085655373\n",
"Step # 311 0.001681938149303642\n",
"Step # 312 0.0016765135257945742\n",
"Step # 313 0.0016711238959792873\n",
"Step # 314 0.0016657689221990137\n",
"Step # 315 0.0016604482711246983\n",
"Step # 316 0.0016551616136878556\n",
"Step # 317 0.0016499086250127352\n",
"Step # 318 0.0016446889843497237\n",
"Step # 319 0.0016395023750101637\n",
"Step # 320 0.0016343484843021818\n",
"Step # 321 0.001629227003467954\n",
"Step # 322 0.0016241376276219487\n",
"Step # 323 0.001619080055690501\n",
"Step # 324 0.001614053990352399\n",
"Step # 325 0.001609059137980624\n",
"Step # 326 0.0016040952085851895\n",
"Step # 327 0.001599161915756965\n",
"Step # 328 0.0015942589766126342\n",
"Step # 329 0.001589386111740561\n",
"Step # 330 0.0015845430451477908\n",
"Step # 331 0.0015797295042078328\n",
"Step # 332 0.0015749452196096151\n",
"Step # 333 0.0015701899253071257\n",
"Step # 334 0.0015654633584701642\n",
"Step # 335 0.0015607652594359178\n",
"Step # 336 0.0015560953716613338\n",
"Step # 337 0.0015514534416765074\n",
"Step # 338 0.0015468392190387274\n",
"Step # 339 0.0015422524562874749\n",
"Step # 340 0.0015376929089001685\n",
"Step # 341 0.0015331603352486678\n",
"Step # 342 0.0015286544965566408\n",
"Step # 343 0.0015241751568575948\n",
"Step # 344 0.0015197220829536045\n",
"Step # 345 0.0015152950443749508\n",
"Step # 346 0.0015108938133403076\n",
"Step # 347 0.001506518164717592\n",
"Step # 348 0.0015021678759856764\n",
"Step # 349 0.001497842727196576\n",
"Step # 350 0.0014935425009383841\n",
"Step # 351 0.0014892669822988897\n",
"Step # 352 0.0014850159588296608\n",
"Step # 353 0.0014807892205109291\n",
"Step # 354 0.0014765865597169416\n",
"Step # 355 0.0014724077711819657\n",
"Step # 356 0.0014682526519668873\n",
"Step # 357 0.0014641210014262843\n",
"Step # 358 0.0014600126211761822\n",
"Step # 359 0.0014559273150622164\n",
"Step # 360 0.0014518648891284985\n",
"Step # 361 0.0014478251515867807\n",
"Step # 362 0.0014438079127864097\n",
"Step # 363 0.0014398129851845107\n",
"Step # 364 0.0014358401833168212\n",
"Step # 365 0.0014318893237690515\n",
"Step # 366 0.001427960225148534\n",
"Step # 367 0.0014240527080565143\n",
"Step # 368 0.0014201665950608262\n",
"Step # 369 0.001416301710669022\n",
"Step # 370 0.001412457881301926\n",
"Step # 371 0.0014086349352676292\n",
"Step # 372 0.001404832702735981\n",
"Step # 373 0.0014010510157132982\n",
"Step # 374 0.001397289708017771\n",
"Step # 375 0.0013935486152549387\n",
"Step # 376 0.0013898275747938728\n",
"Step # 377 0.0013861264257434972\n",
"Step # 378 0.0013824450089294398\n",
"Step # 379 0.0013787831668711824\n",
"Step # 380 0.0013751407437595923\n",
"Step # 381 0.0013715175854347953\n",
"Step # 382 0.001367913539364437\n",
"Step # 383 0.0013643284546222562\n",
"Step # 384 0.0013607621818670114\n",
"Step # 385 0.0013572145733217174\n",
"Step # 386 0.0013536854827532383\n",
"Step # 387 0.0013501747654521238\n",
"Step # 388 0.0013466822782129332\n",
"Step # 389 0.0013432078793146056\n",
"Step # 390 0.0013397514285014057\n",
"Step # 391 0.0013363127869639735\n",
"Step # 392 0.001332891817320703\n",
"Step # 393 0.0013294883835995312\n",
"Step # 394 0.0013261023512197853\n",
"Step # 395 0.0013227335869745427\n",
"Step # 396 0.0013193819590130663\n",
"Step # 397 0.001316047336823662\n",
"Step # 398 0.0013127295912166706\n",
"Step # 399 0.001309428594307766\n",
"Step # 400 0.001306144219501601\n",
"Step # 401 0.0013028763414754797\n",
"Step # 402 0.0012996248361635194\n",
"Step # 403 0.0012963895807408523\n",
"Step # 404 0.0012931704536082113\n",
"Step # 405 0.0012899673343766713\n",
"Step # 406 0.0012867801038525559\n",
"Step # 407 0.0012836086440227708\n",
"Step # 408 0.001280452838040121\n",
"Step # 409 0.0012773125702089847\n",
"Step # 410 0.0012741877259711454\n",
"Step # 411 0.001271078191891917\n",
"Step # 412 0.001267983855646318\n",
"Step # 413 0.0012649046060055527\n",
"Step # 414 0.0012618403328237514\n",
"Step # 415 0.001258790927024721\n",
"Step # 416 0.0012557562805890292\n",
"Step # 417 0.001252736286541282\n",
"Step # 418 0.0012497308389374862\n",
"Step # 419 0.0012467398328526748\n",
"Step # 420 0.0012437631643686506\n",
"Step # 421 0.0012408007305620295\n",
"Step # 422 0.0012378524294922606\n",
"Step # 423 0.0012349181601899752\n",
"Step # 424 0.0012319978226454458\n",
"Step # 425 0.0012290913177972365\n",
"Step # 426 0.0012261985475209183\n",
"Step # 427 0.0012233194146180962\n",
"Step # 428 0.0012204538228054985\n",
"Step # 429 0.0012176016767041437\n",
"Step # 430 0.0012147628818288965\n",
"Step # 431 0.001211937344577902\n",
"Step # 432 0.0012091249722223463\n",
"Step # 433 0.001206325672896266\n",
"Step # 434 0.0012035393555866172\n",
"Step # 435 0.0012007659301232624\n",
"Step # 436 0.0011980053071693644\n",
"Step # 437 0.0011952573982117374\n",
"Step # 438 0.0011925221155513496\n",
"Step # 439 0.0011897993722939958\n",
"Step # 440 0.001187089082341147\n",
"Step # 441 0.00118439116038077\n",
"Step # 442 0.0011817055218784353\n",
"Step # 443 0.0011790320830684352\n",
"Step # 444 0.0011763707609451254\n",
"Step # 445 0.0011737214732542571\n",
"Step # 446 0.0011710841384845044\n",
"Step # 447 0.0011684586758591653\n",
"Step # 448 0.001165845005327818\n",
"Step # 449 0.0011632430475582091\n",
"Step # 450 0.0011606527239282583\n",
"Step # 451 0.0011580739565180418\n",
"Step # 452 0.0011555066681020623\n",
"Step # 453 0.0011529507821414794\n",
"Step # 454 0.0011504062227765052\n",
"Step # 455 0.0011478729148188818\n",
"Step # 456 0.0011453507837445055\n",
"Step # 457 0.001142839755686052\n",
"Step # 458 0.001140339757425801\n",
"Step # 459 0.0011378507163885086\n",
"Step # 460 0.001135372560634334\n",
"Step # 461 0.0011329052188519735\n",
"Step # 462 0.00113044862035173\n",
"Step # 463 0.0011280026950588058\n",
"Step # 464 0.0011255673735066606\n",
"Step # 465 0.0011231425868303204\n",
"Step # 466 0.0011207282667599853\n",
"Step # 467 0.0011183243456145617\n",
"Step # 468 0.0011159307562953504\n",
"Step # 469 0.0011135474322797852\n",
"Step # 470 0.0011111743076152691\n",
"Step # 471 0.0011088113169130636\n",
"Step # 472 0.001106458395342307\n",
"Step # 473 0.0011041154786240565\n",
"Step # 474 0.001101782503025445\n",
"Step # 475 0.00109945940535386\n",
"Step # 476 0.0010971461229512618\n",
"Step # 477 0.0010948425936885542\n",
"Step # 478 0.0010925487559599748\n",
"Step # 479 0.0010902645486776347\n",
"Step # 480 0.001087989911266041\n",
"Step # 481 0.0010857247836567896\n",
"Step # 482 0.0010834691062832588\n",
"Step # 483 0.0010812228200753333\n",
"Step # 484 0.0010789858664543004\n",
"Step # 485 0.001076758187327722\n",
"Step # 486 0.0010745397250843912\n",
"Step # 487 0.0010723304225894125\n",
"Step # 488 0.0010701302231791916\n",
"Step # 489 0.0010679390706566816\n",
"Step # 490 0.0010657569092865494\n",
"Step # 491 0.0010635836837904397\n",
"Step # 492 0.0010614193393423154\n",
"Step # 493 0.0010592638215638258\n",
"Step # 494 0.0010571170765197595\n",
"Step # 495 0.0010549790507135449\n",
"Step # 496 0.0010528496910827633\n",
"Step # 497 0.0010507289449948108\n",
"Step # 498 0.0010486167602425077\n",
"Step # 499 0.0010465130850398144\n"
]
}
],
"source": [
"xs = [\n",
" [2.0, 3.0, -1.0],\n",
" [3.0, -1.0, 0.5],\n",
" [0.5, 1.0, 1.0],\n",
" [1.0, 1.0, -1.0],\n",
"]\n",
"ys = [1.0, -1.0, -1.0, 1.0] # desired targets\n",
"ls = []\n",
"\n",
"for k in range(500):\n",
" # forward pass\n",
" ypred = [n(x) for x in xs]\n",
" loss = sum((yout - ygt)**2 for ygt, yout in zip(ys, ypred))\n",
"\n",
" # backward pass\n",
" for p in n.parameters():\n",
" p.grad = 0.0 # YOU NEED TO clear out your gradient before every backward pass or it will just accumulate\n",
" loss.backward()\n",
"\n",
" # update (the gradient descent)\n",
" for p in n.parameters():\n",
" p.data += -0.05 * p.grad\n",
"\n",
" print('Step #', k, ' ', loss.data)\n",
" ls += [loss.data]"
]
},
{
"cell_type": "code",
"execution_count": 245,
"id": "8615e709-2365-4988-bad8-473590ff22b9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[Value(data=0.9868926891382584),\n",
" Value(data=-0.9822284602914287),\n",
" Value(data=-0.9834981983414189),\n",
" Value(data=0.9831334891456814)]"
]
},
"execution_count": 245,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ypred = [n(x) for x in xs]\n",
"ypred"
]
},
{
"cell_type": "code",
"execution_count": 246,
"id": "046c7e20-5384-476f-abb7-d6d313561ebb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x1325b21b3d0>]"
]
},
"execution_count": 246,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAhYAAAGdCAYAAABO2DpVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAixElEQVR4nO3de3DU1f3/8ddns9klkVy4hZCyUbxSxKACppHaakm1VK366/hzGDrys5121Hih2k5NO/UynTb02/l1sNUftbaV/lGNlyniWMFSFKiVayQVsEawKFFu3siG2+ay5/dHsh+y3DfZ3ZOcPB8zO5vdz+ezn7MnzOTF+bw/53jGGCMAAIA0CNhuAAAAcAfBAgAApA3BAgAApA3BAgAApA3BAgAApA3BAgAApA3BAgAApA3BAgAApE0w2yeMx+PasWOHCgoK5Hletk8PAAB6wRij1tZWlZWVKRA4/rhE1oPFjh07FIlEsn1aAACQBs3NzRo7duxxt2c9WBQUFEjqalhhYWG2Tw8AAHohGo0qEon4f8ePJ+vBInH5o7CwkGABAMAAc7IyBoo3AQBA2hAsAABA2hAsAABA2hAsAABA2hAsAABA2hAsAABA2hAsAABA2hAsAABA2hAsAABA2hAsAABA2hAsAABA2hAsAABA2mR9EbJM+b9/b1LroQ7ddvlZGl04xHZzAAAYlFIesfjwww/1rW99SyNGjFBeXp4uuOACrV+/PhNtS0n9umYteP09fbq/zXZTAAAYtFIasfjss880bdo0XXHFFVq8eLFGjRqlLVu2aNiwYZlq3ykLdK/iGjfGbkMAABjEUgoWv/zlLxWJRPTEE0/4740bNy7tjeqNQPf68OQKAADsSelSyAsvvKApU6boxhtvVElJiS666CI9/vjjJzwmFospGo0mPTKhe8CCEQsAACxKKVj897//1fz583XOOefo5Zdf1m233aa77rpLf/7zn497TF1dnYqKivxHJBLpc6OPxWPEAgAA6zxjTv1PcSgU0pQpU/T666/77911111at26dVq1adcxjYrGYYrGY/zoajSoSiailpUWFhYV9aHqyy/7nFTV/elALb79UF5Xbr/kAAMAl0WhURUVFJ/37ndKIxZgxYzRhwoSk9z7/+c9r+/btxz0mHA6rsLAw6ZEJiRqLOCMWAABYk1KwmDZtmpqampLee+edd3T6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IUNsN8dpM2bM8H+uqKhQZWWlTj/9dD3zzDPKy8uz2LKjDfhLISNHjlROTs5R1a+7d+9WaWmppVa5JdGPJ+rj0tJS7dmzJ2l7R0eHPv30U34Px3DHHXfoxRdf1KuvvqqxY8f675eWlqqtrU179+5N2v/Ivj7W7yKxDV1CoZDOPvtsTZ48WXV1dZo0aZIefvhh+jiNGhoatGfPHl188cUKBoMKBoNasWKFfvOb3ygYDGr06NH0dYYUFxfr3HPP1datW/vdv+kBHyxCoZAmT56sZcuW+e/F43EtW7ZMVVVVFlvmjnHjxqm0tDSpj6PRqNasWeP3cVVVlfbu3auGhgZ/n1deeUXxeFyVlZVZb3N/ZYzRHXfcoYULF+qVV17RuHHjkrZPnjxZubm5SX3d1NSk7du3J/X1xo0bk4Lc0qVLVVhYqAkTJmTniwxA8XhcsViMPk6j6dOna+PGjWpsbPQfU6ZM0axZs/yf6evM2Ldvn959912NGTOm//2bTmspqCX19fUmHA6bBQsWmLfeest873vfM8XFxUnVrzix1tZWs2HDBrNhwwYjyfz61782GzZsMO+//74xput20+LiYrNo0SLz5ptvmuuuu+6Yt5tedNFFZs2aNea1114z55xzDrebHuG2224zRUVFZvny5Um3jR04cMDf59ZbbzXl5eXmlVdeMevXrzdVVVWmqqrK3564bezKK680jY2NZsmSJWbUqFHcntfDfffdZ1asWGG2bdtm3nzzTXPfffcZz/PM3//+d2MMfZxJPe8KMYa+Tpd7773XLF++3Gzbts3861//MtXV1WbkyJFmz549xpj+1c9OBAtjjPntb39rysvLTSgUMpdccolZvXq17SYNKK+++qqRdNRj9uzZxpiuW05/+tOfmtGjR5twOGymT59umpqakj7jk08+MTNnzjRDhw41hYWF5pZbbjGtra0Wvk3/daw+lmSeeOIJf5+DBw+a22+/3QwbNszk5+ebG264wezcuTPpc9577z0zY8YMk5eXZ0aOHGnuvfde097enuVv0399+9vfNqeffroJhUJm1KhRZvr06X6oMIY+zqQjgwV9nR433XSTGTNmjAmFQuZzn/ucuemmm8zWrVv97f2pn1k2HQAApM2Ar7EAAAD9B8ECAACkDcECAACkDcECAACkDcECAACkDcECAACkDcECAACkDcECAACkDcECAACkDcECAACkDcECAACkDcECAACkzf8HeQBqSQlwzRAAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.plot(np.arange(0, 500, 1), ls)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}