- micrograd - numpy - matplotlib

The micrograd demo notebook in pyscript training a model running python natively in your browser


Credit: Andrej Karpathy https://github.com/karpathy/micrograd/blob/master/demo.ipynb
Please wait for the 'Python is ready...' message to appear before starting. If you want to watch the progress you can view it in your browser's console.
Use Shift+Enter to execute cells in the repl.
Alternatively you can have all of the code executed automatically here: https://matdmiller.github.io/fastai-huggingface-sample-web-app1/pyscript-micrograd-demo-autorun.html When it has finished a plot will be displayed.
print('Python is ready...') import random import numpy as np import matplotlib.pyplot as plt
from micrograd.engine import Value from micrograd.nn import Neuron, Layer, MLP
np.random.seed(1337) random.seed(1337)
#An adaptation of sklearn's make_moons function https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_moons.html def make_moons(n_samples=100, noise=None): n_samples_out, n_samples_in = n_samples, n_samples outer_circ_x = np.cos(np.linspace(0, np.pi, n_samples_out)) outer_circ_y = np.sin(np.linspace(0, np.pi, n_samples_out)) inner_circ_x = 1 - np.cos(np.linspace(0, np.pi, n_samples_in)) inner_circ_y = 1 - np.sin(np.linspace(0, np.pi, n_samples_in)) - 0.5 X = np.vstack([np.append(outer_circ_x, inner_circ_x), np.append(outer_circ_y, inner_circ_y)]).T y = np.hstack([np.zeros(n_samples_out, dtype=np.intp), np.ones(n_samples_in, dtype=np.intp)]) if noise is not None: X += np.random.normal(loc=0.0, scale=noise, size=X.shape) return X, y X, y = make_moons(n_samples=100, noise=0.1)
y = y*2 - 1 # make y be -1 or 1 # visualize in 2D plt.figure(figsize=(5,5)) plt.scatter(X[:,0], X[:,1], c=y, s=20, cmap='jet') plt
model = MLP(2, [16, 16, 1]) # 2-layer neural network print(model) print("number of parameters", len(model.parameters()))
Due to a current bug in pyscript the > symbol is imported as >.
Line 24 has been changed from:
accuracy = [(yi > 0) == (scorei.data > 0) for yi, scorei in zip(yb, scores)]
to:
accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for yi, scorei in zip(yb, scores)]
as a work-around to the bug.
# loss function def loss(batch_size=None): # inline DataLoader :) if batch_size is None: Xb, yb = X, y else: ri = np.random.permutation(X.shape[0])[:batch_size] Xb, yb = X[ri], y[ri] inputs = [list(map(Value, xrow)) for xrow in Xb] # forward the model to get scores scores = list(map(model, inputs)) # svm "max-margin" loss losses = [(1 + -yi*scorei).relu() for yi, scorei in zip(yb, scores)] data_loss = sum(losses) * (1.0 / len(losses)) # L2 regularization alpha = 1e-4 reg_loss = alpha * sum((p*p for p in model.parameters())) total_loss = data_loss + reg_loss # also get accuracy accuracy = [((yi).__gt__(0)) == ((scorei.data).__gt__(0)) for yi, scorei in zip(yb, scores)] return total_loss, sum(accuracy) / len(accuracy) total_loss, acc = loss() print(total_loss, acc)
# optimization for k in range(20): #was 100 # forward total_loss, acc = loss() # backward model.zero_grad() total_loss.backward() # update (sgd) learning_rate = 1.0 - 0.9*k/100 for p in model.parameters(): p.data -= learning_rate * p.grad if k % 1 == 0: print(f"step {k} loss {total_loss.data}, accuracy {acc*100}%")
Please wait for the training loop above to complete. It will not print out stats until it is finished.
This will take some time.

Due to a current bug in pyscript the > symbol is imported as >.
Line 9 has been changed from:
Z = np.array([s.data > 0 for s in scores])
to:
Z = np.array([(s.data).__gt__(0) for s in scores])
as a work-around to the bug.
h = 0.25 x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1 y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) Xmesh = np.c_[xx.ravel(), yy.ravel()] inputs = [list(map(Value, xrow)) for xrow in Xmesh] scores = list(map(model, inputs)) Z = np.array([(s.data).__gt__(0) for s in scores]) Z = Z.reshape(xx.shape) fig = plt.figure() plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral, alpha=0.8) plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.Spectral) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) plt
1+1