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

如何降低量化微调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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:03:09