《十二时辰》教你直观理解 Position-Encoding

TL;DR

  • paper中的位置编码定义可以直观理解为 "钟表盘上每个针头的位置坐标"
  • 跟直接拿index作为位置编码的方案相比,这种定义有两个优点
    • 可以使用不含bias的线性变换来表征\Delta t,从而便于模型attend到相对位置[1]
    • 各维度的周期互相交错,表征能力为其最小公倍数;能对训练数据中从没见过的更长位置信息加以编码

问题由来

深度学习中有个著名的 Transformer模型 (2017年Google Brain发表那篇《Attention Is All You Need》[2]) ,其中有个设计得奇形怪状的 “Position Encoding” 一直不太好理解

定义成下面这个样子(一脸懵逼,有木有……)

\begin{aligned} PE_{(pos,2i)} &= sin(pos/10000^{2i/d_{model}}) \\ PE_{(pos,2i+1)} &= cos(pos/10000^{2i/d_{model}}) \end{aligned}

关于这个 Position-Encoding的定义,有以下几点疑惑:

  1. 这种复杂的定义,真的能编码 位置信息吗?
  2. 为啥不直接用下标,而是整个这么复杂的定义?

巧的是,我昨晚看《长安十二时辰》的时候,联想到“天干地支”,
似乎对于这个定义有了 比较直观的理解 ;且待我与列位看官慢慢道来。

真能编码位置信息

干支纪年

不妨回忆一下老祖宗的“天干地支”纪年法(类似两个齿轮):

  • 以"十天干"(“甲、乙、丙、丁、戊、己、庚、辛、壬、癸”)为 第一维度
  • 以"十二地支"(“子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥”)为 第二维度
  • 两个维度 绑定在一起 循环滚动,但是周期不同(分别为10/12)
    • e.g. (简书的markdown-latex在移动端不支持中文字符,只好截图如下)
    • 两维度若独立滚动,排列组合就是 10\times12=120 \neq 60 ,与常识冲突

  • 表征能力是 两个周期的最小公倍数 lcm(10,12)=60

天干地支

(图片来自网络 http://oraclebonescriptdiary.blogspot.com/2013/08/blog-post.html)

钟表计时

类似的,看看机械钟表的表盘

  • 这是机械钟而非电子钟,可以认为 时针与分钟的行程都是连续(而非离散)的
  • 忽略纪年和计时的区别;时针与分针 类似与 天干和地支
    • 时针与分针 滚动速度(频率)不同,前者快60倍
    • 频率是周期的倒数,也可认为两者是 绑定在一起 滚动,但是周期不同
  • 由于时针的周期恰好能被分针整除,故该钟的表征能力 等于一根时针

机械钟的盘面

(图片来自京东 https://item.jd.com/54349670287.html)
(注:图片仅用于研究目的,不带货哈)

单位圆上的点坐标表征与旋转

回顾一下高中数学:

  • 单位圆上的任意点坐标可以表达为 (x,y) = \left(\cos(\varphi), \sin(\varphi)\right) 的形式
  • 不同的周期类比于不同的表针 (时、分、秒 ...) / 或者理解为 天干和地支
  • 任意一根表针的 针头坐标(x,y)旋转\theta角,皆可用 一个 2\times 2的 仅与 旋转角度\theta有关、而与起点位置(x,y)无关的矩阵表达
    \left[\begin{array}{c}{x^{\prime}} \\ {y^{\prime}}\end{array}\right]=\left[\begin{array}{cc}{\cos \theta} & {-\sin \theta} \\ {\sin \theta} & {\cos \theta}\end{array}\right] *\left[\begin{array}{l}{x} \\ {y}\end{array}\right]
  • 多根表针的情况类似,用更大的矩阵可以表达

因此,时间"10:55"也可以(冗余)表达为
\begin{aligned} &\left(hour_x, hour_y, min_x, min_y \right) \\ = &\left( \cos\left(\frac{10}{12}\cdot 2\pi \right), \sin\left(\frac{10}{12}\cdot 2\pi \right), \cos\left(\frac{55}{60}\cdot 2\pi \right), \sin\left(\frac{55}{60}\cdot 2\pi \right) \right) \\ \triangleq &\left( \cos\left(\frac{10}{f_1}\right), \sin\left(\frac{10}{f_1}\right), \cos\left(\frac{55}{f_2}\right), \sin\left(\frac{55}{f_2}\right) \right) \\ \end{aligned}

Transformer模型中的位置编码

再看看 Transformer模型中的 Position-Encoding 定义:

\begin{aligned} PE_{(pos,2i)} &= sin(pos/10000^{2i/d_{model}}) \\ PE_{(pos,2i+1)} &= cos(pos/10000^{2i/d_{model}}) \end{aligned}

其中

  • pos代表序列内维度(第几帧)
  • 2i/2i+1 分别代表PE的奇数/偶数维度(位置编码向量的第几维)
  • 从上述矩阵中切片某一列(viz. 固定列坐标,只看PE的某一个维度),并将pos简写为t,得到下述列向量
    \begin{bmatrix} \sin\left(\frac{t}{f_1}\right)\\ \cos\left(\frac{t}{f_1}\right)\\ \sin\left(\frac{t}{f_2}\right)\\ \cos\left(\frac{t}{f_2}\right)\\ \vdots\\ \sin\left(\frac{t}{f_{\frac{d_\text{model}}{2}}}\right)\\ \cos\left(\frac{t}{f_{\frac{d_\text{model}}{2}}}\right) \end{bmatrix}

恰好就是在描述 d_{\text{model}}/2根针构成的表盘上,各针头的坐标
显然,每个针头的坐标都清楚了,自然有能力表征位置信息(甚至有点维度冗余)

整这么复杂的定义,有道理

上文说过,表针的旋转可以使用不含bias的矩阵来表达;复述如下:

  • 任意一根表针的 针头坐标(x,y)旋转\theta角,皆可用 一个 2\times 2的 仅与 旋转角度\theta有关、而与起点位置(x,y)无关的矩阵表达
    \left[\begin{array}{c}{x^{\prime}} \\ {y^{\prime}}\end{array}\right]=\left[\begin{array}{cc}{\cos \theta} & {-\sin \theta} \\ {\sin \theta} & {\cos \theta}\end{array}\right] *\left[\begin{array}{l}{x} \\ {y}\end{array}\right]
  • 多根表针的情况类似,用更大的矩阵可以表达

矩阵乘法本质是线性变换,对应于Dense层; 而 t_0 + \Delta t帧的位置向量可以表示为 t_0帧 的位置向量的线性变换(只需旋转,无需偏置 ; 详见证明[3]).
这为模型捕捉单词之间的相对位置关系提供了便利,使得模型能够 方便地attend到相对时刻

思考 self-attention-layer 中 Q/K/V 的定义

  • 每一帧都是先做word_embedding("我是啥语义"),然后加上positional_embedding("我在哪一帧"),然后使用 K 矩阵做线性变换,得到代表该帧作为key的向量. (Q/V 类似同理)
  • 解码到t帧时,对t-3帧的attent程度为 Q^T_{t} K_{t-3}; 是点积形式, 两向量取值越接近,点积越大
  • QK分别都是 dense(word_embedding+positional_embedding) 的形式;若能在dense中学到rotate(-3)的关系,即可使两个向量非常接近,点积很大

反之,如果直接使用下标作为位置的定义,
则"相对时间"的概念要通过 含有bias的"仿射变换(viz. 线性变换+平移)"才能表达

另外,如上文所述的“干支纪年法”类似;各个维度的周期不能整除,可以表征的范式是各维度的最小公倍数。
这样就能在inference时,对训练数据中从没见过的更长位置信息加以编码

下面给出 MXNet中位置编码的教学实现[4];工程实现类似,参见 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是常数矩阵,无需训练
        self.P[:, :, 0::2] = nd.sin(T) # 偶数下标行 取sin
        self.P[:, :, 1::2] = nd.cos(T)
        self.dropout = nn.Dropout(dropout)

    def forward(self, X):
        # P是常数矩阵,直接截取需要的形状部分 然后与X相加即可
        X = X + self.P[:, :X.shape[1], :].as_in_context(X.context)
        return self.dropout(X)

尚存几点疑惑

  1. 位置编码为啥要跟语义向量add到一起,而非concat;上文中的旋转矩阵作用到语义部分,担心会有副作用
  2. 相对位置可以表达为线性变换,凭啥就有利于模型学习? paper原文中语焉不详,上述 K/Q/V的解释只是我的一种猜想,也不能很严谨的说服自己
  3. 更多欢迎留言讨论

Reference


  1. "详解Transformer (Attention Is All You Need)", 刘岩, 2018, https://zhuanlan.zhihu.com/p/48508221

  2. Vaswani, Ashish, et al. "Attention is all you need." Advances in neural information processing systems. 2017. https://arxiv.org/abs/1706.03762

  3. "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/

  4. "9.3 Transformer" Dive into Deep Learning, Mu Li, et al, http://en.d2l.ai/chapter_attention-mechanism/transformer.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容

  • 如果不熟悉线性代数的概念,要去学习自然科学,现在看来就和文盲差不多。”,然而“按照现行的国际标准,线性代数是通过公...
    Drafei阅读 1,527评论 0 3
  • 理解矩阵一:转载自:http://blog.csdn.net/myan/article/details/64751...
    jiandanjinxin阅读 1,522评论 1 15
  • 柿色的风里 江南用纤柔的素手 剪出了明净的秋季 落叶丰厚起来 飘逸在女孩纯洁的额头 仿佛弱水三千 江南的女孩 素面...
    馨香倾城阅读 145评论 0 3
  • 无能为力,我不喜欢这个词,但是它又经常出现在我的生活中,我不喜欢这个词又喜欢这个词。 我们有时做事会发现自己,有心...
    闲洛阅读 104评论 0 1
  • 蝶恋花·寒草 文/寒草 原创2009.09.10. 寒风清影千行树, 凄风凉月, 云蔽江石兀。 苦草怜月月不度, ...
    寒草qiu_lixian阅读 319评论 1 6