From e3efd749c4889aaee63b0d4836e625f19e02783f Mon Sep 17 00:00:00 2001 From: Leon Chen Date: Sat, 17 Sep 2016 23:41:22 -0400 Subject: [PATCH] initialization of sequential models --- src/Layer.js | 18 +++++++++++------ src/Model.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/Layer.js b/src/Layer.js index ff74075..9877423 100644 --- a/src/Layer.js +++ b/src/Layer.js @@ -11,14 +11,11 @@ export default class Layer { */ constructor (attrs = {}) { this.name = attrs.name + + this.params = [] + this.weights = {} } - inboundNodes = [] - outboundNodes = [] - - params = [] - weights = {} - /** * Method for setting layer weights * We store the weights as both Tensor instances, @@ -33,6 +30,15 @@ export default class Layer { }) } + /** + * Method for layer computational logic + * @param {Tensor} x + * @returns {Tensor} x + */ + call (x) { + return x + } + /** * Create weblas pipeline tensor weights * 2-D only diff --git a/src/Model.js b/src/Model.js index e1bc87d..6a41ef7 100644 --- a/src/Model.js +++ b/src/Model.js @@ -3,7 +3,10 @@ import Promise from 'bluebird' import toPairs from 'lodash/toPairs' import mapKeys from 'lodash/mapKeys' import camelCase from 'lodash/camelCase' -import * as layers from '../layers' +import find from 'lodash/find' +import * as layers from './layers' +import Input from './Input' +import Tensor from './Tensor' /** * Model class @@ -139,18 +142,66 @@ export default class Model { if (modelClass === 'Sequential') { const modelConfig = this.data.model.config + const inputName = 'input' modelConfig.forEach((layerConfig, index) => { + // create Input node at start + if (index === 0) { + const layer = new Input({ + name: inputName, + inputShape: layerConfig.batch_input_shape.slice(1) + }) + this.modelLayers.set(inputName, layer) + this.modelDAG[inputName] = { + name: inputName, + outbound: [] + } + } + const layerClass = layerConfig.class_name if (layerClass in layers) { const attrs = mapKeys(layerConfig, (v, k) => camelCase(k)) const layer = new layers[layerClass](attrs) - this.modelLayers.set(attrs.name, layer) - this.modelDAG[ + + // layer weights + if (layer.params && layer.params.length) { + const weights = layer.params.map(param => { + const paramMetadata = find(this.data.metadata, meta => { + const weightRE = new RegExp(`^${layerConfig.name}_${param}`) + return meta.layer_name === layerConfig.name && + weightRE.test(meta.weight_name) + }) + if (!paramMetadata) { + throw new Error(`[Model] error loading weights.`) + } + + const { offset, length, shape } = paramMetadata + return new Tensor(new Float32Array(this.data.weights, offset, length), shape) + }) + layer.setWeights(weights) + } + + this.modelLayers.set(layerConfig.name, layer) + this.modelDAG[layerConfig.name] = { + name: layerConfig.name, + outbound: [] + } + if (index === 0) { + this.modelDAG[inputName].outbound.push(layerConfig.name) + } else { + this.modelDAG[modelConfig[index - 1].name].outbound.push(layerConfig.name) + } } else { throw new Error(`Layer ${layerClass} specified in model configuration is not implemented!`) } }) } } + + /** + * Predict API + */ + predict (data) { + + } }