Merge pull request #1521 from PLuv/develop

ML Beta V 1.0
This commit is contained in:
Luis Fernando Molina authored and GitHub committed 2021-08-24 03:44:56 -04:00
commit cfe425d67f
41 files changed
+114392 -527

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -73,7 +73,7 @@ exports.newFoundationsBotModulesLearningEpisode = function (processIndex) {
}
function resetEpisode() {
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT.initializeNode(learningEngine.learningCurrent.learningEpisode)
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).LEARNING_ENGINE_MODULE_OBJECT.initializeNode(learningEngine.learningCurrent.learningEpisode)
}
function updateEnds() {
@@ -73,5 +73,4 @@ exports.newFoundationsBotModulesLearningOutput = function (processIndex) {
throw (TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE)
}
}
}
}
@@ -16,7 +16,7 @@
let dataFiles = new Map()
let multiTimeFrameDataFiles = new Map()
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT = TS.projects.foundations.botModules.learningEngine.newFoundationsBotModulesLearningEngine(processIndex)
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).LEARNING_ENGINE_MODULE_OBJECT = TS.projects.foundations.botModules.learningEngine.newFoundationsBotModulesLearningEngine(processIndex)
let learningOutputModuleObject = TS.projects.foundations.botModules.learningOutput.newFoundationsBotModulesLearningOutput(processIndex)
let currentTimeFrame = {}
@@ -46,12 +46,12 @@
}
/* We set up the Learning Engine Module. */
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT.initialize()
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).LEARNING_ENGINE_MODULE_OBJECT.initialize()
/* Initializing the Learning Process Date */
if (TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).IS_SESSION_FIRST_LOOP === true && TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).IS_SESSION_RESUMING === false) {
/*
This function is going to be called many times by the Learning Bot Loop.
This funcion is going to be called many times by the Learning Bot Loop.
Only during the first execution and when the User is not resuming the execution
of a stopped session / task; we are going to initialize the Process Date Time.
This variable tell us which day we are standing at, specially while working
@@ -65,7 +65,7 @@
This is the Date that is going to be used across the execution of this Learning Process.
We need this because it has a different life cycle than the processData stored at the
Learning Engine data structure. This date has to remain the same during the whole execution
of the Learning Process until the end, inclusind the writing of Data Ranges and Status Reports.
of the Learning Process until the end, inclusind the writting of Data Ranges and Status Reports.
The processDate of the Learning Engine data structure on the other hand can be changed during
the simulation loop, once we discover that all candles from a certain date have benn processed.
Here is the point where we sync one and the other.
@@ -1,6 +1,6 @@
exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
/*
This Module represents the learning simulacion. Escentially a loop through a set of candles and
This Module represents the learning simulation. Essentially a loop through a set of candles and
the execution at each loop cycle of the Learning System Protocol.
*/
const MODULE_NAME = 'Learning Simulation -> ' + TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].session.name
@@ -23,7 +23,6 @@ exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
writeFiles,
) {
try {
let learningSystem = TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SIMULATION_STATE.learningSystem
let learningEngine = TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SIMULATION_STATE.learningEngine
let sessionParameters = TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.learningParameters
@@ -67,7 +66,7 @@ exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
}
} else {
/*
Form Market Files, we are only going to load the model from this and continue the
For Market Files, we are only going to load the model from this and continue the
training it already has when the user resumes the training session. If the user
runs the training session, we will not load from disk, but create a new empty model
instead.
@@ -169,14 +168,15 @@ exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
'[INFO] runSimulation -> loop -> Candle End @ ' + (new Date(candle.end)).toUTCString())
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT.setCurrentCandle(candle) // We move the current candle we are standing at, to the learning engine data structure to make it available to anyone, including conditions and formulas.
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).LEARNING_ENGINE_MODULE_OBJECT.setCurrentCandle(candle) // We move the current candle we are standing at, to the learning engine data structure to make it available to anyone, including conditions and formulas.
/* We emit a heart beat so that the UI can now where we are at the overal process.*/
/* We emit a heart beat so that the UI can know where we are at the overall process. */
heartBeat()
/* Opening the Episode, if needed. */
learningEpisodeModuleObject.openEpisode()
// Skipping current loop if we are before initial candle:
if (checkInitialDatetime() === false) {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
'[INFO] runSimulation -> loop -> Candle Before the Initia Date Time @ ' + (new Date(candle.begin)).toUTCString())
@@ -197,26 +197,17 @@ exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
Episode Counters and Statistics update. Mantaince is done
once per simulation candle.
*/
learningSystemModuleObject.mantain()
learningSystemModuleObject.mantain() /* ***NOTE*** Currently empty */
learningEpisodeModuleObject.mantain()
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT.mantain()
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).LEARNING_ENGINE_MODULE_OBJECT.mantain()
/*
Run the first cycle of the Learning System. In this first cycle we
give some room so that orders can be canceled or filled and we can
write those records into the output memory. During this cycle new
orders can not be created, since otherwise the could be cancelled at
the second cycle without spending real time at the order book.
*/
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT.setCurrentCycle('First')
/* Run the Learning System: */
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).LEARNING_ENGINE_MODULE_OBJECT.setCurrentCycle('First')
await runCycle()
/*
We check if we need to stop before appending the records so that the stop
reason is also propery recorded. Note also that we check this after the first
cycle, where orders have not been submitted to the exchange yet, but we
had the chance to check for the status of placed orders or even cancel
the ones that needed cancellation.
reason is also properly recorded.
*/
checkIfWeNeedToStopBetweenCycles()
@@ -224,29 +215,17 @@ exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
learningRecordsModuleObject.appendRecords()
if (breakLoop === true) { break }
/*
Run the second cycle of the Learning System. During this second run
some new orders might be created at slots freed up during the first
run. This allows for example for a Limit Order to be cancelled during the
first run, and the same Limit Order definition to spawn a new order
without the need to wait until the next candle. Orders can not be cancelled
during the second cycle.
*/
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT.setCurrentCycle('Second')
await runCycle()
checkIfWeNeedToStopAfterBothCycles()
/* Add new records to the process output */
learningRecordsModuleObject.appendRecords()
if (breakLoop === true) { break }
async function runCycle() {
/* Reset Data Structures */
learningSystemModuleObject.reset()
learningEpisodeModuleObject.reset()
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT.reset()
TS.projects.foundations.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).LEARNING_ENGINE_MODULE_OBJECT.reset()
let infoMessage = 'Processing candle # ' + learningEngine.learningCurrent.learningEpisode.candle.index.value + ' @ the ' + learningEngine.learningCurrent.learningEpisode.cycle.value + ' cycle.'
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
@@ -342,7 +321,7 @@ exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
let currentDate = new Date(heartBeatDate)
let percentage = TS.projects.foundations.utilities.dateTimeFunctions.getPercentage(fromDate, currentDate, lastDate)
/*
Theere are a few tasks that we need to do only when the date changes,
There are a few tasks that we need to do only when the date changes,
otherwise it would be suboptimal.
*/
if (heartBeatDate.valueOf() !== previousHeartBeatDate) {
@@ -367,7 +346,7 @@ exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
}
/*
When the Candle Index nees to be shown, then we can not send the hearbet
When the Candle Index needs to be shown, then we can not send the heartbeat
only when the dates changes, we have to send it for every candle.
It might also contain the date information.
*/
@@ -586,5 +565,4 @@ exports.newFoundationsBotModulesLearningSimulation = function (processIndex) {
throw (TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE)
}
}
}
}
@@ -241,7 +241,7 @@ exports.newFoundationsBotModulesLearningSystem = function (processIndex) {
async function run() {
try {
/* Dynamic Indicators */
buildDynamicIndicators()
// buildDynamicIndicators() /* ***NOTE*** Would need to be implemented. */
/*
Initialize the Learning Algorithm
@@ -274,7 +274,7 @@ exports.newFoundationsBotModulesLearningSystem = function (processIndex) {
}
/* Here we check if there is a codition to be evaluated */
if (node.type === 'Condition' && evaluating === 'Conditions') {
if ((node.type === 'Condition' || node.type === 'Collection Condition') && evaluating === 'Conditions') {
/* We will eval this condition */
if (isDescendent === true) {
evalCondition(node)
@@ -428,5 +428,4 @@ exports.newFoundationsBotModulesLearningSystem = function (processIndex) {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[INFO] evalFormula -> value = ' + value)
}
}
}
@@ -62,26 +62,28 @@ function newFoundationsFunctionLibraryLearningSessionFunctions() {
let lightingPath = '' +
'Learning System->' +
'TensorFlow Library->' +
'Execution Environment->Supervised Learning->Unsupervised Learning->Self Learning->Reinforcement Learning->' +
'WebGL Backend->NodeJS Backend->WASM Backend->CPU Backend->' +
'TensorFlow Library->' +
'Execution Environment->Supervised Learning->Unsupervised Learning->Self Learning->Reinforcement Learning->' +
'WebGL Backend->NodeJS Backend->WASM Backend->CPU Backend->' +
'Environment Flags->Debug Mode->Production Mode->' +
'Supervised Learning->Unsupervised Learning->Self Learning->Reinforcement Learning->' +
'Artificial Neural Network->Model->' +
'Compile->Optimizer->Loss Function->Metrics->' +
'Fit Dataset->Verbose->Epochs->Callbacks->' +
'Layers API->Code API->' +
'Sequential Model->Functional Model->' +
'Logistic Regression->Model->' +
'Compile->Optimizer->Loss Function->Metrics->Optimizer by Name->SGD Instance->Momentum Instance->Adagrad Instance->Adadelta Instance->Adam Instance->Rmsprop Instance->' +
'Fit Dataset->Verbose->Epochs->Callbacks->Dataset Args->Batches Per Gradient Update->Shuffle->' +
'Layers API->Core API->' +
'Sequential Model->Functional Model->' +
'Data Reporting->' +
'Input Layer->Sequential layer->Output Layer->'+
'Input Shape->Batch Input Shape->Input Features->Data Feature->Feature Formula->' +
'Output Labels->Data Label->Label Formula->' +
'Input Features->Data Feature->Feature Formula->Input Shape->Batch Input Shape->Feature Preprocessing->MinMax Scaler->Standard Scaler->Collection Condition->' +
'Output Labels->Data Label->Label Formula->' +
'Advanced Activation Layers->Basic Layers->Convolutional Layers->' +
'Conv 1D Layer->Conv 2D Layer->Conv 2D Transpose Layer->Conv 3D Layer->Cropping 2D Layer->Depthwise Convo 2D Layer->Separable Convo 2D Layer->Up Sampling 2D Layer->' +
'Activation Layer->Dense Layer->Dropout Layer->Embedding Layer->Flatten Layer->Permutable Layer->Rrepeat Vector Layer->Reshape Layer->Spatial Dropout 1D Layer->' +
'Elu Layer->Leaky Relu Layer->Prelu Layer->Relu Layer->Softmax Layer->Thresholded Relu Layer->'+
'Dimensionality Units->Activation Function->Batch Size->Dtype->Trainable->Weights->Tensor->Kernel->Bias->' +
'Dimensionality Units->Activation Function->Dtype->Trainable->Weights->Tensor->Kernel->Bias->' +
'Kernel Initializer->Kernel Constraint->Kernel Regularizer->' +
'Bias Initializer->Bias Constraint->Bias Regularizer->'
'Bias Initializer->Bias Constraint->Bias Regularizer->'
let learningSystem = UI.projects.foundations.functionLibraries.protocolNode.getProtocolNode(node.learningSystemReference.payload.referenceParent, false, true, true, false, false, lightingPath)
@@ -118,9 +120,9 @@ function newFoundationsFunctionLibraryLearningSessionFunctions() {
'Begin->End->Exit Type->Status->Begin Rate->End Rate->Stage Base Asset->Stage Quoted Asset->Size Placed->Target Size->Size Filled->Fees Paid->Stage Defined In->' +
'Serial Number->Identifier->Begin->End->Begin Rate->End Rate->Strategy Name->Status->Exit Type->' +
'Balance->Begin Balance->End Balance->' +
'Index->Situation Name->Formula->Periods->' +
'Features->Feature->Begin->End->Feature Value->'+
'Labels->Label->Begin->End->Label Value->'+
'Index->Situation Name->Formula->Periods->' +
'Features->Feature->Begin->End->Feature Value->'+
'Labels->Label->Begin->End->Label Value->'+
'Predictions->Prediction->Begin->End->Prediction Value->'
let learningEngine = UI.projects.foundations.functionLibraries.protocolNode.getProtocolNode(node.learningEngineReference.payload.referenceParent, false, true, true, false, false, lightingPath)
@@ -136,7 +138,7 @@ function newFoundationsFunctionLibraryLearningSessionFunctions() {
let defaultExchange = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(validationsResult.exchange.payload, 'codeName')
let defaultMarket =
UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(validationsResult.market.baseAsset.payload.referenceParent.payload, 'codeName')
+ '-' +
+ '-' +
UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(validationsResult.market.quotedAsset.payload.referenceParent.payload, 'codeName')
let dependencyFilter = UI.projects.foundations.functionLibraries.dependenciesFilter.createDependencyFilter(
+16 -2
View File
@@ -322,7 +322,7 @@
"onMouseOverIndex": 2,
"onMouseClickIndex": 7,
"onMouseDownIndex": 0
},
},
{
"name": "Chat Space",
"folderName": "Chat-Space",
@@ -982,6 +982,20 @@
"functionName": "newTensorFlowBotModulesTensorFlowLibrary",
"fileName": "TensorFlowLibrary.js",
"folderName": "Learning-Bot/Low-Frequency-Learning"
},
{
"name": "TensorFlow Models Manager",
"propertyName": "tensorFlowModelsManager",
"functionName": "newTensorFlowModelsManager",
"fileName": "TensorFlowModelsManager.js",
"folderName": "Learning-Bot/Low-Frequency-Learning"
},
{
"name": "ML Data Manager",
"propertyName": "mlData",
"functionName": "newMLDataObj",
"fileName": "MLDataManager.js",
"folderName": "Learning-Bot/Low-Frequency-Learning"
}
]
}
@@ -1250,4 +1264,4 @@
"Positions"
]
}
]
]
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,36 @@
{
"type": "Adadelta Instance",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"learningRate\": 0.001 ,\n \"rho\": 0.9 ,\n \"epsilon\": 1e-07 \n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Optimizer->"
},
"propertyNameAtParent": "optimizerType",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -0,0 +1,36 @@
{
"type": "Adagrad Instance",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"learningRate\": 0.001 ,\n \"initialAccumulatorValue\": 0.1 \n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Optimizer->"
},
"propertyNameAtParent": "optimizerType",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -0,0 +1,36 @@
{
"type": "Adam Instance",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"learningRate\": 0.001 ,\n \"beta1\": 0.9 ,\n \"beta2\": 0.999 ,\n \"epsilon\": 1e-07 \n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Optimizer->"
},
"propertyNameAtParent": "optimizerType",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -0,0 +1,36 @@
{
"type": "Batches Per Gradient Update",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"value\": 32 \n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Dataset Args->"
},
"propertyNameAtParent": "batchesPerGradientUpdate",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -0,0 +1,35 @@
{
"type": "Collection Condition",
"level": 4,
"propertyNameAtParent": "collectionCondition",
"editors": {
"code": true
},
"initialValues": {
"code": "// Type your code"
},
"attachingRules": {
"compatibleTypes": "->Input Layer->"
},
"menuItems": [
{
"action": "Edit",
"actionFunction": "uiObject.codeEditor.activate",
"label": "Edit",
"iconPathOn": "javascript-code",
"iconPathOff": "javascript-code"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"addLeftIcons": true,
"icon": "tensorflow"
}
@@ -10,6 +10,15 @@
"relatedUiObject": "Feature Formula",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "featurePreprocessing",
"label": "Add Feature Preprocessing",
"relatedUiObject": "Feature Preprocessing",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
@@ -33,7 +42,13 @@
"type": "node",
"childType": "Feature Formula",
"autoAdd": true
},
{
"name": "featurePreprocessing",
"type": "node",
"childType": "Feature Preprocessing",
"autoAdd": false
}
],
"icon": "tensorflow"
}
}
@@ -0,0 +1,36 @@
{
"type": "Data Reporting",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"printDataReports\": true \n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Model->"
},
"propertyNameAtParent": "dataReporting",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -0,0 +1,52 @@
{
"type": "Dataset Args",
"menuItems": [
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "batchesPerGradientUpdate",
"label": "Add Batch Size Per Gradient Update",
"relatedUiObject": "Batches Per Gradient Update",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "shuffle",
"label": "Add Shuffle",
"relatedUiObject": "Shuffle",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Fit Dataset->"
},
"propertyNameAtParent": "datasetArgs",
"childrenNodesProperties": [
{
"name": "batchesPerGradientUpdate",
"type": "node",
"childType": "Batches Per Gradient Update"
},
{
"name": "shuffle",
"type": "node",
"childType": "Shuffle"
}
],
"icon": "tensorflow"
}
@@ -146,4 +146,4 @@
}
],
"icon": "tensorflow"
}
}
@@ -33,4 +33,4 @@
"propertyNameAtParent": "dimensionalityUnits",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
}
@@ -0,0 +1,54 @@
{
"type": "Feature Preprocessing",
"menuItems": [
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "minMaxScaler",
"label": "Add MinMax Scaler",
"relatedUiObject": "MinMax Scaler",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "standardScaler",
"label": "Add Standard Scaler",
"relatedUiObject": "Standard Scaler",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Data Feature->"
},
"propertyNameAtParent": "featurePreprocessing",
"childrenNodesProperties": [
{
"name": "minMaxScaler",
"type": "node",
"childType": "MinMax Scaler",
"autoAdd": false
},
{
"name": "standardScaler",
"type": "node",
"childType": "Standard Scaler",
"autoAdd": false
}
],
"icon": "tensorflow"
}
@@ -1,6 +1,15 @@
{
"type": "Fit Dataset",
"menuItems": [
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "datasetArgs",
"label": "Add Dataset Args",
"relatedUiObject": "Dataset Args",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
@@ -46,6 +55,11 @@
},
"propertyNameAtParent": "fitDataset",
"childrenNodesProperties": [
{
"name": "datasetArgs",
"type": "node",
"childType": "Dataset Args"
},
{
"name": "verbose",
"type": "node",
@@ -63,4 +77,4 @@
}
],
"icon": "tensorflow"
}
}
@@ -1,6 +1,15 @@
{
"type": "Input Layer",
"menuItems": [
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "inputFeatures",
"label": "Add Input Features",
"relatedUiObject": "Input Features",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
@@ -23,9 +32,9 @@
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "inputFeatures",
"label": "Add Input Features",
"relatedUiObject": "Input Features",
"propertyToCheckFor": "collectionCondition",
"label": "Add Collection Condition",
"relatedUiObject": "Collection Condition",
"actionFunction": "payload.executeAction"
},
{
@@ -52,6 +61,11 @@
},
"propertyNameAtParent": "inputLayer",
"childrenNodesProperties": [
{
"name": "inputFeatures",
"type": "node",
"childType": "Input Features"
},
{
"name": "inputShape",
"type": "node",
@@ -63,10 +77,10 @@
"childType": "Batch Input Shape"
},
{
"name": "inputFeatures",
"type": "node",
"childType": "Input Features"
"name": "collectionCondition",
"type": "node",
"childType": "Collection Condition"
}
],
"icon": "tensorflow"
}
}
@@ -0,0 +1,37 @@
{
"type": "Logistic Regression",
"menuItems": [
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "model",
"label": "Add Model",
"relatedUiObject": "Model",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Supervised Learning->Unsupervised Learning->Reinforcement Learning->Self Learning->"
},
"propertyNameAtParent": "typeOfModel",
"childrenNodesProperties": [
{
"name": "model",
"type": "node",
"childType": "Model"
}
]
}
@@ -0,0 +1,36 @@
{
"type": "MinMax Scaler",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"minimum\": 0 ,\n \"maximum\": 1 \n }"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Feature Preprocessing->"
},
"propertyNameAtParent": "minMaxScaler",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -44,6 +44,15 @@
"relatedUiObject": "Fit Dataset",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "dataReporting",
"label": "Add Data Reporting",
"relatedUiObject": "Data Reporting",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
@@ -59,7 +68,7 @@
"config": true
},
"initialValues": {
"config": "{ \n \"codeName\": \"\"\n}"
"config": "{ \n \"codeName\": \"\" \n }"
},
"addLeftIcons": true,
"level": 3,
@@ -87,6 +96,12 @@
"name": "fitDataset",
"type": "node",
"childType": "Fit Dataset"
},
{
"name": "dataReporting",
"type": "node",
"childType": "Data Reporting",
"autoAdd": true
}
]
}
}
@@ -0,0 +1,36 @@
{
"type": "Momentum Instance",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"learningRate\": 0.01 ,\n \"momentum\": 0.5 ,\n \"useNesterov\": false \n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Optimizer->"
},
"propertyNameAtParent": "optimizerType",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -0,0 +1,36 @@
{
"type": "Optimizer by Name",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"value\": \"sgd\"\n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Optimizer->"
},
"propertyNameAtParent": "optimizerType",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -2,11 +2,67 @@
"type": "Optimizer",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "optimizerType",
"label": "Add Optimizer by Name",
"relatedUiObject": "Optimizer by Name",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "optimizerType",
"label": "Add SGD Instance",
"relatedUiObject": "SGD Instance",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "optimizerType",
"label": "Add Momentum Instance",
"relatedUiObject": "Momentum Instance",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "optimizerType",
"label": "Add Adagrad Instance",
"relatedUiObject": "Adagrad Instance",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "optimizerType",
"label": "Add Adadelta Instance",
"relatedUiObject": "Adadelta Instance",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "optimizerType",
"label": "Add Adam Instance",
"relatedUiObject": "Adam Instance",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "optimizerType",
"label": "Add Rmsprop Instance",
"relatedUiObject": "Rmsprop Instance",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
@@ -19,18 +75,48 @@
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"value\": \"sgd\"\n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Compile->"
},
"propertyNameAtParent": "optimizer",
"childrenNodesProperties": [],
"childrenNodesProperties": [
{
"name": "optimizerType",
"type": "node",
"childType": "Optimizer by Name"
},
{
"name": "optimizerType",
"type": "node",
"childType": "SGD Instance"
},
{
"name": "optimizerType",
"type": "node",
"childType": "Momentum Instance"
},
{
"name": "optimizerType",
"type": "node",
"childType": "Adagrad Instance"
},
{
"name": "optimizerType",
"type": "node",
"childType": "Adadelta Instance"
},
{
"name": "optimizerType",
"type": "node",
"childType": "Adam Instance"
},
{
"name": "optimizerType",
"type": "node",
"childType": "Rmsprop Instance"
}
],
"icon": "tensorflow"
}
}
@@ -0,0 +1,36 @@
{
"type": "Rmsprop Instance",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"learningRate\": 0.001 ,\n \"decay\": 0.9 ,\n \"momentum\": 0.0 ,\n \"epsilon\": 1e-07 ,\n \"centered\": false \n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Optimizer->"
},
"propertyNameAtParent": "optimizerType",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -0,0 +1,36 @@
{
"type": "SGD Instance",
"menuItems": [
{
"action": "Configure",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration",
"actionFunction": "uiObject.configEditor.activate"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"editors": {
"config": true
},
"initialValues": {
"config": "{ \n \"learningRate\": 0.01\n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Optimizer->"
},
"propertyNameAtParent": "optimizerType",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -1,5 +1,5 @@
{
"type": "Batch Size",
"type": "Shuffle",
"menuItems": [
{
"action": "Configure",
@@ -23,14 +23,14 @@
"config": true
},
"initialValues": {
"config": "{ \n \"value\": 1\n}"
"config": "{ \n \"booleanValue\": true \n }"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Dense Layer->"
"compatibleTypes": "->Dataset Args->"
},
"propertyNameAtParent": "batchSize",
"propertyNameAtParent": "shuffle",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
}
@@ -0,0 +1,23 @@
{
"type": "Standard Scaler",
"menuItems": [
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Feature Preprocessing->"
},
"propertyNameAtParent": "standardScaler",
"childrenNodesProperties": [],
"icon": "tensorflow"
}
@@ -10,6 +10,15 @@
"relatedUiObject": "Artificial Neural Network",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "typeOfModel",
"label": "Add Logistic Regression",
"relatedUiObject": "Logistic Regression",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
@@ -32,6 +41,11 @@
"name": "typeOfModel",
"type": "node",
"childType": "Artificial Neural Network"
},
{
"name": "typeOfModel",
"type": "node",
"childType": "Logistic Regression"
}
]
}
}
@@ -45,6 +45,16 @@
"label": "Add Reinforcement Learning",
"relatedUiObject": "Reinforcement Learning",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
"askConfirmation": true,
"confirmationLabel": "Confirm to Delete",
"label": "Delete",
"iconPathOn": "delete-entity",
"iconPathOff": "delete-entity",
"actionFunction": "payload.executeAction"
}
],
"addLeftIcons": true,
@@ -0,0 +1,350 @@
/* MLDataManager.js : mlDataObj:
* Author: Philip Love (Pluvtech)
* History:
* 7/25/21: Start
* 7/31/21: Name Change for SA-ML Integration
* 8/24/21: Pushing as beta
*
* ToDo:
* 1.) Clean any erroneous samples
* 2.) Develop a scheme to not call toArray() as often. Especially in stats()
* 3.) Expand logic to include more than one input, i.e.- Higher ranks
* 4.) Expose stats to public.
* 5.) Expand Feature Engineering Section.
*/
exports.newMLDataObj = function(featureLen, labelLen) {
const MODULE_NAME = 'ML Data Manager';
/* Dependencies Section: */
const tf = require("@tensorflow/tfjs-node");
/* Variables Section: */
var _features = {}; // Features Object
var _labels = {}; // Labels Object
var feats = []
var labs = []
//var _rank = []; // Future expansion placeholder variable. [Feature Tensor Rank, Label Tensor Rank]
/* stats{} : Statistics producer object:
* count: returns: int
* mean: returns: { FMeans:[], LMeans:[] }
* std: returns: { FSTDs:[], LSTDs:[] }
* variance: returns: { FVar:[], lVar:[] }
* minMaxMedRange: returns: { fMax:[], fMin:[], fMedian:[], fRange:[],
* lMax:[], lMin:[], lMedian:[], lRange:[] }
* all: returns {count, mean{}, minMaxMedRange{}, std{}, variance{} }
*/
var stats = {};
var dataObject = {
addFeatures: addFeatures, // addFeatures(fArr)
addLabels: addLabels, // addLabels(lArr)
featuresToArray: () => { return toArray('features') },
labelsToArray: () => { return toArray('labels') },
featuresTensor: () => { return tensorMaker('features') },
labelsTensor: () => { return tensorMaker('labels') },
dataEngineering: dataEngineering,
minMaxScaler: minMaxScaler, // minMaxScaler(sMin, sMax, fNum)
standardScaler: standardScaler, // standardScaler(fNum)
print: print
};
// Auto Constructor:
(() => {
let fStr = "Feature #";
let lStr = "Label #";
for (let i = 1; i <= featureLen; i++) {
_features[fStr + i] = [];
}
for (let i = 1; i <= labelLen; i++) {
_labels[lStr + i] = [];
}
})();
stats = {
mean: () => {
let meansObj = { fMeans: [], lMeans: [] };
let fArr = toArray('features');
let lArr = toArray('labels');
fArr.forEach(e => meansObj['fMeans'].push(meanArr(e)));
lArr.forEach(e => meansObj['lMeans'].push(meanArr(e)));
return meansObj;
},
std: () => {
let stdObj = { fStds: [], lStds: [] };
let means = stats.mean();
let fArr = toArray('features');
let lArr = toArray('labels');
fArr.forEach((e, i) => stdObj['fStds'].push(STDev(e, means['fMeans'][i], false)));
lArr.forEach((e, i) => stdObj['lStds'].push(STDev(e, means['lMeans'][i], false)));
return stdObj;
},
count: () => { return _features['Feature #1'].length },
variance: () => {
let varianceObj = { fVar: [], lVar: [] };
let means = stats.mean();
let fArr = toArray('features');
let lArr = toArray('labels');
fArr.forEach((e, i) => varianceObj['fVar'].push(STDev(e, means['fMeans'][i], true)));
lArr.forEach((e, i) => varianceObj['lVar'].push(STDev(e, means['lMeans'][i], true)));
return varianceObj;
},
minMaxMedRange: () => {
let mmmrObj = {
fMin: [], lMin: [], fMax: [], lMax: [],
fRange: [], lRange: [], fMedian: [], lMedian: []
};
let fArr = toArray('features');
let lArr = toArray('labels');
fArr.forEach(e => mmmrObj['fMin'].push(Math.min(...e)));
lArr.forEach(e => mmmrObj['lMin'].push(Math.min(...e)));
fArr.forEach(e => mmmrObj['fMax'].push(Math.max(...e)));
lArr.forEach(e => mmmrObj['lMax'].push(Math.max(...e)));
mmmrObj['fMax'].forEach((e, i) =>
mmmrObj['fRange'].push(e - mmmrObj['fMin'][i]));
mmmrObj['lMax'].forEach((e, i) =>
mmmrObj['lRange'].push(e - mmmrObj['lMin'][i]));
// Median:
let findMedian = (e) => {
let sorted = e.slice().sort((a, b) => a - b);
let mid = Math.floor(sorted.length / 2);
return (sorted.length % 2 === 0) ?
(sorted[mid - 1] + sorted[mid]) / 2 :
sorted[mid];
}
fArr.forEach(e => mmmrObj['fMedian'].push(findMedian(e)));
lArr.forEach(e => mmmrObj['lMedian'].push(findMedian(e)));
return mmmrObj;
},
all: () => {
allStatsObj = {};
allStatsObj.mean = stats.mean();
allStatsObj.std = stats.std();
allStatsObj.count = stats.count();
allStatsObj.variance = stats.variance();
allStatsObj.minMaxMedRange = stats.minMaxMedRange();
return allStatsObj;
}
};
return dataObject;
/* ===========================================================================
* Methods Section:
*/
// addFeatures() : fArr should be => [ Feature, Feature, ... ]
function addFeatures(fArr) {
let fStr = "Feature #";
fArr.forEach((e, i) => _features[fStr+(i+1)].push(e));
}
// addLabels() : lArr should be => [ Label, Label, ... ]
function addLabels(lArr) {
let lStr = "Label #";
lArr.forEach((e, i) => _labels[lStr+(i+1)].push(e));
}
/* featuresArr() : returns the features as an array like =>
* [[Feature 1, Feature 1, ...], [Feature 2, Feature 2, ...], [ ... ]]
*/
function toArray(aType) {
arr = [];
let arrType = (aType === 'features') ? _features : _labels;
Object.entries(arrType).forEach(entry => {
const [key, value] = entry;
arr.push(value);
});
return arr;
}
// tensorMaker() : Return TF.Tensor:
function tensorMaker(tType) {
let tArr = toArray(tType);
let tensorFormat = [];
for (let i = 0; i < tArr[0].length; i++) {
let sample = [];
for (let fNum = 0; fNum < tArr.length; fNum++) {
sample.push(tArr[fNum][i]);
}
tensorFormat.push(sample);
}
return tf.tensor(tensorFormat);
}
/* ===========================================================================
* Feature Engineering Section:
*/
// dataEngineering() : Wrapper for data transformations:
async function dataEngineering(learningSystem) {
// Check if performing any feature engineering:
let dataFeaturesArr = learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel.inputLayer.inputFeatures.dataFeatures;
for (let i = 0, fNum = 1; i < dataFeaturesArr.length; i++, fNum++) {
if (dataFeaturesArr[i].featurePreprocessing !== undefined) {
/* NOTE: If more than one preprocessor has been chosen then they will be processed in the order
* in which they are listed here. This order should be considered or this function re-written in
* the event of future pre-processor additions to SA.
*/
let pType = dataFeaturesArr[i].featurePreprocessing;
if (pType.minMaxScaler !== undefined) {
let sMin = (pType.minMaxScaler.config.minimum !== undefined) ?
pType.minMaxScaler.config.minimum : 0;
let sMax = (pType.minMaxScaler.config.maximum !== undefined) ?
pType.minMaxScaler.config.maximum : 1;
minMaxScaler(sMin, sMax, fNum);
}
if (pType.standardScaler !== undefined) {
standardScaler(fNum);
}
}
}
}
/* Scalers / Normalizers:
*
* minMaxScaler( feature_range=(low), (high) , feature_num):
* Formula: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html
* X_std = (X - X.min) / (X.max - X.min)
* X_scaled = X_std * (max - min) + min
*/
function minMaxScaler(sMin, sMax, fNum) {
let fStr = "Feature #" + fNum;
let fArr = _features[fStr];
let xMin = Math.min(...fArr);
let xMax = Math.max(...fArr);
let scaled = [];
fArr.forEach(e => scaled.push(((e - xMin) / (xMax - xMin)) * (sMax - sMin) + sMin));
_features[fStr] = scaled;
}
/* standardScaler( feature_num )
* Standardize features by removing the mean and scaling to unit variance.
* x = (X`i - μ) / σ
* This will force every feature to have a mean of 0 and a standard deviation of 1,
* and thus be scaled well relative to each other.
*/
function standardScaler(fNum) {
let fStr = "Feature #" + fNum;
let i = fNum - 1;
let fArr = _features[fStr];
let mean = stats.mean(); //fArr.reduce((accumulator, currentValue) => accumulator + currentValue) / fArr.length;
let std = stats.std();
let scaled = [];
fArr.forEach(e => scaled.push((e - mean['fMeans'][i]) / std['fStds'][i]));
_features[fStr] = scaled;
}
/* ===========================================================================
* Helper Math Functions:
*/
// STDev() : if retVar == true then STDev will return Variance else Standard Deviation.
function STDev(dataArr, mean, retVar) {
let numerator = 0;
let denominator = dataArr.length;
dataArr.forEach(e => {
numerator += Math.pow((e - mean), 2);
});
let variance = numerator / denominator;
return (retVar === undefined || !retVar) ? Math.sqrt(variance) : variance;
};
function meanArr(dataArr) {
return dataArr.reduce((accumulator, currentValue) => accumulator + currentValue) / dataArr.length;
}
/* ===========================================================================
* Extra Functionality:
*/
// print() : Top portion is Feature/Label Hard Numbers then Bottom is Statistics:
function print() {
let fkeys = [], fvalues = [], lkeys = [], lvalues = [];
Object.entries(_features).forEach(entry => {
const [key, value] = entry;
fkeys.push(key);
fvalues.push(value);
});
Object.entries(_labels).forEach(entry => {
const [key, value] = entry;
lkeys.push(key);
lvalues.push(value);
});
let topSeparator = "__________________________________________________";
let separator = "==================================================";
let buf = "\n" + topSeparator + "\nSuperalgos ML DataFrame:\n";
let separator2 = "||||||||||||||||||||||||||||||||||||||||||||||||||";
buf += separator;
let fkLen = fkeys.length, fvLen = fvalues[0].length;
let lkLen = lkeys.length;
console.log(buf);
// Features / Labels Hard Numbers:
for (let i = 0; i < fvLen; i++) {
buf = "Sample[" + i + "]=>\n";
for (let j = 0; j < fkLen; j++) {
buf += "\t" + fkeys[j] + ": [" + fvalues[j][i].toFixed(5) + "...]\n";
}
for (let k = 0; k < lkLen; k++) {
buf += "\t" + lkeys[k] + ": [" + lvalues[k][i].toFixed(5) + "...]\n";
}
buf += separator;
if (i > 3 && fvLen > 9 && i < fvLen - 6) { // Fast-forward
buf += "\n\t\t" + "..." + "\n\t\t" + "..." + "\n\t\t" + "...\n" + separator;
i = fvLen - 6;
}
console.log(buf);
}
// Statistics:
buf = separator2 + "\n" + separator + "\n\n" + topSeparator + "\nSuperalgos ML DataFrame Statistics:\n" + separator;
let statistics = stats.all();
console.log(buf);
for (let i = 0; i < fkLen; i++) {
buf = fkeys[i] + ":\n\tCount:\t[" + statistics.count + "]\n";
buf += "\tMean:\t[" + statistics.mean.fMeans[i] + "]\n";
buf += "\tMedian:\t[" + statistics.minMaxMedRange.fMedian[i] + "]\n";
buf += "\tSTDev:\t[" + statistics.std.fStds[i] + "]\n";
buf += "\tVariance: [" + statistics.variance.fVar[i] + "]\n";
buf += "\tMin: [" + statistics.minMaxMedRange.fMin[i].toFixed(4) + "...]\n" +
"\tMax: [" + statistics.minMaxMedRange.fMax[i].toFixed(4) + "...]\n" +
"\tRange: [" + statistics.minMaxMedRange.fRange[i].toFixed(4) + "...]\n";
buf += topSeparator;
console.log(buf);
}
for (let j = 0; j < lkLen; j++) {
buf = lkeys[j] + ":\n\tCount:\t[" + statistics.count + "]\n";
buf += "\tMean:\t[" + statistics.mean.lMeans[j] + "]\n";
buf += "\tMedian:\t[" + statistics.minMaxMedRange.lMedian[j] + "]\n";
buf += "\tSTDev:\t[" + statistics.std.lStds[j] + "]\n";
buf += "\tVariance: [" + statistics.variance.lVar[j] + "]\n";
buf += "\tMin: [" + statistics.minMaxMedRange.lMin[j].toFixed(4) + "...]\n" +
"\tMax: [" + statistics.minMaxMedRange.lMax[j].toFixed(4) + "...]\n" +
"\tRange: [" + statistics.minMaxMedRange.lRange[j].toFixed(4) + "...]\n";
buf += topSeparator;
console.log(buf);
}
console.log(separator + "\n" + separator2 + "\n" + separator);
}
/* A rank two tensor is what we typically think of as a matrix, a rank one tensor is a vector.
* For a rank two tensor you can acccess any element with the syntax t[i, j].
* For a rank three tensor you would need to address an element with t[i, j, k].
*/
// setRank() : placeholder for future expansion past sequential model.
/*setRank() {
}
*/
}
@@ -24,10 +24,12 @@ exports.newTensorFlowBotModulesTensorFlowLibrary = function (processIndex) {
let exchange
let market
let tensorFlowBackend
let tensorFlowAPI
let tensorFlowModel
let tensorFlowData
const requiredErr = (str) => { throw new Error('Missing: ' + str); }
let fLen, lLen;
let tensorFlowBackend;
var tensorFlowModelsManager; // Initialized in setupModel()
var mlDataObj; // ML Data Manager Module.
var hasCondition;
return thisObject
@@ -36,26 +38,25 @@ exports.newTensorFlowBotModulesTensorFlowLibrary = function (processIndex) {
learningEngine = TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).SIMULATION_STATE.learningEngine
sessionParameters = TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.learningParameters
validations();
setupBackend()
setupEnvironmentFlags()
setupModel()
compileModel()
tensorFlowModelsManager = TS.projects.tensorflow.botModules.tensorFlowModelsManager.newTensorFlowModelsManager(processIndex, learningSystem);
callbackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_OK_RESPONSE)
fLen = learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel.inputLayer.inputFeatures.dataFeatures.length;
lLen = learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel.outputLayer.outputLabels.dataLabels.length;
mlDataObj = TS.projects.tensorflow.botModules.mlData.newMLDataObj(fLen, lLen);
hasCondition = (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel.inputLayer.collectionCondition !== undefined) ? true : false;
function setupBackend() {
/*
Setup the default backend.
*/
/* Setup the default backend: */
tensorFlowBackend = require("@tensorflow/tfjs-node")
if (
learningSystem.machineLearningLibrary.executionEnvironment !== undefined &&
learningSystem.machineLearningLibrary.executionEnvironment.backend !== undefined
) {
/*
Replace the backend for the one defined at the UI.
*/
/* Replace the backend for the one defined at the UI: */
switch (learningSystem.machineLearningLibrary.executionEnvironment.backend.config.codeName) {
case 'node': {
// This is already the default.
@@ -95,207 +96,6 @@ exports.newTensorFlowBotModulesTensorFlowLibrary = function (processIndex) {
}
}
}
function setupModel() {
if (
learningSystem.machineLearningLibrary.typeOfLearning !== undefined &&
learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel !== undefined &&
learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model !== undefined &&
learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api !== undefined
) {
switch (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.type) {
case 'Layers API': {
tensorFlowAPI = require("@tensorflow/tfjs-layers")
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel === undefined) { return }
switch (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel.type) {
case 'Sequential Model': {
setupSecuentialModel(learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel)
break
}
case 'Functional Model': {
/* To be implemented some day...*/
break
}
}
break
}
case 'Code API': {
tensorFlowAPI = require("@tensorflow/tfjs-core")
/* To be implemented some day...*/
break
}
}
}
function setupSecuentialModel(secuentialModel) {
/*
Some validations
*/
if (secuentialModel.inputLayer === undefined) {
// TODO
return
}
if (secuentialModel.outputLayer === undefined) {
// TODO
return
}
if (secuentialModel.layers.length === 0) {
// TODO
return
}
if (secuentialModel.inputLayer.referenceParent === undefined) {
// TODO
return
}
tensorFlowModel = tensorFlowAPI.sequential()
for (let i = 0; i < secuentialModel.layers.length; i++) {
let layerNode = secuentialModel.layers[i]
let layersFunction
let argsObject = {}
let layerObject
if (layerNode.typeOfLayer === undefined) { continue }
if (layerNode.typeOfLayer.layer === undefined) { continue }
switch (layerNode.typeOfLayer.layer.type) {
case 'Dense Layer': {
layersFunction = tensorFlowAPI.layers.dense
break
}
case ' ': {
break
}
case ' ': {
break
}
default: {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
'[WARN] Layer of type ' + layerNode.typeOfLayer.layer.type + ' not implemented yet.')
continue
}
}
if (layerNode.typeOfLayer.layer.dimensionalityUnits !== undefined) {
argsObject.units = layerNode.typeOfLayer.layer.dimensionalityUnits.config.value
} else {
argsObject.units = 1
}
if (layerNode.typeOfLayer.layer.activationFunction !== undefined) {
argsObject.activation = layerNode.typeOfLayer.layer.activationFunction.config.value
}
if (layerNode.typeOfLayer.layer.bias !== undefined) {
argsObject.useBias = true
} else {
argsObject.useBias = false
}
if (layerNode.typeOfLayer.layer.kernel !== undefined) {
if (layerNode.typeOfLayer.layer.kernel.kernelInitializer !== undefined) {
argsObject.kernelInitializer = layerNode.typeOfLayer.layer.kernel.kernelInitializer.config.value
}
if (layerNode.typeOfLayer.layer.kernel.kernelConstraint !== undefined) {
argsObject.kernelConstraint = layerNode.typeOfLayer.layer.kernel.kernelConstraint.config.value
}
if (layerNode.typeOfLayer.layer.kernel.kernelRegularizer !== undefined) {
argsObject.kernelRegularizer = layerNode.typeOfLayer.layer.kernel.kernelRegularizer.config.value
}
}
if (layerNode.typeOfLayer.layer.bias !== undefined) {
if (layerNode.typeOfLayer.layer.bias.biasInitializer !== undefined) {
argsObject.biasInitializer = layerNode.typeOfLayer.layer.bias.biasInitializer.config.value
}
if (layerNode.typeOfLayer.layer.bias.biasConstraint !== undefined) {
argsObject.biasConstraint = layerNode.typeOfLayer.layer.bias.biasConstraint.config.value
}
if (layerNode.typeOfLayer.layer.bias.biasRegularizer !== undefined) {
argsObject.biasRegularizer = layerNode.typeOfLayer.layer.bias.biasRegularizer.config.value
}
}
if (layerNode.typeOfLayer.layer.batchSize !== undefined) {
argsObject.batchSize = layerNode.typeOfLayer.layer.batchSize.config.value
}
if (layerNode.typeOfLayer.layer.dtype !== undefined) {
argsObject.dtype = layerNode.typeOfLayer.layer.dtype.config.value
}
if (layerNode.typeOfLayer.layer.trainable !== undefined) {
argsObject.trainable = layerNode.typeOfLayer.layer.trainable.config.value
}
if (layerNode.typeOfLayer.layer.weights !== undefined) {
if (layerNode.typeOfLayer.layer.weights.tensor !== undefined) {
argsObject.weights = layerNode.typeOfLayer.layer.weights.tensor.config.value
}
}
argsObject.name = layerNode.typeOfLayer.layer.config.codeName
/*
Check if this is the input layer.
*/
if (secuentialModel.inputLayer.referenceParent.id === layerNode.id) {
/*
If there is a explicitly defined Input Shape, then we will take it,
otherwise, we will count the amount of features declared.
*/
if (secuentialModel.inputLayer.inputShape !== undefined) {
if (argsObject.inputShape = secuentialModel.inputLayer.inputShape !== undefined) {
if (argsObject.inputShape = secuentialModel.inputLayer.inputShape.config.value !== undefined) {
argsObject.inputShape = secuentialModel.inputLayer.inputShape.config.value
}
}
}
if (argsObject.inputShape === undefined) {
argsObject.inputShape = []
argsObject.inputShape.push(secuentialModel.inputLayer.inputFeatures.dataFeatures.length)
}
}
layerObject = layersFunction(argsObject)
tensorFlowModel.add(layerObject)
}
}
}
}
function compileModel() {
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile === undefined) {
//TODO
return
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer === undefined) {
//TODO
return
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.config.value === undefined) {
//TODO
return
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.lossFunction === undefined) {
//TODO
return
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.lossFunction.config.value === undefined) {
//TODO
return
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.metrics === undefined) {
//TODO
return
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.metrics.config.value === undefined) {
//TODO
return
}
let compileArgs = {
optimizer: learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.config.value,
loss: learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.lossFunction.config.value /*,
metrics: [learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.metrics.config.value]*/
}
tensorFlowModel.compile(compileArgs)
tensorFlowModel.summary()
}
function finalize() {
@@ -308,22 +108,21 @@ exports.newTensorFlowBotModulesTensorFlowLibrary = function (processIndex) {
market = undefined
tensorFlowBackend = undefined
tensorFlowAPI = undefined
tensorFlowModel = undefined
tensorFlowModelsManager.model = undefined
tensorFlowData = undefined
}
async function loadModel() {
tensorFlowModel = await tensorFlowAPI.loadLayersModel('file://' + getModelPath() + '/model.json')
compileModel()
tensorFlowModelsManager.model = await tensorFlowModelsManager.api.loadLayersModel('file://' + getModelPath() + '/model.json');
tensorFlowModelsManager.compileModel();
}
async function saveModel() {
let fileLocation = getModelPath()
/* If necesary a folder or folders are created before writing the file to disk. */
TS.projects.foundations.utilities.miscellaneousFunctions.mkDirByPathSync(fileLocation)
let fileLocation = getModelPath();
/* If necesary a folder or folders are created before writing the file to disk: */
TS.projects.foundations.utilities.miscellaneousFunctions.mkDirByPathSync(fileLocation);
await tensorFlowModel.save('file://' + fileLocation)
const savedModel = await tensorFlowModelsManager.model.save('file://' + fileLocation);
}
function getModelPath() {
@@ -347,159 +146,132 @@ exports.newTensorFlowBotModulesTensorFlowLibrary = function (processIndex) {
market = pMarket
}
function mantain() {
function mantain() {}
}
function reset() {
}
function reset() {}
async function run(callbackFunction) {
let layersModel = learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel
let features = []
let labels = []
/*
Building the Features Tensor
*/
if (layersModel.inputLayer === undefined) {
// TODO
let layersModel = learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel;
let isAllowed = true;
if (hasCondition) {
learningSystem.evalConditions(layersModel.inputLayer.collectionCondition, layersModel.inputLayer.collectionCondition.type);
isAllowed = learningSystem.conditions.get(layersModel.inputLayer.collectionCondition.id);
}
if (layersModel.inputLayer.inputFeatures === undefined) {
// TODO
}
learningSystem.evalFormulas(layersModel.inputLayer.inputFeatures, layersModel.inputLayer.inputFeatures.type)
if (isAllowed) {
let features = await getFeatures(layersModel);
for (let i = 0; i < layersModel.inputLayer.inputFeatures.dataFeatures.length; i++) {
let dataFeature = layersModel.inputLayer.inputFeatures.dataFeatures[i]
if (dataFeature.featureFormula === undefined) { continue }
let featureValue = learningSystem.formulas.get(dataFeature.featureFormula.id)
features.push(featureValue)
/* We will store at the Learning Engine data structure the features we have calculated: */
for (let i = 0; i < layersModel.inputLayer.inputFeatures.dataFeatures.length; i++) {
if (learningEngine.features.features[i] === undefined) { continue }
learningEngine.features.features[i].featureValue.value = features[i];
learningEngine.features.features[i].begin.value = learningEngine.learningCurrent.learningEpisode.candle.begin.value
learningEngine.features.features[i].end.value = learningEngine.learningCurrent.learningEpisode.candle.end.value
}
/*
We will store at the Learning Engine data structure the features we have calculated.
At this point we need to decide if we are going to learn or going to predict.
This is regulated by the backLearningPredictingRatio property at the config
of the Learning Algorithm of the Learning Session.
*/
if (learningEngine.features.features[i] === undefined) { continue }
learningEngine.features.features[i].featureValue.value = featureValue
learningEngine.features.features[i].begin.value = learningEngine.learningCurrent.learningEpisode.candle.begin.value
learningEngine.features.features[i].end.value = learningEngine.learningCurrent.learningEpisode.candle.end.value
}
let backLearningPredictingRatio = 0.8 // this is the default value.
/*
At this point we need to decide if we are going to learn or going to predict.
This is regulated by the backLearningPredictingRatio property at the config
of the Learning Algorithm of the Learning Session.
*/
let backLearningPredictingRatio = 0.8 // this is the default value.
if (sessionParameters.learningAlgorithm !== undefined) {
if (sessionParameters.learningAlgorithm.config.backLearningPredictingRatio !== undefined) {
backLearningPredictingRatio = sessionParameters.learningAlgorithm.config.backLearningPredictingRatio
if (sessionParameters.learningAlgorithm !== undefined) {
if (sessionParameters.learningAlgorithm.config.backLearningPredictingRatio !== undefined) {
backLearningPredictingRatio = sessionParameters.learningAlgorithm.config.backLearningPredictingRatio
}
}
}
let initialCandle = Math.trunc(sessionParameters.timeRange.config.initialDatetime / sessionParameters.timeFrame.config.value)
let finalCandle = Math.trunc(sessionParameters.timeRange.config.finalDatetime / sessionParameters.timeFrame.config.value)
let currentCandle = Math.trunc(learningEngine.learningCurrent.learningEpisode.candle.begin.value / sessionParameters.timeFrame.config.value)
let thresholdCandle = (finalCandle - initialCandle) * backLearningPredictingRatio + initialCandle
let initialCandle = Math.trunc(sessionParameters.timeRange.config.initialDatetime / sessionParameters.timeFrame.config.value)
let finalCandle = Math.trunc(sessionParameters.timeRange.config.finalDatetime / sessionParameters.timeFrame.config.value)
let currentCandle = Math.trunc(learningEngine.learningCurrent.learningEpisode.candle.begin.value / sessionParameters.timeFrame.config.value)
let thresholdCandle = (finalCandle - initialCandle) * backLearningPredictingRatio + initialCandle;
if (currentCandle < thresholdCandle) {
await learn()
} else {
predict()
}
async function learn() {
/*
Building the Labels Tensor
*/
if (layersModel.outputLayer === undefined) {
// TODO
if (currentCandle < thresholdCandle) {
await pushFeaturesLabels();
} else {
if (!tensorFlowModelsManager.isTrained) {
await mlDataObj.dataEngineering(learningSystem);
await tensorFlowModelsManager.trainModel(mlDataObj);
}
predict()
}
if (layersModel.outputLayer.outputLabels === undefined) {
// TODO
async function pushFeaturesLabels() {
let labels = await getLabels(layersModel);
/* We will store at the Learning Engine data structure the labels we have calculated. */
for (let i = 0; i < layersModel.outputLayer.outputLabels.dataLabels.length; i++) {
if (learningEngine.labels.labels[i] === undefined) {
console.log("Warning: learning engine has no space to record label #" + (i+1));
continue;
}
learningEngine.labels.labels[i].labelValue.value = labels[i];
learningEngine.labels.labels[i].begin.value = learningEngine.learningCurrent.learningEpisode.candle.begin.value
learningEngine.labels.labels[i].end.value = learningEngine.learningCurrent.learningEpisode.candle.end.value
}
// Push this features/labels array to the Data Manager:
mlDataObj.addFeatures(features);
mlDataObj.addLabels(labels);
}
learningSystem.evalFormulas(layersModel.outputLayer.outputLabels, layersModel.outputLayer.outputLabels.type)
for (let i = 0; i < layersModel.outputLayer.outputLabels.dataLabels.length; i++) {
let dataLabel = layersModel.outputLayer.outputLabels.dataLabels[i]
if (dataLabel.labelFormula === undefined) { continue }
let labelValue = learningSystem.formulas.get(dataLabel.labelFormula.id)
labels.push(labelValue)
async function predict() {
let featuresTensor = tensorFlowBackend.tensor([features])
let predictions = tensorFlowModelsManager.model.predict(featuresTensor, { verbose: 1 })
/*
We will store at the Learning Engine data structure the labels we have calculated.
/*
We will download the predictions to an array, and we will store each one at the
learning engine data structure.
*/
if (learningEngine.labels.labels[i] === undefined) { continue }
learningEngine.labels.labels[i].labelValue.value = labelValue
learningEngine.labels.labels[i].begin.value = learningEngine.learningCurrent.learningEpisode.candle.begin.value
learningEngine.labels.labels[i].end.value = learningEngine.learningCurrent.learningEpisode.candle.end.value
}
let predictionsArray = predictions.dataSync()
predictions.dispose()
featuresTensor.dispose()
tensorFlowData = require("@tensorflow/tfjs-data")
function* featuresGenerator() {
//console.log('Features: ' + features)
yield features
}
function* labelsGenerator() {
//console.log('Labels: ' + labels)
yield labels
}
const xs = tensorFlowData.generator(featuresGenerator)
const ys = tensorFlowData.generator(labelsGenerator)
const ds = tensorFlowData.zip({ xs, ys }).shuffle(1).batch(1)
let verbose = 0
let ecpochs = 1
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset !== undefined) {
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset.verbose !== undefined) {
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset.verbose.config.value !== undefined) {
verbose = learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset.verbose.config.value
for (let i = 0; i < predictionsArray.length; i++) {
let prediction = predictionsArray[i]
if (isNaN(prediction)) {
prediction = 0
}
}
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset !== undefined) {
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset.epochs !== undefined) {
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset.epochs.config.value !== undefined) {
ecpochs = learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset.epochs.config.value
if (learningEngine.predictions.predictions[i] === undefined) {
console.log("Warning: learning engine has no space to record prediction #" + (i + 1));
continue;
}
learningEngine.predictions.predictions[i].predictionValue.value = prediction
learningEngine.predictions.predictions[i].begin.value = learningEngine.learningCurrent.learningEpisode.candle.begin.value
learningEngine.predictions.predictions[i].end.value = learningEngine.learningCurrent.learningEpisode.candle.end.value
}
}
await tensorFlowModel.fitDataset(ds, {
verbose: verbose,
epochs: ecpochs
})
/* Collecting the Features: */
async function getFeatures(layersModel) {
let features = []
}
learningSystem.evalFormulas(layersModel.inputLayer.inputFeatures, layersModel.inputLayer.inputFeatures.type);
async function predict() {
let featuresTensor = tensorFlowBackend.tensor([features])
let predictions = tensorFlowModel.predict(featuresTensor, { verbose: 1 })
/*
We will download the predictions to an array, and we will store each one at the
learning engine data structure.
*/
let predictionsArray = predictions.dataSync()
predictions.dispose()
featuresTensor.dispose()
for (let i = 0; i < predictionsArray.length; i++) {
let prediction = predictionsArray[i]
if (isNaN(prediction)) {
prediction = 0
for (let i = 0; i < fLen; i++) {
let dataFeature = layersModel.inputLayer.inputFeatures.dataFeatures[i];
if (dataFeature.featureFormula === undefined) { continue }
let featureValue = learningSystem.formulas.get(dataFeature.featureFormula.id);
features.push(featureValue);
}
if (learningEngine.predictions.predictions[i] === undefined) { continue }
learningEngine.predictions.predictions[i].predictionValue.value = prediction
learningEngine.predictions.predictions[i].begin.value = learningEngine.learningCurrent.learningEpisode.candle.begin.value
learningEngine.predictions.predictions[i].end.value = learningEngine.learningCurrent.learningEpisode.candle.end.value
return features;
}
/* Collecting the Labels: */
async function getLabels(layersModel) {
let labels = []
learningSystem.evalFormulas(layersModel.outputLayer.outputLabels, layersModel.outputLayer.outputLabels.type);
for (let i = 0; i < lLen; i++) {
let dataLabel = layersModel.outputLayer.outputLabels.dataLabels[i];
if (dataLabel.labelFormula === undefined) { continue }
let labelValue = learningSystem.formulas.get(dataLabel.labelFormula.id);
labels.push(labelValue);
}
return labels;
}
}
}
@@ -524,4 +296,69 @@ exports.newTensorFlowBotModulesTensorFlowLibrary = function (processIndex) {
}
throw 'Error Already Recorded'
}
/* validations() : This function validates that required nodes exist. */
function validations() {
let layersModel = learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel;
if (layersModel === undefined) {
requiredErr(">layers model<");
}
// Model Structure Validations:
if (layersModel.inputLayer === undefined) {
requiredErr(">input layer<");
}
if (layersModel.outputLayer === undefined) {
requiredErr(">output layer<");
}
if (layersModel.inputLayer.inputFeatures === undefined) {
requiredErr(">input features<");
}
if (layersModel.outputLayer.outputLabels === undefined) {
requiredErr(">output labels<");
}
if (layersModel.inputLayer.inputFeatures.dataFeatures.length === 0) {
requiredErr(">input data features<");
}
if (layersModel.outputLayer.outputLabels.dataLabels.length === 0) {
requiredErr(">output data labels<");
}
if (layersModel.layers.length === 0) {
requiredErr(">Could not find any layers<");
}
if (layersModel.inputLayer.referenceParent === undefined) {
requiredErr(">input layer missing reference parent<");
}
// Model Compiler Validations:
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile === undefined) {
requiredErr(">compile node<");
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.lossFunction === undefined) {
requiredErr(">loss function<");
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.lossFunction.config.value === undefined) {
requiredErr(">loss function value<");
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer === undefined) {
requiredErr(">optimizer node<");
}
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType === undefined) {
requiredErr(">optimizer type node<");
}
//* Feature Validations: */
// Data Features must be Uniquely Named:
/*let duplicates = () => {
let names = [];
layersModel.inputLayer.inputFeatures.dataFeatures.forEach(e => names.push(e.name));
return names;
};
if (layersModel.inputLayer.inputFeatures.dataFeatures.length !==
new Set(duplicates()).size) {
requiredErr(">All Data Feature nodes must be uniquely named<");
}*/
}
}
@@ -0,0 +1,375 @@
/*
* File: TensorFlowModelsManager.js
* TensorFlow Library Model types currently supported by SuperAlgos:
* 1.) Sequential Model
*
* History:
* 7/6/21: Start
* 8/24/21: Pushing as beta
*
* Contents:
* newTensorFlowModelsManager.thisObject,
* Model Manager Initialization ()=>{},
* sequentialModelSetup(),
* compileModel(),
* trainModel(),
* trainSequentialModel(),
* fitArgsConstructor()
*
*/
exports.newTensorFlowModelsManager = function (processIndex, learningSystem) {
const MODULE_NAME = 'Tensorflow Models Manager';
/* ModelsManager Variables/Objects/Dependencies Sections: */
const _tfjsCore = require("@tensorflow/tfjs-core");
var _tensorFlowAPI;
var _learningSystem;
var _tensorFlowModel;
let isTrained;
let modelType;
let thisObject = {
sequentialModelSetup: sequentialModelSetup,
compileModel: compileModel,
trainModel: trainModel,
get api() {return _tensorFlowAPI; },
get model() { return _tensorFlowModel; },
set model(value) {
_tensorFlowModel = value;
},
get isTrained() { return isTrained; },
};
// Model Manager Initialization:
( () => {
if (
learningSystem.machineLearningLibrary.typeOfLearning !== undefined &&
learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel !== undefined &&
learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model !== undefined &&
learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api !== undefined
) {
_learningSystem = learningSystem; // Record locally
isTrained = false;
switch (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.type) {
case 'Layers API': {
_tensorFlowAPI = require("@tensorflow/tfjs-layers")
if (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel === undefined) { return }
switch (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel.type) {
case 'Sequential Model': {
modelType = 'Sequential Model';
sequentialModelSetup();
break
}
case 'Functional Model': {
modelType = 'FunctionalModel';
// To be implemented some day...
break
}
}
break
}
case 'Core API': {
_tensorFlowAPI = require("@tensorflow/tfjs-core")
// To be implemented some day...
break
}
}
}
compileModel();
})();
return thisObject;
/* Model specific setup section: */
function sequentialModelSetup() {
let layersModel = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.api.layersModel;
/* Load the Model: */
_tensorFlowModel = _tensorFlowAPI.sequential();
/* Construct the layers and add to the model: */
for (let i = 0; i < layersModel.layers.length; i++) {
let layerNode = layersModel.layers[i];
let layerFunction; // The layer function.
let layerArgsObject = {}; // layerFunction's arguments.
let layerObject; // The completed layer.
if (layerNode.typeOfLayer === undefined) { continue }
if (layerNode.typeOfLayer.layer === undefined) { continue }
/* Assign tensorFlowAPI layer type to the layer function: */
switch (layerNode.typeOfLayer.layer.type) {
case 'Dense Layer': {
layerFunction = _tensorFlowAPI.layers.dense
break
}
/*case ' ': {
break
}
case ' ': {
break
}*/
default: {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
'[WARN] Layer of type ' + layerNode.typeOfLayer.layer.type + ' not implemented yet.')
continue
}
}
/* Construct layerArgsObject for this layerFunction via collecting the children of the layerNode: */
if (layerNode.typeOfLayer.layer.dimensionalityUnits !== undefined) {
layerArgsObject.units = layerNode.typeOfLayer.layer.dimensionalityUnits.config.value
} else {
layerArgsObject.units = 1
}
if (layerNode.typeOfLayer.layer.activationFunction !== undefined) {
layerArgsObject.activation = layerNode.typeOfLayer.layer.activationFunction.config.value
}
if (layerNode.typeOfLayer.layer.bias !== undefined) {
layerArgsObject.useBias = true
} else {
layerArgsObject.useBias = false
}
if (layerNode.typeOfLayer.layer.kernel !== undefined) {
if (layerNode.typeOfLayer.layer.kernel.kernelInitializer !== undefined) {
layerArgsObject.kernelInitializer = layerNode.typeOfLayer.layer.kernel.kernelInitializer.config.value
}
if (layerNode.typeOfLayer.layer.kernel.kernelConstraint !== undefined) {
layerArgsObject.kernelConstraint = layerNode.typeOfLayer.layer.kernel.kernelConstraint.config.value
}
if (layerNode.typeOfLayer.layer.kernel.kernelRegularizer !== undefined) {
layerArgsObject.kernelRegularizer = layerNode.typeOfLayer.layer.kernel.kernelRegularizer.config.value
}
}
if (layerNode.typeOfLayer.layer.bias !== undefined) {
if (layerNode.typeOfLayer.layer.bias.biasInitializer !== undefined) {
layerArgsObject.biasInitializer = layerNode.typeOfLayer.layer.bias.biasInitializer.config.value
}
if (layerNode.typeOfLayer.layer.bias.biasConstraint !== undefined) {
layerArgsObject.biasConstraint = layerNode.typeOfLayer.layer.bias.biasConstraint.config.value
}
if (layerNode.typeOfLayer.layer.bias.biasRegularizer !== undefined) {
layerArgsObject.biasRegularizer = layerNode.typeOfLayer.layer.bias.biasRegularizer.config.value
}
}
if (layerNode.typeOfLayer.layer.batchSize !== undefined) {
layerArgsObject.batchSize = layerNode.typeOfLayer.layer.batchSize.config.value
}
if (layerNode.typeOfLayer.layer.dtype !== undefined) {
layerArgsObject.dtype = layerNode.typeOfLayer.layer.dtype.config.value
}
if (layerNode.typeOfLayer.layer.trainable !== undefined) {
layerArgsObject.trainable = layerNode.typeOfLayer.layer.trainable.config.value
}
if (layerNode.typeOfLayer.layer.weights !== undefined) {
if (layerNode.typeOfLayer.layer.weights.tensor !== undefined) {
layerArgsObject.weights = layerNode.typeOfLayer.layer.weights.tensor.config.value
}
}
layerArgsObject.name = layerNode.typeOfLayer.layer.config.codeName;
/* Check if this is the input layer: */
if (layersModel.inputLayer.referenceParent.id === layerNode.id) {
/*
* If there is a explicitly defined Input Shape, then we will take it,
* otherwise, we will count the amount of features declared.
*/
if (layersModel.inputLayer.inputShape !== undefined) {
if (layerArgsObject.inputShape = layersModel.inputLayer.inputShape !== undefined) {
if (layerArgsObject.inputShape = layersModel.inputLayer.inputShape.config.value !== undefined) {
layerArgsObject.inputShape = layersModel.inputLayer.inputShape.config.value
}
}
}
if (layerArgsObject.inputShape === undefined) {
layerArgsObject.inputShape = [];
layerArgsObject.inputShape.push(layersModel.inputLayer.inputFeatures.dataFeatures.length);
}
}
/* Call the layerFunction and add layer to the model: */
layerObject = layerFunction(layerArgsObject);
_tensorFlowModel.add(layerObject);
}
}
/* Compile Models Section: */
function compileModel() {
/* optimizerBuilder() : builds and returns either a string or an tf.train.Optimizer:
* TF Docs: optimizer (string|tf.train.Optimizer) An instance of tf.train.Optimizer or a string name for an Optimizer.
*/
let optimizerBuilder = () => {
let optimizerType = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.type;
let learningRate, momentum, useNesterov, initAccVal, rho, decay, epsilon, beta1, beta2, centered;
switch(optimizerType) {
case 'Optimizer by Name': // For specifying string name as optimizer.
// This ensures acceptable type entered:
return _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.value;
// Following Cases for building instance of tf.train.Optimizer:
case 'SGD Instance':
learningRate = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.learningRate;
return _tfjsCore.train.sgd(learningRate);
case 'Momentum Instance':
learningRate = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.learningRate;
momentum = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.momentum;
useNesterov = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.useNesterov;
return _tfjsCore.train.momentum(learningRate, momentum, useNesterov);
case 'Adagrad Instance':
learningRate = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.learningRate;
initAccVal = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.initialAccumulatorValue;
return _tfjsCore.train.adagrad(learningRate, initAccVal);
case 'Adadelta Instance':
learningRate = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.learningRate;
rho = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.rho;
epsilon = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.epsilon;
return _tfjsCore.train.adadelta(learningRate, rho, epsilon);
case 'Adam Instance':
learningRate = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.learningRate;
beta1 = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.beta1;
beta2 = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.beta2;
epsilon = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.epsilon;
return _tfjsCore.train.adam(learningRate, beta1, beta2, epsilon);
case 'Rmsprop Instance':
learningRate = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.learningRate;
decay = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.decay;
momentum = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.momentum;
epsilon = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.epsilon;
centered = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.optimizer.optimizerType.config.centered;
return _tfjsCore.train.rmsprop(learningRate, decay, momentum, epsilon, centered);
default:
return false;
}
}
let compileMetrics;
if (_learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.metrics !== undefined &&
_learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.metrics.config.value !== undefined) {
compileMetrics = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.metrics.config.value;
}
// Collect, build and process optimizer type:
let optimizerBuild = optimizerBuilder();
let compileArgs = {
optimizer: optimizerBuild,
/* Loss Types: see: @tensorflow -> tf-layers.node.js:
* categoricalCrossentropy, sparseCategoricalCrossentropy, binaryCrossentropy, meanSquaredError ...
*/
loss: _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.compile.lossFunction.config.value,
metrics: compileMetrics
}
_tensorFlowModel.compile(compileArgs);
}
/* Fit Model Section: */
async function trainModel(mlDataObj) {
switch(modelType) {
case 'Sequential Model':
_tensorFlowModel.summary();
await trainSequentialModel(mlDataObj);
break;
case 'Functional Model':
// To be implemented some day...
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
'[WARN] Model of type ' + modelType + ' not yet implemented.');
throw new Error('Model Type: >' + modelType + '< not yet implemented');
default: {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
'[WARN] Model of type ' + modelType + ' not yet implemented.');
throw new Error('Model Type: >' + modelType + '< not yet implemented');
}
}
}
async function trainSequentialModel(mlDataObj) {
// Should we print state of mlDataObj:
let dataReporting = (learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.dataReporting !== undefined &&
learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.dataReporting.config.printDataReports === true) ? true : false;
if (dataReporting) {
mlDataObj.print();
}
let xTensor = mlDataObj.featuresTensor();
let yTensor = mlDataObj.labelsTensor();
let modelFitDatasetArgs = {};
// Should we collect any fitArgs:
if (_learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset !== undefined) {
modelFitDatasetArgs = fitArgsConstructor();
if (dataReporting) {
let fitKeys = Object.keys(modelFitDatasetArgs);
let fitVals = Object.values(modelFitDatasetArgs);
console.log("__________________________________________________\nModel Fitting Arguments:\n==================================================");
fitKeys.forEach((e, i) => console.log(i + ": \"" + e + "\"=>[" + fitVals[i] + "]"));
}
}
console.log("__________________________________________________\nTraining " +
_learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.name +
":\n==================================================");
const history = await _tensorFlowModel.fit(xTensor, yTensor, modelFitDatasetArgs);
isTrained = true;
if (dataReporting) {
console.log("\n__________________________________________________\nModel Fitting Report:\n==================================================");
console.log("First Epoch #1:\n\tacc=>" + history.history.acc[0] + "\n\tloss=>" + history.history.loss[0]);
let totalEpochs = history.epoch.length;
console.log("Final Epoch #" + totalEpochs + ":\n\tacc=>" + history.history.acc[totalEpochs - 1] + "\n\tloss=>" + history.history.loss[totalEpochs - 1] + "\n__________________________________________________");
}
}
/* Construct modelFitDatasetArgs by collecting available arguments: */
function fitArgsConstructor() {
let modelFitDatasetArgs = {};
let fitDatasetNode = _learningSystem.machineLearningLibrary.typeOfLearning.typeOfModel.model.fitDataset;
// verbose- Verbosity level:
if (fitDatasetNode.verbose !== undefined) {
if (fitDatasetNode.verbose.config.value !== undefined) {
modelFitDatasetArgs.verbose = fitDatasetNode.verbose.config.value
}
}
// epochs- Integer number of times to iterate over the training data arrays:
if (fitDatasetNode.epochs !== undefined) {
if (fitDatasetNode.epochs.config.value !== undefined) {
modelFitDatasetArgs.epochs = fitDatasetNode.epochs.config.value
}
}
// batchSize- Number of samples per gradient update. If unspecified, it will default to 32 per tf.org:
if (fitDatasetNode.datasetArgs !== undefined) {
if (fitDatasetNode.datasetArgs.batchesPerGradientUpdate !== undefined &&
fitDatasetNode.datasetArgs.batchesPerGradientUpdate.config.value !== undefined) {
modelFitDatasetArgs.batchSize = fitDatasetNode.datasetArgs.batchesPerGradientUpdate.config.value;
}
if (fitDatasetNode.datasetArgs.shuffle !== undefined &&
fitDatasetNode.datasetArgs.shuffle.config.booleanValue !== undefined) {
modelFitDatasetArgs.shuffle = fitDatasetNode.datasetArgs.shuffle.config.booleanValue;
}
// Future Add validation split:
}
// This callback hard coded for now:
modelFitDatasetArgs.callbacks = {
onEpochEnd: (epoch, logs) => console.log("callbacks:\tEpoch:" + epoch + " | Loss=>" + logs.loss)
}
return modelFitDatasetArgs;
}
}
File diff suppressed because it is too large. Load diff
@@ -4,9 +4,9 @@
"description": "Learning Bot",
"main": "TensorFlowLibrary.js",
"author": {
"name": "Luis-Fernando-Molina"
"name": "Luis-F-Molina && Philip-W-Love"
},
"dependencies": {
"@tensorflow/tfjs": "^3.6.0"
"@tensorflow/tfjs-node": "^3.8.0"
}
}
@@ -0,0 +1,28 @@
*** TensorFlow Project Todo Notes ***
8/24/21 - Beta Version being pushed to Code in order for people to begin experimenting with the functionality if they wish.
SA Devs Please Update the below with additional todo findings and/or the date in which a todo was completed.
Pending == Person has begun this work.
*TODO* *Completed*
================================================================
1.) New App-Schemas may require icons
2.) Access to Learn-Eng Predictions from Trade System Pending(Pluvtech)
3.) Integrate the idea of candle.future
4.) Test other loss types
a.) Tested so far: crossCategoricalEntropy, binaryEntropy
5.) Develop more data-engineering methods in MLDataManager.js
a.) Catch/Clean erroneous samples
b.) Expand logic to include more than one input, i.e.- Higher ranks for Functional Model implementation.
c.) Expose stats so they may be accessed from other parts of SA
d.) Add additional standardizing/normalizing functions
6.) ML - Tutorial
7.) ML - Medium Article for SA Pending(Pluvtech)
8.) Integrate additional types (functional model, unsupervised, ...)
9.) Test/implement custom bias types
10.) Test/fix so that things appear in charting space.
11.) Develop / share a better sample model plugin.
12.) Documentation for ML Project and Nodes. Pending(Pluvtech)
13.) Fix heatbeat spamming console Pending(Pluvtech)