游乐游手机版
首页/AI热点日报/热点详情

QLoRA与自定义数据集微调大模型实战(下)

类型:热点整理2026-06-28
大型语言模型微调(LLM Fine-tuning)本质上是在已有强大预训练模型的基础上,利用更低的计算成本和更少的数据量,将其定制为特定领域的专家模型。本文将沿着数据预处理、模型准备、PEFT配置、训练与评估这一完整链路,逐步拆解整个微调流程,帮助您快速掌握QLoRA与自定义数据集微调大模型的核心方

大型语言模型微调(LLM Fine-tuning)本质上是在已有强大预训练模型的基础上,利用更低的计算成本和更少的数据量,将其定制为特定领域的专家模型。本文将沿着数据预处理、模型准备、PEFT配置、训练与评估这一完整链路,逐步拆解整个微调流程,帮助您快速掌握QLoRA与自定义数据集微调大模型的核心方法。

大模型微调,使用QLoRA和自定义数据集微调大模型(下)

4.8 数据预处理:格式化对话数据以适应LLM微调

在开始微调之前,原始数据集不能直接输入模型,需要先转换成模型能够理解的格式。为了让数据适配微调流程,需要编写一个辅助函数来格式化输入数据集。该函数的核心任务是将对话摘要对(即提示与响应)转换为大语言模型(LLM)能够识别的明确指令结构。

def create_prompt_formats(sample):
"""
格式化样本的各种字段('instruction', 'output')
然后使用两个换行符将它们连接起来
:param sample: 样本字典
"""
INTRO_BLURB = "以下是描述任务的指令。写一个适当完成请求的响应。"
INSTRUCTION_KEY = "### 指令:总结以下对话。"
RESPONSE_KEY = "### 输出:"
END_KEY = "### 结束"

blurb = f"n{INTRO_BLURB}"
instruction = f"{INSTRUCTION_KEY}"
input_context = f"{sample['dialogue']}" if sample["dialogue"] else None
response = f"{RESPONSE_KEY}n{sample['summary']}"
end = f"{END_KEY}"

parts = [part for part in [blurb, instruction, input_context, response, end] if part]

formatted_prompt = "nn".join(parts)
sample["text"] = formatted_prompt

return sample

上述函数完成提示文本的“翻译”后,接下来轮到分词器(Tokenizer)出场。它会将处理好的提示文本进一步拆解成模型能识别的token序列。这一步的目标是让输入序列长度统一,既能提升训练效率,也能降低计算成本,同时确保这些序列长度不超过模型允许的最大token数。

from functools import partial

# 来源 https://github.com/databrickslabs/dolly/blob/master/training/trainer.py
def get_max_length(model):
conf = model.config
max_length = None
for length_setting in ["n_positions", "max_position_embeddings", "seq_length"]:
max_length = getattr(model.config, length_setting, None)
if max_length:
print(f"找到最大长度:{max_length}")
break
if not max_length:
max_length = 1024
print(f"使用默认最大长度:{max_length}")
return max_length


def preprocess_batch(batch, tokenizer, max_length):
"""
分批标记化
"""
return tokenizer(
batch["text"],
max_length=max_length,
truncation=True,
)

# 来源 https://github.com/databrickslabs/dolly/blob/master/training/trainer.py
def preprocess_dataset(tokenizer: AutoTokenizer, max_length: int, seed, dataset):
"""格式化并标记化,使其准备好进行训练
:param tokenizer (AutoTokenizer): 模型分词器
:param max_length (int): 分词器发出的最大标记数
"""

# 为每个样本添加提示
print("预处理数据集...")
dataset = dataset.map(create_prompt_formats)#, batched=True)

# 对每个批次的数据集应用预处理并移除 'instruction', 'context', 'response', 'category' 字段
_preprocessing_function = partial(preprocess_batch, max_length=max_length, tokenizer=tokenizer)
dataset = dataset.map(
_preprocessing_function,
batched=True,
remove_columns=['id', 'topic', 'dialogue', 'summary'],
)

# 过滤掉输入_ids超过最大长度的样本
dataset = dataset.filter(lambda sample: len(sample["input_ids"]) < max_length)

# 随机打乱数据集
dataset = dataset.shuffle(seed=seed)

return dataset

经过这几步函数的处理,数据集就算彻底“清洗”完成了,可以放心送入训练流程。

## 数据集预处理
max_length = get_max_length(original_model)
print(max_length)

train_dataset = preprocess_dataset(tokenizer, max_length,seed, dataset['train'])
eval_dataset = preprocess_dataset(tokenizer, max_length,seed, dataset['validation'])

4.9 准备模型进行QLoRA训练:初始化与配置

接下来,使用PEFT库中的prepare_model_for_kbit_training方法对原始模型进行初始化,设置好必要的配置,为后续的QLoRA训练做好准备。这一步是高效微调大型语言模型的关键环节。

4.10 设置PEFT进行微调:LoRA参数配置

配置LoRA参数是微调前的重头戏,它直接影响最终效果。以下是常见的配置方式,其中秩(rank)和学习权重缩放因子等超参数需要根据任务灵活调整。

from peft import LoraConfig, get_peft_model

config = LoraConfig(
r=32, # 定义适配器的秩
lora_alpha=32, # 学习权重的缩放因子
target_modules=[
'q_proj', 'k_proj', 'v_proj', 'dense'
],
bias="none",
lora_dropout=0.05, # 防止过拟合
task_type="CAUSAL_LM", # 任务类型
)

# 启用梯度检查点减少内存消耗
original_model.gradient_checkpointing_enable()

# 获取配置好的PEFT模型
peft_model = get_peft_model(original_model, config)

这里的r(秩)参数控制适配器的复杂度,直接影响模型的表达能力与计算成本;而lora_alpha则用于调整学习权重,决定LoRA激活的强度。配置完成后,可以通过辅助函数查看模型的可训练参数数量,以评估微调效率。

print(print_number_of_trainable_model_parameters(peft_model))

4.11 训练PEFT适配器:参数设置与训练器初始化

训练参数的设置和训练器的初始化,是进入正式训练前最后的准备工作。以下代码展示了如何配置优化器、批次大小、步数等关键超参数,并基于Hugging Face Trainer启动微调。

import transformers
from transformers import TrainingArguments, Trainer, DataCollatorForLanguageModeling

# 设置训练参数
output_dir = f'./peft-dialogue-summary-training-{str(int(time.time()))}'
peft_training_args = TrainingArguments(
output_dir=output_dir,
warmup_steps=1,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
max_steps=1000,
learning_rate=2e-4,
optim="paged_adamw_8bit",
logging_steps=25,
logging_dir="./logs",
sa ve_strategy="steps",
sa ve_steps=25,
evaluation_strategy="steps",
eval_steps=25,
do_eval=True,
gradient_checkpointing=True,
report_to="none",
overwrite_output_dir=True,
group_by_length=True,
)

# 禁用缓存,准备训练器
peft_model.config.use_cache = False
peft_trainer = Trainer(
model=peft_model,
args=peft_training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False),
)

这里计划进行1000步训练,对于这个特定数据集来说是一个合理的起点。当然,实际应用中可以根据验证集的表现灵活调整步数或早停策略。训练时间会因超参数、硬件等因素而浮动,现在就可以启动微调了。

peft_trainer.train()

训练完成后,需要准备一个用于推理的模型。做法是给原始的Phi-2模型加载一个训练好的适配器,并将其设置为不可训练状态——毕竟它的使命到此为止,之后只用于生成摘要。

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

base_model_id = "microsoft/phi-2"
base_model = AutoModelForCausalLM.from_pretrained(base_model_id)
eval_tokenizer = AutoTokenizer.from_pretrained(base_model_id, add_bos_token=True)
eval_tokenizer.pad_token = eval_tokenizer.eos_token

from peft import PeftModel

ft_model = PeftModel.from_pretrained(
base_model,
"/kaggle/working/peft-dialogue-summary-training-1705417060/checkpoint-1000",
torch_dtype=torch.float16,
is_trainable=False
)

微调本质上是一个反复试验、不断调优的过程。很多时候,需要根据验证集和测试集的表现,回头调整模型结构、超参数或训练数据,才能让性能更上一个台阶。

4.12 定性评估模型(人工评估)

使用PEFT模型对同一个输入进行推理,直观感受微调前后摘要质量的差异。以下代码将生成摘要并与人类编写的基线进行对比。

from transformers import set_seed
set_seed(seed)

# 选择测试集中的一个对话样本
index = 5
dialogue = dataset['test'][index]['dialogue']
summary = dataset['test'][index]['summary']

# 构建推理提示
prompt = f"Instruct: Summarize the following conversation.n{dialogue}nOutput:n"

# 使用PEFT模型生成摘要
peft_model_res = gen(ft_model, prompt, 100)
peft_model_output = peft_model_res[0].split('Output:n')[1]
prefix, _, _ = peft_model_output.partition('###')

# 打印结果
dash_line = '-' * 100
print(dash_line)
print(f'输入提示:n{prompt}')
print(dash_line)
print(f'人工摘要:n{summary}n')
print(dash_line)
print(f'PEFT模型输出:n{prefix}')

这段代码会把PEFT模型生成的摘要和人类编写的基线摘要放在一起对比。通过这种人工评估,可以直观地判断微调是否真的带来了可感知的提升。

PEFT 模型输出

4.13 定量评估模型(使用ROUGE指标)

ROUGE(Recall-Oriented Understudy for Gisting Evaluation)是一种评估自动摘要和机器翻译效果的经典工具,核心思路是将机器生成的摘要与人工参考摘要进行比较。虽然不能说尽善尽美,但ROUGE指标能够很好地反映微调后摘要质量的整体变化趋势,是LLM微调评估中常用的定量手段。

接下来通过ROUGE指标定量评估模型生成的摘要:

from transformers import AutoModelForCausalLM
import pandas as pd
import evaluate
import numpy as np

# 加载模型和数据
original_model = AutoModelForCausalLM.from_pretrained(base_model_id, device_map='auto')
dialogues = dataset['test'][0:10]['dialogue']
human_baseline_summaries = dataset['test'][0:10]['summary']

# 初始化摘要列表
original_model_summaries = []
peft_model_summaries = []

# 生成摘要并评估
for idx, dialogue in enumerate(dialogues):
prompt = f"Instruct: Summarize the following conversation.n{dialogue}nOutput:n"
original_model_res = gen(original_model, prompt, 100)
original_model_text_output = original_model_res[0].split('Output:n')[1]

peft_model_res = gen(ft_model, prompt, 100)
peft_model_output = peft_model_res[0].split('Output:n')[1]
peft_model_text_output, _, _ = peft_model_output.partition('###')

original_model_summaries.append(original_model_text_output)
peft_model_summaries.append(peft_model_text_output)

# 将结果存入DataFrame
df = pd.DataFrame(list(zip(human_baseline_summaries, original_model_summaries, peft_model_summaries)),
columns=['human_baseline_summaries', 'original_model_summaries', 'peft_model_summaries'])

# 计算ROUGE指标
rouge = evaluate.load('rouge')
original_model_results = rouge.compute(predictions=original_model_summaries, references=human_baseline_summaries)
peft_model_results = rouge.compute(predictions=peft_model_summaries, references=human_baseline_summaries)

# 打印结果
print('原始模型ROUGE指标:')
print(original_model_results)
print('PEFT模型ROUGE指标:')
print(peft_model_results)

# 计算提升百分比
improvement = (np.array(list(peft_model_results.values())) - np.array(list(original_model_results.values())))
for key, value in zip(peft_model_results.keys(), improvement):
print(f'{key}提升: {value*100:.2f}%')

通过ROUGE指标的数值对比,PEFT模型相对于原始模型在摘要质量上的提升就一目了然了。量化数据能够清晰说明微调的价值与效果。

5 结语:LLM微调的未来与企业应用

微调大语言模型(LLM Fine-tuning)已成为企业优化运营流程、提升智能化水平时不可忽视的关键技术。预训练赋予了模型广泛的语言理解能力,但真正让模型成为某个细分领域专家的,正是微调这一步骤。针对不同任务、行业或数据集定制LLM,本质上是在拓展模型的实用边界,确保其在不断变化的数字环境中保持相关性与高效性。展望未来,随着PEFT、QLoRA等高效微调方法的持续精进,以及更多创新思路的涌现,我们有充分理由期待更加智能、高效且具备情境感知能力的人工智能系统诞生,为各行各业带来更深层次的变革。




来源:https://www.53ai.com/news/finetuning/2024120236075.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。