LLM 从零开始训练大模型-预训练
当前,不少工作选择在一个较强的基座模型上进行微调,且通常效果不错(如:[alpaca]、[vicuna] 等)。
这种成功的前提在于:预训练模型和下游任务的差距不大,预训练模型中通常已经包含微调任务中所需要的知识。
但在实际情况中,我们通常会遇到一些问题,使得我们无法直接使用一些开源 backbone:
| 续写任务测试 | LLaMA | MPT |
|---|---|---|
| 杭州西湖是 | 杭州西湖是杭州的一个静静的一个游泳池,游泳池是杭州西湖的一个游泳池,游泳池是杭州西湖的一个游泳池,游泳池是杭州西湖的一个游泳池,� | 杭州西湖是中国最大的湖泊,是中国最大的湖泊,是中国最大的湖泊,是中国最大的湖泊,是中国最大的湖泊,是中国最大的湖泊,是中国最大的湖泊, |
| 琅琊榜的导演是 | 琅琊榜的导演是很多的人都不知道,因为他的父亲是一位杰作家,他的父亲的杰作家是一位杰作家, | 琅琊榜的导演是谁?Who are the directors of the Rolling Stone?琅琊榜的导演是谁?Who are the |
2. 专业知识不足:当我们需要一个专业领域的 LLM 时,预训练模型中的知识就尤为重要。由于大多数预训练模型都是在通用训练语料上进行学习,对于一些特殊领域(金融、法律等)中的概念和名词无法具备很好的理解。我们通常需要在训练语料中加入一些领域数据(如:[xuanyuan 2.0]),以帮助模型在指定领域内获得更好的效果。

轩辕 2.0(金融对话模型)论文中所提及的训练语料分布,其中 Financial Pretraining 为金融语料
基于上述原因,我们在进行 SFT 步骤之前,先来看看预训练任务是如何做的。
Tokenizer Training
在进行预训练之前,我们需要先选择一个预训练的模型基座。
一个较为普遍的问题是:大部分优秀的语言模型都没有进行充分的中文预训练,
因此,许多工作都尝试将在英语上表现比较优秀的模型用中文语料进行二次预训练,期望其能够将英语上的优秀能力迁移到中文任务中来。
已经有许多优秀的仓库做过这件事情,比如:[ Chinese-LLaMA-Alpaca]。
但在进行正式的训练之前,我们还有一步很重要的事情去做:词表扩充。
通俗来讲,tokenizer 的目的就是将一句话进行切词,并将切好词的列表喂给模型进行训练。
例如:
输入句子 >>> 你好世界
切词结果 >>> ['你', '好', '世', '界']
通常,tokenizer 有 2 种常用形式:WordPiece 和 BPE。
- WordPiece
WordPiece 很好理解,就是将所有的「常用字」和「常用词」都存到词表中,
当需要切词的时候就从词表里面查找即可。

bert-base-chinese tokenizer 可视化
上述图片来自可视化工具 [ tokenizer_viewer]。
如上图所示,大名鼎鼎的 BERT 就使用的这种切词法。
当我们输入句子:你好世界,
BERT 就会依次查找词表中对应的字,并将句子切成词的组合。

BERT 切词测试图
当遇到词表中不存在的字词时,tokenizer 会将其标记为特殊的字符 [UNK]:

Out of Vocabulary(OOV)情况
- Byte-level BPE(BBPE)
感谢评论区指正,有关 BBPE 的原理可以参考 [ 这里]。
WordPiece 的方式很有效,但当字词数目过于庞大时这个方式就有点难以实现了。
对于一些多语言模型来讲,要想穷举所有语言中的常用词(穷举不全会造成 OOV),
既费人力又费词表大小,为此,人们引入另一种方法:BBPE。
BPE 不是按照中文字词为最小单位,而是按照 unicode 编码 作为最小粒度。
对于中文来讲,一个汉字是由 3 个 unicode 编码组成的,
因为平时我们不会拆开来看(毕竟中文汉字是不可拆分的),所以我一开始对这个概念也不太熟悉。
我们来看看 LLaMA 的 tokenizer 对中文是如何进行 encode 的:

LLaMa tokenizer 中文测试
上述图片来自可视化工具 [ tokenizer_viewer]。
可以看到,「编码」两个字能够被正常切成 2 个字,
但「待」却被切成了 3 个 token,这里的每个 token 就是 1 个 unicode 编码。

LLaMA tokenizer 查找结果,「待」不在词表中,「编」「码」在词表中
通过 token 查找功能,我们可以发现「编」「码」在词表中,但「待」不在词表中。
但任何 1 个汉字都是可以由 unicode 表示(只是组合顺序不同),因此「待」就被切成了 3 个 token。
| BBPE 的优势 | 不会出现 OOV 的情况。不管是怎样的汉字,只要可以用 unicode 表示,就都会存在于词表中。 |
| BBPE 的劣势 | 模型训练起来将会更吃力一些。毕竟像「待」这样的汉字特定 unicode 组合其实是不需要模型学习的,但模型却需要通过学习来知道合法的 unicode 序列。 |
通常在模型训练不够充足的时候,模型会输出一些乱码(不合法的 unicode 序列):
游泳池是杭州西湖的一个游泳池,���
- 词表扩充
为了降低模型的训练难度,人们通常会考虑在原来的词表上进行「词表扩充」,
也就是将一些常见的汉字 token 手动添加到原来的 tokenizer 中,从而降低模型的训练难度。
我们对比 [Chinese-LLaMA] 和 [LLaMA] 之间的 tokenizer 的区别:

Chinese LLaMA 和 原始LLaMA 之间 tokenizer 的区别
上述图片来自可视化工具 [ tokenizer_viewer]。
我们可以发现:Chinese LLaMA 在原始 tokenizer 上新增了17953 个 tokens,且加入 token 的大部分为汉字。
而在 [BELLE] 中也有同样的做法:
在 120w 行中文文本上训练出一个 5w 规模的 token 集合,
并将这部分 token 集合与原来的 LLaMA 词表做合并,
最后再在 3.2B 的中文语料上对这部分新扩展的 token embedding 做二次预训练。
语言模型预训练
在扩充完 tokenizer 后,我们就可以开始正式进行模型的预训练步骤了。
Pretraining 的思路很简单,就是输入一堆文本,让模型做 Next Token Prediction 的任务,这个很好理解。
我们主要来讨论几种预训练过程中所用到的方法:数据源采样、数据预处理、模型结构。
- 数据源采样
在 [gpt3] 的训练过程中,存在多个训练数据源,论文中提到:对不同的数据源会选择不同采样比例:

GPT3 Paper Page-9
通过「数据源」采样的方式,能够缓解模型在训练的时候受到「数据集规模大小」的影响。
从上图中可以看到,相对较大的数据集(Common Crawl)会使用相对较大的采样比例(60%),
这个比例远远小于该数据集在整体数据集中所占的规模(410 / 499 = 82.1%),
因此,CC 数据集最终实际上只被训练了 0.44(0.6 / 0.82 * (300 / 499))个 epoch。
而对于规模比较小的数据集(Wikipedia),则将多被训练几次(3.4 个 epoch)。
这样一来就能使得模型不会太偏向于规模较大的数据集,从而失去对规模小但作用大的数据集上的学习信息。
- 数据预处理
数据预处理主要指如何将「文档」进行向量化。
通常来讲,在 Finetune 任务中,我们通常会直接使用 truncation 将超过阈值(2048)的文本给截断,
但在 Pretrain 任务中,这种方式显得有些浪费。
以书籍数据为例,一本书的内容肯定远远多余 2048 个 token,但如果采用头部截断的方式,
则每本书永远只能够学习到开头的 2048 tokens 的内容(连序章都不一定能看完)。
因此,最好的方式是将长文章按照 seq_len(2048)作分割,将切割后的向量喂给模型做训练。
- 模型结构
为了加快模型的训练速度,通常会在 decoder 模型中加入一些 tricks 来缩短模型训练周期。
目前大部分加速 tricks 都集中在 Attention 计算上(如:MQA 和 Flash Attention [falcon] 等);
此外,为了让模型能够在不同长度的样本上都具备较好的推理能力,
通常也会在 Position Embedding 上进行些处理,选用 ALiBi([Bloom])或 RoPE([GLM-130B])等。
具体内容可以参考下面这篇文章:
编辑何枝:【LLM 加速技巧】Muti Query Attention 和 Attention with Linear Bias(附源码)345 赞同 · 23 评论 文章
- Warmup & Learning Ratio 设置
在继续预训练中,我们通常会使用 warmup 策略,此时我们按照 2 种不同情况划分:
- 当训练资源充足时,应尽可能选择较大的学习率以更好的适配下游任务;
- 当资源不充足时,更小的学习率和更长的预热步数或许是个更好的选择。
具体内容可以参考下面这篇文章:
编辑何枝:如何更好地继续预训练(Continue PreTraining)300 赞同 · 20 评论 文章
1.3 数据集清理
中文预训练数据集可以使用 [悟道],数据集分布如下(主要以百科、博客为主):

悟道-数据分布图
但开源数据集可以用于实验,如果想突破性能,则需要我们自己进行数据集构建。
在 [falcon paper] 中提到,
仅使用「清洗后的互联网数据」就能够让模型比在「精心构建的数据集」上有更好的效果,
一些已有的数据集和它们的处理方法如下:

各种数据源 & 数据清理方法
有关 Falcon 更多的细节可以看这里:
编辑何枝:【Falcon Paper】我们是靠洗数据洗败 LLaMA 的!370 赞同 · 13 评论 文章
大模型token, https://teniuapi.online/
1.4 模型效果评测
关于 Language Modeling 的量化指标,较为普遍的有 [PPL],[BPC] 等,
可以简单理解为在生成结果和目标文本之间的 Cross Entropy Loss 上做了一些处理。
这种方式可以用来评估模型对「语言模板」的拟合程度,
即给定一段话,预测后面可能出现哪些合法的、通顺的字词。
但仅仅是「生成通顺句子」的能力现在已经很难满足现在人们的需求,
大部分 LLM 都具备生成流畅和通顺语句能力,很难比较哪个好,哪个更好。
为此,我们需要能够评估另外一个大模型的重要能力 —— 知识蕴含能力。
- C-Eval
一个很好的中文知识能力测试数据集是 [C-Eval],涵盖1.4w 道选择题,共 52 个学科。
覆盖学科如下:

c-eval 数据集覆盖学科图
由于是选择题的形式,我们可以通过将题目写进 prompt 中,
并让模型续写 1 个 token,判断这个续写 token 的答案是不是正确答案即可。
但大部分没有精调过的预训练模型可能无法续写出「A B C D」这样的选项答案,
因此,官方推荐使用 5-shot 的方式来让模型知道如何输出答案:
以下是中国关于会计考试的单项选择题,请选出其中的正确答案。
下列关于税法基本原则的表述中,不正确的是____。
A. 税收法定原则包括税收要件法定原则和税务合法性原则
B. 税收公平原则源于法律上的平等性原则
C. 税收效率原则包含经济效率和行政效率两个方面
D. 税务机关按法定程序依法征税,可以自由做出减征、停征或免征税款的决定
答案:D
甲公司是国内一家领先的新媒体、通信及移动增值服务公司,由于遭受世界金融危机,甲公司经济利润严重下滑,经营面临困境,但为了稳定职工队伍,公司并未进行裁员,而是实行高层管理人员减薪措施。甲公司此举采用的收缩战略方式是____。
A. 转向战略
B. 放弃战略
C. 紧缩与集中战略
D. 稳定战略
答案:C
... # 第 3, 4, 5 道样例题
下列各项中,不能增加企业核心竞争力的是____。
A. 产品差异化
B. 购买生产专利权
C. 创新生产技术
D. 聘用生产外包商
答案:
通过前面的样例后,模型能够知道在「答案:」后面应该输出选项字母。
于是,我们获得模型续写后的第一个 token 的概率分布(logits),
并取出「A B C D」这 4 个字母的概率,通过 softmax 进行归一化:
probs = (
torch.nn.functional.softmax(
torch.tensor(
[
logits[self.tokenizer.encode(
"A", bos=False, eos=False)[0]],
logits[self.tokenizer.encode(
"B", bos=False, eos=False)[0]],
logits[self.tokenizer.encode(
"C", bos=False, eos=False)[0]],
logits[self.tokenizer.encode(
"D", bos=False, eos=False)[0]],
]
),
dim=0,
).detach().cpu().numpy()
)
pred = {0: "A", 1: "B", 2: "C", 3: "D"}[np.argmax(probs)] # 将概率最大的选项作为模型输出的答案
C-Eval 通过这种方式测出了许多模型在中文知识上的效果,
由于是 4 选项问题,所以基线(随机选择)的正确率是 25%。
C-Eval 也再一次证明了 GPT-4 是个多么强大的知识模型:

各模型在 5-shot 下的得分排名
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)