Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CSV-loading mode #1597

Merged
merged 37 commits into from
Nov 9, 2018
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d84a0eb
Add flags to TBContext
jameswex Mar 19, 2018
ab0e9cf
Add flags to TBContext in application
jameswex Mar 19, 2018
e72cbcf
Add flags to tbcontext
jameswex Mar 19, 2018
3803ab7
gitignore changes
jameswex Apr 11, 2018
b65f56c
Merge branch 'master' of https://github.com/tensorflow/tensorboard
jameswex Apr 11, 2018
77a5109
Merge remote-tracking branch 'upstream/master'
jameswex Apr 13, 2018
92e5a72
Merge remote-tracking branch 'upstream/master'
jameswex Apr 18, 2018
0611086
Merge branch 'master' of https://github.com/tensorflow/tensorboard
jameswex Apr 20, 2018
2758a2a
Merge remote-tracking branch 'upstream/master'
jameswex May 9, 2018
8820f4c
Merge remote-tracking branch 'upstream/master'
jameswex May 9, 2018
d1299c6
Merge remote-tracking branch 'upstream/master'
jameswex Aug 6, 2018
c0c8258
jwexler updated rules_closure version
jameswex Aug 6, 2018
019e6f7
Merge remote-tracking branch 'upstream/master'
jameswex Sep 5, 2018
1833317
Merge remote-tracking branch 'upstream/master'
jameswex Sep 10, 2018
286df31
Merge branch 'master' of https://github.com/tensorflow/tensorboard
jameswex Sep 14, 2018
4cebc83
Merge branch 'master' of https://github.com/jameswex/tensorboard
jameswex Sep 17, 2018
d37b198
Merge remote-tracking branch 'upstream/master'
jameswex Sep 19, 2018
9335a8b
Merge remote-tracking branch 'upstream/master'
jameswex Sep 20, 2018
96fe3be
Merge remote-tracking branch 'upstream/master'
jameswex Sep 24, 2018
e2f8e08
Merge remote-tracking branch 'upstream/master'
jameswex Sep 28, 2018
e350d1a
Merge remote-tracking branch 'upstream/master'
jameswex Oct 9, 2018
b7ad234
Merge remote-tracking branch 'upstream/master'
jameswex Oct 11, 2018
89f1f3b
Merge remote-tracking branch 'upstream/master'
jameswex Oct 19, 2018
43622f9
Merge remote-tracking branch 'upstream/master'
jameswex Oct 23, 2018
b86a400
Merge remote-tracking branch 'upstream/master'
jameswex Oct 25, 2018
083fd6c
Merge remote-tracking branch 'upstream/master'
jameswex Oct 26, 2018
eb5c9a4
Merge remote-tracking branch 'upstream/master'
jameswex Oct 30, 2018
69cae44
Initial csv mode
jameswex Oct 31, 2018
c8598ad
fix
jameswex Nov 5, 2018
2292819
Merge remote-tracking branch 'upstream/master'
jameswex Nov 6, 2018
b961c3b
Merge remote-tracking branch 'upstream/master'
jameswex Nov 6, 2018
4e40942
Merge branch 'master' into csv
jameswex Nov 6, 2018
5996a0b
csv and inference results changes
jameswex Nov 6, 2018
88863ec
update readme
jameswex Nov 6, 2018
e30b97f
review comments
jameswex Nov 8, 2018
460f466
inference panel fix
jameswex Nov 9, 2018
d62bfae
final review comments
jameswex Nov 9, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,6 @@
on-blur="onInputBlur"
data-feature="[[feat.name]]"
data-index="[[index]]"
type="[[getInputType(feat.name)]]"
value="[[value]]">
</input>
</template>
Expand All @@ -471,7 +470,6 @@
on-blur="onInputBlur"
data-feature="[[feat.name]]"
data-index="[[zeroIndex]]"
type="[[getInputType(feat.name)]]"
value="[[getFirstFeatureValue(feat.name)]]">
</input>
<template is="dom-if" if="[[featureHasMultipleValues(feat.name)]]">
Expand All @@ -487,15 +485,13 @@
<template is="dom-repeat" items="[[getCompareFeatureValues(feat.name)]]" as="value">
<input type="text" class$="[[getCompareInputClass(feat.name, displayMode, index)]]"
readonly
type="[[getInputType(feat.name)]]"
value="[[value]]">
</input>
</template>
</template>
<template is="dom-if" if="[[!isExpanded(feat.name, expandAllFeatures)]]">
<input type="text" class$="[[getCompareInputClass(feat.name, displayMode, zeroIndex)]]"
readonly
type="[[getInputType(feat.name)]]"
value="[[getFirstCompareFeatureValue(feat.name)]]">
</input>
<template is="dom-if" if="[[compareFeatureHasMultipleValues(feat.name)]]">
Expand Down Expand Up @@ -618,7 +614,6 @@
data-feature="[[seqfeat.name]]"
data-index="[[index]]"
data-seq-num="[[seqNumber]]"
type="[[getInputType(seqfeat.name)]]"
value="[[seqvalue]]">
</input>
</template>
Expand All @@ -632,7 +627,6 @@
data-feature="[[seqfeat.name]]"
data-index="[[zeroIndex]]"
data-seq-num="[[seqNumber]]"
type="[[getInputType(seqfeat.name)]]"
value="[[getFirstSeqFeatureValue(seqfeat.name, seqNumber)]]">
</input>
<template is="dom-if" if="[[seqFeatureHasMultipleValues(seqfeat.name, seqNumber)]]">
Expand All @@ -650,15 +644,13 @@
as="seqvalue">
<input type="text" class$="[[getSeqCompareInputClass(seqfeat.name, displayMode, seqNumber, index)]]"
readonly
type="[[getInputType(seqfeat.name)]]"
value="[[seqvalue]]">
</input>
</template>
</template>
<template is="dom-if" if="[[!isExpanded(seqfeat.name, expandAllFeatures)]]">
<input type="text" class$="[[getSeqCompareInputClass(seqfeat.name, displayMode, seqNumber, zeroIndex)]]"
readonly
type="[[getInputType(seqfeat.name)]]"
value="[[getFirstCompareSeqFeatureValue(seqfeat.name, seqNumber)]]">
</input>
<template is="dom-if" if="[[compareSeqFeatureHasMultipleValues(seqfeat.name, seqNumber)]]">
Expand Down
53 changes: 28 additions & 25 deletions tensorboard/components/vz_example_viewer/vz-example-viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ Polymer({
colors: {type: Object, computed: 'getColors(saliency)', observer: 'createLegend'},
displayMode: {type: String, value: 'grid'},
featureSearchValue: {type: String, value: '', notify: true},
filteredFeaturesList: {type: Object, computed: 'getFilteredFeaturesList(featuresList, featureSearchValue, saliency)'},
filteredSeqFeaturesList: {type: Object, computed: 'getFilteredFeaturesList(seqFeaturesList, featureSearchValue, saliency)'},
filteredFeaturesList: {type: Object},
filteredSeqFeaturesList: {type: Object},
focusedFeatureName: String,
focusedFeatureValueIndex: Number,
focusedSeqNumber: Number,
Expand All @@ -173,6 +173,8 @@ Polymer({
observers: [
'haveSaliency(filteredFeaturesList, saliency, colors, showSaliency, saliencyCutoff)',
'seqSaliency(seqNumber, seqFeaturesList, saliency, colors, showSaliency, saliencyCutoff)',
'setFilteredFeaturesList(featuresList, featureSearchValue, saliency)',
'setFilteredSeqFeaturesList(seqFeaturesList, featureSearchValue, saliency)',
],

isExpanded: function(featName: string, expandAllFeatures: boolean) {
Expand Down Expand Up @@ -274,6 +276,20 @@ Polymer({
.getFeatureLists()!.getFeatureListMap();
},

setFilteredFeaturesList: function(featureList: NameAndFeature[],
searchValue: string, saliency: SaliencyMap) {
this.filteredFeaturesList = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JS style nit: please -2 indent in this function block and the one below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

this.filteredFeaturesList = this.getFilteredFeaturesList(
featureList, searchValue, saliency);
},

setFilteredSeqFeaturesList: function(seqFeatureList: NameAndFeature[],
searchValue: string, saliency: SaliencyMap) {
this.filteredSeqFeaturesList = [];
this.filteredSeqFeaturesList = this.getFilteredFeaturesList(
seqFeatureList, searchValue, saliency);
},

getFilteredFeaturesList: function(featureList: NameAndFeature[],
searchValue: string, saliency: SaliencyMap) {
let filtered = featureList;
Expand Down Expand Up @@ -477,6 +493,14 @@ Polymer({
}
min = Math.min(0, min) * clipSaliencyRatio;
max = Math.max(0, max) * clipSaliencyRatio;
// Make min/max symmetric around 0 so that attribution visualization scales
// for negative and positive attributions are the same, for visual
// consistency.
if (min < 0 && max > Math.abs(min)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you comment on this change, why are we making values symmetric around zero?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

min = -1 * max;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another style nit: -1 indent before max

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

} else if (max > 0 && Math.abs(min) > max) {
max = -1 * min;
}
return [min, max];
},

Expand Down Expand Up @@ -646,27 +670,6 @@ Polymer({
return false;
},

/**
* Gets the allowed input type for a feature value, according to its
* feature type.
*/
getInputType: function(feature: string) {
const feat = this.features.get(feature);
if (feat) {
if (feat.getInt64List() || feat.getFloatList()) {
return 'number'
}
}
const seqfeat = this.seqFeatures.get(feature);
if (seqfeat) {
if (seqfeat.getFeatureList()[0].getInt64List() ||
seqfeat.getFeatureList()[0].getFloatList()) {
return 'number';
}
}
return 'text';
},

/**
* Returns the feature object from the provided json attribute for a given
* feature name.
Expand Down Expand Up @@ -1071,7 +1074,7 @@ Polymer({
* be used in css classes/ids.
*/
sanitizeFeature: function(feat: string) {
let sanitized = feat;
let sanitized = feat.trim();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation looks off

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just saying, because of L1079, sanitized may still have the whitespace. Perhaps use sanitized in L1078 and L1079?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, thx

if (!feat.match(/^[A-Za-z].*$/)) {
sanitized = '_' + feat;
}
Expand Down Expand Up @@ -1155,7 +1158,7 @@ Polymer({
0, LEGEND_WIDTH_PX
]);

const legendAxis = d3.axisBottom(legendScale);
const legendAxis = d3.axisBottom(legendScale).ticks(5);

legendSvg.append('g')
.attr('class', 'legend axis')
Expand Down
29 changes: 27 additions & 2 deletions tensorboard/plugins/interactive_inference/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,45 @@ To use the tool, only the following information needs to be provided:
labels for a classification model. If not, it will show the predicted
class indices.

Alternatively, the What-If Tool can be used to explore a dataset directly from
a CSV file. See the next section for details.

The information can be provided in the settings dialog screen, which pops up
automatically upon opening this tool and is accessible through the settings
icon button in the top-right of the tool.
The information can also be provided directly through URL parameters.
Changing the settings through the controls automatically updates the URL so that
it can be shared with others for them to view the same data in the What-If Tool.

## All I have is a dataset. Where do I start?
## All I have is a dataset. What can I do? Where do I start?

If you want to explore a dataset directly, you have two options:

Check out the [WIT_from_scratch.ipynb ipython notebook](./WIT_from_scratch.ipynb)
If you want to train an ML model from the dataset and explore the dataset and
model, check out the [WIT_from_scratch.ipynb ipython notebook](./WIT_from_scratch.ipynb)
which shows how to install TensorFlow, TensorBoard, and TensorFlow Serving,
train a very simple model to predict a column from a CSV file, serve that model
and load it up in the What-If Tool.

If instead you just want to explore the information in the CSV, just set the
path to the examples to the file (with a ".csv" extension) and leave the
inference address and model name fields blank. The first line of the CSV file
must contain column names. Each line after that contains one example from the
dataset, with values for each of the columns defined on the first line. The pipe
character ("|") deliminates separate feature values in a list of feature values
for a given feature.

In order to make use of the model understanding features of the tool, you can
have columns in your dataset that contain the output from an ML model. If your
file has a column named "probabilities" with a pipe-delimited ("|") list of
probability scores (between 0 and 1), then the tool will treat those as the
output scores of a classification model. If your file has a numeric column named
"score" then the tool will treat those as the output of a regression model. In
this way, the tool can be used to analyze any dataset and the results of any
model run offline against the dataset. Note that in this mode, the examples
aren't editable as there is no way to get new inference results when an example
changes.

## What can it do?
* Visualize a dataset of TensorFlow Example protos.
* The main panel shows the dataset using [Facets Dive](https://pair-code.github.io/facets),
Expand Down
Loading