Commit 30e0d837 authored by Petr Kubeš's avatar Petr Kubeš

ui changes

parent 59cc62c2
[Dolphin]
Timestamp=2018,7,5,23,50,32
Timestamp=2018,7,22,18,0,30
Version=4
[Settings]
HiddenFilesShown=true
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -17,27 +17,38 @@
<body>
<div class="container mt-3">
<div class="custom-control custom-checkbox" style="float: right;">
<input type="checkbox" class="custom-control-input" id="customCheck1" checked="checked">
<label class="custom-control-label" for="customCheck1">Show ads</label>
</div>
<h1>Neural network visualized</h1>
<p class="lead">Visualization of a simple neural network for strictly educational purposes.</p>
<hr>
<div class="container-fluid" id="controls">
<div class="row">
<div class="col-md-3">
<h5>Input values</h5>
<div id="input-controls"></div>
</div>
<div class="col-md-3">
<div class="col-md-4">
<h5>Network size</h5>
<table id="layer-controls">
</table>
</div>
<div class="col-md-3">
<div class="col-md-4 pr-5">
<h5>Learning settings</h5>
<div class="row">
<label for="rate-input" class="control-label col-8">Learning rate:</label>
<input class="form-control form-control-sm col-4" id="rate-input" type="number" name="rate" min="0" max="10" step="0.1" value="1">
<select class="form-control form-control-sm col-4" id="rate-input">
<option value="0.001">0.001</option>
<option value="0.003">0.003</option>
<option value="0.01">0.01</option>
<option value="0.03">0.03</option>
<option value="0.1">0.1</option>
<option value="0.3">0.3</option>
<option value="1" selected="true">1</option>
<option value="3">3</option>
<option value="10">10</option>
<option value="30">30</option>
</select>
</div>
<div class="row">
<div class="row mt-1 mb-1">
<label for="regularization-input" class="col-8">Regularization:</label>
<select class="form-control form-control-sm col-4" id="regularization-type-input">
<option value="none">None</option>
......@@ -47,11 +58,25 @@
</div>
<div class="row">
<label for="regularization-input" class="col-8">Regularization rate:</label>
<input class="form-control form-control-sm col-4" id="regularization-rate-input" type="number" name="rate" min="0" max="10"
step="0.1" value="0.1">
<select class="form-control form-control-sm col-4" id="regularization-rate-input">
<option value="0.00001">0.00001</option>
<option value="0.00003">0.00003</option>
<option value="0.0001">0.0001</option>
<option value="0.0003" selected="true">0.0003</option>
<option value="0.001">0.001</option>
<option value="0.003">0.003</option>
<option value="0.01">0.01</option>
<option value="0.03">0.03</option>
<option value="0.1">0.1</option>
<option value="0.3">0.3</option>
<option value="1">1</option>
<option value="3">3</option>
<option value="10">10</option>
<option value="30">30</option>
</select>
</div>
</div>
<div class="col-md-3">
<div class="col-md-4 pr-5">
<h5>Train</h5>
<div class="row">
<label for="iters-input" class="col-8">Num. of iterations:</label>
......@@ -68,7 +93,13 @@
<div class="row">
<div class="col-4">
<h5>Training set input</h5>
<textarea class="form-control" id="training-set-input" rows="3"></textarea>
<textarea class="form-control" id="training-set-input" rows="6">
[
[[1,1],[0]],
[[1,0],[1]],
[[0,1],[1]],
[[0,0],[0]]
]</textarea>
<button type="button" class="btn btn-outline-primary btn-sm mt-3" onclick="setTrainingData()">Set training data</button>
</div>
<div class="col-8">
......@@ -76,7 +107,6 @@
<table class="table table-sm table-bordered table-hover table-striped">
<thead class="thead-dark">
<tr id="training-set-neurons-output">
</tr>
</thead>
<tbody id="training-set-data-output">
......@@ -91,14 +121,21 @@
<button type="button" class="btn btn-secondary" onclick="train(false)">Step</button>
<button type="button" class="btn btn-danger" onclick="reset()">Reset</button>
</div>
<div class="col-md-auto">
<div class="col-md-auto" style="padding-top: 5px;">
Cost:
<b id="cost"></b>
</div>
</div>
</div>
<div id="input-controls"></div>
<canvas id="content" width="1200" height="600" style="border: 5px solid #2E282A; margin-bottom: 1em">Sorry, you need a better browser to see the neural net.</canvas>
<div>
<h2>What is this?</h2>
<p>
This is implementation of neural network with back-propagation. blablabla
</p>
</div>
<canvas id="content" width="1200" height="600" style="border: 5px solid #2E282A; margin-bottom: 70px;"></canvas>
</div>
</body>
......
......@@ -9,4 +9,15 @@
#controls b {
margin: auto 0px;
}
#input-controls {
position: relative;
}
input[type=range][orient=vertical]
{
writing-mode: bt-lr; /* IE */
-webkit-appearance: slider-vertical; /* WebKit */
width: 8px;
}
\ No newline at end of file
......@@ -7,13 +7,15 @@ export class DrawableNeuron {
public activation: number;
public name: string;
public isBias: boolean;
public id: number;
constructor(x, y, activation, name, isBias = false) {
constructor(x, y, activation, name, id, isBias = false) {
this.x = x;
this.y = y;
this.activation = activation;
this.name = name;
this.isBias = isBias;
this.id = id;
}
}
......@@ -23,6 +25,8 @@ export class Visualizer {
private ctx: CanvasRenderingContext2D;
private height: number;
private width: number;
private drawableNeurons: DrawableNeuron[];
private drawableInputNeurons: DrawableNeuron[];
constructor(content: HTMLCanvasElement) {
this.content = content;
......@@ -34,7 +38,8 @@ export class Visualizer {
public draw(neurons: Neuron[][], connections: Connection[][]) {
this.ctx.clearRect(0, 0, this.width, this.height);
const drawableNeurons: DrawableNeuron[] = [];
this.drawableNeurons = [];
this.drawableInputNeurons = [];
const leftMargin = this.width / (neurons.length + 1);
// Neurons
......@@ -44,22 +49,26 @@ export class Visualizer {
const x = leftMargin * (1 + lIdx);
const y = topMargin * (1 + nIdx);
const drawableNeuron = new DrawableNeuron(x, y, neuron.getActivation(), neuron.getName());
drawableNeurons.push(drawableNeuron);
const drawableNeuron = new DrawableNeuron(x, y, neuron.getActivation(), neuron.getName(), nIdx);
this.drawableNeurons.push(drawableNeuron);
if (lIdx === 0) {
this.drawableInputNeurons.push(drawableNeuron);
}
});
if (lIdx != neurons.length - 1) {
const x = leftMargin * (1 + lIdx);
const y = topMargin * (1 + neurons[lIdx].length);
const drawableNeuron = new DrawableNeuron(x, y, 1, `bias${lIdx}`, true);
drawableNeurons.push(drawableNeuron);
const drawableNeuron = new DrawableNeuron(x, y, 1, `bias${lIdx}`, neurons[lIdx].length, true);
this.drawableNeurons.push(drawableNeuron);
}
});
// Connections
const drawableNameMap = new Map<string, DrawableNeuron>();
drawableNeurons.forEach(
this.drawableNeurons.forEach(
(drawableNeuron) => drawableNameMap.set(drawableNeuron.name, drawableNeuron)// WTF, I was not able to create map from 2d arr
);
......@@ -78,7 +87,7 @@ export class Visualizer {
});
});
drawableNeurons.forEach((neuron) => {
this.drawableNeurons.forEach((neuron) => {
this.drawNeuron(neuron);
});
}
......@@ -117,11 +126,15 @@ export class Visualizer {
Math.log(weight) :
Math.log(-weight);
this.ctx.strokeStyle = (weight > 0) ?
`rgba(205, 83, 52, ${weight})` :
`rgba(61, 232, 255, ${weight * -1})`;
`rgba(205, 83, 52, 1)` :
`rgba(61, 232, 255, 1)`;
this.ctx.moveTo(inputNeuron.x, inputNeuron.y);
this.ctx.lineTo(outputNeuron.x, outputNeuron.y);
this.ctx.closePath();
this.ctx.stroke();
}
public getDrawableInputNeurons() {
return this.drawableInputNeurons;
}
}
import { Visualizer } from './Visualizer';
import { Visualizer, DrawableNeuron } from './Visualizer';
import { NeuralCore } from './neuralNetwork/NeuralCore';
import { Regularizations, TrainSample } from './neuralNetwork/HelperObjects';
import { Neuron } from './neuralNetwork/Neuron';
(window as any).slide = (i: number, value: number) => {
input[i] = value;
......@@ -10,10 +11,7 @@ import { Regularizations, TrainSample } from './neuralNetwork/HelperObjects';
(window as any).addOrRemoveLayer = (add: boolean) => {
neuralCore.addOrRemoveLayer(add);
neuralCore.evaluate(input);
updateUI();
visualizer.draw(neuralCore.getNeurons(), neuralCore.getConnections());
}
(window as any).addOrRemoveNeuron = (add: boolean, layerIdx: number) => {
......@@ -24,10 +22,8 @@ import { Regularizations, TrainSample } from './neuralNetwork/HelperObjects';
else
input.pop();
}
neuralCore.evaluate(input);
updateUI();
visualizer.draw(neuralCore.getNeurons(), neuralCore.getConnections());
}
(window as any).train = (multipleIters: boolean) => {
......@@ -53,9 +49,7 @@ import { Regularizations, TrainSample } from './neuralNetwork/HelperObjects';
neuralCore.train();
}
neuralCore.evaluate(input);
updateUI();
visualizer.draw(neuralCore.getNeurons(), neuralCore.getConnections());
}
(window as any).setTrainingData = () => {
......@@ -74,9 +68,12 @@ import { Regularizations, TrainSample } from './neuralNetwork/HelperObjects';
(window as any).reset = () => {
neuralCore.reset();
neuralCore.evaluate(input);
updateUI();
visualizer.draw(neuralCore.getNeurons(), neuralCore.getConnections());
}
(window as any).applyTrainingSample = (idx: number) => {
input = neuralCore.getTrainingSamples()[idx].input;
updateUI();
}
window.onload = () => {
......@@ -87,11 +84,12 @@ let neuralCore: NeuralCore;
let visualizer: Visualizer;
let input: number[];
let inputSize = 4;
let inputSize = 2;
let hiddenSizes = [3];
let outputSize = 4;
let outputSize = 1;
let layerControls: HTMLElement;
let inputControls: HTMLElement;
let canvas: HTMLCanvasElement;
let cost: HTMLElement;
let iter: HTMLElement;
......@@ -106,7 +104,7 @@ let trainingSetDataOutput: HTMLElement;
let trainingSetInput: HTMLInputElement;
const main = () => {
const content: HTMLCanvasElement = document.getElementById('content') as HTMLCanvasElement;
canvas = document.getElementById('content') as HTMLCanvasElement;
inputControls = document.getElementById('input-controls');
layerControls = document.getElementById('layer-controls');
iter = document.getElementById('iter-output');
......@@ -119,7 +117,7 @@ const main = () => {
trainingSetLabelsOutput = document.getElementById('training-set-neurons-output') as HTMLInputElement;
trainingSetInput = document.getElementById('training-set-input') as HTMLInputElement;
visualizer = new Visualizer(content);
visualizer = new Visualizer(canvas);
initCore();
}
......@@ -127,9 +125,10 @@ const main = () => {
const initCore = () => {
neuralCore = new NeuralCore(inputSize, hiddenSizes, outputSize);
neuralCore.addTrainingSet([1, 0, 0, 0], [0, 1, 0, 0]);
neuralCore.addTrainingSet([0, 1, 0, 0], [0, 0, 1, 0]);
neuralCore.addTrainingSet([0, 0, 1, 0], [0, 0, 0, 1]);
neuralCore.addTrainingSet([1, 1], [0]);
neuralCore.addTrainingSet([1, 0], [1]);
neuralCore.addTrainingSet([0, 1], [1]);
neuralCore.addTrainingSet([0, 0], [0]);
// Set default values
input = new Array(neuralCore.getInputSize());
......@@ -137,10 +136,12 @@ const initCore = () => {
neuralCore.evaluate(input);
updateUI();
visualizer.draw(neuralCore.getNeurons(), neuralCore.getConnections());
}
const updateUI = () => {
neuralCore.evaluate(input);
visualizer.draw(neuralCore.getNeurons(), neuralCore.getConnections());
let content = addLayerControlRow(
'Layers',
neuralCore.getLayerCnt().toString(),
......@@ -175,10 +176,22 @@ const updateUI = () => {
layerControls.innerHTML = content;
inputControls.innerHTML = '';
for (let i = 0; i < neuralCore.getInputSize(); i++) {
inputControls.innerHTML += `<label>Neuron ${i}:</label> <input style="position: relative; top: 5px;" type="range" min="0" max="1" value="1" step="0.05" id="slider${i}" oninput="slide(${i}, this.value);"><br>`;
if (!visualizer.getDrawableInputNeurons()) {
visualizer.draw(neuralCore.getNeurons(), neuralCore.getConnections());
}
const controlHeight = 50;
visualizer.getDrawableInputNeurons().forEach((neuron: DrawableNeuron) => {
const x = neuron.x - 50;
const y = neuron.y - controlHeight / 2 + 5;
inputControls.innerHTML += `<input
style="position: absolute; top: ${y}px; left: ${x}px; height: ${controlHeight}px;"
type="range" orient="vertical" min="0" max="1" value="${neuron.activation}" step="0.05"
oninput="slide(${neuron.id}, this.value);">`;
})
iter.innerHTML = neuralCore.getIteration().toString();
cost.innerHTML = neuralCore.getCost().toString();
......@@ -194,8 +207,8 @@ const updateUI = () => {
// Add training data
let trainingData = '';
neuralCore.getTrainingSamples().forEach(sample => {
trainingData += '<tr>';
neuralCore.getTrainingSamples().forEach((sample, idx) => {
trainingData += `<tr style="cursor:pointer;" onclick="applyTrainingSample(${idx})">`;
sample.input.forEach(val => {
trainingData += `<td>${val}</td>`;
});
......
......@@ -67,6 +67,7 @@ export class NeuralCore {
}
public evaluate(input: number[]): number[] {
if (input.length != this.inputSize) {
throw 'Input size does not match';
}
......@@ -83,6 +84,12 @@ export class NeuralCore {
}
public addTrainingSet(input: number[], output: number[]) {
if (input.length != this.inputSize) {
throw 'Input size does not match';
} else if (output.length != this.outputSize) {
throw 'Output size does not match';
}
this.trainSamples.push(new TrainSample(input, output))
}
......@@ -304,6 +311,7 @@ export class NeuralCore {
}
public reset() {
this.iterCnt = 0;
this.createConnections(0, this.layerCnt - 1);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment