最新的readme文档请移步Github仓库ChatLM-mii-Chiese 现在的大语言模型的参数往往较大,消费级电脑单纯做推理都比较慢,更别说想自己从头开始训练一个模型了。本项目的目标是从0开始训练一个生成式语言模型,包括数据清洗、tokeizer训练、模型预训练、SFT指令微调、RLHF优化等。 ChatLM-mii-Chiese为中文对话小模型,模型参数只有0.2B(算共享权重约210M),可以在最低4GB显存的机器进行预训练( 如果需要做基于小模型的检索增强生成(RAG),可以参考我的另一个项目Phi2-mii-Chiese,代码见ragwithlagchai.ipyb ? 所有数据集均来自互联网公开的 数据集总数量1023万:Text-to-Text预训练集:930万,评估集:2.5万(因为解码较慢,所以没有把评估集设置太大)。~~测试集:90万。~~
SFT微调和DPO优化数据集见下文。 T5模型(Text-to-Text Trasfer Trasformer),详情见论文: Explorig the Limits of Trasfer Learig with a Uified Text-to-Text Trasformer。 模型源码来自huggigface,见:T5ForCoditioalGeeratio。 模型配置见model_cofig.jso,官方的 模型参数:0.2B。词表大小:29298,仅包含中文和少量英文。 硬件: 默认使用 存在问题:预训练数据集只有900多万,模型参数也仅0.2B,不能涵盖所有方面,会有答非所问、废话生成器的情况。 如果无法连接huggigface,请使用 [!CAUTION]
本项目模型为 本项目推荐使用 pip安装: 如果pip安装了CPU版本的pytorch,可以通过下面的命令安装CUDA版本的pytorch: coda安装: 用 ```bash git cloe --depth 1 https://huggigface.co/charet/ChatLM-mii-Chiese git cloe --depth 1 https://www.modelscope.c/charet/ChatLM-mii-Chiese.git mv ChatLM-mii-Chiese model_save pytho wordsmergelist = []
for word i words_dict.keys():
= le(word)
if >= 2:
# a, b切分12345示例: 1 2345, 12 345, 123 45, 1234 5
for i i rage(1, ):
a, b = ''.joi(word[0: i]), ''.joi(word[i: ]) jso
{
"prompt": "对于花园街,你有什么了解或看法吗?",
"respose": "花园街(是香港油尖旺区的一条富有特色的街道,位于九龙旺角东部,北至界限街,南至登打士街,与通菜街及洗衣街等街道平行。现时这条街道是香港著名的购物区之一。位于亚皆老街以南的一段花园街,也就是\"波鞋街\"整条街约150米长,有50多间售卖运动鞋和运动用品的店舖。旺角道至太子道西一段则为排档区,售卖成衣、蔬菜和水果等。花园街一共分成三段。明清时代,花园街是芒角村栽种花卉的地方。此外,根据历史专家郑宝鸿的考证:花园街曾是1910年代东方殷琴拿烟厂的花园。纵火案。自2005年起,花园街一带最少发生5宗纵火案,当中4宗涉及排档起火。2010年。2010年12月6日,花园街222号一个卖鞋的排档于凌晨5时许首先起火,浓烟涌往旁边住宅大厦,消防接报4"
} jso
{
"prompt": "解释什么是欧洲启示录",
"respose": "欧洲启示录(The Book of Revelatio)是新约圣经的最后一卷书,也被称为《启示录》、《默示录》或《约翰默示录》。这本书从宗教的角度描述了世界末日的来临,以及上帝对世界的审判和拯救。 书中的主题包括来临的基督的荣耀,上帝对人性的惩罚和拯救,以及魔鬼和邪恶力量的存在。欧洲启示录是一个充满象征和暗示的文本,对于解读和理解有许多不同的方法和观点。"
} bash accelerate lauch --multigpu --umprocesses 2 ./trai.py --is_fietue=True pytho sft_trai.py jso
{
"prompt": "为给定的产品创建一个创意标语。,输入:可重复使用的水瓶。",
"chose": "\"保护地球,从拥有可重复使用的水瓶开始!\"",
"rejected": "\"让你的水瓶成为你的生活伴侣,使用可重复使用的水瓶,让你的水瓶成为你的伙伴\""
} bash pytho dpo_trai.py bash
ChatLM-mii-Chiese
├─modelsave
| ├─cofig.jso
| ├─cofiguratiochatmodel.py
| ├─geeratiocofig.jso
| ├─model.safetesors
| ├─modeligchatmodel.py
| ├─specialtokesmap.jso
| ├─tokeizer.jso
| └─tokeizer_cofig.jso bash
pytho cli_demo.py bash
pytho api_demo.py bash
curl --locatio '127.0.0.1:8812/api/chat' \
--header 'Cotet-Type: applicatio/jso' \
--header 'Authorizatio: Bearer Bearer' \
--data '{
"iput_txt": "感冒了要怎么办"
}' jso
{
"prompt": "请抽取出给定句子中的所有三元组。给定句子:《家乡的月亮》是宋雪莱演唱的一首歌曲,所属专辑是《久违的哥们》",
"respose": "[(家乡的月亮,歌手,宋雪莱),(家乡的月亮,所属专辑,久违的哥们)]"
} cof
@misc{Charet2023,
author={Charet Che},
title={A small chiese chat laguage model with 0.2B parameters base o T5},
year={2023},
publisher = {GitHub},
joural = {GitHub repository},
howpublished = {\url{https://github.com/charet/ChatLM-mii-Chiese}},
}
``` 本项目不承担开源模型和代码导致的数据安全、舆情风险或发生任何模型被误导、滥用、传播、不当利用而产生的风险和责任。一、?介绍
batch_size=1,fp16或者bf16),float16加载、推理最少只需要512MB显存。
HuggigfaceNLP框架,包括trasformers、accelerate、trl、peft等。traier,支持单机单卡、单机多卡进行预训练、SFT微调。训练过程中支持在任意位置停止,及在任意位置继续训练。Text-to-Text预训练,非mask掩码预测预训练。
setecepiece、huggigface tokeizers的tokeizer训练;batch_size=1, max_le=320下,最低支持在16GB内存+4GB显存的机器上进行预训练;
traier支持prompt指令微调, 支持任意断点继续训练;Huggigface traier的sequece to sequece微调;
peft lora进行偏好优化;Lora adapter合并到原始模型中。 2024-01-30
sapshot_dowload快速下载。
2024-01-07
DropDatasetDuplicate类实现对大数据集的文档去重。
2023-12-29
AutoModelForSeq2SeqLM.from_pretraied(...)加载模型使用。
2023-12-18
ChatLM-mii-0.2B模型微调下游三元组信息抽取任务代码及抽取效果展示 。
2023-12-14
tokeizer为PreTraiedTokeizerFast。 dataset代码,支持动态最大长度,每个批次的最大长度由该批次的最长文本决定,节省显存。 tokeizer训练细节。
2023-12-04
geerate参数及模型效果展示。
2023-11-28
2023-10-19
二、?️ChatLM-0.2B-Chiese模型训练过程
2.1 预训练数据集
utils/raw_data_process.py。主要数据集包括:
Belle_ope_source_1M、trai_2M_CN、及trai_3.5M_CN中部分回答较短、不含复杂表格结构、翻译任务(没做英文词表)的数据,共370万行,清洗后剩余338万行。N个词为回答,使用202309的百科数据,清洗后剩余119万的词条提示语和回答。Wiki下载:zhwiki,将下载的bz2文件转换为wiki.txt参考:WikiExtractor。 2.2 模型
T5-base:ecoder layer和decoder layer均为为12层,本项目这两个参数修改为10层。 2.3 训练过程
# 预训练阶段:
CPU: 28 vCPU Itel(R) Xeo(R) Gold 6330 CPU @ 2.00GHz
内存:60 GB
显卡:RTX A5000(24GB) * 2
# sft及dpo阶段:
CPU: Itel(R) i5-13600k @ 5.1GHz
内存:32 GB
显卡:NVIDIA GeForce RTX 4060 Ti 16GB * 1
tokeizer训练库遇到大语料时存在OOM问题,故全量语料按照类似BPE的方法根据词频合并、构造词库,运行耗时半天。1e-4到5e-3的动态学习率,预训练时间为8天。训练损失:
belle指令训练数据集(指令和回答长度都在512以下),学习率为1e-7到5e-5的动态学习率,微调时间2天。微调损失:
chose文本,步骤2中SFT模型对数据集中的prompt做批量geerate,得到rejected文本,耗时1天,dpo全量偏好优化,学习率le-5,半精度fp16,共2个epoch,耗时3h。dpo损失:
2.4 对话效果展示
2.4.1 stream chat
huggigface trasformers的 TextIteratorStreamer实现流式对话,只支持greedy search,如果需要beam sample等其他生成方式,请将cli_demo.py的stream_chat参数修改为False。
2.4.2 对话展示
三、?使用说明
3.1 快速开始:
modelscope.sapshot_dowload从modelscope下载模型文件。from trasformers import AutoTokeizer, AutoModelForSeq2SeqLM
import torch
model_id = 'charet/ChatLM-mii-Chiese'
# 如果无法连接huggigface,打开以下两行代码的注释,将从modelscope下载模型文件,模型文件保存到'./model_save'目录
# from modelscope import sapshot_dowload
# model_id = sapshot_dowload(model_id, cache_dir='./model_save')
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
tokeizer = AutoTokeizer.from_pretraied(model_id)
model = AutoModelForSeq2SeqLM.from_pretraied(model_id, trust_remote_code=True).to(device)
txt = '如何评价Apple这家公司?'
ecode_ids = tokeizer([txt])
iput_ids, attetio_mask = torch.LogTesor(ecode_ids['iput_ids']), torch.LogTesor(ecode_ids['attetio_mask'])
outs = model.my_geerate(
iput_ids=iput_ids.to(device),
attetio_mask=attetio_mask.to(device),
max_seq_le=256,
search_type='beam',
)
outs_txt = tokeizer.batch_decode(outs.cpu().umpy(), skip_special_tokes=True, clea_up_tokeizatio_spaces=True)
prit(outs_txt[0])
Apple是一家专注于设计和用户体验的公司,其产品在设计上注重简约、流畅和功能性,而在用户体验方面则注重用户的反馈和使用体验。作为一家领先的科技公司,苹果公司一直致力于为用户提供最优质的产品和服务,不断推陈出新,不断创新和改进,以满足不断变化的市场需求。
在iPhoe、iPad和Mac等产品上,苹果公司一直保持着创新的态度,不断推出新的功能和设计,为用户提供更好的使用体验。在iPad上推出的iPad Pro和iPod touch等产品,也一直保持着优秀的用户体验。
此外,苹果公司还致力于开发和销售软件和服务,例如iTues、iCloud和App Store等,这些产品在市场上也获得了广泛的认可和好评。
总的来说,苹果公司在设计、用户体验和产品创新方面都做得非常出色,为用户带来了许多便利和惊喜。
3.2 从克隆仓库代码开始
TextToText模型,在预训练、SFT、RLFH阶段的prompt、respose等字段,请务必加上[EOS]序列结束标记。 3.2.1 克隆项目:
git cloe --depth 1 https://github.com/charet/ChatLM-mii-Chiese.git
cd ChatLM-mii-Chiese
3.2.2 安装依赖
pytho 3.10,过老的pytho版本可能不兼容所依赖的第三方库。 pip istall -r ./requiremets.txt
# pip 安装torch + cu118
pip3 istall torch --idex-url https://dowload.pytorch.org/whl/cu118
coda istall --yes --file ./requiremets.txt
3.2.3 下载预训练模型及模型配置文件
git命令从Huggig Face Hub下载模型权重及配置文件,需要先安装Git LFS,然后运行: 使用git命令下载huggigface模型,先安装[Git LFS],否则下载的模型文件不可用
如果无法连接huggigface,请从modelscope下载
也可以直接从`Huggig Face Hub`仓库[ChatLM-Chiese-0.2B](https://huggigface.co/charet/ChatLM-mii-Chiese)手工下载,将下载的文件移动到`model_save`目录下即可。
## 3.3 Tokeizer训练
原本打算直接用现成的`tokeizer`库训练的(如`setecepiece`),但是数据集一大就容易OOM。另外预训练数据集各个领域的语料不平衡,会产生很多不必要的合并。最后使用`jieba`分词对所有的预训练语料切词后统计词频,只保留出现1500次以上的字、词,参照`PreTraiedTokeizerFast`的`BPE model`的保存格式,构造`tokezier`,最后转换为`PreTraiedTokeizerFast`。核心代码如下,详细的处理过程见`utils/trai_tokeizer.py`。
**该方法不是严谨的merge方法,忽略了词频信息及有不该合并的词也合并了,是针对小于16G机器的折中办法,如果要做预训练,建议使用`trai_tokeizer.ipyb`的代码重新训练。**
构造merge数组
if a i words_dict ad b i words_dict:
words_merge_list.apped((a, b))
本项目还提供了使用预训练模型自带的`tokeizer`根据自己的语料重新训练`tokeizer`的例子,见`trai_tokeizer.ipyb`。注意,重新训练`tokeizer`后,预训练模型的权重将无法使用,需要重新训练模型权重,因为`toke`对应的`id`变了。
## 3.4 Text-to-Text 预训练
1. 预训练数据集示例
2. jupyter-lab 或者 jupyter otebook:
见文件`trai.ipyb`,推荐使用jupyter-lab,避免考虑与服务器断开后终端进程被杀的情况。
3. 控制台:
控制台训练需要考虑连接断开后进程被杀的,推荐使用进程守护工具`Supervisor`或者`scree`建立连接会话。
首先要配置`accelerate`,执行以下命令, 根据提示选择即可,参考`accelerate.yaml`,*注意:DeepSpeed在Widows安装比较麻烦*。
```bash
accelerate cofig
```
开始训练,如果要使用工程提供的配置请在下面的命令`accelerate lauch`后加上参数`--cofig_file ./accelerate.yaml`,*该配置按照单机2xGPU配置。*
*预训练有两个脚本,本项目实现的traier对应`trai.py`,huggigface实现的traier对应`pre_trai.py`,用哪个都可以,效果一致。本项目实现的traier训练信息展示更美观、更容易修改训练细节(如损失函数,日志记录等),均支持断点继续训练,本项目实现的traier支持在任意位置断点后继续训练,按`ctrl+c`退出脚本时会保存断点信息。*
单机单卡:
```bash
# 本项目实现的traier
accelerate lauch ./trai.py trai
# 或者使用 huggigface traier
pytho pre_trai.py
```
单机多卡:
`2`为显卡数量,请根据自己的实际情况修改。
```bash
# 本项目实现的traier
accelerate lauch --multi_gpu --um_processes 2 ./trai.py trai
# 或者使用 huggigface traier
accelerate lauch --multi_gpu --um_processes 2 pre_trai.py
```
从断点处继续训练:
```bash
# 本项目实现的traier
accelerate lauch --multi_gpu --um_processes 2 ./trai.py trai --is_keep_traiig=True
# 或者使用 huggigface traier
# 需要在`pre_trai.py`中的`trai`函数添加`resume_from_checkpoit=True`
accelerate lauch --multi_gpu --um_processes 2 pre_trai.py
```
## 3.5 SFT微调
SFT数据集全部来自[BELLE](https://github.com/LiajiaTech/BELLE)大佬的贡献,感谢。SFT数据集分别为:[geerated_chat_0.4M](https://huggigface.co/datasets/BelleGroup/geerated_chat_0.4M)、[trai_0.5M_CN](https://huggigface.co/datasets/BelleGroup/trai_0.5M_CN)和[trai_2M_CN](https://huggigface.co/datasets/BelleGroup/trai_2M_CN),清洗后剩余约137万行。
sft指令微调数据集示例:
参考`data`目录下的示例`parquet`文件制作自己的数据集,数据集格式:`parquet`文件分两列,一列`prompt`文本,表示提示语,一列`respose`文本,表示期待的模型输出。
微调细节见`model/traier.py`下的`trai`方法, `is_fietue`设置为`True`时,将进行微调,微调默认会冻结embeddig层和ecoder层,只训练decoder层。如需要冻结其他参数,请自行调整代码。
运行SFT微调:
本项目实现的traier, 添加参数
--is_fietue=True即可, 参数--is_keep_traiig=True可从任意断点处继续训练或者使用 huggigface traier, 多GPU请用accelerate lauch --multigpu --umprocesses gpu个数 sft_trai.py
## 3.6 RLHF(强化学习人类反馈优化方法)
偏好方法这里介绍常见的两种:PPO和DPO,具体实现请自行搜索论文及博客。
1. PPO方法(近似偏好优化,Proximal Policy Optimizatio)
步骤1:使用微调数据集做有监督微调(SFT, Supervised Fietuig)。
步骤2:使用偏好数据集(一个prompt至少包含2个回复,一个想要的回复,一个不想要的回复。多个回复可以按照分数排序,最想要的分数最高)训练奖励模型(RM, Reward Model)。可使用`peft`库快速搭建Lora奖励模型。
步骤3:利用RM对SFT模型进行有监督PPO训练,使得模型满足偏好。
2. 使用DPO(直接偏好优化,Direct Preferece Optimizatio)微调(**本项目采用DPO微调方法,比较节省显存**)
在获得SFT模型的基础上,无需训练奖励模型,取得正向回答(chose)和负向回答(rejected)即可开始微调。微调的`chose`文本来自原数据集[alpaca-gpt4-data-zh](https://huggigface.co/datasets/c-s-ale/alpaca-gpt4-data-zh),拒绝文本`rejected`来自SFT微调1个epoch后的模型输出,另外两个数据集:[huozi_rlhf_data_jso](https://huggigface.co/datasets/Skepsu/huozi_rlhf_data_jso)和[rlhf-reward-sigle-roud-tras_chiese](https://huggigface.co/datasets/beyod/rlhf-reward-sigle-roud-tras_chiese),合并后共8万条dpo数据。
dpo数据集处理过程见`utils/dpo_data_process.py`。
DPO偏好优化数据集示例:
运行偏好优化:
多GPU请用accelerate lauch --multigpu --umprocesses gpu个数 dpo_trai.py
## 3.7 推理
确保`model_save`目录下有以下文件,这些文件都可以在`Huggig Face Hub`仓库[ChatLM-Chiese-0.2B](https://huggigface.co/charet/ChatLM-mii-Chiese)中找到:
1. 控制台运行:
2. API调用
API调用示例:

## 3.8 下游任务微调
这里以文本中三元组信息为例,做下游微调。该任务的传统深度学习抽取方法见仓库[pytorch_IE_model](https://github.com/charet/pytorch_IE_model)。抽取出一段文本中所有的三元组,如句子`《写生随笔》是冶金工业2006年出版的图书,作者是张来亮`,抽取出三元组`(写生随笔,作者,张来亮)`和`(写生随笔,出版社,冶金工业)`。
原始数据集为:[百度三元组抽取数据集](https://aistudio.baidu.com/datasetdetail/11384)。加工得到的微调数据集格式示例:
可以直接使用`sft_trai.py`脚本进行微调,脚本[fietue_IE_task.ipyb](./fietue_examples/ifo_extract/fietue_IE_task.ipyb)里面包含详细的解码过程。训练数据集约`17000`条,学习率`5e-5`,训练epoch`5`。微调后其他任务的对话能力也没有消失。

微调效果:
将`百度三元组抽取数据集`公开的`dev`数据集作为测试集,对比传统方法[pytorch_IE_model](https://github.com/charet/pytorch_IE_model)。
| 模型 | F1分数 | 精确率P | 召回率R |
| :--- | :----: | :---: | :---: |
| ChatLM-Chiese-0.2B微调 | 0.74 | 0.75 | 0.73 |
| ChatLM-Chiese-0.2B无预训练| 0.51 | 0.53 | 0.49 |
| 传统深度学习方法 | 0.80 | 0.79 | 80.1 |
备注:`ChatLM-Chiese-0.2B无预训练`指直接初始化随机参数,开始训练,学习率`1e-4`,其他参数和微调一致。
# 四、?引用
如果你觉得本项目对你有所帮助,欢迎引用。
五、?其他事项
点击空白处退出提示







评论