summaryrefslogtreecommitdiff
path: root/code
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 /code
parentc285b7bea0301fea4694484cdbeeca6a2565d72c (diff)
downloadvortrag-knn-6f70c1a4e47b0bc96ed0ebcca0eb384a5dfdc2f4.tar.gz
vortrag-knn-6f70c1a4e47b0bc96ed0ebcca0eb384a5dfdc2f4.zip
calculate and visualize network activation
Diffstat (limited to 'code')
-rw-r--r--code/weightvis.js11
-rw-r--r--code/weightviswrapper.js45
2 files changed, 45 insertions, 11 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;