基于Alpaca-LoRA无监督微调报错AssertionError求助
基于Alpaca-LoRA做无监督MLM微调时的AssertionError排查
修改内容
基于Alpaca-LoRA的finetune.py做无监督领域掩码语言建模,主要做了两处修改:
1. 加载Alpaca-LoRA权重替代Llama基础权重
from peft import ( # LoraConfig, PeftModel, get_peft_model, get_peft_model_state_dict, prepare_model_for_int8_training, set_peft_model_state_dict, )
# 注释原LoraConfig初始化代码 # config = LoraConfig( # r=lora_r, # lora_alpha=lora_alpha, # target_modules=lora_target_modules, # lora_dropout=lora_dropout, # bias="none", # task_type="CAUSAL_LM", # ) # model = get_peft_model(model, config) # 替换为加载Alpaca-LoRA权重 LORA_WEIGHTS = "tloen/alpaca-lora-7b" model = PeftModel.from_pretrained( model, LORA_WEIGHTS, torch_dtype=torch.float16, )
2. 自定义无监督数据集生成逻辑
def chunk_text(data): concantenated_text = '' all_result = [] for i in range(data['train'].num_rows): concantenated_text += data['train']['combined'][i] tokenized_concantenated_text = tokenizer.encode(concantenated_text)[1:] tokenized_prompt = tokenizer.encode("### Text: ")[1:] full_length = len(tokenized_concantenated_text) for i in range(0, full_length, chunk_size): text = tokenized_concantenated_text[i: i+chunk_size+overlap_size] text = tokenized_prompt + text text = tokenizer.decode(text) result = tokenizer(text, padding=False) if result["input_ids"][-1] != tokenizer.eos_token_id: result["input_ids"].append(tokenizer.eos_token_id) result["attention_mask"].append(1) result["labels"] = result["input_ids"].copy() all_result.append(result) return all_result
报错信息
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮ │ in <cell line: 2>:2 │ │ │ │ /usr/local/lib/python3.9/dist-packages/transformers/trainer.py:1662 in train │ │ │ │ 1659 │ │ inner_training_loop = find_executable_batch_size( │ │ 1660 │ │ │ self._inner_training_loop, self._train_batch_size, args.auto_find_batch_size │ │ 1661 │ │ ) │ │ ❱ 1662 │ │ return inner_training_loop( │ │ 1663 │ │ │ args=args, │ │ 1664 │ │ │ resume_from_checkpoint=resume_from_checkpoint, │ │ 1665 │ │ │ trial=trial, │ │ │ │ /usr/local/lib/python3.9/dist-packages/transformers/trainer.py:1991 in _inner_training_loop │ │ │ │ 1988 │ │ │ │ │ │ │ xm.optimizer_step(self.optimizer) │ │ 1989 │ │ │ │ │ elif self.do_grad_scaling: │ │ 1990 │ │ │ │ │ │ scale_before = self.scaler.get_scale() │ │ ❱ 1991 │ │ │ │ │ │ self.scaler.step(self.optimizer) │ │ 1992 │ │ │ │ │ │ self.scaler.update() │ │ 1993 │ │ │ │ │ │ scale_after = self.scaler.get_scale() │ │ 1994 │ │ │ │ │ │ optimizer_was_run = scale_before <= scale_after │ │ │ │ /usr/local/lib/python3.9/dist-packages/torch/cuda/amp/grad_scaler.py:368 in step │ │ │ │ 365 │ │ if optimizer_state["stage"] is OptState.READY: │ │ 366 │ │ │ self.unscale_(optimizer) │ │ 367 │ │ │ │ ❱ 368 │ │ assert len(optimizer_state["found_inf_per_device"]) > 0, "No inf checks were rec │ │ 369 │ │ │ │ 370 │ │ retval = self._maybe_opt_step(optimizer, optimizer_state, *args, **kwargs) │ │ 371 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ AssertionError: No inf checks were recorded for this optimizer.
环境信息
- Python 3.9
- CUDA 11.8
解决方案
1. 修正混合精度配置与模型加载逻辑
该报错核心是GradScaler未检测到梯度缩放操作,通常因混合精度配置不匹配导致:
- 确保基础模型加载时的精度与Peft模型一致,且开启int8/fp16训练:
# 基础模型加载修正 model = AutoModelForCausalLM.from_pretrained( base_model_path, # 替换为你的Llama基础模型路径 load_in_8bit=True, # 若不用int8则设为float16=True torch_dtype=torch.float16, device_map="auto", ) # 加载Alpaca-LoRA LORA_WEIGHTS = "tloen/alpaca-lora-7b" model = PeftModel.from_pretrained( model, LORA_WEIGHTS, torch_dtype=torch.float16, ) # 强制设置模型为训练模式 model.train()
- 确保TrainerArguments中开启
fp16=True:
training_args = TrainingArguments( ... fp16=True, ... )
2. 修复MLM任务的标签逻辑
当前数据集代码将labels直接复制input_ids,是自回归任务的逻辑,而非MLM任务。MLM需要对输入token随机掩码,并仅保留掩码位置的标签,其他位置设为-100(跳过损失计算):
import random def chunk_text(data): all_result = [] chunk_size = 512 # 根据你的硬件调整 overlap_size = 64 mask_ratio = 0.15 for i in range(data['train'].num_rows): text = data['train']['combined'][i] tokenized_text = tokenizer.encode(text, add_special_tokens=False) tokenized_prompt = tokenizer.encode("### Text: ", add_special_tokens=False) full_length = len(tokenized_text) # 单条文本分块,避免拼接所有文本导致内存溢出 for j in range(0, full_length, chunk_size - overlap_size): chunk_tokens = tokenized_text[j:j+chunk_size] input_tokens = tokenized_prompt + chunk_tokens + [tokenizer.eos_token_id] labels = input_tokens.copy() # 生成掩码位置(仅对正文部分掩码,跳过prompt和eos) mask_start = len(tokenized_prompt) mask_end = len(input_tokens) - 1 mask_count = max(1, int(mask_ratio * (mask_end - mask_start))) mask_indices = random.sample(range(mask_start, mask_end), mask_count) # 执行MLM掩码规则:80%掩码,10%随机token,10%保留原token for idx in mask_indices: rand_val = random.random() if rand_val < 0.8: input_tokens[idx] = tokenizer.mask_token_id elif rand_val < 0.9: input_tokens[idx] = random.choice(list(tokenizer.vocab.values())) # 剩余10%保留原token,labels不变 # 非掩码位置设为-100,不参与损失计算 for idx in range(len(labels)): if idx not in mask_indices: labels[idx] = -100 all_result.append({ "input_ids": input_tokens, "attention_mask": [1]*len(input_tokens), "labels": labels }) return all_result
3. 调整依赖库版本
部分版本的transformers/peft/torch存在兼容性问题,可尝试:
- 升级依赖库:
pip install --upgrade transformers peft bitsandbytes torch
- 若仍报错,降级torch到与CUDA11.8兼容的稳定版本:
pip install torch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 --index-url https://download.pytorch.org/whl/cu118
内容的提问来源于stack exchange,提问作者John Jam
相关产品推荐
相关产品推荐

