Compare commits

...

4 Commits

Author SHA1 Message Date
Matthew Honnibal 2bfa9fc7ce Fix import 2020-09-12 20:16:18 +02:00
Matthew Honnibal 6fbb31a136 Add update method to senter 2020-09-12 19:55:12 +02:00
Matthew Honnibal 949c36b876 Fix typo 2020-09-12 17:00:37 +02:00
Matthew Honnibal 164d90878e Fix tagger training when some tags are missing 2020-09-12 16:07:32 +02:00
2 changed files with 52 additions and 1 deletions
+44
View File
@@ -3,6 +3,7 @@ from itertools import islice
import srsly
from thinc.api import Model, SequenceCategoricalCrossentropy, Config
from thinc.api import set_dropout_rate
from ..tokens.doc cimport Doc
@@ -95,6 +96,49 @@ class SentenceRecognizer(Tagger):
else:
doc.c[j].sent_start = -1
def update(self, examples, *, drop=0., sgd=None, losses=None, set_annotations=False):
"""Learn from a batch of documents and gold-standard information,
updating the pipe's model. Delegates to predict and get_loss.
examples (Iterable[Example]): A batch of Example objects.
drop (float): The dropout rate.
set_annotations (bool): Whether or not to update the Example objects
with the predictions.
sgd (thinc.api.Optimizer): The optimizer.
losses (Dict[str, float]): Optional record of the loss during training.
Updated using the component name as the key.
RETURNS (Dict[str, float]): The updated losses dictionary.
DOCS: https://nightly.spacy.io/api/tagger#update
"""
if losses is None:
losses = {}
losses.setdefault(self.name, 0.0)
validate_examples(examples, "Tagger.update")
if not any(len(eg.predicted) if eg.predicted else 0 for eg in examples):
# Handle cases where there are no tokens in any docs.
return
if not any(eg.reference.is_sentenced for eg in examples):
# Handle cases where there are no tagged tokens in any docs.
return
set_dropout_rate(self.model, drop)
tag_scores, bp_tag_scores = self.model.begin_update([eg.predicted for eg in examples])
for sc in tag_scores:
if self.model.ops.xp.isnan(sc.sum()):
raise ValueError(Errors.E940)
loss, d_tag_scores = self.get_loss(examples, tag_scores)
bp_tag_scores(d_tag_scores)
if sgd not in (None, False):
self.model.finish_update(sgd)
losses[self.name] += loss
if set_annotations:
docs = [eg.predicted for eg in examples]
self.set_annotations(docs, self._scores2guesses(tag_scores))
return losses
def get_loss(self, examples, scores):
"""Find the loss and gradient of loss for the batch of documents and
their predicted scores.
+8 -1
View File
@@ -192,6 +192,9 @@ class Tagger(Pipe):
if not any(len(eg.predicted) if eg.predicted else 0 for eg in examples):
# Handle cases where there are no tokens in any docs.
return
if not any(eg.reference.is_tagged for eg in examples):
# Handle cases where there are no tagged tokens in any docs.
return
set_dropout_rate(self.model, drop)
tag_scores, bp_tag_scores = self.model.begin_update([eg.predicted for eg in examples])
for sc in tag_scores:
@@ -251,7 +254,11 @@ class Tagger(Pipe):
DOCS: https://nightly.spacy.io/api/tagger#get_loss
"""
validate_examples(examples, "Tagger.get_loss")
loss_func = SequenceCategoricalCrossentropy(names=self.labels, normalize=False)
loss_func = SequenceCategoricalCrossentropy(
names=self.labels,
normalize=False,
missing_value=""
)
truths = [eg.get_aligned("TAG", as_string=True) for eg in examples]
d_scores, loss = loss_func(scores, truths)
if self.model.ops.xp.isnan(loss):