summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2016-04-03 17:16:03 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2016-04-03 17:16:03 +0200
commit6f70c1a4e47b0bc96ed0ebcca0eb384a5dfdc2f4 (patch)
treea34b4cc2100346f727199a3e7133c0cbbca3a68a
parentc285b7bea0301fea4694484cdbeeca6a2565d72c (diff)
downloadvortrag-knn-6f70c1a4e47b0bc96ed0ebcca0eb384a5dfdc2f4.tar.gz
vortrag-knn-6f70c1a4e47b0bc96ed0ebcca0eb384a5dfdc2f4.zip
calculate and visualize network activation
-rw-r--r--code/weightvis.js11
-rw-r--r--code/weightviswrapper.js45
-rw-r--r--index.html33
3 files changed, 65 insertions, 24 deletions
diff --git a/code/weightvis.js b/code/weightvis.js
index f61ec39..2ef33e1 100644
--- a/code/weightvis.js
+++ b/code/weightvis.js
@@ -30,7 +30,9 @@ var
linkHighlightColor = pDeepPurple[5],
linkHighlightColorAlt = pPink[5],
nodeColor = pDeepPurple[4],
- nodeHighlightColor = accentColor
+ nodeColorAlt = pPink[4],
+ nodeHighlightColor = accentColor,
+ nodeHighlightColorAlt = pPinkA[3]
;
/* network construction */
@@ -63,6 +65,7 @@ var Network = (function() {
this.nodes.push({
id: layer.toString() + "_" + node.toString(),
layer: layer,
+ node: node,
fixed: true
});
}
@@ -507,12 +510,14 @@ var NetVisualizer = (function() {
function activation(x) { return 1 / (1 + Math.exp(-x)); }
var weights = this.data[this.layout.data.batches-1][this.layout.data.epochs-1];
var lastLayerOut = inputs;
+ var activations = [inputs];
var hasBias = false;
if (this.layout.net[0].isBias) {
for (bias=0; bias<inputs.length; bias++) {
lastLayerOut[bias] += weights[0][0][bias];
}
hasBias = true;
+ activations.push(lastLayerOut);
}
for (layer=hasBias?1:0; layer<this.layout.net.layers-1; layer++) {
// manual vector matrix multiplication
@@ -525,9 +530,9 @@ var NetVisualizer = (function() {
thisLayerOut[tar] = activation(thisLayerOut[tar]);
}
lastLayerOut = thisLayerOut;
- //console.log("layer out", layer, lastLayerOut);
+ activations.push(lastLayerOut);
}
- return lastLayerOut;
+ return activations;
};
return NetVisualizer;
diff --git a/code/weightviswrapper.js b/code/weightviswrapper.js
index 1b3a91a..22bbe63 100644
--- a/code/weightviswrapper.js
+++ b/code/weightviswrapper.js
@@ -7,6 +7,7 @@ var WeightVisWrapper = (function() {
this.container = d3.select("body").append("div").remove();
this.svgContainer = this.container.append("div");
this.controlContainer = this.container.append("div");
+ this.controlBarAttached = false;
this.svg = this.svgContainer.append("svg");
this.netVisualizer = new NetVisualizer(this.svg);
this.resizeHooks = [];
@@ -62,7 +63,7 @@ var WeightVisWrapper = (function() {
WeightVisWrapper.prototype.mock = function(shape, callback) {
var self = this;
- this.controlContainer.style("display", "none");
+ this.hideControlBar;
this.netVisualizer.mock(shape, function() { self.loaded(callback); });
};
@@ -94,8 +95,8 @@ var WeightVisWrapper = (function() {
self.slider.node().MaterialSlider.change(0); // wrap at right end
}
});
- this.slider.attr("max", this.netVisualizer.getSteps() - 1);
- this.slider.node().addEventListener("input", function() { self.netVisualizer.showStep(self.value); });
+ this.slider.attr("max", this.steps()-1);
+ this.slider.node().addEventListener("input", function() { self.jumpTo(self.value); });
this.button.node().addEventListener("click", function toggle() {
if (self.button.attr("data-pressed") != "true") {
var step = self.slider.node().value;
@@ -139,15 +140,22 @@ var WeightVisWrapper = (function() {
el.appendChild(this.spinner.node().cloneNode(true));
};
- WeightVisWrapper.prototype.openIn = function(el) {
+ WeightVisWrapper.prototype.openIn = function(el, withControlbar) {
d3.select(el).select(".spinner").remove();
el.appendChild(this.svgContainer.node());
- el.appendChild(this.controlContainer.node());
+ if (withControlbar) {
+ el.appendChild(this.controlContainer.node());
+ this.controlBarAttached = true;
+ } else {
+ this.controlBarAttached = false;
+ }
this.reposition();
};
WeightVisWrapper.prototype.remove = function(el) {
- this.svgContainer.node().parentNode.removeChild(this.controlContainer.node());
+ if (this.controlBarAttached) {
+ this.svgContainer.node().parentNode.removeChild(this.controlContainer.node());
+ }
this.svgContainer.node().parentNode.appendChild(this.spinner.node().cloneNode(true));
this.svgContainer.node().parentNode.removeChild(this.svgContainer.node());
this.netVisualizer.stopAnimation();
@@ -169,9 +177,30 @@ var WeightVisWrapper = (function() {
this.button.select(".pause").style("display", "");
};
+ WeightVisWrapper.prototype.jumpTo = function(step) {
+ this.netVisualizer.showStep(step);
+ };
+
+ WeightVisWrapper.prototype.steps = function() {
+ return this.netVisualizer.getSteps();
+ };
+
+ WeightVisWrapper.prototype.calculate = function(inputs) {
+ // returns the final layer's outputs
+ return this.netVisualizer.activate(inputs).pop();
+ };
+
WeightVisWrapper.prototype.activate = function(inputs) {
- // TODO visualize this :)
- return this.netVisualizer.activate(inputs);
+ // TODO this should be in weightvis.js
+ // …this is rather a hack, I got lazy…
+ var activations = this.netVisualizer.activate(inputs);
+ var flatActivations = [].concat.apply([], activations);
+ var max = d3.max(flatActivations, Math.abs),
+ min = d3.min(flatActivations, Math.abs);
+ var node = this.svg.selectAll(".node");
+ node
+ .attr("r", function(d) { return 2 * d.r * (Math.abs(activations[d.layer][d.node]) - min) / (max-min); })
+ .style("fill", function(d) { return activations[d.layer][d.node]>0?nodeColor:nodeColorAlt; });
};
return WeightVisWrapper;
diff --git a/index.html b/index.html
index 2e17c5c..7bc7474 100644
--- a/index.html
+++ b/index.html
@@ -120,7 +120,7 @@
var mocker = new WeightVisWrapper();
new VisIntegrater(function(c) {
mocker.mock([3, 2, 1], function() {
- mocker.openIn(c);
+ mocker.openIn(c, false);
});
}, function(c) {
mocker.remove(c);
@@ -134,19 +134,26 @@
</div>
<div class="visContainer"></div>
+ <p style="text-align: center; margin-top: 1.5em;">Berechneter MEDV-Wert: <span id="bsCalculated">lade…</span> - Erwarteter MEDV-Wert: <span id="bsExpected">lade…</span></p>
<script type="text/javascript">
new VisIntegrater(function(c) {
weightsWrapper.afterLoad(function() {
- weightsWrapper.openIn(c);
- var testRows = [400, 175, 454, 481, 476, 364, 377, 75, 103, 84, 458, 483];
- for(c=0; c<10; c++){
- //var row = testRows[Math.floor(Math.random()*testRows.length)];
- var row = Math.floor(Math.random()*bostonset.length());
- var inputs = bostonset.inputs(row);
- console.log("calculated", bostonset.asOutput(weightsWrapper.activate(inputs)[0]));
- console.log("real", bostonset.expectedOutput(row));
- }
+ weightsWrapper.jumpTo(weightsWrapper.steps()-1);
+ weightsWrapper.openIn(c, false);
+ var testRows = [400, 175, 454, 481, 476, 364, 377, 75, 103, 84, 458, 483]; // from original test data
+ var row = 0,
+ inputs =[];
+ var calculated, expected;
+ do {
+ row = Math.floor(Math.random()*bostonset.length());
+ inputs = bostonset.inputs(row);
+ calculated = bostonset.asOutput(weightsWrapper.calculate(inputs)[0]);
+ expected = bostonset.expectedOutput(row);
+ } while(Math.abs(calculated - expected) > 5);
+ d3.select("#bsCalculated").text(calculated.toString());
+ d3.select("#bsExpected").text(expected.toString());
+ weightsWrapper.activate(inputs);
});
}, function(c) {
weightsWrapper.remove(c);
@@ -164,7 +171,7 @@
<script type="text/javascript">
new VisIntegrater(function(c) {
errorVis.afterLoad(function() {
- errorVis.openIn(c);
+ errorVis.openIn(c, true);
errorVis.showMarker(203);
});
}, function(c) {
@@ -183,7 +190,7 @@
<script type="text/javascript">
new VisIntegrater(function(c) {
weightsWrapper.afterLoad(function() {
- weightsWrapper.openIn(c);
+ weightsWrapper.openIn(c, true);
weightsWrapper.animate(10, 10);
});
}, function(c) {
@@ -202,7 +209,7 @@
<script type="text/javascript">
new VisIntegrater(function(c) {
weightsWrapper.afterLoad(function() {
- weightsWrapper.openIn(c);
+ weightsWrapper.openIn(c, true);
weightsWrapper.animate(10, 10);
});
}, function(c) {