使用Trainer与直接调用模型评估HuggingFace Transformer为何结果不同?
问题:Trainer类与直接调用模型预测的准确率差异
我使用预训练Transformer模型进行序列分类任务,通过Trainer类在自有数据集上完成微调。使用Trainer类评估模型时,准确率达到94%,代码如下:
trainer = Trainer(model=model) preds = trainer.predict(validation_dataset) predictions = np.argmax(preds.predictions, axis=-1) metric = evaluate.load("accuracy") metric.compute(predictions=predictions, references=preds.label_ids) # prints: {'accuracy': 0.9435554514341591}
但当我直接调用模型获取预测结果时,准确率仅约86%,代码如下:
predictions = [] model.eval() for row in validation_dataset: text_ids = row['input_ids'].unsqueeze(0) predicted = torch.argmax(model(text_ids)[0]) predictions += [predicted.item()] metric.compute(predictions, labels) # prints {'accuracy': 0.8639942552151239}
想了解为何两种方式的预测结果存在差异,且Trainer评估的准确率更高?是遗漏了什么环节,还是实现存在问题?
原因分析与解决方法
- 未传入注意力掩码(attention_mask):Transformer模型需要
attention_mask区分真实输入和padding token,Trainer会自动从数据集中读取并传入,但你的手动推理代码只传了input_ids,模型会错误处理padding部分,导致预测偏差。修改后代码:for row in validation_dataset: text_ids = row['input_ids'].unsqueeze(0) mask = row['attention_mask'].unsqueeze(0) predicted = torch.argmax(model(text_ids, attention_mask=mask)[0]) predictions += [predicted.item()] - 设备不一致问题:如果Trainer用GPU训练/预测,而手动推理时模型或输入张量在CPU上,会导致结果异常。需确保模型和输入在同一设备:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model.to(device) for row in validation_dataset: text_ids = row['input_ids'].unsqueeze(0).to(device) mask = row['attention_mask'].unsqueeze(0).to(device) predicted = torch.argmax(model(text_ids, attention_mask=mask)[0]) predictions += [predicted.item()] - 标签匹配错误:手动推理用的
labels可能和Trainer使用的preds.label_ids顺序或内容不一致,比如数据集循环时被打乱。建议直接从循环的row中取标签:predictions = [] true_labels = [] model.eval() for row in validation_dataset: # 输入处理代码 predicted = torch.argmax(model(text_ids, attention_mask=mask)[0]) predictions += [predicted.item()] true_labels += [row['label'].item()] metric.compute(predictions=predictions, references=true_labels) - 未关闭自动梯度计算:即使开了
model.eval(),手动推理时最好加上torch.no_grad()上下文管理器,避免显存占用和潜在计算误差:predictions = [] true_labels = [] model.eval() with torch.no_grad(): for row in validation_dataset: # 输入处理代码 predicted = torch.argmax(model(text_ids, attention_mask=mask)[0]) predictions += [predicted.item()] true_labels += [row['label'].item()]
内容的提问来源于stack exchange,提问作者Jan Koci
相关产品推荐
相关产品推荐

