从0开始预训练1.4b中文大模型实践

00542c21db794b97dcd9847b1025ed26.png

作者:Lil2J@知乎(已授权)

链接:https://zhuanlan.zhihu.com/p/684946331

简介

这篇文章主要记录了我个人对1.4b中文大模型的实践复现过程。我选择了QWEN作为基座模型,并训练了一个参数量达到1.4b的预训练模型,其中涉及的训练token数量约为8b。在此过程中,我使用了两张a100 80g显卡,并耗费了大约100个小时的训练时间。尽管这个规模无法与其他大型模型相媲美,但我也取得了一定的效果。因此,我想将这次实践的过程和技术细节分享给大家,希望能够为感兴趣的朋友们提供一些参考和帮助。

这次项目:

https://github.com/jiahe7ay/MINI_LLM

因为实在不知道取什么名字,就取了个miniLLM了。

动机

我做这次实践纪录的动机主要如下:

1.在阅读了Allen实验室发布的关于OLMO模型的技术报告后,我深受启发。他们不仅详细介绍了模型的训练细节,还大方地开源了整套大模型构建的代码,涵盖了数据处理、训练、评估等各个环节。这种开源精神让我深感敬佩,我也想为开源尽自己的一份薄力。

2.其实自己尝试预训练一个大模型,这是我一直以来都非常想尝试做的事情,由于对自己的能力和所拥有的资源持有疑虑,我一直未能付诸实践。然而,机缘巧合之下,我在github上看到了这两个项目:

1.baby-llama2-chinese

2.Phi2-mini-Chinese

在深入研究了上述两个项目后,我深受启发,意识到个人尝试复现一个大模型是完全可行的。因此,我决定基于这两个项目的成功经验,结合我自身的需求,更换它们所使用的模型和训练数据集。通过这一尝试,我希望能够训练出属于我自己的“大模型”。通过这样的实践,我能够更深入地理解预训练模型的工作原理,并为我未来的研究和工作积累宝贵的经验。

3.随着技术的不断发展和资源的日益丰富,越来越多的大厂开始关注参数量相对较小的大模型,如qwen-0.5b和phi-2b等。这一趋势让我意识到,在未来,参数量相对较小的大模型可能会在大模型领域中占据一席之地。

相较于庞大的模型,参数量相对较小的大模型具有更低的计算需求、更快的训练速度和更少的资源消耗。这使得更多的个人和团队能够参与到大模型的训练和应用中,推动了技术的普及和发展。同时,这类模型也在某些特定任务上展现出了不俗的性能,证明了其在实际应用中的价值。

总的来说,我个人非常看好参数量相对较小的大模型的发展前景。

细节

模型基座的选择

在我的项目中,我选择了QWEN作为基座模型,并将其配置扩展至1.4b参数规模。具体的修改细节,您可以在我的项目中的模型config文件中找到。我主要调整了模型的注意力头数和层数,以适应我现有的算力资源。当然,每位研究者都可以根据自己的需求和资源情况来进行相应的调整。

选择QWEN模型的原因在于,我认为它是一个成熟且稳定的中文开源大模型。此外,我注意到其他大模型复现项目通常都会自行训练tokenizer,但考虑到我个人并不希望在这一步骤上花费过多时间和精力,我决定从现有的开源项目中选取一个tokenizer。经过对比不同项目的tokenizer的压缩率和训练规模,我发现QWEN的tokenizer表现优异,因此我最终选择使用它,并决定整个模型也采用QWEN。毕竟,我的目标主要是进行复现实践,而非创造出一个新的模型。

训练数据的选择

1.wikipedia-cn-20230720-filtered:本数据集基于中文维基2023年7月20日的dump存档。作为一项以数据为中心的工作,本数据集仅保留了质量较254,547条高的词条内容。

2.中文BaiduBaiKe的数据

3.天工150b中文预训练数据集:因为算力资源限制,我只下载了前20个文件

4.bell数据集:使用了这数据集中的2M,0.5M和1M作为sft的训练数据集

训练集构造

在数据预处理阶段,我遵循了QWEN的通用做法,即在每个文章的末尾加上一个特定的结束符号“<|im_end|>”。这个符号的作用在于清晰地界定单篇文章的边界,确保模型在训练时能够准确地识别出文章的结束位置,从而与下一个文章进行区分。

此外,考虑到模型训练对输入序列长度的限制,如果文章长度超过了这一限制,我会进行截断处理。具体来说,我会将超长的文章截断至规定长度,并将截断的部分作为下一个样本。这样做不仅保证了模型输入的合规性,同时也充分利用了原始数据,避免了信息的浪费。

这种数据预处理方式既遵循了行业内的常见做法,又考虑到了模型训练的实际需求,有助于提升模型的训练效果和泛化能力。

环境

如果安装了flash-attn的话,训练速度大概能提升20%,但是我发现这个flash-attn越来越不好装了。

具体的requirements如下:

datasets
transformers==4.36.0
torch==2.2.0
accelerate==0.27.2
einops==0.7.0
flash-attn==2.5.5
tiktoken
einops

训练参数

预训练参数如下:

per_device_train_batch_size=24,
    per_device_eval_batch_size=4,
    gradient_accumulation_steps=10,
    num_train_epochs=1,
    weight_decay=0.1,
    ddp_find_unused_parameters=False,
    warmup_steps=0,
    learning_rate=1e-4,
    evaluation_strategy='steps',
    eval_steps=100,
    save_steps=50,
    save_strategy='steps',
    save_total_limit=4,
    report_to='tensorboard',
    optim="adamw_torch",
    lr_scheduler_type='cosine',
    bf16=True,
    logging_steps=20,
    log_level='info',
    logging_first_step=True,

sft训练参数

per_device_train_batch_size=32,
    gradient_accumulation_steps=2,
    num_train_epochs=3,
    weight_decay=0.1,
    warmup_steps=0,
    learning_rate=6e-5,
    ddp_find_unused_parameters=False,
    evaluation_strategy='steps',
    eval_steps=500,
    save_steps=500,
    save_total_limit=3,
    report_to='tensorboard',
    optim="adamw_torch",
    remove_unused_columns=False,
    lr_scheduler_type='cosine',
    bf16=True,
    logging_steps=10,
    log_level='info',
    logging_first_step=True,

值得注意一点是:

1.多卡的话最好设置ddp_find_unused_parameters=False,这样也能提升训练的速度

2.尽可能地把单个bs调大,因为我试过把单个bs没有调那么大,通过使用累积梯度步数来增大总的bs,但是收敛的没有把单个bs调大快,我在想这个和学习率调整有关。

训练加速

使用了accelerate库来使用deepspeed来加速,只需要运行 accelerate launch --multi_gpu --config_file accelerate_multi_gpu.yaml xx.py即可

具体的配置如下:

compute_environment: LOCAL_MACHINE
debug: false
deepspeed_config:
  gradient_accumulation_steps: 10
  gradient_clipping: 1.0
  offload_optimizer_device: cpu
  offload_param_device: cpu
  zero3_init_flag: false
  zero3_save_16bit_model: false
  zero_stage: 2
distributed_type: DEEPSPEED
downcast_bf16: 'no'
machine_rank: 0
main_training_function: main
mixed_precision: bf16
num_machines: 1
num_processes: 2
rdzv_backend: static
same_network: true
tpu_env: []
tpu_use_cluster: false
tpu_use_sudo: false
use_cpu: false

启动训练

4e0a588ff5ce73ea8d3b3a9eb4c11112.jpeg

训练的是天工数据集前10个文件

a4f855ac8304791620810b1621f592d4.jpeg

占用的显存

训练结果

预训练loss

我首先预训练的数据集是维基百科加百度百科,然后把checkpoint权重保存下来

709db307dadb3d0b6b7c964288ba3114.jpeg

loss是维基百科加Baidu

接着上次预训练的权重,继续预训练。

ccb152fe8d83fb119266f033928a1705.jpeg

loss是天工前20个数据集

sft训练loss

4428c91acf42fd6a8fb7171af8435d26.jpeg

sft训练的loss

其实通过上面这几个Loss图,就能看出大模型的训练都遵循scaling law的原则,图的走向基本都是那样的,所以这次实践让我更深一步体会到了大模型 scaling law的威力。

模型效果

1.简单的问好

8641dec8dd3e6b75ca57c19353316ecd.jpeg

能回答问候

2.一些通识类的问题

乔布斯的问题基本能回答对80%了,但乔布斯不是在攻读博士的期间开始创业的,还是会有幻觉的问题。苹果公司的基本回答无误了。在介绍广州这个问题上,还是会有重复回答的问题,出现了两个广州塔

67f0ba412fc071e8b21ea79cba2efbec.png

ec90a3c65ff612f4cc797f2c235ab129.jpeg

3.模型有分辨问题并进行准确回答的能力

这四个问题它都回答正确了

dfe826f5e5ed00e47e651ad50bc75353.jpeg

分辨问题
91549af4cc4e7972048fbdb4eb630077.jpeg

4.尝试使用它来写一下代码

首先让它写一个排序算法,它用文字给出了思路,可以看出它给出的是思路是冒泡排序,如果不细看感觉对了,但是仔细看第2步中的“继续比较下一个值和最后一个值”,这个最后一个值是不是多余了,还是差了一点点才能回答正确

然后再让它使用python写一个排序算法,好家伙,直接化身调包侠哈哈哈哈哈。但是它关于这个代码的注释还是有些地方写错了,比如第一个注释说将排序后的结果储存在新的列表中,代码中并没有。第二个注释中的列表名字说错了。

7cb38cb12c93574eb7ed810dfd6b2ce0.jpeg

排序算法

3fceeb1dc1e9a902ea66128400bcbfc5.jpeg

使用python写排序算法

5.尝试写一下文案

这一部分倒是写的有模有样的。

e0f3f03d0cc44b46f4cb364155a7ac88.jpeg 4d8df4b9aa42a8b0207b1ebad7913c48.jpeg

总结

这次实践从准备到完成大约花费了我一个月的时间。虽然整个项目的代码量并不算大,但其中的过程确实充满了挑战和艰辛。作为一个独立完成的项目,我遇到了各种各样的问题和报错,需要逐一排查和解决。这其中的艰辛,只有真正做过的人才能深刻体会到。

然而,正是这些挑战和困难,让我更加深刻地体会到了做模型的乐趣。每一次解决问题,每一次看到模型性能的提升,都像是在玩游戏一样,带给我独特的成就感和快感。这种乐趣不仅来自于技术的挑战,更来自于对知识的探索和应用的满足感。

未来,我还会继续尝试训练更多的模型和数据,希望能够为中文大模型的开源社区贡献自己的一份力量。

最后,我要感谢所有能够看到这里的朋友们。谢谢你们!

QA

Q:为什么没有使用强化学习

A:其实我是有试过DPO去做强化学习的,但是效果不甚理想,知识遗忘的会比较厉害,不知道是我训练数据的问题还是方法的问题,但是后面会继续尝试强化学习去优化模型。

Q:项目的后续是?

A:有可能会继续增加数据规模继续训练,或者转向尝试训练一个Moe模型

Q:为什么没有尝试C-EVAL的评测

A:我现在觉得这个模型还是太弱鸡了,等后续能力强一点再去尝试一下。


备注:昵称-学校/公司-方向/会议(eg.ACL),进入技术/投稿群

450567c4642340709926820120e98722.png

id:DLNLPer,记得备注呦

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值