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

news2024/11/14 14:40:05

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向量。

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MongoDB - 集合和文档的增删改查操作

文章目录 1. MongoDB 运行命令2. MongoDB CRUD操作1. 新增文档1. 新增单个文档 insertOne2. 批量新增文档 insertMany 2. 查询文档1. 查询所有文档2. 指定相等条件3. 使用查询操作符指定条件4. 指定逻辑操作符 (AND / OR) 3. 更新文档1. 更新操作符语法2. 更新单个文档 updateO…

【AI前沿】深度学习:神经网络基础

文章目录 &#x1f4d1;引言一、神经元和感知器1.1 神经元的基本概念1.2 感知器模型 二、多层感知器&#xff08;MLP&#xff09;2.1 MLP的基本结构2.2 激活函数的重要性2.3 激活函数2.4 激活函数的选择 三、小结 &#x1f4d1;引言 深度学习是现代人工智能的核心技术之一&…

p12初步认识c语言

1.初识c语言 什么是c语言 c语言是一门计算机语言 计算机语言是什么 人和计算机交流语言 c/c/JAVA/python 语言发展&#xff1a; 二进制语言 硬件-电-正电/负电 1010001010101010101010101010手册 科学家 1010100010-ADD -助记符-汇编语言 B语言 C语言 C、---高级…

【全面介绍语言模型的原理,实战和评估】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步! 🥂语言模型的原理 🥂语言模型基于统计和机器学习的原理,目标…

实验1 —— 安全策略的练习

实验拓扑图 实验要求 1.DMZ区内的服务器&#xff0c;办公区仅能在办公时间内&#xff08;9&#xff1a;00-18&#xff1a;00&#xff09;可以访问&#xff0c;生产区的设备全天可以访问&#xff1b; 2.生产区不允许访问互联网&#xff0c;办公区和游客区允许访问互联网 3.办公区…

Java protobuf序列化

Protobuf概述 Protobuf&#xff08;全称&#xff1a;Protocol Buffers&#xff09;是由 Google 开发的一种语言中立、平台无关、可扩展的序列化协议。它用于高效地结构化数据的序列化和反序列化。Protobuf 的主要特点是其紧凑、高效和可扩展的编码格式&#xff0c;使其在各种网…

Nginx中文URL请求404

这两天正在搞我的静态网站。方案是&#xff1a;从思源笔记Markdown笔记&#xff0c;用MkOcs build成静态网站&#xff0c;上传到到Nginx服务器。遇到一个问题&#xff1a;URL含有中文会404&#xff0c;全英文URL则正常访问。 ‍ 比如&#xff1a; ​​ ‍ 设置了utf-8 ht…

mac安装配置cmake

本机是2015 macbook pro mid&#xff0c;已经有点老了&#xff0c;用homebrew下cmake老出问题 其实cmake官网安装也不麻烦 一、官网下载对应安装包 Download CMake 和所有dmg文件一样安装 二、改成命令行使用 一般来说 tutorial 给的都是命令行build 命令行的设置如下&am…

React Hooks学习笔记

一、usestate的使用方法-初始化state函数 import React, { useState } from "react"; function App() {const [count, setCount] useState(0);return (<div><p>点击{count}次</p><button onClick{() > setCount(count 1)}>点击</bu…

【TAROT学习日记】韦特体系塔罗牌学习(1)——愚者 THE FOOL 0

韦特体系塔罗牌学习&#xff08;1&#xff09;——愚者 THE FOOL 0 https://www.tarotchina.net/major-arcana0-vip/ 目录 韦特体系塔罗牌学习&#xff08;1&#xff09;——愚者 THE FOOL 0牌面分析1. 基础信息2. 图片元素 正位牌意1. 关键词/句2.爱情婚姻3. 学业事业4. 人际关…

原生小程序生成二维码并保存到本地

需求&#xff1a;我要在一个页面中生成一个二维码&#xff0c;并且这个二维码可以长按保存到本地或者发送给好友&#xff1b; 我这里是将生成的canvas二维码转换成图片&#xff0c;利用长按图片进行保存或转发 效果图&#xff1a; 第一步先下载对应的包&#xff1a; npm instal…

Web3知识图谱,一篇读完

这张图展示了区块链生态系统的架构和主要组件。以下是对图中内容的概括总结&#xff1a; 基础层&#xff1a; 底层基础设施&#xff1a;包括光纤网络、P2P网络、非对称加密、哈希算法、默克尔树和随机数生成。共识机制&#xff1a; PoW&#xff08;工作量证明&#xff09;: 比特…

C语言笔记31 •单链表经典算法OJ题-3.反转链表•

反转链表 1.问题 给你单链表的头节点 head&#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 2.代码实现&#xff1a; //3.反转链表 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <assert.h>typedef int …

华为模拟器ensp中USG6000V防火墙web界面使用

防火墙需要配置 新建拓扑选择USG6000V型号 在防火墙中导包 忘记截图了 启动设备 输入用户名密码 默认用户名&#xff1a;admin 默认密码&#xff1a;Admin123 修改密码 然后他会提示你是否要修改密码&#xff0c;想改就改不想改就不改 进入命令行界面 进入系统视图开启web…

【RHCE】基于用户认证和TLS加密的HTTP服务(HTTPS)

目录 一、创建用户账号 二、TLS加密 三、配置http服务子配置文件 四、创建访问http服务的文件夹以及输入重定向到文件 五、配置Linux本地仓库以及Windows下的本地仓库 六、基础操作 七、测试 一、创建用户账号 用户认证 # 创建两个账户 [rootlocalhost ~]# htpasswd -…

商业合作方案撰写指南:让你的提案脱颖而出的秘诀

作为一名策划人&#xff0c;撰写一份商业合作方案需要细致的规划和清晰的表达。 它是一个综合性的过程&#xff0c;需要策划人具备市场洞察力、分析能力和创意思维。 以下是能够帮助你撰写一份有效的商业合作方案的关键步骤和要点&#xff1a; 明确合作目标&#xff1a;设定…

网络协议(TCP三次握手,四次断开详解)

TCP的详细过程&#xff1a; TCP&#xff08;传输控制协议&#xff09;的三次握手和四次断开是其建立连接和终止连接的重要过程&#xff0c;以下是详细解释&#xff1a; 三次握手&#xff1a; 1. 第一次握手&#xff1a;客户端向服务器发送一个 SYN&#xff08;同步&#x…

深度探讨:无法恢复主文件表的困境与解救之道

在数据存储与管理的复杂世界中&#xff0c;主文件表&#xff08;Master File Table, MFT&#xff09;作为文件系统的核心组件&#xff0c;承载着至关重要的角色。一旦遭遇无法恢复主文件表的困境&#xff0c;用户将面临数据访问受限、文件丢失等严重后果。这通常是由于硬件故障…

火柴棒图python绘画

使用Python绘制二项分布的概率质量函数&#xff08;PMF&#xff09; 在这篇博客中&#xff0c;我们将探讨如何使用Python中的scipy库和matplotlib库来绘制二项分布的概率质量函数&#xff08;PMF&#xff09;。二项分布是统计学中常见的离散概率分布&#xff0c;描述了在固定次…

力扣 hot100 -- 动态规划(下)

目录 &#x1f4bb;最长递增子序列 AC 动态规划 AC 动态规划(贪心) 二分 &#x1f3e0;乘积最大子数组 AC 动规 AC 用 0 分割 &#x1f42c;分割等和子集 AC 二维DP AC 一维DP ⚾最长有效括号 AC 栈 哨兵 &#x1f4bb;最长递增子序列 300. 最长递增子序列…