// the Recurrent library with DCT compression and CoSyNe neuroevolution var R = {}; (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; }, copy: function() { // return a copy of Mat var result = new Mat(this.n, this.d); var i, len; len = this.n*this.d; for (i = 0; i < len; i++) { result.w[i] = this.w[i]; result.dw[i] = this.dw[i]; } return result; }, toString: function(precision_) { var result_w = '['; var i, j; var n, d; var ix; var precision = 10e-4 || precision_; precision = 1/precision; n = this.n; d = this.d; for (i=0;i= 0 && ix < this.w.length); result_w+=''+Math.round(precision*this.w[ix])/precision+',\t'; } result_w+='\n'; } result_w+=']'; return result_w; }, print: function() { console.log(this.toString()); }, dct2: function() { // inefficient implementation of discrete cosine transform (2d) // ref: http://www.mathworks.com/help/images/ref/dct2.html var n = this.n; var d = this.d; var B = new Mat(n, d); // resulting matrix var i, j, k, l; var temp; for (i=0;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(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 = {}; var hidden_size; var prev_size; for(var d=0;d