@torch.no_grad()
def _evaluate(self, loader):
    self.model.eval()
    (total_loss, metric) = (0, AttachmentMetric())
    for batch in loader:
        (words, texts, *feats, arcs, rels) = batch
        word_mask = words.ne(self.args.pad_index)
        mask = (word_mask if (len(words.shape) < 3) else word_mask.any((- 1)))
        mask[:, 0] = 0
        (s_arc, s_rel) = self.model(words, feats)
        loss = self.model.loss(s_arc, s_rel, arcs, rels, mask, self.args.partial)
        (arc_preds, rel_preds) = self.model.decode(s_arc, s_rel, mask, self.args.tree, self.args.proj)
        if self.args.partial:
            mask &= arcs.ge(0)
        if (not self.args.punct):
            mask.masked_scatter_(mask, (~ mask.new_tensor([ispunct(w) for s in texts for w in s])))
        total_loss += loss.item()
        metric(arc_preds, rel_preds, arcs, rels, mask)
    total_loss /= len(loader)
    return (total_loss, metric)
@torch.no_grad()
def _evaluate(self, loader):
    self.model.eval()
    (total_loss, metric) = (0, AttachmentMetric())
    for batch in loader:
        (words, texts, *feats, arcs, rels) = batch
        word_mask = words.ne(self.args.pad_index)
        mask = (word_mask if (len(words.shape) < 3) else word_mask.any((- 1)))
        mask[:, 0] = 0
        (s_arc, s_rel) = self.model(words, feats)
        loss = self.model.loss(s_arc, s_rel, arcs, rels, mask, self.args.partial)
        (arc_preds, rel_preds) = self.model.decode(s_arc, s_rel, mask, self.args.tree, self.args.proj)
        if self.args.partial:
            mask &= arcs.ge(0)
        if (not self.args.punct):
            mask.masked_scatter_(mask, (~ mask.new_tensor([ispunct(w) for s in texts for w in s])))
        total_loss += loss.item()
        metric(arc_preds, rel_preds, arcs, rels, mask)
    total_loss /= len(loader)
    return (total_loss, metric)