社区供稿 | 百川baichuan-7B实测,QLoRA+百万指令数据微调

07/04 19:00
阅读数 2.3K

前言:欢迎关注我们的中文大语言模型开源项目 Firefly(流萤)。正如我们的项目名称一样,希望本项目能够像流萤一般发出淡淡微光,为中文大语言模型社区尽绵薄之力,促进中文大语言模型社区的发展。


项目地址:https://github.com/yangjianxin1/Firefly

01

模型简介

6月15日,百川智能发布了其首个开源可商用的中英文大语言模型——baichuan-7b,该模型的结构与LLaMA基本一致,使用了1.2万亿token进行训练。相较于原生的LLaMA以及经过词表扩充后的LLaMA-Chinese系列模型,baichuan-7b先天上更适合中文场景的任务。


baichuan-7b在C-Eval、AGIEval和Gaokao等榜单上名列前茅。并且在MMLU榜单上的得分也超过了LLaMA-7b。


在SuperCLUE榜单上,baichuan-7b作为一个未经过指令微调的预训练模型,也取得了相当不错的名次。这让我们更加好奇,经过sft后的baichuan-7b模型的能力会如何?


由于baichuan-7b是一个预训练模型,未经过指令对齐,所以指令遵从的能力较弱。为了进一步验证baichuan-7b模型的能力,我们使用Firefly项目中的QLoRA训练流程,在百万多轮指令数据上进行了指令微调。最终得到了firefly-baichuan-7b-qlora-sft模型,我们也开源了模型权重,欢迎大家使用。


项目地址:

https://github.com/yangjianxin1/Firefly

模型权重:

https://huggingface.co/YeungNLP/firefly-baichuan-7b-qlora-sft


由于精力有限,目前尚未在开源测试集或LLM榜单上进行测评。非常欢迎有兴趣的同学进行测评。


对于QLoRA的原理和训练流程尚不熟悉的同学,可参考文章【QLoRA实战】使用单卡高效微调bloom-7b1,效果惊艳Firefly | QLoRA+百万数据,多卡高效微调bloom-7b1模型


02

训练策略

我们将老朋友bloom-7b1替换成baichuan-7b,使用moss-003-sft-data数据训练一个epoch,数据量为100万+。

训练时,我们将多轮对话拼接成如下格式,然后进行tokenize。

<s>input1</s>target1</s>input2</s>target2</s>...

除了embedding和lm_head,我们在所有全连接层处都插入adapter,其中lora_rank为64,lora_alpha为16,lora_dropout为0.05。最终参与训练的参数量约为1.4亿,超过一个bert-base模型的参数量。对于一条多轮指令数据,训练时只计算target部分的损失函


训练超参数如下所示:

max length 1024
lr_scheduler_type constant_with_warmup
batch size 64
lr 2e-4
warmup step 2000
optimizer paged_adamw_32bit
training step 16k


模型的训练损失的变化趋势如下图所示,训练损失的下降比较平滑。


使用firefly-baichuan-7b-qlora-sft进行单轮对话的方式如下:

from peft import PeftModelfrom transformers import AutoModelForCausalLM, AutoTokenizerimport torch
model_name = 'baichuan-inc/baichuan-7B'adapter_name = 'YeungNLP/firefly-baichuan-7b-qlora-sft'max_new_tokens = 500top_p = 0.9temperature = 0.35repetition_penalty = 1.0device = 'cuda'input_pattern = '<s>{}</s>'
model = AutoModelForCausalLM.from_pretrained( model_name, trust_remote_code=True, low_cpu_mem_usage=True, torch_dtype=torch.float16, device_map='auto')model = PeftModel.from_pretrained(model, adapter_name)model.eval()model = model.to(device)tokenizer = AutoTokenizer.from_pretrained( model_name, trust_remote_code=True)
text = input('User:')while True: text = input_pattern.format(text) input_ids = tokenizer(text, return_tensors="pt").input_ids input_ids = input_ids.to(device) outputs = model.generate( input_ids=input_ids, max_new_tokens=max_new_tokens, do_sample=True, top_p=top_p, temperature=temperature, repetition_penalty=repetition_penalty, eos_token_id=tokenizer.eos_token_id ) rets = tokenizer.batch_decode(outputs) output = rets[0].strip().replace(text, "").replace('</s>', "") print("Firefly:{}".format(output)) text = input('User:')

使用firefly-baichuan-7b-qlora-sft进行多轮对话的方式如下:

from transformers import AutoModelForCausalLM, AutoTokenizerfrom peft import PeftModelimport torch
device = 'cuda'model_name = 'baichuan-inc/baichuan-7B'adapter_name = 'YeungNLP/firefly-baichuan-7b-qlora-sft'max_new_tokens = 500top_p = 0.9temperature = 0.35repetition_penalty = 1.0
tokenizer = AutoTokenizer.from_pretrained( model_name, trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained( model_name, trust_remote_code=True, low_cpu_mem_usage=True, torch_dtype=torch.float16, device_map='auto')model = PeftModel.from_pretrained(model, adapter_name)model.eval()model = model.to(device)
# 记录所有历史记录history_token_ids = tokenizer('<s>', return_tensors="pt").input_ids# 输入模型的最大长度history_max_len = 1000
user_input = input('User:')while True: user_input = '{}</s>'.format(user_input) user_input_ids = tokenizer(user_input, return_tensors="pt").input_ids history_token_ids = torch.concat((history_token_ids, user_input_ids), dim=1)
model_input_ids = history_token_ids[:, -history_max_len:].to(device) outputs = model.generate( input_ids=model_input_ids, max_new_tokens=max_new_tokens, do_sample=True, top_p=top_p, temperature=temperature, repetition_penalty=repetition_penalty, eos_token_id=tokenizer.eos_token_id ) model_input_ids_len = model_input_ids.size(1) response_ids = outputs[:, model_input_ids_len:] history_token_ids = torch.concat((history_token_ids, response_ids.cpu()), dim=1)
response = tokenizer.batch_decode(response_ids) print("Firefly:" + response[0].strip().replace('</s>', "")) user_input = input('User:')


03

模型效果

下面的样例均为firefly-baichuan-7b-qlora-sft模型所生成,未经修改,仅供参考。由于图片中的字体过小,建议放大图片后进行阅读。


多轮对话

我们测了几个多轮对话的case,模型的上下文理解能力着实不错,多轮对话中的指代消歧也能很好地完成。

对话示例1:

对话示例2:


知识库问答

我们从网上随机复制了一些文本片段,测试模型的知识库问答能力,模型的表现相当不错。模型基本上都能够根据给定的文章内容,生成合适的答案,这在知识库问答场景中有非常大的实用价值。


古诗词


邮件生成


商品文案生成


中英翻译

我们测试了一些常规的中英翻译case,以及将古诗词翻译成英文的能力,表现也不错,翻译结果与古诗词表达的意境相近。


医疗问答


其他示例


04

结语

从有限的评测case来看,baichuan-7b经过QLoRA进行指令微调之后,具有十分优秀的指令遵从能力。baichuan-7b是一个十分优秀的中文基座模型,值得在中英文下游任务中进行尝试。


由于尚未在开源测试集或LLM榜单上进行评测,客观的评测结果尚不得知。后续若有时间精力,将会对评测部分的工作进行补充。




本文转载自社区供 稿项目,内容不代表官方立场。了解更多,请关注下面的公众号卡片:
如果你有好的文章希望通过我们的平台分享给更多人,请通过这个链接与我们联系: 

https://huggingface.link/tougao

本文分享自微信公众号 - Hugging Face(gh_504339124f0f)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部