大语言模型微调快速上手

大家知道,我做这些AI视频的目的,是消除大家的AI恐惧症。AI 只是计算机科学的一个分支,其本质和其他算法没有太多区别;实际应用中,你稍微学习一下,可能就和那些所谓的大拿就差不多了,因为这块没有人敢说自己彻底弄明白了。你和他们的区别,就是,他们整体在这个领域摸打滚爬,比你早几天,多了解一些东西。

这期内容的目的就是破除模型微调的神秘感,让大家能够快速上手,对开源的模型进行微调。

我已经在很多期节目里讲过,大模型的训练是非常烧钱的事情,以至于这件事情,已经变成了那些大公司的或他们的马夹公司的玩物,甚至对大公司都需要考虑一下如何快速且省钱省力地调整模型。我们提到了三种方法:

  • 微调
  • 提示词工程
  • 增强式生成

微调就是其中这三个里最费钱、费力,但可能最接近模型本身的解决方式。

大模型微调(Fine-tuning)是指在已经预训练好的大模型基础上,使用特定的数据集进行进一步的训练,以使模型适应特定任务或领域。这个已经训练好的模型,我们称之为预训练模型(Pre-trained Model),或基础模型(Foundation Model),微调在大语言模型里非常通用,发展出很多技术,在其他一些模型,比如图像生成的 Diffusion 模型里,也很常见。

微调的技术,有很多分类方式。从训练数据的来源、以及训练的方法的角度,大模型的微调有以下几条技术路线:

  • 监督微调(Supervised Fine-tuning) SFT
  • 无监督微调(Unsupervised Fine-tuning) UFT
  • 和半监督微调

按对模型内部参赛的修改,分为:

  • 全微调(Full Fine-tuning)
  • 部分微调(Repurposing)
  • 适配器微调(Adapter Tuning)
  • 低秩适配微调 LoRA(Low-rank adaptation )

全微调

全微调的原理,就是使用特定领域的数据,对预训练模型进行额外训练,使得模型在特定领域表现更出色。

全微调大开销是很大的,和正常的模型训练的区别只是训练数据集不同,且比较小。一般只有当目标任务与基础模型之间存在较大差异,或者需要模型具有高度自适应能力,才会被使用。另外,还有可能导致灾难性遗忘,把原来表现好的别的领域的能力变差。

部分微调

部分微调解决了全微调的上面两个问题,它是一种被广泛采用的技术,发展出很多细分技术。比如:

  • 层级微调,只微调预训练模型的一部分层,通常是最后几个层或某些特定层,这些参数通常低于整个参数集的1%
  • 冻结层微调,在微调过程中固定预训练模型的大部分层,只微调部分层。

适配器微调

  • 严格来说,Adapter是种特殊的部分微调,适配器可以看作是一种额外的层,它在模型里插入小型的可学习参数集(称为适配器)作为特定任务的学习参数集。Adapter层可以添加在模型的内部任何地方。这种方式在大语言模型被广泛使用,来实现很多自然语言处理的特殊任务,比如:
    • 文本分类
    • 命名实体识别
    • 词性标注
    • 文本摘要和关键词提取
    • 等等。
  • Adapter 微调有如下的优点:
    • 参数共享:不同任务的差异由Adapter实现,模型的其他部分参数被所有任务共享。
    • 训练资源需求低。适配器的参数量非常小,微调需要的计算量和存储就非常小
    • 高效:训练非常快
    • 适配器引入了额外的泛化能力,可以让整个模型快速适应不同的任务。
    • 可解释性较高:不同适配器针对不同的任务,其参数可以帮助理解模型在不同任务上的表现。

提示词微调

  • 提示词(Prompt) 微调其核心思想是使用简短的提示(prompt)来指导模型生成文本或执行特定任务,生成符合预期的输出。它的实现原理是在词嵌入层(Embedding),在输入序列X之前,增加一些特定长度的特殊Token(也就是文本或提示),以增大生成期望序列的概率。从实现上看,它是一种在词嵌入层上实现特殊的适配器微调。提示词微调通常用于生成式任务,如文本生成、问答系统等,以及分类任务,如文本分类、序列标注等。与传统的微调方法相比,提示词微调更加灵活和可控,可以根据任务的特点和需求来设计和调整提示。以下是一些提示词微调的关键特点和优势:
    • 任务定制:提示词微调允许用户根据特定任务的需求设计自定义的提示,从而使得模型能够更好地理解和执行任务,从而提高模型在特定任务上的性能。
    • 控制生成:通过设计合适的提示,可以有效地控制模型生成的文本内容,使其符合预期的要求,提高生成式任务的质量和准确性。
    • 灵活性:提示词微调提供了灵活的方式来调整模型的行为,用户可以根据需要自由地设计和调整提示,以适应不同的任务和场景。
    • 解释性:由于提示是人为设计的,因此模型生成的结果通常更容易被解释和理解。这种解释性可以帮助用户更好地理解模型的行为和输出。
    • 适用范围广泛:提示词微调适用于各种生成式和分类任务,包括文本生成、问答系统、文本分类、序列标注等。用户可以根据具体任务的需求来设计和使用合适的提示。

前缀微调

  • 前缀(Prefix) 微调,和提示词微调¡有类似的基本原理和出发点,也常见于大语言模型。两者的区别是,前缀微调添加在不同的层。在以Transformer位基础的大语言模型中,额外层添加在模型的Encoder和Decoder ,而不是词嵌入层。这些额外层添加在模型的输入端。前缀微调的一些关键特点和优势和适配器微调类同。

低秩适配微调

  • Low-rank adaptation (LoRA)微调方法利用了一个关键洞察或假说,即使在微调过程中,预训练模型中的一些参数可能并不需要高精度的调整。基于这一观察,LoRA 把需要微调的参数转换成W+∆W的形式,并把∆W分解成 A*B的低秩形式。微调的过程,就是训练得到A和B,也就得到了∆W。在推理过程中,只需要把执行W+∆W即可对于特定的任务。切换不同的任务,只需要对应的∆W即可。LoRA有适配器微调的各种优点,同时还多出两个其他优点:
    • 由于将预训练模型中的一些参数转化为低秩形式,并且仅对这些低秩参数进行微调,从而以更少的资源实现高效微调,并且更快的收敛。
    • 它不会像适配器微调一样增加模型的深度,因此微调前后推理速度不变。

量化低秩适配微调

  • 量化(Quantization),是一种在保证模型效果基本不降低的前提下,通过降低参数的精度,来减少模型对于计算资源的需求的方法。
  • 量化的核心目标是降成本,降训练成本,特别是降后期的推理成本。
  • QLoRA就是量化版的LoRA,将原本用16bit表示的参数,降为用更少的参数,比如4bit来表示,可以在保证模型效果的同时,极大地降低成本。
  • QLoRA 有LoRA优点,但是训练成本更低。

训练方法

LLaMA-Factory 里提供了很多常见的训练方法。我们需要大概了解一下。每种方法的具体原理,今天就不介绍了。

  • 预训练/Pre-Training:预训练模型
  • 监督微调/Supervised Fine-Tuning:利用有标签的数据来微调预训练模型的方法
  • 奖励模型/Reward Modeling:通过构建奖励模型来衡量生成文本的质量,并以此指导预训练模型的微调过程
  • 近端策略优化/PPO(Proximal Policy Optimization) :其核心思想是通过限制每次策略更新的幅度,防止过大的更新步伐破坏已有的策略结构
  • 直接偏好优化/DPO(Direct Preference Optimization):主要通过直接优化模型生成结果的偏好分布来提高模型在特定任务上的表现。
  • 知识转移/KTO(Knowledge Transfer Optimization):将预训练模型在大规模数据上学到的知识迁移到特定任务中
  • 正交正则化近端优化/Orthogonal Regularization Proximal Optimization(ORPO):旨在通过正则化策略和优化算法来提高模型的性能和稳定性。
  • 同步预测和优化/SimPO(Simultaneous Prediction and Optimization):一种简化的近端优化方法

上面所有的训练方法,都可配合全微调,部分微调,LoRA和QLoRA使用。

微调的一般性步骤

微调虽然有很多细分的技术,但是他们大都有下面几个一般性的步骤,但具体细节可能会因需求的不同而有所变化:

  • 准备数据集:收集和准备与目标任务相关的训练数据集。确保数据集质量和标注准确性,并进行必要的数据清洗和预处理。
  • 选择预训练模型/基础模型:根据目标任务的性质和数据集的特点,选择适合的预训练模型。
  • 设定微调策略:根据任务需求和可用资源,选择适当的微调策略。考虑是进行全微调还是部分微调,以及微调的层级和范围。
  • 设置超参数:确定微调过程中的超参数,如学习率、批量大小、训练轮数等。这些超参数的选择对微调的性能和收敛速度有重要影响。
  • 初始化模型参数:根据预训练模型的权重,初始化微调模型的参数。对于全微调,所有模型参数都会被随机初始化;对于部分微调,只有顶层或少数层的参数会被随机初始化。
  • 进行微调训练:使用准备好的数据集和微调策略,对模型进行训练。在训练过程中,根据设定的超参数和优化算法,逐渐调整模型参数以最小化损失函数。
  • 模型评估和调优:在训练过程中,使用验证集对模型进行定期评估,并根据评估结果调整超参数或微调策略。这有助于提高模型的性能和泛化能力。
  • 测试模型性能:在微调完成后,使用测试集对最终的微调模型进行评估,以获得最终的性能指标。这有助于评估模型在实际应用中的表现。
  • 模型部署和应用:将微调完成的模型部署到实际应用中,并进行进一步的优化和调整,以满足实际需求。

微调在以前是有相当技术含量的工作。但在开源社区的不断努力下,尤其是新一代中国年轻开源贡献者的努力下,微调已经被干成白菜了。如果你在GitHub上搜索一下,你会发现很多很多微调工具。今天我给大家介绍的 LLaMA-Factory 就是由北航的某位女大咖奉献的。这是GitHub网址:https://github.com/hiyouga/LLaMA-Factory

下面我就用弱智吧的对话数据,以最简单的方式,对最新的 Llama 3 进行微调,希望对那些希望快速上手的朋友有些帮助。

一、运行环境

  • UM790 Pro 64GB Ram + eGPU RTX 3060
  • Windows 11 + WSL 2 + Ubuntu 22.04 LTS
  • MiniConda + Python 3.10.14
  • 机器的具体安装配置过程请参考我以前的视频或博客

二、基本过程

  • 使用 Mini Conda 创建 Python 虚拟环境
  • 下载 LLaMA-Factory 源代码
  • 安装和配置 Python 的运行环境
  • 申请 HuggingFace 的账号,生成 Access Token
  • 修改运行时的配置文件。配置文件里的内容都是自解释的,你可以根据自己的需要进行调整,我这里只修改了dataset 和 use_unsloth 这两项。LLaMA-Factory已经集成了很多准备完善的微调训练数据,可以省下大量数据准备时间。
  • 运行。由于我的GPU比较差,运行实际非常长,请保证机器能够连续运行。
  • 推理测试。不知是什么原因,这个推理问答非常慢。我用 ollama 测试同一个模型,要快很多。
  • 导出模型。
# 创建并激活运行环境
conda create -n llama-factory python=3.10
conda activate llama-factory
# 下载源代码
git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git
# 安装运行时需要的各种第三方包
cd LLaMA-Factory
pip install -e .[torch,metrics]
pip install --upgrade huggingface_hub
pip install flash_attn
# 如果使用 vllm 做推理测试,需要安装 vllm
pip install vllm
# 如果使用了任何在 hugginface 上的数据或模型,你需要先生成一个 token,然后用这个Token登录一下
huggingface-cli login
# 修改配置文件。弱智吧的数据已经被集成近 LLaMA-Factory,我们只需要修改一下配置文件里的 dataset。我们使用了默认的单GPU LoRA微调。
vi examples/lora_single_gpu/llama3_lora_sft.yaml
dataset: identity,ruozhiba_gpt4
# 进行微调
CUDA_VISIBLE_DEVICES=0 llamafactory-cli train examples/lora_single_gpu/llama3_lora_sft.yaml 
# 推理测试
CUDA_VISIBLE_DEVICES=0 llamafactory-cli chat examples/inference/llama3_lora_sft.yaml
# 导出模型
CUDA_VISIBLE_DEVICES=0 llamafactory-cli export examples/merge_lora/llama3_lora_sft.yaml
Category:

Related Posts