LLM:使用Python总结对话的实用指南

2024年06月06日 由 alex 发表 59 0

在过去的一年半中,自然语言处理 (NLP) 因大型语言模型 (LLM) 而发生了巨大变化。这些模型可以处理几年前看似不可能完成的语言任务。


LLM 非常棒——它们可以翻译语言、分析情绪,甚至生成文本。但从头开始训练这些模型非常昂贵,而且需要大量时间。这就是微调如此重要的原因。微调意味着采用预先训练的模型并对其进行调整以执行特定任务。这使得模型在这些任务上表现更好,并在更多情况下有用。


通过微调,我们可以利用预训练 LLM 的强大功能,训练它们执行我们所需的操作。这使得它们在客户服务聊天机器人、研究工具等方面非常有用。


我们将利用 Hugging Face 生态系统中的多个高级库和工具,包括transformers、、和。这些工具旨在高效处理自然datasets语言处理 (NLP) 任务的各个方面,从加载和预处理数据集到配置和训练复杂的模型。以下是我们将涵盖的内容概述:peftbitsandbytes


  1. 安装所需的软件包:我们将首先安装所有必要的 Python 包。
  2. 导入必要的库:接下来,我们将导入在整个微调过程中将使用的必要库。
  3. 加载数据集:我们将加载dialogsum数据集。
  4. 准备和预处理数据集:我们将通过定义和应用提示模板来准备训练。通过标记文本并删除不必要的列来预处理数据集。
  5. 配置和加载模型:我们将配置和加载预先训练的语言模型,BitsAndBytesConfig以实现高效的内存使用。
  6. 配置和初始化 QLoRA:我们将设置 QLoRA(量化 LoRA)参数以实现参数高效的微调。
  7. 设置训练参数:我们将定义和设置训练参数,包括批量大小、学习率和评估策略。
  8. 保存和加载训练好的模型:训练后,我们将保存微调后的模型和标记器,然后重新加载模型进行评估。
  9. 测试和评估模型:最后,我们将使用 Rouge 分数(摘要任务的标准指标)来测试和评估模型的性能。


6


安装所需的软件包

在开始之前,我们需要安装必要的软件包。其中包括用于处理数据集、实现转换器、参数高效微调 (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


  1. use_4bit: 布尔变量,表示是否使用 4 位精度量化。设置为 True 时,将启用 4 位量化,从而在保持性能的同时减少模型的内存占用和计算需求。
  2. bnb_4bit_compute_dtype: 一个字符串,用于指定 4 位量化期间计算所用的数据类型。在本例中,它被设置为 “bfloat16”,代表 “bfloat16 ”数据类型。Bfloat16 是一种 16 位浮点表示法,在精度和内存效率之间提供了一种折中方案。
  3. bnb_4bit_quant_type: 一个字符串,指定用于 4 位量化的量化类型。这里设置为 “nf4”,表示 “NearFloat4”。NearFloat4 量化是一种将模型参数量化为 4 位的方法,同时将性能损失降至最低。
  4. use_nested_quant(使用嵌套量化): 布尔变量,表示是否使用嵌套量化。设置为 True 时,将启用嵌套量化,即对模型的某些层或组件进行额外的量化。
  5. compute_dtype(计算类型): 一个变量,代表量化过程中用于计算的数据类型。可通过 getattr 函数获取,该函数从火炬模块中获取一个属性(“bfloat16”)。


配置和初始化 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)配置的参数。


  • lora_r 指定 LoRA 的注意力维度。
  • lora_alpha 为 LoRA 缩放设置 alpha 参数。
  • lora_dropout 定义 LoRA 层的辍学概率。
  • task_type 设置为 “CAUSAL_LM”,指定模型将用于的任务类型(因果语言建模)。
  • peft_model: 该变量使用 get_peft_model 函数初始化 PEFT 模型。
  • peft_config 将作为 PEFT 模型的配置传递。


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. 输出目录:

  • output_dir = f'./peft-dialogue-summary-training-{str(int(time.time()))}': 根据当前时间戳创建一个唯一目录,用于存储训练输出。


2. 训练参数:

  • output_dir: 保存模型检查点的位置。
  • warmup_steps(热身步骤): 预热步数。
  • per_device_train_batch_size(每设备训练批次大小): 每个设备的批量大小。
  • gradient_accumulation_steps(梯度累积步数): 梯度累积的步数。
  • max_steps:最大训练步数: 最大训练步数。
  • learning_rate: 学习率。
  • optim: 优化器类型,此处为 “paged_adamw_8bit”。
  • logging_steps(记录步数): 日志记录频率。
  • logging_dir: 日志文件目录。
  • save_strategy 和 save_steps:保存检查点的策略和频率: 保存检查点的策略和频率。
  • evaluation_strategy 和 eval_steps: 评估策略和频率。
  • do_eval: 是否在训练过程中执行评估。
  • report_to: 报告到 “tensorboard ”以记录日志。
  • overwrite_output_dir(覆盖输出目录): 是否覆盖输出目录。
  • group_by_length(按长度分组): 是否对长度相似的序列进行分组,以提高训练效率。


3. 训练器初始化:

  • model(模型): 要训练的 PEFT 模型。
  • train_dataset 和 eval_dataset: 训练数据集和评估数据集。
  • data_collator: 用于语言建模的数据整理器,可处理批处理和填充。


4. 模型训练

  • trainer.train(): 根据指定设置启动训练过程。


测试和评估模型

最后,我们使用 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 = evaluate.load('rouge'): 加载 ROUGE 评估器,它通常用于摘要任务,以测量生成的摘要与参考摘要之间的重叠度。
  • rouge.compute(...): 使用生成的摘要和人类参考摘要计算 ROUGE 分数。


ROUGE(Recall-Oriented Understudy for Gisting Evaluation)是一组用于评估文本摘要和翻译质量的指标,通过比较生成的文本和参考文本来进行评估。


以下是主要的 ROUGE 指标:

  1. ROUGE-N:衡量生成文本和参考文本之间 n-grams 的重叠度(例如,ROUGE-1 表示单字元,ROUGE-2 表示双字元)。
  2. ROUGE-L: 在考虑词序的情况下,测量词的最长公共子序列(LCS)。
  3. ROUGE-S:测量跳读重定语从句(skip-bigrams)的重叠度,允许词与词之间存在间隙。
  4. ROUGE-SU: 将跳字重合度与单字重合度相结合,以获得更全面的测量结果。


这些指标有助于评估生成的文本与人类撰写的摘要的匹配程度,同时考虑召回率和精确度。


结论

在过去的一年半里,由于大型语言模型(LLM)的兴起,自然语言处理(NLP)领域取得了长足的进步。这些模型彻底改变了语言翻译、情感分析和文本生成等应用。尽管 LLM 的能力令人印象深刻,但从头开始训练 LLM 仍然是一个耗时且昂贵的过程。这就是微调预训练模型的作用所在。

文章来源:https://medium.com/gopenai/fine-tuning-llms-a-practical-guide-to-summarizing-conversations-with-python-a1c1688aaecf
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
写评论取消
回复取消