From c6ad2b8e746ef666ad8febc86efec157ebe09098 Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Tue, 20 Sep 2016 21:45:58 -0400 Subject: [PATCH 1/2] More es6-ish syntax --- examples/es6/bechmarks/pi.js | 16 +- examples/es6/common/index.js | 25 ++- examples/es6/machine-learning/ann.js | 201 +++++++++--------- examples/es6/machine-learning/mnist.js | 54 +++-- .../es6/machine-learning/neuralNetwork.js | 25 ++- 5 files changed, 165 insertions(+), 156 deletions(-) diff --git a/examples/es6/bechmarks/pi.js b/examples/es6/bechmarks/pi.js index c2f5407..c8bc5ee 100644 --- a/examples/es6/bechmarks/pi.js +++ b/examples/es6/bechmarks/pi.js @@ -17,7 +17,7 @@ are permitted provided that the following conditions are met: contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR @@ -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); @@ -52,4 +50,4 @@ let pi = async(function*(af, deviceInfo) { console.log(`PI = ${piVal}`); }); -common.runOnAllPlatforms(pi, "pi example"); +common.runOnAllPlatforms(pi, 'pi example'); diff --git a/examples/es6/common/index.js b/examples/es6/common/index.js index ff49174..fa5178c 100644 --- a/examples/es6/common/index.js +++ b/examples/es6/common/index.js @@ -17,7 +17,7 @@ are permitted provided that the following conditions are met: contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR @@ -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); @@ -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); @@ -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])) { @@ -81,6 +80,12 @@ let runOnBestDevice = async(function*(f, name) { catch (e) { console.error(e.stack); } + + try { + + } catch (e) { + + } }); let printDeviceInfo = function (deviceInfo) { diff --git a/examples/es6/machine-learning/ann.js b/examples/es6/machine-learning/ann.js index 7a43599..8dc3d8d 100644 --- a/examples/es6/machine-learning/ann.js +++ b/examples/es6/machine-learning/ann.js @@ -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; @@ -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; @@ -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; + } +} diff --git a/examples/es6/machine-learning/mnist.js b/examples/es6/machine-learning/mnist.js index c8f67c9..1b63727 100644 --- a/examples/es6/machine-learning/mnist.js +++ b/examples/es6/machine-learning/mnist.js @@ -1,32 +1,34 @@ -"use strict"; - -let Bluebird = require("bluebird"); -let async = Bluebird.coroutine; -let fs = Bluebird.promisifyAll(require("fs-extra")); -let ref = require("ref"); -let float = ref.types.float; -let uint = ref.types.uint; -let debug = require("debug")("af:mnist"); -let _ = require("lodash"); -let assert = require("better-assert"); -let path = require("path"); - -let readData = async(function*(f, data) { +import Promises from 'bluebird'; +import ref from 'ref'; +import fsExtra from 'fs-extra'; +import debug from 'debug'; +import _ from 'lodash'; +import assert from 'better-assert'; +import path from 'path'; + +debug('af:mnist'); + +const async = Promises.coroutine; +const fs = Promises.promisifyAll(fsExtra); +const float = ref.types.float; +const uint = ref.types.uint; + +const readData = async(function*(f, data) { let bytesRead = yield fs.readAsync(f, data, 0, data.length, null); if (bytesRead !== data.length) { - throw new Error("File reading error!"); + throw new Error('File reading error!'); } }); -let readIdx = async(function*(path, type) { - let file = yield fs.openAsync(path, "r"); +const readIdx = async(function*(path, type) { + let file = yield fs.openAsync(path, 'r'); try { let d = new Buffer(4); yield readData(file, d); if (d[2] != 8) { - throw new Error("Unsupported data type"); + throw new Error('Unsupported data type'); } const numDims = d[3]; @@ -55,21 +57,20 @@ let readIdx = async(function*(path, type) { dims: dims, data: data }; - } - finally { + } finally { yield fs.closeAsync(file); } }); -let mnist = { +export default const mnist = { setup: async(function*(af, expandLabels, frac) { frac = Math.min(frac || 1.0, 0.8); - let dataRoot = path.resolve(path.join(__dirname, "../../ml_lab/data/mnist")); + let dataRoot = path.resolve(path.join(__dirname, '../../ml_lab/data/mnist')); let AFArray = af.AFArray; let Dim4 = af.Dim4; - let imageData = yield readIdx(path.join(dataRoot, "images-subset"), float); - let labelData = yield readIdx(path.join(dataRoot, "labels-subset"), uint); + let imageData = yield readIdx(path.join(dataRoot, 'images-subset'), float); + let labelData = yield readIdx(path.join(dataRoot, 'labels-subset'), uint); let rIDims = new Dim4(_(imageData.dims).reverse().value()); let images = yield AFArray.createAsync(rIDims, af.dType.f32, imageData.data); @@ -115,8 +116,7 @@ let mnist = { assert(label >= 0 && label <= 9); testLabels.set(label, i, 1); } - } - else { + } else { let labels = yield AFArray.createAsync(labelData.dims[0], af.dType.u32, labelData.data); trainLabels = labels.at(trainIndices); testLabels = labels.at(testIndices); @@ -133,5 +133,3 @@ let mnist = { }; }) }; - -module.exports = mnist; \ No newline at end of file diff --git a/examples/es6/machine-learning/neuralNetwork.js b/examples/es6/machine-learning/neuralNetwork.js index 59f3a7a..f92f082 100644 --- a/examples/es6/machine-learning/neuralNetwork.js +++ b/examples/es6/machine-learning/neuralNetwork.js @@ -1,11 +1,10 @@ -"use strict"; +import Promises from 'bluebird'; +import common from '../common'; +import mnist from './mnist'; +import ANN from './ann'; +import now from 'performance-now'; -let Bluebird = require("bluebird"); -let async = Bluebird.coroutine; -let common = require("../common"); -let mnist = require("./mnist"); -let ANN = require("./ann"); -let now = require("performance-now"); +let async = Promises.coroutine; let accuracy = function(af, predicted, target) { let pMax = af.findMaxAt(predicted, 1); @@ -14,11 +13,11 @@ let accuracy = function(af, predicted, target) { }; let annDemo = async(function*(af, deviceInfo) { - console.log("Running ANN Demo on device:\n"); + console.log('Running ANN Demo on device:\n'); common.printDeviceInfo(deviceInfo); - console.log(""); + console.log(''); - console.log("Setting up training data."); + console.log('Setting up training data.'); let data = yield mnist.setup(af, true, 0.6); let featureSize = data.trainImages.elements() / data.numTrain; @@ -51,13 +50,13 @@ let annDemo = async(function*(af, deviceInfo) { let trainOutput = network.predict(trainFeats); let testOutput = network.predict(testFeats); - console.log("Training set:"); + console.log('Training set:'); console.log(`Accuracy on training data: ${(accuracy(af, trainOutput, trainTarget)).toFixed(2)}`); - console.log("Test set:"); + console.log('Test set:'); console.log(`Accuracy on testing data: ${(accuracy(af, testOutput, testTarget)).toFixed(2)}`); console.log(`Training time: ${((end - start) / 1000).toFixed(10)} seconds\n`); }); -common.runOnBestDevice(annDemo, "ANN Demo"); \ No newline at end of file +common.runOnBestDevice(annDemo, 'ANN Demo'); \ No newline at end of file From ddeb194b28cf8e58656344e78776f75be340b9c8 Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Wed, 21 Sep 2016 07:57:42 -0400 Subject: [PATCH 2/2] More es6-ish syntax --- examples/es6/bechmarks/pi.js | 2 +- examples/es6/common/index.js | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/examples/es6/bechmarks/pi.js b/examples/es6/bechmarks/pi.js index c8bc5ee..9b8988b 100644 --- a/examples/es6/bechmarks/pi.js +++ b/examples/es6/bechmarks/pi.js @@ -17,7 +17,7 @@ are permitted provided that the following conditions are met: contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR diff --git a/examples/es6/common/index.js b/examples/es6/common/index.js index fa5178c..f81f781 100644 --- a/examples/es6/common/index.js +++ b/examples/es6/common/index.js @@ -17,7 +17,7 @@ are permitted provided that the following conditions are met: contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR @@ -80,12 +80,6 @@ let runOnBestDevice = async(function*(f, name) { catch (e) { console.error(e.stack); } - - try { - - } catch (e) { - - } }); let printDeviceInfo = function (deviceInfo) {