🟡序章:Transformer的并行缺陷
Transformer有超强的视力,它的核心武器------自注意力机制正是让它能一步到位地处理句子中的所有词,计算它们之间错综复杂的关系,这比 RNN/LSTM 那样一个词一个词地"读"要快得多,也强大得多。所以它可以一瞬间看到一本书里的每一个字(并行处理)。但他有个的缺陷:他看到的所有字都像是漂浮在空中,分不清哪个字在哪个字前面。对他来说,"我爱你"和"你爱我"看起来毫无区别,都是"我"、"爱"、"你"三个字。
而语言中,顺序就是一切。"狗咬人"和"人咬狗"天差地别。因此,Transformer 必须有一个额外的机制来弥补这个缺陷,每个漂浮的字挂上一个"位置坐标牌"。这个机制,就是位置编码PE (Positional Encoding)。
我们以 "小姜今天没有撸铁"这个句子为例,看这个"坐标"是怎么制作,怎么挂上去的。
🟡第一步:词语到数字------Tokenization词元化
计算机只认数字(本质还是二进制)。第一步就是把文字转换成它能理解的数字ID。这个过程叫 Tokenization。
- "小姜" -> Token 1、 "今天" -> Token 2、 "没有" -> Token 3、"撸铁" -> Token 4
实际应用中模型其实会用更细的粒度,比如把"撸铁"拆成"撸"和"铁"两个子词(Subword),原理完全一样。
🟡第二步:词语到语义------Embedding (词嵌入)
有了数字ID,模型依然不知道这些词是什么意思。我们需要一个"含义字典",把每个ID转换成一个具有意义的向量。这个字典就是 Embedding Layer。
🔥 千万别混淆Embedding Layer 和Embedding Model。
Embedding Layer 只是一个层而已,是一个静态字典,不能单独使用。而 Embedding Model 是一个完整的神经网络架构,用于训练或生成词向量。像 Word2Vec 就是一个 Embedding Model,它通过预测上下文等任务训练出词向量,训练完成后输出的其实就是一个固定的 Embedding Layer,没有自注意力,不能根据上下文动态改变词义。而像 BERT 也是Embedding Model,它不仅包含 Embedding Layer,还通过自注意力机制动态生成上下文相关的语义向量,能真正体现词在不同语境中的意义。
- 向量维度 (
d_model
) : 我们设定为 5维,方便观察。真实模型中通常是 768 或更高。 - "小姜"的肖像: 可能在"人名"这个特征维度上数值很高。
- "撸铁"的肖像: 可能在"动作"这个特征维度上数值很高。
这些特征具体是什么,我们不用管,模型会在训练中自己学习。假设模型学完后,我们得到了每个词的"含义向量"
- Token 1 ("小姜") :
embedding_小姜 = [0.1, 0.5, -0.2, 0.8, 0.3]
- Token 2 ("今天") :
embedding_今天 = [-0.3, 0.7, 0.1, -0.5, 0.9]
- Token 3 ("没有") :
embedding_没有 = [0.6, -0.1, 0.3, 0.2, -0.4]
- Token 4 ("撸铁") :
embedding_撸铁 = [-0.4, 0.2, -0.7, 0.9, 0.1]
到此为止,我们有了四个包含"词义"的向量。但就像前面说的,如果我们把这四个向量直接丢给 Transformer,它看到的是一团乱麻,不知道谁是谁的前后桌。
🟡 补充: One-Hot Encoding (独热编码)------最纯粹的稀疏编码
在 Tokenization 和 Embedding 这俩环节之间,还存在一个"稀疏编码"的概念阶段。切记,这是概念阶段, 是因为在实际操作中,它被 Embedding 层这个更高效率的机制"吸收"掉了。但讲清楚这个东西可以让你对 Embedding 的理解瞬间清晰好几倍。
在你得到 Token ID 之后,比如:
- "小姜" -> ID: 28、"今天" -> ID: 15、 "没有" -> ID: 99、 "撸铁" -> ID: 1024
在理论上,最朴素地表示这些词的方法,就是 One-Hot Encoding,假设我们的整个词典里有 10,000 个不同的词(Tokens)。那么,我们可以用一个长度为 10,000 的向量来表示任何一个词。这个向量只有一个位置是 1,这个 1 所在的位置,就对应着这个词的 ID,其余的位置,全部都是0。举个例子 (假设词典大小为 10,000):
- 小姜" (ID=28) 的独热编码向量是:
[0, 0, ..., 0, 1, 0, ..., 0]
(只在第28个位置是1) - 今天" (ID=15)的独热编码向量是:
[0, ..., 0, 1, 0, ..., 0]
(只在第15个位置是1) - 撸铁" (ID=1024)的独热编码向量是:
[0, ..., 0, 1, 0, ..., 0]
(只在第1024个位置是1)
这种编码方式虽然简单纯粹,但有几个致命的缺陷,这也是为什么我们需要 Embedding 层的原因:(1)首先是维度灾难和计算效率低下,如果你的词典有5万个词,那每个词的向量就是5万维,两个5万维的向量做乘法,其中99.99%的计算都是"乘以0",这是巨大的浪费,(2)而且点积本身也没任何意义,这就是最致命的一点,因为任意两个不同的独热编码向量都是正交的。这意味着它们的点积永远是0。 对于模型来说,"国王"和"王后"的相似度,与"国王"和"香蕉"的相似度,竟然是一样的(都是0),这完全丢失了词语之间的语义关联。
Embedding 层的作用,就是为了解决上述稀疏编码的所有问题。你可以把 Embedding 层想象成一个高效的可学习的"压缩机"。输入一个词的 ID (比如 28)。输出一个低维度的、包含丰富语义的稠密向量。从概念上讲,Embedding 层就是一个巨大的 "查询表" 而已。你可以想象它是一张有 10,000 行、5 列的表格(行数=词典大小,列数=Embedding维度)。
erlang
Embedding Layer
| dim_0 | dim_1 | dim_2 | dim_3 | dim_4
------|--------|--------|--------|--------|--------
ID 0 | ... | ... | ... | ... | ...
... | ... | ... | ... | ... | ...
ID 15 | -0.3 | 0.7 | 0.1 | -0.5 | 0.9 <-- "今天"的Embedding
... | ... | ... | ... | ... | ...
ID 28 | 0.1 | 0.5 | -0.2 | 0.8 | 0.3 <-- "小姜"的Embedding
... | ... | ... | ... | ... | ...
ID 1024| -0.4 | 0.2 | -0.7 | 0.9 | 0.1 <-- "撸铁"的Embedding
... | ... | ... | ... | ... | ...
当我们给 Embedding 层输入 ID 28
时,它就去这个大表格里,把第 28
行的那个 5 维向量取出来,作为输出。这个大表格里的所有数值,都不是固定的,它们是模型的可训练参数。在模型训练的过程中,这些数值会不断被优化调整,最终使得意思相近的词在向量空间中的位置也相互靠近。怎么训练?那就是靠神经网络BP训练了
🔥Embedding Layer 本身在训练完成后是静态的。无论是 Word2Vec 还是 Transformer
因为Embedding 层本质上就是一个固定的查询表:一旦模型训练完成,这个矩阵就固定下来了。输入相同 ID就会输出相同向量,对于同一个词 ID无论是 Word2Vec 还是训练好的 Transformer 模型,Embedding 层本身总是会输出完全相同的那个 D 维向量。这一点上,两者没有区别。所以再次强调,推理阶段(使用模型时)的参数是冻结的,不变的。
🔥Transformer的"动态语义" 不是 Embedding Layer本身,而是整个架构最终输出的词表示
这才是关键的区别: Word2Vec 模型输出的就是EmbeddingLayer这个表 。 因为Word2Vec 模型本身非常浅,它的输出层(那个 <math xmlns="http://www.w3.org/1998/Math/MathML"> W W </math>W 矩阵)只用于训练,最终产品就是那个 Embedding 矩阵,没有下一步了!所以它没啥使用阶段,没有推理阶段,它就是训练出一个表给被人当做一个层用而已。
而Transformer是有训练阶段和推理阶段的,Embedding Layer 仅仅是模型的第一层而已,提供个基本语义就行,真正的动态上下文理解能力是由后续强大的 Transformer 层赋予的。想象你是一个机器人,面对一个对话或句子,你需要判断"苹果"是水果还是手机。你会:
- 读取"苹果"的基础属性(TokenID 直接从 Embedding Layer 里去找稠密向量 )。
- 观察周围词(上下文)的描述(进入到注意力层,Query--Key 机制)。
- 根据这些描述决定你更应该关注哪几个词(注意力分配)。
- 从这些词那里"取材"来补充或调整你对"苹果"的理解(加权组合 Value 向量)。
🟡 第三步:词语与位置------Positional Encoding
首先回答这个问题,为什么同一位置在不同句子里,位置向量必须是一样的?
- 因为位置编码不关心词的内容,只关心句中顺序,你八竿子打不着的句子无所谓,但是位置3的PE,都是一样的
- 它的目的只是给模型一个"坐标系"而已,让模型去组合词Embedding和位置Embedding共同决定含义。
- 词Embedding告诉你"这是什么词",位置Embedding告诉你"它在什么位置"。
因为位置向量在任何上下文里都一致,模型才能稳定地学会相对位置规律,而不是死记硬背特定的组合。
在看公式前,先搞清楚为什么不直接用整数0,1,2...当作位置?
这是很多人一开始最自然的想法: "给'小姜'的向量加0,给'今天'的向量加1,依次递增,多直观!"但这样神经网络的训练会崩盘,有三个原因:
🔘数值灾难(盐比菜多)
词嵌入(Embedding)向量里的数,通常都是-1到1之间的小数,比如 0.1
、-0.3
,这是它们经过训练自动调节出来的范围。如果你直接把位置编号当作一个整数加进去,比如第500个词加上499,这个499就像一勺比菜还多的盐,把词本身的语义彻底"淹没"掉。模型只会盯着这个巨大数字,完全失去对词语含义的敏感度。
🔘泛化灾难(没见过世面)
这里最容易搞混:
位置ID(pos)只是一个整数 ,
但我们用它生成的是一个高维连续向量,它和词Embedding是同样维度(比如512或1024)才能直接相加。
所以:"100比99大1"这个整数关系对神经网络没有任何意义。因为它只看位置ID映射成的向量,而新的编号就对应从未见过的新向量。假设训练时,你的模型只见过最长100个词的句子,所以它只接触过0到99这100个位置编号。测试时突然来了一句120个词的句子,于是模型看到了全新的位置ID:100、101、102...
虽然在我们人看来,"100比99大1",它们有清晰的顺序,但对模型来说,位置编码不是整数本身,而是把这个编号映射成一个高维的向量。重要的事情再说一遍:位置编码不是ID,是和EmbeddingLayer一样的高维向量!ID只是生成这个PE的一个参数而已,所以对于ID而言,100比99大,100在99后面没问题,但是PE是高维向量,你怎么能知道ID为100的token的PE,在ID为99的token的后面?理解不了,因为它压根都没见过 EmbeddingID100
scss
ID
99 和 100
机器中看到是PE
PE(99) = [a₁, a₂, a₃, ...a1024]
PE(100) = [b₁, b₂, b₃, ...b1024] (这是俩向量的位置比较!)
所以,要用一种数学函数,把任意位置编号映射成固定的、连续的、高维向量,这样即使位置编号再大,生成的向量依然是可解释、规律的。
🔘关系灾难(远近不分)
Transformer的核心是Self-Attention,它最关心的不是绝对位置,而是词与词之间的相对距离
举个例子:
- "我吃苹果"里,"我"在"吃"前面一个位置。
- "苹果吃我"里,"我"在"吃"后面一个位置。
如果你只把位置当整数编号(0,1,2...),模型必须死记硬背每一对位置的关系:
(3,5)、(10,12)、 (57,59)...这都是隔了2,但是还是那句话,你能知道这都是隔了2,但是它的PE是高维向量,不是ID,就是需要死死记住 [a₁, a₂, a₃, ...a1024] [b₁, b₂, b₃, ...b1024] 这是一对儿,中间隔了2,是必须"背下来"所有可能组合,而不是"理解"它们之间的共同规律。而最理想的方式,不管哪个绝对位置,只要相对距离是2,就能用一模一样的方式来表示它们的关系。而不是让模型单独死死记住(5,3)和(50,48),都是距离2。
🔘绝对位置与相对位置
为啥两者都需要:
- 绝对位置:告诉模型"这是句首"或"这是句尾",有些特殊含义(比如BERT中第一个位置是[CLS])。
- 相对位置:帮助模型理解词语之间的距离关系。更重要
绝对位置的核心作用是为句子中的每个词提供一个"全局标签"告诉模型"这个词在句子的哪个位置",就是特殊位置的"锚点",语言中存在大量依赖"绝对位置"的特殊场景:
- 句首标记:如BERT中的
[CLS]
必须固定在第一个位置,作为全句的"代表符号"; - 句尾标记:如句号
.
通常出现在最后一个位置,标志句子结束; - 结构化文本:如诗歌的"起承转合"、代码的"缩进层级",都依赖绝对位置定义规则。
绝对位置和相对位置哪个重要? 其实就是相对位置更重要,后续的RoPE的旋转矩阵等技术就走向了更纯粹的相对位置编码,并取得了更好的效果。但原始 Transformer 用一个巧妙的绝对位置编码方案来高效实现相对位置的计算,同时保留了绝对位置的"锚点"作用。
终极方案:用绝对位置来实现相对位置计算
就像给每个城市一个固定的GPS坐标(经纬度):
- 经纬度是绝对的。
- 任意两点之间的相对距离,可以直接从经纬度计算出来。而不用把所有城市两两距离都预先存下来。
Transformer的PE,就是让每个位置有一个绝对的高维"坐标" ,而这个坐标用sin
和cos
函数生成就具备以下能力:
- 解决数值灾难:不会溢出(所有值在[-1,1]之间)
- 解决变长问题:无限扩展(任何大编号都能算)10个token的句子,9992321个token的句子,无所谓。
- 解决关系灾难:因为三角函数具有平移规律,所以相对关系本身就编码进去了,不用死记硬背
🔘数学定义Positional Encoding公式
当Embedding维度为1024时,位置编码(PE)的维度与Embedding维度一致(1024维)。根据公式:
- 偶数维度(0, 2, 4...1022)共512维,由 <math xmlns="http://www.w3.org/1998/Math/MathML"> sin ( p o s 1000 0 2 i / d m o d e l ) \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) </math>sin(100002i/dmodelpos)计算;
- 奇数维度(1, 3, 5...1023)共512维,由 <math xmlns="http://www.w3.org/1998/Math/MathML"> cos ( p o s 1000 0 2 i / d m o d e l ) \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) </math>cos(100002i/dmodelpos)计算。
因此,位置888的PE向量其实由512个sin值和512个cos值拼接而成。
每个位置索引(pos)唯一对应一组sin和cos值。例如,pos=0时,所有偶数维的sin值为 <math xmlns="http://www.w3.org/1998/Math/MathML"> sin ( 0 ) = 0 \sin(0)=0 </math>sin(0)=0,奇数维的cos值为 <math xmlns="http://www.w3.org/1998/Math/MathML"> cos ( 0 ) = 1 \cos(0)=1 </math>cos(0)=1;pos=1时,偶数维的sin值为 <math xmlns="http://www.w3.org/1998/Math/MathML"> sin ( 1 1000 0 2 i / d m o d e l ) \sin\left(\frac{1}{10000^{2i/d_{model}}}\right) </math>sin(100002i/dmodel1),奇数维的cos值为 <math xmlns="http://www.w3.org/1998/Math/MathML"> cos ( 1 1000 0 2 i / d m o d e l ) \cos\left(\frac{1}{10000^{2i/d_{model}}}\right) </math>cos(100002i/dmodel1),与pos=0的向量不同。
三角函数的平移公式:
sin(a+b)
、cos(a+b)
都可以表示为sin(a)
、cos(a)
的线性组合。
所以:
任意两个位置的相对位置差,可以通过对它们的位置向量做一个线性变换直接计算得到。
这就是为什么模型能够仅凭绝对位置向量推断相对位置 ,不需要把所有组合背下来。任意位置pos+k
的PE向量可以通过pos
的PE向量进行固定线性变换得到。例如:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> sin ( p o s + k 1000 0 2 i / d m o d e l ) = sin ( p o s 1000 0 2 i / d m o d e l ) cos ( k 1000 0 2 i / d m o d e l ) + cos ( p o s 1000 0 2 i / d m o d e l ) sin ( k 1000 0 2 i / d m o d e l ) \sin\left(\frac{pos+k}{10000^{2i/d_{model}}}\right) = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)\cos\left(\frac{k}{10000^{2i/d_{model}}}\right) + \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)\sin\left(\frac{k}{10000^{2i/d_{model}}}\right) </math>sin(100002i/dmodelpos+k)=sin(100002i/dmodelpos)cos(100002i/dmodelk)+cos(100002i/dmodelpos)sin(100002i/dmodelk)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> cos ( p o s + k 1000 0 2 i / d m o d e l ) = cos ( p o s 1000 0 2 i / d m o d e l ) cos ( k 1000 0 2 i / d m o d e l ) − sin ( p o s 1000 0 2 i / d m o d e l ) sin ( k 1000 0 2 i / d m o d e l ) \cos\left(\frac{pos+k}{10000^{2i/d_{model}}}\right) = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)\cos\left(\frac{k}{10000^{2i/d_{model}}}\right) - \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)\sin\left(\frac{k}{10000^{2i/d_{model}}}\right) </math>cos(100002i/dmodelpos+k)=cos(100002i/dmodelpos)cos(100002i/dmodelk)−sin(100002i/dmodelpos)sin(100002i/dmodelk)
这意味着,模型只要学会"从pos
到pos+k
的变换规则"(即上述线性变换),就能通过任意pos
的PE向量推导出pos+k
的PE向量,无需重新学习。因此相对位置k
的差异信息被编码在向量的线性关系中。通俗解释时,可以简化为:"句中第三个词的PE向量(无论句子多长)会和另一个句子中第三个词的PE向量有相似的'变化规律',模型能通过这种规律推断它们的相对位置。"
🔘为什么要用不同频率?
以一个句子为例感受不同频率的正弦/余弦函数如何捕捉不同粒度的位置信息
共20个词,位置索引0~19
"小明早上8点在公园跑步时遇到了小红,两人聊了关于最近上映的电影《流浪地球3》的剧情,觉得特效非常震撼。"
模型需要理解句子中"词与词的相对位置",比如:
- 局部关系:"小明"(位置0)和"跑步"(位置4)差4个词(局部距离);
- 中等距离:"早上8点"(位置2-3)和"公园"(位置5)差3个词;
- 全局关系:"小明"(位置0)和"电影《流浪地球3》"(位置12-16)差12个词(大跨度)。
频率的数量由词的Embedding维度决定,具体是 <math xmlns="http://www.w3.org/1998/Math/MathML"> d − m o d e l / 2 d-model/2 </math>d−model/2种,比如 <math xmlns="http://www.w3.org/1998/Math/MathML"> d − m o d e l d-model </math>d−model=1024时,i的取值数量是512种,对应512种频率;如果是512维,则i的取值数量是256种,对应256种频率。
这里假设用3种不同频率的正弦函数编码(对应i=0、i=1、i=2):
这里简化公式,用 <math xmlns="http://www.w3.org/1998/Math/MathML"> freq i = 1 1000 0 2 i / 5 \text{freq}_i = \frac{1}{10000^{2i/5}} </math>freqi=100002i/51(d_model=5)模拟不同频率,计算每个位置pos的sin值(偶数维)和cos值(奇数维)。
🔵高频编码(i=0,频率最高)
高频编码对"小距离"(如相邻词差1、差2)极其敏感,微小变化会导致sin/cos值剧烈波动。
位置pos | 高频sin值(偶数维) | 高频cos值(奇数维) | 直观解释(小距离敏感) |
---|---|---|---|
0 | sin(0/10000⁰)=0 | cos(0/10000⁰)=1 | 起点,小距离变化的"基准点" |
1 | sin(1/10000⁰)=sin(1)≈0.84 | cos(1/10000⁰)=cos(1)≈0.54 | 与pos0差1,sin值从0→0.84(剧变) |
2 | sin(2/10000⁰)=sin(2)≈0.91 | cos(2/10000⁰)=cos(2)≈-0.42 | 与pos1差1,sin值从0.84→0.91(仍明显变化) |
3 | sin(3/10000⁰)=sin(3)≈0.14 | cos(3/10000⁰)=cos(3)≈-0.99 | 与pos2差1,sin值从0.91→0.14(骤降) |
... | ... | ... | ... |
高频编码能清晰捕捉"相邻词"(差1)、"隔1词"(差2)等小距离的变化------模型通过它知道"小明(0)和跑步(4)之间隔了3个词(差3)",甚至"跑步(4)和小红(7)之间差3"。
🔵中频编码(i=1,频率中等)
对"中等距离"(如差5、差10)敏感,需要位置差较大才会引起sin/cos值明显变化。
位置pos | 中频sin值(偶数维) | 中频cos值(奇数维) | 直观解释(中等距离敏感) |
---|---|---|---|
0 | sin(0/(10000²/5))≈0 | cos(0/(10000²/5))≈1 | 起点,中等距离的"基准点" |
5 | sin(5/(10000²/5))≈sin(5/40000)≈0.00012 | cos(...)≈0.99999999 | 与pos0差5,sin值几乎不变(0→0.00012) |
10 | sin(10/(10000²/5))≈sin(10/40000)≈0.00031 | cos(...)≈0.99999999 | 与pos5差5,sin值仍几乎不变(0.00012→0.00031) |
15 | sin(15/(10000²/5))≈sin(15/40000)≈0.00047 | cos(...)≈0.99999999 | 与pos10差5,sin值缓慢增加(0.00031→0.00047) |
... | ... | ... | ... |
中频编码对"差5""差10"等中等距离更敏感------模型通过它知道"小明(0)和公园(5)之间差5",但"小明(0)和电影(12)之间差12"需要结合低频编码才能捕捉。
🔵低频编码(i=2,频率最低)
对"大距离"(如差10、差20)敏感,需要位置差极大才会引起sin/cos值明显变化。
位置pos | 低频sin值(偶数维) | 低频cos值(奇数维) | 直观解释(大距离敏感) |
---|---|---|---|
0 | sin(0/(10000⁴/5))≈0 | cos(0/(10000⁴/5))≈1 | 起点,大距离的"基准点" |
10 | sin(10/(10000⁴/5))≈sin(10/100000000)≈0 | cos(...)≈1 | 与pos0差10,sin值几乎不变(0→0) |
20 | sin(20/(10000⁴/5))≈sin(20/100000000)≈0 | cos(...)≈1 | 与pos10差10,sin值仍几乎不变(0→0) |
... | ... | ... | ... |
低频编码对"差10""差20"等大距离更敏感------模型通过它知道"小明(0)和电影(12)之间差12",但"小明(0)和跑步(4)之间差4"需要结合高频编码才能捕捉。前面维度 (i值小) → 高频 (放大镜)... (平滑过渡) ..到后面维度 (i值大) → 低频 (广角镜) 。 例子中为了简化,将i=0, 1, 2
分别作为高、中、低的代表。
每个位置的PE向量由高频、中频、低频的sin/cos值拼接而成(比如d_model=5时,是2组sin+2组cos+1组sin)。模型通过这些值的组合,既能看到"小明和跑步差3"的局部细节,又能看到"小明和电影差12"的全局结构------这就是不同频率位置编码的核心作用,高频编码是"放大镜",专门看"相邻词"的小距离;中频是"望远镜",专门看"隔几句"的中等距离;低频是"广角镜",专门看"句首到句尾"的大距离。三者拼接,模型才能"既看清局部,又看懂全局"!
🟡第四步:语义加位置
万事俱备,只差临门一脚。现在每个词的"含义向量"(Embedding)和它对应位置的"坐标向量"(Positional Encoding)逐个维度相加。
scss
* "小姜" (位置 0):
`Input_小姜 = embedding_小姜 + pos_encoding_0`
`= [0.1, 0.5, -0.2, 0.8, 0.3] + [0.0, 1.0, 0.0, 1.0, 0.0]`
`= [0.1, 1.5, -0.2, 1.8, 0.3]`
* "今天" (位置 1)*
`Input_今天 = embedding_今天 + pos_encoding_1`
`= [-0.3, 0.7, 0.1, -0.5, 0.9] + [0.84, 0.54, 0.016, 0.999, 0.00016]`
`= [0.54, 1.24, 0.116, 0.499, 0.90016]`
最终,送入 Transformer Encoder 的输入就是这一串融合了"含义"和"位置"的新向量。
©唐山市环境科学规划研究院
唐山市环境规划科学研究院(唐山市生态环境宣传教育中心)是唐山市生态环境局直属的事业单位。我院以科学研究为主体、技术服务为支撑,创新发展模式,注重发展质量,历经唐山市环保事业发展的各个阶段。以"为生态环境保护提供技术服务"为宗旨,开展大气、双碳、水、海洋、土壤、固废、噪声、规划、排污许可等多个领域的研究及成果运用,在生态规划编制、重污染天气应急、减污降碳、水(海洋)资源分析、土壤污染调查、EOD项目、无废城市、企业诊所、环保管家、智慧环保平台开发等方面持续深耕,为生态环境保护提供系统化解决方案。
由作者个人全栈开发的垂直模型系统:唐山小环,是一个知识图谱+混检的双擎多模态RAG系统,专注于环保领域,现位于河北省科技厅持续展示,欢迎相关从业者咨询我院。