当前位置:   article > 正文

Llama3-8B基于peft+trl进行SFT监督微调(Python代码模式)_llama3sft

llama3sft

4月19日Meta终于发布了Llama3,包含8B和70B两种模型,本次我们就来试着微调下8B的模型。

命令行模式的SFT见:Llama3-8B基于trl进行SFT监督微调(命令行模式)-CSDN博客

环境:

GPU:NVIDIA A100 80G

CUDA:12.3

Python 3.11+PyTorch 2.1.2+transformers 4.40.0

一、准备环境

安装Python依赖,重点是

  1. pip install trl
  2. pip install peft
  3. pip install bitsandbytes

其他缺什么补什么。

下载Llama3-8B模型,国内可以从modelscope上下载:

git clone https://www.modelscope.cn/LLM-Research/Meta-Llama-3-8B.git

下载完毕后有如下文件:

下载微调数据:

本次我们使用ruozhiba_qa数据。

HuggingFace下载地址:https://huggingface.co/datasets/LooksJuicy/ruozhiba

核心是其中的ruozhiba_qa.json。数据格式:

二、数据集处理

如上图,原始的ruozhiba_qa.json中问题和答案分别在不同的字段上,即"instruction"和“output”。而待会训练时SFTTrainer中要求传入的数据集的“dataset_text_field”字段只能为string类型,不能传list<string>,而对于问答微调任务,显然是要把问题和答案一起喂给训练器的。因此需要对原始数据进行合并处理,将instruction和output合并在一个新的"text"字段中。合并的代码如下:

  1. # -*- coding: utf-8 -*-
  2. """
  3. 数据集处理
  4. """
  5. import json
  6. def process():
  7. input_filename = "/Users/zhujiahui/Downloads/ruozhiba_qa.json"
  8. output_filename = "/Users/zhujiahui/Local/model/Llama3-Chinese-Dataset/ruozhiba_qa.json"
  9. result_json_list = []
  10. with open(output_filename, "w") as write_file:
  11. with open(input_filename, 'r') as read_file:
  12. data_json = json.load(read_file)
  13. for each_json in data_json:
  14. each_result_json = {"text": "<s>[INST]" + each_json["instruction"]
  15. + "[/INST] " + each_json["output"] + "</s>"}
  16. result_json_list.append(each_result_json)
  17. write_file.write(json.dumps(result_json_list, ensure_ascii=False, indent=4))
  18. if __name__ == '__main__':
  19. process()

处理之后新的数据集格式如下:

处理完后将数据上传至服务器。

参考:python - TRL SFTTrainer - llama2 finetuning on Alpaca - datasettext field - Stack Overflow

三、直接推理

采用如下代码先直接对原始的Llama3-8B进行推理:

  1. import torch
  2. from transformers import (
  3. AutoModelForCausalLM,
  4. AutoTokenizer,
  5. AutoModel
  6. )
  7. # 根据不同的环境设置GPU名称
  8. DEVICE = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
  9. def origin_main():
  10. origin_model = "/Users/zhujiahui/Local/model/Meta-Llama-3-8B"
  11. tokenizer = AutoTokenizer.from_pretrained(origin_model, trust_remote_code=True)
  12. model = AutoModelForCausalLM.from_pretrained(origin_model).to(DEVICE)
  13. prompt = "只剩一个心脏了还能活吗?"
  14. inputs = tokenizer([prompt], max_length=128)
  15. input_ids = torch.tensor(inputs["input_ids"]).to(DEVICE)
  16. print(input_ids)
  17. outputs = model.generate(input_ids, max_length=128)
  18. final_result = tokenizer.decode(outputs[0], skip_special_tokens=True)
  19. print(final_result)
  20. if __name__ == '__main__':
  21. origin_main()

笔者的Mac可以直接基于mps本地跑,结果如下:

可以发现Llama对于中文问题的回答实在是惨不忍睹。

感觉有点问题,怕是tokenizer分词之后映射有些问题,基于transformers.pipeline换另外一种方式推理:

  1. import torch
  2. from transformers import (
  3. AutoModelForCausalLM,
  4. AutoTokenizer,
  5. AutoModel,
  6. BitsAndBytesConfig,
  7. HfArgumentParser,
  8. TrainingArguments,
  9. pipeline,
  10. logging
  11. )
  12. # 根据不同的环境设置GPU名称
  13. DEVICE = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
  14. def pipeline_main():
  15. origin_model = "/Users/zhujiahui/Local/model/Meta-Llama-3-8B"
  16. tokenizer = AutoTokenizer.from_pretrained(origin_model, trust_remote_code=True)
  17. llama_pipeline = pipeline("text-generation", model=origin_model, tokenizer=tokenizer, device=DEVICE)
  18. sentences = llama_pipeline("只剩一个心脏了还能活吗?", do_sample=True, top_k=10,
  19. eos_token_id=tokenizer.eos_token_id, max_length=128)
  20. for seq in sentences:
  21. print(seq["generated_text"])
  22. if __name__ == '__main__':
  23. pipeline_main()

结果如下:

结果正常许多。

四、使用peft+trl进行LoRA指令微调

trl (Transformer Reinforcement Learning),Transformer强化学习,它提供了在训练和微调LLM的各个步骤中的实现,包括监督微调步骤(SFT),奖励建模步骤(RM)和近端策略优化(PPO)等。

peft (Parameter-Efficient Fine-Tuning),是HuggingFace推出的一个参数高效微调库,详见:https://www.wpsshop.cn/w/2023面试高手/article/detail/620559

推荐阅读
相关标签
  

闽ICP备14008679号