Tokenizer
1. 什么是分词器?
分词器是一种将输入的文本字符串分解为较小单元(如词、子词或字符)的工具。这些单元可以被模型更容易地处理,并且可以映射到一个固定的词汇表中的ID。
2. 分词器的类型:
- 基于词的分词器:按照空格和标点符号将文本划分为词。
- 基于子词的分词器:将文本划分为子词或词片段。常见的方法包括BPE(Byte-Pair Encoding)、WordPiece等。这些方法首先从字符级别开始,然后逐渐合并最常见的字符或字符组合形成子词。
- 基于字符的分词器:将文本划分为单个字符。
3. 分词器在大模型中的作用:
-
向量化:模型只能处理数值数据,所以需要一种方法将文本转化为数值。分词器将文本转化为单词或子词,然后这些单词或子词可以映射到词汇表中的唯一ID,这些ID再被转化为向量。
-
固定的词汇表:分词器使模型可以处理一个固定大小的词汇表,而不是无限的词汇。这也使得模型的参数数量受到控制。
-
处理未知词汇:通过子词或字符级的分词,模型可以处理不在其词汇表中的词汇。例如,如果“ChatGPT”这个词不在词汇表中,但“Chat”和“GPT”是,那么模型仍然可以通过这两个子词来处理它。
-
跨语言和多语言模型:特别是对于多语言模型,子词分词器可以更好地处理多种语言,因为很多语言都共享相同的子词和词根。
-
节省存储和计算资源:通过将输入文本转化为较小的单元,可以减少存储和计算的需求,使得模型运行更高效。
简而言之,分词器为模型提供了一种将文本数据转化为数值格式的方法,从而使模型可以进行学习和预测。在大型语言模型中,尤其是多语言模型,选择适当的分词策略对模型性能至关重要。
Transformer
Transformer 是自然语言处理和深度学习领域的一种重要架构,自从 2017 年由 Vaswani 等人在 “Attention Is All You Need” 这篇论文中提出后,已经广泛应用于各种任务,并取得了显著的成功。以下是关于 Transformer 的基本介绍:
1. 主要特点:
-
自注意力机制:Transformer 使用了一种称为“自注意力”(self-attention)的机制,它允许模型在处理一个词时,关注输入序列中的其他词。这种机制使模型能够捕捉长距离依赖关系。
-
堆叠的层:Transformer 是由多个相同的层堆叠而成的,每一层都有自注意力机制和前馈神经网络。
-
并行处理:不同于传统的 RNN 或 LSTM,Transformer 可以并行处理整个序列,从而提高训练速度。
2. 主要组件:
-
多头自注意力机制:该机制将注意力权重分为多个“头”,每个头捕捉不同的信息。这允许模型同时关注不同类型的上下文信息。
-
前馈神经网络:每个 Transformer 层除了自注意力机制外,还包括一个前馈神经网络,用于进一步处理自注意力的输出。
-
位置编码:由于 Transformer 本身不包含任何关于序列位置的信息,因此需要添加位置编码以保持词序的信息。
-
规范化和残差连接:每个子层(如自注意力或前馈神经网络)后都有一个规范化步骤和残差连接,有助于训练深层模型。
3. 应用:
自从 Transformer 提出后,其基本架构已被用于开发多种大型语言模型,如 BERT、GPT、T5 等,它们在各种 NLP 任务上都取得了前所未有的成果。
4. 为什么它有效?
Transformer 能够并行处理整个文本序列,这使得它比传统的 RNN 或 LSTM 更高效。同时,其自注意力机制使模型能够捕捉文本中的复杂模式和长距离的依赖关系。多头注意力使模型能够关注多个不同的上下文信息,而残差连接和规范化有助于训练深层的网络结构。
总的来说,Transformer 架构由于其独特的设计和能够处理复杂的依赖关系,已经成为了当前 NLP 领域的核心技术。
解析Tansformer模型—理解GPT-3, BERT和T5背后的模型
https://waytoagi.feishu.cn/wiki/WCOcwp3DYiNj2mkiGVycjJ0Znaf#part-X4UQdLUvDoBCtkxmLDocbRzQn9b
位置嵌入(Positional Embeddings)
1. 为什么需要位置嵌入?
Transformer 的自注意力机制同时处理整个序列的所有词,不像 RNN 之类的结构是一个接一个地处理词。这意味着,如果没有其他的位置信息,Transformer 就无法知道词在序列中的位置,或者说无法区分“我爱你”和“你爱我”之间的区别。因此,我们需要为每个词添加位置信息。
2. 如何计算位置嵌入?
在原始的 Transformer 论文中,位置嵌入是使用正弦和余弦函数来计算的。对于位置 p 和维度 i,位置嵌入使用以下公式:
其中, 是嵌入的维度。这种方法生成的位置嵌入可以捕捉到相对位置关系,并且可以扩展到不在训练集中的序列长度。
3. 如何使用位置嵌入?
计算得到的位置嵌入会与词嵌入(词在模型中的向量表示)相加。这样,模型在进行自注意力计算时,不仅可以关注词的语义信息,还可以关注词的位置信息。
4. 其他位置嵌入方法:
除了上述基于正弦和余弦的方法,也有其他的方法来为序列中的词提供位置信息,例如:
- 学习式位置嵌入:与预先定义的正弦/余弦函数不同,学习式位置嵌入是作为模型参数的一部分进行学习的。例如,BERT 使用了这种方法。
- 相对位置嵌入:某些变种的 Transformer,例如 Transformer-XL,考虑到了词之间的相对位置而不是绝对位置。
您的观点是合理的,从直观上看,为句子中的每个单词简单地分配一个位置序号似乎是一个明显的解决方案。但在深度学习和Transformer架构中,位置编码的问题比这更为复杂。以下是为什么需要复杂的位置编码方法的一些原因:
-
连续性和平滑性:简单地为每个位置分配一个整数序号可能会导致模型难以学习位置之间的连续性和平滑性。例如,位置1和位置2之间的差异与位置1和位置10之间的差异是相同的,但我们可能希望模型能够认识到位置1和位置2是更为相近的。
-
高维表示:Transformer模型中的嵌入是高维的。为了与这些嵌入兼容,位置编码也需要是高维的。使用正弦和余弦函数等方法可以为每个位置生成一个高维向量,这有助于模型更好地捕获位置信息。
-
泛化到不同长度的序列:一些位置编码方法,如正弦和余弦位置编码,允许模型泛化到训练时未见过的序列长度。这是因为这些方法为每个可能的位置生成一个独特的编码,而不仅仅是训练数据中出现的位置。
-
模型性能和训练稳定性:实践中发现,某些位置编码方法可能会导致模型的性能和训练稳定性更好。这可能与如何将位置信息与令牌嵌入结合起来有关。
-
研究和探索:由于Transformer架构的流行和成功,研究人员一直在探索如何进一步改进模型的各个方面,包括位置编码。这导致了多种不同的位置编码方法的出现。
激活函数 (Activations)
在神经网络中,激活函数是用来决定一个神经元是否应该被“激活”或“触发”的。简单来说,它的作用是为神经网络添加一些非线性特性,使得网络可以学习并执行更复杂的任务。
激活函数在神经网络中是至关重要的组成部分,它的主要目的是引入非线性。如果没有激活函数,无论神经网络有多少层,它仍然是一个线性模型。常见的激活函数包括ReLU (Rectified Linear Unit)、sigmoid、tanh等。
- 作用:为模型提供非线性能力,从而使模型能够学习复杂的模式。
规范化 (Normalizations)
规范化通常是指在神经网络中对输入或输出进行某种标准化处理,以使其保持在一个合理的范围内。这样可以帮助网络更快地收敛,并提高模型的稳定性。
规范化技术通常被应用于神经网络的输入或输出,以保持数据或激活的一致性和标准化。这有助于加快训练速度,提高模型的稳定性。Layer Normalization和Batch Normalization是常用的规范化技术。
- 作用:加快训练速度、稳定神经网络、减少训练不稳定性和内部协变量移位.
归一化,尤其是Layer Normalization、Batch Normalization等方法,能够帮助避免梯度消失或爆炸的问题,是因为它们能够确保网络中的中间激活值保持在一个相对稳定的分布。当中间激活值的分布保持稳定,模型训练会更加稳定,梯度更新方向也更加准确,从而缓解梯度消失和爆炸的风险。
梯度消失和爆炸的概念:
-
梯度消失:在神经网络的反向传播过程中,当我们从输出层向输入层回传时,梯度可能会变得非常小,几乎趋近于0。当这种情况发生时,权重更新将会变得非常小,这意味着网络几乎不学习。
-
梯度爆炸:与梯度消失相反,梯度爆炸是指梯度变得非常大,这会导致权重更新非常大,从而使网络变得非常不稳定。
举例说明:
假设我们有一个非常深的神经网络,并使用Sigmoid激活函数。当输入值远离0时,Sigmoid函数的导数(或斜率)接近0。如果我们在网络中有很多这样的Sigmoid函数,它们的导数将会相乘,导致反向传播的梯度快速减小。这就是梯度消失的一个典型示例。
假设每一层的导数为0.1,如果我们有100层,那么反向传播到第一层时,梯度大约是0.11000.1100,这几乎是0,导致这一层的权重几乎不更新。
相反,如果每层的梯度大于1,例如3,并且我们有100层,那么到第一层时,梯度大约是31003100,这是一个非常大的数,导致权重更新非常大,这是梯度爆炸的示例。
归一化的方法,通过调整激活的均值和方差,确保了在网络的每一层,激活值都保持在一个较为稳定的分布。这有助于避免由于值过大或过小而导致的梯度消失或爆炸问题。
优化器
优化器是深度学习训练中用于更新模型参数的工具,它基于模型的梯度来最小化(或最大化)损失函数。优化器负责决定如何改变模型的权重来提高模型的性能。
在上面的图示中,我们可以看到两部分:前向传播(图中的”正向”)和反向传播(图中的”反向”)。
-
正向传播:模型根据给定的输入数据计算输出。在这个过程中,模型中的权重(模型参数)使用float16(即半精度浮点数)。
-
反向传播:基于输出与真实目标之间的差异,计算损失函数的梯度。这些梯度被用来更新模型的权重。在这个过程中,模型的权重和损失函数的梯度使用float32(即单精度浮点数)。
当模型完成一次前向传播和反向传播后,优化器会根据计算出的梯度来更新模型的权重。常见的优化器包括SGD(随机梯度下降)、Adam、RMSprop等。
图示中的”优化器”部分,表明了在进行权重更新时,使用了float32的精度。这是为了确保数值稳定性,因为在权重更新过程中,我们希望每一步的更新都是准确的。而float16可能在某些情况下会导致数值不稳定。
反向传播(Backpropagation)
反向传播(Backpropagation)是神经网络训练中的一种算法,用于计算损失函数关于每个权重的梯度。简单来说,反向传播的目的是确定每个权重如何影响最终的损失,并据此更新权重以减少损失。
反向传播分为以下步骤:
-
前向传播:输入数据在网络中从输入层传递到输出层,产生预测输出。
-
计算损失:使用损失函数(例如均方误差或交叉熵)计算预测输出与真实目标之间的差异。
-
反向传播梯度:从输出层开始,计算损失函数关于每个权重的梯度。这是通过链式法则实现的,首先计算输出层的梯度,然后反向计算每个隐藏层的梯度。
-
权重更新:使用上一步计算的梯度,结合一个优化算法(如随机梯度下降、Adam等)来更新网络的权重。
举个简单的例子: 考虑一个简单的线性回归模型,模型预测输出为 y = wx + b,其中 w 是权重,b 是偏置项。我们的目标是找到最佳的 w 和 b 值,使得预测 y 与真实值尽可能接近。
-
前向传播:对于给定的 x 输入值,计算 y。
-
计算损失:假设我们使用均方误差作为损失函数,计算预测 y 与真实 y 之间的差异。
-
反向传播梯度:计算损失函数关于 w 和 b 的梯度。
-
权重更新:使用计算出的梯度来更新 w 和 b。
这个过程会在多次迭代中重复,每次都根据损失函数的梯度来微调 w 和 b,直到损失达到一个满意的最小值。
梯度
梯度是一个向量,表示了某个函数在某一点上的方向导数。简单地说,它指出了函数值增加最快的方向。在多变量函数中,梯度包括了每个独立变量的偏导数。
在深度学习和神经网络的背景下,当我们说到“计算梯度”,我们通常是指计算损失函数(或目标函数)关于模型参数(如权重和偏置)的偏导数。这些偏导数提供了关于如何更新参数以达到优化目的的信息。
为了更直观地理解,让我们使用一个简单的例子:
假设你在山上,目前你无法看到周围的地形,但你想知道为了尽快下山,你应该往哪个方向走。在这种情况下,你可以想象梯度就像一个指南针,它会指向你当前所在位置下坡最陡的方向。如果你沿着这个方向走,你会在最短的时间内下到山脚。
- 在这个比喻中,山的高度代表了损失函数的值。
- 你的位置代表了当前的模型参数。
- 梯度就像指南针,指示了损失函数下降最快的方向。
- 沿着梯度方向更新模型参数就像沿着最陡峭的路径下山。
然而,只是盲目地追随梯度并不总是最佳的策略,因为可能会走进局部最小值而非全局最小值,或者步长太大导致“跳过”最佳点。这就是为什么深度学习优化中还有学习率和其他策略的原因。