Scores the predictive performance of the Classifier on all tasks
        Args:
            data: either a Pytorch Dataset, DataLoader or tuple supplying (X,Y):
                X: The input for the predict method
                Y: A t-length list of [n] or [n, 1] np.ndarrays or
                   torch.Tensors of gold labels in {1,...,K_t}
            metric: The metric with which to score performance on each task
            validation_task:
                int: returns score for specific task number.
            reduce: How to reduce the scores of multiple tasks:
                 None : return a t-length list of scores
                'mean': return the mean score across tasks
            break_ties: How to break ties when making predictions
        Returns:
            scores: A (float) score or a t-length list of such scores if
                reduce=None

def score(
        self,
        data,
        metric="accuracy",
        validation_task=None,
        reduce="mean",
        break_ties="random",
        verbose=True,
        print_confusion_matrix=False,
        **kwargs,
    ):
        """Scores the predictive performance of the Classifier on all tasks
        Args:
            data: either a Pytorch Dataset, DataLoader or tuple supplying (X,Y):
                X: The input for the predict method
                Y: A t-length list of [n] or [n, 1] np.ndarrays or
                   torch.Tensors of gold labels in {1,...,K_t}
            metric: The metric with which to score performance on each task
            validation_task:
                int: returns score for specific task number.
            reduce: How to reduce the scores of multiple tasks:
                 None : return a t-length list of scores
                'mean': return the mean score across tasks
            break_ties: How to break ties when making predictions
        Returns:
            scores: A (float) score or a t-length list of such scores if
                reduce=None
        """
        Y_p, Y, Y_s = self._get_predictions(
            data, break_ties=break_ties, return_probs=True, **kwargs
        )

        # TODO: Handle multiple metrics...
        metric_list = metric if isinstance(metric, list) else [metric]
        if len(metric_list) > 1:
            raise NotImplementedError(
                "Multiple metrics for multi-task score() not yet supported."
            )
        metric = metric_list[0]

        # Return score for task t only.
        if validation_task is not None:
            score = metric_score(
                Y[validation_task],
                Y_p[validation_task],
                metric,
                probs=Y_s[validation_task],
                ignore_in_gold=[0],
            )
            if verbose:
                print(f"{metric.capitalize()}: {score:.3f}")
            return score

        task_scores = []
        for t, Y_tp in enumerate(Y_p):
            score = metric_score(Y[t], Y_tp, metric, probs=Y_s[t], ignore_in_gold=[0])
            task_scores.append(score)

        # TODO: Other options for reduce, including scoring only certain
        # primary tasks, and converting to end labels using TaskGraph...
        if reduce is None:
            score = task_scores
        elif reduce == "mean":
            score = np.mean(task_scores)
        else:
            raise Exception(f"Keyword reduce='{reduce}' not recognized.")

        if verbose:
            if reduce is None:
                for t, score_t in enumerate(score):
                    print(f"{metric.capitalize()} (t={t}): {score_t:0.3f}")
            else:
                print(f"{metric.capitalize()}: {score:.3f}")

        return score