从零开始实现大语言模型(三):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)矩阵是一个二维的张量,矩阵的行数为6,列数为3,每一行是一个3维向量。词汇表中共6个不同的tokens,第1个token对应的Embedding向量即为权重矩阵的第1行,第2个token对应的Embedding向量即为权重矩阵的第2行。依次类推,第6个token对应的Embedding向量为权重矩阵第6行的向量。权重矩阵是随机初始化的,会在模型训练期间使用随机梯度下降算法更新。

假设输入文本对应的token ID列表为[5, 1, 3, 2],可以使用如下代码,将文本对应的token IDs全部转换成Embedding向量:

input_ids = torch.tensor([5, 1, 3, 2])
token_embeddings = token_embedding_layer(input_ids)
print(token_embeddings)

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

tensor([[-2.8400, -0.7849, -1.4096],
        [ 0.9178,  1.5810,  1.3010],
        [-0.4015,  0.9666, -1.1481],
        [ 1.2753, -0.2010, -0.1606]], grad_fn=<EmbeddingBackward0>)

将文本对应的4个token IDs输入Embedding层,输出一个4行3列的张量矩阵。可以观察到矩阵的第1行即为Embedding层权重矩阵第6行对应的向量,第2行即为Embedding层权重矩阵第2行对应的向量,第3行即为Embedding层权重矩阵第4行对应的向量,第4行即为Embedding层权重矩阵第3行对应的向量。

如下图所示,输入的token ID列表为[5, 1, 3, 2],输出的张量矩阵分别由Embedding层权重矩阵的第6、2、4、3行的向量构成。由此可见,Embedding层本质上是初始化了一个token ID到Embedding向量的映射,将token ID列表输入Embedding层,会依次索引不同token ID对应的Embedding向量,返回一个Embedding向量矩阵。

图二

4. 位置编码(Positional Encoding)

Embedding层构造了词汇表中全部token IDs到Embedding向量的映射,输入文本数据对应的token ID列表,Embedding层输出相应Embedding向量。Embedding向量与token ID是一一对应关系,token ID列表中不同位置的相同token ID对应的Embedding向量相同,即Embedding层输出的Embedding向量不包含token的位置信息。

图三

大语言模型使用自注意力机制(self-attention)处理自然语言文本,其神经网络不具备循环结构。自注意力机制无法捕捉输入文本中的token序列位置信息,将两个含义不同的文本序列“你爸妈对我的看法”和“我爸妈对你的看法”输入自注意力层,生成的用于预测下一个字的输出向量会完全相同。

后续文章将详细介绍自注意力机制理论原理,提前了解自注意力机制无法捕捉输入文本中的token序列位置信息的原因,可以参见本人写的博客文章BERT与ERNIE - 4. Self-Attention层无法捕捉句子中词序信息原因。

在输入文本对应token的Embedding向量中添加token位置信息的方法有两种:相对位置编码(relative positional embeddings)和绝对位置编码(absolute positional embeddings)。

如下图所示,绝对位置编码直接将输入文本token的绝对位置编码成Embedding向量。假设大语言模型支持的最大输入token数量为 k k k,则总共包含 k k k个不同的待学习的位置Embedding向量。将token对应的Embedding向量与token所在位置对应的Embedding向量相加,生成最终输入大语言模型的Embedding向量。

图四

相对位置编码并不将输入token的绝对位置编码成Embedding向量,而是将不同token之间的相对位置编码成Embedding向量。假设设定的最大输入token数量为 k k k,则总共包含 2 k − 1 2k-1 2k1个不同的待学习的相对位置Embedding向量。

2 k − 1 2k-1 2k1个不同的带学习的位置Embedding向量分别为: e − k + 1 , e − k + 2 , ⋯   , e − 1 , e 0 , e 1 , ⋯   , e i , ⋯   , e k − 2 , e k − 1 e_{-k+1}, e_{-k+2}, \cdots, e_{-1}, e_0, e_1, \cdots, e_i, \cdots, e_{k-2}, e_{k-1} ek+1,ek+2,,e1,e0,e1,,ei,,ek2,ek1,其中 i i i表示与当前token的相对距离为多少个token。

除了上述两种将token位置编码成Embedding向量的位置编码方法,还有许多其他类型的位置编码方法。不管那种位置编码方法,都是为了使大语言模型具备理解token之间顺序及位置关系的能力。OpenAI的GPT系列大语言模型使用的是上述绝对位置编码方法。

假设大语言模型支持的最大输入token数量为8,则可以使用如下代码随机初始化各个位置对应的Embedding向量,并生成输入文本对应的token ID列表中各个token位置对应的Embedding向量:

context_len = 8

position_embedding_layer = torch.nn.Embedding(context_len, embedding_dim)
position_embeddings = position_embedding_layer(torch.arange(input_ids.shape[0]))
print(position_embeddings)

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

tensor([[-2.1338,  1.0524, -0.3885],
        [-0.9343, -0.4991, -1.0867],
        [ 0.9624,  0.2492, -0.9133],
        [-0.4204,  1.3111, -0.2199]], grad_fn=<EmbeddingBackward0>)

将输入文本对应的token_embeddingsposition_embeddings相加,即可生成最终输入大语言模型的Embedding向量:

input_embeddings = token_embeddings + position_embeddings
print(input_embeddings)

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

tensor([[-4.9737,  0.2675, -1.7981],
        [-0.0166,  1.0818,  0.2144],
        [ 0.5609,  1.2158, -2.0615],
        [ 0.8549,  1.1101, -0.3805]], grad_fn=<AddBackward0>)

5. 结束语

对自然语言文本数据做tokenization,可以将文本分割成一连串tokens,并通过词汇表映射成token ID列表。使用Embedding层将token IDs及其位置转换成相同维度的Embedding向量,token对应的Embedding向量与其位置对应的Embedding向量相加,最终生成输入大语言模型的Embedding向量。

接下来,我们该去了解注意力机制了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/791138.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

imx6ull/linux应用编程学习(17)利用mqtt上传开发板数据,和控制开发板led(基于正点)

1.关于如何创建自己的服务器&#xff0c;可看上篇文章 imx6ull/linux应用编程学习&#xff08;16&#xff09;emqx &#xff0c;mqtt创建连接mqtt.fx-CSDN博客 2.实现任务&#xff1a;&#xff08;正点原子教程源码改&#xff09; (1)用户可通过手机或电脑远程控制开发板上的…

java入门-告别C进入java世界

目标 java体系 java开发环境 helloworld java语法 java体系 java开发环境 安装JDK JDK&#xff1a; Java Developement Kit 配置jdk 为什么需要配置 操作系统找不到此程序 操作系统PATH PATH C:\Users\49354>echo %PATH% C:\Program Files (x86)\VMware\VMware Works…

Python8:线程和进程

1.并发和并行 并发&#xff1a;在逻辑上具备同时处理多个任务的能力&#xff08;其实每时刻只有一个任务&#xff09; 并行&#xff1a;物理上在同一时刻执行多个并发任务 2.线程与进程 一个进程管多个线程&#xff0c;一个进程至少有一个线程 python多线程是假的&#xf…

基于Booth乘法和Wallace树的乘法器优化思想

基于Booth乘法和Wallace树的快速乘法器 为了理解Booth乘法和Wallace数如何让乘法器变得更快&#xff1a; 先考虑不优化的8位乘法器实现&#xff0c;即8个16位数字累积共进行7次加法运算&#xff0c;可以认为一次16位加法用到16个全加器&#xff0c;则共需要112个全加器件&…

计算机毕业设计Python深度学习游戏推荐系统 Django PySpark游戏可视化 游戏数据分析 游戏爬虫 Scrapy 机器学习 人工智能 大数据毕设

本论文的主要研究内容如下&#xff1a; 了解基于Spark的TapTap游戏数据分析系统的基本架构&#xff0c;掌握系统的开发方法&#xff0c;包括系统开发基本流程、开发环境的搭建、测试与运行等。 主要功能如下&#xff1a; &#xff08;1&#xff09;用户管理模块&#xff1a…

【Spring Boot 教程:从入门到精通】掌握 Spring Boot 开发技巧与窍门(一)-java语法(1)

一些Java基本语法的基本介绍&#xff0c;语法更新结束会紧跟项目实战&#xff0c;后续会持续在该专栏进行更新&#xff01;&#xff01;&#xff01; 目录 前言 一、基本概念 1.JDK、JRE、JVM的关系&#xff1a; 2.JDK版本选择 3.Java代码的编译运行流程 4.JSE、JEE、J…

Java学习Day3

数组 4.1 什么是数组&#xff1f; 容器 可以存多个同种类型的数据 4.2 Java中如何表示数组 定义数组 数据类型[] 数组名;实例化数组 public class Main {public static void main(String[] args) {int[] arryList new int[7];for (int i 0 ;i<7;i){arryList[i] i*2;Sy…

python-26-零基础自学python-如何创建文件、读取数据、处理多个文件及程序异常处理等

学习内容&#xff1a;《python编程&#xff1a;从入门到实践》第二版第10章 知识点&#xff1a; 程序异常如何处理&#xff1f;try-except-else 多个文件处理 创建文件&#xff1a;在文件中储存数据 练习内容&#xff1a; 练习10-8&#xff1a;猫和狗 创建文件cats.txt和…

Flink ui 本地flink ui 报错 {“errors“:[“Not found: /“]}

在学习flink 的过程中&#xff0c;伊始的flink 版本是1.17.2 报题目的错误 &#xff0c;百思不得其解&#xff0c;尝试更替了1.19.1 然后就成功了 &#xff0c;期间未做任何的修改 。 ui 默认地址 &#xff1a; http://localhost:8081 pom 文件 如下 <?xml version&qu…

人工智能算法工程师(中级)课程4-sklearn机器学习之回归问题与代码详解

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能算法工程师(中级)课程4-sklearn机器学习之回归问题与代码详解。回归分析是统计学和机器学习中的一种重要方法&#xff0c;用于研究因变量和自变量之间的关系。在机器学习中&#xff0c;回归算法被广泛应用于…

“论基于构件的软件开发方法及其应用”精选范文,软考高级论文,系统架构设计师论文

论文真题 基于构作的软件开发 (Component-Based Software Development&#xff0c;CBSD) 是一种基于分布对象技术、强调通过可复用构件设计与构造软件系统的软件复用途径。基于构件的软件系统中的构件可以是COTS &#xff08;Commercial-Off-the-Shelf&#xff09;构件&#x…

学生选课管理系统(Java+MySQL)

技术栈 Java: 用于实现系统的核心业务逻辑。MySQL: 作为关系型数据库&#xff0c;用于存储系统中的数据。JDBC: 用于Java程序与MySQL数据库之间的连接和交互。Swing GUI: 用于创建图形用户界面&#xff0c;提升用户体验。 系统功能 我们的学生选课管理系统主要针对学生和管理…

AI降痕工具:助力学术论文降AI率的智能选择

不知道大家有没有发现&#xff0c;随着人工智能技术的快速发展&#xff0c;AI工具正逐渐渗透到我们日常生活的各个方面&#xff0c;极大地提高了我们的工作和学习效率。 随着AI论文的出现&#xff0c;论文去AI痕迹成为了确保原创性的关键。接下来我将为大家介绍一款AI降痕神器…

LinK3D: Linear Keypoints Representation for 3D LiDAR Point Cloud【翻译与解读】

LinK3D: Linear Keypoints Representation for 3D LiDAR Point Cloud 摘要 特征提取和匹配是许多机器人视觉任务的基本组成部分&#xff0c;如 2D 或 3D 目标检测、识别和配准。2D 特征提取和匹配已取得巨大成功。然而&#xff0c;在 3D 领域&#xff0c;当前方法由于描述性差…

国内的几款强大的智能—AI语言模型

AI 绘图 链接&#xff1a;点我进入 1、国内百度研发的&#xff0c;文心一言&#xff1a; https://yiyan.baidu.com/welcome 大家如果像我的界面一样有【开始体验】就是可以使用的&#xff0c;否则就是说明在等待中&#xff01; 优点&#xff1a;会画画&#xff0c;暂无次数限…

【线性表,线性表中的顺序表和链表】

目录 1、线性表的定义和基本操作1.1、线性表的定义1.2、线性表的基本操作 2、顺序表和链表的比较2.1、顺序表2.1.1、顺序表的定义和特点2.1.2、顺序表的实现&#xff08;1&#xff09;顺序表的静态分配&#xff1a;&#xff08;2&#xff09;顺序表的动态分配 2.1.3、顺序表的基…

韦尔股份:深蹲起跳?

利润大增7倍&#xff0c;是反转信号还是回光返照&#xff1f; 今天我们聊聊光学半导体龙头——韦尔股份。 上周末&#xff0c;韦尔股份发布半年业绩预告&#xff0c;预计上半年净利润13至14亿&#xff0c;同比增幅高达 754%至 819%。 然而&#xff0c;回首 2023 年它的净利仅 …

如何将HEVC格式的视频转换为无损、未压缩的MP4格式视频?

在和大家分享视频格式转换之前&#xff0c;先跟大家分享一下HEVC格式的视频到底是什么文件&#xff1f;压缩原理是什么&#xff1f;了解了它的本质之后&#xff0c;我们就可以知道如何保证视频高清无损了。 如何将HEVC格式的视频转换为无损、未压缩的MP4格式视频&#xff1f; …

arm 、stm32、linux该如何学习?有没有先后顺序,先学什么比较好?

先讲自己&#xff0c;我是从Arduino单片机入门&#xff0c;再到stm32 &#xff0c;再开发瑞萨&#xff0c;TI&#xff0c;然后学校教了51。这是一个奇怪的学习过程&#xff0c;所以当我第一次接触51单片机的时候&#xff0c;刚好我有一些资料&#xff0c;是我根据网友给的问题精…

deep learning 环境配置

1 NVIDIA驱动安装 ref link: https://blog.csdn.net/weixin_37926734/article/details/123033286 2 cuda安装 ref link: https://blog.csdn.net/qq_63379469/article/details/123319269 进去网站 https://developer.nvidia.com/cuda-toolkit-archive 选择想要安装的cuda版…