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.AUDIO: 4,
|
||||
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);
|
||||
p = this.requestManager.request(url);
|
||||
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 {
|
||||
wall_time: histo.wall_time,
|
||||
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
|
||||
* the standard d3 histogram data format to make it more compatible and easier
|
||||
* 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 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),
|
||||
* and a y (count).
|
||||
*
|
||||
* 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) {
|
||||
throw(new Error('Edges and counts are of different lengths.'));
|
||||
}
|
||||
|
||||
var previousRightEdge = histogram.min;
|
||||
return histogram.bucketRightEdges.map(function(
|
||||
rightEdge: number, i: number) {
|
||||
let binWidth = (max - min) / numBins;
|
||||
let bucketLeft = min; // Use the min as the starting point for the bins.
|
||||
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
|
||||
var left = previousRightEdge;
|
||||
// Take the count of each existing bucket, multiply it by the proportion
|
||||
// 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
|
||||
// infinite-sized
|
||||
var right = Math.min(histogram.max, rightEdge);
|
||||
let intersect =
|
||||
Math.min(bucketRight, binRight) - Math.max(bucketLeft, binLeft);
|
||||
let count = (intersect / (bucketRight - bucketLeft)) *
|
||||
histogram.bucketCounts[bucketPos];
|
||||
|
||||
// Store rightEdgeValue for next iteration
|
||||
previousRightEdge = rightEdge;
|
||||
binY += intersect > 0 ? count : 0;
|
||||
|
||||
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() {
|
||||
assert.throws(function() {
|
||||
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.');
|
||||
});
|
||||
|
||||
it('Handles data with no bins', function() {
|
||||
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 rightEdges = [1.21e-12];
|
||||
let histogram = [{x: 1.1e-12, dx: 1.21e-12 - 1.1e-12, y: 1}];
|
||||
let newHistogram = convertBins({
|
||||
bucketRightEdges: rightEdges,
|
||||
bucketCounts: counts,
|
||||
min: 1.1e-12,
|
||||
max: 1.21e-12
|
||||
});
|
||||
let newHistogram = convertBins(
|
||||
{
|
||||
bucketRightEdges: rightEdges,
|
||||
bucketCounts: counts,
|
||||
min: 1.1e-12,
|
||||
max: 1.21e-12
|
||||
},
|
||||
1.1e-12, 1.21e-12, 1);
|
||||
assertHistogramEquality(newHistogram, histogram);
|
||||
});
|
||||
|
||||
@ -218,15 +223,17 @@ module TF.Backend {
|
||||
let counts = [1, 2];
|
||||
let rightEdges = [1.1e-12, 1.21e-12];
|
||||
let histogram = [
|
||||
{x: 1.0e-12, dx: 1.1e-12 - 1.0e-12, y: 1},
|
||||
{x: 1.1e-12, dx: 1.21e-12 - 1.1e-12, y: 2}
|
||||
{x: 1.0e-12, dx: 1.05e-13, y: 1.09090909090909},
|
||||
{x: 1.105e-12, dx: 1.05e-13, y: 1.9090909090909}
|
||||
];
|
||||
let newHistogram = convertBins({
|
||||
bucketRightEdges: rightEdges,
|
||||
bucketCounts: counts,
|
||||
min: 1.0e-12,
|
||||
max: 1.21e-12
|
||||
});
|
||||
let newHistogram = convertBins(
|
||||
{
|
||||
bucketRightEdges: rightEdges,
|
||||
bucketCounts: counts,
|
||||
min: 1.0e-12,
|
||||
max: 1.21e-12
|
||||
},
|
||||
1.0e-12, 1.21e-12, 2);
|
||||
assertHistogramEquality(newHistogram, histogram);
|
||||
});
|
||||
|
||||
@ -236,15 +243,17 @@ module TF.Backend {
|
||||
let counts = [1, 2];
|
||||
let rightEdges = [-1.0e-12, 1.0e-12];
|
||||
let histogram = [
|
||||
{x: -1.1e-12, dx: 1.1e-12 - 1.0e-12, y: 1},
|
||||
{x: -1.0e-12, dx: 2.0e-12, y: 2}
|
||||
{x: -1.1e-12, dx: 1.05e-12, y: 1.95},
|
||||
{x: -0.5e-13, dx: 1.05e-12, y: 1.05}
|
||||
];
|
||||
let newHistogram = convertBins({
|
||||
bucketRightEdges: rightEdges,
|
||||
bucketCounts: counts,
|
||||
min: -1.1e-12,
|
||||
max: 1.0e-12
|
||||
});
|
||||
let newHistogram = convertBins(
|
||||
{
|
||||
bucketRightEdges: rightEdges,
|
||||
bucketCounts: counts,
|
||||
min: -1.1e-12,
|
||||
max: 1.0e-12
|
||||
},
|
||||
-1.1e-12, 1.0e-12, 2);
|
||||
assertHistogramEquality(newHistogram, histogram);
|
||||
});
|
||||
|
||||
@ -253,15 +262,18 @@ module TF.Backend {
|
||||
let counts = [1, 2, 3];
|
||||
let rightEdges = [0, 1.0e-12, 1.0e14];
|
||||
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: 1.1e-12 - 1.0e-12, y: 3}
|
||||
{x: -1.0e-12, dx: 0.7e-12, y: 0.7},
|
||||
{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({
|
||||
bucketRightEdges: rightEdges,
|
||||
bucketCounts: counts,
|
||||
min: -1.0e-12,
|
||||
max: 1.1e-12
|
||||
});
|
||||
let newHistogram = convertBins(
|
||||
{
|
||||
bucketRightEdges: rightEdges,
|
||||
bucketCounts: counts,
|
||||
min: -1.0e-12,
|
||||
max: 1.1e-12
|
||||
},
|
||||
-1.0e-12, 1.1e-12, 3);
|
||||
assertHistogramEquality(newHistogram, histogram);
|
||||
});
|
||||
});
|
||||
|
@ -19,6 +19,7 @@ limitations under the License.
|
||||
<script src="../../webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||
<script src="../../web-component-tester/browser.js"></script>
|
||||
<link rel="import" href="../../polymer/polymer.html">
|
||||
<link rel="import" href="../../tf-imports/d3.html">
|
||||
</head>
|
||||
<body>
|
||||
<test-fixture id="testElementFixture">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<link rel="import" href="../polymer/polymer.html">
|
||||
<link rel="import" href="../tf-imports/lodash.html">
|
||||
<link rel="import" href="../tf-imports/d3.html">
|
||||
|
||||
<script src="requestManager.js"></script>
|
||||
<script src="urlPathHelpers.js"></script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user