摘要
文章介绍了QLoRa(Quantized LLMs with Low-Rank Adapters),一种在消费者级别的硬件上微调大型语言模型(LLM)的新方法。QLoRa通过引入4位量化、双重量化和利用nVidia统一内存进行分页,大大减少了微调所需的内存,同时保持了与标准微调相当的性能。文章还提供了如何使用QLoRa微调一个拥有200亿参数的GPT模型的详细步骤,包括硬件和软件的要求,以及如何准备数据集和进行微调。
开篇
微调具有数十亿参数的模型现在可以在消费者硬件上实现。大多数大型语言模型(LLM)过于庞大,无法在消费者硬件上进行微调。例如,要微调一个拥有650亿参数的模型,我们需要超过780 Gb的GPU内存。这相当于十个A100 80 Gb的GPU。换句话说,您需要云计算来微调您的模型。现在,有了QLoRa,只需要一个A100就可以做到。
在这篇博客文章中,将介绍QLoRa的工作原理,同时会描述如何使用QLoRa在GPU上微调一个拥有200亿参数的GPT模型。
注意:我使用我自己的nVidia RTX 3060 12 Gb来运行这篇文章中的所有命令。您也可以使用Google Colab的免费实例来达到相同的效果。如果你想使用一个内存更小的GPU,就必须选择更小的LLM。
QLoRa:使用低秩适配器的量化LLM
2021年6月,Hu等人(2021)在一篇论文中提出这样一个概念,就是为LLM引入低秩适配器(Low-Rank Adapters)。
【编者:低秩low rank是指一个矩阵的秩(rank)比较低,也就是说,这个矩阵中的行向量或列向量之间存在一定的线性相关性,可以用更少的向量来表示整个矩阵。在某些应用中,低秩的矩阵可以帮助我们更好地理解数据的结构和特征,例如在降维、数据压缩、图像处理等领域中都有广泛的应用。】
LoRa为LLM的每一层添加了微小量的可训练参数,即适配器,并冻结所有原始参数。对于微调,我们只需要更新适配器权重,这大大减少了内存占用。
QLoRa通过引入4位量化、双重量化和利用nVidia统一内存进行分页。
下面简单描述,其工作原理:
- 4位NormalFloat量化:这是一种改进量化的方法。它确保每个量化箱中的值数量相等。这避免了计算问题和异常值的错误。
- 双重量化:QLoRa的作者将其定义为:“对量化常数进行量化以节省更多内存的过程。”
- 使用统一内存进行分页:它依赖于NVIDIA统一内存功能,并自动处理CPU和GPU之间的页到页传输。它确保GPU处理无误,特别是在GPU可能内存不足的情况下。
所有这些步骤都大大减少了微调所需的内存,同时几乎与标准微调的性能相当。
使用QLoRa微调GPT模型
QLoRa的硬件要求:
- GPU:以下演示适用于拥有12 Gb VRAM的GPU,对于参数少于200亿的模型,例如GPT-J。我用我的RTX 3060 12 Gb运行了它。如果你有一个更大的卡,拥有24 Gb的VRAM,你可以用一个200亿参数的模型,例如GPT-NeoX-20b。
- RAM:我建议最少6 Gb。大多数最新的计算机都有足够的RAM。
- 硬盘:GPT-J和GPT-NeoX-20b都是非常大的模型。我建议至少有80 Gb的可用空间。
如果你的机器不满足这些要求,Google Colab的免费实例将足够。
【编者:Google Colab是一种云端的Jupyter Notebook环境,由Google提供,用户可以在其中编写和运行Python代码。它提供了免费的GPU和TPU资源,使得用户可以在云端进行机器学习和深度学习的实验,而无需购买昂贵的硬件设备。同时,Google Colab还与Google Drive集成,用户可以将Notebook存储在自己的Google Drive中,并与其他人共享。】
QLoRa的软件要求:
我们需要CUDA。确保它已经安装在你的机器上。
【编者:CUDA (Compute Unified Device Architecture) 是由 NVIDIA 开发的一种并行计算平台和编程模型,它允许开发人员使用 C/C++、Fortran 等高级语言编写并行计算程序,利用 NVIDIA GPU 的并行计算能力加速计算。CUDA 可以在多种操作系统上运行,包括 Windows、Linux 和 macOS。它被广泛应用于科学计算、机器学习、深度学习、图像处理、计算机视觉等领域。】
与此同时还需要如下依赖项:
- bitsandbytes:一个包含我们需要量化LLM所需的所有内容的库。
- Hugging Face Transformers和Accelerate:这些是用于有效训练Hugging Face Hub模型的标准库。
- PEFT:一个提供各种方法实现只微调少量(额外)模型参数的库。我们需要它来进行LoRa。
- Datasets:并不是必选项。我们只会用它来获取一个用于微调的数据集。当然,你也可以提供你自己的数据集。