ValueError: недостаточно значений для распаковки (ожидалось 4, получено 1): Pytorch - PullRequest
0 голосов
/ 29 мая 2020

Я получаю эту ошибку при запуске отчета eval. Я обучил свою модель с помощью bert-base-german-cased для моего пользовательского набора данных.

Код выглядит следующим образом:

    from sklearn.metrics import mean_squared_error, matthews_corrcoef, confusion_matrix
    from scipy.stats import pearsonr

    def get_mismatched(labels, preds):
        mismatched = labels != preds
        examples = processor.get_dev_examples(args['data_dir'])
        wrong = [i for (i, v) in zip(examples, mismatched) if v]

        return wrong

    def get_eval_report(labels, preds):
        mcc = matthews_corrcoef(labels, preds)
        tn, fp, fn, tp = confusion_matrix(labels, preds).ravel()
        return {
            "mcc": mcc,
            "tp": tp,
            "tn": tn,
            "fp": fp,
            "fn": fn
        }, get_mismatched(labels, preds)

    def compute_metrics(task_name, preds, labels):
        assert len(preds) == len(labels)
        return get_eval_report(labels, preds)

    def evaluate(model, tokenizer, prefix=""):
        # Loop to handle MNLI double evaluation (matched, mis-matched)
        eval_output_dir = args['output_dir']

        results = {}
        EVAL_TASK = args['task_name']

        eval_dataset = load_and_cache_examples(EVAL_TASK, tokenizer, evaluate=True)
        if not os.path.exists(eval_output_dir):
            os.makedirs(eval_output_dir)


        eval_sampler = SequentialSampler(eval_dataset)
        eval_dataloader = DataLoader(eval_dataset, sampler=eval_sampler, batch_size=args['eval_batch_size'])

        # Eval!
        logger.info("***** Running evaluation {} *****".format(prefix))
        logger.info("  Num examples = %d", len(eval_dataset))
        logger.info("  Batch size = %d", args['eval_batch_size'])
        eval_loss = 0.0
        nb_eval_steps = 0
        preds = None
        out_label_ids = None
        for batch in tqdm_notebook(eval_dataloader, desc="Evaluating"):
            model.eval()
            batch = tuple(t.to(device) for t in batch)

            with torch.no_grad():
                inputs = {'input_ids':      batch[0],
                          'attention_mask': batch[1],
                          'token_type_ids': batch[2] if args['model_type'] in ['bert', 'xlnet'] else None,  # XLM don't use segment_ids
                          'labels':         batch[3]}
                outputs = model(**inputs)
                tmp_eval_loss, logits = outputs[:2]

                eval_loss += tmp_eval_loss.mean().item()
            nb_eval_steps += 1
            if preds is None:
                preds = logits.detach().cpu().numpy()
                out_label_ids = inputs['labels'].detach().cpu().numpy()
            else:
                preds = np.append(preds, logits.detach().cpu().numpy(), axis=0)
                out_label_ids = np.append(out_label_ids, inputs['labels'].detach().cpu().numpy(), axis=0)

        eval_loss = eval_loss / nb_eval_steps
        if args['output_mode'] == "classification":
            preds = np.argmax(preds, axis=1)
        elif args['output_mode'] == "regression":
            preds = np.squeeze(preds)
        result, wrong = compute_metrics(EVAL_TASK, preds, out_label_ids)
        results.update(result)

        output_eval_file = os.path.join(eval_output_dir, "eval_results.txt")
        with open(output_eval_file, "w") as writer:
            logger.info("***** Eval results {} *****".format(prefix))
            for key in sorted(result.keys()):
                logger.info("  %s = %s", key, str(result[key]))
                writer.write("%s = %s\n" % (key, str(result[key])))

        return results, wrong

    ValueError                                Traceback (most recent call last)
    <ipython-input-33-0d7757abd7dd> in <module>
         10         model = model_class.from_pretrained(checkpoint)
         11         model.to(device)
    ---> 12         result, wrong_preds = evaluate(model, tokenizer, prefix=global_step)
         13         result = dict((k + '_{}'.format(global_step), v) for k, v in result.items())
         14         results.update(result)

    <ipython-input-30-c0946f859f89> in evaluate(model, tokenizer, prefix)
         76     elif args['output_mode'] == "regression":
         77         preds = np.squeeze(preds)
    ---> 78     result, wrong = compute_metrics(EVAL_TASK, preds, out_label_ids)
         79     results.update(result)
         80 

    <ipython-input-30-c0946f859f89> in compute_metrics(task_name, preds, labels)
         25 def compute_metrics(task_name, preds, labels):
         26     assert len(preds) == len(labels)
    ---> 27     return get_eval_report(labels, preds)
         28 
         29 def evaluate(model, tokenizer, prefix=""):

    <ipython-input-30-c0946f859f89> in get_eval_report(labels, preds)
         14 def get_eval_report(labels, preds):
         15     mcc = matthews_corrcoef(labels, preds)
    ---> 16     tn, fp, fn, tp = confusion_matrix(labels, preds).ravel()
         17     return {
         18         "mcc": mcc,

Когда я запускаю функцию do_eval, появляется следующая ошибка случилось. Как исправить эту ошибку?

1 Ответ

0 голосов
/ 29 мая 2020

sklearn.confusion_matrix возвращает 1-элементный одномерный массив, когда все прогнозы и достоверность совпадают. Например:

>>> confusion_matrix([1, 1, 1, 1], [1, 1, 1, 1]).ravel()
array([4], dtype=int64)

Таким образом, хотя мы могли иметь дело с двоичной классификацией, то есть 0 и 1, confusion_matrix, естественно, не имеет ни малейшего представления. Но есть способ сказать это, и это параметр labels:

>>> confusion_matrix([1, 1, 1, 1], [1, 1, 1, 1], labels=[0, 1]).ravel()
array([0, 0, 0, 4], dtype=int64)

Теперь все в порядке: у нас есть 4 TP и нет образца для других 3 полей.

Итак, вы должен содержать аргумент labels с двумя возможными значениями классификации, например [0, 1].

...