Deep Dive into LLMs like ChatGPT

ChatGPT构建 - 预训练

Step 1 - 下载和预处理(internet)

预训练阶段的首要步骤是下载并处理互联网数据

Hugging Face公司收集并构建了名为FineWeb的数据集

他们在这篇博文中详细阐述了FineWVeb数据集的构建方法

核心目标是从公开来源获取海量互联网文本数据,要求数据具有高度多样性,因为模型需要吸收广泛的知识,所以需要海量且多样化的优质文档,实现这一目标相当复杂,需要经过多个处理阶段

文本提取

需要网页的纯文本内容,需要提取网页正文文本,而非导航菜单等无关元素,需要大量过滤和经验法则来精准提取优质内容

语言过滤

以FineWeb为例,它使用语言分类器进行过滤,系统会判断每个网页的语言类型,例如仅保留英文内容占比超过65%的网页,不同公司可以自主制定此类设计决策 “我们的数据集应该包含哪些语言及其比例?” 例如若完全过滤西班牙语内容,后续模型在该语言上的表现就会受限,因其缺乏相关训练数据。

语言过滤后还需进行去重等其他过滤步骤,最后阶段包括个人身份信息去除等处理,例如地址、社会保障号码等敏感信息,系统会检测并过滤包含此类信息的网页,整个预处理流程包含多个阶段,其复杂程度可见一斑,最终得到例如FineWeb这样的预处理数据集

处理后数据实际样例展示

这里展示最终进入训练集的文本样例 - 44TB,数据量极其庞大,将所有文本进行拼接处理

Step 2 - tokenization令牌

未经处理的原始网络文本

呈现出由文本数据构成的巨型“挂毯”,这些文本数据蕴含着各种模式,接下来将基于这些数据训练神经网络,让神经网络学习并建模文本的流动规律。

在输入文本到神经网络前,需要确定文本的表示方式和输入方法,当前技术方案要求神经网络接收一维符号序列。且这些符号必须来自有限集合。因此需要确定符号的组成。然后将数据表示为这些符号的一维序列。

在计算机系统中,文本存在底层表示形式。通过UTF-8编码可获得对应的计算机原始比特流。其表现形式如下

这意味着是我们需要的数据表示形式,此时仅有0和1两种符号,形成超长序列。实际上在神经网络中,序列长度是有限且珍贵的资源。我们不希望仅有两种符号的过长序列。需要在词汇表规模(符号数量)与序列长度之间取得平衡。需要更多符号和更短的序列。一种简单的序列压缩方法是将连续的比特分组处理,比如将八个比特组合成单个字节。由于每个比特只有开/关两种状态,八位组合总共能产生256种不同的开关状态组合。因此我们可以将原始比特序列重新表示为字节序列。这种字节序列长度会缩短至八分之一,但符号种类增加到256个。每个字节的数值范围是0到255。

需要强调的是,这些数值不应单纯视为数字,而应作为唯一标识符或符号来理解。更好的理解方式可能是将每个字节值映射为独特的表情符号。

转换后我们会得到类似这样的表情符号序列

整个序列由256种不同的表情符号构成。实际上,当前最先进的语言模型需要在此基础进一步优化。为了提升模型效率,我们需要继续缩短序列长度,这需要以扩大词汇表规模为代价。实现这一目标的核心算法就是字节对编码(BPE)算法。该算法的原理是寻找并合并高频出现的连续符号对。例如,数值116和32的组合出现频率极高。我们的处理策略是将这对符号合并为新符号。为此创建ID为256的新符号,并用它替换所有116+32组合。通过多次迭代执行此算法。每次创建新符号都会缩短序列长度并扩展符号库。实践证明,将词汇表规模控制在约10万符号时效果最佳。具体来说,GPT-4使用的词汇表包含100,277个符号。这种将原始文本转换为符号(即分词单元)的过程称分词

现在让我们具体观察GPT-4的分词机制,包括文本到分词的转换及逆向过程。推荐使用tiktoken网站来探索分词表示。

在下拉菜单中选择CL100K Base(GPT-4的基础分词器)左侧输入文本即可实时查看分词结果。

现在已经用分词器将数据集中的文本序列重新编码为token序列。例如FineWeb数据集不仅占用44TB存储空间,更包含约15万亿个token的序列。再次强调,所有这些数字都代表着文本片段。它们就像序列的基本原子单位,数字本身没有实际含义,这些仅仅是唯一的标识符。

Step 3 - 神经网络训练

这正是训练神经网络时计算量最大的核心环节。这个阶段的目标是建模token序列的统计关联关系。具体做法是从数据中随机截取token窗口。窗口长度理论上可以从零扩展到我们设定的最大值。实际应用中,常见的有8,000个token的窗口长度。虽然理论上可以处理任意长度,但过长窗口会导致计算成本剧增。因此我们通常会选取8,000、4,000或16,000等折中值。本例中为演示方便,仅选取前四个token.

这四个token(对应这些ID)构成我们的窗口样本,我们的训练目标是预测序列中的下一个token,比如这里的下一个token就是3962,我们将这四个token称为上下文(context)。它们将作为神经网络的输入,输入是长度可变的token序列(0到最大值如8,000之间),输出则是对后续token的预测结果,由于词表包含100,277个可能token,神经网络将输出对应数量的概率值。每个数值代表对应token作为序列下一个元素的概率预测。最初,这个神经网络是随机初始化的,本质上这是一种随机变换。因此在训练的最初阶段,这些概率输出也具有一定随机性。这里虽然只展示三个示例,但请注意实际存在10万个数字参数。

当前神经网络预测空格分隔符标记的出现概率为4%,标记11799的概率是2%,而标记3962(对应“post“)的概率为3%,需要说明的是,这个文本窗口是从数据集中采样的,因此我们已知后续标记,这个已知结果即为标签,正确答案是3962实际出现在序列。现在我们拥有对神经网络进行参数更新的数学方法,我们具备调节机制,木稍后将深入讲解,核心目标是将当前3%的概率值提升, 同时降低其他标记的概率。

通过数学计算,我们可以精确调整神经网络参数,使正确答案的概率获得微量提升。完成参数更新后,当再次输入相同的四个标记序列时,调整后的神经网络可能将“post”的概率提升至4%, “‘case“降至1%,“direction“调整到2%左右。这种微调机制能够渐进式地提高序列中正确后续标记的预测概率。需要强调的是,这个优化过程不仅作用于当前预测标记(四个输入预测一个输出的情况)该过程实际上会同步作用于整个数据集的所有标记。实际操作中,我们通过采样文本窗口片段组成训练批量,在每个标记位置都进行神经网络参数调整以提高对应概率。这些计算过程通过大规模批量并行处理实现。这就是神经网络训练的核心流程。通过持续的参数更新,使预测概率逐步匹配训练集的统计特征,最终让标记间的序列概率符合数据中的实际分布规律。

神经网络内部

现在让我们简要剖析神经网络的内部结构以加深理解。如前所述,输入是标记序列。本例使用四个输入标记,但实际可处理从零到约一千个标记的任意长度。理论上处理无限长序列是可行的。但无限长度会导致计算成本过高。因此实际应用中会设定最大上下文长度进行截断处理。这些输入X与神经网络参数(权重)通过复杂数学表达式进行融合计算。这里展示了六个参数示例及其数值。而现代神经网络实际包含数十亿量级的参数。

在初始阶段,所有这些参数都完全随机设置。现在,在参数随机设置的情况下,你可能会认为这个神经网络会做出随机预测,事实确实如此。最初阶段,它的预测完全是随机的。但通过我们称之为神经网络训练的这个迭代更新过程,这些参数的设置会不断调整,最终使得神经网络的输出与训练集中呈现的模式保持一致。可以将这些参数想象成DJ调音台上的旋钮,当你旋转这些旋钮时,每个可能的标记序列输入都会得到不同的预测结果。而训练神经网络的过程,本质上就是在寻找与训练集统计特性相吻合的参数设置。

现在,通过一个具体例子展示这个复杂数学表达式的样貌,以便获得直观理解。现代网络的数学表达式可能包含数万亿个计算项。但这里我先展示一个简单的示例。

Last updated

Was this helpful?