GPT-Neo微调文本分类遇AttributeError报错求助
GPT-Neo微调tweet_eval情感分类报错排查:AttributeError: 'list' object has no attribute 'keys'
问题背景
使用Hugging Face的tweet_eval情感子集,基于GPT-Neo-2.7B做文本分类,运行trainer.train()时触发AttributeError: 'list' object has no attribute 'keys'错误。
错误原因
核心问题是传给Trainer的数据集格式错误:
- 手动拆分了数据集的文本和标签,用
tokenizer批量处理后得到的train_inputs是一个包含input_ids、attention_mask等键的大字典(每个键对应所有样本的列表),但Trainer需要的是每个元素为单样本字典的数据集结构(比如Hugging Face Dataset对象,或[{"input_ids": [...], "attention_mask": [...], "label": ...}, ...]形式的列表)。 - 当DataLoader尝试迭代这个大字典时,会把每个键对应的值(比如
input_ids的列表)当成单个样本,导致后续pad函数接收到列表而非字典,触发keys属性不存在的错误。
修正后的完整代码
from transformers import AutoModelForSequenceClassification, AutoTokenizer, TrainingArguments, Trainer import datasets import torch as t from transformers import DataCollatorWithPadding import evaluate import numpy as np # 直接加载数据集,不手动拆分文本和标签 dataset = datasets.load_dataset("tweet_eval", "emotion") def load_LLM(llm, device): num_labels = 4 id2label = {0: "Anger", 1: "Joy", 2: "Optimism", 3: "Sadness"} label2id = {"Anger": 0, "Joy": 1, "Optimism": 2, "Sadness":3} model = AutoModelForSequenceClassification.from_pretrained(llm, num_labels=num_labels, id2label=id2label, label2id=label2id) model.to(device) tokenizer = AutoTokenizer.from_pretrained(llm) return model, tokenizer llm = "EleutherAI/gpt-neo-2.7B" device = t.device('cuda' if t.cuda.is_available() else 'cpu') model, tokenizer = load_LLM(llm, device) # GPT-Neo默认无pad token,推荐用eos_token替代,避免新增特殊token导致embedding不匹配 tokenizer.pad_token = tokenizer.eos_token # 定义tokenization函数,在原始数据集上批量处理 def tokenize_function(examples): return tokenizer(examples["text"], truncation=True) # 对数据集做tokenization,保留label字段 tokenized_datasets = dataset.map(tokenize_function, batched=True) data_collator = DataCollatorWithPadding(tokenizer=tokenizer) accuracy = evaluate.load("accuracy") def compute_metrics(eval_pred): predictions, labels = eval_pred predictions = np.argmax(predictions, axis=1) return accuracy.compute(predictions=predictions, references=labels) training_args = TrainingArguments( output_dir="my_awesome_model", learning_rate=2e-5, per_device_train_batch_size=16, per_device_eval_batch_size=16, num_train_epochs=2, weight_decay=0.01, evaluation_strategy="epoch", save_strategy="epoch", load_best_model_at_end=True, push_to_hub=True, # GPT-Neo-2.7B参数量大,显存不足时开启梯度检查点 gradient_checkpointing=True ) trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_datasets["train"], eval_dataset=tokenized_datasets["test"], tokenizer=tokenizer, data_collator=data_collator, compute_metrics=compute_metrics ) trainer.train()
关键修改说明
- 保留Dataset原始结构:不再手动拆分文本和标签,用
dataset.map()批量处理tokenization,确保每个样本保留label字段,生成符合要求的Dataset对象。 - 正确设置pad token:用GPT-Neo自带的
eos_token作为pad token,避免新增特殊token导致模型embedding层不兼容。 - 传递合规数据集:将处理后的
tokenized_datasets["train"]和tokenized_datasets["test"]传给Trainer,而非tokenizer返回的大字典。
内容的提问来源于stack exchange,提问作者Aditya Srinivas
相关产品推荐
相关产品推荐

