继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

如何为自己的需求定制大模型:轻松微调Llama 3 8B

12345678_0001
关注TA
已关注
手记 240
粉丝 13
获赞 47

LLM生成的关于LLM微调的图像(左边为GPT,中间也为GPT,右边为Gemini)

自2022年11月发布以来,ChatGPT已经引起了关于大型语言模型(LLM)和人工智能能力的广泛讨论。现在,很少有人没听说过ChatGPT或没尝试过使用它。尽管像GPT、Gemini或Claude这样的工具拥有数百亿甚至数千亿的参数,并且已经在庞大的文本语料库上进行了预训练,它们并非万能。这些模型在某些特定任务上会显得力不从心。不过,我们并不缺少解决方法。我们可以利用较小的开源模型,将它们调整以适应我们特定的问题。

这篇博客旨在简单介绍一下几个较小的开源大型语言模型,并讲解两个重要概念:量化和LoRA。此外,我们还将介绍几个最受欢迎的库,并附有代码示例,让您快速应用这些概念。让我们开始吧,一起深入了解微调。

如果你想跳过理论直接看代码,可以点击这里。

目录如下
  1. “小规模”大型语言模型
  2. 量化技术
  3. 低秩适应(LoRA)
  4. Unsloth
  5. 监督微调训练器(SFT)技术
  6. 比率偏好优化技术(ORPO)
  7. 结论。
  8. 参考文献资料
小型大语言模型

看看Llama 3和其他模型相比如何

微调大语言模型可能会非常昂贵,尤其是对于参数量很大的模型。一般来说,参数少于10亿的模型通常可以进行微调而不会遇到显著的基础设施挑战。然而,对于更大的模型,如Llama 3 70亿参数,需要大量的资源。微调一个像Llama 3这样的70亿参数模型大约需要1.5太字节的GPU显存。为了更好地理解这个数量,这相当于大约20个配备80GB显存的Nvidia A100显卡组成的集群。这种设置的成本大约为40万美元(假设硬件可获得)。

或者可以使用像 AWS、Azure 或 GCP 这样的云服务提供商,但这也非常昂贵。例如,在 AWS 上使用 8 个 Nvidia A100 GPU 一小时需要 40 美元。如果你用 20 个 GPU 在 5 天内对 70B 参数的模型进行微调,大约需要花费 12,000 美元。

由于这些成本,大多数实践者主要使用参数少于10亿的小型LLM。这些模型可以更经济地训练它们,只需要16GB到24GB的vRAM(支持更大的批处理和更快的训练)。比如说,我使用AWS上的Nvidia A10将Mistral 7B微调到塞尔维亚语,这花费不到10小时,成本不到20美元。

当然,还是,7B模型仍然无法在不进行4位量化的情况下,在那么多vRAM上训练。

(量化)

(量化)指将连续的数值范围转换为离散的数值范围的过程。

即使使用全32位参数,我们仍然需要极其夸张(以凡人标准来看)的大约150GB的显存来训练这个大型语言模型。

把 FP32 转换为 INT8

量化通过将模型参数转换为低精度的数据类型(如8位或4位),显著减少了内存消耗,并且提升了执行速度。其概念很简单:所有可能的32位数值被映射到一个较小的范围,例如8位转换为256个可能的值。这个过程可以被理解为将高精度值分组到几个特定的固定点周围,这些固定点代表了附近值的近似。

下秩适应(LoRA).

LoRA 是一种利用矩阵维度减少来更新模型权重的技术。由于变压器在大语言模型中被广泛应用且依赖于矩阵,因此这项技术尤为重要。Jay Alammar 的一篇 博客文章 中详细解释了 LoRA 的底层工作方式。

定期微调

在更新模型权重时,需要调整这些矩阵中的参数,即调整权重。从概念上看,这种调整可以看作是在原矩阵上加上一个权重更新矩阵:W’ = W + ΔW,其中W’表示更新后的权重,W表示原来的权重,ΔW表示权重的更新量。LoRA 通过将权重更新矩阵分解为两个较小的矩阵来引入了一种新的方法,这两个矩阵相乘可以近似原权重更新矩阵。在微调阶段,LoRA 直接生成这两个较小的矩阵,而不是先创建更新矩阵再进行分解,而是直接生成这两个较小的矩阵。

以下图片展示了常规微调与使用LoRA进行微调之间的说明性比较,取自塞巴斯蒂安·拉施卡(Sebastian Raschka)的博客文章

左边是常规微调的另一种方式,右边是使用LoRA的微调方法。

LoRA 的关键优势在于,虽然近似可能稍微不那么精确,但显著提升了内存和计算效率。例如,考虑一个 1000x1000 的参数矩阵,总共有 100 万个参数。通过使用略微不那么精确的 1000x100 和 100x1000 矩阵的分解版本,参数数量减少到 20 万个,参数量减少了 80%。

量化和LoRA经常被一起使用,形成了所谓的QLoRA,这种组合被称为QLoRA。

Unsloth

如果我要重新开始大规模语言模型(LLM)的微调,我会选择 Unsloth。Unsloth 提供了多种针对 LLM 微调优化,并支持包括 Mistral、Llama 3、Gemma 等在内的多种流行的大规模语言模型。例如,他们的免费层级包含了对 Mistral 的 12 种微调优化,加速了近 2.2 倍。

UNSLOTH 精细调优

以下是一些代码片段,展示了如何使用Unsloth库对Llama 3 8B进行调优。以下代码均来自Unsloth GitHub,完整的Llama 3 8B调优笔记本可以在这里查看:此处。Llama 3 8B(一种大型语言模型)。

导入4比特模型:

    model, tokenizer = FastLanguageModel.from_pretrained(  
        model_name = "unsloth/llama-3-8b-bnb-4bit",  
        max_seq_length = 最大序列长度,  
        dtype = 数据类型,  
        load_in_4bit = load_in_4bit,  
        # 如果使用的是像meta-llama/Llama-2-7b-hf这样的受保护模型,你需要提供一个token  
    )

配置LoRA参数:

    model = FastLanguageModel.get_peft_model(  
        model,  
        r = 16, # 选择任何大于0的数!建议选择8、16、32、64或128  
        target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",  
                          "gate_proj", "up_proj", "down_proj",],  
        lora_alpha = 16,  
        lora_dropout = 0, # 支持任何值,但=0是优化过的  
        bias = "none",    # 支持任何值,但='none'是优化过的  
        # [NEW] "unsloth" 使用30%更少的VRAM,适合两倍大的批次  
        use_gradient_checkpointing = "unsloth", # True或"unsloth"适用于非常长的上下文  
        random_state = 3407,  
        use_rslora = False,  # 我们支持秩稳定的LoRA和LoftQ  
        loftq_config = None,  
    )

开始使用 Hugging Face 的有监督微调工具:

    trainer = SFTTrainer(  
        model = model,  
        tokenizer = tokenizer,  
        train_dataset = dataset,  
        dataset_text_field = "text",  
        max_seq_length = max_seq_length,  
        dataset_num_proc = 2,  
        packing = False, # 可以将短序列的训练速度提高5倍。  
        args = TrainingArguments(  
            per_device_train_batch_size = 2,  
            gradient_accumulation_steps = 4,  
            warmup_steps = 5,  
            max_steps = 60,  
            learning_rate = 2e-4,  
            fp16 = not torch.cuda.is_bf16_supported(),  
            bf16 = torch.cuda.is_bf16_supported(),  
            logging_steps = 1,  
            optim = "adamw_8bit",  
            weight_decay = 0.01,  
            lr_scheduler_type = "linear",  
            seed = 3407,  
            output_dir = "outputs",  
        ),  
    )

训练模型:

trainer_stats = trainer.train(); // 训练器的统计数据通过调用训练器的训练方法获得。

监督微调训练师 (SFT,即监督微调训练)

在经过预训练一个大模型之后,接下来的关键步骤是监督微调。这个过程对于开发一个能够理解和生成连贯的回复的模型至关重要,而不是仅仅完成句子的填充。

像 Hugging Face 提供的 SFT 和 PEFT 这样的工具,以及 Tim Dettmers 开发的 BitsAndBytes,显著简化了将诸如 LoRA、量化以及微调等技术应用到模型中的过程。这些库使得实现这些高级优化方法变得更加简单高效,无论是对开发者还是研究人员来说都更加友好。

下面你会发现Unsloth、SFT和ORPO的代码相当相似。这种相似性是因为这些库的基本理念大体相同,区别主要在于库的具体实现以及可能涉及的一些超参数。

导入4位精度的模型:

    # Hugging Face 模型 ID  
    model_id = "meta-llama/Meta-Llama-3-8B"  
    model_id = "mistralai/Mistral-7B-v0.1"  

    # 位宽4配置  
    bnb_config = BitsAndBytesConfig(  
        load_in_4bit=True,  
        bnb_4bit_use_double_quant=True,  
        bnb_4bit_quant_type="nf4",  
        bnb_4bit_compute_dtype=torch.bfloat16 if use_flash_attention2 else torch.float16  
    )  

    # 加载自回归语言模型和自动分词器  
    model = AutoModelForCausalLM.from_pretrained(  
        model_id,   
        quantization_config=bnb_config,   
        use_cache=False,   
        device_map="auto",  # 设备分配方式为自动模式  
        token=os.environ["HF_TOKEN"],  # 如果模型是受保护的,比如 llama 或者 Mistral  
        attn_implementation="flash_attention_2" if use_flash_attention2 else "sdpa"  
    )  
    model.config.pretraining_tp = 1  

    tokenizer = AutoTokenizer.from_pretrained(  
        model_id,  
        token=os.environ["HF_TOKEN"],  # 如果模型是受保护的,比如 llama 或者 Mistral  
    )  
    tokenizer.pad_token = tokenizer.eos_token  
    tokenizer.padding_side = "right"  # 分词器的填充方向设置为右边

设置LoRA:

    # 基于 QLoRA 论文的 LoRA 配置如下
    peft_config = LoraConfig(
            lora_alpha=16,
            lora_dropout=0.1,
            r=64,
            bias="none",
            task_type="CAUSAL_LM",
            target_modules=[
                "q_proj",
                "k_proj",
                "v_proj",
                "o_proj",
                "gate_proj",
                "up_proj",
                "down_proj",
            ]
    )

    # 准备模型训练
    model = prepare_model_for_kbit_training(model)

开始使用 Hugging Face 的监督微调训练程序:

    args = TrainingArguments(  
        output_dir="mistral-int4-alpaca",  
        num_train_epochs=1,  
        per_device_train_batch_size=6 if use_flash_attention2 else 2, # 你可以根据你的硬件调整批量大小。  
        gradient_accumulation_steps=4, # 梯度累积步数  
        gradient_checkpointing=True,  
        optim="paged_adamw_8bit", # 注意:paged_adamw_8bit 是一种特定的优化器,可能需要额外解释  
        logging_steps=10,  
        save_strategy="epoch",  
        learning_rate=2e-4,  
        bf16=use_flash_attention2,  
        fp16=not use_flash_attention2,  
        tf32=use_flash_attention2,  
        max_grad_norm=0.3,  
        warmup_steps=5,  
        lr_scheduler_type="linear", # 学习率调度器类型  
        disable_tqdm=False, # 禁用进度条  
        report_to="none"  
    )  

    model = get_peft_model(model, peft_config)
    trainer = SFTTrainer(  
        model=model,  
        train_dataset=dataset,  
        peft_config=peft_config,  
        max_seq_length=2048,  
        tokenizer=tokenizer,  
        packing=True,  
        formatting_func=format_instruction,  
        args=args,  
    )

训练这个模型:

trainer.训练模型() # 开始训练模型

该完整的笔记本可以在这里找到这里

优势比率偏好优化 ORPO

在这篇博客文章中,我们重点介绍了大型语言模型(LLM)的预训练和有监督的微调。然而,所有顶尖的大型语言模型都会经历另一个关键步骤:偏好调整。这一步发生在预训练和微调之后,通过告诉模型哪些生成的输出是可取的,哪些不是。偏好调整的流行方法包括从人类反馈中的强化学习(RLHF)和直接偏好优化法(DPO)。

2024年3月,出现了一种叫做优势比偏好优化法(ORPO)的新方法,结合了监督微调和偏好对齐。

传统LLM调优与ORPO LLM调优对比

关于ORPO的详细解释,包括代码示例和总体概述,可以参阅Maxime Labonne的内容深刻的博客文章

这里有一段使用ORPO进行微调和调整偏好的代码。完整代码可以在这里找到:here

导入4位精度的模型:

    # 模型  
    base_model = "meta-llama/Meta-Llama-3-8B"  
    new_model = "OrpoLlama-3-8B"  

    # QLoRA 配置  
    bnb_config = 位和字节配置(  
        加载4位=True,  
        4位量化类型="nf4",  
        4位计算数据类型=torch_dtype,  
        4位使用双量化=True,  
    )  

    # 定义自动分词器  
    tokenizer = 自动分词器.from_pretrained(base_model)  

    # 定义自动因果语言模型  
    model = 自动因果语言模型.from_pretrained(  
        base_model,  
        量化配置=bnb_config,  
        设备映射="自动",  
        注意力实现方式=attn_implementation  
    )

设置LoRA环境:

    # LoRA
    peft_config = LoraConfig(
        r=16,
        lora_alpha=32,
        lora_dropout=0.05,
        bias="none",
        task_type="CAUSAL_LM",  # 代表因果语言模型 (CAUSAL_LM)
        target_modules=['up_proj', 'down_proj', 'gate_proj', 'k_proj', 'q_proj', 'v_proj', 'o_proj']  # 目标模块
    )

    model = prepare_model_for_kbit_training(model)  # 准备模型进行位元训练

初始化 Hugging Face 的 ORPO Trainer, 如下:

    orpo_args = ORPOConfig(  
        learning_rate=8e-6,  # 学习率
        beta=0.1,  # 衰减系数
        lr_scheduler_type="linear",  # 学习率调度器类型:线性
        max_length=1024,  # 最大长度
        max_prompt_length=512,  # 最大提示长度
        per_device_train_batch_size=2,  # 每设备训练批次大小
        per_device_eval_batch_size=2,  # 每设备评估批次大小
        gradient_accumulation_steps=4,  # 梯度累积步数
        optim="paged_adamw_8bit",  # 优化器:paged_adamw_8bit
        num_train_epochs=1,  # 训练周期数
        evaluation_strategy="steps",  # 评估策略:步骤
        eval_steps=0.2,  # 评估步数
        logging_steps=1,  # 日志步数
        warmup_steps=10,  # 预热步数
        report_to="wandb",  # 报告到wandb
        output_dir="./results/",  # 输出目录
    )
trainer = ORPOTrainer(  
    model=model,  
    args=orpo_args,  
    train_dataset=dataset["train"],  
    eval_dataset=dataset["test"],  
    peft_config=peft_config,  
    tokenizer=tokenizer,  
)

让我们来训练模型。

trainer.训练()
结语

虽然像GPT、Gemini或Claude这样的大型语言模型(LLMs)非常强大,但其庞大的规模和资源需求使得它们在许多任务中难以实现。为了解决这个问题,可以使用如量化和低秩适应(LoRA)等技术对较小的开源LLMs进行微调和定制,以满足特定需求的定制。这些技术能够减少内存消耗并提高计算效率,使其更加经济高效,特别是那些参数少于100亿的模型。

像 Unsloth、监督微调(SFT)和几率比偏好优化(ORPO)这样的工具简化了微调过程,使其更加易于使用。例如,Unsloth 就能显著加速训练过程。而 ORPO 结合了监督微调和偏好一致来提升模型性能。

通过利用这些技术和工具,开发人员和研究人员可以定制大语言模型(LLM),以满足他们的特定需求,而无需承担训练大型模型的高昂成本。这种方法使高级语言模型的访问更加民主化,从而使各个领域中广泛应用的程序得以实现。

参考文献

[1] 模型内存实用:https://huggingface.co/spaces/hf-accelerate/model-memory-usage

AWS EC2 P4d 实例定价: https://aws.amazon.com/ec2/instance-types/p4/#:~:text=了解更多详情%C2%BB-,实例详情,-实例规格

  1. 量化详细说明:https://huggingface.co/docs/optimum/concept_guides/quantization

[4] 使用 NVIDIA TensorRT 进行量化感知训练法以使 INT8 推理达到 FP32 的精度:https://developer.nvidia.com/blog/achieving-fp32-accuracy-for-int8-inference-using-quantization-aware-training-with-tensorrt/

《Transformer 图解》: https://jalammar.github.io/illustrated-transformer/

[6] LoRA:低秩适配:大型语言模型的低秩适配:https://arxiv.org/abs/2106.09685论文

[7] 使用低秩适应(LoRA)进行参数高效的LLM微调:https://sebastianraschka.com/blog/2023/llm-finetuning-lora.html

[8] QLoRA:高效微调量化LLM。点击这里查看详细信息:https://arxiv.org/abs/2305.14314

[9] Unsloth:https://unsloth.ai/ (一个专注于减少工作倦怠的人工智能平台)

[10] 带有监督的微调训练器:https://huggingface.co/docs/trl/sft_trainer

[11] ORPO:不依赖参考模型的一体化偏好优化:https://arxiv.org/abs/2403.07691

[12] 使用 ORPO 微调 Llama 3 模型:https://huggingface.co/blog/mlabonne/orpo-llama-3

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP