Published
Edited
Aug 7, 2020
Importers
11 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
f = x => (x - 40)**2 + x
Insert cell
fp = x => 2 * x - 79
Insert cell
fpp = x => 2
Insert cell
Insert cell
Insert cell
Insert cell
class Func {
constructor() {
// Some generic constructor
}
calc(x) {
// Return the value of this function at x
}
df() {
// Return the differential of this function
}
toString() {
return `?`
}
clean() {
return "?"; // Returns a cleaned function.
}
}
Insert cell
Insert cell
class Add extends Func {
constructor(left, right) {
super();
this.left = left;
this.right = right;
}
calc(x) {
return this.left.calc(x) + this.right.calc(x);
}
df() {
return new Add(this.left.df(), this.right.df())
}
toString() {
return `(${this.left.toString()} + ${this.right.toString()})`
}
}
Insert cell
Insert cell
class Mult extends Func {
constructor(left, right) {
super();
this.left = left;
this.right = right;
}
calc(x) {
return this.left.calc(x) * this.right.calc(x);
}
df() {
return new Add(
new Mult(this.left, this.right.df()),
new Mult(this.right, this.left.df())
)
}
toString() {
return `(${this.left.toString()} * ${this.right.toString()})`
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
F = new Add(new Pow(new Add(new X(), new Constant(-40)), 2), new X())
Insert cell
Insert cell
F.df()
Insert cell
Insert cell
Insert cell
tex `f'(x)=${F.df().toString()}`
Insert cell
tex `f''(x)=${F.df().df().toString()}`
Insert cell
Insert cell
md `We should get that ${tex `${F.df().df().clean().toString()}`} = 2.`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
x = new Value(35);
Insert cell
y = new Value(-40);
Insert cell
z = add(pow(add(x, y), 2), x);
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
class Value {
constructor(data, _deps=[], _op='') {
this.data = data;
this.grad = 0;
this._dependencies = _deps
this._op = _op;
this._order = [];
}
_backward() {
// Reimplemented by the operators.
}
zeroGrad() {
this.grad = 0;
}
backward(focus) {
// Find the topological ordering of the values
// For each value, visit it's dependencies first and add them to the ordering
let order = [];
let visited = [];

function get_deps(focus) {
if (!visited.includes(focus)) {
visited.push(focus);
focus._dependencies.forEach(
(dep) => get_deps(dep)
)

order.push(focus)
}
}

get_deps(this);

// Initialize the gradient of the whole function to 1
// and calculate the gradient for each value.
this.grad = 1;

for (let i = 1; i <= order.length; i++) {
let focus = order[order.length - i]
focus._backward()
}
this._order = order;
}

}
Insert cell
function neg(val) {
return mul(val, new Value(-1))
}
Insert cell
function sub(left, right) {
return add(left, neg(right))
}
Insert cell
function sum(items) {
return items.reduce((acc, current) => add(acc, current), new Value(0))
}
Insert cell
function add(left, right) {
let val = new Value(left.data+right.data, [left, right], '+');
val._backward = function() {
left.grad += val.grad;
right.grad += val.grad;
}
return val;
}
Insert cell
function div(left, right) {
return mul(left, pow(right, -1))
}
Insert cell
function mul(left, right) {
let val = new Value(left.data*right.data, [left, right], '*');
val._backward = function() {
left.grad += val.grad * right.data;
right.grad += val.grad * left.data;
}
return val;
}
Insert cell
function pow(base, power) {
let val = new Value(base.data ** power, [base] , `^${power}`);
val._backward = function() {
base.grad += power * (base.data ** (power -1)) * val.grad;
}
return val;
}
Insert cell
function relu(input) {
let val = new Value(Math.max(0, input.data),[input], 'relu');
val._backward = function() {
input.grad += val.data > 0 ? val.grad : 0;
}
return val;
}
Insert cell
Math.min
Insert cell
Insert cell
function graph(root) {
let nodes = [];
let edges = [];
for(let i=0; i<root._order.length;i++) {
let node = root._order[i];
let index = root._order.indexOf(node);
nodes.push(`n${index} [shape=record label="val ${node.data} | grad ${node.grad}"]`);
if(node._op !== "") {
nodes.push(`n${index}op [label="${node._op}"]`);
edges.push(`n${index}op -> n${index}`);
node._dependencies.forEach(d => {
edges.push(`n${root._order.indexOf(d)} -> n${index}op`);
})
}
}
return edges.join(";\n") + ";\n" + nodes.join(";\n")
}
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more