From 3e62bba15db6dbbc83514bfcbf6cb49f0b4fe2ec Mon Sep 17 00:00:00 2001 From: karpathy Date: Thu, 18 Dec 2014 12:29:45 -0800 Subject: first commit --- src/recurrent.js | 528 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/vis.js | 88 ++++++++++ 2 files changed, 616 insertions(+) create mode 100644 src/recurrent.js create mode 100644 src/vis.js (limited to 'src') diff --git a/src/recurrent.js b/src/recurrent.js new file mode 100644 index 0000000..4c20a39 --- /dev/null +++ b/src/recurrent.js @@ -0,0 +1,528 @@ +var R = {}; // the Recurrent library + +(function(global) { + "use strict"; + + // Utility fun + function assert(condition, message) { + // from http://stackoverflow.com/questions/15313418/javascript-assert + if (!condition) { + message = message || "Assertion failed"; + if (typeof Error !== "undefined") { + throw new Error(message); + } + throw message; // Fallback + } + } + + // Random numbers utils + var return_v = false; + var v_val = 0.0; + var gaussRandom = function() { + if(return_v) { + return_v = false; + return v_val; + } + var u = 2*Math.random()-1; + var v = 2*Math.random()-1; + var r = u*u + v*v; + if(r == 0 || r > 1) return gaussRandom(); + var c = Math.sqrt(-2*Math.log(r)/r); + v_val = v*c; // cache this + return_v = true; + return u*c; + } + var randf = function(a, b) { return Math.random()*(b-a)+a; } + var randi = function(a, b) { return Math.floor(Math.random()*(b-a)+a); } + var randn = function(mu, std){ return mu+gaussRandom()*std; } + + // helper function returns array of zeros of length n + // and uses typed arrays if available + var zeros = function(n) { + if(typeof(n)==='undefined' || isNaN(n)) { return []; } + if(typeof ArrayBuffer === 'undefined') { + // lacking browser support + var arr = new Array(n); + for(var i=0;i= 0 && ix < this.w.length); + return this.w[ix]; + }, + set: function(row, col, v) { + // slow but careful accessor function + var ix = (this.d * row) + col; + assert(ix >= 0 && ix < this.w.length); + this.w[ix] = v; + }, + toJSON: function() { + var json = {}; + json['n'] = this.n; + json['d'] = this.d; + json['w'] = this.w; + return json; + }, + fromJSON: function(json) { + this.n = json.n; + this.d = json.d; + this.w = zeros(this.n * this.d); + this.dw = zeros(this.n * this.d); + for(var i=0,n=this.n * this.d;i=0;i--) { + this.backprop[i](); // tick! + } + }, + rowPluck: function(m, ix) { + // pluck a row of m with index ix and return it as col vector + assert(ix >= 0 && ix < m.n); + var d = m.d; + var out = new Mat(d, 1); + for(var i=0,n=d;i 0 ? out.dw[i] : 0.0; + } + } + this.backprop.push(backward); + } + return out; + }, + mul: function(m1, m2) { + // multiply matrices m1 * m2 + assert(m1.d === m2.n, 'matmul dimensions misaligned'); + + var n = m1.n; + var d = m2.d; + var out = new Mat(n,d); + for(var i=0;i maxval) maxval = m.w[i]; } + + var s = 0.0; + for(var i=0,n=m.w.length;i clipval) { + mdwi = clipval; + num_clipped++; + } + if(mdwi < -clipval) { + mdwi = -clipval; + num_clipped++; + } + num_tot++; + + // update (and regularize) + m.w[i] += - step_size * mdwi / Math.sqrt(s.w[i] + this.smooth_eps) - regc * m.w[i]; + m.dw[i] = 0; // reset gradients for next iteration + } + } + } + solver_stats['ratio_clipped'] = num_clipped*1.0/num_tot; + return solver_stats; + } + } + + var initLSTM = function(input_size, hidden_sizes, output_size) { + // hidden size should be a list + + var model = {}; + for(var d=0;d