GPT2模型训练出现Loss Nan问题求助(附实现代码)
GPT2微调问答任务时Loss出现NaN的问题排查
问题概述
我正在做GPT2的微调用于问答任务,因为数据集规模较大,用了Dataloader做批处理,但训练时Loss直接变成NaN。以下是我的批处理创建流程及代码:
class FeedbackEssentials(Dataset): def __init__(self, qa_pairs, tokenizer, max_length): self.qa_pairs = qa_pairs self.tokenizer = tokenizer self.max_length = max_length def __len__(self): return len(self.qa_pairs) def __getitem__(self, idx): question = self.qa_pairs[idx][0] text = f"{question} {self.tokenizer.eos_token}" input_ids = self.tokenizer.encode(text, add_special_tokens=True, max_length=self.max_length, padding='max_length', truncation=True) attention_mask = [1] * len(input_ids) # Assuming all tokens should be attended to return { 'input_ids': torch.tensor(input_ids), 'attention_mask': torch.tensor(attention_mask) } def text_manipulation(train_dataset): column1_values = train_dataset['Total Marks'].values column2_values = train_dataset['Coding'].values listOfLists = [[pair[0], pair[1]] for pair in zip(column1_values, column2_values)] text = "" for feedback in listOfLists: text += f"{feedback[0]} {feedback[1]} {tokenizer.eos_token}" return text training_dataset = text_manipulation(dataset) max_length_training = max(len(tokenizer.encode(qa_pair[0],add_special_tokens=True)) for qa_pair in training_dataset) dataset_training = FeedbackEssentials(training_dataset, tokenizer, max_length_training)
数据加载器及优化器设置:
batch_size = 4 dataloader = DataLoader(dataset_training, batch_size=batch_size, shuffle=True) optimizer = torch.optim.AdamW(model.parameters(), lr=5e-5) scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.9)
问题排查及修复方案
1. 数据集构造核心错误
你的text_manipulation函数返回的是拼接后的大字符串,但FeedbackEssentials需要的是QA对列表。这导致后续training_dataset是字符串,遍历它时qa_pair是单个字符,__getitem__里取qa_pairs[idx][0]就是单个字符,完全不符合QA对的格式,输入数据混乱直接导致Loss NaN。
修复text_manipulation,直接返回QA对列表:
def text_manipulation(train_dataset): column1_values = train_dataset['Total Marks'].values column2_values = train_dataset['Coding'].values # 直接返回QA对列表,不要拼接成字符串 return [[pair[0], pair[1]] for pair in zip(column1_values, column2_values)]
2. Max Length计算错误
之前因为training_dataset是字符串,计算max_length_training时遍历的是单个字符,得到的max_length是1,导致所有输入被截断成1个token,模型根本无法学习。修复后重新计算:
training_dataset = text_manipulation(dataset) # 计算每个QA对(问题+答案)的最大token长度 max_length_training = max( len(tokenizer.encode(f"{qa[0]} {qa[1]}", add_special_tokens=True)) for qa in training_dataset ) dataset_training = FeedbackEssentials(training_dataset, tokenizer, max_length_training)
3. 缺少训练所需的Labels
GPT2是自回归语言模型,训练时需要labels(和input_ids对应,模型会自动处理移位逻辑)。当前代码没有返回labels,模型计算loss时会出错。修改__getitem__:
def __getitem__(self, idx): question, answer = self.qa_pairs[idx] # 拼接问题+答案,作为模型的输入和目标 text = f"{question} {answer} {self.tokenizer.eos_token}" encoding = self.tokenizer( text, max_length=self.max_length, padding='max_length', truncation=True, return_tensors='pt' ) input_ids = encoding['input_ids'].squeeze() attention_mask = encoding['attention_mask'].squeeze() # labels和input_ids一致,将padding位置设为-100,计算loss时会忽略这些位置 labels = input_ids.clone() labels[attention_mask == 0] = -100 return { 'input_ids': input_ids, 'attention_mask': attention_mask, 'labels': labels }
4. Attention Mask错误
之前的attention_mask把padding部分也设为1,这会让模型关注无效的padding token,导致计算异常。现在直接使用tokenizer返回的attention_mask即可,它会自动把padding位置设为0。
5. 其他辅助修复点
- 梯度裁剪:训练时添加梯度裁剪,防止梯度爆炸导致NaN:
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) - 降低学习率:当前5e-5可能过高,尝试降到1e-5
- 检查数据:确认
Total Marks和Coding列有没有异常值(比如空值、非文本内容)
内容的提问来源于stack exchange,提问作者Irfan Yaqub
相关产品推荐
相关产品推荐

