上一章,我们把文字变成了token编号。但把“猫”记为0,把“狗”记为1,电脑就知道它们都是动物了吗?如果再把“雨”记为2,它会不会误以为“雨”比“狗”大一倍?
编号只负责找到对象。要让不同对象之间的关系参与计算,我们还需要一种可以比较、组合、调整的表示。向量提供一组数,矩阵规定怎样把这些数重新组合。理解它们,后面看到注意力、神经网络和检索时,就不必把所有方框都当作魔法。
本篇的目标,是跟踪一种信息怎样换成另一种可计算的表示。先固定词表与全部参数,只改变输入;遇到训练时再明确指出哪些数可以改。本篇只用加减乘除,以及计算器上的平方根,从一张很小的表开始。
1.embedding的第一步,是按编号取一行
假设我们人为规定一个只有四项的教学词表:“猫”“狗”“雨”“伞”分别是编号0、1、2、3,每项都恰好是一个token。真实分词未必如此。再给这四项安排一张表:
- 编号0,猫:[1,1]
- 编号1,狗:[2,1]
- 编号2,雨:[0,2]
- 编号3,伞:[−1,2]
输入编号1,就取出[2,1]。这一步叫embedding查表,embedding通常译作“嵌入”。表里的数字都由我们手填,只用于计算演示,并非从真实模型提取的词义。
向量就是按顺序排列的一组数。[2,1]含两个数,称为二维向量。维度是每个向量有多少项,与输入句子有几个token是两回事。三个token各有二维表示,就会得到三行、每行两个数;句子变长,行数增加,每行的宽度可以不变。
装着所有基础向量的数字表叫embedding矩阵。若词表有V项,每项有d维,表的形状就是V×d,有V乘d个数。这里V是词表项数,d是表示宽度;字母只是避免反复写长句。PyTorch的Embedding定义
真实模型中,这些数通常属于可训练参数。训练会调整它们,使它们配合后续计算完成预测。编号则仍是查表地址,不会因为“狗”变得更像“猫”,就从1逐渐变成0.3。具体怎样调整数字,第07章再讲。
查表本身不会理解句子。即便把整张表初始化成随机数,仍然能够按编号取行;只是这些数起初未必形成对任务有用的关系。可学习的关键是表能随训练改变,并且后续计算也配合改变。
还有一种表示身份的方法:用[0,1,0,0]代表编号1,只有对应位置为1,其他位置为0,叫独热表示。拿它对表的各行做加权求和,也会选出第二行。这个等价关系帮助我们理解查表,但实际实现不必先创建一条很长的独热向量,再做大量与0相乘的运算。
2.有了坐标,为什么仍不能给每一维写词典
二维向量可以画成平面上的箭头:[2,1]表示横向走2格、纵向走1格。更高维只是拥有更多坐标,我们难以画出,却仍能逐项计算。
很容易产生一个诱人的想法:把第一维叫“动物程度”,第二维叫“雨天程度”,是不是就能读懂模型?在自行设计的特征表里可以这样约定;在训练得到的embedding里,通常没有这种保证。
训练只要求整套计算对任务有用,并没有要求某个坐标用一个人类词语命名。一种区别可能分散在许多维里,一维也可能参与多种区别。上面的教学坐标因此只叫“第1维”“第2维”,不能拿来声称猫的某种属性等于1。
想象把一张地图连同所有箭头一起旋转:坐标数值变了,箭头之间的夹角和距离却可以保持。仅凭某一项变大,就断言“这个概念增强了”,会忽略整套表示之间的关系。真实模型的可解释性研究需要更多证据。
稠密表示的价值之一,在于让后续计算有机会复用数值模式。假如两种动物在相关方向上接近,学习一种动物的用法,可能帮助预测另一种动物的用法。这种“可能迁移”还取决于任务、数据和后续计算,不能由两个向量接近直接保证。早期神经概率语言模型研究
3.先手算一种比较,再看它漏掉了什么
取查询向量q=[1,1],以及两个候选a=[2,1]、b=[0,2]。字母只给三组数起名字。最简单的比较之一叫点积:把对应位置相乘,再相加。
q与a的点积=1×2+1×1=3。
q与b的点积=1×0+1×2=2。
点积把多维关系压成一个分数。在这个例子里,a得分更高。但如果把b扩大五倍,变成[0,10],分数就变成10。它的方向没变,却超过了a。因此,点积同时受到方向与长度的影响,不能一概解释为“意思更相近”。
如果希望主要比较方向,可以用余弦相似度:先算点积,再除以两个向量长度的乘积。二维向量的长度用勾股定理得到,例如[2,1]的长度是√5。于是:
- q与a的余弦=3÷(√2×√5),约为0.949
- q与b的余弦=2÷(√2×2),约为0.707
- q与[0,10]的余弦仍约为0.707
它消除了单纯放大长度的影响。对非零向量,余弦范围在−1到1之间;方向相同为1,垂直为0,完全相反为−1。零向量没有方向,不能直接套用这个除法。
看图1时,先按编号从表里取数,再把同一组数画到坐标上。查表只选择一行,点积与余弦才是在这些行之间计算关系。

图1|先按编号查出二维向量,再在同一坐标系里比较q、a、b。点积同时受方向和长度影响;把b放大5倍会改变点积,却不改变与q的余弦。坐标轴只表示两个数值位置,相似度没有事实概率含义。
在实际比较中,也可以先把每个非零向量都缩放到长度1,再计算点积。此时两边长度的乘积就是1,点积便等于余弦。这个缩放叫长度归一化,它不会把每个坐标都变成正数,也不是把各项加起来凑成1。向量的长度与下一章概率的总和,是不同的量。
余弦0.949并不意味着“有94.9%的概率是同义词”。它只是指定表示、指定算法产生的几何分数。反义词也可能共享很多语境;两段内容都在讲同一个产品,也可能一段说支持退款,另一段说不支持。是否相关、是否同义、是否互相矛盾,需要按任务分别判断。
4.矩阵怎样一次完成许多加权组合
比较两组数还不够,模型也要把已有信息变成下一步需要的信息。矩阵可以承担这种变换。
我们沿用横排向量x=[2,1],安排一张两行三列的权重表W。第一行是[1,0,1],第二行是[0,2,−1]。这里W的每一列,都给出“怎样把两个输入数合成一个输出数”的规则。
第一列是[1,0]:输出第1项=2×1+1×0=2。
第二列是[0,2]:输出第2项=2×0+1×2=2。
第三列是[1,−1]:输出第3项=2×1+1×(−1)=1。
所以xW=[2,2,1]。二维输入经过这张表,变成了三维输出。相乘前,中间的尺寸必须对得上:输入有两项,W必须为每个输出提供两个权重。
请注意,得到三个数,不等于凭空增加了新事实。它们都是原来两个数的组合。更多输出位置,可以方便后续计算使用不同组合,却不能仅凭“升维”证明信息增加或能力提高。
现在把三个输入向量叠成矩阵X:第一行[1,1],第二行[2,1],第三行[1,1]。每行都使用同一个W,得到的三行依次是[1,2,0]、[2,2,1]、[1,2,0]。用形状简写:
X的3×2,乘W的2×3,得到输出的3×3。
这就是批量加权变换:同一套规则同时处理多行输入。你可以只核算第二行第三项,确认它仍是2减1等于1。矩阵乘法把许多这样的乘加整理在一起,便于计算机高效执行。
X是这次输入产生的数据,W在这个例子里充当变换参数。形状相同的数字表也可能扮演不同角色,所以“都是矩阵”不等于“都是需要训练的参数”。矩阵描述排列与计算方式,数据和参数描述用途。
图2圈出第二行第三列的输出。沿着这一格反向找回输入行与权重列,就能独立检查矩阵乘法;其他格也按同样的规则计算。

图2|从一行输入到整批输入,沿用同一套加权规则。颜色对应一个输出列的权重;注意第一行和第三行相同,输出也相同。这一步尚未让不同位置互相读取信息。
5.同一个token,怎样得到不同的上下文表示
刚才的最后一句很关键。如果每一行只单独乘同一个W,两处相同的“苹果”就仍得到相同结果。这样的计算本身无法分清“我吃了一个苹果”和“这台电脑来自苹果”。
假设两处“苹果”恰好对应同一个token,在参数固定的查表阶段,它们确实取出同一行基础向量。这种不随当前句子改变的表示,可以称为静态表示。
接下来,模型让当前位置与它能读取的上下文共同参与计算。“吃了一个”和“电脑来自”带来不同信息,当前位置便可能形成不同的向量,称为上下文表示。上下文表示是本次计算产生的中间结果;它改变了,不代表embedding表当场被重新训练。
为了让“上下文改变表示”也能手算,我们另做一个极简演示。把两处“苹果”的共同基础向量都设为e=[1,1];把两段上下文已经提供的数值摘要分别设为c甲=[2,0]、c乙=[0,3]。暂时规定后续计算只是逐项相加:h=e+c。于是h甲=[3,1],h乙=[1,4]。
这三个输入向量和相加规则都是人工设定,不是模型对“苹果”的实测,也不说明“吃”和“电脑”天然对应哪两个数。这个小计算只证明一件事:同一个基础向量,经过同一套固定计算,只要读取的上下文不同,就能得到不同结果。真实模型如何生成、选择并混合上下文信息,第08章再展开。

图3|两支路从同一个token ID取出同一行e;只改变本次上下文c,按同一教学规则h=e+c得到不同激活。embedding表与计算规则均固定,图中没有参数更新。
顺序也不能被忽略。假设“猫”“追”“狗”各是一项token,只把三个静态向量相加或取平均,那么“猫追狗”和“狗追猫”会得到同一组数,因为加法换顺序不改变结果。可是两句话里追赶者变了。要保留这类区别,计算必须有办法利用位置与组合关系,不能只收集出现过哪些词。
这条思路有公开研究依据。2018年的ELMo研究用上下文相关的词表示处理同一词在不同语境中的用法。它的具体结构与今天常见的生成模型不同,但“基础身份相同,当前表示可以不同”这个区分仍然重要。ELMo原论文
上下文也有可见范围。预测下一token的模型通常只能使用当前前缀,不能在这一步偷看尚未生成的后文。其他任务可以允许读取左右两侧。位置和信息可见范围怎样进入计算,第08、09章会逐步展开。
6.打开一个真实模型配置,能读出什么
Qwen团队公开的Qwen3-0.6B配置,在固定版本中给出:vocab_size为151936,hidden_size为1024。配套实现用这两个数创建token embedding表,因此表有151936行、每行1024个数,共155,582,464个数。官方模型配置、对应结构实现
151936是这里的模型词表槽位数,1024是每个token的表示宽度。它们都不是“能记住多少知识”的直接计数,也不说明有1024个可命名的概念。输入100个token,查表结果就有100行;不能把它误读成100维向量。
再看同团队的Qwen3-Embedding-0.6B。它面向文本表示任务,官方示例先处理完整文本,取最后一个有效token的上下文表示,再做长度归一化,用所得向量比较查询和文档。模型卡说明它支持32至1024维的输出。官方文本embedding模型卡
这里的整段文本向量,与输入端按token编号查到的一行向量,处在不同位置。前者已经经过上下文计算,并针对表示任务训练。看见“embedding”这个名字,要继续问:它代表一个token、一个位置,还是整段文本?它是怎样得到的,用什么任务训练的?
7.向量好用,也有选择成本
更宽的表示,需要存储和计算更多数字,却不保证检索更准。比较效果时,还应看训练目标、语言、文档类型、输入长度以及评测问题。不能把不同模型的维度当作统一的质量刻度。
点积和余弦也各有取舍。归一化有意去掉长度差异,适合方向更有用的比较;某些训练目标可能让长度也承载有用信号,贸然抹掉它就会损失信息。应优先遵循模型推荐的比较方法,再用自己的样本检验,而非把余弦当作所有向量的默认答案。
查询和资料也需要使用兼容的表示方法。两个模型都输出1024维,不意味着第一个模型的查询可以直接和第二个模型的文档比较;相同长度不保证坐标系统对齐。工程中检查矩阵形状,类似检查接口的输入输出尺寸:它能拦住“2项输入接到3项权重”的错误,却不能验证两边的数代表同一种信息。尺寸检查和语义兼容检查各有职责。
即使用同一个模型,整段压成一个向量也可能弱化日期、否定词、例外条件等细节。需要精确匹配合同编号或金额时,关键词、字段过滤和原文核对仍有作用。相似度适合帮助找到候选材料,材料是否真的支持结论,还需要继续检查。
本章练习
题目
问题1|从编号取出一批向量
使用本章四项教学词表与embedding表,输入ID序列[1,0,1]。写出三行查表结果,并分别说明整张表与本次结果的形状。
问题2|检查一格乘法
输入x=[2,1],权重W的第一行[1,0,1],第二行[0,2,−1]。求xW,并说明为什么输出有3项。
问题3|改变上下文,再检查哪份数变了
在图3的教学运算h=e+c中,e仍为[1,1],把c换成[−1,2]。算出h,并判断这次计算有没有修改embedding表。
问题4|理解几何分数
q=[1,1],b=[0,2]。把b扩大5倍后,点积和余弦各是多少?这些数能直接表示事实正确率吗?
思考提示
提示1|对应问题1
编号从0开始;重复编号会选中同一行,输入位置仍需保留。
提示2|对应问题2
每一个输出对应W的一列;逐列做输入与权重的乘加。
提示3|对应问题3
相加规则固定,逐项计算;把输入数据和存储参数区分开。
提示4|对应问题4
放大会改变长度,方向保持不变;对余弦同时检查分子与分母。
参考答案与解析
答案1|对应问题1
查表结果依次为[2,1]、[1,1]、[2,1]。整张表是4×2,本次结果是3×2。两次ID 1得到同一基础向量,但分别占两个序列位置。
答案2|对应问题2
三个输出为2×1+1×0=2、2×0+1×2=2、2×1+1×(−1)=1,所以xW=[2,2,1]。W有3列,每列从2项输入组合出1项输出,因此得到3项。
答案3|对应问题3
h=[1+(−1),1+2]=[0,3]。这里只换了本次上下文向量并重新计算激活,没有修改embedding表,也没有发生参数训练。
答案4|对应问题4
q与5b=[0,10]的点积为10;余弦为10÷(√2×10)=1÷√2,约0.707,与放大前相同。两者都是指定表示下的几何分数,不能直接解释为事实正确率。
下一章
现在我们已经能跟踪“编号→一行数→多次组合”的路径。但当模型准备输出时,它往往不会立刻挑出唯一答案,而是先给每个候选打分。这些分数为什么要变成概率,又怎样判断这次预测好不好?下一章,从分数走到损失。