马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
在定制化业务场景中,假如使用专属数据集,经过微调的大模型能够在多种任务上与GPT-4媲美,并支持本地摆设,保护隐私,同时还能降低运算本钱。最新推出的Llama3,作为当前性能最强的开源基础大模型,非常实用于自然语言处置惩罚、呆板翻译、文本生成、问答体系、谈天呆板人等多种应用场景。
通过微调这一技术,基础大模型如Llama3即使原生不支持中文,也能增长对中文的支持。本教程将展示怎样使用LooPIN提供的GPU算力,从零开始为大模型添加新的训练素材,拓展其在原有能力基础上的新大概性。
准备工作
本教程将引导你怎样设置环境、准备数据、训练模型、摆设模型及生存模型。在8G显存的显卡上微调只需不到2分钟,且微调后的模型能被量化为4bit,在CPU上本地进行流畅的谈天推理。
我们将使用以下开源代码库:
Unsloth开源微调LLM工具
Unsloth: Github地址 - Unsloth GitHub
Unsloth是一款集成的模型微调工具。使用Unsloth微调Mistral、Gemma、Llama时,速率可提高2-5倍,内存使用可镌汰70%!
中文指令数据集
尽管LLM在中文指令调优方面还有不少进步空间,现有的数据集要么以英语为主,要么不适合现实中的中国用户交互模式。
为解决这一问题,由10家机构联合发布的研究提出了COIG-CQIA(全称Chinese Open Instruction Generalist - Quality Is All You Need),这是一个高质量的中文指令调优数据集。数据来源包括问答社区、维基百科、测验题目和现有的NLP数据集,经过了严酷的过滤和处置惩罚。
我们将使用此中的8000条来自百度贴吧的弱智吧数据进行微调:
ruozhiba-llama3-tt
开始模型训练
设置GPU实例
请访问以下页面,得到详细的交互式引导: LooPIN流动性池
1. LooPIN流动性池:
前往LooPIN的流动性池( LooPIN Network Pool),使用$LOOPIN代币购买GPU时间。以RTX 3080 GPU为例,根据自身需求和预算,在 GPU UserBenchmark 中选择合适的GPU型号。
2. 代币兑换GPU资源:
- 选择所需的$LOOPIN代币数目。
- 通过滑块选择GPU数目。
- 确认兑换量并完成生意业务。
3. 进入Jupyter Notebook:
生意业务乐成后,进入Rented Servers下的Server区域,通过你的长途服务器访问Jupyter Notebook。通常,实例启动需要2-4分钟。
4. 用nvidia-smi验证GPU:
在Jupyter Notebook中,打开新的终端窗口,运行nvidia-smi命令,检查GPU是否已激活。
复制
- +-----------------------------------------------------------------------------------------+
- | NVIDIA-SMI 550.54.15 Driver Version: 550.54.15 CUDA Version: 12.4 |
- |-----------------------------------------+------------------------+----------------------+
- | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
- | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
- | | | MIG M. |
- |=========================================+========================+======================|
- | 0 NVIDIA GeForce RTX 3080 Off | 00000000:01:00.0 Off | N/A |
- | 0% 39C P8 21W / 350W | 12MiB / 12288MiB | 0% Default |
- | | | N/A |
- +-----------------------------------------+------------------------+----------------------+
- +-----------------------------------------------------------------------------------------+
- | Processes: |
- | GPU GI CI PID Type Process name GPU Memory |
- | ID ID Usage |
- |=========================================================================================|
- +-----------------------------------------------------------------------------------------+
复制代码 安装Unsloth开源训练框架
1. 确认Unsloth安装版本
在Unsloth官方readme中找到对应的版本 ( Unsloth GitHub)
复制
- import torch; print('cuda:', torch.version.cuda, '\nPytorch:', torch.__version__)1.
复制代码 返回
复制
- cuda: 12.1
- Pytorch: 2.2.0+cu1211.2.
复制代码 复制
- pip install "unsloth[cu121-ampere-torch220] @ git+https://github.com/unslothai/unsloth.git"1.
复制代码 留意:对于新型RTX 30xx或更高级的GPU,请使用"ampere"路径。
2. Huggingface上下载Llama-7B基础模型
使用Unsloth快速加载预训练模型和分词器。
复制
- from unsloth import FastLanguageModel
- import torch
- max_seq_length = 2048 # 根据需求选择,我们内部支持RoPE缩放!
- dtype = None # 无需设置,自动检测。对于Tesla T4, V100使用Float16,对于Ampere+使用Bfloat16。
- model, tokenizer = FastLanguageModel.from_pretrained(
- model_name = "unsloth/llama-3-8b-bnb-4bit",
- max_seq_length = max_seq_length,
- dtype = dtype,
- load_in_4bit = True, # 使用4bit量化以减少内存使用。也可以设置为False。
- )
复制代码 等候模型下载完成
复制
- config.json: 100%
- 1.14k/1.14k [00:00<00:00, 72.1kB/s]
- ==((====))== Unsloth: Fast Llama patching release 2024.4
- \\ /| GPU: NVIDIA GeForce RTX 3080. Max memory: 11.756 GB. Platform = Linux.
- O^O/ \_/ \ Pytorch: 2.2.0+cu121. CUDA = 8.6. CUDA Toolkit = 12.1.
- \ / Bfloat16 = TRUE. Xformers = 0.0.24. FA = True.
- "-____-" Free Apache license: http://github.com/unslothai/unsloth
- model.safetensors: 100%
- 5.70G/5.70G [00:52<00:00, 88.6MB/s]
- generation_config.json: 100%
- 131/131 [00:00<00:00, 8.23kB/s]
- tokenizer_config.json: 100%
- 50.6k/50.6k [00:00<00:00, 2.55MB/s]
- tokenizer.json: 100%
- 9.09M/9.09M [00:00<00:00, 11.6MB/s]
- special_tokens_map.json: 100%
- 449/449 [00:00<00:00, 28.4kB/s]
复制代码 如需针对其他基础模型进行微调,可在此处找到并替换model_name ( Unsloth Huggingface)。
3. 准备Lora Adapter
我们在微调过程中只需更新1%-10%的模型参数。
复制
- 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,可以处理2倍大的批量大小!
- use_gradient_checkpointing = "unsloth", # True或"unsloth"用于非常长的上下文。
- random_state = 3407,
- use_rslora = False, # 我们支持排名稳定的LoRA。
- loftq_config = None, # 以及LoftQ。
- )
复制代码 等候输出
复制
- Unsloth 2024.4 patched 32 layers with 32 QKV layers, 32 O layers and 32 MLP layers.1.
复制代码 4. 准备微调数据集
我们将使用一个高质量的中文指令调优数据集子集进行微调。
复制
- from datasets import load_dataset
- dataset = load_dataset("kigner/ruozhiba-llama3-tt", split = "train")
- dataset = dataset.map(formatting_prompts_func, batched = True)
复制代码 等候数据下载完成
复制
- Downloading readme: 100%
- 28.0/28.0 [00:00<00:00, 4.94kB/s]
- Downloading data: 100%
- 616k/616k [00:00<00:00, 4.03MB/s]
- Generating train split: 100%
- 1496/1496 [00:00<00:00, 150511.62 examples/s]
- Map: 100%
- 1496/1496 [00:00<00:00, 152505.32 examples/s]
复制代码 5. 训练模型
接下来,我们将使用Huggingface的SFTTrainer作为训练框架,详细文档请见 SFT Trainer Documentation.
复制
- from trl import SFTTrainer
- from transformers import TrainingArguments
- 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()
复制代码 在训练过程中,max_steps表现训练步数,可以根据实际情况调整;learning_rate是学习率;output_dir是归并模型的输出目录。设置完成后即可开始训练。
复制
- max_steps is given, it will override any value given in num_train_epochs
- ==((====))== Unsloth - 2x faster free finetuning | Num GPUs = 1
- \\ /| Num examples = 1
- ,496 | Num Epochs = 1
- O^O/ \_/ \ Batch size per device = 2 | Gradient Accumulation steps = 4
- \ / Total batch size = 8 | Total steps = 60
- "-____-" Number of trainable parameters = 41,943,040
- [60/60 01:54, Epoch 0/1]
- Step Training Loss
- 1 2.674800
- 2 2.681600
- 3 2.603500
- 4 2.454600
- 5 2.463700
- 6 2.137400
- 7 2.170800
- 8 1.690200
- 9 1.543300
- 10 1.588800
- 11 1.434700
- 12 1.436800
- 13 1.546900
- 14 1.473900
- 15 1.328600
- 16 1.290700
- 17 1.428500
- 18 1.335700
- 19 1.493200
- 20 1.276300
- 21 1.352100
- 22 1.496900
- 23 1.501500
- 24 1.292600
- 25 1.317700
- 26 1.240400
- 27 1.334700
- 28 1.384600
- 29 1.261500
- 30 1.286000
- 31 1.312000
- 32 1.301000
- 33 1.331100
- 34 1.253900
- 35 1.374100
- 36 1.206200
- 37 1.218700
- 38 1.167600
- 39 1.391100
- 40 1.130700
- 41 1.298100
- 42 1.252400
- 43 1.330500
- 44 1.340500
- 45 1.365700
- 46 1.200900
- 47 1.163000
- 48 1.199100
- 49 1.260800
- 50 1.290200
- 51 1.319400
- 52 1.278800
- 53 1.326200
- 54 1.210400
- 55 1.369100
- 56 1.186300
- 57 1.328200
- 58 1.237400
- 59 1.245100
- 60 1.305800
复制代码 训练步调和训练损失两列数据显示了训练过程中的性能,损失的稳步下降表明模型正在有效学习我们提供的训练素材。整个训练过程不到2分钟即可完成。
6. 模型测试
现在,我们将用中文问题来测试经过微调的Llama3模型的中文处置惩罚能力。
复制
- # alpaca_prompt = Copied from above
- FastLanguageModel.for_inference(model) # 启用原生2倍速的推理
- inputs = tokenizer(
- [
- alpaca_prompt.format(
- "只能用中文回答问题", # 指令
- "陨石为什么每次都能精准砸到陨石坑", # 输入
- "", # 输出 - 留空用于生成
- )
- ], return_tensors = "pt").to("cuda")
- from transformers import TextStreamer
- text_streamer = TextStreamer(tokenizer)
- _ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 256)
复制代码 复兴如下:
复制
- Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
- ### Instruction:
- 只能用中文回答问题
- ### Input:
- 陨石为什么每次都能精准砸到陨石坑
- ### Response:
- 陨石坑是由陨石撞击地球形成的,陨石坑的位置和大小取决于陨石的大小、速度和撞击的角度等多种因素。所以,每次陨石撞击地球,都会形成新的陨石坑,而这些陨石坑的位置
- 和大小可能会有所不同。所以,陨石每次都能精准砸到陨石坑,是因为陨石坑的位置和大小是随着时间变化的,而陨石的撞击位置和大小是随机的。
复制代码 这表明模型已经具备了中文问答和逻辑推理的能力。
7. 模型生存与量化
Lora 模型
复制
- model.save_pretrained("lora_model") # 本地保存1.
复制代码 将训练好的模型先生存为Lora格式,在workspace中找到命名为lora_model的文件夹,里面生存了 README.md、adapter_config.json、adapter_model.safetensors,此中adapter_model.safetensors为Lora文件,可以导入其他Inference推理工具使用。
4bit量化
或者我们可以接纳4bit量化,如许在牺牲极小部分模型精度的同时,可以最大限度地提高推理速率和镌汰显存占用。
复制
- model.save_pretrained_merged("model", tokenizer, save_method = "merged_4bit_forced",)1.
复制代码 输出为:
复制
- Unsloth: Merging 4bit and LoRA weights to 4bit...
- This might take 5 minutes...
- /usr/local/lib/python3.10/dist-packages/peft/tuners/lora/bnb.py:325: UserWarning: Merge lora module to 4-bit linear may get different generations due to rounding errors.
- warnings.warn(
- Done.
- Unsloth: Saving tokenizer... Done.
- Unsloth: Saving model... This might take 10 minutes for Llama-7b... Done.
复制代码 此中model文件夹生存了量化后的模型权重。
GGUF/Llama.cpp
也可以生存成gguf格式用于CPU推理。
复制
- model.save_pretrained_gguf("model", tokenizer, quantization_method = "q4_k_m")1.
复制代码 等候一段时间后,在/workspace下可以找到文件名为model-unsloth.Q4_K_M.gguf的文件。
总结
本教程详细介绍了怎样使用Unsloth和LooPIN环境对Llama 3进行微调。通过这一过程,我们不仅学会了数据准备和模型训练的焦点步调,还掌握了怎样使用GPU资源进行高效的模型训练。我们会在后续教程中继续探讨LLM的工程实践。
转至:https://blog.51cto.com/u_16765961/10814836
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |