預訓練位置編碼
基于Transformer 的預訓練語言模型如何區分文本位置?
基于 Transformer 的預訓練語言模型主要通過位置編碼來區分文本位置。Transformer 核心的自注意力機制本身并不考慮詞的順序,它對輸入序列的處理是與位置無關的。在 query 和 key 的矩陣乘法之后,計算出當前 query 與所有 key 的相關性得分,經過 softmax 運算后得到一個表示相關性的概率分布,分布中的每一個元素都叫作“注意力分數”。自注意力機制已經喪失了表示詞的位置信息的能力,所計算的注意力分數僅僅是表示相關性大小的標量。換句話說,把任意兩個詞的位置相互調換,它們之間的注意力分數是一樣的。
位置信息在各類自然語言處理任務中都很重要,尤其是在漢語中,順序等位置信息對于語義理解十分關鍵。因此,為了使 Transformer 模型能夠區分詞的順序,我們需要給模型添加位置信息,這就是要在 Transformer 模型中增加位置編碼的原因。經典的位置編碼主要分為兩種,分別是絕對位置編碼和相對位置編碼。
絕對位置編碼的主要思想是建模文本中每個詞的位置信息,并將位置信息融入模型的輸入中。以下是兩種具有代表性的絕對位置編碼方法。
-
*第一種是 BERT 所用的訓練式絕對位置編碼。該編碼方法可以將文本的位置信息編碼成大小為 seq_len×hidden_size 的可訓練參數,并隨著模型的訓練不斷更新,其中,seq_len 表示模型輸入文本的最大長度,hidden_size 表示位置向量的編碼維度。訓練式絕對位置編碼的一個顯著缺點是無法外推,即當輸入到模型中的文本長度超過 seq_len 時,模型無法為超長的文本提供有意義的位置編碼。
-
*第二種是 Transformer 所用的 sinusoidal 位置編碼。如下述公式所示:
{pk,2i=sin?(k/10?0002i/d)pk,2i+1=cos?(k/10?0002i/d) \begin{cases} p_{k,2i} = \sin(k / 10\ 000^{2i/d}) \\ p_{k,2i+1} = \cos(k / 10\ 000^{2i/d}) \end{cases} {pk,2i?=sin(k/10?0002i/d)pk,2i+1?=cos(k/10?0002i/d)?
對于位置 kkk,利用三角函數將文本的位置信息編碼為維度大小是 ddd 的位置向量 p\boldsymbol{p}p,其中,iii 表示位置向量中的第 iii 維,位置向量 p\boldsymbol{p}p 在模型的訓練過程中不參與梯度更新。
在 Transformer 的開創性論文 “Attention Is All You Need” 中,作者給出了采用三角函數 sin?\sinsin 與 cos?\coscos 的兩個原因。如下述公式所示,
-
第一個原因
是,在位置 kkk上,對于任意的位置偏移 koffsetk_{\text{offset}}koffset?,位置 k+koffsetk+k_{\text{offset}}k+koffset? 上的位置編碼 p(k+koffset)\boldsymbol{p}(k+k_{\text{offset}})p(k+koffset?) 均可以表示成位置 kkk 和位置 koffsetk_{\text{offset}}koffset? 的線性向量組合,這使得模型可以輕松學習到相對位置信息:
cos?(k+koffset)=cos?k?cos?koffset?sin?k?sin?koffset\cos(k + k_{\text{offset}}) = \cos k \cdot \cos k_{\text{offset}} - \sin k \cdot \sin k_{\text{offset}}cos(k+koffset?)=cosk?coskoffset??sink?sinkoffset? -
第二個原因
是,sin?\sinsin 函數與 cos?\coscos 函數的值域穩定在固定區間,這意味著無論編碼的文本長度是 5 還是 500,位置向量中的取值均在 [?1,1][-1,1][?1,1] 之間。輸出值域的穩定有助于模型的穩定訓練。
要理解位置編碼后詞向量矩陣的計算,需從位置編碼的公式和矩陣逐元素相加兩方面分析,以下分步拆解:
以一個簡單的例子來說明位置編碼的計算過程:假如我們輸入的是一個長度為 4 的句子"I like to code",我們可以得到下面的詞向量矩陣 x\rm xx ,其中每一行代表的就是一個詞向量, x0=[0.1,0.2,0.3,0.4]\rm x_0=[0.1,0.2,0.3,0.4]x0?=[0.1,0.2,0.3,0.4] 對應的就是“I”的詞向量,它的pos就是為0,以此類推,第二行代表的是“like”的詞向量,它的pos就是1:
x=[0.10.20.30.40.20.30.40.50.30.40.50.60.40.50.60.7] \rm x = \begin{bmatrix} 0.1 & 0.2 & 0.3 & 0.4 \\ 0.2 & 0.3 & 0.4 & 0.5 \\ 0.3 & 0.4 & 0.5 & 0.6 \\ 0.4 & 0.5 & 0.6 & 0.7 \end{bmatrix} x=?0.10.20.30.4?0.20.30.40.5?0.30.40.50.6?0.40.50.60.7??
?則經過位置編碼后的詞向量為:
xPE=[0.10.20.30.40.20.30.40.50.30.40.50.60.40.50.60.7]+[sin?(0100000)cos?(0100000)sin?(0100002/4)cos?(0100002/4)sin?(1100000)cos?(1100000)sin?(1100002/4)cos?(1100002/4)sin?(2100000)cos?(2100000)sin?(2100002/4)cos?(2100002/4)sin?(3100000)cos?(3100000)sin?(3100002/4)cos?(3100002/4)]=[0.11.20.31.41.0410.840.411.491.209?0.0160.521.590.541?0.4890.8951.655] \rm x_{PE} = \begin{bmatrix} 0.1 & 0.2 & 0.3 & 0.4 \\ 0.2 & 0.3 & 0.4 & 0.5 \\ 0.3 & 0.4 & 0.5 & 0.6 \\ 0.4 & 0.5 & 0.6 & 0.7 \end{bmatrix} + \begin{bmatrix} \sin(\frac{0}{10000^0}) & \cos(\frac{0}{10000^0}) & \sin(\frac{0}{10000^{2/4}}) & \cos(\frac{0}{10000^{2/4}}) \\ \sin(\frac{1}{10000^0}) & \cos(\frac{1}{10000^0}) & \sin(\frac{1}{10000^{2/4}}) & \cos(\frac{1}{10000^{2/4}}) \\ \sin(\frac{2}{10000^0}) & \cos(\frac{2}{10000^0}) & \sin(\frac{2}{10000^{2/4}}) & \cos(\frac{2}{10000^{2/4}}) \\ \sin(\frac{3}{10000^0}) & \cos(\frac{3}{10000^0}) & \sin(\frac{3}{10000^{2/4}}) & \cos(\frac{3}{10000^{2/4}}) \end{bmatrix} = \begin{bmatrix} 0.1 & 1.2 & 0.3 & 1.4 \\ 1.041 & 0.84 & 0.41 & 1.49 \\ 1.209 & -0.016 & 0.52 & 1.59 \\ 0.541 & -0.489 & 0.895 & 1.655 \end{bmatrix} xPE?=?0.10.20.30.4?0.20.30.40.5?0.30.40.50.6?0.40.50.60.7??+?sin(1000000?)sin(1000001?)sin(1000002?)sin(1000003?)?cos(1000000?)cos(1000001?)cos(1000002?)cos(1000003?)?sin(100002/40?)sin(100002/41?)sin(100002/42?)sin(100002/43?)?cos(100002/40?)cos(100002/41?)cos(100002/42?)cos(100002/43?)??=?0.11.0411.2090.541?1.20.84?0.016?0.489?0.30.410.520.895?1.41.491.591.655??
詳細講解
Transformer中,位置編碼(Positional Encoding)的公式為:
PE(pos,2i)=sin?(pos100002i/dmodel)PE(pos,2i+1)=cos?(pos100002i/dmodel)
\text{PE}_{(\text{pos}, 2i)} = \sin\left( \frac{\text{pos}}{10000^{2i/d_{\text{model}}}} \right) \\
\text{PE}_{(\text{pos}, 2i+1)} = \cos\left( \frac{\text{pos}}{10000^{2i/d_{\text{model}}}} \right)
PE(pos,2i)?=sin(100002i/dmodel?pos?)PE(pos,2i+1)?=cos(100002i/dmodel?pos?)
其中:
- pos\text{pos}pos:詞在序列中的位置(從0開始);
- iii:詞向量的維度索引(從0開始);
- dmodeld_{\text{model}}dmodel?:詞向量的維度(示例中詞向量是4維,所以 dmodel=4d_{\text{model}}=4dmodel?=4)。
位置編碼矩陣的計算(逐行、逐列拆解)
示例中句子長度為4(詞的位置 pos=0,1,2,3\text{pos}=0,1,2,3pos=0,1,2,3),詞向量維度 dmodel=4d_{\text{model}}=4dmodel?=4。我們需要為每個位置 pos\text{pos}pos 生成一個4維的位置編碼向量,最終組成4×4的位置編碼矩陣,再與原始詞向量矩陣逐元素相加。
步驟1:計算位置編碼矩陣的每個元素
以“位置 pos=0\text{pos}=0pos=0(對應單詞"I")”的4維位置編碼為例,逐維度(i=0,1,2,3i=0,1,2,3i=0,1,2,3)計算:
-
維度 i=0i=0i=0:
代入公式,2i=02i = 02i=0,所以用 sin?\sinsin 公式:
PE(0,0)=sin?(0100000/4)=sin?(0)=0 \text{PE}_{(0, 0)} = \sin\left( \frac{0}{10000^{0/4}} \right) = \sin(0) = 0 PE(0,0)?=sin(100000/40?)=sin(0)=0 -
維度 i=1i=1i=1:
2i=22i = 22i=2,但 2i+1=12i+1 = 12i+1=1,所以用 cos?\coscos 公式:
PE(0,1)=cos?(0100002/4)=cos?(0)=1 \text{PE}_{(0, 1)} = \cos\left( \frac{0}{10000^{2/4}} \right) = \cos(0) = 1 PE(0,1)?=cos(100002/40?)=cos(0)=1 -
維度 i=2i=2i=2:
2i=22i = 22i=2,用 sin?\sinsin 公式:
PE(0,2)=sin?(0100004/4)=sin?(0)=0 \text{PE}_{(0, 2)} = \sin\left( \frac{0}{10000^{4/4}} \right) = \sin(0) = 0 PE(0,2)?=sin(100004/40?)=sin(0)=0 -
維度 i=3i=3i=3:
2i+1=32i+1 = 32i+1=3,用 cos?\coscos 公式:
PE(0,3)=cos?(0100006/4)=cos?(0)=1 \text{PE}_{(0, 3)} = \cos\left( \frac{0}{10000^{6/4}} \right) = \cos(0) = 1 PE(0,3)?=cos(100006/40?)=cos(0)=1
因此,pos=0\text{pos}=0pos=0 的位置編碼向量為 [0,1,0,1][0, 1, 0, 1][0,1,0,1]。
步驟2:同理計算其他位置的編碼向量
-
pos=1\text{pos}=1pos=1(對應單詞"like"):
逐維度計算后,位置編碼向量為:
[sin?(1100000),cos?(1100000),sin?(1100002/4),cos?(1100002/4)]≈[0.841,0.540,0.841,0.540] \left[ \sin\left( \frac{1}{10000^0} \right), \cos\left( \frac{1}{10000^0} \right), \sin\left( \frac{1}{10000^{2/4}} \right), \cos\left( \frac{1}{10000^{2/4}} \right) \right] \approx [0.841, 0.540, 0.841, 0.540] [sin(1000001?),cos(1000001?),sin(100002/41?),cos(100002/41?)]≈[0.841,0.540,0.841,0.540] -
pos=2\text{pos}=2pos=2(對應單詞"to"):
位置編碼向量為:
[sin?(2100000),cos?(2100000),sin?(2100002/4),cos?(2100002/4)]≈[0.909,?0.416,0.909,?0.416] \left[ \sin\left( \frac{2}{10000^0} \right), \cos\left( \frac{2}{10000^0} \right), \sin\left( \frac{2}{10000^{2/4}} \right), \cos\left( \frac{2}{10000^{2/4}} \right) \right] \approx [0.909, -0.416, 0.909, -0.416] [sin(1000002?),cos(1000002?),sin(100002/42?),cos(100002/42?)]≈[0.909,?0.416,0.909,?0.416] -
pos=3\text{pos}=3pos=3(對應單詞"code"):
位置編碼向量為:
[sin?(3100000),cos?(3100000),sin?(3100002/4),cos?(3100002/4)]≈[0.141,?0.989,0.141,?0.989] \left[ \sin\left( \frac{3}{10000^0} \right), \cos\left( \frac{3}{10000^0} \right), \sin\left( \frac{3}{10000^{2/4}} \right), \cos\left( \frac{3}{10000^{2/4}} \right) \right] \approx [0.141, -0.989, 0.141, -0.989] [sin(1000003?),cos(1000003?),sin(100002/43?),cos(100002/43?)]≈[0.141,?0.989,0.141,?0.989]
步驟3:組合成“位置編碼矩陣”
將4個位置的編碼向量按行排列,得到4×4的位置編碼矩陣:
[01010.8410.5400.8410.5400.909?0.4160.909?0.4160.141?0.9890.141?0.989]
\left[
\begin{array}{cccc}
0 & 1 & 0 & 1 \\
0.841 & 0.540 & 0.841 & 0.540 \\
0.909 & -0.416 & 0.909 & -0.416 \\
0.141 & -0.989 & 0.141 & -0.989 \\
\end{array}
\right]
?00.8410.9090.141?10.540?0.416?0.989?00.8410.9090.141?10.540?0.416?0.989??
三、原始詞向量與位置編碼“逐元素相加”
原始詞向量矩陣 x\text{x}x 是:
x=[0.10.20.30.40.20.30.40.50.30.40.50.60.40.50.60.7]
\text{x} = \left[
\begin{array}{cccc}
0.1 & 0.2 & 0.3 & 0.4 \\
0.2 & 0.3 & 0.4 & 0.5 \\
0.3 & 0.4 & 0.5 & 0.6 \\
0.4 & 0.5 & 0.6 & 0.7 \\
\end{array}
\right]
x=?0.10.20.30.4?0.20.30.40.5?0.30.40.50.6?0.40.50.60.7??
位置編碼矩陣與 x\text{x}x 逐元素相加(即每個位置的詞向量 + 對應位置的編碼向量),以第一行為例:
- 原始第一行:[0.1,0.2,0.3,0.4][0.1, 0.2, 0.3, 0.4][0.1,0.2,0.3,0.4]
- 位置編碼第一行:[0,1,0,1][0, 1, 0, 1][0,1,0,1]
- 相加后第一行:[0.1+0,0.2+1,0.3+0,0.4+1]=[0.1,1.2,0.3,1.4][0.1+0, 0.2+1, 0.3+0, 0.4+1] = [0.1, 1.2, 0.3, 1.4][0.1+0,0.2+1,0.3+0,0.4+1]=[0.1,1.2,0.3,1.4]
其余情況相同,以此類推
- 實現代碼:
import numpy as np
import matplotlib.pyplot as plt
def PositionEncoding(seq_len, d_model, n=10000):P = np.zeros((seq_len, d_model))for k in range(seq_len):for i in np.arange(int(d_model/2)):denominator = np.power(n, 2*i/d_model)P[k, 2*i] = np.sin(k/denominator)P[k, 2*i+1] = np.cos(k/denominator)return PP = PositionEncoding(seq_len=4, d_model=4, n=1000)
print(P)[[ 0. 1. 0. 1. ][ 0.84147098 0.54030231 0.03161751 0.99950004][ 0.90929743 -0.41614684 0.0632034 0.99800067][ 0.14112001 -0.9899925 0.09472609 0.99550337]]
其中參數n
的作用是控制位置編碼中正弦/余弦函數的周期變化速率,具體來說:
n
是一個縮放因子,默認值通常設為10000(如原Transformer論文中所示)- 在計算時,它通過
np.power(n, 2*i/d_model)
影響函數的周期 - 不同的
i
(維度索引)會得到不同周期的正弦/余弦函數,周期范圍從2π
到2π*n
n
值越大,不同維度之間的周期差異越顯著
n
被設為100,這會使得位置編碼的周期變化比默認值10000更快。通過這種方式,模型能夠區分序列中不同位置的元素,即使它們在詞嵌入上是相同的。
當
n
較小時(如100),位置編碼的數值變化會更劇烈;而當n
較大時(如10000),數值變化會更平緩,能更好地處理長序列。
這樣的位置編碼主要有兩個好處:
- 使 PE 能夠適應比訓練集里面所有句子更長的句子,假設訓練集里面最長的句子是有 30 個單詞,突然來了一個長度為 31 的句子,則使用公式計算的方法可以計算出第 31 位的 Embedding。
- 可以讓模型容易地計算出相對位置,對于固定長度的間距 k,PE(pos+k) 可以用 PE(pos) 計算得到。因為 Sin(A+B) = Sin(A)Cos(B) + Cos(A)Sin(B), Cos(A+B) = Cos(A)Cos(B) - Sin(A)Sin(B)。
進一步推理:
更多原理性知識見前置知識模塊
可以通過嚴謹的數學推導證明該編碼方式的優越性。原始的 Transformer Embedding 可以表示為:
f(??,xm,??,xn,??)=f(??,xn,??,xm,??) \begin{equation}f(\cdots,\boldsymbol{x}_m,\cdots,\boldsymbol{x}_n,\cdots)=f(\cdots,\boldsymbol{x}_n,\cdots,\boldsymbol{x}_m,\cdots)\end{equation} f(?,xm?,?,xn?,?)=f(?,xn?,?,xm?,?)??
很明顯,這樣的函數是不具有不對稱性的,也就是無法表征相對位置信息。我們想要得到這樣一種編碼方式:
f~(??,xm,??,xn,??)=f(??,xm+pm,??,xn+pn,??) \begin{equation}\tilde{f}(\cdots,\boldsymbol{x}_m,\cdots,\boldsymbol{x}_n,\cdots)=f(\cdots,\boldsymbol{x}_m + \boldsymbol{p}_m,\cdots,\boldsymbol{x}_n + \boldsymbol{p}_n,\cdots)\end{equation} f~?(?,xm?,?,xn?,?)=f(?,xm?+pm?,?,xn?+pn?,?)??
這里加上的 pmp_mpm?, pnp_npn? 就是位置編碼。接下來我們將 f(...,xm+pm,...,xn+pn)f(...,x_m+p_m,...,x_n+p_n)f(...,xm?+pm?,...,xn?+pn?) 在 m,n 兩個位置上做泰勒展開:
f~≈f+pm??f?xm+pn??f?xn+12pm??2f?xm2pm+12pn??2f?xn2pn+pm??2f?xm?xnpn?pm?Hpn \begin{equation}\tilde{f}\approx f + \boldsymbol{p}_m^{\top} \frac{\partial f}{\partial \boldsymbol{x}_m} + \boldsymbol{p}_n^{\top} \frac{\partial f}{\partial \boldsymbol{x}_n} + \frac{1}{2}\boldsymbol{p}_m^{\top} \frac{\partial^2 f}{\partial \boldsymbol{x}_m^2}\boldsymbol{p}_m + \frac{1}{2}\boldsymbol{p}_n^{\top} \frac{\partial^2 f}{\partial \boldsymbol{x}_n^2}\boldsymbol{p}_n + \underbrace{\boldsymbol{p}_m^{\top} \frac{\partial^2 f}{\partial \boldsymbol{x}_m \partial \boldsymbol{x}_n}\boldsymbol{p}_n}_{\boldsymbol{p}_m^{\top} \boldsymbol{\mathcal{H}} \boldsymbol{p}_n}\end{equation} f~?≈f+pm???xm??f?+pn???xn??f?+21?pm???xm2??2f?pm?+21?pn???xn2??2f?pn?+pm??Hpn?pm???xm??xn??2f?pn?????
可以看到第1項與位置無關,2~5項僅依賴單一位置,第6項(f 分別對 m、n 求偏導)與兩個位置有關,所以我們希望第六項( pmTHpnp_m^THp_npmT?Hpn? )表達相對位置信息,即求一個函數 g 使得:
pmTHpn=g(m?n) p_m^THp_n = g(m-n) pmT?Hpn?=g(m?n)
我們假設 HHH 是一個單位矩陣,則:
pmTHpn=pmTpn=?pm,pn?=g(m?n) p_m^THp_n = p_m^Tp_n = \langle\boldsymbol{p}_m, \boldsymbol{p}_n\rangle = g(m-n) pmT?Hpn?=pmT?pn?=?pm?,pn??=g(m?n)
通過將向量 [x,y] 視為復數 x+yi,基于復數的運算法則構建方程:
?pm,pn?=Re[pmpn?] \begin{equation}\langle\boldsymbol{p}_m, \boldsymbol{p}_n\rangle = \text{Re}[\boldsymbol{p}_m \boldsymbol{p}_n^*]\end{equation} ?pm?,pn??=Re[pm?pn??]??
再假設存在復數 qm?nq_{m-n}qm?n? 使得:
pmpn?=qm?n \begin{equation}\boldsymbol{p}_m \boldsymbol{p}_n^* = \boldsymbol{q}_{m-n}\end{equation} pm?pn??=qm?n???
使用復數的指數形式求解這個方程,得到二維情形下位置編碼的解:
pm=eimθ?pm=(cos?mθsin?mθ) \begin{equation}\boldsymbol{p}_m = e^{\text{i}m\theta}\quad\Leftrightarrow\quad \boldsymbol{p}_m=\begin{pmatrix}\cos m\theta \\ \sin m\theta\end{pmatrix}\end{equation} pm?=eimθ?pm?=(cosmθsinmθ?)??
由于內積滿足線性疊加性,所以更高維的偶數維位置編碼,我們可以表示為多個二維位置編碼的組合:
pm=(eimθ0eimθ1?eimθd/2?1)?pm=(cos?mθ0sin?mθ0cos?mθ1sin?mθ1?cos?mθd/2?1sin?mθd/2?1) \begin{equation}\boldsymbol{p}_m = \begin{pmatrix}e^{\text{i}m\theta_0} \\ e^{\text{i}m\theta_1} \\ \vdots \\ e^{\text{i}m\theta_{d/2-1}}\end{pmatrix}\quad\Leftrightarrow\quad \boldsymbol{p}_m=\begin{pmatrix}\cos m\theta_0 \\ \sin m\theta_0 \\ \cos m\theta_1 \\ \sin m\theta_1 \\ \vdots \\ \cos m\theta_{d/2-1} \\ \sin m\theta_{d/2-1} \end{pmatrix}\end{equation} pm?=?eimθ0?eimθ1??eimθd/2?1????pm?=?cosmθ0?sinmθ0?cosmθ1?sinmθ1??cosmθd/2?1?sinmθd/2?1?????
再取 θi=10000?2i/d\theta_i = 10000^{-2i/d}θi?=10000?2i/d(該形式可以使得隨著|m?n|的增大,?pm,pn?有著趨于零的趨勢,這一點可以通過對位置編碼做積分來證明,而 base 取為 10000 是實驗結果),就得到了上文的編碼方式。
當 HHH 不是一個單位矩陣時,因為模型的 Embedding 層所形成的 d 維向量之間任意兩個維度的相關性比較小,滿足一定的解耦性,我們可以將其視作對角矩陣,那么使用上述編碼:
pm?Hpn=∑i=1d/2H2i,2icos?mθicos?nθi+H2i+1,2i+1sin?mθisin?nθi \begin{equation}\boldsymbol{p}_m^{\top} \boldsymbol{\mathcal{H}} \boldsymbol{p}_n=\sum_{i=1}^{d/2} \boldsymbol{\mathcal{H}}_{2i,2i} \cos m\theta_i \cos n\theta_i + \boldsymbol{\mathcal{H}}_{2i+1,2i+1} \sin m\theta_i \sin n\theta_i\end{equation} pm??Hpn?=i=1∑d/2?H2i,2i?cosmθi?cosnθi?+H2i+1,2i+1?sinmθi?sinnθi???
通過積化和差:
∑i=1d/212(H2i,2i+H2i+1,2i+1)cos?(m?n)θi+12(H2i,2i?H2i+1,2i+1)cos?(m+n)θi \begin{equation}\sum_{i=1}^{d/2} \frac{1}{2}\left(\boldsymbol{\mathcal{H}}_{2i,2i} + \boldsymbol{\mathcal{H}}_{2i+1,2i+1}\right) \cos (m-n)\theta_i + \frac{1}{2}\left(\boldsymbol{\mathcal{H}}_{2i,2i} - \boldsymbol{\mathcal{H}}_{2i+1,2i+1}\right) \cos (m+n)\theta_i \end{equation} i=1∑d/2?21?(H2i,2i?+H2i+1,2i+1?)cos(m?n)θi?+21?(H2i,2i??H2i+1,2i+1?)cos(m+n)θi???
說明該編碼仍然可以表示相對位置。
上述?編碼結果,如圖所示:
前置知識:泰勒展開(Taylor Expansion)
要理解泰勒展開(Taylor Expansion),核心是解決一個問題:如何用“多項式”近似“復雜函數”?比如用簡單的多項式去逼近sin(x)、e^x這類無法用四則運算直接計算的函數,這在數學分析、工程計算、機器學習(如神經網絡激活函數近似)中都有重要用途。
-
本質思想:“局部線性化”的延伸
函數在某點(比如x?)的切線(一次多項式)可以近似該點附近的函數值(局部線性化)。但切線的近似精度很低,離x?越遠誤差越大。
泰勒展開的思路是:用更高次的多項式(比如二次、三次、n次)替代切線,通過匹配函數在x?點的“函數值”“一階導數”“二階導數”……“n階導數”,讓多項式與原函數在x?附近盡可能重合,從而提升近似精度。 -
泰勒展開公式
對于一個在x?點“足夠光滑”(即n階導數存在)的函數f(x),其在x?點的n階泰勒多項式(泰勒展開的核心表達式)為:
f(x)≈Pn(x)=f(x0)+f′(x0)(x?x0)+f′′(x0)2!(x?x0)2+f′′′(x0)3!(x?x0)3+?+f(n)(x0)n!(x?x0)n f(x) \approx P_n(x) = f(x_0) + f'(x_0)(x - x_0) + \frac{f''(x_0)}{2!}(x - x_0)^2 + \frac{f'''(x_0)}{3!}(x - x_0)^3 + \dots + \frac{f^{(n)}(x_0)}{n!}(x - x_0)^n f(x)≈Pn?(x)=f(x0?)+f′(x0?)(x?x0?)+2!f′′(x0?)?(x?x0?)2+3!f′′′(x0?)?(x?x0?)3+?+n!f(n)(x0?)?(x?x0?)n
當n→∞時,若誤差項(余項)趨近于0,則P?(x)會精確等于f(x),此時稱為泰勒級數。
公式中各部分的含義:
- x?:展開的“中心點”(通常選易計算的點,如x?=0,此時稱為“麥克勞林展開”);
- f(x?):函數在x?點的函數值(保證多項式與原函數在x?點“重合”);
- f’(x?)(x-x?):一階導數項(保證多項式與原函數在x?點“斜率相同”,即切線方向一致);
- f’'(x?)/2! · (x-x?)2:二階導數項(保證多項式與原函數在x?點“曲率相同”,即彎曲方向一致);
- 更高次項:進一步匹配函數的“高階彎曲特性”,讓近似更精準;
- 1/n!:階乘分母是“歸一化因子”,用于抵消高階導數帶來的數值放大(比如n階導數可能很大,除以n!后能讓各項貢獻更均衡)。
簡單例子:e^x的麥克勞林展開
選擇最經典的例子——指數函數f(x)=ex,展開中心點x?=0(麥克勞林展開),因為ex的各階導數非常簡單,便于計算。
-
步驟1:計算f(x)=e^x在x?=0處的各階導數
ex的一個特殊性質是:**任意階導數都等于自身**,即f(k)(x)=ex(k=0,1,2,…,f(0)(x)表示原函數)。
因此,在x?=0處,所有導數的值都為:f(k)(0)=e0=1。 -
步驟2:代入泰勒展開公式
將f(k)(0)=1、x?=0代入公式,得到ex的麥克勞林展開式:
ex≈1+x+x22!+x33!+x44!+?+xnn! e^x \approx 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \frac{x^4}{4!} + \dots + \frac{x^n}{n!} ex≈1+x+2!x2?+3!x3?+4!x4?+?+n!xn? -
步驟3:用具體數值驗證近似效果
我們用x=1(計算e^1≈2.71828)來驗證不同階數多項式的近似精度:
- 0階多項式(只保留常數項):P?(1)=1 → 誤差=2.71828-1=1.71828(誤差很大);
- 1階多項式(保留到x項):P?(1)=1+1=2 → 誤差=0.71828(誤差減小);
- 2階多項式(保留到x2/2!):P?(1)=1+1+1/2=2.5 → 誤差=0.21828(誤差進一步減小);
- 3階多項式(保留到x3/6):P?(1)=1+1+0.5+1/6≈2.66667 → 誤差≈0.05161;
- 4階多項式(保留到x?/24):P?(1)=2.66667 + 1/24≈2.70833 → 誤差≈0.00995;
- 5階多項式(保留到x?/120):P?(1)=2.70833 + 1/120≈2.71667 → 誤差≈0.00161;
- 10階多項式:P??(1)≈2.71828 → 誤差幾乎為0!
前置概念:多變量函數的泰勒展開核心思想
單變量泰勒展開是“匹配單個變量的各階導數”,而多變量泰勒展開的核心是:
對需要偏移的變量(此處為 ( x_m ) 和 ( x_n )),同時匹配它們的“函數值”“一階偏導數”“二階混合偏導數”……“k階混合偏導數”,讓多項式與原函數在“原位置 ( (x_m, x_n) )”附近盡可能重合,從而近似偏移后的函數值 ( f(\dots, x_m+p_m, \dots, x_n+p_n) )。
為簡化表述,我們先定義“簡化函數”:固定除 ( x_m ) 和 ( x_n ) 外的所有變量,將函數記為 二元函數
F(u,v)=f(…,u,…,v,…?) F(u, v) = f(\dots, u, \dots, v, \dots) F(u,v)=f(…,u,…,v,…)
其中 ( u = x_m )(原第m個變量)、( v = x_n )(原第n個變量),偏移后的函數值即為 ( F(u + p_m, v + p_n) )。
我們的目標就是對 二元函數 ( F(u, v) ) 在點 ( (u_0, v_0) = (x_m, x_n) ) 處做泰勒展開,最終再還原回原函數的表述。
二元函數的泰勒展開公式(核心推導)
對于二元函數 ( F(u, v) ),若在 ( (u_0, v_0) ) 處“足夠光滑”(各階混合偏導數存在),其 k階泰勒多項式(近似偏移后的函數值 ( F(u_0+p_m, v_0+p_n) ))的通用形式為:
F(u0+pm,v0+pn)≈∑k=0K1k!(pm???u+pn???v)kF(u0,v0)
F(u_0 + p_m, v_0 + p_n) \approx \sum_{k=0}^K \frac{1}{k!} \left( p_m \cdot \frac{\partial}{\partial u} + p_n \cdot \frac{\partial}{\partial v} \right)^k F(u_0, v_0)
F(u0?+pm?,v0?+pn?)≈k=0∑K?k!1?(pm???u??+pn???v??)kF(u0?,v0?)
公式中關鍵符號的含義:
- ( k ):泰勒展開的“階數”(k=0為常數項,k=1為一階偏導數項,k=2為二階混合偏導數項,以此類推);
- ( \frac{\partial}{\partial u} ) / ( \frac{\partial}{\partial v} ):對變量 ( u )(原 ( x_m ))、( v )(原 ( x_n ))的一階偏導數算子(固定其他變量,僅對單個變量求導);
- ( \left( p_m \cdot \frac{\partial}{\partial u} + p_n \cdot \frac{\partial}{\partial v} \right)^k ):k階偏導數算子展開(類似二項式定理展開,會產生“純u偏導”“純v偏導”“混合u-v偏導”項);
- ( \frac{1}{k!} ):階乘歸一化因子(抵消高階偏導數的數值放大,保證各項貢獻均衡)。
分階展開:從低階到高階,直觀理解
為了更清晰,我們按“階數”逐步展開公式,最終還原回原函數 ( f ) 的表述(將 ( u_0=x_m )、( v_0=x_n )、( F ) 換回 ( f ),偏導數算子對應原變量 ( x_m )、( x_n ))。
1. *0階展開(常數項,最粗糙近似)
k=0時,算子項 ( \left( p_m \frac{\partial}{\partial u} + p_n \frac{\partial}{\partial v} \right)^0 = 1 )(任何算子的0次冪為“恒等算子”,即不改變函數),因此:
f(…,xm+pm,…,xn+pn)≈f(…,xm,…,xn,…?)
f(\dots, x_m+p_m, \dots, x_n+p_n) \approx f(\dots, x_m, \dots, x_n, \dots)
f(…,xm?+pm?,…,xn?+pn?)≈f(…,xm?,…,xn?,…)
含義:完全忽略偏移 ( p_m )、( p_n ),直接用原位置的函數值近似偏移后的值——誤差最大,但最簡單。
2. 1階展開(線性項,局部線性近似)
k=1時,算子項展開為 ( p_m \frac{\partial}{\partial u} + p_n \frac{\partial}{\partial v} ),因此:
f(…,xm+pm,…,xn+pn)≈f(…,xm,…,xn,…?)+pm??f?xm(…,xm,…,xn,…?)+pn??f?xn(…,xm,…,xn,…?)
\begin{align*}
f(\dots, x_m+p_m, \dots, x_n+p_n) &\approx f(\dots, x_m, \dots, x_n, \dots) + \\
&p_m \cdot \frac{\partial f}{\partial x_m}(\dots, x_m, \dots, x_n, \dots) + \\
&p_n \cdot \frac{\partial f}{\partial x_n}(\dots, x_m, \dots, x_n, \dots)
\end{align*}
f(…,xm?+pm?,…,xn?+pn?)?≈f(…,xm?,…,xn?,…)+pm???xm??f?(…,xm?,…,xn?,…)+pn???xn??f?(…,xm?,…,xn?,…)?
符號說明:( \frac{\partial f}{\partial x_m} ) 表示“固定其他變量,僅對第m個變量 ( x_m ) 求一階偏導數”,反映 ( x_m ) 變化對 ( f ) 的“線性影響速率”;同理 ( \frac{\partial f}{\partial x_n} ) 反映 ( x_n ) 的線性影響速率。
含義:用“平面”(二元函數的“切線平面”)近似偏移后的函數值,考慮了兩個變量的“獨立線性貢獻”——誤差比0階小,適用于偏移量 ( p_m )、( p_n ) 很小的場景。
3. 2階展開(二次項,考慮曲率和交互作用)
k=2時,算子項按二項式定理展開為 ( p_m^2 \frac{\partial^2}{\partial u^2} + 2p_m p_n \frac{\partial^2}{\partial u \partial v} + p_n^2 \frac{\partial^2}{\partial v^2} ),因此:
f(…,xm+pm,…,xn+pn)≈0階項+1階項+12![pm2??2f?xm2+2pmpn??2f?xm?xn+pn2??2f?xn2]
\begin{align*}
f(\dots, x_m+p_m, \dots, x_n+p_n) &\approx 0階項 + 1階項 + \\
&\frac{1}{2!} \left[ p_m^2 \cdot \frac{\partial^2 f}{\partial x_m^2} + 2p_m p_n \cdot \frac{\partial^2 f}{\partial x_m \partial x_n} + p_n^2 \cdot \frac{\partial^2 f}{\partial x_n^2} \right]
\end{align*}
f(…,xm?+pm?,…,xn?+pn?)?≈0階項+1階項+2!1?[pm2???xm2??2f?+2pm?pn???xm??xn??2f?+pn2???xn2??2f?]?
符號說明:
- ( \frac{\partial^2 f}{\partial x_m^2} ):對 ( x_m ) 的“二階純偏導數”,反映 ( x_m ) 變化對 ( f ) 的“曲率影響”(比如變量 ( x_m ) 增加時,( f ) 的增長速率是加快還是減慢);
- ( \frac{\partial^2 f}{\partial x_n^2} ):對 ( x_n ) 的二階純偏導數,含義同上;
- ( \frac{\partial^2 f}{\partial x_m \partial x_n} ):“混合偏導數”,反映 ( x_m ) 和 ( x_n ) 的“交互影響”(比如 ( x_m ) 增加時,( x_n ) 對 ( f ) 的影響是否會變化)。
含義:用“二次曲面”近似函數,不僅考慮了線性貢獻,還加入了“曲率”和“變量交互作用”——近似精度顯著提升,適用于偏移量稍大或需要更高精度的場景。
4. 高階展開(k≥3)
k≥3時,會產生更高階的混合偏導數項(如 ( p_m^3 \frac{\partial^3 f}{\partial x_m^3} )、( p_m^2 p_n \frac{\partial^3 f}{\partial x_m^2 \partial x_n} ) 等),形式更復雜,但核心邏輯不變:通過匹配更高階的偏導數,進一步減小近似誤差。
當 ( k \to \infty ) 且余項趨近于0時,泰勒多項式會精確等于原函數,此時稱為“泰勒級數”。
簡單例子:用具體函數驗證
假設原函數為 二元二次函數 ( f(x_m, x_n) = x_m^2 + 2x_m x_n + 3x_n^2 )(固定其他變量,僅關注 ( x_m ) 和 ( x_n )),我們要近似偏移后的函數值 ( f(x_m + p_m, x_n + p_n) ),并與“直接計算結果”對比,驗證泰勒展開的正確性。
步驟1:直接計算偏移后的函數值(真實值)
f(xm+pm,xn+pn)=(xm+pm)2+2(xm+pm)(xn+pn)+3(xn+pn)2=xm2+2xmpm+pm2+2xmxn+2xmpn+2xnpm+2pmpn+3xn2+6xnpn+3pn2 \begin{align*} f(x_m+p_m, x_n+p_n) &= (x_m+p_m)^2 + 2(x_m+p_m)(x_n+p_n) + 3(x_n+p_n)^2 \\ &= x_m^2 + 2x_m p_m + p_m^2 + 2x_m x_n + 2x_m p_n + 2x_n p_m + 2p_m p_n + 3x_n^2 + 6x_n p_n + 3p_n^2 \end{align*} f(xm?+pm?,xn?+pn?)?=(xm?+pm?)2+2(xm?+pm?)(xn?+pn?)+3(xn?+pn?)2=xm2?+2xm?pm?+pm2?+2xm?xn?+2xm?pn?+2xn?pm?+2pm?pn?+3xn2?+6xn?pn?+3pn2??
步驟2:用2階泰勒展開計算(近似值)
首先計算原函數在 ( (x_m, x_n) ) 處的各階偏導數:
- 0階項:( f(x_m, x_n) = x_m^2 + 2x_m x_n + 3x_n^2 );
- 1階偏導數:( \frac{\partial f}{\partial x_m} = 2x_m + 2x_n ),( \frac{\partial f}{\partial x_n} = 2x_m + 6x_n );
- 2階偏導數:( \frac{\partial^2 f}{\partial x_m^2} = 2 ),( \frac{\partial^2 f}{\partial x_n^2} = 6 ),( \frac{\partial^2 f}{\partial x_m \partial x_n} = 2 );
- 3階及以上偏導數:均為0(因為原函數是二次函數,高階導數為0)。
代入2階泰勒展開公式:
近似值=0階項+1階項+12![pm2?2+2pmpn?2+pn2?6]=(xm2+2xmxn+3xn2)+[pm(2xm+2xn)+pn(2xm+6xn)]+12[2pm2+4pmpn+6pn2]=xm2+2xmxn+3xn2+2xmpm+2xnpm+2xmpn+6xnpn+pm2+2pmpn+3pn2
\begin{align*}
\text{近似值} &= 0階項 + 1階項 + \frac{1}{2!}[p_m^2 \cdot 2 + 2p_m p_n \cdot 2 + p_n^2 \cdot 6] \\
&= (x_m^2 + 2x_m x_n + 3x_n^2) + [p_m(2x_m+2x_n) + p_n(2x_m+6x_n)] + \frac{1}{2}[2p_m^2 + 4p_m p_n + 6p_n^2] \\
&= x_m^2 + 2x_m x_n + 3x_n^2 + 2x_m p_m + 2x_n p_m + 2x_m p_n + 6x_n p_n + p_m^2 + 2p_m p_n + 3p_n^2
\end{align*}
近似值?=0階項+1階項+2!1?[pm2??2+2pm?pn??2+pn2??6]=(xm2?+2xm?xn?+3xn2?)+[pm?(2xm?+2xn?)+pn?(2xm?+6xn?)]+21?[2pm2?+4pm?pn?+6pn2?]=xm2?+2xm?xn?+3xn2?+2xm?pm?+2xn?pm?+2xm?pn?+6xn?pn?+pm2?+2pm?pn?+3pn2??
可以發現:2階泰勒展開的近似值與直接計算的真實值完全相等!
原因是原函數是“二次函數”,而2階泰勒展開已經包含了所有“二次項”,高階項(k≥3)為0,因此沒有誤差——這也體現了泰勒展開的本質:對“k次多項式函數”,k階泰勒展開可完全精確還原函數。
相對位置編碼
相對位置編碼的主要思想是修改自注意力機制,在對兩個位置i和j上的詞進行自注意力運算的時候,將兩個位置的相對距離i-j考慮進來,使得進行自注意力運算之后的結果中包含相對位置信息。在具體實現上,論文“Self-Attention with Relative Position Representations”中給出了實現相對位置編碼方案的框架,后續諸多相對位置編碼的設計思路均遵循此框架。
Transformer對i和j這兩個位置進行自注意力運算的公式如下:
{ai,j=softmax(qikjT)oi=∑jai,jvj
\left\{
\begin{aligned}
a_{i,j} &=\text{softmax}\left( q_i k_j^{\text{T}} \right) \\
o_i &= \sum_j a_{i,j} v_j
\end{aligned}
\right.
????ai,j?oi??=softmax(qi?kjT?)=j∑?ai,j?vj??
其中,qiq_iqi?表示位置iii上的查詢矩陣,kjk_jkj?表示位置jjj上的鍵矩陣,vjv_jvj?表示位置jjj上的值矩陣,ai,ja_{i,j}ai,j?表示位置iii上的查詢矩陣與位置jjj上的鍵矩陣的相關性得分,oio_ioi?是考慮了位置iii和位置jjj上兩個詞之間相關性的表征,其缺少位置iii和位置jjj之間的距離信息。為了將位置iii和位置jjj之間的相對距離信息融入 oio_ioi? 中,作者給出了以下計算方式(具體推導過程見原論文):
oi=∑jai,j(xjWV+Ri,jV)o_i = \sum_j a_{i,j} \left( x_j W_V + R_{i,j}^V \right)oi?=j∑?ai,j?(xj?WV?+Ri,jV?)
其中,xjx_jxj? 是位置 jjj 上的詞向量,WVW_VWV? 是自注意力在構建查詢矩陣時隨機初始化的一個權重矩陣,其隨著模型的訓練不斷更新。Ri,jVR_{i,j}^VRi,jV? 是一個依賴相對位置信息 i?ji-ji?j 的矩陣,其取值可以由三角函數計算得出,也可以作為可訓練的參數在訓練過程中不斷調整。后續無論是 XLNet、T5、DeBERTa,還是 RoPE 和 ALiBi,它們均圍繞對 qikjTq_i k_j^\text{T}qi?kjT? 的展開式進行修改。它們不僅可以將相對位置信息 i?ji-ji?j 融入自注意力的計算過程中,還在提升訓練效率、增強模型外推能力、融入絕對位置信息等方面給出了各自的方案。
更多位置編碼面試問題
在面試中,關于 Transformer 預訓練模型中的位置編碼(Positional Encoding) 是一個高頻且深入的話題,尤其在考察對 Transformer 架構理解的深度時。以下是可能被問到的相關面試問題,按難度和類別進行分類整理:
🔹 一、基礎概念類問題
-
為什么 Transformer 需要位置編碼?
提示:自注意力機制本身是“位置無關”的(permutation-equivariant),無法捕捉序列順序信息。
-
位置編碼的核心作用是什么?
給序列中的每個位置賦予獨特的 “位置標識”,讓模型能夠區分不同位置的 token,從而學習到序列的順序依賴關系。
-
原始 Transformer 中使用的是哪種位置編碼?它是如何設計的?
答案:正弦和余弦函數組合的固定位置編碼(sinusoidal positional encoding)。① 不同位置有不同編碼;② 編碼值應能反映位置間的相對距離(如位置 k 和 k+1 的差異應小于 k 和 k+100);③ 對任意長度序列通用(尤其是長序列)
-
請寫出 sinusoidal 位置編碼的公式。
PE(pos,2i)=sin?(pos100002i/d),PE(pos,2i+1)=cos?(pos100002i/d) PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d}}\right), \quad PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d}}\right) PE(pos,2i)?=sin(100002i/dpos?),PE(pos,2i+1)?=cos(100002i/dpos?)
其中pos
是位置索引,i
是維度索引,d
是 embedding 維度。 -
位置編碼加在哪兒?是加在詞向量上嗎?
是的,位置編碼加在輸入嵌入(token embeddings)上,在送入第一層 encoder/decoder 之前。將位置編碼與詞嵌入直接相加(element-wise addition),兩者維度均為dmodel,相加后作為 Transformer 的輸入
🔹 二、設計原理與動機類問題
-
為什么使用正弦函數?有什么好處?
- 可以讓模型學習到相對位置信息(因為 sin?(a+b)\sin(a+b)sin(a+b) 可以用 sin?a,cos?a\sin a, \cos asina,cosa 表示)
- 能夠外推到比訓練時更長的序列(理論上)① 天然滿足 “不同位置有不同編碼”;② 能通過三角函數的周期性反映相對位置(如sin(a+b)可由sina,cosa,sinb,cosb線性表示);③ 對長序列友好(無需隨序列長度重新訓練)
-
位置編碼為什么能表示相對位置?
利用三角恒等式:sin?(ω(pos+k))\sin(\omega (pos + k))sin(ω(pos+k)) 和 cos?(ω(pos+k))\cos(\omega (pos + k))cos(ω(pos+k)) 可以表示為 sin?(ωpos)\sin(\omega pos)sin(ωpos) 和 cos?(ωpos)\cos(\omega pos)cos(ωpos) 的線性組合,因此模型可以通過權重學習相對偏移 kkk。
-
為什么選擇 100001000010000 這個常數?
為了讓不同頻率的位置編碼覆蓋從短距離到非常長距離的周期變化,適合大多數自然語言任務的序列長度。
-
位置編碼是可學習的還是固定的?兩者有何優劣?
- 原始 Transformer 使用固定編碼。
- BERT 等預訓練模型使用可學習的位置嵌入(learned positional embeddings)。
對比:
- 固定:無需訓練,可外推;
- 可學習:更靈活,但受限于最大長度。
🔹 三、變體與改進類問題(進階)
- 除了正弦余弦編碼,還有哪些常用的位置編碼方法?
(考察知識廣度:① 可學習位置編碼(Learned Positional Embedding):隨機初始化參數,隨模型一起訓練;② 相對位置編碼(Relative Position Encoding):直接建模位置間的相對距離;③ 旋轉位置編碼(RoPE):通過旋轉矩陣將絕對位置轉化為相對位置信息(如 LLaMA、GPT 等模型使用)。)
-
BERT 是如何處理位置編碼的?和原始 Transformer 有何不同?
BERT 使用可學習的一維位置嵌入,每個位置對應一個向量,通過訓練得到。
-
ALiBi(Attention with Linear Biases)是如何替代位置編碼的?
不顯式添加位置編碼,而是在注意力分數上加上與相對距離成線性的偏置項:$ \text{bias} = -\alpha \cdot |i-j| $,其中 α\alphaα 是每個頭不同的斜率。
-
RoPE(Rotary Position Embedding)的工作原理是什么?為何被廣泛采用(如 LLaMA、ChatGLM)?
將位置信息通過旋轉矩陣融入 query 和 key 向量中,使得相對位置關系自然體現在點積注意力中,支持更好的外推性和長序列建模。
-
什么是絕對位置編碼 vs 相對位置編碼?各自的優缺點?
- 絕對:每個位置一個編碼(如 BERT),簡單但難外推;
- 相對:關注 token 之間的相對距離(如 Transformer-XL, DeBERTa),更適合長序列和遷移。
🔹 四、實際應用與限制類問題
-
如果輸入序列超過模型允許的最大長度,位置編碼會出問題嗎?
是的。對于可學習的位置編碼,超出部分沒有定義;對于固定編碼(如 RoPE),可通過插值等方式外推。
-
如何讓模型支持更長的上下文(比如從 512 擴展到 2048)?位置編碼方面有哪些方法?
- 位置插值(Position Interpolation)
- 動態縮放(NTK-aware scaling)
- 使用支持外推的編碼方式(如 ALiBi、RoPE)
- 可學習編碼重新初始化并微調
-
位置編碼會影響模型的泛化能力嗎?
會。錯誤的位置編碼設計可能導致模型無法理解順序、難以遷移或外推。
-
位置編碼是否需要歸一化?為什么?
(考察細節處理:通常不需要額外歸一化,因正弦余弦編碼的值范圍固定在 [-1,1],與詞嵌入(通常經 LayerNorm 處理)的尺度兼容;若為可學習編碼,可能需通過初始化控制尺度,避免與詞嵌入差異過大。
- 如何驗證位置編碼的有效性?
(考察實驗思維:① 對比 “有無位置編碼” 的模型性能;② 分析模型對序列順序敏感的任務(如語序判斷、問答中的位置依賴)的表現;③ 可視化位置編碼的相似度矩陣,驗證相鄰位置的編碼是否更相似。)
- 在多語言模型中,位置編碼是否需要針對不同語言調整?
(考察跨語言適配:通常不需要,因位置編碼建模的是 “序列順序”,與語言無關;但需保證編碼對不同語言的序列長度都有良好泛化性。)
- 位置編碼在 Encoder 和 Decoder 中是否有區別?
(考察結構理解:在原始 Transformer 中,Encoder 和 Decoder 使用相同的位置編碼;但部分改進模型中,Decoder 可能采用特殊編碼(如考慮輸出序列的自回歸特性)。)
- 為什么位置編碼通常加在詞嵌入之后,而不是作為額外輸入?
(考察設計權衡:直接相加可復用模型的輸入維度,無需增加參數或修改網絡結構,且能讓位置信息與語義信息在底層就融合,更符合 “位置影響語義理解” 的邏輯。)
🔹 五、開放性 / 設計題(高階)
-
如果你要設計一個支持無限長度文本的模型,你會如何設計位置編碼?
考察點:是否了解外推性、相對位置、循環編碼、稀疏注意力配合等。
-
能否將位置編碼放在網絡中間層而不是輸入層?有沒有相關工作?
有研究嘗試(如 DeepNet 中的想法),但主流仍放在輸入側。中間加位置編碼可能破壞深層表示結構,需謹慎設計。
-
視覺 Transformer(ViT)中的位置編碼和 NLP 中有何異同?
ViT 通常使用可學習的 1D 或 2D 位置編碼(考慮圖像空間結構),有時也探索無位置編碼的方法(如 iGPT)。