UNPKG

pi-emergence

Version:
331 lines (264 loc) 12.9 kB
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Neuro Networks</title> <!-- The script includes need to be in this specific order --> <!-- Foundational includes --> <script src="../common/jquery-3.6.3.min.js" x-data="note: Only used in this index.html file for ui/ux"></script> <script src="../common/p5.js" x-data="note: Used for drawing and vector math (which is used for drawing)"></script> <script src="p5-neuro-drawer.js" x-data="note: Defines the neuron drawing function for the different neuron visual components"></script> <script src="../common/vector-handler.js" x-data="note: Defines the vector object, along with the respective math operations"></script> <script src="../common/app.js"></script> <script src="../common/agent.js"></script> <!-- Core includes --> <script src="components/neuron-matrix.js"></script> <script src="components/activation-function.js"></script> <script src="apps/app.matrix-neuro.js"></script> <!-- Visual includes --> <script src="components/neuron.js"></script> <script src="components/neuron-connector.js"></script> <script src="components/neuron-layer.js"></script> <script src="networks/feed-forward.js"></script> <script src="components/neuron-runner.js"></script> <script src="apps/app.visual-neuro.js"></script> <!-- Rendering includes --> <script src="sketch.neuro.js"></script> <!-- CSS/other --> <link href="../../css/fontawesome/css/fontawesome.min.css" rel="stylesheet"> <link href="../../css/fontawesome/css/brands.min.css" rel="stylesheet"> <link href="../../css/fontawesome/css/solid.min.css" rel="stylesheet"> <link href="../../css/styles.css" type="text/css" rel="stylesheet" /> </head> <body id="neuro"> <header> <div> <div id="ui-container" style="display:none;"> <div id="ui-legend"> </div> </div> <h1> <span class="page-title">Neuro - Neural Network</span> <span class="menu-item" id="menu-item-settings"> <span class="title" id="settings"> <label class="shown"><i class="fa-sharp fa-regular fa-caret-down"></i></label> <label class="not-shown"><i class="fa-sharp fa-regular fa-caret-right"></i></label> <label>Model Setup</label> </span> <span class="panel" id="settings-panel"> <span class="content"> <ul> <li> <span class="stack"> <strong>Input Parameters: <strong id="input-count">2</strong></strong> <p>Length of the input vector</p> <span><input type="range" min="2" max="2400.0" value="2" onchange="onRangeChange(this, 'setInputCount')" oninput="onRangeViewChange(this, 'input-count')" class="slider" id="input-count-value" /></span> </span> </li> <li> <span class="stack"> <strong>Hidden Layers: <strong id="hidden-layer-count">2</strong></strong> <p>Number of inner (hidden) layers</p> <span><input type="range" min="0" max="16" value="2" step="1" onchange="onRangeChange(this, 'setSpeed')" oninput="onRangeViewChange(this, 'hidden-layer-count')" class="slider" id="hidden-layer-count-value" /></span> </span> </li> <li> <span class="stack"> <strong>Output Labels: <strong id="output-count">2</strong></strong> <p>Number of labels</p> <span><input type="range" min="2" max="2400.0" value="2" onchange="onRangeChange(this, 'setOutputCount')" oninput="onRangeViewChange(this, 'output-count')" class="slider" id="output-count-value" /></span> </span> </li> </ul> </span> </span> </span> <span class="menu-item" id="menu-item-legend"> <span class="title" id="legend"> <label class="shown"><i class="fa-sharp fa-regular fa-caret-down"></i></label> <label class="not-shown"><i class="fa-sharp fa-regular fa-caret-right"></i></label> <label>I/O</label> </span> <span class="panel" id="legend-panel"> <span class="content"> <span class="stack footer keys"> <h3 class="first">Input Values</h3> <ul id="input-layer-values"> <li> <span><input checked type="checkbox" id="train-flag" /></span> <span>Use as Training</span> </li> </ul> <span><button id="input-value-button">Go</button></span> <h3>Import/Export</h3> <ul> <li><span>Import Json Weights</span></li> <li><span>Export Json Weights</span></li> </ul> </span> </span> </span> </span> </h1> <nav> <ul> <li><a href="https://www.jadecharles.com/" target="_jade"><i class="fa-solid fa-user"></i> JadeCharles.com</a></li> <li><a href="https://www.penumbralabs.io" target="_pi"><i class="fa-solid fa-flask"></i> PenumbraLabs.io</a></li> </ul> </nav> </div> </header> <main id="main-canvas"></main> <footer> <p id="footer"> <span id="main-menu"></span> <span id="main-version">v1.0.0</span> </p> </footer> <script src="../common/ui/ui.js"></script> <script> // ------ This is all the form event handlers and value setters */ App.initMainMenu({ neuro: true }); /** NeuroApp init */ NeuroApp.init(P5NeuroDrawer); var app = new NeuroApp(); window.onresize = function () { if (!app) return; app.updateCanvasSize(); app.network.refreshLayout(); } /** JQuery init */ $(document).ready(() => { const button = $("#input-value-button"); button.off(); // In case it was already bound button.click((ev) => { const inputs = getInputsFromForm(); testNetworkWithInputs(inputs); }); // Lazy way to wait for the UI to really be ready setTimeout(() => { if (!!app){ if (!app.addEventListeners()) console.warn("No event listeners added."); app.getInputValues = getInputsFromForm; } }, 750); }); /** Create HTML form fields for each of the input neurons */ function refreshInputFields(minValue = 0, maxValue = 1.0, step = 1) { if (!app) { console.log("No app. Exiting refreshInputFields"); return; } const elementList = $('#input-layer-values'); if (!app.network?.inputLayer) { console.warn("No network available. Set one up first"); return elementList; } const inputNeurons = app.network.inputLayer.neurons.filter((n) => !n.isBias).map((n, index) => { const elementId = 'input_param_' + index.toString(); const element = $('<li class="input-element"><input type="number" min="' + minValue + '" max="' + maxValue + '" value="' + n.value + '" id="' + elementId + '" /></li>'); return element; }); $('.input-element').remove(); elementList.append(inputNeurons); return elementList; } function addEventListeners() { if (!app) return; const canvas = app.setCanvasEventListeners(true); if (!canvas || !app.network) return; //canvas.onmousemove = (e) => app.handleMouseMove(e); // Handle Key Presses and other events document.addEventListener("keydown", (e) => { const k = e.key.toLowerCase(); app.selectedKeys[k] = true; switch (k) { case "escape": app.clearSelectedNeurons(); break; case "a": case "keya": app.network.execute(app.getInputValues(e)); break; case "t": case "keyt": const epocCount = 10000; console.log("Training and testing XOR example x" + epocCount + "..."); const trainedNetwork = NeuroApp.trainAndTestXor(new MatrixNeuroApp(2, 8, 4, 1), epocCount, 3); app.network.initWithMatrixNetwork(trainedNetwork); if (typeof app.refreshInputFields === "function") app.refreshInputFields(); else console.warn("No refreshInputFields() method found"); app.text = ""; break; case "r": case "keyr": app.randomizeWeights(); app.network.execute(app.getInputValues(e)); break; } }); document.addEventListener("keyup", (e) => { const k = e.key.toLowerCase(); delete app.selectedKeys[k]; // Keep track of keyup events for mult-select and other things }); console.log("Added event listeners: " + (canvas !== null).toString()); return canvas; } function testNetworkWithInputs(inputs) { if (!app) { console.log("No app. Exiting testNetworkWithInputs"); return; } if (!!app.network.matrixNetwork) { const nnResult = app.network.executeMatrix(inputs); console.log("Matrix Results:"); console.table(nnResult); } const piResult = app.network.execute(inputs); console.log("Pi Results:"); console.table(piResult); } function onRangeChange(e) { const input = $(e); const value = input.val(); const id = input.attr('id'); console.log("RangeId: " + id + ", Value: " + value); refreshInputFields(); } function onRangeViewChange(e) { if (!app) { console.log("No app. Exiting onRangeViewChange"); return; } const input = $(e); const value = input.val(); const id = input.attr('id'); app.network.initWithMatrixNetwork(nn); } if (!!app && !app.refreshInputFields) app.refreshInputFields = refreshInputFields; /** Get inputs from fields and convert them to an array */ function getInputsFromForm(sender) { let inputs = []; let i = 0; while (true) { const element = $(`#input_param_${i}`); if (!!element.get(0)) { const value = parseFloat(element.val()) if (isNaN(value)) { const message = "Bad value: " + element.val(); alert(message); throw new Error(message); } inputs.push(value); i++; } else return inputs; } return inputs; } </script> </body> </html>