【bug】KeyError: “The metric_for_best_model training argument is set to ‘eval_loss’, which is not foun

文章目录

问题

KeyError: “The metric_for_best_model training argument is set to ‘eval_loss’, which is not found in the evaluation metrics. The available evaluation metrics are: [‘eval_runtime’, ‘eval_samples_per_second’, ‘eval_steps_per_second’, ‘epoch’]. Consider changing the metric_for_best_model via the TrainingArguments.”

在Transformer的Trainer中添加的compute_metrics没起作用。

参考:
***eval_loss not found when training a peft model using trainer.py #33420
It just doesn’t calculate the metrics #782

当前transformers版本为4.46.0

def compute_metrics(eval_preds, **kwargs):
    preds, labels, *inputs_losses = eval_preds
    
    # preprocess labels
    # take label which not equal to -100
    preds = preds[labels != -100]
    labels = labels[labels != -100]
    labels = np.where(labels > 0.5, 1, 0)

    accuracy = accuracy_score(labels, preds)
    f1 = f1_score(labels, preds)
    auc = roc_auc_score(labels, preds)
    precision = precision_score(labels, preds)
    recall = recall_score(labels, preds)
    
    return dict(
        accuracy=accuracy,
        f1=f1,
        auc=auc,
        precision=precision,
        recall=recall
    )

trainer = Trainer(
    model=model,
    processing_class=tokenizer,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=valid_dataset,
    data_collator=DataCollatorWithPadding(tokenizer),
    preprocess_logits_for_metrics=preprocess_logits_for_metrics,
    compute_metrics=compute_metrics,
    compute_loss_func=compute_loss_func,
)

尝试过在training_args中添加include_for_metrics = ['loss'],但是不起作用。compute_metrics中的内容没有返回。

解决

本质上由于使用的是PeftModel导致self.label_names[]
所以,在trainer.py732行附近,修改为如下代码。
原代码:

default_label_names = find_labels(self.model.__class__)
self.label_names = default_label_names if self.args.label_names is None else self.args.label_names
self.can_return_loss = can_return_loss(self.model.__class__)

修改为如下:

if _is_peft_model(self.model):
    if hasattr(self.model, "get_base_model"):
        model_to_inspect = self.model.get_base_model()
        default_label_names = find_labels(model_to_inspect.__class__)
        self.can_return_loss = can_return_loss(model_to_inspect.__class__)
else:
    default_label_names = find_labels(self.model.__class__)
    self.can_return_loss = can_return_loss(self.model.__class__)
self.label_names = default_label_names if self.args.label_names is None else self.args.label_names

分析

经过trainer.py的源码分析,发现是all_labels竟然是空的。导致compute_metrics未执行。

请添加图片描述

向上回溯,发现prediction_step返回的labels也是空的。
请添加图片描述

labels is None!

进入看看,理论上has_labels应该为True,因为len(self.label_names) != 0,但是has_labels == False
请添加图片描述

has_labels == False!

看看self.label_names的定义,发生了什么?理论上default_label_names将找到默认的标签labels,然后赋值给self.label_names
请添加图片描述

看看find_labels,它将forward函数的参数签名拿到,然后将里面包含label的参数签名返回。
请添加图片描述


重点来了,因为我们使用的是PeftModel,它的forward函数的没有包含label的参数签名。

请添加图片描述

找到问题后,发现已经有人提出PR了,但是最新版本的transformers还没有更新上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值