使用 Hugging Face 和 oneAPI 微调 70 亿参数的 Falcon 模型
使用 Intel® AMX (Intel® Advanced Matrix Extensions) 在 Intel® Xeon® 处理器上优化大型语言模型。
开源大型语言模型 (LLM) 有助于将人工智能技术普及到世界各地。不大可能的是,下一项人工智能研究突破将来自没有大规模分布式加速器集群访问权限的人。然而,在人工智能应用开发领域,情况则大不相同,因为在选择产品开发基础设施时有更多的灵活性。这使得 CPU 的可用性和可扩展性与 Falcon LLM 背后真正的开源许可证相结合,成为人工智能的一个主要推动因素。
本文探讨了使用 Hugging Face* 监督微调训练器 (SFTTrainer)、支持 Intel® Advanced Matrix Extensions (Intel® AMX) 的 Intel® Extension for PyTorch* (IPEX) 和 Bfloat16 自动混合精度 (AMP) 在 Intel® Xeon® 处理器上微调最先进的 Falcon 70 亿参数语言模型 (Falcon-7B) 的激动人心的挑战。
环境设置
按以下方式设置环境
- 安装 miniconda。
- 创建 conda 环境:
conda create -n falconft python==3.8.10
- 安装依赖项:
pip install -r requirements.txt
。requirements.txt 文件列出了以下依赖项torch==2.0.1 transformers==4.30.1 bitsandbytes==0.39.0 peft==0.3.0 accelerate==0.20.3 datasets==2.12.0 trl==0.4.4 einops==0.6.1 scipy==1.10.1 intel_extension_for_pytorch==2.0.100
- 激活 conda 环境:
conda activate falconft
因果语言模型微调
因果语言模型涉及根据前面的上下文预测序列中的下一个词,从而实现文本生成等任务。微调像 Falcon-7B 这样的模型以适应特定任务,包括通过提供特定任务的标记数据来调整预训练模型。然后在此数据上进一步训练模型,调整其参数以优化新任务的性能。通过这个过程,Falcon-7B 逐渐学习特定因果任务的模式和细节,使其能够为特定用例生成连贯且上下文相关的文本。
我们将使用 Open Assistant 数据集的一个子集,该子集仅包含对话树中评分最高的路径(共 9,846 个样本)。请参阅这篇 文章,了解更多关于微调和迁移学习的信息。
虽然 GPU 一直是深度学习任务的首选,但在 CPU 上微调 Falcon-7B 具有一些优势:
- 可用性:CPU 无处不在且易于访问,这使其成为可能无法访问昂贵 GPU 集群的研究人员和从业者的有吸引力的选择。
- 成本:对于大规模部署,CPU 通常比 GPU 更具成本效益。
- 兼容性:CPU 与各种硬件和基础设施兼容,确保与现有系统的顺畅集成。
通过将 SFTTrainer 与支持 Intel AMX 和 Bfloat16 AMP 的 IPEX 相结合,Falcon-7B 的微调变得更加高效和有效。SFTTrainer 通过为复杂任务提供更高级别的抽象来简化微调过程。IPEX 和 AMP 利用 Intel Xeon 处理器中的最新硬件功能。此扩展在将新优化和设备上游合并到开源 PyTorch* 之前提供支持。它还支持 AMP 训练和推理,将参数和操作转换为 Bfloat16,以进一步加速 Intel AMX,同时在必要时保留完整的 32 位精度。
Falcon-7B 是由阿布扎比技术创新研究所 (TII) 开发的一个 70 亿参数的仅解码器模型。它在 LLaMA、StableLM、RedPajama 和 MPT 等模型上表现出色,利用 FlashAttention 方法实现更快的推理,从而在不同任务中显著提高速度(图 1)。
运行以下脚本将从 Hugging Face 加载“tiiuae/falcon-7b”模型,进行标记化,设置训练参数,并使用 SFTTrainer
进行微调。微调模型所需的时间将取决于我们设置的计算和超参数。在运行脚本之前,必须设置以下环境变量以确保我们选择 Intel AMX ISA:export ONEDNN_MAX_CPU_ISA="AVX512_CORE_AMX"
# falcon-tune.py
import time
import argparse
from datasets import load_dataset
from trl import SFTTrainer
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
TrainingArguments)
def main(FLAGS):
dataset = load_dataset("timdettmers/openassistant-guanaco", split="train")
model_name = "tiiuae/falcon-7b"
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True)
print('setting training arguments')
training_arguments = TrainingArguments(
output_dir="./results",
bf16=FLAGS.bf16, #change for CPU
use_ipex=FLAGS.use_ipex, #change for CPU IPEX
no_cuda=True,
fp16_full_eval=False,
)
print('Creating SFTTrainer')
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
dataset_text_field="text",
max_seq_length=FLAGS.max_seq_length,
tokenizer=tokenizer,
args=training_arguments,
packing=True,
)
print('Starting Training')
start = time.time()
trainer.train()
total = time.time() - start
print(f'Time to tune {total}')
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-bf16',
'--bf16',
type=bool,
default=True,
help="activate mix precision training with bf16")
parser.add_argument('-ipex',
'--use_ipex',
type=bool,
default=True,
help="used to control the maximum length of the generated text in text generation tasks")
parser.add_argument('-msq',
'--max_seq_length',
type=int,
default=512,
help="specifies the number of highest probability tokens to consider at each step")
FLAGS = parser.parse_args()
main(FLAGS)
我们可以使用以下命令执行我们的脚本
python falcon-tune.py --bf16 True --use_ipex True --max_seq_length 512
在训练期间,我们将看到一个进度条,指示完成过程的估计时间(图 2)。
训练完成后,我们应该会找到一个包含各种检查点文件夹的“results”目录。数字最大的检查点文件夹(checkpoint-3000)将包含我们所有的配置、PyTorch 模型文件等(图 3)。我们将需要此文件夹中的文件来部署我们的模型并处理推理请求。
使用我们微调后的 Falcon-7B 模型进行推理
现在我们的模型已经微调完毕,我们可以使用以下脚本创建一个 Hugging Face pipeline 来测试它,并提供一个示例提示:
# falcon-tuned-inference.py
from transformers import AutoTokenizer, AutoModelForCausalLM, AutoConfig
import transformers
import torch
import argparse
import time
def main(FLAGS):
model = AutoModelForCausalLM.from_pretrained(FLAGS.checkpoints, trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained(FLAGS.checkpoints, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
generator = transformers.pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
torch_dtype=torch.bfloat16,
trust_remote_code=True,
device_map="auto",
)
user_input = "start"
while user_input != "stop":
user_input = input(f"Provide Input to tuned falcon: ")
start = time.time()
if user_input != "stop":
sequences = generator(
f""" {user_input}""",
max_length=FLAGS.max_length,
do_sample=False,
top_k=FLAGS.top_k,
num_return_sequences=1,
eos_token_id=tokenizer.eos_token_id,)
inference_time = time.time() - start
for seq in sequences:
print(f"Result: {seq['generated_text']}")
print(f'Total Inference Time: {inference_time} seconds')
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-c',
'--checkpoints',
type=str,
default=None,
help="path to model checkpoint files")
parser.add_argument('-ml',
'--max_length',
type=int,
default="200",
help="used to control the maximum length of the generated text in text generation tasks")
parser.add_argument('-tk',
'--top_k',
type=int,
default="10",
help="specifies the number of highest probability tokens to consider at each step")
FLAGS = parser.parse_args()
main(FLAGS)
要执行此脚本,请运行以下命令:
python falcon-tuned-inference.py --checkpoints <PATH-TO-CHECKPOINT> --max_length 200 --top_k 10
在我们的脚本提示下,我们问 Falcon:“你能告诉我三个关于太空的有趣事实吗?”它的回答显示在图 4 中。除了关于土星的部分正确的事实外,模型似乎提供了事实准确的回答,并以易于理解的格式组织。有令人鼓舞的迹象表明,我们的微调已经比未微调的模型有所改进。
我们的模型与原始的、未微调的 Falcon-7B 版本相比如何?我们使用与上述相同的提示测试了未微调的 Falcon-7B 模型(图 5)。我们可以看到未微调的模型在理解我们的请求和形成连贯的响应方面存在困难。这表明微调已提高了模型的理解能力和整体响应质量。量化改进程度需要运行因果语言模型基准测试,这超出了本文的范围。
总结和讨论
现在我们已经拥有了曾经发布过的最强大的“真正开源”LLM 之一的微调版本!Hugging Face 的 API、Intel 的加速 AI 工具、CPU 硬件的可访问性以及 Falcon 的开源许可相结合,使得这一实现成为各种企业和 AI 应用开发者的可行选择。
我的目标是实现这一工作负载,而不是分析性能,因此我省略了硬件性能和因果模型指标。不过,我鼓励开发人员探索使用超参数优化、Intel® Extension for Transformers、Intel® Neural Compressor、参数高效微调 (PEFT)、LLM 低秩自适应 (LoRA) 以及在 Habana Gaudi*-1 和 Gaudi-2 加速器上微调 Falcon 来优化此工作流,以提高训练性能。