赞
踩
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依赖,重点是
- pip install trl
- pip install peft
- 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"字段中。合并的代码如下:
- # -*- coding: utf-8 -*-
-
- """
- 数据集处理
- """
-
- import json
-
-
- def process():
- input_filename = "/Users/zhujiahui/Downloads/ruozhiba_qa.json"
- output_filename = "/Users/zhujiahui/Local/model/Llama3-Chinese-Dataset/ruozhiba_qa.json"
-
- result_json_list = []
- with open(output_filename, "w") as write_file:
- with open(input_filename, 'r') as read_file:
- data_json = json.load(read_file)
- for each_json in data_json:
- each_result_json = {"text": "<s>[INST]" + each_json["instruction"]
- + "[/INST] " + each_json["output"] + "</s>"}
- result_json_list.append(each_result_json)
-
- write_file.write(json.dumps(result_json_list, ensure_ascii=False, indent=4))
-
-
- if __name__ == '__main__':
- process()
处理之后新的数据集格式如下:
处理完后将数据上传至服务器。
参考:python - TRL SFTTrainer - llama2 finetuning on Alpaca - datasettext field - Stack Overflow
采用如下代码先直接对原始的Llama3-8B进行推理:
- import torch
-
- from transformers import (
- AutoModelForCausalLM,
- AutoTokenizer,
- AutoModel
- )
-
- # 根据不同的环境设置GPU名称
- DEVICE = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
-
-
- def origin_main():
-
- origin_model = "/Users/zhujiahui/Local/model/Meta-Llama-3-8B"
- tokenizer = AutoTokenizer.from_pretrained(origin_model, trust_remote_code=True)
- model = AutoModelForCausalLM.from_pretrained(origin_model).to(DEVICE)
-
- prompt = "只剩一个心脏了还能活吗?"
- inputs = tokenizer([prompt], max_length=128)
- input_ids = torch.tensor(inputs["input_ids"]).to(DEVICE)
- print(input_ids)
-
- outputs = model.generate(input_ids, max_length=128)
- final_result = tokenizer.decode(outputs[0], skip_special_tokens=True)
- print(final_result)
-
-
-
- if __name__ == '__main__':
- origin_main()
笔者的Mac可以直接基于mps本地跑,结果如下:
可以发现Llama对于中文问题的回答实在是惨不忍睹。
感觉有点问题,怕是tokenizer分词之后映射有些问题,基于transformers.pipeline换另外一种方式推理:
- import torch
-
- from transformers import (
- AutoModelForCausalLM,
- AutoTokenizer,
- AutoModel,
- BitsAndBytesConfig,
- HfArgumentParser,
- TrainingArguments,
- pipeline,
- logging
- )
-
- # 根据不同的环境设置GPU名称
- DEVICE = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
-
-
- def pipeline_main():
- origin_model = "/Users/zhujiahui/Local/model/Meta-Llama-3-8B"
- tokenizer = AutoTokenizer.from_pretrained(origin_model, trust_remote_code=True)
- llama_pipeline = pipeline("text-generation", model=origin_model, tokenizer=tokenizer, device=DEVICE)
- sentences = llama_pipeline("只剩一个心脏了还能活吗?", do_sample=True, top_k=10,
- eos_token_id=tokenizer.eos_token_id, max_length=128)
- for seq in sentences:
- print(seq["generated_text"])
-
-
- if __name__ == '__main__':
- pipeline_main()
结果如下:
结果正常许多。
trl (Transformer Reinforcement Learning),Transformer强化学习,它提供了在训练和微调LLM的各个步骤中的实现,包括监督微调步骤(SFT),奖励建模步骤(RM)和近端策略优化(PPO)等。
peft (Parameter-Efficient Fine-Tuning),是HuggingFace推出的一个参数高效微调库,详见:https://www.wpsshop.cn/w/2023面试高手/article/detail/620559
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。