Skip to content

Commit 5cda536

Browse files
committed
Added training controls and logger.
1 parent b25b8f5 commit 5cda536

File tree

4 files changed

+190
-95
lines changed

4 files changed

+190
-95
lines changed

wasm/network_interface.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
class NetworkController {
1616
private:
17-
nn::vi_t dimensions;
17+
nn::vi_t dimensions = {2, 3, 2};
1818
nn::act::Function actFunction = nn::act::relu;
1919
nn::loss::function_t lossFunction = nn::loss::sse;
2020
double alpha = 0.1;
@@ -49,6 +49,10 @@ class NetworkController {
4949
}
5050

5151
public:
52+
NetworkController() {
53+
build();
54+
}
55+
5256
~NetworkController() {
5357
delete inTrainFile;
5458
delete outTrainFile;

web/content/control-panel.html

Lines changed: 174 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,206 @@
1-
<div id="controlAccordion" class="accordion py-4">
1+
<div id="controlAccordion" class="accordion py-5">
22
<div class="accordion-item">
33
<h2 class="accordion-header">
4-
<button class="accordion-button" type="button" data-bs-toggle="collapse"
4+
<button class="accordion-button lead fs-4" type="button" data-bs-toggle="collapse"
55
data-bs-target="#controlCollapseOne" aria-expanded="false" aria-controls="controlCollapseOne">
66
Load Your Data
77
</button>
88
</h2>
99
<div id="controlCollapseOne" class="accordion-collapse collapse show" data-bs-parent="#controlAccordion">
10-
<div class="accordion-body row gy-4">
11-
<div class="col">
12-
<h5>Training Data</h5>
13-
<div class="btn-group">
14-
<p class="btn btn-light" id="inputTrainingDataButton"
15-
onclick="network.promptInputTrainingData()">Browse Input File</p>
16-
<p class="btn btn-light" id="outputTrainingDataButton"
17-
onclick="network.promptOutputTrainingData()">Browse Output File</p>
10+
<div class="accordion-body py-5">
11+
<div class="row">
12+
<div class="col">
13+
<h5>Training Data</h5>
14+
<div class="btn-group">
15+
<p class="btn btn-light" id="inputTrainingDataButton"
16+
onclick="network.promptInputTrainingData()">Browse Input File</p>
17+
<p class="btn btn-light" id="outputTrainingDataButton"
18+
onclick="network.promptOutputTrainingData()">Browse Output File</p>
19+
</div>
20+
<div class="d-inline-block">
21+
<p class="btn btn-primary" id="prepareTrainingDataButton"
22+
onclick="network.prepareTrainingData()">Load</p>
23+
<p class="btn btn-danger" id="clearTrainingDataButton"
24+
onclick="onClearTrainingData()">Clear</p>
25+
</div>
1826
</div>
19-
<p class="btn btn-primary" id="prepareTrainingDataButton"
20-
onclick="network.prepareTrainingData()">Load</p>
21-
<p class="btn btn-danger" id="clearTrainingDataButton"
22-
onclick="onClearTrainingData()">Clear</p>
23-
</div>
24-
<div class="col">
25-
<h5>Testing Data</h5>
26-
<div class="btn-group">
27-
<p class="btn btn-light" id="inputTestingDataButton"
28-
onclick="network.promptInputTestingData()">Browse Input File</p>
29-
<p class="btn btn-light" id="outputTestingDataButton"
30-
onclick="network.promptOutputTestingData()">Browse Output File</p>
27+
<div class="col">
28+
<h5>Testing Data</h5>
29+
<div class="btn-group">
30+
<p class="btn btn-light" id="inputTestingDataButton"
31+
onclick="network.promptInputTestingData()">Browse Input File</p>
32+
<p class="btn btn-light" id="outputTestingDataButton"
33+
onclick="network.promptOutputTestingData()">Browse Output File</p>
34+
</div>
35+
<div class="d-inline-block">
36+
<p class="btn btn-primary" id="prepareTestingDataButton"
37+
onclick="network.prepareTestingData()">Load</p>
38+
<p class="btn btn-danger" id="clearTestingDataButton"
39+
onclick="onClearTestingData()">Clear</p>
40+
</div>
3141
</div>
32-
<p class="btn btn-primary" id="prepareTestingDataButton"
33-
onclick="network.prepareTestingData()">Load</p>
34-
<p class="btn btn-danger" id="clearTestingDataButton"
35-
onclick="onClearTestingData()">Clear</p>
3642
</div>
43+
<script>
44+
function onDataFileSet(element, filename, dataSize) {
45+
element.setAttribute('data-size', dataSize);
46+
element.innerHTML = filename + "<br>" + "Valid Rows: " + Number(dataSize);
47+
element.classList.add('active');
48+
}
49+
50+
function onInputTrainingFileSet(filename, dataSize) {
51+
onDataFileSet(document.getElementById('inputTrainingDataButton'), filename, dataSize);
52+
}
53+
54+
function onOutputTrainingFileSet(filename, dataSize) {
55+
onDataFileSet(document.getElementById('outputTrainingDataButton'), filename, dataSize);
56+
}
57+
58+
function onInputTestingFileSet(filename, dataSize) {
59+
onDataFileSet(document.getElementById('inputTestingDataButton'), filename, dataSize);
60+
}
61+
62+
function onOutputTestingFileSet(filename, dataSize) {
63+
onDataFileSet(document.getElementById('outputTestingDataButton'), filename, dataSize);
64+
}
65+
66+
function onTrainingDataPrepared(dataSize) {
67+
showSimpleToast("<h5>Loaded " + dataSize + " Valid Rows</h5>");
68+
}
69+
70+
function onTestingDataPrepared(dataSize) {
71+
showSimpleToast("<h5>Loaded " + dataSize + " Valid Rows</h5>");
72+
}
73+
74+
function onClearFileData(input, output) {
75+
input.removeAttribute('data-size');
76+
input.classList.remove('active');
77+
input.innerHTML = "Browse Input File";
78+
output.removeAttribute('data-size');
79+
output.classList.remove('active');
80+
output.innerHTML = "Browse Output File";
81+
}
82+
83+
function onClearTrainingData() {
84+
const input = document.getElementById('inputTrainingDataButton');
85+
const output = document.getElementById('outputTrainingDataButton');
86+
onClearFileData(input, output);
87+
}
88+
89+
function onClearTestingData() {
90+
const input = document.getElementById('inputTestingDataButton');
91+
const output = document.getElementById('outputTestingDataButton');
92+
onClearFileData(input, output);
93+
}
94+
</script>
3795
</div>
3896
</div>
3997
</div>
4098
<div class="accordion-item">
4199
<h2 class="accordion-header">
42-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
100+
<button class="accordion-button collapsed lead fs-4" type="button" data-bs-toggle="collapse"
43101
data-bs-target="#controlCollapseTwo" aria-expanded="false" aria-controls="controlCollapseTwo">
44-
2
102+
Train It
45103
</button>
46104
</h2>
47105
<div id="controlCollapseTwo" class="accordion-collapse collapse" data-bs-parent="#controlAccordion">
48-
<div class="accordion-body row gy-4">
106+
<div class="accordion-body py-5">
107+
<div class="row justify-content-center">
108+
<div class="col">
109+
<h5 class="py-4">Epochs:</h5>
110+
<div class="btn-group" role="group" aria-label="Basic radio toggle button group">
111+
<input type="radio" class="btn-check" name="epochsRadio" id="epochsRadio1"
112+
autocomplete="off" value="1" checked>
113+
<label class="btn btn-light fs-5" for="epochsRadio1">1</label>
114+
<input type="radio" class="btn-check" name="epochsRadio" id="epochsRadio5"
115+
autocomplete="off" value="5">
116+
<label class="btn btn-light fs-5" for="epochsRadio5">5</label>
117+
<input type="radio" class="btn-check" name="epochsRadio" id="epochsRadio10"
118+
autocomplete="off" value="10">
119+
<label class="btn btn-light fs-5" for="epochsRadio10">10</label>
120+
<input type="radio" class="btn-check" name="epochsRadio" id="epochsRadio50"
121+
autocomplete="off" value="50">
122+
<label class="btn btn-light fs-5" for="epochsRadio50">50</label>
123+
<input type="radio" class="btn-check" name="epochsRadio" id="epochsRadio100"
124+
autocomplete="off" value="100">
125+
<label class="btn btn-light fs-5" for="epochsRadio100">100</label>
126+
<button type="button" title="start" id="startTrainingButton" onclick="startTraining()"
127+
class="btn btn-lg btn-success bi bi-play-fill fs-5"></button>
128+
</div>
129+
<div>
130+
<h5 class="py-4">Options:</h5>
131+
<div class="px-2">
132+
<div class="form-check">
133+
<input class="form-check-input" type="checkbox" id="useTestDataCheck">
134+
<label class="form-check-label" for="useTestDataCheck">
135+
Use Testing Data
136+
</label>
137+
</div>
138+
</div>
139+
</div>
140+
<hr class="my-4">
141+
<div>
142+
<button type="button" title="start" id="refreshWeightsButton" onclick="network.build()"
143+
class="btn btn-lg btn-danger bi bi-arrow-clockwise fs-5"> Randomize Weights
144+
</button>
145+
</div>
146+
</div>
147+
<div class="col">
148+
<h5 class="py-4">Training Errors:</h5>
149+
<div id="trainingLogger"></div>
150+
</div>
151+
<div class="col">
152+
<h5 class="py-4">Testing Errors:</h5>
153+
<div id="testingLogger"></div>
154+
</div>
155+
</div>
156+
<script>
157+
function startTraining() {
158+
const trainLogger = document.getElementById('trainingLogger');
159+
const testLogger = document.getElementById('testingLogger');
160+
trainLogger.innerHTML = "";
161+
testLogger.innerHTML = "";
162+
163+
const epochs = getSelectedEpochValue();
164+
let res;
165+
if (document.getElementById('useTestDataCheck').checked) {
166+
res = network.trainAndTestFor(epochs);
167+
for (let i = 0; i < res.size(); ++i) {
168+
trainLogger.innerHTML += "<p>" + res.get(i).get(0) + "</p>";
169+
testLogger.innerHTML += "<p>" + res.get(i).get(1) + "</p>";
170+
}
171+
} else {
172+
res = network.trainFor(epochs);
173+
for (let i = 0; i < res.size(); ++i) {
174+
trainLogger.innerHTML += "<p>" + res.get(i) + "</p>";
175+
}
176+
}
177+
}
178+
179+
function getSelectedEpochValue() {
180+
const radioButtons = document.querySelectorAll('input[name="epochsRadio"]');
181+
for (const radioButton of radioButtons) {
182+
if (radioButton.checked) {
183+
return Number(radioButton.value);
184+
}
185+
}
186+
}
187+
</script>
49188
</div>
50189
</div>
51190
</div>
52191
<div class="accordion-item">
53192
<h2 class="accordion-header">
54-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
193+
<button class="accordion-button collapsed lead fs-4" type="button" data-bs-toggle="collapse"
55194
data-bs-target="#controlCollapseThree" aria-expanded="false" aria-controls="controlCollapseThree">
56-
3
195+
Test It
57196
</button>
58197
</h2>
59198
<div id="controlCollapseThree" class="accordion-collapse collapse" data-bs-parent="#controlAccordion">
60-
<div class="accordion-body row gy-4">
199+
<div class="accordion-body">
200+
<div class="row gy-4">
201+
202+
</div>
61203
</div>
62204
</div>
63205
</div>
64206
</div>
65-
<script>
66-
function onDataFileSet(element, filename, dataSize) {
67-
element.setAttribute('data-size', dataSize);
68-
element.innerHTML = filename + "<br>" + "Valid Rows: " + Number(dataSize);
69-
element.classList.add('active');
70-
}
71-
72-
function onInputTrainingFileSet(filename, dataSize) {
73-
onDataFileSet(document.getElementById('inputTrainingDataButton'), filename, dataSize);
74-
}
75-
76-
function onOutputTrainingFileSet(filename, dataSize) {
77-
onDataFileSet(document.getElementById('outputTrainingDataButton'), filename, dataSize);
78-
}
79-
80-
function onInputTestingFileSet(filename, dataSize) {
81-
onDataFileSet(document.getElementById('inputTestingDataButton'), filename, dataSize);
82-
}
83-
84-
function onOutputTestingFileSet(filename, dataSize) {
85-
onDataFileSet(document.getElementById('outputTestingDataButton'), filename, dataSize);
86-
}
87-
88-
function onTrainingDataPrepared(dataSize) {
89-
showSimpleToast("<h5>Loaded " + dataSize + " Valid Rows</h5>");
90-
}
91-
92-
function onTestingDataPrepared(dataSize) {
93-
showSimpleToast("<h5>Loaded " + dataSize + " Valid Rows</h5>");
94-
}
95-
96-
function onClearFileData(input, output) {
97-
input.removeAttribute('data-size');
98-
input.classList.remove('active');
99-
input.innerHTML = "Browse Input File";
100-
output.removeAttribute('data-size');
101-
output.classList.remove('active');
102-
output.innerHTML = "Browse Output File";
103-
}
104-
105-
function onClearTrainingData() {
106-
const input = document.getElementById('inputTrainingDataButton');
107-
const output = document.getElementById('outputTrainingDataButton');
108-
onClearFileData(input, output);
109-
}
110-
111-
function onClearTestingData() {
112-
const input = document.getElementById('inputTestingDataButton');
113-
const output = document.getElementById('outputTestingDataButton');
114-
onClearFileData(input, output);
115-
}
116-
</script>

web/content/visualizer.html

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@
1414
network.setActivationFunction(document.getElementById('activationFunctionInput').value);
1515
network.setLossFunction(document.getElementById('lossFunctionInput').value);
1616
network.setLearningRate(document.getElementById('learningRateInput').value);
17-
updateNetworkDimensions(structure)
17+
updateNetworkDimensions(structure);
1818
}
1919
</script>
20-
<div id="visualizerAccordion" class="accordion py-4">
20+
<div id="visualizerAccordion" class="accordion py-5">
2121
<div class="accordion-item" oninput="onStructureChange()">
2222
<h2 class="accordion-header">
23-
<button class="accordion-button" type="button" data-bs-toggle="collapse"
23+
<button class="accordion-button lead fs-4" type="button" data-bs-toggle="collapse"
2424
data-bs-target="#visualizerCollapseOne" aria-expanded="true" aria-controls="visualizerCollapseOne">
2525
Structure Controls
2626
</button>
2727
</h2>
2828
<div id="visualizerCollapseOne" class="accordion-collapse collapse show" data-bs-parent="#visualizerAccordion">
29-
<div class="accordion-body">
30-
<div class="container p-4 flex-column gap-4">
31-
<div class="row row-cols-1 row-cols-lg-3 gx-4">
29+
<div class="accordion-body py-5">
30+
<div class="container flex-column gap-4">
31+
<div class="row row-cols-1 row-cols-lg-3 g-4">
3232
<div class="col">
3333
<label for="inputLayerHeight" class="form-label">Input Layer Height</label>
3434
<input type="range" class="form-range" min="1" max="10" step="1" id="inputLayerHeight"
@@ -51,26 +51,26 @@ <h2 class="accordion-header">
5151
</div>
5252
<div class="accordion-item" oninput="onStructureChange()">
5353
<h2 class="accordion-header">
54-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
54+
<button class="accordion-button collapsed lead fs-4" type="button" data-bs-toggle="collapse"
5555
data-bs-target="#visualizerCollapseTwo" aria-expanded="false" aria-controls="visualizerCollapseTwo">
5656
Hidden Layers Heights
5757
</button>
5858
</h2>
5959
<div id="visualizerCollapseTwo" class="accordion-collapse collapse" data-bs-parent="#visualizerAccordion">
60-
<div class="accordion-body">
60+
<div class="accordion-body py-5">
6161
<div id="hiddenLayersContainer"></div>
6262
</div>
6363
</div>
6464
</div>
6565
<div class="accordion-item">
6666
<h2 class="accordion-header">
67-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" aria-expanded="false"
67+
<button class="accordion-button collapsed lead fs-4" type="button" data-bs-toggle="collapse" aria-expanded="false"
6868
data-bs-target="#visualizerCollapseThree" aria-controls="visualizerCollapseThree">
6969
Advanced Controls
7070
</button>
7171
</h2>
7272
<div id="visualizerCollapseThree" class="accordion-collapse collapse" data-bs-parent="#visualizerAccordion">
73-
<div class="accordion-body row gy-4">
73+
<div class="accordion-body row py-5 gy-5">
7474
<div class="col-sm-6">
7575
<label for="learningRateInput" class="form-label">Learning Rate</label>
7676
<input type="number" step="0.01" min="0.001" max="3" class="form-control" id="learningRateInput"

web/layouts/_default/baseof.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
{{ partialCached "assets/css.html" . }}
1616
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
1717
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
18+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.min.css">
1819
</head>
1920
<body class="bg-light-subtle">
2021
<header>

0 commit comments

Comments
 (0)