diff options
| author | schneefux <schneefux+commit@schneefux.xyz> | 2016-04-03 17:16:03 +0200 |
|---|---|---|
| committer | schneefux <schneefux+commit@schneefux.xyz> | 2016-04-03 17:16:03 +0200 |
| commit | 6f70c1a4e47b0bc96ed0ebcca0eb384a5dfdc2f4 (patch) | |
| tree | a34b4cc2100346f727199a3e7133c0cbbca3a68a | |
| parent | c285b7bea0301fea4694484cdbeeca6a2565d72c (diff) | |
| download | vortrag-knn-6f70c1a4e47b0bc96ed0ebcca0eb384a5dfdc2f4.tar.gz vortrag-knn-6f70c1a4e47b0bc96ed0ebcca0eb384a5dfdc2f4.zip | |
calculate and visualize network activation
| -rw-r--r-- | code/weightvis.js | 11 | ||||
| -rw-r--r-- | code/weightviswrapper.js | 45 | ||||
| -rw-r--r-- | index.html | 33 |
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; @@ -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) { |
