首页 > 其他分享 >Unsloth 微调 Llama 3

Unsloth 微调 Llama 3

时间:2024-07-16 14:26:28浏览次数:10  
标签:tokenizer 模型 微调 Unsloth Llama memory model save lora

本文参考:
https://colab.research.google.com/drive/135ced7oHytdxu3N2DNe1Z0kqjyYIkDXp
改编自:https://blog.csdn.net/qq_38628046/article/details/138906504


文章目录


一、项目说明

Llama-3-Chinese-Instruct 是基于Meta Llama-3的中文开源大模型,其在原版Llama-3的基础上使用了大规模中文数据进行增量预训练,并且使用精选指令数据进行精调,进一步提升了中文基础语义和指令理解能力,相比二代相关模型获得了显著性能提升。

GitHub:https://github.com/ymcui/Chinese-LLaMA-Alpaca-3


安装相关依赖

unsloth 根据不同改的 cuda 版本有不同的安装方式,详见:https://blog.csdn.net/lovechris00/article/details/140404957

pip install --no-deps "xformers<0.0.26" trl peft accelerate bitsandbytes

下载模型和数据

Unsloth 支持很多模型: https://huggingface.co/unsloth,包括 mistral,llama,gemma

这里我们使用 FlagAlpha/Llama3-Chinese-8B-Instruct 模型 和 kigner/ruozhiba-llama3 数据集

提前下载:

export HF_ENDPOINT=https://hf-mirror.com

huggingface-cli download FlagAlpha/Llama3-Chinese-8B-Instruct
uggingface-cli download --repo-type dataset kigner/ruozhiba-llama3

数据将保存到 ~/.cache/huggingface/hub


你也可以使用 modelscope下载,如:

from modelscope import snapshot_download

model_dir = snapshot_download('FlagAlpha/Llama3-Chinese-8B-Instruct',cache_dir="/root/models")

安装 modelscope

pip install modelscope 

二、训练

1、加载 model、tokenizer

from unsloth import FastLanguageModel
import torch


model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "/root/models/Llama3-Chinese-8B-Instruct", # 模型路径
    max_seq_length = 2048, # 可以设置为任何值内部做了自适应处理
    # dtype = torch.float16, # 数据类型使用float16
    dtype = None,  # 会自动推断类型
    load_in_4bit = True, # 使用4bit量化来减少内存使用

2、设置LoRA训练参数

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" 使用的VRAM减少30%,适用于2倍更大的批处理大小!
    use_gradient_checkpointing = "unsloth", # True或"unsloth"适用于非常长的上下文
    random_state = 3407,
    use_rslora = False,  # 支持排名稳定的LoRA
    loftq_config = None, # 和LoftQ

3、准备数据集

准备数据集其实就是指令集构建,LLM的微调一般指指令微调过程。所谓指令微调,就是使用指定的微调数据格式、形式。
训练目标是让模型具有理解并遵循用户指令的能力。因此在指令集构建时,应该针对目标任务,针对性的构建任务指令集。
这里使用 alpaca 格式的数据集,格式形式如下:

[
	{
	  "instruction": "用户指令(必填)",
	  "input": "用户输入(选填)",
	  "output": "模型回答(必填)",
	},
    "system": "系统提示词(选填)",
    "history": [
      ["第一轮指令(选填)", "第一轮回答(选填)"],
      ["第二轮指令(选填)", "第二轮回答(选填)"]
    ]
]


  • instruction:用户指令,要求AI执行的任务或问题
  • input:用户输入,是完成用户指令所必须的输入内容,就是执行指令所需的具体信息或上下文
  • output:模型回答,根据给定的指令和输入生成答案

这里根据企业私有文档数据,生成相关格式的训练数据集,大概格式如下:

[
  {
    "instruction": "内退条件是什么?",
    "input": "",
    "output": "内退条件包括与公司签订正式劳动合同并连续工作满20年及以上,以及距离法定退休年龄不足5年。特殊工种符合国家相关规定可提前退休的也可在退休前5年内提出内退申请。"
  },
]

数据格式处理

定义对数据处理的函数方法

alpaca_prompt = """下面是一项描述任务的说明,配有提供进一步背景信息的输入。写出一个适当完成请求的回应。

### Instruction:
{}

### Input:
{}

### Response:
{}"""

EOS_TOKEN = tokenizer.eos_token # Must add EOS_TOKEN
def formatting_prompts_func(examples):
    instructions = examples["instruction"]
    inputs       = examples["input"]
    outputs      = examples["output"]
    texts = []
    for instruction, input, output in zip(instructions, inputs, outputs):
        # Must add EOS_TOKEN, otherwise your generation will go on forever!
        text = alpaca_prompt.format(instruction, input, output) + EOS_TOKEN
        texts.append(text)
    return { "text" : texts, }


加载数据集并进行映射处理操作
from datasets import load_dataset
dataset = load_dataset("kigner/ruozhiba-llama3", split = "train")
dataset = dataset.map(formatting_prompts_func, batched = True,)

print(dataset[0])

经处理后的一条数据格式如下:

{'output': '输出内容',
 'input': '',
 'instruction': '指令内容',
 'text': '下面是一项描述任务的说明,配有提供进一步背景信息的输入。写出一个适当完成请求的回应。\n\n### Instruction:\n指令内容?\n\n### Input:\n\n\n### Response:\n输出内容。<|end_of_text|>'
}

4、训练超参数配置

from transformers import TrainingArguments
from trl import SFTTrainer

training_args  = TrainingArguments(
        output_dir = "models/lora/llama", # 输出目录
        per_device_train_batch_size = 2, # 每个设备的训练批量大小
        gradient_accumulation_steps = 4, # 梯度累积步数
        warmup_steps = 5,
        max_steps = 60, # 最大训练步数,测试时设置
        # num_train_epochs= 5, # 训练轮数   
        logging_steps = 10,  # 日志记录频率
        save_strategy = "steps", # 模型保存策略
        save_steps = 100, # 模型保存步数
        learning_rate = 2e-4, # 学习率
        fp16 = not torch.cuda.is_bf16_supported(), # 是否使用float16训练
        bf16 = torch.cuda.is_bf16_supported(), # 是否使用bfloat16训练
        optim = "adamw_8bit",  # 优化器
        weight_decay = 0.01,  # 正则化技术,通过在损失函数中添加一个正则化项来减小权重的大小
        lr_scheduler_type = "linear",  # 学习率衰减策略
        seed = 3407, # 随机种子
    )


SFTTrainer
trainer = SFTTrainer(
	model=model, # 模型
	tokenizer=tokenizer, # 分词器
	args=training_args, # 训练参数
	train_dataset=dataset, # 训练数据集
	dataset_text_field="text", # 数据集文本字段名称
	max_seq_length=2048, # 最大序列长度
	dataset_num_proc=2, # 数据集处理进程数
	packing=False, # 可以让短序列的训练速度提高5倍
)


显示当前内存状态
# 当前GPU信息
gpu_stats = torch.cuda.get_device_properties(0)
# 当前模型内存占用
start_gpu_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)
# GPU最大内存
max_memory = round(gpu_stats.total_memory / 1024 / 1024 / 1024, 3)

print(f"GPU = {gpu_stats.name}. Max memory = {max_memory} GB.")
print(f"{start_gpu_memory} GB of memory reserved.")

可以看出当前模型占用5.633G显存


5、执行训练

trainer_stats = trainer.train()

显示最终内存和时间统计数据

# 计算总的GPU使用内存(单位:GB)
used_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)
# 计算LoRA模型使用的GPU内存(单位:GB)
used_memory_for_lora = round(used_memory - start_gpu_memory, 3)
# 计算总的GPU内存使用百分比
used_percentage = round(used_memory / max_memory * 100, 3)
# 计算LoRA模型的GPU内存使用百分比
lora_percentage = round(used_memory_for_lora / max_memory * 100, 3)

print(f"{trainer_stats.metrics['train_runtime']} seconds used for training.")
print(f"{round(trainer_stats.metrics['train_runtime'] / 60, 2)} minutes used for training.")
print(f"Peak reserved memory = {used_memory} GB.")
print(f"Peak reserved memory for training = {used_memory_for_lora} GB.")
print(f"Peak reserved memory % of max memory = {used_percentage} %.")
print(f"Peak reserved memory for training % of max memory = {lora_percentage} %.")

可以看出模型训练时显存增加了0.732G


6、模型推理

FastLanguageModel.for_inference(model) # 启用原生推理速度快2倍
inputs = tokenizer(
[
    alpaca_prompt.format(
        "内退条件是什么?", # instruction
        "", # input
        "", # output
    )
], return_tensors = "pt").to("cuda")

outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
tokenizer.batch_decode(outputs)

可以看出模型回答跟训练数据集中的数据意思基本一致。


7、保存LoRA模型

注意:这仅保存 LoRA 适配器,而不是完整模型

lora_model = '/home/username/models/lora/llama0715/llama_lora'
model.save_pretrained(lora_model)
# adapter_config.json  adapter_model.safetensors  README.md

tokenizer.save_pretrained(lora_model)
# tokenizer_config.json  special_tokens_map.json  tokenizer.json

# 保存到huggingface
# model.push_to_hub("your_name/lora_model", token = "...")
# tokenizer.push_to_hub("your_name/lora_model", token = "...")

adapter_config.json 内容如下:

{
  "alpha_pattern": {},
  "auto_mapping": null,
  "base_model_name_or_path": "FlagAlpha/Llama3-Chinese-8B-Instruct",
  "bias": "none",
  "fan_in_fan_out": false,
  "inference_mode": true,
  "init_lora_weights": true,
  "layer_replication": null,
  "layers_pattern": null,
  "layers_to_transform": null,
  "loftq_config": {},
  "lora_alpha": 16,
  "lora_dropout": 0,
  "megatron_config": null,
  "megatron_core": "megatron.core",
  "modules_to_save": null,
  "peft_type": "LORA",
  "r": 16,
  "rank_pattern": {},
  "revision": "unsloth",
  "target_modules": [
    "gate_proj",
    "k_proj",
    "up_proj",
    "q_proj",
    "o_proj",
    "v_proj",
    "down_proj"
  ],
  "task_type": "CAUSAL_LM",
  "use_dora": false,
  "use_rslora": false
}

8、加载模型

注意:从新加载模型将额外占用显存,若GPU显存不足,需关闭、清除先前加载、训练模型的内存占用
加载刚保存的LoRA适配器用于推断,他将自动加载整个模型及LoRA适配器。adapter_config.json定义了完整模型的路径。

import torch
from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "models/llama_lora",
    max_seq_length = 2048,
    dtype = torch.float16,
    load_in_4bit = True,
)

FastLanguageModel.for_inference(model)

9、执行推理

outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
tokenizer.batch_decode(outputs)

10、保存完整模型

# 合并到16bit 保存到本地 OR huggingface
model.save_pretrained_merged("models/Llama3", tokenizer, save_method = "merged_16bit",)
# model.push_to_hub_merged("hf/model", tokenizer, save_method = "merged_16bit", token = "")

# 合并到4bit 保存到本地 OR huggingface
model.save_pretrained_merged("models/Llama3", tokenizer, save_method = "merged_4bit",)
# model.push_to_hub_merged("hf/model", tokenizer, save_method = "merged_4bit", token = "")

11、保存为GGUF格式

将模型保存为GGUF格式

# 保存到 16bit GGUF 体积大
model.save_pretrained_gguf("model", tokenizer, quantization_method = "f16")
model.push_to_hub_gguf("hf/model", tokenizer, quantization_method = "f16", token = "")

# 保存到 8bit Q8_0 体积适中
model.save_pretrained_gguf("model", tokenizer,)
model.push_to_hub_gguf("hf/model", tokenizer, token = "")

# 保存到 q4_k_m GGUF 体积小
model.save_pretrained_gguf("model", tokenizer, quantization_method = "q4_k_m")
model.push_to_hub_gguf("hf/model", tokenizer, quantization_method = "q4_k_m", token = "")

2024-07-15(一)

标签:tokenizer,模型,微调,Unsloth,Llama,memory,model,save,lora
From: https://blog.csdn.net/lovechris00/article/details/140447611

相关文章

  • ollama 模型国内加速下载,制作自定义Modelfile模型文件
    参考:https://www.zhihu.com/question/640579563/answer/3562899008https://github.com/ollama/ollama/blob/main/docs/modelfile.mdgguf格式介绍:https://www.datalearner.com/blog/10517057188355861、ollama模型国内加速下载ollama主要的模型文件格式是gguf,可以在mo......
  • MoneyPrinterPlus全面支持本地Ollama大模型
    MoneyPrinterPlus现在支持批量混剪,一键AI生成视频,一键批量发布短视频这些功能了。之前支持的大模型是常用的云厂商,比如OpenAI,Azure,Kimi,Qianfan,Baichuan,TongyiQwen,DeepSeek这些。支持云厂商的原因是现在大模型使用基本都很便宜,并且大厂的稳定性,性能都比本地搭建要好很多......
  • Llama2大语言模型在云GPU(AutoDL)上进行训练微调(自定义数据集)
    Llama2是Meta开源的语言大模型,它经过训练的数据集包含2万亿个token。相比Llama,Llama2的上下文长度已经从2048扩展到4096,这使其能够理解和生成更长的文本。Llama2包括了多个模型,分别是7B、13B和70B的模型。一、准备工作在autodl平台租用实例(直接搜索,有许多租用教程,建议租......
  • 使用llama.cpp量化模型
    文章目录概要整体实验流程技术细节小结概要大模型量化是指在保持模型性能尽可能不变的情况下,通过减少模型参数的位数来降低模型的计算和存储成本。本次实验环境为魔搭社区提供的免费GPU环境(24G),使用Llama.cpp进行4bit量化可以大幅减少大语言模型的内存占用,并提高推理......
  • LoRA微调中文版Llama3模型
    文章目录概要整体微调流程疑难问题有哪些小结概要LoRA(Low-RankAdaptation)是一种微调大模型的方法,通过引入低秩矩阵来减少参数量和计算复杂度,主要应用于大型预训练语言模型的微调过程。本文章讲解的是使用LoRA技术微调Llama3中文版模型。实验环境为kaggle、GPU环境......
  • llama.cpp 和 SYCL oneMKL 后端
    在cpu下运行llama.cpp用https://github.com/flame/blis计算库是目前最好的选择。SYCLSYCLisahigh-levelparallelprogrammingmodeldesignedtoimprovedevelopersproductivitywritingcodeacrossvarioushardwareacceleratorssuchasCPUs,GPUs,andFPGAs.......
  • 【 2024!深入了解 大语言模型(LLM)微调方法(总结)】
    文末有福利!引言众所周知,大语言模型(LLM)正在飞速发展,各行业都有了自己的大模型。其中,大模型微调技术在此过程中起到了非常关键的作用,它提升了模型的生成效率和适应性,使其能够在多样化的应用场景中发挥更大的价值。那么,今天这篇文章就带大家深入了解大模型微调。其中主要......
  • 简单几步,免费微调大语言模型
    我总是受大脑运行方式的启发…大脑收集信息,然后对信息进行加权再输出,问题就在于,怎么调整这些权重使这些信息发挥作用。——杰弗里·辛顿今天和大家分享下,怎么用开源工具免费微调大模型。要用到的工具有:autotrain:huggingface开放的零代码大模型微调平台,无需编程,只需要通......
  • T5架构和主流llama3架构有什么区别和优缺点、transformer中encoder 和decoder的不同、
    T5架构和主流llama3架构有什么区别和优缺点T5和LLaMA是两种在自然语言处理(NLP)领域广泛应用的大型语言模型,它们在架构和应用上有显著的区别和各自的优缺点。T5架构架构特点:Encoder-Decoder结构:T5(Text-to-TextTransferTransformer)采用了经典的Encoder-DecoderTransform......
  • 本地 AI RAG 系列之 使用 OpenLlama、Postgres、Node.js 和 Next.js 进行 100% 免费矢
    简介所以你想尝试向量搜索,但你不想付钱给OpenAI,或者使用Huggingface,也不想付钱给向量数据库公司。我来帮你。让我们在自己的机器上免费开始向量搜索吧。推荐文章《知识图谱大模型系列之01利用KeyBERT、HDBSCAN和Zephyr-7B-Beta构建知识图谱,LLM增强的自然语言处......