不久前,面壁 MiniCPM 的发布引发了开源社区的热烈讨论。它以 2B 规模、1T tokens,就能和来自「欧洲版 OpenAI」的 Mistral-7B 一较高下。这颗超级能打的「小钢炮」如何做到以小博大?
2月25日,微信大模型团队成员王焱同学邀请 MiniCPM 作者内部做了一个小范围分享,探讨面壁 MiniCPM 的预训练奥秘。
文章原载于:
https://zhuanlan.zhihu.com/p/686664720
根据 scaling law,模型越大,高质量数据越多,效果越好。
但还有一个很直观的情况,随着预训练样本的质量不断提升,训练手段的优化。新的模型,往往效果能轻松反超参数量两倍于它的模型。
例如,最新出的 MiniCPM,微信内部评测效果也是非常棒的。跟规模相对接近的 2B、7B 模型比,得分比 Qwen-2B 高,和 Qwen-7B 比有的高有的低。
这个是 MiniCPM 的详细技术文档:
https://shengdinghu.notion.site/MiniCPM-c805a17c5c8046398914e47f0542095a
这说明,现有参数量情况下,哪怕是 2B 尺度,也并没有得到充分训练。
近期,邀请 MiniCPM 作者内部做了一个小范围分享,参与人员有国内好几个大模型团队的成员,基本上都是预训练为主。
样本构成
大家已经达成一些基础的共识。
如中英混合比例大家都大差不差。
逻辑推理比较强的样本,像代码,数学。这种就是模型越大,混合的比例反而可以越高。
跟 SFT 是类似的,越大的模型,越聪明的模型,需要的 SFT 数据就越少。同理,越大的模型,越聪明,复杂样本混合比例就可以越高。
样本质量
1. 基本清洗
导致 ppl 崩掉的,都要清洗掉,政治敏感数据清洗,去重等,肯定是一个很长的 pipeline。
大家比较一致的结论是,天工开源的那份预训练数据,是一个比较好的满足基础清洗要求的数据。
2. 进阶清洗
大家都不太方便展开,但可以透露的信息。
跟 SFT 一样,产出各种各样的 label 来刻画数据,有的公司实习生就优化几个 label。
不过随着优化的往后拓展,这些 label 的投入产出比越来越难以评估。
3. PHI式的生成(synthetic)数据
预训练清洗的 pipeline 搭建,对于开源团队,小公司来讲,成本其实还是蛮高的。
所以,基于开源数据,做一些聚类的 topic。然后基于这些 topic,丢到更大的模型,来构建一批高质量的数据,是一个反而比较低成本的方案。
4. 买数据
嗯,这次大模型,除了李一舟。卖数据的公司,也是真的赚到钱了。
不同训练阶段的训练样本
经过讨论,发现有三种方案。
1. 末期高质量样本(MiniCPM)
快速收敛阶段和平稳阶段,都采用普通样本。
退火阶段,混入高质量样本来做教科书式的学习。
2. 初期高质量样本
快速收敛阶段,以高质量样本为主,让模型快速收敛。
平稳阶段,逐步调整比例,增加更多的普通样本。
退火阶段,跟平稳阶段一致
3. 全程高质量样本( PHIL 方式)
全程都是高质量样本
这里大家讨论的蛮激烈的,有这么几点。
第一,初期就加入高质量样本,初期收敛的更快。但高质量样本少,不断的重复学习高质量样本,会不会导致过拟合?但反方认为,人类的本质上就是复读机,特别对于小模型,不断的重复学习,好像也没太大问题。
第二,初期学习高质量样本,会不会导致初期模型的初始化,局限在特定的区域,后面的普通样本学了之后,也不一定能很好的跳出来,会不会影响泛化?但反方认为,末期加入高质量样本,反而会不会因为最后加入高质量样本,导致泛化能力受损,集中在高质量样本的领域?
第三,PHIL 方式,大家很快达成一致,PHIL 就是探索小模型能不能在特定领域达到 SOTA。好处,特定榜单/领域效果会特别好。坏处,模型泛化能力会很差,但 PHIL从来没说要做世界模型。
小模型样本的极限在哪?
到底喂了多少 tokens,小模型参数才算是充分得到训练?
当天讨论,并没有一个很好的结论。
最近 Yi-9B 的公开技术文档,做了一个有趣的尝试。把每层的输入和输出算 cos,来评估模型是否训练的非常充分。
但内部讨论后,发现这种尝试有一个巨大的遗漏点。
前段时间,我们做 long context 调研,也是把每层也都单独做了一个分析。结论是,如果模型深度足够的话,有些层其实区分度是在降低的,相当于几层做了一层做的事情。
以及,另外一个可能,小模型每一层 cos 都小,有可能每一层在干不同的事,或者每一层都会注意到新的东西。大模型某些层 cos 大,有可能是因为句子太简单,大模型对结果更加肯定,靠后的层的功能没有被激活。
感觉这种评估方式,仍旧有一定的优化空间,也期待业内能公开更多好用的评估方式。
tokenizer
小模型过大的 tokenizer 的确是一种浪费。很多小模型有大 tokenizer,一个潜在的可能性,作者人力不足,直接是把大模型的 tokenizer 拿来复用了。
阶段
现在大家预训练分成三个阶段。
快速收敛阶段,稳定阶段,退火阶段(MiniCPM 比较显式的提出这个阶段)
1. 为什么要分阶段
这个阶段来自于大家对 loss 曲线的观察,发现 loss 曲线的收敛就是这么一个特点。
然后,大家发现不同的 loss 曲线阶段,做一些针对性样本和参数的调整,能带来更好的效果,于是就这么分了。
2. 不同阶段学的是什么东西?
首先,我们现在的评估手段还是比较粗糙的,假如有了更细的评估手段,可能能观测到更多有趣的东西。
例如之前俊林做过关于涌现的分享,涌现从指标观测来看,就是突然出现的。但当把指标细化后,可以发现这个涌现好像也没那么突然,这个可以参考 https://arxiv.org/abs/2310.03262 把原本离散的准确率在 1e-5 级别的时候的值估计出来了。
但反方这里又有不同的观点,我们用物理学的一个理论来解释涌现。
我们可以把涌现替换成相变来聊一聊它和指标突变的辩证关系:当我们谈论相变时,我们指的是物质从一种状态转变为另一种状态的过程,比如水从液态变成固态的过程(冰冻)或者从液态变成气态的过程(蒸发)。而指标突变通常指的是某种性质或者物理量在某个条件下突然发生明显的变化,比如在某个温度或者压力下,某种物质的导电性、磁性或者其他性质突然发生变化。
相变与指标突变之间存在着密切的关系,因为相变往往伴随着物质性质的突变。当物质经历相变时,它的一些性质会突然改变,这些性质就是我们所说的指标。举个例子,当水温降到 0 摄氏度以下时,水会由液态变成固态,这就是相变,同时水的密度也会突然增加,导致它的体积变小,这就是指标突变。
虽然相变往往伴随着物质性质的指标突破,但是不意味着不突变就不是相变,指标的突变不是相变的重点,相变的重点在于从一个状态/性质,变成另外一个状态/性质,这两种状态有着很不一样的差别。
尽管可以使用一些技巧方法来构造一些看起来特别平滑的指标来反对大模型涌现这个词汇,但是不可否认的事实是,在不同的尺寸变化或者数据量、计算量变化之后,人们可以非常明显地感知到大模型表现的巨大差异,这就是一个相变的结果,就像是炼制一门 18 连环刃的法器,从第一把的炼制到第18 把,从个数的指标上来说是非常平滑的,但是从威力上来说,18 把可以构建一个法阵,极大地增加了武器的威力,与之前不可同日而语。
batch size
老调重弹的问题。
2020 年,transformer 出来后,当时大家就碰到这么一个问题。模型太大了,用尽可能能塞进内存的 batch size 去 train 模型,来提升速度。
很快,大家发现 batch size 有个 trade off。
batch size 过小,波动会比较大,不太容易收敛。但这种波峰,也有助于跳出局部最优,模型更容易有更好的泛化能力。
batch size 变大,步数整体变少,训练的步数更少,本来就波动就小,步数也少,同样本的情况下,你收敛的会更慢。
2020 年其实有人就研究,如何用大 batch size,更快的训练的同时,也能收敛的更好。一个解决思路是优化了优化器,例如谷歌当年出的 LAMB,就把 batch size 从 512 扩充到了 6w,收敛效果也不错。
LR scheduler
机器学习的目标,都是为了收敛 loss,让学习的 target 和我们预测的 target 的 loss 尽可能低。
学习的过程,就是基于样本,分批(batch size)丢进去。根据过去,现在学习的效果,来决定参数更新的方向和大小。
batch size 这里是很清晰的。比较纠结的点是,优化器和 LR scheduler 这俩好像边界不是很清晰。
1. LR scheduler 是什么
假如我们要下山,山脚就是我们的目标,learning rate 就是我们每一步要走多远。如果速度太快,可能开到山脚后,发现刹不住车,还会往山上多开一会,于是这样反复在目标处来回震荡。如果太小的话,到山脚的速度又太慢了。
现在主流的就是 cosine,初期 warmup learning rate 线性增长,然后 learning rate 就是以余弦函数的周期方式周期性变换。
2. 优化器做什么?
优化器核心要解决的问题,初期怎么更好的学,那些地方要加速学,那些地方容易陷入局部最优,要如何跳出来。
现在的主流做法都是基于历史的反馈。
类似于爬山,某个地方你发现爬的很慢,那么就加下油门。有的地方你发现是下坡路,跑的贼快,那就就要松下油门,免得油门太快,直接从主路跑出去了。
从 momentum,到 adagrad,再到 adam,这两年还有人在各种折腾。
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 像是一个全局的油门,定期更新,帮助老司机跳出局部最优。
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。
退火加 sft &“和面”
前段时间,业界流行一个说法,你发现某块效果差,在预训练最后阶段补充一些类似的数据,效果就会蹭蹭的往上涨。
简称,和面——水多了加面,面多了加水。
刚开始,大家都很鄙视这种行为,觉得这种行为不就是刷榜么?
但现在我们来探讨这块的合理性,MiniCPM 可以算是更进一步的“作弊”了,如果按照之前的观点。他都直接把 SFT 数据混入了预训练数据里面,更加明目张胆的“刷榜”。
王焱个人觉得这里可以用两个角度去理解:
角度一,模型学习的训练动态角度,在退火的时候 loss 下降较 stable 和正常的 cosine 都要快,证明这里的学习效率在提升(最聪明的时候?),而此时在这一刻使用高质量数据来喂给模型, 可以尽可能发挥高质量数据的作用;
角度二, SFT 数据较正常的文本数据, 王焱猜测会更偏向于 benchmark 一些,因为 SFT 很多都是" QA 型"结构的数据, 对于模型认识 bechmark 有一定的改善。
之前预训练完毕后,直接上 SFT 数据,语料分布差距很大,其实天然是不太好的。这种作弊的行为,只要控制样本比例得当,反而能保证后面通用对其的一致性。
随着一些 common sense 的建立,scaling law 的指导意义的确是在不断下降的。
举个例子,假如我有 300 张卡,我要 train 多大的模型?
计算方式,往往就变成,我大致知道训练 1T-2T tokens 效果往往就不错了,这个模型两个月后我想赶一个发布会。那么就来反推,1T 的 tokens 训练 2 个月,300 张卡能 train 多大的。
但我们回到 2020 年,当大部分人都在基于 bert 做各种魔改的时候。
OpenAI 发现了这么一个规律。数据,训练,参数一直增长下去,好像 loss 的确是在不断的下降哎?
于是,他们拿着这个 paper 去问微软的 CTO,你想不想看看这个 loss 下降到一定程度会发生什么?
会发生什么?
ChatGPT 就出来了
➤ 加社群/ 提建议/ 有疑问
请找 OpenBMB 万能小助手:
官方网站
https://www.openbmb.org
GitHub
https://github.com/OpenBMB
https://github.com/thunlp
长期开放招聘|含实习
开发岗 | 算法岗 | 产品岗
交流QQ群
735930538