TL;DR
- paper中的位置編碼定義可以直觀理解為 "鐘表盤上每個針頭的位置坐標(biāo)"
- 跟直接拿index作為位置編碼的方案相比祥国,這種定義有兩個優(yōu)點
- 可以使用不含bias的線性變換來表征飞蛹,從而便于模型attend到相對位置[1]
- 各維度的周期互相交錯施戴,表征能力為其最小公倍數(shù);能對訓(xùn)練數(shù)據(jù)中從沒見過的更長位置信息加以編碼
問題由來
深度學(xué)習(xí)中有個著名的 Transformer模型 (2017年Google Brain發(fā)表那篇《Attention Is All You Need》[2]) ,其中有個設(shè)計得奇形怪狀的 “Position Encoding” 一直不太好理解
定義成下面這個樣子(一臉懵逼和悦,有木有……)
關(guān)于這個 Position-Encoding的定義,有以下幾點疑惑:
- 這種復(fù)雜的定義渠缕,真的能編碼 位置信息嗎鸽素?
- 為啥不直接用下標(biāo),而是整個這么復(fù)雜的定義亦鳞?
巧的是馍忽,我昨晚看《長安十二時辰》的時候,聯(lián)想到“天干地支”燕差,
似乎對于這個定義有了 比較直觀的理解 遭笋;且待我與列位看官慢慢道來。
真能編碼位置信息
干支紀(jì)年
不妨回憶一下老祖宗的“天干地支”紀(jì)年法(類似兩個齒輪):
- 以"十天干"(“甲徒探、乙瓦呼、丙、丁测暗、戊央串、己、庚碗啄、辛质和、壬、癸”)為 第一維度
- 以"十二地支"(“子挫掏、丑侦另、寅、卯、辰褒傅、巳弃锐、午、未殿托、申霹菊、酉、戌支竹、亥”)為 第二維度
- 兩個維度 綁定在一起 循環(huán)滾動旋廷,但是周期不同(分別為10/12)
-
e.g. (簡書的markdown-latex在移動端不支持中文字符,只好截圖如下)
兩維度若獨立滾動礼搁,排列組合就是 饶碘,與常識沖突
-
e.g. (簡書的markdown-latex在移動端不支持中文字符,只好截圖如下)
- 表征能力是 兩個周期的最小公倍數(shù)
(圖片來自網(wǎng)絡(luò) http://oraclebonescriptdiary.blogspot.com/2013/08/blog-post.html)
鐘表計時
類似的,看看機(jī)械鐘表的表盤
- 這是機(jī)械鐘而非電子鐘馒吴,可以認(rèn)為 時針與分鐘的行程都是連續(xù)(而非離散)的
- 忽略紀(jì)年和計時的區(qū)別扎运;時針與分針 類似與 天干和地支
- 時針與分針 滾動速度(頻率)不同,前者快60倍
- 頻率是周期的倒數(shù)饮戳,也可認(rèn)為兩者是 綁定在一起 滾動豪治,但是周期不同
- 由于時針的周期恰好能被分針整除,故該鐘的表征能力 等于一根時針
(圖片來自京東 https://item.jd.com/54349670287.html)
(注:圖片僅用于研究目的扯罐,不帶貨哈)
單位圓上的點坐標(biāo)表征與旋轉(zhuǎn)
回顧一下高中數(shù)學(xué):
- 單位圓上的任意點坐標(biāo)可以表達(dá)為 的形式
- 不同的周期類比于不同的表針 (時负拟、分、秒 ...) / 或者理解為 天干和地支
- 任意一根表針的 針頭坐標(biāo)旋轉(zhuǎn)角歹河,皆可用 一個 的 僅與 旋轉(zhuǎn)角度有關(guān)掩浙、而與起點位置無關(guān)的矩陣表達(dá)
- 多根表針的情況類似,用更大的矩陣可以表達(dá)
因此秸歧,時間"10:55"也可以(冗余)表達(dá)為
Transformer模型中的位置編碼
再看看 Transformer模型中的 Position-Encoding 定義:
其中
- 代表序列內(nèi)維度(第幾幀)
- / 分別代表PE的奇數(shù)/偶數(shù)維度(位置編碼向量的第幾維)
- 從上述矩陣中切片某一列(viz. 固定列坐標(biāo)涣脚,只看PE的某一個維度),并將簡寫為寥茫,得到下述列向量
恰好就是在描述 根針構(gòu)成的表盤上,各針頭的坐標(biāo)
顯然矾麻,每個針頭的坐標(biāo)都清楚了纱耻,自然有能力表征位置信息(甚至有點維度冗余)
整這么復(fù)雜的定義,有道理
上文說過险耀,表針的旋轉(zhuǎn)可以使用不含bias的矩陣來表達(dá)弄喘;復(fù)述如下:
- 任意一根表針的 針頭坐標(biāo)旋轉(zhuǎn)角,皆可用 一個 的 僅與 旋轉(zhuǎn)角度有關(guān)甩牺、而與起點位置無關(guān)的矩陣表達(dá)
- 多根表針的情況類似蘑志,用更大的矩陣可以表達(dá)
矩陣乘法本質(zhì)是線性變換,對應(yīng)于Dense
層; 而 幀的位置向量可以表示為 幀 的位置向量的線性變換(只需旋轉(zhuǎn),無需偏置 ; 詳見證明[3]).
這為模型捕捉單詞之間的相對位置關(guān)系提供了便利急但,使得模型能夠 方便地attend到相對時刻
思考 self-attention-layer 中 Q/K/V 的定義
- 每一幀都是先做word_embedding("我是啥語義")澎媒,然后加上positional_embedding("我在哪一幀"),然后使用 矩陣做線性變換波桩,得到代表該幀作為key的向量. (Q/V 類似同理)
- 解碼到幀時戒努,對幀的attent程度為 ; 是點積形式, 兩向量取值越接近,點積越大
-
和 分別都是
dense(word_embedding+positional_embedding)
的形式镐躲;若能在dense中學(xué)到rotate(-3)
的關(guān)系储玫,即可使兩個向量非常接近,點積很大
反之萤皂,如果直接使用下標(biāo)作為位置的定義撒穷,
則"相對時間"的概念要通過 含有bias的"仿射變換(viz. 線性變換+平移)"才能表達(dá)
另外,如上文所述的“干支紀(jì)年法”類似裆熙;各個維度的周期不能整除端礼,可以表征的范式是各維度的最小公倍數(shù)。
這樣就能在inference時弛车,對訓(xùn)練數(shù)據(jù)中從沒見過的更長位置信息加以編碼
下面給出 MXNet中位置編碼的教學(xué)實現(xiàn)[4]齐媒;工程實現(xiàn)類似,參見 GitHub
class PositionalEncoding(nn.Block):
def __init__(self, units, dropout, max_len=1000):
super(PositionalEncoding, self).__init__()
T = nd.arange(0, max_len).reshape((-1,1)) / nd.power(
10000, nd.arange(0, units, 2)/units) # 臨時矩陣T
self.P = nd.zeros((1, max_len, units)) # 注意P是常數(shù)矩陣纷跛,無需訓(xùn)練
self.P[:, :, 0::2] = nd.sin(T) # 偶數(shù)下標(biāo)行 取sin
self.P[:, :, 1::2] = nd.cos(T)
self.dropout = nn.Dropout(dropout)
def forward(self, X):
# P是常數(shù)矩陣喻括,直接截取需要的形狀部分 然后與X相加即可
X = X + self.P[:, :X.shape[1], :].as_in_context(X.context)
return self.dropout(X)
尚存幾點疑惑
- 位置編碼為啥要跟語義向量
add
到一起,而非concat
贫奠;上文中的旋轉(zhuǎn)矩陣作用到語義部分唬血,擔(dān)心會有副作用 - 相對位置可以表達(dá)為線性變換,憑啥就有利于模型學(xué)習(xí)唤崭? paper原文中語焉不詳拷恨,上述 K/Q/V的解釋只是我的一種猜想,也不能很嚴(yán)謹(jǐn)?shù)恼f服自己
- 更多歡迎留言討論
Reference
-
"詳解Transformer (Attention Is All You Need)", 劉巖, 2018, https://zhuanlan.zhihu.com/p/48508221 ?
-
Vaswani, Ashish, et al. "Attention is all you need." Advances in neural information processing systems. 2017. https://arxiv.org/abs/1706.03762 ?
-
"Linear Relationships in the Transformer’s Positional Encoding" Timo Denk's Blog, Timo Denk, 2019, https://timodenk.com/blog/linear-relationships-in-the-transformers-positional-encoding/ ?
-
"9.3 Transformer" Dive into Deep Learning, Mu Li, et al, http://en.d2l.ai/chapter_attention-mechanism/transformer.html ?