基础综合示例

示例:从两句话到三维表示

基础综合示例约 4.1 千字全部数字可手算1 组分步图解

本例衔接基础篇F01—F06,用两句话和一张小型参数表,串联编号、组批、形状与查表。先计算小规模表示,再解释[2,128,4096]。所有数字都可以手算。

本章目录
动态图解 · F05

Embedding是查一行,不是把编号转二进制

一组浮点数怎样替代一个Token编号?

词表编号像目录的页码;Embedding像打开那一页看到的数值卡。页码2并不会通过“转成0010”得到语义。模型取到的是参数表里事先存好的小数和负数,后续层再根据上下文加工它。

EEmbedding参数表:每行对应一个词表项。
查表以整数编号选择一整行。
上下文化同一初始向量经过不同上下文后得到不同表示。

输入与适用条件:完全沿用F05正文6×4小数参数表。图示的维度是特征宽度,不是二进制位数。

1 / 5 · 为“我”取第1行

第1步,共5步

窄屏可左右滑动图形,或点击“放大图形”。文字解释紧随图后。

Embedding是查一行,不是把编号转二进制:为“我”取第1行6行4列参数表 EPAD0000我0.2-0.10.70.4爱-0.30.80.10.5学习0.60.2-0.40.9你0.1-0.50.90.3!-0.20.40.5-0.6我 → 编号1用编号选一行,不对编号做二进制展开。取出的四个特征0.2-0.10.70.4

编号1定位Embedding表的第1行,得到[0.2, -0.1, 0.7, 0.4]。这一行用来表示本例Token“我”,不会因为同批还有其他句子而改为另一行。

E[1] = [0.2, -0.1, 0.7, 0.4]

默认静止。用“下一步”看完解释再继续;播放到最后一步自动停止。键盘聚焦播放器后,可用左右键逐步查看、空格播放/暂停。图中颜色辅助区分,含义同时用文字注明。

为什么需要

编号方便定位项目,但直接比较编号大小不能表达任务所需关系。

怎样实现

为每项取出可训练的向量,再交给后续运算。

可能的代价与误解

误把0/1教学矩阵当成所有Embedding的格式;误以为同一个词在所有层都不变。

如何判断是否做对

逐项检查原文、编号、取表行号、输出行顺序四者一一对应。

1.文字如何转换为编号

我们用两条文字:“我爱学习”和“你爱”。分词器是一套把文字片段对应到整数编号的规则。本页人为规定它把第一句分成“我/爱/学习”,第二句分成“你/爱”。这只是为了算得清楚,不是任何商业模型的真实分词结果。

文本片段 我 爱 学习 你 ! 填空用的特殊项PAD
教学编号 1 2 3 4 5 0

因此,第一句成为[1,2,3],第二句成为[4,2]。一个编号只回答“是哪一项”,不回答“意思是什么”。4比1大,不表示“你”比“我”更重要。

现在还没有预测答案。我们只把文字换成了以后可以拿来找位置的编号。

2.“组批”到底组了什么

把两条输入交给同一次运算,一起处理,叫组批。这一组是一个批次(batch);批里有2条输入,所以批大小B=2。

这里B只是“有几条”的缩写。没有引入神秘数学对象。两条输入依然各算各的,不能把第二条用户输入当成第一条用户的上下文。

但两条编号列表一条长3、一条长2。为了先用普通规则表格计算,我们给短的那条末尾放一个占位编号0:

第0条输入:1  2  3      真实有3个片段
第1条输入:4  2  0      真实有2个片段,末尾0只是填空

这个动作叫补齐(padding)。补齐后每行安排3个位置,写作T=3。T说的是安排了几个位置;第二句话真实长度仍是2。占位项不是模型突然理解出的一个新词。[F-PADDING]

3.为什么编号表写成[2,3]

两行,每行三个编号,所以表的大小写成[2,3]。这种描述大小的写法叫形状(shape)。

“里面存着[[1,2,3],[4,2,0]]”是在说内容;“形状是[2,3]”是在说大小。不要把两者混淆。编号表含2×3=6个整数。

在机器学习程序中,像这样规则排列的一组数字叫张量(tensor)。本页先把它理解成“数字容器”:一排数、表格、若干张同样大的表,都可以用张量来装。两行三列的编号表是一个有两个轴的张量:第一个轴选哪句话,第二个轴选那句话里的哪一个位置。[F-TENSOR]

4.为什么还要把编号换成一排数

编号可以找到某一项,但直接比较编号大小没有语义意义。模型为每个词表项准备一排可以被后续计算使用的数字,把这些行放成一张表,叫Embedding表(嵌入表)。

先不去猜每个数代表什么意思。本页每行只放4个数,完整表如下。它们是人为设置的小数和负数,不是真实语言模型训练得到的参数。采用小数而不是只有0和1,是为了避免把Embedding误认成二进制编码:

查找编号 对应片段 第0个数 第1个数 第2个数 第3个数
0 PAD 0.0 0.0 0.0 0.0
1 我 0.2 -0.1 0.7 0.4
2 爱 -0.3 0.8 0.1 0.5
3 学习 0.6 0.2 -0.4 0.9
4 你 0.1 -0.5 0.9 0.3
5 ! -0.2 0.4 0.5 -0.6

这张Embedding表有6行、4列,形状是[6,4]。6是词表项数:一共有多少种可以查找的编号。4是表示宽度d:每项用几个数表示。本页d=4。

编号、二进制、One-hot与Embedding不是一回事:“爱”的编号为2;如果只讨论它在电脑里如何以8位保存,可以写成00000010;如果用长度6的独热标识,可以写成[0,0,1,0,0,0];但本例真正查出的Embedding是[-0.3,0.8,0.1,0.5]。第三个轴就是这一排4个浮点数的索引方向,不是二进制位数。实际查表只需要编号,不需要先构造One-hot。

6、3、4分别回答不同问题。 词表有6种可用项,不意味着一句话必须长6;一句话安排3个位置,不意味着每项只用3个数;每项用4个数,也不意味着一定有4个能人工命名的语义属性。

5.“查Embedding”真的只是先找到对应的行

先看第一句“我爱学习”:按本例的Token划分,它依次是“我/爱/学习”,所以编码后的编号才是[1,2,3]。这里不是拿三个随机数字找行,而是依次把原句的三个Token转换成Embedding向量:编号1对应“我”,编号2对应“爱”,编号3对应“学习”。

“我”   (编号1) → [0.2,-0.1,0.7,0.4]
“爱”   (编号2) → [-0.3,0.8,0.1,0.5]
“学习” (编号3) → [0.6,0.2,-0.4,0.9]

于是第一句成为:
[[0.2,-0.1,0.7,0.4],
 [-0.3,0.8,0.1,0.5],
 [0.6,0.2,-0.4,0.9]]

原来“我”这个位置只存编号1;现在这个位置对应一排[0.2,-0.1,0.7,0.4]。并没有把1转换成四位二进制码,而是按编号1读取参数矩阵的一整行。这样的每个Token向量以后还会参与注意力计算。[F-EMBED]

第二句则是“你爱”:它实际只包含“你/爱”两个Token,编码为[4,2]。为了和第一句放在同一批次里计算,才补成[4,2,0]。这表示“你”(4)、“爱”(2),加上一个不属于原句的PAD占位(0)。因此依次查表取的是“你”的向量、“爱”的向量,以及PAD占位的向量:

第二句成为:
[[0.1,-0.5,0.9,0.3],
 [-0.3,0.8,0.1,0.5],
 [0,0,0,0]]

这不是把“你爱”编码成三个真实词:第三行只是为了补齐到长度3。查表得到的仍是逐Token的初始数值表示,而不是对完整句意的一次理解。注意“爱”在两句话里,初次查表得到同一排数。这不表示它永远不看上下文;后面的网络会把当前位置与允许读取的其他位置结合,产生新的表示。查表是起点,不是全部理解过程。

6.现在为什么多出一层[2,3,4]

把两句话的结果合在一起,是两张表,每张3行、每行4个数。于是整体形状为[2,3,4]。

形状中的数 这里具体数什么
2 两条输入,因此有两张表
3 每条输入安排三个位置,因此每张表三行
4 每个位置用四个数,因此每行四列

总共2×3×4=24个数。原来6个编号,各自换成4个数,所以也可以算成6×4=24。

从下标理解第三个轴:第一个下标选择“我爱学习”还是“你爱”;第二个下标选择其中的哪个位置;第三个下标选择该Token向量的第几个数。例如H[0,1,0]=-0.3,是第一句话的第二个Token“爱”的初始表示第一个数。新增的是每个位置的数值特征轴,不是额外的词或二进制位。

“这是三维张量”说有三个轴;“每个位置是四维向量”说每排有四个数。这里维的两种说法要区分。向量就是此处有顺序的一排数,不需要先想象四维空间。

7.将表示扩展为[2,128,4096]

现在只换三个大小,不换计算道理。

  • B=2:本批两条输入。
  • T=128:每条输入补齐或安排到128个位置。
  • d=4096:每个位置查表后用4096个数表示。

编号表有两行、每行128个整数,所以是[2,128]。每个整数再换成长度4096的一排数,整体就是[2,128,4096]。

它含2×128×4096=1,048,576个数。4096不是Token数,不是词表大小,也不是整个模型的参数总量。 它叫隐藏维度或隐藏表示宽度,意思是模型用这么宽的一排数来表示每个位置。更深的层通常还沿用这个宽度,但会改变数字内容。

若每个数用2字节保存,这一份输出约占2MiB。字节是存储大小的单位,MiB是1,048,576字节。这个估算只针对这一份数据,不包含模型全部参数、缓存或临时计算空间。F06会完整讲存储精度与设备。

8.“放到设备”没有改变这句话的意思

设备在这里指执行计算的处理器,例如CPU或GPU。CPU是通用处理器,GPU擅长并行执行大量合适的数值运算。为了让运算执行,程序要让输入数据与模型参数位于相容的设备和存储格式中。

可以把[1,2,3]存到内存,再复制到GPU显存中;它们仍然是相同编号,并没有因为移动就变得更“智能”。显存是GPU可直接使用的一类存储空间。移动数据可能花时间,空间也可能不够,所以这是实在的工程步骤。

在常见输入Embedding层中,查找地址使用整数编号,取出来的参数通常是浮点数;浮点数就是可以近似表示0.1、−0.7等数值的计算机数值格式。设备、格式和形状是三种不同属性。

9.还要带哪几份“辅助信息”

第一份是填充掩码:告诉后续计算哪些位置是真的。

第一句:[1,1,1]   都是真的
第二句:[1,1,0]   最后是补齐位置

这里的0/1不是Token编号,而是“能不能算作有效内容”的标记。即使PAD的Embedding恰好全0,也不代表后续计算自然会忽略它,因此仍需正确处理这些位置。

第二份是注意力掩码(attention mask)。注意力先理解为“为当前这个位置挑出可以参考的位置,再按不同份额结合它们的数字”。掩码决定“能参考谁”,不是决定“参考多少”。后者要到F09–12用加权平均算出来。

生成下一Token时,训练与运算通常要遵守不能偷看未来的规则。对三位置例子,可以读的位置是:

当前查询位置 能参考位置0吗 位置1吗 位置2吗
位置0 能 不能 不能
位置1 能 能 不能
位置2 能 能 能

这是因果掩码。第二句话还必须把作为填充项的位置2排除。模型内部不同接口使用的掩码形状和真假含义不一定相同;本页表格只解释可见关系,不冒充某个API的入参。

第三份是位置编号(position IDs)。比如真实的三个位置记为0、1、2。Token ID回答“哪个片段”,位置ID回答“出现在哪里”,二者不是同一列。采用左补齐或缓存时,逻辑位置与表格列号可能不同,F13会分别举例。

最后可能有KV缓存(KV Cache)。缓存就是保存已经算过、后面还能复用的结果。第一次从头处理时通常没有历史缓存;继续生成时,可以带回之前各层算好的部分数字,避免从头重算。这不是长期记忆,也不是新知识进入模型参数。K和V的含义、为什么可以复用、哪些改动让它失效,会先在F11解释注意力,再在F16完整推演;此页不要求先背这两个字母。[F-CACHE]

10.完整过程小结

把两条独立输入一起计算,并把较短的编号列表补到本批安排的长度。由此得到一张两行、每行128个编号的表。模型根据每个编号,从自己的Embedding参数表中取出一排4096个数,所以结果是两张128行、4096列的表。程序同时准备有效位置、哪些位置能互相参考、各个真实片段的位置编号;若这是继续生成,还带入可复用的历史计算结果。随后开始各层的注意力与其他数值变换。Embedding查表本身已经属于模型数值表示的计算步骤,不是查完之后才第一次碰到神经网络。

你现在不需要先理解Attention的完整公式,便能解释这一步的每个对象。下一段若直接出现Q、K、V或softmax,先走F07→F09→F11;不是靠猜缩写读下去。

自检:请先口头回答,再看答案

问题一:词表1000项、三条输入、每条10个位置、每项用8个数表示,Embedding表和查表结果分别多大?

查看参考答案收起参考答案
参数表是[1000,8],编号表是[3,10],查表结果是[3,10,8]。1000决定可以查多少种条目,3和10决定这一批查了多少个位置。

问题二:为何同样写0,有时表示PAD编号,有时表示掩码里的不能看?

查看参考答案收起参考答案
它们属于不同数据对象。input_ids的0用于找词表行;有效性或可见性表里的0是一条运算标记。不能只看数字相同就混为一谈。

问题三:Embedding的第2个数是不是永远表示情绪?

查看参考答案收起参考答案
没有这种一般保证。它是训练得到的分布式表示的一部分。教材里的数字只演示读取和计算过程,不给每一列强行贴语义标签。

问题四:组批时第二个用户会读取第一个用户的内容吗?

查看参考答案收起参考答案
普通独立样本batch不应如此。批轴安排一起运算,不是把样本拼成一条上下文。真实系统还需落实租户和缓存隔离。
记录保存在本机浏览器。

输入关键词即可检索。

↑ ↓ 选择 Enter 打开Esc 关闭 · 仅本地搜索

阅读设置

阅读设置仅保存在本机浏览器,不上传任何数据。