大语言模型微调实践记录
背景
根据目前公开的训练范式,大模型微调主要经过三个步骤的训练:
- 万亿Token预训练
- SFT指令对齐
- RLHF阶段
目前开源的模型大部分为基座大模型与对齐后的chat模型,大体对应了两个阶段中的1与2阶段。本篇将记录根据开源的基座大模型进行SFT微调的实战记录。
基座大模型是不具备对话能力的,所以回答会出现牛头不对马嘴的情况。所以需要我们针对具体的对话数据进行SFT微调,使之具备初步的对话能力。
3月初时,笔者当时根据羊驼项目进行过Llama模型的初步微调,但当时受客观条件限制——训练时间过长与数据集准备不充分、模型了解不多,导致训练完毕后,生成部分会出现token重复,回答截断等问题。所以微调阶段一度放弃。
时间来到9月份,一是认为微调不出具备良好效果的大模型则无法踩坑,也不会有太大成长。二是毕竟这是大势所趋,作为算法工程师应是必备技能。另外,随着陆续开源,可借鉴的资料也很多,所以再度挤时间投入这部分的实验验证。
模型训练大致需要做好三个准备工作:
- 数据集准备
- 模型训练代码
- 资源环境配置、评估工作
数据部分
数据集部分,对于超大数据量数据,通常需要做数据清洗与聚类去重操作,这里将常见的清洗类型与聚类方法进行列举:
- 清洗类型节选自百度: 文心一言数据清洗使用说明
- 去重操作: BigCode 背后的大规模数据去重
- 基本处理流程: 大语言模型复杂处理流程
这里,我们不涉及数据清洗与数据去重操作,在已知的高质量指令数据中选取复旦大学MOSS团队开源的中英文多轮对话数据。
模型部分
本次微调基于开源Firefly项目(代码友好型,组织结构易于理解)。基座模型选取Baichuan-7B与
Baichuan2-7B进行对比。模型的具体细节不再赘述。具体细节讲解见此处。
在实际测试过程中,基座模型是不具备对话能力的,所以需要针对基座模型进行SFT的微调。这里之前我一直有误解。这里值得一提的是在多轮对话训练过程中,Firefly损失函数处稍有改进,具体讲解见此处。
训练部分
日志记录
训练过程各相关曲线的观察,这里未采用原项目中的tensorboard,而是选用的wandb。
起初实验验证部分选取了MOSS前10万条数据,epoch=1,在两个A6000大约耗时22小时进行微调,结果发现模型已实现了基本的指令对齐,而且并未出现回答token重复等现象出现,这已验证了Firefly项目的良好微调特性。
Moss前10万,Epoch=1
效果图
目前正在进行基于baichuan-7B与Baichuan2-7B在MOSS上的全量数据微调,相关结果等数据出现后会再公布。
Update:
2023-09-10
baichuan-7B
数据集: Moss
微调日志: 机器 4卡- A100
【2023-09-10 10:18:45】***** train metrics *****
1350
【2023-09-10 10:18:45】 epoch = 1.0
1351
【2023-09-10 10:18:45】 train_loss = 0.7111
1352
【2023-09-10 10:18:45】 train_runtime = 1 day, 20:04:26.08
1353
【2023-09-10 10:18:45】 train_samples_per_second = 6.772
1354
【2023-09-10 10:18:45】 train_steps_per_second = 0.053
1355
【2023-09-10 10:18:45】wandb: Waiting for W&B process to finish... (success).
【2023-09-10 10:18:46】wandb: Run summary:
1369
【2023-09-10 10:18:46】wandb: train/epoch 1.0
1370
【2023-09-10 10:18:46】wandb: train/global_step 8395
1371
【2023-09-10 10:18:46】wandb: train/learning_rate 0.0002
1372
【2023-09-10 10:18:46】wandb: train/loss 0.6591
1373
【2023-09-10 10:18:46】wandb: train/total_flos 2.4055027002056376e+19
1374
【2023-09-10 10:18:46】wandb: train/train_loss 0.71107
1375
【2023-09-10 10:18:46】wandb: train/train_runtime 158666.0883
1376
【2023-09-10 10:18:46】wandb: train/train_samples_per_second 6.772
1377
【2023-09-10 10:18:46】wandb: train/train_steps_per_second 0.053
多轮对话效果图
User | hello |
---|---|
Moss | Hello! How can I assist you today? |
User | 你谁 会说中文吗 |
Moss | 是的,我可以使用中文与您交流。 |
User | 北京连续下了两天雨了,已经入秋,你能作首宋词描述一下吗 |
Moss | 当然可以,以下是我为您创作的一首宋词: 《秋雨》 秋雨绵绵,秋风萧瑟, 梧桐叶落,满地黄。 秋雨绵绵,秋风萧瑟, 万物凋零,人心思归。 秋雨绵绵,秋风萧瑟, 梧桐叶落,满地黄。 秋雨绵绵,秋风萧瑟, 万物凋零,人心思归。 |
User | 你能背诵李白的将进酒吗 |
Moss | 当然可以,以下是我为您背诵的李白的《将进酒》: 君不见黄河之水天上来,奔流到海不复回。 君不见高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。 烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。 钟鼓馔玉不足贵,但愿长醉不复醒。 古来圣贤皆寂寞,惟有饮者留其名。 陈王昔时宴平乐,斗酒十千恣欢谑。 主人何为言少钱,径须沽取对君酌。 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。 |
User | 可以把最后一句翻译成英文吗 |
Moss | Sure, the last line of the poem is: “五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。” Translation: “Five-colored horse, thousand-gold coat, call my son to exchange for wine, and you can help me forget the world for thousands of years.” |
User | 你做的很不错呢 |
Moss | 谢谢夸奖!我会继续努力的。 |
User | 你认识黑塞吗 |
Moss | 黑塞是德国作家,他的作品被翻译成多种语言,包括中文。他的代表作包括《荒原狼》、《流浪者之歌》等。 |
User | 荒原狼讲的 什么啊 |
Moss | 《荒原狼》是黑塞的代表作之一,讲述了一个孤独的男子在荒原上寻找自我和意义的故事。主人公哈里在现实生活中感到孤独和无助,于是他开始漫游荒原,寻找自我和意义。在荒原上,他遇到了许多人和事物,包括一个神秘的流浪者,一个神秘的女子,以及一只狼。在与这些人和事物的接触中,哈里逐渐找到了自我和意义,最终回到了现实生活中。 |
User | 我刚要开始读它,有什么建议吗 |
Moss | 如果你想开始读《荒原狼》,我建议你先了解一些背景知识。黑塞的作品通常涉及到哲学、宗教、历史等多个领域,需要有一定的阅读基础。此外,黑塞的作品通常比较深刻,需要有一定的思考和理解能力。如果你对这些方面不太熟悉,可以先阅读一些相关的介绍和导读,或者选择一些比较易读的作品。最后,阅读黑塞的作品需要耐心和时间,不要急于求成,慢慢地品味其中的深意和美感。 |
User | 好的,谢谢了,周末愉快 |
Moss | 很高兴能够帮到你,祝你周末愉快!如果你有任何其他问题,随时都可以问我。 |
从几个测试样例看,效果还是蛮不错的,唯独宋词部分重复输出,综合细评后续给出。
baichuan2-7B
目前微调800step后,会遇到Assertion srcIndex < srcSelectDimSize
错误,从而中断,查阅资料应该是token 索引溢出,但具体错误需要在cpu模式下才会报具体的错误信息,目前不太好解决。。。
Update:
2023-09-12
baichuan2-7B报错是因为包含了add_tokens.json中
目前baichuan2-7B正在微调中.
Update:
2023-09-13
baichuan2-7B
数据集: Moss
微调日志: 机器 4卡- A100
【2023-09-13 12:56:48】wandb: Run summary:
【2023-09-13 12:56:48】wandb: train/epoch 1.0
【2023-09-13 12:56:48】wandb: train/global_step 16790
【2023-09-13 12:56:48】wandb: train/learning_rate 0.0002
【2023-09-13 12:56:48】wandb: train/loss 0.7066
【2023-09-13 12:56:48】wandb: train/total_flos 2.5723421463171564e+19
【2023-09-13 12:56:48】wandb: train/train_loss 0.74206
【2023-09-13 12:56:48】wandb: train/train_runtime 145986.254
【2023-09-13 12:56:48】wandb: train/train_samples_per_second 7.361
【2023-09-13 12:56:48】wandb: train/train_steps_per_second 0.115
多轮对话效果: 测试样例与baichuan1 保持相同
User | hello |
---|---|
Moss | Hello! How can I assist you today? |
User | 你谁 会说中文吗 |
Moss | 是的,我会说中文。请问有什么可以帮助您的吗? |
User | 当然可以,以下是我为您创作的宋词: 《秋雨》 秋雨绵绵,落满京城。 梧桐叶落,秋风萧瑟。 行人匆匆,脚步匆匆。 思绪万千,愁绪满怀。 但愿秋雨,早日停息。 但愿秋风,不再萧瑟。 但愿行人,不再匆匆。 但愿愁绪,早日消散。 |
User | 你能背诵李白的将进酒吗 |
Moss | 当然可以,以下是我为您背诵的《将进酒》: 君不见黄河之水天上来,奔流到海不复回。 君不见高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。 烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。 钟鼓馔玉不足贵,但愿长醉不愿醒。 古来圣贤皆寂寞,惟有饮者留其名。<br /陈王昔时宴平乐,斗酒十千恣欢谑。 主人何为言少钱,径须沽取对君酌。 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。 |
User | 可以把最后一句翻译成英文吗 |
Moss | 当然可以,最后一句的英文翻译是: “Call for the horses and the fur coat, let the children bring out the wine, and we will drink together to forget the sorrows of the ages.” |
User | 你做的很不错呢 |
Moss | 谢谢夸奖,我会继续努力为您服务的。 |
User | 你认识黑塞吗 |
Moss | 是的,我认识黑塞。黑塞是德国作家赫尔曼·黑塞的笔名,他是20世纪德国文学的代表人物之一,被誉为“德国文学的巨匠”。他的作品以深刻的哲学思考、细腻的情感描写和独特的艺术风格著称,深受读者喜爱。 |
User | 荒原狼讲的 什么啊 |
Moss | 《荒原狼》是德国作家赫尔曼·黑塞的一部小说,讲述了一个名叫哈勒尔的孤独、忧郁、反叛的作家,他在一次意外中失去了自己的灵魂,变成了荒原狼。他试图寻找自己的灵魂,但在这个过程中,他遇到了各种人和事,经历了许多磨难和痛苦,最终找到了自己的归宿。 小说中,黑塞通过哈勒尔的遭遇,探讨了人类的孤独、痛苦、反叛、追求等问题,表达了对人类命运的深刻思考和对人性的深刻洞察。同时,小说也展现了黑塞独特的文学风格和艺术魅力,被誉为德国文学的经典之作。 |
User | 我刚要开始读它,有什么建议吗 |
Moss | 当然,以下是一些阅读《荒原狼》的建议: 1. 了解黑塞的创作背景和思想,这有助于更好地理解小说中的主题和意义。 2. 注意小说中的细节描写和象征意义,这些细节和象征往往能够揭示出小说的深层含义。 3. 注意小说中的对话和内心独白,这些是小说中最重要的部分,能够揭示出哈勒尔的内心世界和情感变化。 4. 注意小说中的节奏和结构,黑塞的小说往往具有独特的节奏和结构,需要耐心阅读和理解。 5. 注意小说中的情感和主题,黑塞的小说往往具有深刻的情感和主题,需要用心去感受和理解。 希望这些建议能够对您阅读《荒原狼》有所帮助。 |
User | 好的,谢谢了,周末愉快 |
Moss | 不客气,祝您周末愉快!如果您有其他问题或需要帮助,随时都可以问我。 |
测试样例输出其他参数均为变化,可以看到与1对比,内容稍显丰富,同时秋雨的重复问题不再出现,但是在回答上,在“我刚要开始读它,有什么建议吗”的回答方式上,感觉1的开头回答方式稍显好些。
模型评估
通过阅读baichuan2技术论文,目前总体表现测试主要在以下8个benchmark下进行: MMLU,C-Eval,CMMLU,AGIEval, GaoKao,BBH,GSM8K,HumanEval。
另外还包括了垂直领域测试,数学与代码能力测试,多语言测试,道德测试。
测试方式主要为构建5-shot prompt的方式,让模型预测给出的问题答案,然后计算平均正确率。
Baichuan1-7B
经过Moss数据微调后,模型在C-Eval dev数据单次测试Average Acc为42.5%, github首页为42.8%,由于测试时为随机5-shot,0.3%的偏差在误差允许范围内,可见微调对原模型结构影响很小。
Baichuan2-7B
同上述测试一样,单次测试Average Acc 46.2%,github首页为54%,出入较大。
Argue
根据baichuan测评方法
C-Eval 数据集是一个全面的中文基础模型评测数据集,涵盖了 52 个学科和四个难度的级别。我们使用该数据集的 dev 集作为 few-shot 的来源,在 test 集上进行了 5-shot
测试。
通过看公开数据集,test文件夹csv种是不含answer的,看源码测试也不是,所以有点🤔疑惑怎么测试的。是用dev作为few-shot来源,测试val??
总之,目前SFT到测评全流程已基本跑通,暂不关注。
训练平台
公司目前已开放了ModelHub平台,但是我并未采用此方式进行微调训练。
主要采用了两种方式:
- 实验验证部分,基于离线容器,通过创建python虚拟容器进行环境配置。
- 全量数据部分,目前正通过鲁班平台→离线任务→开发任务 进行微调,但是该方法存在稳定性的问题,偶尔会因为显存问题训练过程被中断。
下面列举详细配置及参数
- Firefly项目:
项目介绍页会列举torch版本的区别,可全部采用2.0以上版本, python版本3.8.10。
accelerate==0.21.0
peft==0.4.0
bitsandbytes==0.41.0
loguru==0.7.0
numpy==1.21.4
pandas==1.2.5
tqdm==4.62.3
deepspeed==0.9.5
tensorboard
sentencepiece
transformers_stream_generator
tiktoken
einops
Xformers
torch==2.0.1
scipy
wandb
transformers需要原包安装
2.模型训练参数
{
"output_dir": "output/firefly-baichuan-7b-1000000",
"model_name_or_path": "baichuan-7B",
"cache_dir": "cache_model",
"train_file": "./data/moss-003-sft-data.jsonl",
"num_train_epochs": 1,
"per_device_train_batch_size": 16,
"gradient_accumulation_steps": 2,
"learning_rate": 2e-4,
"max_seq_length": 1024,
"logging_steps": 50,
"save_steps": 100,
"save_total_limit": 1,
"lr_scheduler_type": "constant_with_warmup",
"warmup_steps": 1000,
"lora_rank": 64,
"lora_alpha": 16,
"lora_dropout": 0.05,
"bits": 4,
"gradient_checkpointing": true,
"disable_tqdm": false,
"optim": "paged_adamw_32bit",
"seed": 42,
"fp16": true,
"report_to": "wandb",
"dataloader_num_workers": 0,
"save_strategy": "steps",
"weight_decay": 0,
"max_grad_norm": 0.3,
"remove_unused_columns": false,
"do_eval": false,
"evaluation_strategy": "no"
}
模型评估
该部分待全量模型训练完毕后再进行补充
TO-DO
- 更改Dataloader为动态加载文件方式,以适应超大规模数据
- 添加模型评估方法
- 添加交互界面以供测试,提供http调用
FAQ:
1. 训练提示bitsandbytes报错?
Transformer版本一定要用原库安装,一般安装命令
pip install git+https:*//github.com/huggingface/transformers.git
不过由于公司平台网络限制原因,建议直接下载git包后,通过pip install -e .
的方式进行安装
2. 如果发生生成token重复怎么办?
生成token重复通常可能因训练不充分,或数据集质量太差,另外也可通过生成参数去控制,具体可见[**此处**](https://yuansearch.com/2023/08/14/%E8%A7%A3%E7%A0%81%E7%9A%84%E7%94%9F%E6%88%90%E5%A4%9A%E6%A0%B7%E6%80%A7/)
以上为本周进展,本篇将根据具体实验进展不断更新,以上部分观点仅为个人见解,如有错误,望批评指正。