Update the TensorBoard backend to use a new binning algorithm.
Update the TensorBoard backend size guidelines for the new histograms. Change: 129806300
This commit is contained in:
parent
cf6857d476
commit
bfcbc262af
@ -41,7 +41,7 @@ TENSORBOARD_SIZE_GUIDANCE = {
|
|||||||
event_accumulator.IMAGES: 4,
|
event_accumulator.IMAGES: 4,
|
||||||
event_accumulator.AUDIO: 4,
|
event_accumulator.AUDIO: 4,
|
||||||
event_accumulator.SCALARS: 1000,
|
event_accumulator.SCALARS: 1000,
|
||||||
event_accumulator.HISTOGRAMS: 1,
|
event_accumulator.HISTOGRAMS: 50,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -182,11 +182,16 @@ module TF.Backend {
|
|||||||
let url = this.router.histograms(tag, run);
|
let url = this.router.histograms(tag, run);
|
||||||
p = this.requestManager.request(url);
|
p = this.requestManager.request(url);
|
||||||
return p.then(map(detupler(createHistogram))).then(function(histos) {
|
return p.then(map(detupler(createHistogram))).then(function(histos) {
|
||||||
|
// Get the minimum and maximum values across all histograms so that the
|
||||||
|
// visualization is aligned for all timesteps.
|
||||||
|
let min = d3.min(histos, d => d.min);
|
||||||
|
let max = d3.max(histos, d => d.max);
|
||||||
|
|
||||||
return histos.map(function(histo, i) {
|
return histos.map(function(histo, i) {
|
||||||
return {
|
return {
|
||||||
wall_time: histo.wall_time,
|
wall_time: histo.wall_time,
|
||||||
step: histo.step,
|
step: histo.step,
|
||||||
bins: convertBins(histo)
|
bins: convertBins(histo, min, max)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -367,34 +372,59 @@ module TF.Backend {
|
|||||||
* Takes histogram data as stored by tensorboard backend and converts it to
|
* Takes histogram data as stored by tensorboard backend and converts it to
|
||||||
* the standard d3 histogram data format to make it more compatible and easier
|
* the standard d3 histogram data format to make it more compatible and easier
|
||||||
* to visualize. When visualizing histograms, having the left edge and width
|
* to visualize. When visualizing histograms, having the left edge and width
|
||||||
* makes things quite a bit easier.
|
* makes things quite a bit easier. The bins are also converted to have an
|
||||||
|
* uniform width, what makes the visualization easier to understand.
|
||||||
*
|
*
|
||||||
* @param histogram A histogram from tensorboard backend.
|
* @param histogram A histogram from tensorboard backend.
|
||||||
|
* @param min The leftmost edge. The binning will start on it.
|
||||||
|
* @param max The rightmost edge. The binning will end on it.
|
||||||
|
* @param numBins The number of bins of the converted data. The default of 30
|
||||||
|
* is a sensible default, using more starts to get artifacts because the event
|
||||||
|
* data is stored in buckets, and you start being able to see the aliased
|
||||||
|
* borders between each bucket.
|
||||||
* @return A histogram bin. Each bin has an x (left edge), a dx (width),
|
* @return A histogram bin. Each bin has an x (left edge), a dx (width),
|
||||||
* and a y (count).
|
* and a y (count).
|
||||||
*
|
*
|
||||||
* If given rightedges are inclusive, then these left edges (x) are exclusive.
|
* If given rightedges are inclusive, then these left edges (x) are exclusive.
|
||||||
*/
|
*/
|
||||||
export function convertBins(histogram: Histogram) {
|
export function convertBins(
|
||||||
|
histogram: Histogram, min: number, max: number, numBins = 30) {
|
||||||
if (histogram.bucketRightEdges.length !== histogram.bucketCounts.length) {
|
if (histogram.bucketRightEdges.length !== histogram.bucketCounts.length) {
|
||||||
throw(new Error('Edges and counts are of different lengths.'));
|
throw(new Error('Edges and counts are of different lengths.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
var previousRightEdge = histogram.min;
|
let binWidth = (max - min) / numBins;
|
||||||
return histogram.bucketRightEdges.map(function(
|
let bucketLeft = min; // Use the min as the starting point for the bins.
|
||||||
rightEdge: number, i: number) {
|
let bucketPos = 0;
|
||||||
|
return d3.range(min, max, binWidth).map(function(binLeft) {
|
||||||
|
let binRight = binLeft + binWidth;
|
||||||
|
|
||||||
// Use the previous bin's rightEdge as the new leftEdge
|
// Take the count of each existing bucket, multiply it by the proportion
|
||||||
var left = previousRightEdge;
|
// of overlap with the new bin, then sum and store as the count for the
|
||||||
|
// new bin. If no overlap, will add to zero, if 100% overlap, will include
|
||||||
|
// the full count into new bin.
|
||||||
|
let binY = 0;
|
||||||
|
while (bucketPos < histogram.bucketRightEdges.length) {
|
||||||
|
// Clip the right edge because right-most edge can be infinite-sized.
|
||||||
|
let bucketRight = Math.min(max, histogram.bucketRightEdges[bucketPos]);
|
||||||
|
|
||||||
// We need to clip the rightEdge because right-most edge can be
|
let intersect =
|
||||||
// infinite-sized
|
Math.min(bucketRight, binRight) - Math.max(bucketLeft, binLeft);
|
||||||
var right = Math.min(histogram.max, rightEdge);
|
let count = (intersect / (bucketRight - bucketLeft)) *
|
||||||
|
histogram.bucketCounts[bucketPos];
|
||||||
|
|
||||||
// Store rightEdgeValue for next iteration
|
binY += intersect > 0 ? count : 0;
|
||||||
previousRightEdge = rightEdge;
|
|
||||||
|
|
||||||
return {x: left, dx: right - left, y: histogram.bucketCounts[i]};
|
// If bucketRight is bigger than binRight, than this bin is finished and
|
||||||
|
// there is data for the next bin, so don't increment bucketPos.
|
||||||
|
if (bucketRight > binRight) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bucketLeft = Math.max(min, bucketRight);
|
||||||
|
bucketPos++;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {x: binLeft, dx: binWidth, y: binY};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -191,13 +191,16 @@ module TF.Backend {
|
|||||||
it('Throws and error if the inputs are of different lengths', function() {
|
it('Throws and error if the inputs are of different lengths', function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
convertBins(
|
convertBins(
|
||||||
{bucketRightEdges: [0], bucketCounts: [1, 2], min: 1, max: 2});
|
{bucketRightEdges: [0], bucketCounts: [1, 2], min: 1, max: 2}, 1, 2,
|
||||||
|
2);
|
||||||
}, 'Edges and counts are of different lengths.');
|
}, 'Edges and counts are of different lengths.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Handles data with no bins', function() {
|
it('Handles data with no bins', function() {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
convertBins({bucketRightEdges: [], bucketCounts: [], min: 0, max: 0}),
|
convertBins(
|
||||||
|
{bucketRightEdges: [], bucketCounts: [], min: 0, max: 0}, 0, 0,
|
||||||
|
0),
|
||||||
[]);
|
[]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -205,12 +208,14 @@ module TF.Backend {
|
|||||||
let counts = [1];
|
let counts = [1];
|
||||||
let rightEdges = [1.21e-12];
|
let rightEdges = [1.21e-12];
|
||||||
let histogram = [{x: 1.1e-12, dx: 1.21e-12 - 1.1e-12, y: 1}];
|
let histogram = [{x: 1.1e-12, dx: 1.21e-12 - 1.1e-12, y: 1}];
|
||||||
let newHistogram = convertBins({
|
let newHistogram = convertBins(
|
||||||
bucketRightEdges: rightEdges,
|
{
|
||||||
bucketCounts: counts,
|
bucketRightEdges: rightEdges,
|
||||||
min: 1.1e-12,
|
bucketCounts: counts,
|
||||||
max: 1.21e-12
|
min: 1.1e-12,
|
||||||
});
|
max: 1.21e-12
|
||||||
|
},
|
||||||
|
1.1e-12, 1.21e-12, 1);
|
||||||
assertHistogramEquality(newHistogram, histogram);
|
assertHistogramEquality(newHistogram, histogram);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -218,15 +223,17 @@ module TF.Backend {
|
|||||||
let counts = [1, 2];
|
let counts = [1, 2];
|
||||||
let rightEdges = [1.1e-12, 1.21e-12];
|
let rightEdges = [1.1e-12, 1.21e-12];
|
||||||
let histogram = [
|
let histogram = [
|
||||||
{x: 1.0e-12, dx: 1.1e-12 - 1.0e-12, y: 1},
|
{x: 1.0e-12, dx: 1.05e-13, y: 1.09090909090909},
|
||||||
{x: 1.1e-12, dx: 1.21e-12 - 1.1e-12, y: 2}
|
{x: 1.105e-12, dx: 1.05e-13, y: 1.9090909090909}
|
||||||
];
|
];
|
||||||
let newHistogram = convertBins({
|
let newHistogram = convertBins(
|
||||||
bucketRightEdges: rightEdges,
|
{
|
||||||
bucketCounts: counts,
|
bucketRightEdges: rightEdges,
|
||||||
min: 1.0e-12,
|
bucketCounts: counts,
|
||||||
max: 1.21e-12
|
min: 1.0e-12,
|
||||||
});
|
max: 1.21e-12
|
||||||
|
},
|
||||||
|
1.0e-12, 1.21e-12, 2);
|
||||||
assertHistogramEquality(newHistogram, histogram);
|
assertHistogramEquality(newHistogram, histogram);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -236,15 +243,17 @@ module TF.Backend {
|
|||||||
let counts = [1, 2];
|
let counts = [1, 2];
|
||||||
let rightEdges = [-1.0e-12, 1.0e-12];
|
let rightEdges = [-1.0e-12, 1.0e-12];
|
||||||
let histogram = [
|
let histogram = [
|
||||||
{x: -1.1e-12, dx: 1.1e-12 - 1.0e-12, y: 1},
|
{x: -1.1e-12, dx: 1.05e-12, y: 1.95},
|
||||||
{x: -1.0e-12, dx: 2.0e-12, y: 2}
|
{x: -0.5e-13, dx: 1.05e-12, y: 1.05}
|
||||||
];
|
];
|
||||||
let newHistogram = convertBins({
|
let newHistogram = convertBins(
|
||||||
bucketRightEdges: rightEdges,
|
{
|
||||||
bucketCounts: counts,
|
bucketRightEdges: rightEdges,
|
||||||
min: -1.1e-12,
|
bucketCounts: counts,
|
||||||
max: 1.0e-12
|
min: -1.1e-12,
|
||||||
});
|
max: 1.0e-12
|
||||||
|
},
|
||||||
|
-1.1e-12, 1.0e-12, 2);
|
||||||
assertHistogramEquality(newHistogram, histogram);
|
assertHistogramEquality(newHistogram, histogram);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -253,15 +262,18 @@ module TF.Backend {
|
|||||||
let counts = [1, 2, 3];
|
let counts = [1, 2, 3];
|
||||||
let rightEdges = [0, 1.0e-12, 1.0e14];
|
let rightEdges = [0, 1.0e-12, 1.0e14];
|
||||||
let histogram = [
|
let histogram = [
|
||||||
{x: -1.0e-12, dx: 1.0e-12, y: 1}, {x: 0, dx: 1.0e-12, y: 2},
|
{x: -1.0e-12, dx: 0.7e-12, y: 0.7},
|
||||||
{x: 1.0e-12, dx: 1.1e-12 - 1.0e-12, y: 3}
|
{x: -0.3e-12, dx: 0.7e-12, y: 1.1},
|
||||||
|
{x: 0.4e-12, dx: 0.7e-12, y: 4.2}
|
||||||
];
|
];
|
||||||
let newHistogram = convertBins({
|
let newHistogram = convertBins(
|
||||||
bucketRightEdges: rightEdges,
|
{
|
||||||
bucketCounts: counts,
|
bucketRightEdges: rightEdges,
|
||||||
min: -1.0e-12,
|
bucketCounts: counts,
|
||||||
max: 1.1e-12
|
min: -1.0e-12,
|
||||||
});
|
max: 1.1e-12
|
||||||
|
},
|
||||||
|
-1.0e-12, 1.1e-12, 3);
|
||||||
assertHistogramEquality(newHistogram, histogram);
|
assertHistogramEquality(newHistogram, histogram);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -19,6 +19,7 @@ limitations under the License.
|
|||||||
<script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
|
<script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||||
<script src="../../web-component-tester/browser.js"></script>
|
<script src="../../web-component-tester/browser.js"></script>
|
||||||
<link rel="import" href="../../polymer/polymer.html">
|
<link rel="import" href="../../polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../tf-imports/d3.html">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<test-fixture id="testElementFixture">
|
<test-fixture id="testElementFixture">
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<link rel="import" href="../polymer/polymer.html">
|
<link rel="import" href="../polymer/polymer.html">
|
||||||
<link rel="import" href="../tf-imports/lodash.html">
|
<link rel="import" href="../tf-imports/lodash.html">
|
||||||
|
<link rel="import" href="../tf-imports/d3.html">
|
||||||
|
|
||||||
<script src="requestManager.js"></script>
|
<script src="requestManager.js"></script>
|
||||||
<script src="urlPathHelpers.js"></script>
|
<script src="urlPathHelpers.js"></script>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user