pi-emergence
Version:
Various emergent phenomena
331 lines (264 loc) • 12.9 kB
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>