导读

1.了解微调Llama 3使用的开源组件

2.了解微调的数据准备及逻辑

微调环境

数据集: Openhermes-2.5(训练700k,测试300k)

GPU: 4个RTX 4090, 24GB

整个微调过程会用到以下组件:

在这里插入图片描述

Deepspeed

DeepSpeed 是一个深度学习优化库,使分布式训练和推断变得简单、高效和有效。

https://github.com/microsoft/DeepSpeed

我将使用四个 RTX 4090 GPU 来训练这个模型,所以我们需要采取一些步骤来跨多个 GPU 训练模型。

与在单个 GPU 上训练相比,在多个 GPU 上训练是一个复杂的任务。

为什么呢?当我们在单个 GPU 上训练时,优化器状态、参数和梯度都驻留在单个系统中,这有助于在一个 GPU 上迭代模型

现在,如果我们添加另一个 GPU,就会有两个系统来训练模型,每个系统都有自己的状态(优化器状态、参数和梯度)。

经过一个 epoch 或几个步骤后,我们希望获得一个单一的结果。

现在想象一下两个系统并行训练两个数据批次;它们需要相互通信关于它们的状态,并以最小的数据损失收敛结果。

有多种方法可以利用多个 GPU:我们可以在所有 GPU 上复制参数、梯度和优化器状态,或者只分片优化器状态,或者优化器状态和梯度。DeepSpeed 有助于在 GPU 上分发负载而不会出现任何问题。而 Huggingface 的 accelerate 包让我们像吃蛋糕一样做到这一点。

我将使用阶段 3,它将分片所有参数、梯度和优化器状态,这将让我们在更少的内存需求下进行训练。

在这里插入图片描述

QLoRA

70B/8B模型非常庞大,这意味着当您对其进行微调时,您将无法完全使用任何普通人预算内的GPU进行微调,因此我们尝试使用非常低的资源对其进行微调,并开发了LoRA,它帮助我们仅使用低秩训练参数并将它们与原始权重合并,然后出现了QLoRA,它通过将预训练的LLM量化为4位精度,进一步减少了内存消耗,量化本身就是一个专题,所以不再深入讨论。

开始微调 LLamA 3

我们将在 teknium 提供的 openhermes 数据集上对 llama3 instruct 模型进行微调 meta-llama/Meta-Llama-3–8B-Instruct · Hugging Face。

数据准备

Meta 有他们自己的chat格式,所以我试图遵循他们提供的格式,并阅读他们在 llama3 git中的编码算法,

加载数据集

from datasets import load_dataset              



dataset = load_dataset("teknium/OpenHermes-2.5")

我从 llama3 git 中获得编码实用程序的灵感

def _return_header(message)-> str:              
    role = message["from"]              
    header = ""              
    if role == "system":              
        header = "system"              
    elif role == "gpt":              
        header = "assistant"              
    elif role == "human":              
        header = "user"              
    return header              



def encode_header(message):              
    text = ''              
    text = text + "<|start_header_id|>"              
    header = _return_header(message)              
    text = text + header              
    text = text + "<|end_header_id|>"              
    text = text + "\n\n"              
    return text              



def encode_message(message)->str:              
    text = encode_header(message)              
    text = text + message["value"].strip()              
    text = text + "<|eot_id|>"              
    return text              



def encode_dialog_prompt(dialog):              
    text = ''              
    text = text + "<|begin_of_text|>"              
    for message in dialog:              
        text = text + encode_message(message)              
    return text
ds = dataset.map(lambda x: {"content":encode_dialog_prompt(x['conversations'])}, num_proc=10)

删除冗余列并将其拆分为训练集和验证集

ds = ds.remove_columns(['custom_instruction', 'topic', 'model_name', 'model', 'skip_prompt_formatting', 'category', 'conversations', 'views', 'language', 'id', 'title', 'idx', 'hash', 'avatarUrl', 'system_prompt', 'source'])              
train_test_split = ds["train"].train_test_split(test_size=0.3)

然后将其推送到 hub

train_test_split.push_to_hub("sumandas/openhermes-2.5-llama3")

结果数据集,sumandas/openhermes-2.5-llama3 · Datasets at Hugging Face,示例文本

<|begin_of_text|><|start_header_id|>system<|end_header_id|> You are an AI assistant. Provide a detailed answer so user don't need to search outside to understand the answer.<|eot_id|><|start_header_id|>user<|end_header_id|> Instructions: Given a sentence, generate what should be the most likely next statement. The next statement should be reasonable and logically correct. Input: The screen is full of white bubbles and words, while a pair of hands plays the piano. The bubbles and words disappear and it Output:<|eot_id|><|start_header_id|>assistant<|end_header_id|> Output: becomes apparent that the hands are creating a visual representation of the music being played, captivating the audience with this unique sensory experience.<|eot_id|>

所有资源都已可用,我们只是为了我的设置和数据需求进行微调,

先决条件

1.安装cuda开发工具包 conda install cuda 或者按照 developer.nvidia.com/cuda-downloads?target_os=Linux 进行安装

2.安装deepspeed

3.安装flash-attention pip install flash-attn - no-build-isolation

4.安装这些库,我使用 uv 进行更快的依赖解析,

git+https://github.com/huggingface/transformers              
git+https://github.com/huggingface/accelerate              
git+https://github.com/huggingface/peft              
git+https://github.com/huggingface/trl              
huggingface-hub              
bitsandbytes              
evaluate              
datasets              
einops              
wandb              
tiktoken              
xformers              
sentencepiece              
deepspeed              
torch==2.2.2

训练代码

可以根据自己的方便在多种模式下进行训练,在这个repo中找到了这个 pacman100/LLM-Workshop: LLM Workshop by Sourab Mangrulkar (github.com)。

training.py 文件是我们将使用加速器和适当的配置启动的文件,只是在这里放置了training.py的要点https://gist.github.com/sumandas0/0483db8514ea43e45cc5e5f5525914ab

这个训练代码使用了来自huggingface的SFTTrainer,更多细节请参阅 Supervised Fine-tuning Trainer (huggingface.co)

您可以使用这个代码做很多事情,您可以使用loftq、unsloth、FFT、normal lora进行训练,但我只会使用QloRa与Deepspeed ZerO stage 3。

首先让我们定义使用deepspeed的加速器配置

注意,如果您增加了GPU的数量,请更新num_processes

现在让我们运行加速器命令来开始训练,

accelerate launch --config_file "deepspeed_config.yaml"  train.py \              
--seed 100 \              
--model_name_or_path "meta-llama/Meta-Llama-3-8B-Instruct" \              
--dataset_name "sumandas/openhermes-2.5-llama3" \              
--chat_template_format "none" \              
--add_special_tokens False \              
--append_concat_token False \              
--splits "train,test" \              
--max_seq_len 2048 \              
--num_train_epochs 1 \              
--logging_steps 5 \              
--log_level "info" \              
--logging_strategy "steps" \              
--evaluation_strategy "epoch" \              
--save_strategy "steps" \              
--push_to_hub \              
--hub_private_repo True \              
--report_to "wandb" \              
--hub_strategy "every_save" \              
--bf16 True \              
--packing True \              
--learning_rate 1e-4 \              
--lr_scheduler_type "cosine" \              
--weight_decay 1e-4 \              
--warmup_ratio 0.0 \              
--max_grad_norm 1.0 \              
--output_dir "llama3-openhermes-2.5" \              
--per_device_train_batch_size 4\              
--per_device_eval_batch_size 4\              
--gradient_accumulation_steps 2 \              
--gradient_checkpointing True \              
--use_reentrant True \              
--dataset_text_field "content" \              
--use_flash_attn True \              
--use_peft_lora True \              
--lora_r 8 \              
--lora_alpha 16 \              
--lora_dropout 0.1 \              
--lora_target_modules "all-linear" \              
--use_4bit_quantization True \              
--use_nested_quant True \              
--bnb_4bit_compute_dtype "bfloat16" \              
--bnb_4bit_quant_storage_dtype "bfloat16"

注意,

1.首先设置环境变量HF_HUB_ENABLE_HF_TRANSFER=1

2.output_dir也将是在huggingface中创建的存储所有检查点的repo,检查点默认每500步创建一次

3.我将chat模板格式设置为none,因为我已经按照我的方式格式化了这些内容,如果您有其他格式,比如chatml、zephyr

4.lora_target_modules 设置为all-linear,这是QLoRa特有的,他们发表了一篇论文,表明对所有线性层进行微调可以给我们带来与全面微调可比较的结果

5.要设置LoRa的超参数,请参阅这篇很棒的博客 LoRA Fine-tuning & Hyperparameters Explained (in Plain English) | Entry Point AI

6.果要报告给wandb,请设置WANDB_API_KEY=,否则删除report_to=‘wandb’

这就是全部,您的训练应该在全力进行中,查看GPU利用率。

观察过程

只进行了1个epoch的微调,大约花了15个小时。损失曲线如下:

在这里插入图片描述
WandB 摘要

{              
  "train/learning_rate": 0.00004551803455482833,              
  "eval/steps_per_second": 0.893,              
  "_wandb.runtime": 51487,              
  "_runtime": 51480.36651659012,              
  "_timestamp": 1713698971.6200776,              
  "train/epoch": 1.0571428571428572,              
  "train/grad_norm": 0.14189070214353952,              
  "train/global_step": 8325,              
  "eval/samples_per_second": 7.141,              
  "_step": 1665,              
  "eval/loss": 0.963840126991272,              
  "train/loss": 0.9674,              
  "eval/runtime": 7532.9797              
}

最后一步,在微调之后,您将获得一个小的适配器模型,而不是完整的模型,你可以马上开始使用模型,我们需要将适配器添加到原始的元llama3权重中,

加载PEFT适配器模型

from peft import PeftModel              
from transformers import AutoModelForCausalLM              



base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct",torch_dtype=torch.bfloat16, device_map="auto")              
adapter_model = PeftModel.from_pretrained(base_model, "sumandas/llama3-openhermes-2.5")              
adapter_model.merge_and_unload()

现在将适配器模型保存到hf中

adapter_model.push_to_hub("sumandas/llama3-openhermes-2.5")

推理

import torch              
import transformers              
from transformers import pipeline              



pipe = pipeline("text-generation", model="sumandas/llama3-openhermes-2.5",model_kwargs={"torch_dtype": torch.bfloat16},              
    device="cuda")              



generate_kwargs = {              
    "do_sample": True,              
    "temperature": 0.7,              
    "max_new_tokens": 35,              
}
pipe("<|begin_of_text|><|start_header_id|>user<|end_header_id|> Describe the food of Thailand in Chinese<|eot_id|><|start_header_id|>assistant<|end_header_id|>",max_length=2048)

模型回复如下:

泰国菜是浓郁风味和芳香成分的融合,创造出甜、酸、咸、苦和辣味的和谐平衡。泰国的食物在不同地区之间有所不同,但一些常见的成分包括大米、面条、蔬菜、草药和香料。大米是泰国菜的主食,几乎每顿饭都会配上,无论是炒、煮,还是用来做粥或炒饭。由大米或小麦制成的面条也非常受欢迎,可以在许多泰国菜中找到,配以各种汤、酱和配料。泰国菜以其使用新鲜草药和香料而闻名,如柠檬草、高良姜、香菜、罗勒、青柠檬叶、姜和大蒜,这些为菜肴赋予了独特的风味。泰国辣椒也被广泛使用,为食物增添不同程度的辣味。一些受欢迎的泰国菜包括冬阴汤(酸辣汤,加入柠檬草、青柠檬叶和辣椒)、泰式炒河粉(炒米粉配蔬菜、花生和一种酸甜的酱汁)和青咖喱(用青辣椒、椰奶和泰式罗勒制成的辣味咖喱)。许多泰国菜也配有各种酱料和调味品,包括鱼露、酱油、辣椒酱和罗望子酱。新鲜水果如芒果、木瓜和菠萝也常作为一顿饭的甜点享用。总的来说,泰国菜是一种充满活力和风味的美食,将传统的成分和烹饪技术与平衡的风味相结合,让人垂涎欲滴。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

Logo

更多推荐