You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Huggingface Trainer微调GPT-J失败:模型未返回Loss求助

GPT-J微调报错:模型未返回loss的解决方法

问题背景

尝试用Huggingface Trainer微调GPT-J 6B模型时失败,报错提示模型未返回loss。参考BERT微调示例,但GPT-J作为因果语言模型和BERT有本质区别。使用Transformers 4.22.2版本,CPU和Paperspace GPU环境均出现相同错误,怀疑是从BERT示例照搬的配置(如compute_metrics、标签设置)存在问题,不清楚如何让模型生成loss并调整Trainer配置。

报错信息

File "xxx\ft_v3.py", line 66, in <module>
File "xxx\venv\lib\site-packages\transformers\trainer.py", line 1521, in train
    return inner_training_loop(
File "xxx\venv\lib\site-packages\transformers\trainer.py", line 1763, in _inner_training_loop
    tr_loss_step = self.training_step(model, inputs)
File "xxx\venv\lib\site-packages\transformers\trainer.py", line 2499, in training_step
    loss = self.compute_loss(model, inputs)
File "xxx\venv\lib\site-packages\transformers\trainer.py", line 2544, in compute_loss
    raise ValueError(
ValueError: The model did not return a loss from the inputs, only the following keys: logits,past_key_values. For reference, the inputs it received are input_ids,attention_mask.

报错原因

  1. 因果语言模型的训练逻辑差异:GPT-J是自回归模型,需要将input_ids作为标签传入模型才会自动计算交叉熵损失,原代码未添加标签列,导致模型无法生成loss。
  2. 错误的label_names配置:原代码将input_ids和attention_mask设为标签,Trainer无法识别正确的标签字段。
  3. 不必要的评估函数干扰:训练阶段直接照搬BERT的compute_metrics函数,因果语言模型的评估逻辑与BERT不同,且训练阶段无需该函数。

修正步骤

  • 添加标签列:在tokenize时将input_ids复制为labels,并将padding对应的标签设为-100(模型会忽略-100的标签,避免计算padding的损失)。
  • 修正label_names:将标签字段设为labels,删除错误的配置。
  • 移除训练阶段的评估函数:先跑通训练流程,评估逻辑后续再补充。

完整修正代码

from transformers import Trainer, TrainingArguments, GPTJForCausalLM, AutoTokenizer
from datasets import load_dataset
import time
import torch

start = time.time()

GPTJ_FINE_TUNED_FILE = "./fine_tuned_models/gpt-j-6B"

print("Loading model")
model = GPTJForCausalLM.from_pretrained("EleutherAI/gpt-j-6B", low_cpu_mem_usage=True)
model.config.pad_token_id = model.config.eos_token_id

print("Loading tokenizer")
tokenizer = AutoTokenizer.from_pretrained("EleutherAI/gpt-j-6B")
tokenizer.pad_token = tokenizer.eos_token

print("Loading dataset")
current_dataset = load_dataset("wikitext", 'wikitext-103-v1')
current_dataset['train'] = current_dataset['train'].select(range(1200))


def tokenize_function(examples):
    # 处理文本,添加padding和截断
    tokenized = tokenizer(examples["text"], padding="max_length", truncation=True, max_length=512)
    # 生成labels,将padding对应的token设为-100,避免计算损失
    tokenized["labels"] = [
        [-100 if token == tokenizer.pad_token_id else token for token in seq]
        for seq in tokenized["input_ids"]
    ]
    return tokenized


print("Splitting and tokenizing dataset")
tokenized_datasets = current_dataset.map(tokenize_function, batched=True)
# 过滤空文本样本(可选)
tokenized_datasets = tokenized_datasets.filter(lambda x: len(x["input_ids"]) > 0)
small_train_dataset = tokenized_datasets["train"].select(range(100))

print("Preparing training arguments")
training_args = TrainingArguments(
    output_dir=GPTJ_FINE_TUNED_FILE,
    report_to='all',
    logging_dir='./logs',
    per_device_train_batch_size=1,
    num_train_epochs=1,
    no_cuda=True,
    label_names=['labels']  # 明确标签字段为labels
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=small_train_dataset
)

print("Starting training")
trainer.train()
print(f"Finished fine-tuning in {time.time() - start}")

补充说明

  • GPU环境适配:去掉no_cuda=True即可自动加载到CUDA设备,注意调整per_device_train_batch_size避免显存溢出,GPT-J 6B在单GPU上可配合梯度累积或8-bit量化(如bitsandbytes库)使用。
  • 评估阶段补充:若需评估,需修改compute_metrics函数,先过滤掉labels中的-100值,再计算准确率等指标。

内容的提问来源于stack exchange,提问作者Erik Hyrkas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 04:32:09