使用LoRA对Llama3微调

news2024/9/28 17:31:21

使用LoRA(Low-Rank Adaptation of Large Language Models)技术对Llama-3语言模型进行微调。

理论知识参考百度安全验证

微调的前提条件

现在huggingface上下载llama2或llama3的huggingface版本。

我下载的是llama-2-13b-chat。 

大语言模型微调方法

全参数微调(Full parameter fine-tuning)是一种对预训练模型所有层的所有参数进行微调的方法。一般来说,它可以实现最佳性能,但也是最耗资源和耗时的:它需要最多的 GPU 资源,并且耗时最长。

PEFT(Parameter-Efficient Fine-Tuning,允许以最少的资源和成本微调模型。有两种重要的 PEFT 方法:LoRA(Low Rank Adaptation)和 QLoRA(Quantized LoRA),其中预训练模型分别作为量化的 8 位和 4 位权重加载到 GPU。您很可能可以使用 LoRA 或 QLoRA 微调在具有 24GB 内存的单个消费级 GPU 上微调 Llama 2-13B 模型,并且使用 QLoRA 所需的 GPU 内存和微调时间甚至比 LoRA 更少。

通常,应该先尝试 LoRA,如果资源极其有限,则应先尝试 QLoRA,然后在完成微调后评估性能。只有当性能不理想时才考虑进行全面微调。

使用LoRA对Llama2微调

1. 导入库

from transformers import LlamaTokenizer, LlamaForCausalLM, Trainer, TrainingArguments
from peft import get_peft_model, LoraConfig, TaskType
from datasets import load_from_disk, Dataset

解释:导入所需的库:

  • transformers 用于处理语言模型和分词器。
  • peft 用于实现LoRA微调。
  • datasets 用于处理数据集。

2. 构建数据集

 此处的数据集你可以根据你领域的数据构建。

data = {
    "instruction": [
        "What is the capital of France?",
        "What is 2 + 2?",
        "How do you greet someone in English?"
    ],
    "response": [
        "The capital of France is Paris.",
        "2 + 2 equals 4.",
        "You greet someone by saying 'Hello' in English."
    ]
}

dataset = Dataset.from_dict(data)
dataset.save_to_disk("simple_dataset")

解释:创建了一个简单的数据集,包括instructionresponse字段。然后将其转换为Dataset对象,并保存到磁盘中。

3. 加载模型和分词器

model_name = r"C:\apps\ml_model\llama-2-13b-chat-hf"
print("starting to load tokenizer.")
tokenizer = LlamaTokenizer.from_pretrained(model_name)
print("starting to load model.")
model = LlamaForCausalLM.from_pretrained(model_name)
print("Finished to load model")

解释:指定模型路径,加载Llama-2的分词器和模型,打印加载过程的日志信息。

4. 定义LoRA配置

lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    r=16,
    lora_alpha=32,
    lora_dropout=0.1,
)

解释:配置LoRA相关参数,如低秩分解的维度r,缩放因子lora_alpha,以及Dropout比例lora_dropout

5. 包装模型

print("Starting to get peft model")
model = get_peft_model(model, lora_config)
tokenizer.pad_token = tokenizer.eos_token

解释:将预训练模型通过LoRA技术进行包装,并设置分词器的填充标记。

6. 加载数据集

dataset = load_from_disk("simple_dataset")

解释:从磁盘加载之前保存的数据集。

7. 数据集分词

def tokenize_function(examples):
    combined_texts = [
        instruction + " " + response
        for instruction, response in zip(examples["instruction"], examples["response"])
    ]
    tokenized_inputs = tokenizer(
        combined_texts,
        truncation=True,
        padding="max_length",
        max_length=128
    )
    tokenized_inputs["labels"] = tokenized_inputs["input_ids"].copy()
    return tokenized_inputs

tokenized_dataset = dataset.map(tokenize_function, batched=True)

解释:定义了一个函数,将指令和响应文本连接起来,并对其进行分词。结果包括输入的input_ids,并将其复制为标签。

8. 定义训练参数

training_args = TrainingArguments(
    output_dir="./llama2-lora-finetuned",
    per_device_train_batch_size=1,
    num_train_epochs=3,
    logging_dir="./logs",
    logging_steps=10,
    save_steps=500,
    save_total_limit=2,
)

解释:配置训练参数,如输出目录、每设备的训练批量大小、训练轮数、日志记录频率、保存频率等。

9. 初始化Trainer

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
)

解释:使用Hugging Face的Trainer类,传入微调后的模型、训练参数和数据集,准备开始训练。

10. 模型训练和保存

print("Starting to training")
trainer.train()
print("Finished to training")
trainer.save_model("llama2-lora-finetuned")
print("model saved")

解释:开始微调模型,训练完成后将微调后的模型保存到指定目录中,并打印相关日志信息。

执行结果如下

Saving the dataset (1/1 shards): 100%|██████████| 3/3 [00:00<00:00, 428.59 examples/s]
starting to load tokenizer.
starting to load model.
Loading checkpoint shards: 100%|██████████| 3/3 [03:10<00:00, 63.57s/it]
Finished to load model
Starting to get peft model
get peft model
Map: 100%|██████████| 3/3 [00:00<00:00, 37.04 examples/s]
C:\Users\Harry\anaconda3\envs\ai_service\lib\site-packages\accelerate\accelerator.py:451: FutureWarning: Passing the following arguments to `Accelerator` is deprecated and will be removed in version 1.0 of Accelerate: dict_keys(['dispatch_batches']). Please pass an `accelerate.DataLoaderConfiguration` instead: 
dataloader_config = DataLoaderConfiguration(dispatch_batches=None)
  warnings.warn(
C:\Users\Harry\anaconda3\envs\ai_service\lib\site-packages\pydantic\_internal\_fields.py:151: UserWarning: Field "model_server_url" has conflict with protected namespace "model_".

You may be able to resolve this warning by setting `model_config['protected_namespaces'] = ()`.
  warnings.warn(
C:\Users\Harry\anaconda3\envs\ai_service\lib\site-packages\pydantic\_internal\_config.py:322: UserWarning: Valid config keys have changed in V2:
* 'schema_extra' has been renamed to 'json_schema_extra'
  warnings.warn(message, UserWarning)
Starting to training
100%|██████████| 9/9 [47:12<00:00, 314.57s/it]{'train_runtime': 2832.8354, 'train_samples_per_second': 0.003, 'train_steps_per_second': 0.003, 'train_loss': 5.6725747850206165, 'epoch': 3.0}
100%|██████████| 9/9 [47:12<00:00, 314.72s/it]
Finished to training
model saved 

Process finished with exit code 0

在llama2-lora-finetuned目录下你会发现lora模型

全部代码

from transformers import LlamaTokenizer, LlamaForCausalLM, Trainer, TrainingArguments
from peft import get_peft_model, LoraConfig, TaskType
from datasets import load_from_disk

from datasets import Dataset

data = {
    "instruction": [
        "What is the capital of France?",
        "What is 2 + 2?",
        "How do you greet someone in English?"
    ],
    "response": [
        "The capital of France is Paris.",
        "2 + 2 equals 4.",
        "You greet someone by saying 'Hello' in English."
    ]
}

dataset = Dataset.from_dict(data)
dataset.save_to_disk("simple_dataset")



# Load the model and tokenizer
model_name = r"C:\apps\ml_model\llama-2-13b-chat-hf"
print("starting to load tokenizer.")
tokenizer = LlamaTokenizer.from_pretrained(model_name)
print("starting to load model.")
# Load model with 8-bit precision
model = LlamaForCausalLM.from_pretrained(model_name)
print("Finished to load model")
# Define LoRA configuration
lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,  # This is for language modeling
    r=16,  # LoRA attention dimension
    lora_alpha=32,  # LoRA scaling factor
    lora_dropout=0.1,  # Dropout for LoRA layers
)

print("Starting to get peft model")
# Wrap the model with LoRA
model = get_peft_model(model, lora_config)

tokenizer.pad_token = tokenizer.eos_token

# if tokenizer.pad_token is None:
#     tokenizer.add_special_tokens({'pad_token':'PAD'})
#     model.resize_token_embeddings(len(tokenizer))


print("get peft model")
# Load the dataset
dataset = load_from_disk("simple_dataset")

# Tokenize the dataset
def tokenize_function(examples):
    combined_texts = [
        instruction + " " + response
        for instruction, response in zip(examples["instruction"], examples["response"])
    ]
    tokenized_inputs = tokenizer(
        combined_texts,
        truncation=True,
        padding="max_length",  # Ensure consistent padding
        max_length=128  # Adjust max_length as needed
    )
    tokenized_inputs["labels"] = tokenized_inputs["input_ids"].copy()
    return tokenized_inputs

tokenized_dataset = dataset.map(tokenize_function, batched=True)

# Define training arguments
training_args = TrainingArguments(
    output_dir="./llama2-lora-finetuned",
    per_device_train_batch_size=1,
    num_train_epochs=3,
    logging_dir="./logs",
    logging_steps=10,
    save_steps=500,
    save_total_limit=2,
    # fp16=True,  # Enable mixed precision
)

# Initialize the Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset,
)
print("Starting to training")
# Fine-tune the model with LoRA
trainer.train()

print("Finished to training")
# Save the fine-tuned model
trainer.save_model("llama2-lora-finetuned")
print("model saved ")

合并LoRA微调权重到基础模型中,生成一个完整的模型

导入必要的库

from transformers import LlamaForCausalLM, LlamaTokenizer
from peft import PeftModel, PeftConfig

解释:导入transformers库中的Llama模型和分词器,以及peft库中的用于处理LoRA微调模型的PeftModel类。

加载基础Llama 2模型

model_name = r"C:\apps\ml_model\llama-2-13b-chat-hf"
base_model = LlamaForCausalLM.from_pretrained(model_name)
tokenizer = LlamaTokenizer.from_pretrained(model_name)
base_model.resize_token_embeddings(len(tokenizer))

解释

  • model_name 是基础Llama-2模型的路径。
  • LlamaForCausalLM.from_pretrained(model_name) 用于加载预训练的基础模型。
  • LlamaTokenizer.from_pretrained(model_name) 加载对应的分词器。
  • base_model.resize_token_embeddings(len(tokenizer)) 调整模型的词嵌入大小,以适应分词器的词汇量。

加载PEFT微调模型

peft_model_path = "./llama2-lora-finetuned"  # Path to your fine-tuned model
peft_model = PeftModel.from_pretrained(base_model, peft_model_path)

解释:加载经过LoRA微调的模型,路径是peft_model_path,并基于已经加载的基础模型base_model

合并LoRA权重并卸载LoRA配置

peft_model = peft_model.merge_and_unload()

解释:合并LoRA权重到基础模型中,这一步将LoRA微调权重应用到基础模型的权重上,并且卸载LoRA配置,使得模型变成一个完整的标准模型。

保存合并后的模型

peft_model.save_pretrained("./llama2-finetuned-combined")
tokenizer.save_pretrained("./llama2-finetuned-combined")

解释:将合并后的模型和分词器保存到指定的路径"./llama2-finetuned-combined"

重新加载合并后的模型和分词器

from transformers import LlamaForCausalLM, LlamaTokenizer

model = LlamaForCausalLM.from_pretrained("./llama2-finetuned-combined")
tokenizer = LlamaTokenizer.from_pretrained("./llama2-finetuned-combined")

解释:从保存的路径中加载已经合并权重的Llama-2模型和对应的分词器。

使用模型进行推理

inputs = tokenizer("What is the capital of France?", return_tensors="pt")
outputs = model.generate(**inputs)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

解释

  • 使用分词器将问题"What is the capital of France?" 转换为模型可以处理的张量格式。
  • 调用模型的generate()方法生成模型的输出。
  • 使用分词器将模型输出的token序列解码为可读文本,并打印输出。

完整代码

from transformers import LlamaForCausalLM, LlamaTokenizer
from peft import PeftModel, PeftConfig

# Load the base LLaMA 2 model
model_name = r"C:\apps\ml_model\llama-2-13b-chat-hf"
base_model = LlamaForCausalLM.from_pretrained(model_name)
tokenizer = LlamaTokenizer.from_pretrained(model_name)

base_model.resize_token_embeddings(len(tokenizer))

# Load the PEFT fine-tuned model
peft_model_path = "./llama2-lora-finetuned"  # Path to your fine-tuned model
peft_model = PeftModel.from_pretrained(base_model, peft_model_path)

# Merge the LoRA weights into the base model
peft_model = peft_model.merge_and_unload()

peft_model.save_pretrained("./llama2-finetuned-combined")
tokenizer.save_pretrained("./llama2-finetuned-combined")


from transformers import LlamaForCausalLM, LlamaTokenizer

model = LlamaForCausalLM.from_pretrained("./llama2-finetuned-combined")
tokenizer = LlamaTokenizer.from_pretrained("./llama2-finetuned-combined")

# Now you can use the model for inference
inputs = tokenizer("What is the capital of France?", return_tensors="pt")
outputs = model.generate(**inputs)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

执行后你会发现下面的模型代码生成

huggingface模型转换为gguf并量化请参考下面博客

Huggingface 模型转换成gguf并且量化_sft训练模型转gguf-CSDN博客

其它

把huggingface的模型转换成GGUF格式

python convert.py C:\Users\Harry\PycharmProjects\llm-finetuning\llama2-finetuned-combined --outfile C:\Users\Harry\PycharmProjects\llm-finetuning\llama2-finetuned-combined\llama2-7b-chat_f16.gguf --outtype f16

量化gguf格式模型

运行命令测试模型

main -m C:\Users\Harry\PycharmProjects\llm-finetuning\llama2-finetuned-combined\llama2-7b-chat_f16-q4_0.gguf --color --ctx_size 2048 -n -1 -ins -b 256 --top_k 10000 --temp 0.2 --repeat_penalty 1.1 -t 8






GitHub - huggingface/peft: 🤗 PEFT: State-of-the-art Parameter-Efficient Fine-Tuning.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2052458.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ComfyUI的部署,Ubuntu22.04系统下——点动科技

在服务器Ubuntu22.04系统下&#xff0c;ComfyUI的部署 一、ubuntu22.04基本环境配置1.1 更换清华Ubuntu镜像源1.2 更新包列表&#xff1a;2. 安装英伟达显卡驱动2.1 使用wget在命令行下载驱动包2.2 更新软件列表和安装必要软件、依赖2.2 卸载原有驱动2.3 安装驱动2.4 安装CUDA2…

【实战】分组校验

在实际的业务场景中同一个Entity的校验可能会有不同的规则&#xff0c;比如添加数据品牌id必须为空&#xff0c;而更新数据品牌Id必须不为空&#xff0c;针对这种情况我们需要使用分组校验来实现 在Entity中指定分组规则 使用 /*** 保存*/RequestMapping("/save")pub…

[STM32]如何正确的安装和配置keil?(详细)

一、我们为什么需要keil? 对于嵌入式开发的硬件来讲STM32可以说有着不可撼动的地位&#xff0c;它可能是很多人入门嵌入式开发接触到的第一款芯片&#xff0c;其强大的生态和大量开放的源代码也深受开发者的喜爱。对于嵌入式开发的软件来讲&#xff0c;keil绝对是在一届软件中…

知识竞赛中限时答题环节竞赛规则有哪些设计方案

限时答题在知识竞赛活动中是一个比较新颖的玩法&#xff0c;通过在一定时间内快速答题来提高现场紧张气氛&#xff0c;达到很好的现场效果。这种方式要求选手不但要答题正确&#xff0c;还要答题速度。那么&#xff0c;常用的限时答题环节规则应怎么设计呢&#xff1f;下面列出…

智能数字矿山钻机机械设备类网站模板

智能数字矿山钻机设备类网站模板&#xff0c;非常高端大气上档次&#xff01;易优内容管理系统是一套专注中小型企业信息传播解决方案的管理系统&#xff0c;更是一套后台管理框架&#xff0c;可以通过个性定制导航入口&#xff0c;扩展前端多个场景&#xff0c;比如可以用于小…

后端开发刷题 | 链表内指定区间反转【链表篇】

描述 将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转&#xff0c;要求时间复杂度 O(n)O(n)&#xff0c;空间复杂度 O(1)O(1)。 例如&#xff1a; 给出的链表为 1→2→3→4→5→NULL1→2→3→4→5→NULL, m2,n4 返回 1→4→3→2→5→NULL 数据范围&#xff1a; 链表…

【Linux】【系统纪元】Linux基础指令

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《C游记》《进击的C》《Linux迷航》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、文件管理1.1 ls1.2 pwd1.3 cd1.4 mkdir1.5 touch1.6 rm1.7 cp1.8 mv 二、文件输出2.1 echo2.2 cat2.3 less…

新学期新动力,以骨传导耳机开启健康音乐之旅

大学生快开学啦&#xff01;激励自己在学期的状态给自己准备一个礼物应该不过分吧&#xff0c;相信没有大学生能够没有耳机&#xff01;不管是在赶早八的路上也要放收歌来醒醒神&#xff0c;还是日常散步不那么单调&#xff0c;使用频率都很高&#xff0c;但是入耳式的蓝牙耳机…

Stable Diffusion 提示词插件:开启个性化艺术创作大门,探索AI绘画新境界。让灵感枯竭再无可能!

前言 之前的文章介绍了提示词的基础用法和进阶用法&#xff0c;东西很多很复杂&#xff0c;那么非程序员相关行业的人员&#xff0c;对字符不敏感怎么办&#xff1f; 没关系&#xff0c;今天我来介绍几款提示词插件&#xff0c;可以大大提升 Stable Diffusion 的使用效率。 …

微信怎么恢复聊天记录?轻松4招,恢复消失的聊天记录

微信聊天记录不仅是日常沟通的桥梁&#xff0c;更是珍贵记忆的储存库。然而&#xff0c;误删、系统故障或设备更换等意外情况&#xff0c;时常让我们的聊天记录瞬间消失&#xff0c;给我们留下遗憾。面对这一挑战&#xff0c;微信怎么恢复聊天记录成为许多人的迫切需求。幸运的…

opensuse leap15安装配置

opensuse leap15安装配置 查看opensuse leap15安装完成后的基本配置关闭SELinux禁用AppArmor 关闭firewalld防火墙关闭polki服务&#xff08;非必须&#xff09;tuned服务安装必备软件 查看opensuse leap15安装完成后的基本配置 默认开启了防火墙默认开启了Linux安全模块 关闭…

day34 代码随想录 | 不同路径 整数拆分

不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。问总共有多少条不同的路径&#xff1f…

第37讲:Cephfs文件系统的正确使用姿势

文章目录 1.Cephfs文件系统简介2.Cephfs文件系统细节介绍2.1.Cephfs文件系统多客户端隔离挂载2.2.Ceph集群中多个Cephfs如何单独使用 3.挂载多个Cephfs文件系统4.Cephfs文件系统多客户端隔离挂载实战4.1.创建一个Cephfs文件系统4.2.将Cephfs文件系统挂载到本地路径4.3.在Cephfs…

JavaWeb - 认识web开发

JavaWeb Java和JavaWeb是两个不同的概念&#xff0c;它们在范围和应用上有所区别&#xff1a; Java&#xff1a; 定义&#xff1a;Java是一种面向对象的编程语言&#xff0c;由Sun Microsystems公司&#xff08;现已被Oracle收购&#xff09;于1995年推出。应用范围&#xff1…

易企秀场景秀源码系统全新升级,方便制作各种Html5应用的制作工具 带完整的安装代码包以及搭建部署教程

系统概述 在当今数字化的时代&#xff0c;Html5 应用已经成为了展示和传播信息的重要方式。而在众多的制作工具中&#xff0c;易企秀场景秀源码系统以其全新升级的功能和便捷性&#xff0c;吸引了众多用户的目光。它不仅为用户提供了方便制作各种 Html5 应用的工具&#xff0c…

亚马逊测评自养号:揭秘高效环境搭建的秘诀

亚马逊测评自养号环境搭建的技术要点主要涵盖了网络环境、IP管理、设备配置、浏览器防关联、支付卡选择与管理以及账号管理等多个方面。以下是对这些技术要点的详细解析&#xff1a; 1. 网络环境 使用国外服务器&#xff1a;在云端搭建安全终端&#xff0c;确保能够阻断硬件参…

【python基础】—离线环境下,在linux中安装python包(以sqlalchemy为例)

文章目录 第一步&#xff1a;在线环境下载离线安装包及依赖包。第二步&#xff1a;把包上传到离线环境的服务器上&#xff0c;进行安装。第三步&#xff1a;测试是否安装成功。常见报错之版本选择问题 第一步&#xff1a;在线环境下载离线安装包及依赖包。 下载第三方库官网&am…

基于django的影音播放网站 /基于python的影视网站/影视播放系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

在Vue工程中开发页面时,发现页面垂直方向出现两个滚动条的处理

在Vue工程中开发页面时&#xff0c;发现页面垂直方向出现两个滚动条 最近在开发页面时&#xff0c;发现页面多了两个滚动条&#xff0c;如图&#xff1a; 原因&#xff1a; 当一个页面的内容高度大于屏幕的高度时就会出现滚动条。一般情况下当一个页面高度大于屏幕高度时&a…

Yolov8 人脸关键点检测

原文&#xff1a;Yolov8 人脸关键点检测 - 知乎 (zhihu.com) 基于yolov8的人脸检测&#xff0c;带关键点检测。主要基于yolov8 姿态估计进行修改&#xff1a; Ctrl CV&#xff1a;Yolov8 姿态估计20 赞同 39 评论文章 人脸关键点有5个点&#xff0c;分别为左右两个嘴角&…