-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add the attention visualization to the textual entailment demo #1219
Add the attention visualization to the textual entailment demo #1219
Conversation
murphp15
commented
May 15, 2018
could I ask that you give your PRs (especially) and commits (less crucial) more descriptive names? most of us don't have the issue numbers memorized, so the titles aren't very helpful. we typically link to the relevant issue in the description of the PR (which has the benefit of automatically associating the PR with the issue) |
Great point Joel! For example, here I would name the PR "Add the attention visualization to the textual entailment demo" and in the description I would have "Fixes #1033". GitHub treats that phrase specially--see https://help.github.com/articles/closing-issues-using-keywords/. |
Fixes #1033 |
Github is weird - you have to edit the original PR description with the |
3ab0f14
to
9b9bddb
Compare
9b9bddb
to
9cbd543
Compare
@matt-gardner
Does that look ok to you now? |
Yeah, this looks much better, thanks. Future commits on this PR (if there are any) don't need to have the same "Fixes" message, they should have something more descriptive of the contents of that commit. We also have typically just put the "Fixes" message in the original PR description instead of a commit message, but either is fine. |
Cool I'll do this from now on. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than switching from a MetadataField
to using the Predictor
to pass the tokens to the demo, looks great, thanks for the PR!
@@ -71,6 +71,10 @@ def text_to_instance(self, # type: ignore | |||
hypothesis_tokens = self._tokenizer.tokenize(hypothesis) | |||
fields['premise'] = TextField(premise_tokens, self._token_indexers) | |||
fields['hypothesis'] = TextField(hypothesis_tokens, self._token_indexers) | |||
fields['metadata'] = MetadataField({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of adding a MetadataField
that the model doesn't really need, I think this would be cleaner if you just modified the Predictor
. The Predictor
can tokenize the text and pass the tokens on as output to the demo. That would look something like this:
allennlp/allennlp/service/predictors/sentence_tagger.py
Lines 27 to 39 in f246da7
@overrides | |
def _json_to_instance(self, json_dict: JsonDict) -> Tuple[Instance, JsonDict]: | |
""" | |
Expects JSON that looks like ``{"sentence": "..."}``. | |
Runs the underlying model, and adds the ``"words"`` to the output. | |
""" | |
sentence = json_dict["sentence"] | |
tokens = self._tokenizer.split_words(sentence) | |
instance = self._dataset_reader.text_to_instance(tokens) | |
return_dict: JsonDict = {"words":[token.text for token in tokens]} | |
return instance, return_dict |
You'd have to grab the _tokenizer
from self._dataset_reader
in the Predictor
(with # pylint: disable=protected-access
) and use that to tokenize the text, instead of instantiating a tokenizer in __init__
. You'd also need to modify this DatasetReader
's text_to_instance
method to optionally take pre-tokenized text, which would look something like how passage_tokens
is treated here:
allennlp/allennlp/data/dataset_readers/reading_comprehension/squad.py
Lines 74 to 83 in f246da7
@overrides | |
def text_to_instance(self, # type: ignore | |
question_text: str, | |
passage_text: str, | |
char_spans: List[Tuple[int, int]] = None, | |
answer_texts: List[str] = None, | |
passage_tokens: List[Token] = None) -> Instance: | |
# pylint: disable=arguments-differ | |
if not passage_tokens: | |
passage_tokens = self._tokenizer.tokenize(passage_text) |
@@ -164,13 +165,29 @@ def forward(self, # type: ignore | |||
|
|||
output_dict = {"label_logits": label_logits, "label_probs": label_probs} | |||
|
|||
self.add_insight_to_output_dict(metadata, output_dict, p2h_attention, h2p_attention) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After switching the MetadataField
to something on the Predictor
, it seems a bit of overkill to add a method just to add the two attention fields to output_dict
. I'd just put those two lines inline here.
hypothesis_tokens = [] | ||
if metadata is not None: | ||
for datum in metadata: | ||
premise_tokens.append(datum['premise_tokens'][:len(datum['premise_tokens'])-1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just FYI (because this should be removed, anyway), the MetadataField
does not get padded, so you don't need to do this [:len...]
stuff. It will just be the exact list you created in the DatasetReader
.
PR updated. |
91ae8f2
to
77b60ec
Compare
1. The predictor is now responsible for tokenizing hypothesis and premise. 2. The model no longer takes the metadata parameter anymore.
77b60ec
to
8461056
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks!
…ai#1219) * Fixes allenai#1033 * changes following PR review. 1. The predictor is now responsible for tokenizing hypothesis and premise. 2. The model no longer takes the metadata parameter anymore. * Removed some extra blank lines * Fix spacing issues