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 ability to set attributions in WIT #2252

Merged
merged 31 commits into from
May 24, 2019
Merged

Conversation

jameswex
Copy link
Contributor

@jameswex jameswex commented May 20, 2019

  • Motivation for features / changes

Enabling WIT to be able to display feature-level attributions for individual predictions if the model provides it.

  • Technical description of changes
  • Update visuals of attribution(saliency) viewing in vz-example-viewer, including better layout/coloring, and removing some unnecessary controls.
  • Update inference_utils.py logic to be able to handle inference results with new, optional attribution values.
  • Update WitWidget custom_predict_functions to be able to optionally return attributions in addition to predictions, by returning a dict containing both. Update parsing of those results to handle that case.
  • Update AI platform custom predict function to pass any attributions it generates back through that newly-defined dict.
  • Update WitWidget colab and jupyter code to pass those optional attributions to javascript when inferences are made.
  • Update WIT element to handle attributions passed to it by updating the visdata for the elements that have attribution information to include that information so it is visualized by vz-example-viewer, and usable in Facets Dive.
  • Screenshots of UI changes

attribs

  • Detailed steps to verify changes work correctly (as executed by you)

Created custom predict function that created fake attributions and inferences, tested it in colab and jupyter notebooks to see correct visual handling of those attributions.

  • Alternate designs / implementations considered

@jameswex
Copy link
Contributor Author

@tolga-b please review

Copy link
Contributor

@tolga-b tolga-b left a comment

Choose a reason for hiding this comment

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

Added some comments.

@@ -397,7 +397,7 @@ Polymer({
(d: {}, i: number) => this.getColorForSaliency(val[i]) :
() => this.getColorForSaliency(val);
this.selectAll(
`input.${this.sanitizeFeature(feat.name)}.value-pill`)
`iron-autogrow-textarea.${this.sanitizeFeature(feat.name)}.value-pill`)
Copy link
Contributor

Choose a reason for hiding this comment

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

General comment, it would be better if this code did not depend on the type of text box (iron-autogrow-textarea or input). It looks a bit fragile right now in case we forget to change this when html side is updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code actually works correctly without the selector for the element this, so i removed it. Thanks for catching this.

@@ -122,8 +123,11 @@ def infer_impl(self):
self.estimator_and_spec.get('estimator'),
self.estimator_and_spec.get('feature_spec'),
self.custom_predict_fn)
infer_objs.append(inference_utils.run_inference_for_inference_results(
(preidctions, attributions) = (
Copy link
Contributor

Choose a reason for hiding this comment

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

typo

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

@@ -413,6 +413,24 @@ def set_custom_predict_fn(self, predict_fn):
- For regression: A 1D list of numbers, with a regression score for each
example being predicted.

Optionally, if attributions can be returned by the model with each
prediction, then this method can return a dict with the key 'predictions'
containing the preidctions result list described above, and with the key
Copy link
Contributor

Choose a reason for hiding this comment

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

typo preidctions, this happens in a lot of places so mass replace should fix it.

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

for (let i = 0; i < attributions.indices.length; i++) {
const idx = attributions.indices[i];
const datapoint = this.visdata[idx];
// For now, we only display attribution from the first model, if WIT
Copy link
Contributor

Choose a reason for hiding this comment

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

Add TODO here for two models

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

@@ -2186,6 +2186,27 @@ <h2>Show similarity to selected datapoint</h2>
observer: 'newInferences_',
value: () => ({})
},
// Attributions from inference. A dict with two fields: 'indices' and
// 'attributions'. Inidicies contains a list of example indices that
Copy link
Contributor

Choose a reason for hiding this comment

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

typo Inidicies

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

@jameswex jameswex requested a review from stephanwlee May 22, 2019 20:30
@jameswex
Copy link
Contributor Author

@stephanwlee please review thx

infer_objs.append(inference_utils.run_inference_for_inference_results(
examples_to_infer, serving_bundle))
(predictions, _) = inference_utils.run_inference_for_inference_results(
examples_to_infer, serving_bundle)
Copy link
Contributor

Choose a reason for hiding this comment

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

+2 whitespace per python style guide.

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

attributions: {
type: Object,
observer: 'newAttributions_',
value: () => ({})
Copy link
Contributor

Choose a reason for hiding this comment

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

null might be better.

datapoint[attribSparseValueKey] = attribs[keys[j]][1];
} else {
const attribKey = attributionPrefix + keys[j];
datapoint[attribKey] = attribs[keys[j]];
Copy link
Contributor

Choose a reason for hiding this comment

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

it feels un-Polymermic to mutate data like this and then trigger a draw (as opposed to using prop changes to trigger data binding). Can you consider creating another object and do this.set(`visdata[${index}]`, newObject)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixing

@jameswex jameswex merged commit 49fed7e into tensorflow:master May 24, 2019
@jameswex jameswex deleted the attribution branch May 24, 2019 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants