在过去的一年半中,自然语言处理 (NLP) 因大型语言模型 (LLM) 而发生了巨大变化。这些模型可以处理几年前看似不可能完成的语言任务。
LLM 非常棒——它们可以翻译语言、分析情绪,甚至生成文本。但从头开始训练这些模型非常昂贵,而且需要大量时间。这就是微调如此重要的原因。微调意味着采用预先训练的模型并对其进行调整以执行特定任务。这使得模型在这些任务上表现更好,并在更多情况下有用。
通过微调,我们可以利用预训练 LLM 的强大功能,训练它们执行我们所需的操作。这使得它们在客户服务聊天机器人、研究工具等方面非常有用。
我们将利用 Hugging Face 生态系统中的多个高级库和工具,包括transformers、、和。这些工具旨在高效处理自然datasets语言处理 (NLP) 任务的各个方面,从加载和预处理数据集到配置和训练复杂的模型。以下是我们将涵盖的内容概述:peftbitsandbytes
安装所需的软件包
在开始之前,我们需要安装必要的软件包。其中包括用于处理数据集、实现转换器、参数高效微调 (PEFT) 和评估模型性能的库。
!pip install bitsandbytes transformers peft accelerate datasets evaluate rouge_score
导入必要的库
接下来,我们导入数据处理、模型训练和评估所需的所有库。
from datasets import load_dataset
from transformers import (AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TrainingArguments, Trainer, GenerationConfig, pipeline)
from tqdm import tqdm
from peft import LoraConfig, PeftModel, get_peft_model, prepare_model_for_kbit_training
import torch
import time
import pandas as pd
import numpy as np
from huggingface_hub import interpreter_login
import os
import transformers
加载数据集
我们将使用 dialogsum 数据集来完成这项任务。首先,我们加载数据集。dialogsum 数据集来自Hugging Face Datasets库,这是一个用于自然语言处理任务的各种数据集的存储库。
dataset = load_dataset("knkarthick/dialogsum")"knkarthick/dialogsum")
准备和预处理数据集
prepare_prompt_template 函数将对话、说明和摘要结合起来,为对话摘要任务格式化提示信息。它利用预定义的标记和常量来有效地构建提示语。使用该函数处理数据集中的示例,为训练和测试数据集生成提示。
def prepare_prompt_template(example):
dialogue = example['dialogue']
summary = example['summary']
PROMPT_START = '<s>'
PROMPT_END = '</s>'
INTRO_BLURB = "Below is an instruction that describes a task. Write a response that appropriately completes the request."
INSTRUCTION_KEY_START = "[INST]: Summarize the conversation in two lines.\n"
INSTRUCTION_END_KEY = "[/INST]"
SYSTEM_START_KEY = '<<SYS>>'
SYSTEM_END_KEY = '<</SYS>>'
formatted_prompt = f'{PROMPT_START}{INSTRUCTION_KEY_START} {dialogue} {INSTRUCTION_END_KEY} {summary} {PROMPT_END}'
example["text"] = formatted_prompt
return example
example = dataset['train'][10]
example = prepare_prompt_template(example)
print(example['text'])
train_dataset = dataset['train'].map(prepare_prompt_template)
test_dataset = dataset['test']
配置和加载模型
我们使用 BitsAndBytesConfig 配置和加载预训练模型,以提高内存使用效率。
提供的代码片段为语言模型配置量化设置,并使用这些设置初始化预训练模型。它设置了量化精度、量化类型以及是否使用嵌套量化等参数。这些设置会应用到从抱脸模型集线器获取的基础语言模型。此外,模型配置中还禁用了缓存,并设置了预训练任务参数。
use_4bit = TrueTrue
bnb_4bit_compute_dtype = "bfloat16"
bnb_4bit_quant_type = "nf4"
use_nested_quant = False
compute_dtype = getattr(torch, bnb_4bit_compute_dtype)
bnb_config = BitsAndBytesConfig(
load_in_4bit=use_4bit,
bnb_4bit_quant_type=bnb_4bit_quant_type,
bnb_4bit_compute_dtype=compute_dtype,
bnb_4bit_use_double_quant=use_nested_quant
)
model_name = "NousResearch/Llama-2-7b-chat-hf"
device_map = 'auto'
base_model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map=device_map
)
base_model.config.use_cache = False
base_model.config.pretraining_tp = 1
配置和初始化 QLoRA
我们设置 QLoRA(Quantized LoRA)参数进行微调。
PEFT(参数高效微调)是一种通过更新一小部分参数对大型语言模型进行微调的方法,因此非常节省资源。QLoRA(Quantized LoRA)将量化与 LoRA(Low-Rank Adaptation)相结合,进一步降低了微调过程中的内存和计算需求。
该代码片段正在以特定设置配置和初始化 PEFT(参数高效微调)模型。让我们来分解一下:
lora_r = 88
lora_alpha = 16
lora_dropout = 0.05
peft_config = LoraConfig(
lora_alpha=lora_alpha,
lora_dropout=lora_dropout,
r=lora_r,
bias="none",
task_type="CAUSAL_LM",
)
peft_model = get_peft_model(base_model, peft_config)
peft_model.config.use_cache = False
lora_r、lora_alpha 和 lora_dropout: 这些变量定义了 QLoRA(量化 LoRA)配置的参数。
peft_model.config.use_cache = False: 这一行禁用了模型配置中的缓存,这有助于在训练过程中节省内存。
总的来说,这段代码设置了一个用于微调的 PEFT 模型,配置了 QLoRA 关注的特定参数,然后初始化模型以进行进一步训练。
设置训练参数
我们定义了训练参数,包括输出目录、批量大小、学习率和评估策略。
output_dir = f'./peft-dialogue-summary-training-{str(int(time.time()))}'f'./peft-dialogue-summary-training-{str(int(time.time()))}'
training_arguments = TrainingArguments(
output_dir=output_dir,
warmup_steps=1,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
max_steps=10,
learning_rate=2e-4,
optim="paged_adamw_8bit",
logging_steps=25,
logging_dir="./logs",
save_strategy="steps",
save_steps=25,
evaluation_strategy="steps",
eval_steps=25,
do_eval=True,
report_to="tensorboard",
overwrite_output_dir=True,
group_by_length=True,
)
trainer = transformers.Trainer(
model=peft_model,
train_dataset=train_dataset,
eval_dataset=test_dataset,
args=training_arguments,
data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False),
)
trainer.train()
该代码片段使用 Hugging Face 的变换器库设置并启动了 PEFT 模型的训练。下面是简要说明:
1. 输出目录:
2. 训练参数:
3. 训练器初始化:
4. 模型训练
测试和评估模型
最后,我们使用 Rouge 分数来评估模型的性能。
使用以下代码段准备测试提示。
def prepare_test_prompt_template(example):
dialogue = example['dialogue']
summary = example['summary']
PROMPT_START = '<s>'
INSTRUCTION_KEY_START = "[INST]: Summarize the conversation in one line.\n"
INSTRUCTION_END_KEY = "[/INST]"
formatted_prompt = f'{PROMPT_START}{INSTRUCTION_KEY_START} {dialogue} {INSTRUCTION_END_KEY}'
return formatted_prompt, summary
index = 0
example = test_dataset[index]
prompt, summary = prepare_test_prompt_template(example)
input_ids = tokenizer(prompt, return_tensors='pt').input_ids
peft_model_outputs = peft_model.generate(input_ids=input_ids, generation_config=GenerationConfig(max_new_tokens=200, num_beams=1))
peft_model_text_output = tokenizer.decode(peft_model_outputs[0], skip_special_tokens=True)
import evaluate
# Load the Rouge evaluator
rouge = evaluate.load('rouge')
# Compute ROUGE scores for the generated summaries compared to the human summaries
rouge.compute(
predictions=generated_output,
references=human_summary,
use_aggregator=True,
use_stemmer=True
)
ROUGE(Recall-Oriented Understudy for Gisting Evaluation)是一组用于评估文本摘要和翻译质量的指标,通过比较生成的文本和参考文本来进行评估。
以下是主要的 ROUGE 指标:
这些指标有助于评估生成的文本与人类撰写的摘要的匹配程度,同时考虑召回率和精确度。
结论
在过去的一年半里,由于大型语言模型(LLM)的兴起,自然语言处理(NLP)领域取得了长足的进步。这些模型彻底改变了语言翻译、情感分析和文本生成等应用。尽管 LLM 的能力令人印象深刻,但从头开始训练 LLM 仍然是一个耗时且昂贵的过程。这就是微调预训练模型的作用所在。