diff --git a/src/plugins/ImportKeras/ImportKeras.js b/src/plugins/ImportKeras/ImportKeras.js new file mode 100644 index 0000000..dcffba6 --- /dev/null +++ b/src/plugins/ImportKeras/ImportKeras.js @@ -0,0 +1,301 @@ +/*globals define*/ +define([ + 'plugin/PluginConfig', + 'text!./metadata.json', + 'plugin/PluginBase', + './utils/JSONModelMaps', + './utils/json-model-parser', +], function ( + PluginConfig, + pluginMetadata, + PluginBase, + ModelMaps, + JSONLayerParser, +) { + 'use strict'; + + pluginMetadata = JSON.parse(pluginMetadata); + + + /** + * Initializes a new instance of ImportKeras. + * @class + * @augments {PluginBase} + * @classdesc This class represents the plugin ImportKeras. + * @constructor + */ + var ImportKeras = function () { + // Call base class' constructor. + PluginBase.call(this); + this.pluginMetadata = pluginMetadata; + }; + + /** + * Metadata associated with the plugin. Contains id, name, version, description, icon, configStructure etc. + * This is also available at the instance at this.pluginMetadata. + * @type {object} + */ + ImportKeras.metadata = pluginMetadata; + + // Prototypical inheritance from PluginBase. + ImportKeras.prototype = Object.create(PluginBase.prototype); + ImportKeras.prototype.constructor = ImportKeras; + + /** + * Main function for the plugin to execute. This will perform the execution. + * Notes: + * - Always log with the provided logger.[error,warning,info,debug]. + * - Do NOT put any user interaction logic UI, etc. inside this method. + * - callback always has to be called even if error happened. + * + * @param {function(Error|null, plugin.PluginResult)} callback - the result callback + */ + ImportKeras.prototype.main = async function(callback){ + let srcJsonHash = this.getCurrentConfig().srcModel; + if (!srcJsonHash) { + callback(new Error('Keras Json Not Provided'), this.result); + return; + } + try { + let archName = this.getCurrentConfig().archName; + let metadata = await this.blobClient.getMetadata(srcJsonHash); + archName = archName ? archName : metadata.name.replace('.json', ''); + let modelJson = await this.blobClient.getObjectAsJSON(srcJsonHash); + this.modelInfo = JSONLayerParser.flatten(modelJson).config; + let importedArchNode = this.addNewArchitecture(archName); + this.addLayers(importedArchNode); + await this.addConnections(); + await this.save('Completed Import Model'); + this.result.setSuccess(true); + callback(null, this.result); + } catch (err) { + this.logger.debug(`Something Went Wrong, Error Message: ${err}`); + callback(err, this.result); + } + }; + + ImportKeras.prototype.addNewArchitecture = function (archName) { + // Add Architecture + let importedArch = this.core.createNode({ + parent: this.activeNode, + base: this.META.Architecture + }); + const uniqueName = archName; + this.core.setAttribute(importedArch, 'name', uniqueName); + this.logger.debug(`Added ${uniqueName} as a new architecture.`); + return importedArch; + }; + + // This should add layers. constraints, initializers, regularizers as well as activations to the layer. + ImportKeras.prototype.addLayers = function (importedArch) { + let layers = this.modelInfo.layers; + let layerToCreate = null; + this.layerInfo = {}; + layers.forEach((layer) => { + layerToCreate = this._getMetaTypeForClass(layer.class_name); + let layerNode = this.core.createNode({ + parent: importedArch, + base: this.META[layerToCreate] + }); + this.logger.debug(`Added ${layerToCreate}\ + to ${this.core.getAttribute(importedArch, 'name')}`); + + // Add all attributes, from the model JSON, as well as from the layers schema + this._addLayerAttributes(layerNode, layer); + this._addConfigurableNodes(layerNode, layer); + }); + }; + + // All the attributes, which do not require a separate node to be created + // 1. First find the validAttributeNames for the layer + // 2. If the name is in layer, set it. + // 3. If the name is in layer.config, set it. + // 4. Finally, check the layers schema for remaining attributes. + ImportKeras.prototype._addLayerAttributes = function (layerNode, attrObj) { + let config = attrObj.config; + let validAttributeNamesForThisLayer = this.core.getValidAttributeNames(layerNode); + let configKeys = Object.keys(config); + let remainingKeys = Object.keys(attrObj) + .filter(value => value !== 'config'); + + validAttributeNamesForThisLayer.forEach((attribute) => { + if (remainingKeys.indexOf(this._jsonConfigToNodeAttr(attribute)) > -1) { + this.core.setAttribute(layerNode, attribute, this._toPythonType(attrObj[this._jsonConfigToNodeAttr(attribute)])); + this.logger.debug(`Set ${attribute} for ${this.core.getGuid(layerNode)}` + + ` to ${this.core.getAttribute(layerNode, attribute)}`); + } else if (configKeys.indexOf(this._jsonConfigToNodeAttr(attribute)) > -1) { + this.core.setAttribute(layerNode, attribute, this._toPythonType(config[this._jsonConfigToNodeAttr(attribute)])); + this.logger.debug(`Set ${attribute} for ${this.core.getGuid(layerNode)}` + + ` to ${this.core.getAttribute(layerNode, attribute)}`); + } + }); + let layerName = this.core.getAttribute(layerNode, 'name'); + this.layerInfo[layerName] = layerNode; + + }; + + ImportKeras.prototype._addConfigurableNodes = function (layerNode, layerConfig) { + let allPointerNames = this.core.getValidPointerNames(layerNode); + let config = layerConfig.config; + this.logger.debug(`Layer ${this.core.getAttribute(layerNode, 'name')}` + + ` has following configurable attributes ${allPointerNames.join(', ')}`); + allPointerNames.filter(pointer => !!config[pointer]) + .forEach((pointer) => { + let node = this._addFunctionNode(layerNode, config, pointer); + this.core.setPointer(layerNode, pointer, node); + this.logger.debug(`Added ${this.core.getAttribute(node, 'name')}` + + ` as ${pointer} to the layer ` + + `${this.core.getAttribute(layerNode, 'name')}`); + }); + }; + + + ImportKeras.prototype._addFunctionNode = function (layerNode, config, pointer){ + const baseNodeName = (typeof config[pointer] === 'string' ? config[pointer] : config[pointer].class_name); + let configurableNode = this.core.createNode({ + parent: layerNode, + base: this.META[this._getMetaTypeForClass(baseNodeName)] + }); + this.logger.debug(`Added ${this.core.getAttribute(configurableNode, 'name')} as` + + ` ${pointer} to the layer ${this.core.getAttribute(layerNode, 'name')}`); + let validArgumentsForThisNode = this.core.getValidAttributeNames(configurableNode); + let configForAddedNode = config[pointer].config; + if (validArgumentsForThisNode && configForAddedNode) { + validArgumentsForThisNode.forEach((arg) => { + if (configForAddedNode[arg]) + this.core.setAttribute(configurableNode, arg, + this._toPythonType(configForAddedNode[arg])); + }); + } + return configurableNode; + }; + + // This method is used to convert javascript arrays/booleans to a + // list(python)/boolean in string Representation. Needed for + // Code generation. + ImportKeras.prototype._toPythonType = function (obj) { + if (obj == null) { + return 'None'; + } + if (obj instanceof Array) { + return '(' + obj.map((val) => { + return this._toPythonType(val); + }).join(', ') + ')'; + } else if (typeof obj === 'boolean') { + return obj ? 'True' : 'False'; + } else { + return obj; + } + }; + + // This method is used to convert various classes from the + // keras JSON to deepforge meta Nodes + ImportKeras.prototype._getMetaTypeForClass = function (kerasClass) { + let classMap = ModelMaps.CLASS_MAP; + if (Object.keys(classMap).indexOf(kerasClass) > -1) { + return classMap[kerasClass]; + } else { + return kerasClass; + } + }; + + // Change the model converts some JSON + // layer attributes names (from keras) to the correct + // attribute name for deepforge-keras nodes + ImportKeras.prototype._jsonConfigToNodeAttr = function (orgName) { + let argMap = ModelMaps.ARGUMENTS_MAP; + if (Object.keys(argMap).indexOf(orgName) > -1) { + return argMap[orgName]; + } else { + return orgName; + } + }; + + /**********************The functions below Add Connections between the Layers**************/ + ImportKeras.prototype.addConnections = async function () { + // this._findNodeByName(); + let layers = this.modelInfo.layers; + let layerInputConnections = {}; + let layerOutputConnections = {}; + let connections = null; + layers.forEach((layer) => { + layerInputConnections[layer.name] = []; + layerOutputConnections[layer.name] = []; + }); + + layers.forEach((layer) => { + if (layer.inbound_nodes.length > 0) { + connections = layer.inbound_nodes; + connections.forEach((connection) => { + + if (this._layerNameExists(connection)) { + layerInputConnections[layer.name].push(connection); + layerOutputConnections[connection].push(layer.name); + } + }); + + } + }); + + await this._updateConnections(layerInputConnections); + }; + + + ImportKeras.prototype._layerNameExists = function (layerName) { + let allLayerNames = this.modelInfo.layers.map((layer) => { + return layer.name; + }); + + return allLayerNames.indexOf(layerName) > -1; + }; + + ImportKeras.prototype._updateConnections = function (inputs) { + let allLayerNames = Object.keys(inputs); + return Promise.all(allLayerNames.map((layerName) => { + let dstLayer = this.layerInfo[layerName]; + let srcs = inputs[layerName]; + return Promise.all(srcs.map((src, index) => { + return this._connectLayers(this.layerInfo[src], dstLayer, index); + })); + })); + }; + + ImportKeras.prototype._connectLayers = async function (srcLayer, dstLayer, index) { + + // FIXME: Do we really want to always be connecting to the *first* input/output? + let srcPort = (await this.getOrderedMembers(srcLayer, 'outputs'))[0]; + let dstPort = (await this.getOrderedMembers(dstLayer, 'inputs'))[0]; + + if (dstPort && srcPort) { + this.core.addMember(dstPort, 'source', srcPort); + this.core.setMemberRegistry(dstPort, + 'source', + this.core.getPath(srcPort), + 'position', {x: 100, y: 100}); + this.core.setMemberAttribute(dstPort, 'source', + this.core.getPath(srcPort), + 'index', index); + this.logger.debug(`Connected ${this.core.getAttribute(srcLayer, 'name')} ` + + `with ${this.core.getAttribute(dstLayer, 'name')} as input ${index}`); + } + }; + + ImportKeras.prototype.getOrderedMembers = async function (node, setName) { + const members = await this.core.loadMembers(node, setName); + + members.sort((m1, m2) => { + const index1 = this.getMemberIndex(node, setName, m1); + const index2 = this.getMemberIndex(node, setName, m2); + return index1 < index2 ? -1 : 1; + }); + + return members; + }; + + ImportKeras.prototype.getMemberIndex = function (node, setName, member) { + const path = this.core.getPath(member); + return this.core.getMemberAttribute(node, setName, path, 'index'); + }; + + return ImportKeras; +}); diff --git a/src/plugins/ImportKeras/metadata.json b/src/plugins/ImportKeras/metadata.json new file mode 100644 index 0000000..862c815 --- /dev/null +++ b/src/plugins/ImportKeras/metadata.json @@ -0,0 +1,29 @@ +{ + "id": "ImportKeras", + "name": "ImportKeras", + "version": "0.1.0", + "description": "", + "icon": { + "class": "glyphicon glyphicon-download-alt", + "src": "" + }, + "disableServerSideExecution": false, + "disableBrowserSideExecution": false, + "dependencies": [], + "writeAccessRequired": false, + "configStructure": [{ + "name": "srcModel", + "displayName": "Keras Model JSON File", + "description": "The Keras model JSON to import.", + "valueType": "asset", + "readOnly": false + }, + { + "name": "archName", + "displayName": "Model Name", + "description": "Name of the imported model", + "valueType": "string", + "readOnly": false + } + ] +} \ No newline at end of file diff --git a/src/plugins/ImportKeras/utils/JSONModelMaps.js b/src/plugins/ImportKeras/utils/JSONModelMaps.js new file mode 100644 index 0000000..c490286 --- /dev/null +++ b/src/plugins/ImportKeras/utils/JSONModelMaps.js @@ -0,0 +1,27 @@ +/*globals define */ +define([], function() { + const ModelMaps = {}; + + ModelMaps.CLASS_MAP = { + InputLayer: 'Input', + L1L2: 'l1_l2' + }; + + ModelMaps.ARGUMENTS_MAP = { + batch_shape: 'batch_input_shape' + }; + + ModelMaps.ModelTypes = { + sequential : 'Sequential', + functional : 'Model' + }; + + ModelMaps.AbstractLayerTypeMapping = { + Activation: 'activation', + ActivityRegularization: 'activity_regularizer' + }; + + + return ModelMaps; + +}); \ No newline at end of file diff --git a/src/plugins/ImportKeras/utils/json-model-parser.js b/src/plugins/ImportKeras/utils/json-model-parser.js new file mode 100644 index 0000000..fcff5b1 --- /dev/null +++ b/src/plugins/ImportKeras/utils/json-model-parser.js @@ -0,0 +1,161 @@ +/*globals define*/ +define(['./JSONModelMaps'], function (JSONModelMaps) { + const ModelParser = { + flatten: flatten + }; + + /* + This function will flatten nested models (i.e. a Model inside a model) + and create a simple array of all the layers that can be directly used by + the plugin + */ + function flatten(modelConfig) { + let alteredModelConfig = JSON.parse(JSON.stringify(modelConfig)); + let layersInfo = []; + let replacementInboundNodeKeys = {}; + flattenNestedModel(alteredModelConfig, layersInfo, replacementInboundNodeKeys); + alteredModelConfig.config.layers = layersInfo; + addInputLayer(alteredModelConfig); + inboundNodesToStringArray(alteredModelConfig); + replaceModelInboundKeyWithFirstLayer(alteredModelConfig, replacementInboundNodeKeys); + return alteredModelConfig; + } + + function flattenNestedModel(modelConfig, layersInfo = [], inboundNodeKeys = {}) { + let layers = modelConfig.config.layers; + if (layers) { + layers.forEach((layer, index, records) => { + if (isModel(layer)) { + addInboundNodesForSequential(layer); + let lastIndex = layer.config.layers.length - 1; + inboundNodeKeys[layer.name] = layer.config.layers[lastIndex].config.name; // Change model inbound to first layer in the model. + if (layer.inbound_nodes) { + layer.config.layers[0].inbound_nodes = layer.inbound_nodes; + } else { + if (records[index - 1]) { + layer.config.layers[0].inbound_nodes = records[index - 1].config.name; + } + else { + layer.config.layers[0].inbound_nodes = []; + } + } + flattenNestedModel(layer, layersInfo); + } else { + layersInfo.push(layer); + } + }); + } + } + + + function addInboundNodesForSequential(layersInfo) { + if (determineModelType(layersInfo) !== JSONModelMaps.ModelTypes.sequential) { + return; + } + layersInfo = layersInfo.config.layers; + for (let i = 0; i < layersInfo.length - 1; i++) { + layersInfo[i + 1].inbound_nodes = [layersInfo[i].config.name]; + if (i === 0) { + layersInfo[i].inbound_nodes = []; + layersInfo[i].name = layersInfo[i].config.name; + } + // This adds Consistency with the functional models, because + // the functional JSON file has duplicate name keys, + // one inside config and one at the top level + if (!layersInfo[i + 1].name) { + layersInfo[i + 1].name = layersInfo[i + 1].config.name; + } + } + } + + + function isModel(modelConfig) { + return Array.isArray(modelConfig.config.layers); + } + + + function addInputLayer(modelConfig) { + if (determineModelType(modelConfig) === JSONModelMaps.ModelTypes.sequential) { + let inputLayerToAdd = { + 'class_name': 'InputLayer', + 'config': { + 'batch_input_shape': modelConfig.config.layers[0].config.batch_input_shape, + 'dtype': 'float32', + 'name': 'input', + 'sparse': false + }, + 'name': 'input', + 'inbound_nodes': [] + }; + + delete modelConfig.config.layers[0].config.batch_input_shape; + modelConfig.config.layers.splice(0, 0, inputLayerToAdd); + addInboundNodesForSequential(modelConfig); + } + } + + // Determine whether the model is 'Sequential' Or 'Functional' + // Its necessary because 'Sequential' Models do not have the property inbound_nodes + // In their layer so, it should be added externally + // Cases for a sequential model: + // 1. The model has an attribute called class_name and is equal to 'Sequential' + // 2. The model has an no attribute inbound_nodes + function determineModelType(model) { + if (model.class_name && model.class_name === JSONModelMaps.ModelTypes.sequential) { + return JSONModelMaps.ModelTypes.sequential; + } + let layers = model.config.layers; + if (layers) { + for (let i = 0; i < layers.length; i++) { + if (!layers[i].inbound_nodes) { + return JSONModelMaps.ModelTypes.sequential; + } + } + } + return JSONModelMaps.ModelTypes.functional; + } + + + // After getting flattened layers, change from + function inboundNodesToStringArray(modelConfig) { + if (determineModelType(modelConfig) === JSONModelMaps.ModelTypes.sequential) { + return; + } + let layers = modelConfig.config.layers; + layers.forEach((layer) => { + + if (layer.inbound_nodes[0] && layer.inbound_nodes[0][0] && layer.inbound_nodes[0][0] instanceof Array) { + let inBoundNodesArr = layer.inbound_nodes[0]; + let inBoundNodesNames = []; + for (let i = 0; i < inBoundNodesArr.length; i++) { + inBoundNodesNames.push(inBoundNodesArr[i][0]); + //ToDo: Implement Logic for Custom Layers + } + layer.inbound_nodes = inBoundNodesNames; + } + + }); + + + } + + function replaceModelInboundKeyWithFirstLayer(modelInfo, replacementLayerPairs) { + let replacementKeys = Object.keys(replacementLayerPairs); + let layers = modelInfo.config.layers; + if (replacementKeys.length > 0) { + replacementKeys.forEach(key => { + for (let i = 0; i < layers.length; i++) { + let inboundNodesArray = layers[i].inbound_nodes; + inboundNodesArray.forEach((node, index, records) => { + if (node === key) { + records[index] = replacementLayerPairs[key]; + } + }); + } + }); + } + } + + return ModelParser; + +}); \ No newline at end of file diff --git a/test/integration/ImportArchitectureCode/ImportedArchitectureCode.spec.js b/test/integration/ImportArchitectureCode/ImportedArchitectureCode.spec.js new file mode 100644 index 0000000..709ad8b --- /dev/null +++ b/test/integration/ImportArchitectureCode/ImportedArchitectureCode.spec.js @@ -0,0 +1,128 @@ +/*eslint-env node, mocha*/ +'use strict'; + +describe('Imported JSON to Code', function () { + const testFixture = require('../../globals'); + const requrireJs = require('webgme').requirejs; + const BlobClient = requrireJs('webgme-engine/src/server/middleware/blob/BlobClientWithFSBackend'), + fs = require('fs'), + {promisify} = require('util'), + assert = require('assert'), + gmeConfig = testFixture.getGmeConfig(), + executePython = testFixture.executePython, + path = testFixture.path, + logger = testFixture.logger.fork('ImportedArchitectureToCode'), + PluginCliManager = testFixture.WebGME.PluginCliManager, + SEED_DIR = path.join(__dirname, '..', '..', '..', 'src', 'seeds'), + manager = new PluginCliManager(null, logger, gmeConfig), + projectName = 'testProject', + ImportPluginName = 'ImportKeras', + CodeGenerationPluginName = 'GenerateKeras', + blobClient = new BlobClient(gmeConfig, logger), + JSON_DIR = path.join(__dirname, '../../test-cases/modelJsons/'); + + let project, + gmeAuth, + awaitableLoadObject, + storage, + commitHash, + importPlugin, + codeGenerationPlugin; + + before(async function () { + gmeAuth = await testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName); + storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth); + await storage.openDatabase(); + const importParam = { + projectSeed: path.join(SEED_DIR, 'keras', 'keras.webgmex'), + projectName: projectName, + branchName: 'master', + logger: logger, + gmeConfig: gmeConfig + }; + const importResult = await testFixture.importProject(storage, importParam); + project = importResult.project; + commitHash = importResult.commitHash; + awaitableLoadObject = promisify(project.loadObject); + + await project.createBranch('test', commitHash); + importPlugin = await manager.initializePlugin(ImportPluginName); + codeGenerationPlugin = await manager.initializePlugin(CodeGenerationPluginName); + const context = { + project: project, + commitHash: commitHash, + branchName: 'test', + activeNode: '' + }; + await manager.configurePlugin(importPlugin, {}, context); + await manager.configurePlugin(codeGenerationPlugin, {}, context); + }); + + after(async function () { + await storage.closeDatabase(); + await gmeAuth.unload(); + }); + + let modelsToTest = fs.readdirSync(JSON_DIR).filter((targetFile) => { + return targetFile.endsWith('.json'); + }); + + // let modelsToTest = ['sequential_dense.json']; + + modelsToTest.forEach((modelJSON) => { + describe(`Import JSON and generate Code For ${modelJSON}`, function () { + let generatedCode; + before(async function () { + generatedCode = await ImportJSONAndGetGeneratedCode(modelJSON); + }); + + it(`should run the python code generated for ${modelJSON}`, () => { + let execResult = executePython(generatedCode); + assert(execResult.success); + }).timeout(5000); + }); + }); + + + /** This function runs ImportKeras, followed by GenerateKeras + * @return {string} + */ + const ImportJSONAndGetGeneratedCode = async function(fileName){ + let executePlugin = promisify(manager.executePlugin), + pluginConfig = {}, + context = { + project: project, + activeNode: '', + branchName: 'test', + commitHash: commitHash, + namespace: '' + }; + let data = fs.readFileSync(path.join(JSON_DIR, fileName), 'utf-8'); + + pluginConfig.srcModel = await blobClient.putFile(fileName, data); + await executePlugin(ImportPluginName, pluginConfig, context); + + let newBranchHash = await project.getBranchHash('test'); + commitHash = newBranchHash; + let newCommitObj = await awaitableLoadObject(newBranchHash); + + let newRootNode = await importPlugin.core.loadRoot(newCommitObj.root); + const addedArchitectureNode = (await importPlugin.core.loadChildren(newRootNode)).filter((node) => { + return importPlugin.core.getAttribute(node, 'name') === fileName.replace('.json', ''); + })[0]; + + context = { + project: project, + commitHash: commitHash, + branchName: 'test', + activeNode: importPlugin.core.getPath(addedArchitectureNode), + namespace: '' + }; + pluginConfig = {}; + let generateCodePluginResult = await executePlugin(CodeGenerationPluginName, pluginConfig, context); + assert(generateCodePluginResult.success); + const codeHash = generateCodePluginResult.artifacts[0]; + const codeObj = await blobClient.getObject(codeHash); + return String.fromCharCode.apply(null, new Uint8Array(codeObj)); + }; +}); \ No newline at end of file diff --git a/test/plugins/ImportKeras/ImportKeras.spec.js b/test/plugins/ImportKeras/ImportKeras.spec.js new file mode 100644 index 0000000..6fd4c4c --- /dev/null +++ b/test/plugins/ImportKeras/ImportKeras.spec.js @@ -0,0 +1,180 @@ +/*eslint-env node, mocha*/ +describe('ImportKeras', function () { + const testFixture = require('../../globals'), + BlobClient = require('webgme-engine/src/server/middleware/blob/BlobClientWithFSBackend'), + fs = require('fs'), + {promisify} = require('util'), + assert = require('assert'), + gmeConfig = testFixture.getGmeConfig(), + expect = testFixture.expect, + path = testFixture.path, + logger = testFixture.logger.fork('ImportKeras'), + PluginCliManager = testFixture.WebGME.PluginCliManager, + SEED_DIR = path.join(__dirname, '..', '..', '..', 'src', 'seeds'), + manager = new PluginCliManager(null, logger, gmeConfig), + projectName = 'testProject', + pluginName = 'ImportKeras', + blobClient = new BlobClient(gmeConfig, logger), + JSON_DIR = path.join(__dirname, '../../test-cases/modelJsons/'); + + let project, + gmeAuth, + awaitableLoadObject, + storage, + commitHash, + plugin; + + before(async function () { + gmeAuth = await testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName); + storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth); + await storage.openDatabase(); + const importParam = { + projectSeed: path.join(SEED_DIR, 'keras', 'keras.webgmex'), + projectName: projectName, + branchName: 'master', + logger: logger, + gmeConfig: gmeConfig + }; + const importResult = await testFixture.importProject(storage, importParam); + project = importResult.project; + commitHash = importResult.commitHash; + awaitableLoadObject = promisify(project.loadObject); + + await project.createBranch('test', commitHash); + plugin = await manager.initializePlugin(pluginName); + const context = { + project: project, + commitHash: commitHash, + branchName: 'test', + activeNode: '' + }; + await manager.configurePlugin(plugin, {}, context); + }); + + after(async function () { + await storage.closeDatabase(); + await gmeAuth.unload(); + }); + + describe('without-json-file', function () { + it('should fail without a JSON file', async () => { + let manager = new PluginCliManager(null, logger, gmeConfig), + context = { + project: project, + commitHash: commitHash, + branchName: 'test', + activeNode: '' + }, + runPlugin = promisify(manager.executePlugin); + try { + let pluginResult = await runPlugin(pluginName, context, context); + assert(!pluginResult.success); + } catch (err) { + expect(err.message).to.equal('Keras Json Not Provided'); + } + + let branchHash = await project.getBranchHash('test'); + expect(branchHash).to.equal(commitHash); + }); + }); + + const runPluginTest = async (modelName) => { + let manager = new PluginCliManager(null, logger, gmeConfig), + runPlugin = promisify(manager.executePlugin), + pluginConfig = {}, + context = { + project: project, + activeNode: '', + branchName: 'test' + }; + + let data = fs.readFileSync(path.join(JSON_DIR, modelName), 'utf-8'); + + assert(data != null); + + let branchHash = await project.getBranchHash('test'); + let commitObject = await awaitableLoadObject(branchHash); + let rootNode = await plugin.core.loadRoot(commitObject.root); + + assert(rootNode != null); + + let childrenPaths = (await plugin.core.loadChildren(rootNode)).map(plugin.core.getPath); + pluginConfig.srcModel = await blobClient.putFile(modelName, data); + let pluginResult = await runPlugin(pluginName, pluginConfig, context); + + assert(pluginResult != null && pluginResult.success === true); + assert(rootNode != null); + + let newBranchHash = await project.getBranchHash('test'); + commitHash = newBranchHash; + let newCommitObj = await awaitableLoadObject(newBranchHash); + + let newRootNode = await plugin.core.loadRoot(newCommitObj.root); + let newChildrenPaths = (await plugin.core.loadChildren(newRootNode)).map(plugin.core.getPath); + assert(newChildrenPaths.length === childrenPaths.length + 1); + }; + + describe('test-cases', function () { + const modelsToTest = fs.readdirSync(JSON_DIR).filter((targetFile) => { + return targetFile.endsWith('.json'); + }); + + modelsToTest.forEach((model) => { + it(`should run plugin for ${model}`, async () => { + await runPluginTest(model); + }); + }); + + }); + + describe('test-connections', function () { + // For name's sake + const modelToTest = path.join(JSON_DIR, 'sequential_conv_mnist.json'); + const layerNames = ['input', 'conv2d_1', 'conv2d_2', 'max_pooling2d_1', + 'dropout_6', 'flatten_1', 'dense_9', 'dropout_7', 'dense_10']; + + it('should run plugin and connect layers correctly', async () => { + const manager = new PluginCliManager(null, logger, gmeConfig), + runPlugin = promisify(manager.executePlugin), + pluginConfig = {}, + context = { + project: project, + activeNode: '', + branchName: 'test' + }; + const data = fs.readFileSync(modelToTest, 'utf-8'); + + pluginConfig.srcModel = await blobClient.putFile(modelToTest, data); + const pluginResult = await runPlugin(pluginName, pluginConfig, context); + + assert(pluginResult != null); + assert(pluginResult.success === true); + + commitHash = await project.getBranchHash('test'); + const commitObj = await awaitableLoadObject(commitHash); + + const rootNode = await plugin.core.loadRoot(commitObj.root); + const children = (await plugin.core.loadChildren(rootNode)) + .filter((node) => { + return plugin.core.getAttribute(node, 'name') + === modelToTest.replace('.json', ''); + }); + assert(children.length === 1); + const layers = await plugin.core.loadChildren(children[0]); + let layersMap = {}; + layers.map(node => { + layersMap[plugin.core.getAttribute(node, 'name')] = node; + }); + let inputSourcePort, destinationMembers, sourceMembers; + + for(let i = 1; i < layerNames.length; i++){ + inputSourcePort = await plugin.core.loadMembers(layersMap[layerNames[i]], 'inputs'); + destinationMembers = await plugin.core.loadMembers(layersMap[layerNames[i-1]], 'outputs'); + sourceMembers = await plugin.core.loadMembers(inputSourcePort[0], 'source'); + assert(destinationMembers[0]); + assert(sourceMembers[0]); + assert(sourceMembers[0] === destinationMembers[0]); + } + }); + }); +}); \ No newline at end of file diff --git a/test/plugins/json-model-parser.spec.js b/test/plugins/json-model-parser.spec.js new file mode 100644 index 0000000..7c23add --- /dev/null +++ b/test/plugins/json-model-parser.spec.js @@ -0,0 +1,162 @@ +describe('json-model-parser', function () { + 'use strict'; + const requireJs = require('webgme').requirejs; + const fs = require('fs'); + const path = require('path'); + const assert = require('assert'); + const ModelParser = requireJs('plugin/ImportKeras/ImportKeras/utils/json-model-parser'); + + describe('basic-sequential', function () { + let sequentialModelConfig = null; + let layerConfigProperties = null; + before(() => { + layerConfigProperties = [ + 'bias_regularizer', 'dtype', 'bias_constraint', + 'kernel_regularizer', 'name', 'trainable', 'bias_initializer', + 'activity_regularizer', 'kernel_constraint', + ]; + let sequentialModelTxt = fs.readFileSync(path.resolve(__dirname, + '../test-cases/modelJsons/sequential_dense.json')); + sequentialModelConfig = JSON.parse(sequentialModelTxt); + }); + + it('It should parse the sequential model, with no nested models', () => { + let flattenedConfig = ModelParser.flatten(sequentialModelConfig); + assert.equal(flattenedConfig.config.layers.length, + sequentialModelConfig.config.layers.length + 1); + // Test all layers are imported correctly + for (let i = 1; i < flattenedConfig.config.layers.length; i++) { + assert.equal(flattenedConfig.config.layers[i].name, + sequentialModelConfig.config.layers[i - 1].config.name); + assert(Object.prototype.hasOwnProperty.call(flattenedConfig.config.layers[i],'inbound_nodes')); + assert.deepEqual(flattenedConfig.config.layers[i].config.bias_regularizer); + } + // Check the layer config properties for equality + layerConfigProperties.forEach((prop) => { + for (let i = 1; i < flattenedConfig.config.layers.length; i++) { + if (flattenedConfig.config.layers[i].config[prop]) { + assert.deepEqual(flattenedConfig.config.layers[i].config[prop], + sequentialModelConfig.config.layers[i - 1].config[prop]); + } + } + }); + + // Check the properties of the added InputLayer + assert.equal(flattenedConfig.config.layers[0].class_name, 'InputLayer'); + assert.deepEqual(flattenedConfig.config.layers[0].config.batch_input_shape, + sequentialModelConfig.config.layers[0].config.batch_input_shape); + + }); + }); + + describe('nested-sequential', function () { + let nestedSequentialModelConfig = null; + before(() => { + let nestedSequentialModelTxt = fs.readFileSync(path.resolve(__dirname, + '../test-cases/modelJsons/sequential_nested.json')); + nestedSequentialModelConfig = JSON.parse(nestedSequentialModelTxt); + }); + + + it('Should flatten the nested sequential model', function () { + let flattenedConfig = ModelParser.flatten(nestedSequentialModelConfig); + assert.equal(flattenedConfig.config.layers.length, 4); + assert.equal(flattenedConfig.config.layers[0].class_name, 'InputLayer'); + assert.deepEqual(flattenedConfig.config.layers[0].config.batch_input_shape, + nestedSequentialModelConfig.config.layers[0].config.batch_input_shape); + assert.deepEqual(flattenedConfig.config.layers[2].class_name, + nestedSequentialModelConfig.config.layers[1] + .config.layers[0].config.layers[0].class_name); + }); + + + }); + + describe('sequential-inside-functional', function () { + let nestedFunctionalModelConfig = null; + before(() => { + let nestedFunctionalModelTxt = fs.readFileSync(path.resolve(__dirname, + '../test-cases/modelJsons/functional_memnn_babi.json')); + nestedFunctionalModelConfig = JSON.parse(nestedFunctionalModelTxt); + }); + + it('should flatten the sequential inside functional model', function () { + let flattenedConfig = ModelParser.flatten(nestedFunctionalModelConfig); + + // Tests for layers + assert.deepEqual(flattenedConfig.config.layers[0], nestedFunctionalModelConfig.config.layers[0]); + assert.deepEqual(flattenedConfig.config.layers[1], nestedFunctionalModelConfig.config.layers[1]); + assert.deepEqual(flattenedConfig.config.layers[2].config, + nestedFunctionalModelConfig.config.layers[2].config.layers[0].config); + assert.deepEqual(flattenedConfig.config.layers[3].config, + nestedFunctionalModelConfig.config.layers[2].config.layers[1].config); + assert.deepEqual(flattenedConfig.config.layers[4].config, + nestedFunctionalModelConfig.config.layers[3].config.layers[0].config); + assert.deepEqual(flattenedConfig.config.layers[5].config, + nestedFunctionalModelConfig.config.layers[3].config.layers[1].config); + assert.deepEqual(flattenedConfig.config.layers[6].config, + nestedFunctionalModelConfig.config.layers[4].config); + assert.deepEqual(flattenedConfig.config.layers[7].config, + nestedFunctionalModelConfig.config.layers[5].config); + assert.deepEqual(flattenedConfig.config.layers[8].config, + nestedFunctionalModelConfig.config.layers[6].config.layers[0].config); + assert.deepEqual(flattenedConfig.config.layers[9].config, + nestedFunctionalModelConfig.config.layers[6].config.layers[1].config); + assert.deepEqual(flattenedConfig.config.layers[10].config, + nestedFunctionalModelConfig.config.layers[7].config); + assert.deepEqual(flattenedConfig.config.layers[11].config, + nestedFunctionalModelConfig.config.layers[8].config); + let i = 12, j = 9; + while (i < flattenedConfig.config.layers.length) { + assert.deepEqual(flattenedConfig.config.layers[i].config, + nestedFunctionalModelConfig.config.layers[j].config); + i++; + j++; + } + + // Tests for inbound nodes, tested using model_graph. + assert.deepEqual(flattenedConfig.config.layers[2].inbound_nodes, ['input_3']); + assert.deepEqual(flattenedConfig.config.layers[3].inbound_nodes, ['embedding_3']); + assert.deepEqual(flattenedConfig.config.layers[4].inbound_nodes, ['input_4']); + assert.deepEqual(flattenedConfig.config.layers[5].inbound_nodes, ['embedding_5']); + assert.deepEqual(flattenedConfig.config.layers[6].inbound_nodes, ['dropout_1', 'dropout_3']); + assert.deepEqual(flattenedConfig.config.layers[7].inbound_nodes, ['dot_1']); + assert.deepEqual(flattenedConfig.config.layers[8].inbound_nodes, ['input_3']); + assert.deepEqual(flattenedConfig.config.layers[9].inbound_nodes, ['embedding_4']); + assert.deepEqual(flattenedConfig.config.layers[10].inbound_nodes, ['activation_1', 'dropout_2']); + assert.deepEqual(flattenedConfig.config.layers[11].inbound_nodes, ['add_1']); + assert.deepEqual(flattenedConfig.config.layers[12].inbound_nodes, ['permute_1', 'dropout_3']); + assert.deepEqual(flattenedConfig.config.layers[13].inbound_nodes, ['concatenate_2']); + assert.deepEqual(flattenedConfig.config.layers[14].inbound_nodes, ['lstm_3']); + assert.deepEqual(flattenedConfig.config.layers[15].inbound_nodes, ['dropout_4']); + assert.deepEqual(flattenedConfig.config.layers[16].inbound_nodes, ['dense_2']); + }); + }); + + describe('redshift-convolutional-model', function () { + let redshiftModelConfig = null; + before(() => { + let redshiftModelTxt = fs.readFileSync(path.resolve(path.resolve(__dirname, + '../test-cases/modelJsons/redshiftModel.json'))); + redshiftModelConfig = JSON.parse(redshiftModelTxt); + }); + + it('should flatten the model and change its inbound_nodes config', function () { + let flattenedRedshiftConfig = ModelParser.flatten(redshiftModelConfig); + // Test the layer config + for(let i = 0; i < flattenedRedshiftConfig.config.layers.length; i++){ + let flatLayer = flattenedRedshiftConfig.config.layers[i]; + let normalLayer = redshiftModelConfig.config.layers[i]; + // Test the layer config + assert.deepEqual(flatLayer.config, normalLayer.config); + // Tests for inbound nodes, it should be iterable, since the model is functional and not nested. + if(normalLayer.inbound_nodes.length > 0){ + normalLayer.inbound_nodes[0].forEach((node, index) =>{ + assert.deepEqual(flatLayer.inbound_nodes[index], node[0]); + }); + } + } + + }); + }); +}); diff --git a/test/test-cases/modelJsons/functional_memnn_babi.json b/test/test-cases/modelJsons/functional_memnn_babi.json new file mode 100644 index 0000000..d3864fb --- /dev/null +++ b/test/test-cases/modelJsons/functional_memnn_babi.json @@ -0,0 +1,493 @@ +{ + "class_name": "Model", + "keras_version": "2.3.0", + "config": { + "name": "model_2", + "layers": [ + { + "name": "input_3", + "class_name": "InputLayer", + "config": { + "name": "input_3", + "sparse": false, + "batch_input_shape": [ + null, + 68 + ], + "dtype": "float32" + }, + "inbound_nodes": [] + }, + { + "name": "input_4", + "class_name": "InputLayer", + "config": { + "name": "input_4", + "sparse": false, + "batch_input_shape": [ + null, + 4 + ], + "dtype": "float32" + }, + "inbound_nodes": [] + }, + { + "name": "sequential_1", + "class_name": "Sequential", + "config": { + "name": "sequential_1", + "layers": [ + { + "class_name": "Embedding", + "config": { + "input_dim": 22, + "input_length": null, + "embeddings_initializer": { + "class_name": "RandomUniform", + "config": { + "minval": -0.05, + "seed": null, + "maxval": 0.05 + } + }, + "activity_regularizer": null, + "dtype": "float32", + "batch_input_shape": [ + null, + null + ], + "mask_zero": false, + "name": "embedding_3", + "trainable": true, + "embeddings_constraint": null, + "embeddings_regularizer": null, + "output_dim": 64 + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.3, + "name": "dropout_1", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + } + ] + }, + "inbound_nodes": [ + [ + [ + "input_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "sequential_3", + "class_name": "Sequential", + "config": { + "name": "sequential_3", + "layers": [ + { + "class_name": "Embedding", + "config": { + "input_dim": 22, + "input_length": 4, + "embeddings_initializer": { + "class_name": "RandomUniform", + "config": { + "minval": -0.05, + "seed": null, + "maxval": 0.05 + } + }, + "activity_regularizer": null, + "dtype": "float32", + "batch_input_shape": [ + null, + 4 + ], + "mask_zero": false, + "name": "embedding_5", + "trainable": true, + "embeddings_constraint": null, + "embeddings_regularizer": null, + "output_dim": 64 + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.3, + "name": "dropout_3", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + } + ] + }, + "inbound_nodes": [ + [ + [ + "input_4", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "dot_1", + "class_name": "Dot", + "config": { + "name": "dot_1", + "trainable": true, + "normalize": false, + "axes": [ + 2, + 2 + ], + "dtype": "float32" + }, + "inbound_nodes": [ + [ + [ + "sequential_1", + 1, + 0, + {} + ], + [ + "sequential_3", + 1, + 0, + {} + ] + ] + ] + }, + { + "name": "activation_1", + "class_name": "Activation", + "config": { + "name": "activation_1", + "trainable": true, + "activation": "softmax", + "dtype": "float32" + }, + "inbound_nodes": [ + [ + [ + "dot_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "sequential_2", + "class_name": "Sequential", + "config": { + "name": "sequential_2", + "layers": [ + { + "class_name": "Embedding", + "config": { + "input_dim": 22, + "input_length": null, + "embeddings_initializer": { + "class_name": "RandomUniform", + "config": { + "minval": -0.05, + "seed": null, + "maxval": 0.05 + } + }, + "activity_regularizer": null, + "dtype": "float32", + "batch_input_shape": [ + null, + null + ], + "mask_zero": false, + "name": "embedding_4", + "trainable": true, + "embeddings_constraint": null, + "embeddings_regularizer": null, + "output_dim": 4 + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.3, + "name": "dropout_2", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + } + ] + }, + "inbound_nodes": [ + [ + [ + "input_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "add_1", + "class_name": "Add", + "config": { + "name": "add_1", + "trainable": true, + "dtype": "float32" + }, + "inbound_nodes": [ + [ + [ + "activation_1", + 0, + 0, + {} + ], + [ + "sequential_2", + 1, + 0, + {} + ] + ] + ] + }, + { + "name": "permute_1", + "class_name": "Permute", + "config": { + "name": "permute_1", + "dims": [ + 2, + 1 + ], + "trainable": true, + "dtype": "float32" + }, + "inbound_nodes": [ + [ + [ + "add_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "concatenate_2", + "class_name": "Concatenate", + "config": { + "name": "concatenate_2", + "trainable": true, + "axis": -1, + "dtype": "float32" + }, + "inbound_nodes": [ + [ + [ + "permute_1", + 0, + 0, + {} + ], + [ + "sequential_3", + 1, + 0, + {} + ] + ] + ] + }, + { + "name": "lstm_3", + "class_name": "LSTM", + "config": { + "recurrent_constraint": null, + "unit_forget_bias": true, + "units": 32, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "recurrent_regularizer": null, + "implementation": 2, + "stateful": false, + "bias_regularizer": null, + "unroll": false, + "dtype": "float32", + "name": "lstm_3", + "trainable": true, + "go_backwards": false, + "kernel_constraint": null, + "use_bias": true, + "return_state": false, + "recurrent_activation": "sigmoid", + "activity_regularizer": null, + "dropout": 0.0, + "bias_constraint": null, + "recurrent_initializer": { + "class_name": "Orthogonal", + "config": { + "seed": null, + "gain": 1.0 + } + }, + "activation": "tanh", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "kernel_regularizer": null, + "recurrent_dropout": 0.0, + "return_sequences": false + }, + "inbound_nodes": [ + [ + [ + "concatenate_2", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "dropout_4", + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.3, + "name": "dropout_4", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + }, + "inbound_nodes": [ + [ + [ + "lstm_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "dense_2", + "class_name": "Dense", + "config": { + "units": 22, + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "dense_2", + "trainable": true, + "kernel_constraint": null, + "activation": "linear", + "use_bias": true + }, + "inbound_nodes": [ + [ + [ + "dropout_4", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "activation_2", + "class_name": "Activation", + "config": { + "name": "activation_2", + "trainable": true, + "activation": "softmax", + "dtype": "float32" + }, + "inbound_nodes": [ + [ + [ + "dense_2", + 0, + 0, + {} + ] + ] + ] + } + ], + "output_layers": [ + [ + "activation_2", + 0, + 0 + ] + ], + "input_layers": [ + [ + "input_3", + 0, + 0 + ], + [ + "input_4", + 0, + 0 + ] + ] + }, + "backend": "tensorflow" +} \ No newline at end of file diff --git a/test/test-cases/modelJsons/functional_rnn_babi.json b/test/test-cases/modelJsons/functional_rnn_babi.json new file mode 100644 index 0000000..50f6774 --- /dev/null +++ b/test/test-cases/modelJsons/functional_rnn_babi.json @@ -0,0 +1,317 @@ +{ + "class_name": "Model", + "keras_version": "2.3.0", + "config": { + "name": "model_1", + "layers": [ + { + "name": "input_1", + "class_name": "InputLayer", + "config": { + "name": "input_1", + "sparse": false, + "batch_input_shape": [ + null, + 552 + ], + "dtype": "int32" + }, + "inbound_nodes": [] + }, + { + "name": "input_2", + "class_name": "InputLayer", + "config": { + "name": "input_2", + "sparse": false, + "batch_input_shape": [ + null, + 5 + ], + "dtype": "int32" + }, + "inbound_nodes": [] + }, + { + "name": "embedding_1", + "class_name": "Embedding", + "config": { + "input_dim": 36, + "input_length": null, + "embeddings_initializer": { + "class_name": "RandomUniform", + "config": { + "minval": -0.05, + "seed": null, + "maxval": 0.05 + } + }, + "activity_regularizer": null, + "dtype": "float32", + "batch_input_shape": [ + null, + null + ], + "mask_zero": false, + "name": "embedding_1", + "trainable": true, + "output_dim": 50, + "embeddings_regularizer": null, + "embeddings_constraint": null + }, + "inbound_nodes": [ + [ + [ + "input_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "embedding_2", + "class_name": "Embedding", + "config": { + "input_dim": 36, + "input_length": null, + "embeddings_initializer": { + "class_name": "RandomUniform", + "config": { + "minval": -0.05, + "seed": null, + "maxval": 0.05 + } + }, + "activity_regularizer": null, + "dtype": "float32", + "batch_input_shape": [ + null, + null + ], + "mask_zero": false, + "name": "embedding_2", + "trainable": true, + "output_dim": 50, + "embeddings_regularizer": null, + "embeddings_constraint": null + }, + "inbound_nodes": [ + [ + [ + "input_2", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "lstm_1", + "class_name": "LSTM", + "config": { + "recurrent_constraint": null, + "unit_forget_bias": true, + "units": 100, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "recurrent_regularizer": null, + "implementation": 2, + "stateful": false, + "bias_regularizer": null, + "unroll": false, + "dtype": "float32", + "name": "lstm_1", + "trainable": true, + "go_backwards": false, + "kernel_constraint": null, + "use_bias": true, + "return_state": false, + "recurrent_activation": "sigmoid", + "activity_regularizer": null, + "dropout": 0.0, + "bias_constraint": null, + "recurrent_initializer": { + "class_name": "Orthogonal", + "config": { + "seed": null, + "gain": 1.0 + } + }, + "activation": "tanh", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "kernel_regularizer": null, + "recurrent_dropout": 0.0, + "return_sequences": false + }, + "inbound_nodes": [ + [ + [ + "embedding_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "lstm_2", + "class_name": "LSTM", + "config": { + "recurrent_constraint": null, + "unit_forget_bias": true, + "units": 100, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "recurrent_regularizer": null, + "implementation": 2, + "stateful": false, + "bias_regularizer": null, + "unroll": false, + "dtype": "float32", + "name": "lstm_2", + "trainable": true, + "go_backwards": false, + "kernel_constraint": null, + "use_bias": true, + "return_state": false, + "recurrent_activation": "sigmoid", + "activity_regularizer": null, + "dropout": 0.0, + "bias_constraint": null, + "recurrent_initializer": { + "class_name": "Orthogonal", + "config": { + "seed": null, + "gain": 1.0 + } + }, + "activation": "tanh", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "kernel_regularizer": null, + "recurrent_dropout": 0.0, + "return_sequences": false + }, + "inbound_nodes": [ + [ + [ + "embedding_2", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "concatenate_1", + "class_name": "Concatenate", + "config": { + "name": "concatenate_1", + "trainable": true, + "axis": -1, + "dtype": "float32" + }, + "inbound_nodes": [ + [ + [ + "lstm_1", + 0, + 0, + {} + ], + [ + "lstm_2", + 0, + 0, + {} + ] + ] + ] + }, + { + "name": "dense_1", + "class_name": "Dense", + "config": { + "units": 36, + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "dense_1", + "trainable": true, + "kernel_constraint": null, + "activation": "softmax", + "use_bias": true + }, + "inbound_nodes": [ + [ + [ + "concatenate_1", + 0, + 0, + {} + ] + ] + ] + } + ], + "output_layers": [ + [ + "dense_1", + 0, + 0 + ] + ], + "input_layers": [ + [ + "input_1", + 0, + 0 + ], + [ + "input_2", + 0, + 0 + ] + ] + }, + "backend": "tensorflow" +} \ No newline at end of file diff --git a/test/test-cases/modelJsons/redshiftModel.json b/test/test-cases/modelJsons/redshiftModel.json new file mode 100644 index 0000000..4fe617a --- /dev/null +++ b/test/test-cases/modelJsons/redshiftModel.json @@ -0,0 +1,2122 @@ +{ + "backend": "tensorflow", + "class_name": "RedShiftClassificationModel", + "config": { + "layers": [ + { + "class_name": "InputLayer", + "config": { + "batch_input_shape": [ + null, + 64, + 64, + 5 + ], + "dtype": "float32", + "name": "input_1", + "sparse": false + }, + "name": "input_1", + "inbound_nodes": [] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_1", + "strides": [ + 1, + 1 + ], + "filters": 64, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 5, + 5 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_1", + "inbound_nodes": [ + [ + [ + "input_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "AveragePooling2D", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "average_pooling2d_1", + "strides": [ + 2, + 2 + ], + "pool_size": [ + 2, + 2 + ], + "padding": "same" + }, + "name": "average_pooling2d_1", + "inbound_nodes": [ + [ + [ + "conv2d_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_2", + "strides": [ + 1, + 1 + ], + "filters": 48, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_2", + "inbound_nodes": [ + [ + [ + "average_pooling2d_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_3", + "strides": [ + 1, + 1 + ], + "filters": 48, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_3", + "inbound_nodes": [ + [ + [ + "average_pooling2d_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_4", + "strides": [ + 1, + 1 + ], + "filters": 48, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_4", + "inbound_nodes": [ + [ + [ + "average_pooling2d_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_5", + "strides": [ + 1, + 1 + ], + "filters": 64, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_5", + "inbound_nodes": [ + [ + [ + "average_pooling2d_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_6", + "strides": [ + 1, + 1 + ], + "filters": 64, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 3, + 3 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_6", + "inbound_nodes": [ + [ + [ + "conv2d_2", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_7", + "strides": [ + 1, + 1 + ], + "filters": 64, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 5, + 5 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_7", + "inbound_nodes": [ + [ + [ + "conv2d_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "AveragePooling2D", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "average_pooling2d_2", + "strides": [ + 1, + 1 + ], + "pool_size": [ + 2, + 2 + ], + "padding": "same" + }, + "name": "average_pooling2d_2", + "inbound_nodes": [ + [ + [ + "conv2d_4", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Concatenate", + "config": { + "trainable": true, + "axis": -1, + "dtype": "float32", + "name": "concatenate_1" + }, + "name": "concatenate_1", + "inbound_nodes": [ + [ + [ + "conv2d_5", + 0, + 0, + {} + ], + [ + "conv2d_6", + 0, + 0, + {} + ], + [ + "conv2d_7", + 0, + 0, + {} + ], + [ + "average_pooling2d_2", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_8", + "strides": [ + 1, + 1 + ], + "filters": 64, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_8", + "inbound_nodes": [ + [ + [ + "concatenate_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_9", + "strides": [ + 1, + 1 + ], + "filters": 64, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_9", + "inbound_nodes": [ + [ + [ + "concatenate_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_10", + "strides": [ + 1, + 1 + ], + "filters": 64, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_10", + "inbound_nodes": [ + [ + [ + "concatenate_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_11", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_11", + "inbound_nodes": [ + [ + [ + "concatenate_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_12", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 3, + 3 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_12", + "inbound_nodes": [ + [ + [ + "conv2d_8", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_13", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 5, + 5 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_13", + "inbound_nodes": [ + [ + [ + "conv2d_9", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "AveragePooling2D", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "average_pooling2d_3", + "strides": [ + 1, + 1 + ], + "pool_size": [ + 2, + 2 + ], + "padding": "same" + }, + "name": "average_pooling2d_3", + "inbound_nodes": [ + [ + [ + "conv2d_10", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Concatenate", + "config": { + "trainable": true, + "axis": -1, + "dtype": "float32", + "name": "concatenate_2" + }, + "name": "concatenate_2", + "inbound_nodes": [ + [ + [ + "conv2d_11", + 0, + 0, + {} + ], + [ + "conv2d_12", + 0, + 0, + {} + ], + [ + "conv2d_13", + 0, + 0, + {} + ], + [ + "average_pooling2d_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "AveragePooling2D", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "average_pooling2d_4", + "strides": [ + 2, + 2 + ], + "pool_size": [ + 2, + 2 + ], + "padding": "same" + }, + "name": "average_pooling2d_4", + "inbound_nodes": [ + [ + [ + "concatenate_2", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_14", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_14", + "inbound_nodes": [ + [ + [ + "average_pooling2d_4", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_15", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_15", + "inbound_nodes": [ + [ + [ + "average_pooling2d_4", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_16", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_16", + "inbound_nodes": [ + [ + [ + "average_pooling2d_4", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_17", + "strides": [ + 1, + 1 + ], + "filters": 128, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_17", + "inbound_nodes": [ + [ + [ + "average_pooling2d_4", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_18", + "strides": [ + 1, + 1 + ], + "filters": 128, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 3, + 3 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_18", + "inbound_nodes": [ + [ + [ + "conv2d_14", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_19", + "strides": [ + 1, + 1 + ], + "filters": 128, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 5, + 5 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_19", + "inbound_nodes": [ + [ + [ + "conv2d_15", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "AveragePooling2D", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "average_pooling2d_5", + "strides": [ + 1, + 1 + ], + "pool_size": [ + 2, + 2 + ], + "padding": "same" + }, + "name": "average_pooling2d_5", + "inbound_nodes": [ + [ + [ + "conv2d_16", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Concatenate", + "config": { + "trainable": true, + "axis": -1, + "dtype": "float32", + "name": "concatenate_3" + }, + "name": "concatenate_3", + "inbound_nodes": [ + [ + [ + "conv2d_17", + 0, + 0, + {} + ], + [ + "conv2d_18", + 0, + 0, + {} + ], + [ + "conv2d_19", + 0, + 0, + {} + ], + [ + "average_pooling2d_5", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_20", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_20", + "inbound_nodes": [ + [ + [ + "concatenate_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_21", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_21", + "inbound_nodes": [ + [ + [ + "concatenate_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_22", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_22", + "inbound_nodes": [ + [ + [ + "concatenate_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_23", + "strides": [ + 1, + 1 + ], + "filters": 128, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_23", + "inbound_nodes": [ + [ + [ + "concatenate_3", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_24", + "strides": [ + 1, + 1 + ], + "filters": 128, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 3, + 3 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_24", + "inbound_nodes": [ + [ + [ + "conv2d_20", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_25", + "strides": [ + 1, + 1 + ], + "filters": 128, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 5, + 5 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_25", + "inbound_nodes": [ + [ + [ + "conv2d_21", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "AveragePooling2D", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "average_pooling2d_6", + "strides": [ + 1, + 1 + ], + "pool_size": [ + 2, + 2 + ], + "padding": "same" + }, + "name": "average_pooling2d_6", + "inbound_nodes": [ + [ + [ + "conv2d_22", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Concatenate", + "config": { + "trainable": true, + "axis": -1, + "dtype": "float32", + "name": "concatenate_4" + }, + "name": "concatenate_4", + "inbound_nodes": [ + [ + [ + "conv2d_23", + 0, + 0, + {} + ], + [ + "conv2d_24", + 0, + 0, + {} + ], + [ + "conv2d_25", + 0, + 0, + {} + ], + [ + "average_pooling2d_6", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "AveragePooling2D", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "average_pooling2d_7", + "strides": [ + 2, + 2 + ], + "pool_size": [ + 2, + 2 + ], + "padding": "same" + }, + "name": "average_pooling2d_7", + "inbound_nodes": [ + [ + [ + "concatenate_4", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_26", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_26", + "inbound_nodes": [ + [ + [ + "average_pooling2d_7", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_27", + "strides": [ + 1, + 1 + ], + "filters": 92, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_27", + "inbound_nodes": [ + [ + [ + "average_pooling2d_7", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_28", + "strides": [ + 1, + 1 + ], + "filters": 128, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 1, + 1 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_28", + "inbound_nodes": [ + [ + [ + "average_pooling2d_7", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Conv2D", + "config": { + "dilation_rate": [ + 1, + 1 + ], + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "data_format": "channels_last", + "name": "conv2d_29", + "strides": [ + 1, + 1 + ], + "filters": 128, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "kernel_size": [ + 3, + 3 + ], + "activity_regularizer": null, + "padding": "same" + }, + "name": "conv2d_29", + "inbound_nodes": [ + [ + [ + "conv2d_26", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "AveragePooling2D", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "average_pooling2d_8", + "strides": [ + 1, + 1 + ], + "pool_size": [ + 2, + 2 + ], + "padding": "same" + }, + "name": "average_pooling2d_8", + "inbound_nodes": [ + [ + [ + "conv2d_27", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Concatenate", + "config": { + "trainable": true, + "axis": -1, + "dtype": "float32", + "name": "concatenate_5" + }, + "name": "concatenate_5", + "inbound_nodes": [ + [ + [ + "conv2d_28", + 0, + 0, + {} + ], + [ + "conv2d_29", + 0, + 0, + {} + ], + [ + "average_pooling2d_8", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Flatten", + "config": { + "trainable": true, + "data_format": "channels_last", + "dtype": "float32", + "name": "flatten_1" + }, + "name": "flatten_1", + "inbound_nodes": [ + [ + [ + "concatenate_5", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Dense", + "config": { + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "name": "dense_2", + "units": 1024, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "relu", + "activity_regularizer": null + }, + "name": "dense_2", + "inbound_nodes": [ + [ + [ + "flatten_1", + 0, + 0, + {} + ] + ] + ] + }, + { + "class_name": "Dense", + "config": { + "trainable": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "name": "dense_1", + "units": 32, + "kernel_constraint": null, + "bias_constraint": null, + "kernel_regularizer": null, + "use_bias": true, + "bias_regularizer": null, + "dtype": "float32", + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "distribution": "uniform", + "scale": 1.0, + "mode": "fan_avg" + } + }, + "activation": "softmax", + "activity_regularizer": null + }, + "name": "dense_1", + "inbound_nodes": [ + [ + [ + "dense_2", + 0, + 0, + {} + ] + ] + ] + } + ], + "output_layers": [ + [ + "dense_1", + 0, + 0 + ] + ], + "name": "redshiftclassificationmodel_1", + "input_layers": [ + [ + "input_1", + 0, + 0 + ] + ] + }, + "keras_version": "2.3.0" +} \ No newline at end of file diff --git a/test/test-cases/modelJsons/sequential_conv_cifar.json b/test/test-cases/modelJsons/sequential_conv_cifar.json new file mode 100644 index 0000000..8b8239e --- /dev/null +++ b/test/test-cases/modelJsons/sequential_conv_cifar.json @@ -0,0 +1,378 @@ +{ + "class_name": "Sequential", + "keras_version": "2.3.0", + "config": { + "name": "sequential_6", + "layers": [ + { + "class_name": "Conv2D", + "config": { + "data_format": "channels_last", + "strides": [ + 1, + 1 + ], + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "padding": "same", + "dtype": "float32", + "kernel_size": [ + 3, + 3 + ], + "bias_regularizer": null, + "dilation_rate": [ + 1, + 1 + ], + "batch_input_shape": [ + null, + 64, + 64, + 3 + ], + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "conv2d_3", + "filters": 32, + "trainable": true, + "kernel_constraint": null, + "activation": "linear", + "use_bias": true + } + }, + { + "class_name": "Activation", + "config": { + "name": "activation_4", + "trainable": true, + "activation": "relu", + "dtype": "float32" + } + }, + { + "class_name": "Conv2D", + "config": { + "data_format": "channels_last", + "strides": [ + 1, + 1 + ], + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "padding": "valid", + "dtype": "float32", + "kernel_size": [ + 3, + 3 + ], + "bias_regularizer": null, + "dilation_rate": [ + 1, + 1 + ], + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "conv2d_4", + "filters": 32, + "trainable": true, + "kernel_constraint": null, + "activation": "linear", + "use_bias": true + } + }, + { + "class_name": "Activation", + "config": { + "name": "activation_5", + "trainable": true, + "activation": "relu", + "dtype": "float32" + } + }, + { + "class_name": "MaxPooling2D", + "config": { + "data_format": "channels_last", + "pool_size": [ + 2, + 2 + ], + "name": "max_pooling2d_2", + "trainable": true, + "padding": "valid", + "strides": [ + 2, + 2 + ], + "dtype": "float32" + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.25, + "name": "dropout_8", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + }, + { + "class_name": "Conv2D", + "config": { + "data_format": "channels_last", + "strides": [ + 1, + 1 + ], + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "padding": "same", + "dtype": "float32", + "kernel_size": [ + 3, + 3 + ], + "bias_regularizer": null, + "dilation_rate": [ + 1, + 1 + ], + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "conv2d_5", + "filters": 64, + "trainable": true, + "kernel_constraint": null, + "activation": "linear", + "use_bias": true + } + }, + { + "class_name": "Activation", + "config": { + "name": "activation_6", + "trainable": true, + "activation": "relu", + "dtype": "float32" + } + }, + { + "class_name": "Conv2D", + "config": { + "data_format": "channels_last", + "strides": [ + 1, + 1 + ], + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "padding": "valid", + "dtype": "float32", + "kernel_size": [ + 3, + 3 + ], + "bias_regularizer": null, + "dilation_rate": [ + 1, + 1 + ], + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "conv2d_6", + "filters": 64, + "trainable": true, + "kernel_constraint": null, + "activation": "linear", + "use_bias": true + } + }, + { + "class_name": "Activation", + "config": { + "name": "activation_7", + "trainable": true, + "activation": "relu", + "dtype": "float32" + } + }, + { + "class_name": "MaxPooling2D", + "config": { + "data_format": "channels_last", + "pool_size": [ + 2, + 2 + ], + "name": "max_pooling2d_3", + "trainable": true, + "padding": "valid", + "strides": [ + 2, + 2 + ], + "dtype": "float32" + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.25, + "name": "dropout_9", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + }, + { + "class_name": "Flatten", + "config": { + "name": "flatten_2", + "trainable": true, + "data_format": "channels_last", + "dtype": "float32" + } + }, + { + "class_name": "Dense", + "config": { + "units": 512, + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "dense_11", + "trainable": true, + "kernel_constraint": null, + "activation": "linear", + "use_bias": true + } + }, + { + "class_name": "Activation", + "config": { + "name": "activation_8", + "trainable": true, + "activation": "relu", + "dtype": "float32" + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.5, + "name": "dropout_10", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + }, + { + "class_name": "Dense", + "config": { + "units": 10, + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "dense_12", + "trainable": true, + "kernel_constraint": null, + "activation": "linear", + "use_bias": true + } + }, + { + "class_name": "Activation", + "config": { + "name": "activation_9", + "trainable": true, + "activation": "softmax", + "dtype": "float32" + } + } + ] + }, + "backend": "tensorflow" +} \ No newline at end of file diff --git a/test/test-cases/modelJsons/sequential_conv_mnist.json b/test/test-cases/modelJsons/sequential_conv_mnist.json new file mode 100644 index 0000000..813d28a --- /dev/null +++ b/test/test-cases/modelJsons/sequential_conv_mnist.json @@ -0,0 +1,209 @@ +{ + "class_name": "Sequential", + "keras_version": "2.3.0", + "config": { + "name": "sequential_5", + "layers": [ + { + "class_name": "Conv2D", + "config": { + "data_format": "channels_last", + "strides": [ + 1, + 1 + ], + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "padding": "valid", + "dtype": "float32", + "kernel_size": [ + 3, + 3 + ], + "bias_regularizer": null, + "dilation_rate": [ + 1, + 1 + ], + "batch_input_shape": [ + null, + 28, + 28, + 1 + ], + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "conv2d_1", + "filters": 32, + "trainable": true, + "kernel_constraint": null, + "activation": "relu", + "use_bias": true + } + }, + { + "class_name": "Conv2D", + "config": { + "data_format": "channels_last", + "strides": [ + 1, + 1 + ], + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "padding": "valid", + "dtype": "float32", + "kernel_size": [ + 3, + 3 + ], + "bias_regularizer": null, + "dilation_rate": [ + 1, + 1 + ], + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "conv2d_2", + "filters": 64, + "trainable": true, + "kernel_constraint": null, + "activation": "relu", + "use_bias": true + } + }, + { + "class_name": "MaxPooling2D", + "config": { + "data_format": "channels_last", + "pool_size": [ + 2, + 2 + ], + "name": "max_pooling2d_1", + "trainable": true, + "padding": "valid", + "strides": [ + 2, + 2 + ], + "dtype": "float32" + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.25, + "name": "dropout_6", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + }, + { + "class_name": "Flatten", + "config": { + "name": "flatten_1", + "trainable": true, + "data_format": "channels_last", + "dtype": "float32" + } + }, + { + "class_name": "Dense", + "config": { + "units": 128, + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "dense_9", + "trainable": true, + "kernel_constraint": null, + "activation": "relu", + "use_bias": true + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.5, + "name": "dropout_7", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + }, + { + "class_name": "Dense", + "config": { + "units": 10, + "bias_constraint": null, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": null + } + }, + "name": "dense_10", + "trainable": true, + "kernel_constraint": null, + "activation": "softmax", + "use_bias": true + } + } + ] + }, + "backend": "tensorflow" +} \ No newline at end of file diff --git a/test/test-cases/modelJsons/sequential_dense.json b/test/test-cases/modelJsons/sequential_dense.json new file mode 100644 index 0000000..b3ea262 --- /dev/null +++ b/test/test-cases/modelJsons/sequential_dense.json @@ -0,0 +1,153 @@ +{ + "class_name": "Sequential", + "keras_version": "2.3.0", + "config": { + "name": "sequential_4", + "layers": [ + { + "class_name": "Dense", + "config": { + "units": 32, + "bias_constraint": { + "class_name": "MinMaxNorm", + "config": { + "min_value": -1, + "max_value": 1, + "rate": 1.0, + "axis": 0 + } + }, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "normal", + "mode": "fan_avg", + "seed": 33 + } + }, + "dtype": "float32", + "bias_regularizer": null, + "batch_input_shape": [ + null, + 32 + ], + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": 46 + } + }, + "name": "dense_3", + "trainable": true, + "kernel_constraint": { + "class_name": "MaxNorm", + "config": { + "max_value": 1.5, + "axis": 0 + } + }, + "activation": "linear", + "use_bias": true + } + }, + { + "class_name": "Activation", + "config": { + "name": "activation_3", + "trainable": true, + "activation": "relu", + "dtype": "float32" + } + }, + { + "class_name": "Dense", + "config": { + "units": 32, + "bias_constraint": null, + "activity_regularizer": { + "class_name": "L1L2", + "config": { + "l2": 0.05000000074505806, + "l1": 0.05000000074505806 + } + }, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": 46 + } + }, + "name": "dense_4", + "trainable": true, + "kernel_constraint": { + "class_name": "MaxNorm", + "config": { + "max_value": 1.5, + "axis": 0 + } + }, + "activation": "tanh", + "use_bias": false + } + }, + { + "class_name": "Dense", + "config": { + "units": 10, + "bias_constraint": null, + "activity_regularizer": { + "class_name": "L1L2", + "config": { + "l2": 0.05000000074505806, + "l1": 0.05000000074505806 + } + }, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": 46 + } + }, + "name": "dense_5", + "trainable": true, + "kernel_constraint": { + "class_name": "MaxNorm", + "config": { + "max_value": 1.5, + "axis": 0 + } + }, + "activation": "softmax", + "use_bias": false + } + } + ] + }, + "backend": "tensorflow" +} \ No newline at end of file diff --git a/test/test-cases/modelJsons/sequential_nested.json b/test/test-cases/modelJsons/sequential_nested.json new file mode 100644 index 0000000..eb56d63 --- /dev/null +++ b/test/test-cases/modelJsons/sequential_nested.json @@ -0,0 +1,125 @@ +{ + "class_name": "Sequential", + "config": { + "name": "sequential_11", + "layers": [ + { + "class_name": "Dense", + "config": { + "bias_constraint": null, + "units": 32, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "mode": "fan_avg", + "distribution": "uniform", + "scale": 1.0 + } + }, + "activity_regularizer": null, + "dtype": "float32", + "name": "dense_16", + "kernel_regularizer": null, + "kernel_constraint": null, + "activation": "relu", + "trainable": true, + "use_bias": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "batch_input_shape": [ + null, + 32 + ], + "bias_regularizer": null + } + }, + { + "class_name": "Sequential", + "config": { + "name": "sequential_10", + "layers": [ + { + "class_name": "Sequential", + "config": { + "name": "sequential_9", + "layers": [ + { + "class_name": "Dense", + "config": { + "bias_constraint": null, + "units": 32, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "mode": "fan_avg", + "distribution": "uniform", + "scale": 1.0 + } + }, + "activity_regularizer": null, + "dtype": "float32", + "name": "dense_14", + "kernel_regularizer": null, + "kernel_constraint": null, + "activation": "relu", + "trainable": true, + "use_bias": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "batch_input_shape": [ + null, + 32 + ], + "bias_regularizer": null + } + }, + { + "class_name": "Dense", + "config": { + "bias_constraint": null, + "units": 32, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "seed": null, + "mode": "fan_avg", + "distribution": "uniform", + "scale": 1.0 + } + }, + "activity_regularizer": null, + "dtype": "float32", + "name": "dense_15", + "kernel_regularizer": null, + "kernel_constraint": null, + "activation": "relu", + "trainable": true, + "use_bias": true, + "bias_initializer": { + "class_name": "Zeros", + "config": {} + }, + "batch_input_shape": [ + null, + 32 + ], + "bias_regularizer": null + } + } + ] + } + } + ] + } + } + ] + }, + "keras_version": "2.3.0", + "backend": "tensorflow" +} \ No newline at end of file diff --git a/test/test-cases/modelJsons/sequential_subclass.json b/test/test-cases/modelJsons/sequential_subclass.json new file mode 100644 index 0000000..a7f5a9b --- /dev/null +++ b/test/test-cases/modelJsons/sequential_subclass.json @@ -0,0 +1,169 @@ +{ + "class_name": "SequentialSubClass", + "keras_version": "2.3.0", + "config": { + "name": "sequentialsubclass_1", + "layers": [ + { + "class_name": "Dense", + "config": { + "units": 32, + "bias_constraint": { + "class_name": "MinMaxNorm", + "config": { + "min_value": -1, + "max_value": 1, + "rate": 1.0, + "axis": 0 + } + }, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "normal", + "mode": "fan_avg", + "seed": 33 + } + }, + "dtype": "float32", + "bias_regularizer": null, + "batch_input_shape": [ + null, + 32 + ], + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": 46 + } + }, + "name": "dense_6", + "trainable": true, + "kernel_constraint": { + "class_name": "MaxNorm", + "config": { + "max_value": 1.5, + "axis": 0 + } + }, + "activation": "linear", + "use_bias": true + } + }, + { + "class_name": "Dense", + "config": { + "units": 32, + "bias_constraint": { + "class_name": "MinMaxNorm", + "config": { + "min_value": -1, + "max_value": 1, + "rate": 1.0, + "axis": 0 + } + }, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "normal", + "mode": "fan_avg", + "seed": 33 + } + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": 46 + } + }, + "name": "dense_7", + "trainable": true, + "kernel_constraint": { + "class_name": "MaxNorm", + "config": { + "max_value": 1.5, + "axis": 0 + } + }, + "activation": "tanh", + "use_bias": true + } + }, + { + "class_name": "Dropout", + "config": { + "seed": null, + "rate": 0.5, + "name": "dropout_5", + "noise_shape": null, + "trainable": true, + "dtype": "float32" + } + }, + { + "class_name": "Dense", + "config": { + "units": 10, + "bias_constraint": { + "class_name": "MinMaxNorm", + "config": { + "min_value": -1, + "max_value": 1, + "rate": 1.0, + "axis": 0 + } + }, + "activity_regularizer": null, + "kernel_regularizer": null, + "bias_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "normal", + "mode": "fan_avg", + "seed": 33 + } + }, + "dtype": "float32", + "bias_regularizer": null, + "kernel_initializer": { + "class_name": "VarianceScaling", + "config": { + "scale": 1.0, + "distribution": "uniform", + "mode": "fan_avg", + "seed": 46 + } + }, + "name": "dense_8", + "trainable": true, + "kernel_constraint": { + "class_name": "MaxNorm", + "config": { + "max_value": 1.5, + "axis": 0 + } + }, + "activation": "softmax", + "use_bias": true + } + } + ] + }, + "backend": "tensorflow" +} \ No newline at end of file diff --git a/webgme-setup.json b/webgme-setup.json index 3e97f0a..0e34032 100644 --- a/webgme-setup.json +++ b/webgme-setup.json @@ -12,6 +12,10 @@ "ValidateKeras": { "src": "src/plugins/ValidateKeras", "test": "test/plugins/ValidateKeras" + }, + "ImportKeras": { + "src": "src/plugins/ImportKeras", + "test": "test/plugins/ImportKeras" } }, "visualizers": {