Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More es6-ish syntax #13

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions examples/es6/bechmarks/pi.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,18 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import Promises from 'bluebird';
import common from '../common';

"use strict";
let Bluebird = require("bluebird");
let async = Bluebird.coroutine;
let common = require("../common");

const async = Promises.coroutine;
const numberOfPoints = 20000000;

let pi = async(function*(af, deviceInfo) {
let AFArray = af.AFArray;

console.log("Calculating pi on device:\n");
console.log('Calculating pi on device:\n');
common.printDeviceInfo(deviceInfo);
console.log("");
console.log('');

let x = af.randu(numberOfPoints, af.dtype.f32);
let y = af.randu(numberOfPoints, af.dtype.f32);
Expand All @@ -52,4 +50,4 @@ let pi = async(function*(af, deviceInfo) {
console.log(`PI = ${piVal}`);
});

common.runOnAllPlatforms(pi, "pi example");
common.runOnAllPlatforms(pi, 'pi example');
17 changes: 8 additions & 9 deletions examples/es6/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

"use strict";
let Bluebird = require("bluebird");
let async = Bluebird.coroutine;
let af = require("../../..");
let util = require("util");
let now = require("performance-now");
let _ = require("lodash");
import Promises from 'bluebird';
import af from '../../..';
import now from 'performance-now';
import _ from 'lodash';

const async = Promises.coroutine;

let runOnDevices = async(function*(platformID, f, onID) {
let afOfPlatform = af(platformID);
Expand All @@ -52,7 +51,7 @@ let runOnDevices = async(function*(platformID, f, onID) {

let runOnAllPlatforms = async(function*(f, name) {
let platfroms = af.supportedPlatforms();
console.log(`Running ${name} on all supported platfroms: ${platfroms.join(", ")}\n`);
console.log(`Running ${name} on all supported platfroms: ${platfroms.join(', ')}\n`);
try {
for (let id of platfroms) {
yield runOnDevices(id, f);
Expand All @@ -65,7 +64,7 @@ let runOnAllPlatforms = async(function*(f, name) {

let runOnBestDevice = async(function*(f, name) {
let platfroms = af.supportedPlatforms();
let order = ["CUDA", "OpenCL", "CPU"];
let order = ['CUDA', 'OpenCL', 'CPU'];
console.log(`Running ${name} on best available device.\n`);
try {
if (_(platfroms).contains(order[0])) {
Expand Down
201 changes: 105 additions & 96 deletions examples/es6/machine-learning/ann.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
"use strict";
import debug from 'debug';
import now from 'performance-now';

let _ = require("lodash");
let Bluebird = require("bluebird");
let async = Bluebird.coroutine;
let debug = require("debug")("af:ann");
let now = require("performance-now");
debug('af:ann');

function ANN(af, layers, range) {
export default class ANN {
constructor(af, layers, range) {
range = range || 0.05;
this.af = af;
this.numLayers = layers.length;
Expand All @@ -15,80 +13,92 @@ function ANN(af, layers, range) {
for (let i = 0; i < this.numLayers; i++) {
this.signal.push(new af.AFArray());
if (i < this.numLayers - 1) {
let w = af.randu(layers[i] + 1, layers[i + 1], af.dType.f32).mul(range).sub(range / 2);
let w = af
.randu(layers[i] + 1, layers[i + 1], af.dType.f32)
.mul(range)
.sub(range / 2);
this.weights.push(w);
}
}
}

let proto = ANN.prototype;
}

proto.deriv = function (out) {
return out.rhsSub(1).mul(out);
};
deriv(out) {
return out
.rhsSub(1)
.mul(out);
}

proto.addBias = function (input) {
return this.af.join(1, this.af.constant(1, input.dims(0), this.af.dType.f32), input);
};
addBias(input) {
let { af } = this;
return af.join(1, af.constant(1, input.dims(0), af.dType.f32), input);
}

proto._calculateError = function(out, pred) {
_calculateError(out, pred) {
let dif = out.sub(pred);
let sq = dif.mul(dif);
return Math.sqrt(this.af.sum(sq)) / sq.elements();
};
let { af } = this;
return Math.sqrt(af.sum(sq)) / sq.elements();
}

proto.forwardPropagate = function (input) {
forwardPropagate(input) {
let { af } = this;
this.signal[0].set(input);

for (let i = 0; i < this.numLayers - 1; i++) {
let self = this;
this.af.scope(function() {
let inVec = self.addBias(self.signal[i]);
let outVec = self.af.matMul(inVec, self.weights[i]);
self.signal[i + 1].set(self.af.sigmoid(outVec));
});
af.scope(() => {
let inVec = this.addBias(this.signal[i]);
let outVec = af.matMul(inVec, this.weights[i]);
this.signal[i + 1].set(af.sigmoid(outVec));
});
}
};
}

proto.backPropagate = function (target, alpha) {
let self = this;
let af = self.af;
let Seq = self.af.Seq;
backPropagate(target, alpha) {
let { af } = this;
let { Seq } = af;

// Get error for output layer
af.scope(function() {
let outVec = self.signal[self.numLayers - 1];
let err = outVec.sub(target);
let m = target.dims(0);

for (let i = self.numLayers - 2; i >= 0; i--) {
af.scope(function() {
let inVec = self.addBias(self.signal[i]);
let delta = af.transpose(self.deriv(outVec).mul(err));

// Adjust weights
let grad = af.matMul(delta, inVec).mul(alpha).neg().div(m);
self.weights[i].addAssign(af.transpose(grad));

// Input to current layer is output of previous
outVec = self.signal[i];
err.set(self.af.matMulTT(delta, self.weights[i]));

// Remove the error of bias and propagate backward
err.set(err.at(af.span, new Seq(1, outVec.dims(1))));
});
}
af.scope(() => {
let outVec = this.signal[this.numLayers - 1];
let err = outVec.sub(target);
let m = target.dims(0);

for (let i = this.numLayers - 2; i >= 0; i--) {
af.scope(() => {
let inVec = this.addBias(this.signal[i]);
let delta = af.transpose(
this
.deriv(outVec)
.mul(err)
);

// Adjust weights
let grad = af.matMul(delta, inVec)
.mul(alpha)
.neg()
.div(m);

this.weights[i].addAssign(af.transpose(grad));

// Input to current layer is output of previous
outVec = this.signal[i];
err.set(af.matMulTT(delta, this.weights[i]));

// Remove the error of bias and propagate backward
err.set(err.at(af.span, new Seq(1, outVec.dims(1))));
});
}
});
};
}

proto.predict = function (input) {
predict(input) {
this.forwardPropagate(input);
return this.signal[this.numLayers - 1].copy();
};
}

proto.train = function(input, target, options) {
let self = this;
let af = self.af;
let Seq = self.af.Seq;
train(input, target, options) {
let { af } = this;
let { Seq } = af;

let numSamples = input.dims(0);
let numBatches = numSamples / options.batchSize;
Expand All @@ -97,44 +107,43 @@ proto.train = function(input, target, options) {
let allTime = 0;

for (let i = 0; i < options.maxEpochs; i++) {
const start = now();
for (let j = 0; j < numBatches - 1; j++) {
af.scope(() => {
let startPos = j * options.batchSize;
let endPos = startPos + options.batchSize - 1;

let x = input.at(new Seq(startPos, endPos), af.span);
let y = target.at(new Seq(startPos, endPos), af.span);

self.forwardPropagate(x);
self.backPropagate(y, options.alpha);
});
}

const start = now();
for (let j = 0; j < numBatches - 1; j++) {
af.scope(() => {
// Validate with last batch
let startPos = (numBatches - 1) * options.batchSize;
let endPos = numSamples - 1;
let outVec = self.predict(input.at(new Seq(startPos, endPos), af.span));
err = self._calculateError(outVec, target.at(new Seq(startPos, endPos), af.span));
});
let startPos = j * options.batchSize;
let endPos = startPos + options.batchSize - 1;

const end = now();
allTime += (end - start) / 1000;

if ((i + 1) % 10 === 0) {
console.log(`Epoch: ${i + 1}, Error: ${err.toFixed(6)}, Duration: ${(allTime / 10).toFixed(6)} seconds`);
allTime = 0;
}
let x = input.at(new Seq(startPos, endPos), af.span);
let y = target.at(new Seq(startPos, endPos), af.span);

// Check if convergence criteria has been met
if (err < options.maxError) {
console.log(`Converged on Epoch: ${i + 1}`);
break;
}
this.forwardPropagate(x);
this.backPropagate(y, options.alpha);
});
}

af.scope(() => {
// Validate with last batch
let startPos = (numBatches - 1) * options.batchSize;
let endPos = numSamples - 1;
let outVec = this.predict(input.at(new Seq(startPos, endPos), af.span));
err = this._calculateError(outVec, target.at(new Seq(startPos, endPos), af.span));
});

const end = now();
allTime += (end - start) / 1000;

if ((i + 1) % 10 === 0) {
console.log(`Epoch: ${i + 1}, Error: ${err.toFixed(6)}, Duration: ${(allTime / 10).toFixed(6)} seconds`);
allTime = 0;
}

// Check if convergence criteria has been met
if (err < options.maxError) {
console.log(`Converged on Epoch: ${i + 1}`);
break;
}
}

return err;
};

module.exports = ANN;
}
}
Loading