如何降低量化微调Falcon-7b模型的幻觉问题?
问题
我使用PEFT微调技术对开源大语言模型Falcon-7b-sharded进行了微调,但模型输出效果不佳,存在幻觉问题。在资源有限的情况下(训练环境配置如下),该如何优化模型输出?
训练GPU配置
- CUDA: 12.1
- GPU: NVIDIA Quadro P5000
模型输出

微调代码
from datasets import load_dataset # 指定数据集名称 dataset_name = "timdettmers/openassistant-guanaco" # 加载数据集并选择训练集,强制重新下载 dataset = load_dataset(dataset_name, split="train", download_mode="force_redownload") # 导入所需库 import torch from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig # 指定Falcon模型名称 model_name = "ybelkada/falcon-7b-sharded-bf16" # 配置BitsAndBytes量化参数 bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.float16, ) # 加载带量化配置的Falcon模型 model = AutoModelForCausalLM.from_pretrained( model_name, quantization_config=bnb_config, trust_remote_code=True ) # 禁用模型缓存 model.config.use_cache = False # 加载Falcon 7B的tokenizer,信任远程代码 tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) # 将padding token设置为eos token tokenizer.pad_token = tokenizer.eos_token # 导入LoRA配置模块 from peft import LoraConfig # 定义LoRA配置参数 lora_alpha = 16 lora_dropout = 0.1 lora_r = 64 # 创建LoRA配置对象 peft_config = LoraConfig( lora_alpha=lora_alpha, lora_dropout=lora_dropout, r=lora_r, bias="none", task_type="CAUSAL_LM", target_modules=[ "query_key_value", "dense", "dense_h_to_4h", "dense_4h_to_h", ] ) from transformers import TrainingArguments # 定义训练结果保存目录 output_dir = "./results" # 设置单设备训练批次大小 per_device_train_batch_size = 2 # 梯度累积步数 gradient_accumulation_steps = 4 # 选择优化器类型 optim = "paged_adamw_32bit" # 模型 checkpoint 保存间隔 save_steps = 10 # 训练指标日志间隔 logging_steps = 10 # 学习率 learning_rate = 2e-4 # 梯度裁剪的最大范数 max_grad_norm = 0.3 # 最大训练步数 max_steps = 50 # 学习率预热比例 warmup_ratio = 0.03 # 学习率调度器类型 lr_scheduler_type = "constant" # 创建训练配置对象 training_arguments = TrainingArguments( output_dir=output_dir, per_device_train_batch_size=per_device_train_batch_size, gradient_accumulation_steps=gradient_accumulation_steps, optim=optim, save_steps=save_steps, logging_steps=logging_steps, learning_rate=learning_rate, fp16=True, # 使用16位混合精度训练 max_grad_norm=max_grad_norm, max_steps=max_steps, warmup_ratio=warmup_ratio, group_by_length=True, lr_scheduler_type=lr_scheduler_type, ) from transformers import TrainingArguments # 重复定义了TrainingArguments,此处保留原始代码结构 output_dir = "./results" per_device_train_batch_size = 2 gradient_accumulation_steps = 4 optim = "paged_adamw_32bit" save_steps = 10 logging_steps = 10 learning_rate = 2e-4 max_grad_norm = 0.3 max_steps = 50 warmup_ratio = 0.03 lr_scheduler_type = "constant" training_arguments = TrainingArguments( output_dir=output_dir, per_device_train_batch_size=per_device_train_batch_size, gradient_accumulation_steps=gradient_accumulation_steps, optim=optim, save_steps=save_steps, logging_steps=logging_steps, learning_rate=learning_rate, fp16=True, max_grad_norm=max_grad_norm, max_steps=max_steps, warmup_ratio=warmup_ratio, group_by_length=True, lr_scheduler_type=lr_scheduler_type, ) # 将模型中的norm层转为float32 for name, module in trainer.model.named_modules(): if "norm" in name: module = module.to(torch.float32) trainer.train()
微调模型调用代码
# 导入所需库 import torch from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig # 指定Falcon模型名称 model_name = "ybelkada/falcon-7b-sharded-bf16" # 配置BitsAndBytes量化参数 bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.float16, ) # 加载带量化配置的Falcon模型 model = AutoModelForCausalLM.from_pretrained( model_name, quantization_config=bnb_config, trust_remote_code=True ) # 禁用模型缓存 model.config.use_cache = False # 加载Falcon 7B的tokenizer,信任远程代码 tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) # 将padding token设置为eos token tokenizer.pad_token = tokenizer.eos_token from peft import PeftModel, PeftConfig from transformers import AutoModelForCausalLM # 加载PEFT模型 PEFT_MODEL = "omarfarooq908/falcon-7b-finetuned01" # PEFT_MODEL = <你的模型仓库URL> config = PeftConfig.from_pretrained(PEFT_MODEL) peft_base_model = AutoModelForCausalLM.from_pretrained( config.base_model_name_or_path, return_dict=True, quantization_config=bnb_config, device_map="auto", trust_remote_code=True, ) peft_model = PeftModel.from_pretrained(peft_base_model, PEFT_MODEL) peft_tokenizer = AutoTokenizer.from_pretrained(config.base_model_name_or_path) peft_tokenizer.pad_token = peft_tokenizer.eos_token from transformers import GenerationConfig def generate_answer(query): system_prompt = """Answer the following question truthfully. You are a chatbot that can coherently hold conversations with humans, in English""" user_prompt = f""": {query} : """ final_prompt = system_prompt + "\n" + user_prompt device = "cuda:0" dashline = "-" * 50 encoding = tokenizer(final_prompt, return_tensors="pt").to(device) outputs = model.generate(input_ids=encoding.input_ids, generation_config=GenerationConfig(max_new_tokens=256, pad_token_id = tokenizer.eos_token_id, \ eos_token_id = tokenizer.eos_token_id, attention_mask = encoding.attention_mask, \ temperature=0.4, top_p=0.6, repetition_penalty=1.3, num_return_sequences=1,)) text_output = tokenizer.decode(outputs[0], skip_special_tokens=True) # print(dashline) # print(f'原始模型输出:\n{text_output}') # print(dashline) peft_encoding = peft_tokenizer(final_prompt, return_tensors="pt").to(device) peft_outputs = peft_model.generate(input_ids=peft_encoding.input_ids, generation_config=GenerationConfig(max_new_tokens=256, pad_token_id = peft_tokenizer.eos_token_id, \ eos_token_id = peft_tokenizer.eos_token_id, attention_mask = peft_encoding.attention_mask, \ temperature=0.4, top_p=0.6, repetition_penalty=1.3, num_return_sequences=1,)) peft_text_output = peft_tokenizer.decode(peft_outputs[0], skip_special_tokens=True) print(f'PEFT模型输出:\n{peft_text_output}') print(dashline) generate_answer("What is normal body temperature?")
优化方案
针对当前模型幻觉问题和资源限制,可从以下几个方向优化:
1. 训练数据与流程优化
- 增加训练步数:当前仅训练50步,对于Falcon-7B这类大模型远远不足,建议将
max_steps提升至500-1000步(P5000的16GB显存可支持该范围)。 - 删除代码冗余:微调代码中重复定义了
TrainingArguments,需删除重复部分,避免逻辑混乱。 - 适配任务数据集:若任务聚焦事实问答,可替换为
truthful_qa这类事实性数据集,或过滤openassistant-guanaco中事实性强的样本,减少无关对话内容干扰。 - 添加验证监控:在
TrainingArguments中设置evaluation_strategy="steps"和eval_steps=50,加入验证集监控模型性能,避免过拟合。
2. LoRA参数调整
- 缩小目标模块范围:优先仅针对
query_key_value层做LoRA微调,减少计算量的同时聚焦注意力机制的调整,去掉dense、dense_h_to_4h等模块。 - 降低LoRA秩:将
lora_r从64降至8或16,减少可训练参数数量,降低显存占用,同时避免过拟合。
3. 生成策略优化
- 降低温度参数:将
temperature从0.4进一步降至0.1-0.2,减少生成随机性,提升事实准确性。 - 强化提示约束:修改系统提示词为
"""请基于已知事实回答问题,不确定的内容明确说明不知道,禁止编造信息。你是可以流畅对话的英文聊天机器人""",明确约束模型输出。 - 切换波束搜索:将生成策略改为波束搜索(设置
do_sample=False、num_beams=3),提升输出严谨性。
4. 训练细节修复
- 修正norm层转换逻辑:将
module = module.to(torch.float32)改为module.to(torch.float32),确保模型中的norm层真正切换为float32精度,避免数值不稳定。 - 启用梯度检查点:加载模型时添加
gradient_checkpointing=True,进一步降低显存占用,支持更大批次或更多训练步数。
内容的提问来源于stack exchange,提问作者Muhammad Omar Farooq
相关产品推荐
相关产品推荐

