从零开始实现大语言模型(三):Token Embedding与位置编码

1. 前言

Embedding是深度学习领域一种常用的类别特征数值化方法。在自然语言处理领域,Embedding用于将对自然语言文本做tokenization后得到的tokens映射成实数域上的向量。

本文介绍Embedding的基本原理,将训练大语言模型文本数据对应的tokens转换成Embedding向量,介绍并实现OpenAI的GPT系列大语言模型中将tokens在文本数据中的位置编码成Embedding向量的方法。

2. Embedding

Embedding是指将类别特征(categorical feature)映射到连续向量空间中,即使用实数域上的向量表示类别特征。其中,向量的长度是超参数,必须人为设定。向量中每一个元素的值,均是模型的参数,必须从训练数据中学习获得,即通过大量数据训练,模型自动获得每一个类别特征该被表示成一个怎样的向量。

Deep Learning is all about “Embedding Everything”.

Embedding的核心思想是将离散对象映射到连续的向量空间中,其主要目的是将非数值类型的数据转换成神经网络可以处理的格式。

Embedding向量维度的设定并没有精确的理论可以指导,设定的原则是:Embedding向量表示的对象包含的信息越多,则Embedding向量维度应该越高;训练数据集越大,Embedding向量维度可以设置得更高。在大语言模型出现前,深度学习自然语言处理领域,一般Embedding向量的维度是8维(对于小型数据集)到1024维(对于超大型数据集)。更高维度得Embedding向量可以捕获特征对象之间更精细的关系,但是需要更多数据去学习,否则模型非常容易过拟合。GPT-2 small版本使用的Embedding向量维度是768,GPT-3 175B版本使用的Embedding向量维度是12288。

在自然语言处理领域,可以将一个单词或token映射成一个Embedding向量,也可以一个句子、一个文本段落或一整篇文档映射成一个向量。对句子或一段文本做Embedding是检索增强生成(RAG, retrieval-augmented generation)领域最常用的技术方法,RAG是目前缓解大语言模型幻觉现象最有效的技术方法之一。

将一个单词或token映射成一个Embedding向量,只需要构造一个token ID到向量的映射表。将一个句子、一个文本段落或一整篇文档映射成一个向量,往往需要使用一个神经网络模型。模型的输入是一段文本的tokens对应的token ID,输出是一个向量。

以前比较流行的学习一个单词对应的Embedding向量的方法是Word2Vec。Word2Vec的主要思想是具有相同上下文的单词一般有相似的含义,因此可以构造一个给定单词的上下文预测任务来学习单词对应的Embedding向量。如下图所示,如果将单词对应的Embedding向量维度设置为2,可以发现具有相似属性的单词对应的Embedding向量在向量空间中的距离更近,反之则更远。

图一

在大语言模型中不会使用Word2Vec等算法训练生成的Embedding向量,而是直接使用torch.nn.Embedding随机初始化各个tokens对应的Embedding向量,并在训练阶段更新这些Embedding向量中各个元素的值。将各个tokens对应的Embedding向量作为大语言模型的参数,可以确保学到的Embedding向量更加适合当前任务。

在自然语言处理项目实践中,如果训练数据集足够大,一般会使用上述随机初始化并训练Embedding向量的方法,如果训练数据集不够大,则更推荐使用在大数据集上预训练生成的Embedding向量,或者可以直接将预训练模型作为特征提取器,在其后接一个面向下游任务的输出层,只训练输出层参数。

3. 将Tokens转换成Embedding向量

对训练大语言模型的自然语言文本做tokenization,可以将文本转换成一系列tokens。通过词汇表(vocabulary)可以将tokens转换成token IDs。torch.nn.Embedding层可以将token ID映射成Embedding向量。

假设词汇表中共包含6个不同的tokens,每个token对应的Embedding向量维度设置为3。可以使用如下代码随机初始化各个tokens对应的Embedding向量:

import torch

torch.manual_seed(123)

input_ids = torch.tensor([5, 1, 3, 2])
vocabulary_size = 6
embedding_dim = 3

token_embedding_layer = torch.nn.Embedding(vocabulary_size, embedding_dim)
print(token_embedding_layer.weight)

执行上面代码,打印结果如下:

Parameter containing:
tensor([[ 0.3374, -0.1778, -0.1690],
        [ 0.9178,  1.5810,  1.3010],
        [ 1.2753, -0.2010, -0.1606],
        [-0.4015,  0.9666, -1.1481],
        [-1.1589,  0.3255, -0.6315],
        [-2.8400, -0.7849, -1.4096]], requires_grad=True)

Embedding层的权重(weight)矩阵是一个二维的张量

### Transformer 模型位置编码的图表可视化 为了更好地理解Transformer模型中的位置编码机制,可以借助一些常见的图表和可视化方法来展示其工作原理。 #### 1. 位置编码的作用 位置编码用于给定输入序列中的每个位置赋予唯一的表示形式。由于Transformer模型本身不具备处理顺序信息的能力,因此引入了位置编码以帮助网络识别不同token之间的相对距离[^2]。 #### 2. 使用角函数的原因 选择正弦和余弦函数作为位置编码的基础是因为这些周期性的函数可以帮助模型学习到更复杂的模式,并且使得任意两个固定间隔的位置具有相同的相对关系。具体来说,在偶数维度上使用`sin`函数而在奇数维度上使用`cos`函数来进行编码: \[ PE_{(pos,2i)} = \sin\left(\frac{pos}{10000^{2i/d}}\right) \] \[ PE_{(pos,2i+1)} = \cos\left(\frac{pos}{10000^{2i/d}}\right) \] 其中\( pos \)代表位置索引;\( d \)为嵌入向量的总维数;而 \( i \) 则是从零开始计数的具体维度编号。 #### 3. 可视化实例 下面是一个简单的Python代码片段,用来绘制前几个位置上的位置编码值随时间变化的趋势图: ```python import numpy as np import matplotlib.pyplot as plt def get_position_encoding(seq_len=50, embed_dim=64): position_encodings = [] for pos in range(seq_len): encoding_at_pos = [ (np.sin(pos / (10000 ** ((2 * i)/embed_dim))) if i % 2 == 0 else np.cos(pos / (10000 ** ((2 * i)/embed_dim)))) for i in range(embed_dim)] position_encodings.append(encoding_at_pos) return np.array(position_encodings) seq_length = 50 embedding_dimension = 8 pe_matrix = get_position_encoding(seq_length, embedding_dimension) plt.figure(figsize=(10,7)) for dim in range(embedding_dimension//2): plt.plot(pe_matrix[:,dim*2], label=f'Dim {dim*2}') plt.plot(pe_matrix[:,dim*2+1], linestyle='--',label=f'Dim {dim*2+1}') plt.title('Position Encodings Visualization') plt.xlabel('Sequence Position') plt.ylabel('Encoding Value') plt.legend() plt.show() ``` 这段代码会生成一系列曲线,每条曲线上下波动代表着对应维度下的位置编码数值随着序列长度的变化情况。通过观察图形可以看出,即使是在较长的距离内,相邻位置之间仍然保持着一定的相似性和规律性,这有助于保持长期依赖的有效捕捉能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

RuizhiHe

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

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

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

打赏作者

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

抵扣说明:

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

余额充值