五分钟轻松通俗理解 tokenizer、encoder、decoder、embedding 的区别和联系

五分钟轻松通俗理解 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)层的功能是不一样的。

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个使用神经机器翻译(NMT)的英语到印地语的 seq2seq 模型代码示例: ```python from keras.models import Model from keras.layers import Input, LSTM, Dense, Embedding from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences from keras.utils import to_categorical import numpy as np # 定义模型输入和输出序列的最大长度 max_encoder_seq_length = 50 max_decoder_seq_length = 50 # 定义输入序列的维度 num_encoder_tokens = ... num_decoder_tokens = ... # 定义LSTM层的维度 latent_dim = 256 # 定义编码器模型 encoder_inputs = Input(shape=(None,)) encoder_embedding = Embedding(num_encoder_tokens, latent_dim) encoder_lstm = LSTM(latent_dim, return_state=True) encoder_outputs, state_h, state_c = encoder_lstm(encoder_embedding(encoder_inputs)) encoder_states = [state_h, state_c] # 定义解码器模型 decoder_inputs = Input(shape=(None,)) decoder_embedding = Embedding(num_decoder_tokens, latent_dim) decoder_lstm = LSTM(latent_dim, return_sequences=True, return_state=True) decoder_outputs, _, _ = decoder_lstm(decoder_embedding(decoder_inputs), initial_state=encoder_states) decoder_dense = Dense(num_decoder_tokens, activation='softmax') decoder_outputs = decoder_dense(decoder_outputs) # 定义整个模型 model = Model([encoder_inputs, decoder_inputs], decoder_outputs) # 编译模型 model.compile(optimizer='rmsprop', loss='categorical_crossentropy') # 训练模型 model.fit([encoder_input_data, decoder_input_data], decoder_target_data, batch_size=batch_size, epochs=epochs, validation_split=0.2) # 预测模型 encoder_model = Model(encoder_inputs, encoder_states) decoder_state_input_h = Input(shape=(latent_dim,)) decoder_state_input_c = Input(shape=(latent_dim,)) decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c] decoder_outputs, state_h, state_c = decoder_lstm(decoder_embedding(decoder_inputs), initial_state=decoder_states_inputs) decoder_states = [state_h, state_c] decoder_outputs = decoder_dense(decoder_outputs) decoder_model = Model([decoder_inputs] + decoder_states_inputs, [decoder_outputs] + decoder_states) # 定义预测函数 def decode_sequence(input_seq): states_value = encoder_model.predict(input_seq) target_seq = np.zeros((1, 1)) target_seq[0, 0] = target_token_index['\t'] stop_condition = False decoded_sentence = '' while not stop_condition: output_tokens, h, c = decoder_model.predict([target_seq] + states_value) sampled_token_index = np.argmax(output_tokens[0, -1, :]) sampled_char = reverse_target_char_index[sampled_token_index] decoded_sentence += sampled_char if (sampled_char == '\n' or len(decoded_sentence) > max_decoder_seq_length): stop_condition = True target_seq = np.zeros((1, 1)) target_seq[0, 0] = sampled_token_index states_value = [h, c] return decoded_sentence ``` 需要注意的是,NMT 的 seq2seq 模型相对于简单的 seq2seq 模型要复杂得多,需要更多的调整和优化才能在实际任务中获得好的性能。此外,还需要对数据进行预处理,比如分词、标记化等,这些内容在上述代码中并未包含。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青缘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值