AI 文摘

如何从零开始训练大模型(minicpm分享&讨论)





作者: 吃果冻不吐果冻皮 来源: 吃果冻不吐果冻皮

####**【点击】加入大模型技术交流群**

原文:https://zhuanlan.zhihu.com/p/686664720

1. 背景

根据scaling law,模型越大,高质量数据越多,效果越好。

但还有一个很直观的情况,随着预训练样本的质量不断提升,训练手段的优化。新的模型,往往效果能轻松反超参数量两倍于它的模型。

例如,最新出的minicpm,微信内部评测效果也是非常棒的。跟规模相对接近的2b、7b模型比,得分比qwen2b高,和qwen7b比有的高有的低。

这个是minicpm的详细技术文档:

https://shengdinghu.notion.site/MiniCPM-c805a17c5c8046398914e47f0542095a

这说明,现有参数量情况下,哪怕是2B尺度,也并没有得到充分训练。

近期,邀请minicpm作者内部做了一个小范围分享,参与人员有国内好几个大模型团队的成员,基本上都是预训练为主。

很多人都签了保密协议,所以都是基于公开信息沟通。

提前约法三章,对面拒绝回答,就不要做一些比较不知趣的追问操作。

限制很多,但也得到了一些有趣的结论。

因为都是基于公开信息的讨论,放出来也无伤大雅,也欢迎大家的反馈。

参会人, 鼎叮, @swtheking(知乎), @孙培钦(知乎) ,殷超,晓楠, @孔某人(知乎)。还有一些不方便挂名的,这里就不写了。

2. 样本

2.1 样本构成

大家已经达成一些基础的共识。

如中英混合比例大家都大差不差。

逻辑推理比较强的样本,像代码,数学。这种就是模型越大,混合的比例反而可以越高。

跟SFT是类似的,越大的模型,越聪明的模型,需要的SFT数据就越少。同理,越大的模型,越聪明,复杂样本混合比例就可以越高。

2.2 样本质量

2.1.1 基本清洗

导致ppl崩掉的,都要清洗掉,政治敏感数据清洗,去重等,肯定是一个很长的pipeline。

大家比较一致的结论是,天工开源的那份预训练数据,是一个比较好的满足基础清洗要求的数据。

2.1.2 进阶清洗

大家都不太方便展开,但可以透露的信息。

跟SFT一样,产出各种各样的label来刻画数据,有的公司实习生就优化几个label。

不过随着优化的往后拓展,这些label的投入产出比越来越难以评估。

2.1.3 PHI式的生成(synthetic)数据

预训练清洗的pipeline搭建,对于开源团队,小公司来讲,成本其实还是蛮高的。

所以,基于开源数据,做一些聚类的topic。然后基于这些topic,丢到更大的模型,来构建一批高质量的数据,是一个反而比较低成本的方案。

2.1.4 买数据

嗯,这次大模型,除了李一舟。卖数据的公司,也是真的赚到钱了。

2.3 不同训练阶段的训练样本

经过讨论,发现有三种方案。

2.3.1 末期高质量样本(minicpm)

快速收敛阶段和平稳阶段,都采用普通样本。

退火阶段,混入高质量样本来做教科书式的学习。

2.3.2 初期高质量样本

快速收敛阶段,以高质量样本为主,让模型快速收敛。

平稳阶段,逐步调整比例,增加更多的普通样本。

退火阶段,跟平稳阶段一致

2.3.3全程高质量样本(PHIL方式)

全程都是高质量样本

这里大家讨论的蛮激烈的,有这么几点。

第一,初期就加入高质量样本,初期收敛的更快。但高质量样本少,不断的重复学习高质量样本,会不会导致过拟合?但反方认为,人类的本质上就是复读机,特别对于小模型,不断的重复学习,好像也没太大问题。

第二,初期学习高质量样本,会不会导致初期模型的初始化,局限在特定的区域,后面的普通样本学了之后,也不一定能很好的跳出来,会不会影响泛化?但反方认为,末期加入高质量样本,反而会不会因为最后加入高质量样本,导致泛化能力受损,集中在高质量样本的领域?

第三,PHIL方式,大家很快达成一致,PHIL就是探索小模型能不能在特定领域达到SOTA。好处,特定榜单/领域效果会特别好。坏处,模型泛化能力会很差 (但PHIL从来没说要做世界模型。

2.4 小模型样本的极限在哪?

到底喂了多少tokens,小模型参数才算是充分得到训练?

当天讨论,并没有一个很好的结论。

最近YI-9B的公开技术文档,做了一个有趣的尝试。把每层的输入和输出算cos,来评估模型是否训练的非常充分。

但内部讨论后,发现这种尝试有一个巨大的遗漏点。

前段时间,我们做long context调研,也是把每层也都单独做了一个分析。结论是,如果模型深度足够的话,有些层其实区分度是在降低的,相当于几层做了一层做的事情。

以及,**另外一个可能,小模型每一层cos都小,有可能每一层在干不同的事,或者每一层都会注意到新的东西。**大模型某些层cos大,有可能是因为句子太简单,大模型对结果更加肯定,靠后的层的功能没有被激活。

感觉这种评估方式,仍旧有一定的优化空间,也期待业内能公开更多好用的评估方式。

3. 训练

3.1 tokenizer

小模型过大的tokenizer的确是一种浪费。很多小模型有大tokenizer,一个潜在的可能性,作者人力不足,直接是把大模型的tokenizer拿来复用了。

3.2 阶段

现在大家预训练分成三个阶段。

快速收敛阶段,稳定阶段,退火阶段(minicpm比较显式的提出这个阶段)

3.2.1 为什么要分阶段

这个阶段来自于大家对loss曲线的观察,发现loss曲线的收敛就是这么一个特点。

然后,大家发现不同的loss曲线阶段,做一些针对性样本和参数的调整,能带来更好的效果,于是就这么分了。

3.2.2 不同阶段学的是什么东西?

首先,我们现在的评估手段还是比较粗糙的,假如有了更细的评估手段,可能能观测到更多有趣的东西。

例如之前俊林做过关于涌现的分享,涌现从指标观测来看,就是突然出现的。但当把指标细化后,可以发现这个涌现好像也没那么突然,这个可以参考https://arxiv.org/abs/2310.03262把原本离散的准确率在1e-5级别的时候的值估计出来了。

但反方这里又有不同的观点,我们用物理学的一个理论来解释涌现。

我们可以把涌现替换成相变来聊一聊它和指标突变的辩证关系:当我们谈论相变时,我们指的是物质从一种状态转变为另一种状态的过程,比如水从液态变成固态的过程(冰冻)或者从液态变成气态的过程(蒸发)。而指标突变通常指的是某种性质或者物理量在某个条件下突然发生明显的变化,比如在某个温度或者压力下,某种物质的导电性、磁性或者其他性质突然发生变化。

相变与指标突变之间存在着密切的关系,因为相变往往伴随着物质性质的突变。当物质经历相变时,它的一些性质会突然改变,这些性质就是我们所说的指标。举个例子,当水温降到0摄氏度以下时,水会由液态变成固态,这就是相变,同时水的密度也会突然增加,导致它的体积变小,这就是指标突变。

虽然相变往往伴随着物质性质的指标突破,但是不意味着不突变就不是相变,指标的突变不是相变的重点,相变的重点在于从一个状态/性质,变成另外一个状态/性质,这两种状态有着很不一样的差别。

尽管可以使用一些技巧方法来构造一些看起来特别平滑的指标来反对大模型涌现这个词汇,但是不可否认的事实是,在不同的尺寸变化或者数据量、计算量变化之后,人们可以非常明显地感知到大模型表现的巨大差异, 这就是一个相变的结果,就像是炼制一门18连环刃的法器,从第一把的炼制到第18把,从个数的指标上来说是非常平滑的,但是从威力上来说,18把可以构建一个法阵,极大地增加了武器的威力,与之前不可同日而语。

3.3 batch size

老调重弹的问题。

transformer出来后,当时大家就碰到这么一个问题。模型太大了,用尽可能能塞进内存的batch size去train模型,来提升速度。

很快,大家发现batch size有个trade off。

batch size过小,波动会比较大,不太容易收敛。但这种波峰,也有助于跳出局部最优,模型更容易有更好的泛化能力。

batch size变大,步数整体变少,训练的步数更少,本来就波动就小,步数也少,同样本的情况下,你收敛的会更慢。

2020年其实有人就研究,如何用大batch size,更快的训练的同时,也能收敛的更好。一个解决思路是优化了优化器, 例如谷歌当年出的LAMB,就把batch size从512扩充到了6w,收敛效果也不错。

3.4 LR scheduler

机器学习的目标,都是为了收敛loss,让学习的target和我们预测的target的loss尽可能低。

学习的过程,就是基于样本,分批(batch size)丢进去。根据过去,现在学习的效果,来决定参数更新的方向和大小。

batch size这里是很清晰的。比较纠结的点是,优化器和LR scheduler 这俩好像边界不是很清晰。

3.4.1 LR scheduler是什么

假如我们要下山,山脚就是我们的目标,learning rate就是我们每一步要走多远。如果速度太快,可能开到山脚后,发现刹不住车,还会往山上多开一会,于是这样反复在目标处来回震荡。如果太小的话,到山脚的速度又太慢了。

现在主流的就是cosine,初期warmup learning rate线性增长,然后learning rate就是以余弦函数的周期方式周期性变换。

3.4.2 优化器做什么?

优化器核心要解决的问题,初期怎么更好的学,那些地方要加速学,那些地方容易陷入局部最优,要如何跳出来。

现在的主流做法都是基于历史的反馈

类似于爬山,某个地方你发现爬的很慢,那么就加下油门。有的地方你发现是下坡路,跑的贼快,那就就要松下油门,免得油门太快,直接从主路跑出去了。

从momentum,到adagrad,再到adam,这两年还有人在各种折腾。

3.4.3 优化器和LR scheduler如何协同工作?

问题就来了,LR scheduler决定了learning rate的大小。优化器也会根据历史情况来自动调整。

这俩会不会冲突?

优化器的优点刚刚说了,但它的缺点就是无论优化器怎么说的高大上,它本质上还规则,是大家基于调参经验,或者一些假设,定的规则。

规则就很难完美适配所有任务,事实上2020年左右,大家就发现不同的任务上不同的优化器效果是不同的。例如当年的炼丹经验,计算机视觉优先使用SGD(with Momentum),NLP(特别是用Transformer)优先使用Adam,现在CV都上transformer了,那么就又切到了AdamW。

除此之外,还有一个learning rate decay的问题,但这个偏经验,并不一定完全solid!

用CIFAR或者ImageNet跑一跑常见的模型,就会发现,最后如果不把learning rate降低下去,loss很难收敛到一个很小的数字。

SGD和Adam的收敛性证明也都是要求learning rate最后会降到足够低的。但自适应优化器的学习率不会在训练中自动降到很低。

现在大模型预训练,大家其实最关注的就是这个loss的收敛效果。

这个时候,LR schedule的出现就是一个比较好的补充,能够补足优化器的一些问题。

所以,你可以理解为,现在我们没有一个完美的油门,所以搞了俩油门,互相辅助。

优化器是个老司机的油门,好用,但人类的经验是有局限性的,很容易陷入局部最优跑不出来。

LR schedule像是一个全局的油门,定期更新,帮助老司机跳出局部最优。

3.4.4 W-S-D的讨论和优化方案

minicpm提出了W-S-D LR scheduler,但stable阶段高learning rate,相当于把调节油门的压力全给到优化器了。

但S-D的确也有很多好处,例如我想train到什么时候就train到什么时候。

这里提出了一个解决思路,W-S-D 是不是可以改成,warm-cosine-stable-decay,cosine占据训练阶段大头,甚至多个余弦波段,余弦波段多了,如上文所说,是不是能更好的跳出局部最优?

快要结束训练的时候,把cosine的learning rate给升上去,走一段stable+decay。

3.5 退火加sft & “和面”

前段时间,业界流行一个说法,你发现某块效果差,在预训练最后阶段补充一些类似的数据,效果就会蹭蹭的往上涨。

简称,和面——水多了加面,面多了加水。

刚开始,大家都很鄙视这种行为,觉得这种行为不就是刷榜么?

但现在我们来探讨这块的合理性,minicpm可以算是更进一步的“作弊”了,如果按照之前的观点。他都直接把sft数据混入了预训练数据里面 ,更加明目张胆的“刷榜”。

我个人觉得这里可以用两个角度去理解:

角度一,模型学习的训练动态角度,在退火的时候loss下降较stable和正常的cosine都要快,证明这里的学习效率在提升(最聪明的时候?),而此时在这一刻使用高质量数据来喂给模型, 可以尽可能发挥高质量数据的作用;

角度二, SFT数据较正常的文本数据, 我猜测会更偏向于benchmark一些,因为SFT很多都是"QA型"结构的数据, 对于模型认识bechmark有一定的改善。

之前预训练完毕后,直接上SFT数据,语料分布差距很大,其实天然是不太好的。这种作弊的行为,只要控制样本比例得当,反而能保证后面通用对其的一致性。

4. 再看scaling law

随着一些common sense的建立,scaling law的指导意义的确是在不断下降的。

举个例子,假如我有300张卡,我要train多大的模型?

计算方式,往往就变成,我大致知道训练1T-2T tokens效果往往就不错了,这个模型两个月后我想赶一个发布会。那么就来反推,1T的tokens训练2个月,300张卡能train多大的。

但我们回到2020年,当大部分人都在基于bert做各种魔改的时候。

OpenAI发现了这么一个规律。数据,训练参数一直增长下去,好像loss的确是在不断的下降哎?

于是,他们拿着这个paper去问微软的CTO,你想不想看看这个loss下降到一定程度会发生什么?

会发生什么?

chatgpt就出来了

更多AI工具,参考Github-AiBard123国内AiBard123