def METHOD_NAME(self, mode, features, labels, records, **kwargs):
    """
    Args:
        features:
            list of unpadded features [feat1, feat2, ...]
            each feat is in torch.FloatTensor and already
            put in the device assigned by command-line args
        labels:
            the frame-wise phone labels
        records:
            defaultdict(list), by appending contents into records,
            these contents can be averaged and logged on Tensorboard
            later by self.log_records every log_step
    Return:
        loss:
            the loss to be optimized, should not be detached
    """
    lengths = torch.LongTensor([len(l) for l in labels])
    features = pad_sequence(features, batch_first=True)
    labels = pad_sequence(labels, batch_first=True, padding_value=-100).to(features.device)
    features, labels = self._match_length(features, labels)
    predicted = self.model(features)
    # cause logits are in (batch, seq, class) and labels are in (batch, seq)
    # nn.CrossEntropyLoss expect to have (N, class) and (N,) as input
    # here we flatten logits and labels in order to apply nn.CrossEntropyLoss
    class_num = predicted.size(-1)
    loss = self.objective(predicted.reshape(-1, class_num), labels.reshape(-1))
    predicted_classid = predicted.max(dim=-1).indices
    sames = (predicted_classid == labels)
    for s, l in zip(sames, lengths):
        utter_result = s[:l].tolist()
        records['acc'] += utter_result
        records['sample_wise_metric'] += [torch.FloatTensor(utter_result).mean().item()]
    return loss