五分钟轻松通俗理解 tokenizer、encoder、decoder、embedding 的区别和联系
常有初学者会问,在decoder-only的大语言模型(如GPT系列和Llama系列)中,输入文本首先被tokenizer编码,之后又对token_id进行嵌入变成了高维嵌入向量,这个过程难道不是encoder吗?为什么实际上是decoder-only呢?
基本概念
首先对以下的概念有一个基础了解(看不懂没关系,有个印象,后面有比较通俗的解释)。根据自然语言文本的输入顺序,会经过以下几个过程:
tokenizer
将文本根据词表,变成向量。即,文本变成数字向量。通过tokenizer完成。
embedding
在输入时,词表向量转化为高维向量,便于更好地表示特征和词之间的关系(可以简单理解为特征向量升维过程)。通过嵌入层完成、或embedding模型完成。
虽然这两个过程看起来类似于“编码”,将文本变成了向量特征表示,但这与Transformer中的编码器(Encoder)层的功能是不一样的。
encoder、decoder
encoder和decoder指的是模型架构,而不是输入前的数据处理过程。在完整的Transformer架构中,模型通常由两个主要部分组成:编码器(Encoder) 和 解码器(Decoder)。
-
编码器会处理整个输入序列,并生成一个上下文感知的表示,这个表示捕捉了输入序列的语义信息。
-
解码器则根据编码器生成的上下文表示(以及它自身的输入)生成输出序列。在decoder-only的模型中,解码器只能根据前面的已生成的部分来生成下一个标记。
在decoder-only的模型中,整个模型架构中只使用了Transformer的解码器部分,没有编码器(encoder)部分。虽然有一个输入的处理过程(前面说的token化和嵌入),但模型的核心结构只包含解码器层。 输入序列经过嵌入后直接进入解码器。解码器会逐步生成输出(下一个token),但整个过程没有使用编码器层。
通俗地说
在每个生成步骤中,虽然token化和嵌入过程看起来像是“编码”,但这只是输入数据预处理的一部分。Decoder-only模型中真正体现“decoder-only”的地方在于模型的架构设计上:输入数据(经过预处理)直接通过解码器层处理,并生成输出,而没有编码器层的参与。这种结构特别适合语言生成任务,因为它可以逐步生成下一个token。
扩展一下encoder-decoder的概念,能更好理解。encoder-decoder的目的是处理seq2seq任务,也就是说,需要的是从一个完整序列表示到另外一个完整序列表示的映射关系。通俗来讲相当于,根据用户的的输入,模型先通过encoder生成一个自己的理解。再在这个自己的理解上生成输出(通过decoder)。翻译任务和总结任务是符合这个映射关系的。而decoder-only更加适合续写。
通过具体一个简单的神经网络代码来加深理解
这是一个循环神经网络的模型,用于对文本进行情感判断。不用管这么多,直接看模型的每个层。
class BiRNN(nn.Module):
def __init__(self, vocab, embed_size, num_hiddens, num_layers):
super(BiRNN, self).__init__()
# 看这里,这就是嵌入层,用来进行词嵌入
self.embedding = nn.Embedding(len(vocab), embed_size)
# 这是encoder
self.encoder = nn.LSTM(input_size=embed_size,
hidden_size=num_hiddens,
num_layers=num_layers,
bidirectional=True)
# 这是decoder输出
self.decoder = nn.Linear(4*num_hiddens, 2)
def forward(self, inputs):
# 输入嵌入层的向量是 token_id_list, 即 词索引向量
embeddings = self.embedding(inputs.permute(1, 0))
outputs, _ = self.encoder(embeddings) # output, (h, c)
encoding = torch.cat((outputs[0], outputs[-1]), -1)
outs = self.decoder(encoding)
return outs
整个输入的过程是:自然语言文本 -> token_id_list -> 词嵌入向量 -> encoder -> decoer -> 生成的标签
这样,就能更加直观地看出来,tokenizer、embedding、encoder、decoder分别在什么位置发挥作用了。
总结
tokenizer和embedding可以理解为数据的预处理。输入文本首先通过tokenizer被转换成标记(tokens_id),这是将文本转化为模型可以处理的数字序列的第一步。
然后,这些标记会通过嵌入层(Embedding Layer)被转换成高维向量表示。这一步是将离散的标记映射到连续的向量空间,以便模型能够在向量空间中处理信息。
虽然这个过程看起来类似于“编码”(因为我们在将离散标记转换为连续向量),但这与Transformer中的编码器(Encoder)层的功能是不一样的。