一、Vector Set as Input
1、文字處理:
在文字處理中,我們的input是一個句子(不同的句子或者詞匯著不同的長度)我們可以將句子中的每個詞匯描繪成一個vector,這樣我們將文字的輸入轉變成輸入一個vector set,(不同長短的句子對應的vector的長度不同)
2、One-Hot Encoding(將詞匯變成vector的一種編碼方式)

我們可以設計一個很長的向量,這個向量包括了這個世界上的所有詞匯,其中的每一個維度對應著一個詞匯,(如上圖所示)
但是這種編碼也有一定的缺陷,它所有假設的詞匯彼此之間都是相互獨立的,在上面幾個向量中,Cat跟Dog都是動物所以他們本應該比較相近,但是Cat跟Apple一個是動物一個是植物,他們應該相隔比較遠,但是在one-hot encoding中我們無法描述出他們之間的關系,
當然一樣有辦法去解決這個問題,我們可以使用另一種編碼方式:Word Embeding
這種編碼方式一樣是給每一個詞匯一個vector,但是這個vector中都是包括了語意資訊的,上圖是將Word Embedding可視化之后的樣子,所有的植物可能都聚成一團,所有的動詞聚成一團等,我們需要明白Word Embedding就是給每一個詞匯一個vector,而每一個句子就是一排長度不一的vector,
3、聲音信號處理

一段聲音信號其實就是一排信號,我們可以將一段聲音信號取一個范圍,這個范圍就叫做一個Window,我們將這個Window中的資訊描述成一個向量,這個向量就叫做一個Frame,在語音上,我們會把一個vector叫做一個Frane,通常一個Window的長度就是25個Millisecond,
一段25Millisecond里面的語音信號,為了要描述整個聲音信號,我們可以把這個Window向右移動10個Millisecond,
在一段聲音信號中,我們用一串向量來表示,而因為每個Window往右是平移10個Milisecond,所以在一秒中的聲音信號就有100個向量,因此聲音信號是一個很復雜的vector set,
4、圖(graph)
在Social Network中,每一個節點就是一個人,然后節點跟節點之間的edge就是他們之間的關系連接(比如說是不是朋友等)
而每一個節點可以看作是一個向量,我們們可以拿其中的任何一個人的,比方說他的個人資訊就可以用一個vector來表示)
因此一個Social Network或者Graph也可以看成由一堆向量組成的,(當然分子的資訊,我們也可以用graph描述)
二、What is the output?
1、每一個向量都有一個對應的一個label
舉例來說 在文字處理上,假設你今天要做的是POS Tagging,
POS Tagging就是詞性標註,你要讓機器自動決定每一個詞匯它是什么的詞性?(它是名詞 還是動詞 還是形容詞等等)

舉例來說,你現在看到一個句子,I saw a saw
這個句子意思是:“我看到一個鋸子”, 這個第二個saw當名詞用的時候,它是鋸子,那所以機器要知道,第一個saw是個動詞,第二個saw雖然它也是個saw,但它是名詞,但是每一個輸入的詞匯,都要有一個對應的輸出的詞性
這個任務就是,輸入跟輸出的長度是一樣的Case,這個就是屬于第一個型別的輸出,
2、一整個Sequence,只需要輸出一個Label

Sentiment Analysis(給機器看一段話,它要決定說這段話是正面的還是負面的)
假設你的公司開發了一個產品,這個產品上線了,你想要知道網友的評價怎么樣,但是你又不可能一則一則網友的留言都去分析,那我們就可以使用Sentiment Analysis的技術,讓機器自動去判讀說,當一則評價里面有提到某個產品的時候,它是正面的還是負面的,那你就可以知道你的產品,在網友心中的評價怎么樣,這個是Sentiment Analysis給一整個句子,只需要一個Label,那Positive或Negative,那這個就是第二類的輸出,
或者是如果是Graph的話呢,今天你可能想要給一個分子,然后要預測說這個分子,比如說它有沒有毒性,或者是它的親水性如何,那這就是給一個Graph 輸出一個Label
3、機器自己去決定輸出多少個Label(sequence to sequence)
翻譯就是sequence to sequence的任務,因為輸入輸出是不同的語言,它們的詞匯的數目本來就不會一樣多
或者是語音辨識也是,真正的語音辨識也是一個sequence to sequence的任務,輸入一句話,然后輸出一段文字,這也是一個sequence to sequence的任務
三、Sequence Labeling(輸入跟輸出數目一樣多的狀況)
1、解決sequence to sequence問題的方法
直覺的想法就是我們就拿個Fully-Connected的Network

然后雖然這個輸入是一個Sequence,但我們就各個擊破,不要管它是不是一個Sequence,把每一個向量,分別輸入到Fully-Connected的Network里面,然后Fully-Connected的Network就會給我們輸出,那現在看看,你要做的是Regression還是Classification,產生正確的對應的輸出,就結束了
那這么做顯然有非常大的瑕疵,假設今天是,詞性標記的問題,你給機器一個句子,I saw a saw,對Fully-Connected Network來說,后面這一個saw跟前面這個saw完全一模一樣,它們是同一個詞匯,
既然Fully-Connected的Network輸入同一個詞匯,它沒有理由輸出不同的東西
但實際上,你期待第一個saw要輸出動詞,第二個saw要輸出名詞,但對Network來說它不可能做到,因為這兩個saw 明明是一模一樣的,你叫它一個要輸出動詞,一個要輸出名詞,它會非常地困惑,完全不知道要怎么處理
為了讓Fully-Connected的Network,考慮更多的,比如說背景關系的Context的資訊把前后幾個向量都串起來,一起丟到Fully-Connected的Network就結束了

所以我們可以給Fully-Connected的Network,一整個Window的資訊,讓它可以考慮一些背景關系的,跟我現在要考慮的這個向量,相鄰的其他向量的資訊
但是這樣子的方法還是有極限,真正的問題,但是如果今天我們有某一個任務,不是考慮一個Window就可以解決的,而是要考慮一整個Sequence才能夠解決的話,就算是給你Sequence的資訊,你考慮整個Sequence,你可能也很難再做的更好了,

那有人可能會想說這個很容易,我就把Window開大一點,大到可以把整個Sequence蓋住就結束了
但是,今天Sequence的長度是有長有短的,我們剛才有說,我們輸入給我們的Model的Sequence的長度,每次可能都不一樣
如果你今天說我真的要開一個Window,把整個Sequence蓋住,那你可能要統計一下你的訓練資料,然后看看你的訓練資料裡面,最長的Sequence有多長,然后開一個Window比最長的Sequence還要長,你才有可能把整個Sequence蓋住
但是你開一個這麼大的Window,意味著說你的Fully-Connected的Network,它需要非常多的引數,那可能不只運算量很大,可能還容易Overfitting
這時候我們可以使用Self-Attention,考慮整個Input Sequence的資訊
四、Self-Attention
Self-Attention的運作方式就是,Self-Attention會“吃”一整個Sequence的資訊
然后你Input幾個Vector,它就輸出幾個Vector,比如說你這邊Input一個深藍色的Vector,這邊就給你一個另外一個Vector
這邊給個淺藍色,它就給你另外一個Vector,這邊輸入4個Vector,它就Output 4個Vector
如此一來你這個Fully-Connected的Network,它就不是只考慮一個非常小的范圍,或一個小的Window,而是考慮整個Sequence的資訊,再來決定現在應該要輸出什么樣的結果,這個就是Self-Attention,
Self-Attention不是只能用一次,你可以疊加很多次

可以Self-Attention的輸出,通過Fully-Connected Network以后,再做一次Self-Attention,Fully-Connected的Network,再過一次Self-Attention,再重新考慮一次整個Input Sequence的資訊,再丟到另外一個Fully-Connected的Network,最后再得到最終的結果,所以可以把Fully-Connected的Network,跟Self-Attention交替使用:
1、Self-Attention處理整個Sequence的資訊
2、Fully-Connected的Network,專注于處理某一個位置的資訊
3、再用Self-Attention,再把整個Sequence資訊再處理一次
4、然后交替使用Self-Attention跟Fully-Connected
五、Self-Attention程序
Self-Attention的Input,它就是一串的Vector,那這個Vector可能是你整個Network的Input,它也可能是某個Hidden Layer的Output,所以我們這邊不是用
x
x
x來表示它,

我們
a
a
a用來表示它,代表它有可能是前面已經做過一些處理,它是某個Hidden Layer的Output,那Input一排a這個向量以后,Self-Attention要Output另外一排
b
b
b這個向量,
那這每一個
b
b
b都是考慮了所有的
a
a
a以后才生成出來的,所以這邊刻意畫了非常非常多的箭頭,告訴你
b
1
b^{1}
b1 考慮了
a
1
a^{1}
a1 到
a
4
a^{4}
a4 產生的,
b
2
b^{2}
b2 考慮
a
1
a^{1}
a1 到
a
4
a^{4}
a4 產生的,
b
3
b
4
b^{3} b^{4}
b3b4 也是一樣,考慮整個input的sequence才產生出來的,
那接下來呢就是要跟大家說明,怎么產生
b
1
b^{1}
b1 這個向量
當我們知道怎么產生
b
1
b^{1}
b1 這個向量以后,你就知道怎么產生
b
1
b
2
b
3
b
4
b^{1} b^{2} b^{3} b^{4}
b1b2b3b4 剩下的向量
這里有一個特別的機制,這個機制是根據
a
1
a^{1}
a1 這個向量,找出整個很長的sequence里面,到底哪些部分是重要的,哪些部分跟判斷
a
1
a^{1}
a1 是 哪一個 label是有關系的, ,哪些部分是我們要決定
a
1
a^{1}
a1 的class,決定
a
1
a^{1}
a1 的regression數值的時候,所需要用到的資訊,
每一個向量跟的關聯的程度,用一個數值叫
α
α
α來表示
這個self-attention的module,怎么自動決定兩個向量之間的關聯性呢?
你給它兩個向量
a
1
a^{1}
a1 跟
a
4
a^{4}
a4, 它怎么決定
a
1
a^{1}
a1 跟
a
4
a^{4}
a4 有多相關,然后給它一個數值
α
α
α,
此時我們需要一個計算attention的模組

這個計算attention的模組,就是拿兩個向量作為輸入,然后它就直接輸出
α
α
α那個數值,
計算這個 α α α的數值有各種不同的做法
1、dot product(比較常見的作法),輸入的這兩個向量分別乘上兩個不同的矩陣,左邊這個向量乘上
W
q
W^{q}
Wq 這個矩陣得到矩陣
q
q
q,右邊這 個向量乘上
W
k
W^{k}
Wk 這個矩陣得到矩陣
k
k
k,再把
q
q
q 跟
k
k
k 做dot product,就是把他們做element-wise 的相乘,再全部加起來以后就得到一個 scalar,這個scalar就是
a
a
a, 這是一種計算a的 方式
2、Additive,它的計算方法就是,把同樣這兩個向量通過
W
q
W
k
W^{q} W^{k}
WqWk, 得到
q
q
q 跟
k
k
k,那我們不是把它做Dot-Product,是 把它這個串起來,然后丟到這個過一個Activation Function,然后再通過一個Transform,然后得到
α
α
α**
但是在接下來的討論里面,我們都只用dot product方法,這也是今日最常用的方法,也是用在Transformer里面的方法
下面我們就要把這邊的去跟這邊的,分別都去計算他們之間的關聯性,也就是計算他們之間的
α
α
α
我們將
a
1
a^{1}
a1 乘上
W
q
W^{q}
Wq 得到
q
1
q^{1}
q1(這個q有一個名字,叫做Query),它就像是你搜尋引擎的時候,去搜尋相關文章的問題就像搜尋相關文章的關鍵字,所以這邊叫做Query Product
然后接下來
a
2
a
3
a
4
a^{2} a^{3} a^{4}
a2a3a4 我們都要去把它乘上W
k
^{k}
k, 得到
k
k
k 這個Vector, k這個Vectora叫做Key,把這個Query q1,跟這個Key k2,算Inner-product就得到
α
α
α
我們這邊用
α
1
,
2
\alpha_{1,2}
α1,2? 來代表說,Query是1提供的,Key是2提供的時候這個1跟2他們之間的關聯性,這個a這個關聯性叫做Attention的Score, 叫做 Attention的分數,
接下來也要跟
a
3
a
4
a^{3} a^{4}
a3a4 來計算
把
a
3
a_{3}
a3? 乘上
W
k
W^{k}
Wk, 得到另外一個Key也就是
k
3
,
a
4
k^{3}, a^{4}
k3,a4 乘上
W
k
W^{k}
Wk 得到
k
4
k^{4}
k4,然后你再把
k
3
k^{3}
k3這個Key,跟
q
1
q^{1}
q1 這個Query做 lnner-Product,得到1跟3之間的關聯性,得到
α
1
,
3
\alpha_{1,3}
α1,3?,我們把
k
4
k^{4}
k4 跟
q
1
q^{1}
q1 做Dot-Product,得到
α
1
,
4
\alpha_{1,4}
α1,4?, 得到1跟4之間的關聯性,其實一般在實做時候,
q
1
q^{1}
q1也會跟自己算關聯性,自己跟自己計算關聯性這件事情有多重要
計算出,a1跟每一個向量的關聯性以后,接下來這邊會接入一個Soft-Max

這個Soft-Max跟分類的時候的那個Soft-Max是一模一樣的,所以Soft-Max的輸出就是一排
α
α
α,所以本來有一排
α
α
α,通過Soft-Max就得到
α
′
\alpha^{\prime}
α′
這邊我們不一定要用Soft-Max,用別的替代也沒問題,比如說有人嘗試過說做個ReLU,這邊通通做個ReLU,那結果發現還比Soft-Max好一點,這邊我們要用什么Activation Function都行(Soft-Max是最常見的),
接下來得到這個
α
′
\alpha^{\prime}
α′以后,我們就要根據這個
α
′
\alpha^{\prime}
α′去抽取出這個Sequence里面重要的資訊,
根據這個
α
1
\alpha^{1}
α1我們已經知道說,哪些向量跟是最有關系的,怎么抽取重要的資訊呢?
根據這個
α
1
\alpha^{1}
α1我們已經知道說,哪些向量跟是最有關系的,怎么抽取重要的資訊呢?
1、首先把
a
1
a^{1}
a1 到
a
4
a^{4}
a4 這邊每一個向量,乘上
W
v
W^{v}
Wv 得到新的向量,這邊分別就是用
v
1
v
2
v
3
v
4
v^{1} v^{2} v^{3} v^{4}
v1v2v3v4 來表示
2、接下來把這邊的
v
1
v^{1}
v1 到
v
4
v^{4}
v4,每一個向量都去乘上Attention的分數,都去乘上
α
′
\alpha^{\prime}
α′
3、然后再把它加起來,得到
b
1
b^{1}
b1
b
1
=
∑
i
α
1
,
i
′
v
i
b^{1}=\sum_{i} \alpha_{1, i}^{\prime} v^{i}
b1=i∑?α1,i′?vi
如果某一個向量它得到的分數越高,比如說如果
a
1
a^{1}
a1 跟
a
2
a^{2}
a2 的關聯性很強,這個
α
′
\alpha^{\prime}
α′ 得到的值很大,那我們今天在做Weighted Sum以后,得到的
b
1
b^{1}
b1 的 值,就可能會比較接近
v
2
v^{2}
v2
所以誰的那個Attention的分數最大,誰的那個v就會Dominant你抽出來的結果
怎么計算這個
b
2
b^{2}
b2 ? 我們現在的主角,就變成
a
2
a^{2}
a2
1、把
a
2
a^{2}
a2 乘上一個 matrix,變成
q
2
q^{2}
q2
2、然后接下來根據
q
2
q^{2}
q2,去對
a
1
a^{1}
a1 到
a
4
a^{4}
a4 這四個位置,都去計算 attention 的 score
- 把 q 2 q^{2} q2 跟 k 1 k^{1} k1 做個這個 dot product
- 把 q 2 q^{2} q2 跟 k 2 k^{2} k2 也做個 dot product
- 把 q 2 q^{2} q2 跟 k 3 k^{3} k3 也做 dot product
- 把 q 2 q^{2} q2 跟 k 4 k^{4} k4 也做 dot product,得到四個分數
3、得到這四個分數以后,可能還會做一個 normalization,比如說 softmax,然后得到最后的 attention 的 score,
α
2
,
1
′
α
2
,
2
′
α
2
,
3
′
α
2
,
4
′
\alpha_{2,1}^{\prime} \alpha_{2,2}^{\prime} \alpha_{2,3}^{\prime} \alpha_{2,4}^{\prime}
α2,1′?α2,2′?α2,3′?α2,4′? 那我們 這邊用
α
′
\alpha^{\prime}
α′ 表示經過 normalization 以后的attention score
4、接下來拿這四個數值,分別乘上
v
1
v
2
v
3
v
4
v^{1} v^{2} v^{3} v^{4}
v1v2v3v4
- 把 α 2 , 1 ′ \alpha_{2,1}^{\prime} α2,1′? 乘上 v 1 v^{1} v1
- 把 α 2 , 2 ′ \alpha_{2,2}^{\prime} α2,2′? 乘上 v 2 v^{2} v2
- 把 α 2 , 3 ′ \alpha_{2,3}^{\prime} α2,3′? 乘上 v 3 v^{3} v3
- 把
α
2
,
4
′
\alpha_{2,4}^{\prime}
α2,4′? 乘上
v
4
v^{4}
v4,然后全部加起來就是
b
2
b^{2}
b2
b 2 = ∑ i α 2 , i ′ v i b^{2}=\sum_{i} \alpha_{2, i}^{\prime} v^{i} b2=i∑?α2,i′?vi
六、從矩陣的角度去計算Self-attention
接下來我們從矩陣乘法的角度,再重分析一下Self-attention 是怎么運作的
我們現在已經知道每一個 a 都產生 q k v
我們每一個
a
a
a, 都乘上一個矩陣,我們這邊用
W
q
W^{q}
Wq 來表示它,得到
q
i
q^{i}
qi, 每一個
a
a
a 都要乘上
W
q
W^{q}
Wq, 得到
q
i
q^{i}
qi, 這些不同的
a
a
a 你可以把它合起來,當作一個 矩陣來看待

一樣
a
2
a
3
a
4
a^{2} a^{3} a^{4}
a2a3a4 也都乘上
W
q
W^{q}
Wq 得到
q
2
q
3
q^{2} q^{3}
q2q3 跟
q
4
q^{4}
q4,那你可以把
a
1
\mathrm{a} 1
a1 到
a
4
\mathrm{a} 4
a4 拼起來,看作是一個矩陣,這個矩陣我們用
I
I
I 來表示, 這個矩陣的四個 column 就是
a
1
a^{1}
a1 到
a
4
a^{4}
a4
I
I
I 乘上
W
q
W^{q}
Wq 就得到另外一個矩陣,我們用
Q
Q
Q 來表示它,這個
Q
Q
Q 就是把
q
1
q^{1}
q1 到
q
4
q^{4}
q4 這四個 vector 拼起來,就是
Q
Q
Q 的四個 column
所以我們 從
a
1
a^{1}
a1 到
a
4
a^{4}
a4,得到
q
1
q^{1}
q1 到
q
4
q^{4}
q4 這個操作,其實就是把
I
I
I這個矩陣,乘上另外一個矩陣
W
q
W^{q}
Wq, 得到矩陣
Q
°
I
Q_{\circ} I
Q°?I 這個矩陣它裡面的 column就 是我們 Self-attention 的 input是
a
1
a^{1}
a1 到
a
4
;
?
?
W
q
a^{4} ; **W^{q}
a4;??Wq 其實是 network 的引數,它是等一下會被learn出來的** ;
Q
Q
Q 的四個 column,就是
q
1
q^{1}
q1 到
q
4
q^{4}
q4
接下來產生k跟v的操作跟q是一模一樣的
所以每一個 a 得到 q k v ,其實就是把輸入的這個,vector sequence 乘上三個不同的矩陣,你就得到了 q,得到了 k,跟得到了 v
下一步是,每一個 q 都會去跟每一個 k,去計算這個 inner product,去得到這個 attention 的分數
那得到 attention 分數這一件事情,如果從矩陣操作的角度來看,它在做什么樣的事情呢?

你就是把
q
1
q^{1}
q1 跟
k
1
k^{1}
k1 做 inner product,得到
α
1
,
1
\alpha_{1,1}
α1,1?,所以
α
1
,
1
\alpha_{1,1}
α1,1? 就是
q
1
q^{1}
q1 跟
k
1
k^{1}
k1 的 inner product,那這邊我就把這個,
k
1
k^{1}
k1 它背后的這個向量,把它畫成 比較寬一點代表說它是 transpose
同理
α
1
,
2
\alpha_{1,2}
α1,2? 就是
q
1
q^{1}
q1 跟
k
2
k^{2}
k2,做 inner product,
α
1
,
3
\alpha_{1,3}
α1,3? 就是
q
1
q^{1}
q1 跟
k
3
k^{3}
k3 做 inner product,這個
α
1
,
4
\alpha_{1,4}
α1,4? 就是
q
1
q^{1}
q1 跟
k
4
k^{4}
k4 做 inner product 那這個四個步驟的操作,你其實可以把它拼起來,看作是矩陣跟向量相乘
那這個四個步驟的操作,你其實可以把它拼起來,看作是矩陣跟向量相乘

這四個動作,可以看作是我們把
k
1
k^{1}
k1 到
k
4
k^{4}
k4 拼起來,當作是一個矩陣的四個 row
那我們剛才講過說我們不只是
q
1
q^{1}
q1,要對
k
1
k^{1}
k1 到
k
4
k^{4}
k4 計算
a
t
t
e
n
t
i
o
n
,
q
2
,
q
3
,
q
4
\mathrm{attention}, q^{2}, q^{3}, q^{4}
attention,q2,q3,q4 也要對
k
1
k^{1}
k1 到
k
4
k^{4}
k4 計算 attention,操作其實都是一模一樣的

所以這些 attention 的分數可以看作是兩個矩陣的相乘一個矩陣它的 row,就是
k
1
k^{1}
k1 到
k
4
k^{4}
k4,另外一個矩陣它的 column
我們會在 attention 的分數,做一下 normalization,比如說你會做 softmax,你會對這邊的每一個 column,每一個 column 做 softmax,讓每 一個 column 裡面的值相加是 1
之前有講過說 其實這邊做 softmax不是唯一的選項,你完全可以選擇其他的操作,比如說 ReLU 之類的,那其實得到的結果也不會比較差,通 過了 softmax 以后,它得到的值有點不一樣了,所以我們用
A
′
A^{\prime}
A′,來表示通過 softmax 以后的結果
我們已經計算出
A
′
A^{\prime}
A′
那我們把這個
v
1
v^{1}
v1 到
v
4
v^{4}
v4 乘上這邊的
a
a
a 以后,就可以得到
b
b
b
我們把
v
1
v^{1}
v1 到
v
4
v^{4}
v4 拼起來,把
v
1
v^{1}
v1 到
v
4
v^{4}
v4 當成是
V
V
V 這個矩陣的四個 column,把它拼起來,然后接下來把
v
v
v 乘上,
A
′
A^{\prime}
A′ 的第一個 column 以后,你 得到的結果就是
b
1
b^{1}
b1
如果熟悉線性代數的話,你知道說把這個
A
′
A^{\prime}
A′ 乘上
V
V
V, 就是把
A
′
A^{\prime}
A′ 的第一個 column,乘上
V
V
V 這一個矩陣,你會得到你 output 矩陣的第一個 column
而把
A
\mathrm{A}
A 的第一個 column乘上
V
\mathrm{V}
V 這個矩陣做的事情,其實就是把
V
\mathrm{V}
V 這個矩陣里面的每一個 column,根據第
A
′
A^{\prime}
A′ 這個矩陣里面的每一個 column 里面每一個 element,做 weighted sum,那就得到
b
1
b^{1}
b1
那就是這邊的操作,把
v
1
v^{1}
v1 到
v
4
v^{4}
v4 乘上 weight,全部加起來得到
b
1
b^{1}
b1,
如果我們是用矩陣操作的角度來看它,就是把
A
′
A^{\prime}
A′ 的第一個 column 乘上
V
\mathrm{V}
V,就得到
b
1
b^{1}
b1,然后接下來就是以此類推

就是以此類推,把
A
′
A^{\prime}
A′ 的第二個 column 乘上
V
\mathrm{V}
V, 就得到
b
2
,
A
′
b^{2}, A^{\prime}
b2,A′ 的第三個 column 乘上
V
V
V 就得到
b
3
,
A
′
b^{3}, A^{\prime}
b3,A′ 的最后一個 column 乘上
V
V
V,就得到
b
4
b^{4}
b4 所以我們等于就是把
A
′
A^{\prime}
A′ 這個矩陣,乘上
V
V
V 這個矩陣,得到
O
O
O 這個矩陣,O 這個矩陣里面的每一個 column,就是 Self-attention 的輸出,也就是
b
1
b^{1}
b1 到
b
4
b^{4}
b4

- I 是 Self-attention 的 input,Self-attention 的 input 是一排的vector,這排 vector 拼起來當作矩陣的 column,就是 I
- 這個 input 分別乘上三個矩陣, W q W k W^{q} W^{k} WqWk 跟 W v W^{v} Wv,得到 Q K V
- 這三個矩陣,接下來 Q \mathrm{Q} Q 乘上 K \mathrm{K} K 的 transpose,得到 A \mathrm{A} A 這個矩陣, A \mathrm{A} A 的矩陣你可能會做一些處理,得到 A ′ A^{\prime} A′,那有時候我們會把這個 A ′ A^{\prime} A′, 叫做 Attention Matrix, 生成Q矩陣就是為了得到Attention的score
- 然后接下來你把 A ′ A^{\prime} A′ 再乘上 V V V,就得到 O,O 就是 Self-attention 這個 layer 的輸出,生成V是為了計算最后的b, 也就是矩陣 O \mathrm{O} O
所以 Self-attention 輸入是 l,輸出是 O,我們發現說雖然是叫 attention,但是其實 Self-attention layer 里面,唯一需要學的引數,就只有
W
q
W
k
W^{q} W^{k}
WqWk 跟
W
v
W^{v}
Wv 而已,只有
W
q
W
k
W^{q} W^{k}
WqWk 跟
W
v
W^{v}
Wv 是末知的,是需要透過我們的訓練資料把它找出來的
但是其他的操作都沒有末知的引數,都是我們人為設定好的,都不需要透過 training data 找出來,那這整個就是 Self-attention 的操作,從 I 到 O 就是做了 Self-attention
七、Multi-head Self-attention
Self-attention 有一個進階的版本,叫做 Multi-head Self-attention, Multi-head Self-attention,其實今天的使用是非常地廣泛的
需要用多少的 head,這個又是另外一個 hyperparameter,也是我們需要調的

- 先把 a a a 乘上一個矩陣得到 q q q
- 再把 q q q 乘上另外兩個矩陣,分別得到 q 1 q^{1} q1 跟 q 2 q^{2} q2,那這邊還有 這邊是用兩個上標, i 代表的是位置,然后這個 1 跟 2 代表是,這個位置 的第幾個 q,所以這邊有 q i , 1 q^{i, 1} qi,1 跟 q i , 2 q^{i, 2} qi,2,代表說我們有兩個 head
我們認為這個問題,里面有兩種不同的相關性,是我們需要產生兩種不同的 head,來找兩種不同的相關性
既然
q
q
q 有兩個,那
k
k
k 也就要有兩個,那
v
v
v 也就要有兩個, 從
q
q
q 得到
q
1
q
2
q^{1} q^{2}
q1q2, 從
k
k
k 得到
k
1
k
2
,
從
∨
k^{1} k^{2}, 從 \vee
k1k2,從∨ 得到
v
1
v
2
v^{1} v^{2}
v1v2,那其實就是把
q
q
q 把
k
\mathrm{k}
k 把
v
\mathrm{v}
v,分別乘上兩個矩陣,得到這個不同的 head,就這樣子而已,
對另外一個位置,也做一樣的事情,只是現在
q
1
q^{1}
q1,它在算這個 attention 的分數的時候,它就不要管那個
k
2
k^{2}
k2 了
- 所以 q i , 1 q_{i, 1} qi,1? 就跟 k i , 1 k^{i, 1} ki,1 算 attention
- q i , 1 q_{i, 1} qi,1? 就跟 k j , 1 k^{j, 1} kj,1 算 attention,也就是算這個 dot product,然后得到這個 attention 的分數
- 然后今天在做 weighted sum 的時候,也不要管 v 2 v^{2} v2 了,看 V i , 1 V^{i, 1} Vi,1 跟 v j , 1 v^{j, 1} vj,1 就好,把 attention 的分數乘 v i , 1 v^{i, 1} vi,1,把 attention 的分數乘 v j , 1 v^{j, 1} vj,1
- 然后接下來就得到 b i , 1 b^{i, 1} bi,1
這邊只用了其中一個 head,用另外一個 head,也做一模一樣的事情
所以
q
2
q^{2}
q2 只對
k
2
k^{2}
k2 做 attention,它們在做 weighted sum 的時候,只對
v
2
v^{2}
v2 做 weighted sum,然后接下來我們就得到
b
i
,
2
b^{i, 2}
bi,2
如果有多個 head,有 8 個 head 有 16 個 head,那也是一樣的操作,那這邊是用兩個 head 來當作例子
然后接下來我么可以 把
b
i
,
1
b^{i, 1}
bi,1 跟
b
i
,
2
b^{i, 2}
bi,2,把它接起來,然后再通過一個 transform

也就是再乘上一個矩陣,然后得到 bi,然后再送到下一層去,那這個就是 Multi-head attention,一個這個 Self-attention 的變形
八、Positional Encoding
目前為止,我們會發現 Self-attention 的這個 layer,它少了一個也許很重要的資訊,這個資訊是位置的資訊
我們做 Self-attention 的時候,如果覺得位置的資訊是一個重要的事情,那可以把位置的資訊把它塞進去,
怎么把位置的資訊塞進去呢,這邊就要用到一個叫做positional encoding 的技術

我們為每一個位置設定一個 vector, 叫做 positional vector,這邊用
e
i
e^{i}
ei 來表示,上標 i 代表是位置,每一個不同的位置,就有不同的vector,就是
e
1
e^{1}
e1 是一個 vector,
e
2
e^{2}
e2 是一個vector,
e
128
e^{128}
e128 是一個vector,不同的位置都有一個它專屬的 e,然后 把這個 e 加到
a
i
a^{i}
ai 上面,就結束了(就是告訴我們Self-attention,位置的資訊,如果它看到說
a
i
a^{i}
ai 好像有被加上
e
i
e^{i}
ei,它就知道說現在出現的位置,應該是在 i 這個位置)
九、Self-attention for Speech
比如說在做語音的時候,我們也可以用 Self-attention,不過在做語音的時候,可能會對 Self-attention,做一些小小的改動
因為一般語音的,如果我們要把一段聲音訊號,表示成一排向量的話,這排向量可能會非常地長

而每一個向量,其實只代表了 10 millisecond 的長度而已,所以如果今天是 1 秒鐘的聲音訊號,它就有 100 個向量了,5 秒鐘的聲音訊號,就 500 個向量了,我們隨便講一句話,都是上千個向量了
所以一段聲音訊號,要描述它的時候,那個像這個 vector 的 sequence 它的長度是非常可觀的,
那可觀的 sequence,可觀的長度,會造成什么問題呢?
我們今天在計算這個 attention matrix 的時候,它的 計算complexity 是長度的平方

計算這個 attention matrix
A
\mathrm{A}
A 我們需要做
L
\mathrm{L}
L 乘以
L
\mathrm{L}
L 次的 inner product,那如果這個
L
\mathrm{L}
L 的值很大的話,它的計算量就很 可觀,也需要很大的這個 memory, 才能夠把這個矩陣存下來
所以今天如果在做語音辨識的時候,一句話所產生的這個attention matrix,可能會太大,大到你根本就不容易處理,不容易訓練,所以在做語音的時候,有一招叫做 Truncated Self-attention

Truncated Self-attention做的事情就是,我們今天在做Self-attention的時候,不要看一整句話,就我們就只看一個小的范圍就好
那至于這個范圍應該要多大,那個是人設定的
今天在做語音辨識的時候,也許只需要看一個小的范圍就好,那就是取決于你對這個問題的理解,也許我們要辨識這個位置有什么樣的phoneme,這個位置有什么樣的內容,我們并不需要看整句話,只要看這句話,跟它前后一定范圍之內的資訊,其實就可以判斷,所以如果在做 Self-attention 的時候,也許沒有必要看過一整個句子,也許沒有必要讓 Self-attention 考慮一整個句子,也許只需要考慮一個小范圍就好,這樣就可以加快運算的速度,這個是 Truncated Self-attention,
十、Self-attention與CNN比較

用 Self-attention 來處理一張圖片,代表說,假設這個是你要考慮的 pixel,那它產生query,其他 pixel 產生 key,今天在做 inner product 的時候,考慮的不是一個小的receptive field的資訊,而是整張影像的資訊,
但是今天在做 CNN 的時候,會畫出一個 receptive field,每一個 filter,每一個 neural,只考慮 receptive field 范圍裡面的資訊
CNN 可以看作是一種簡化版的 Self-attention,因為在做CNN的時候,我們只考慮 receptive field 里面的資訊,而在做 Self-attention 的時候,我們是考慮整張圖片的資訊,所以 CNN,是簡化版的 Self-attention(或者是你可以反過來說,Self-attention 是一個復雜化的 CNN)
在 CNN 裡面,我們要劃定 receptive field,每一個 neural,只考慮 receptive field 裡面的資訊,而 receptive field 的范圍跟大小,是人決定的,
而對 Self-attention 而言,我們用 attention,去找出相關的 pixel,就好像是 receptive field 是自動被學出的,network 自己決定說,receptive field 的形狀長什么樣子,network 自己決定說,以這個 pixel 為中心,哪些 pixel 是我們真正需要考慮的,那些 pixel 是相關的
所以 receptive field 的范圍,不再是人工劃定,而是讓機器自己學出來
既然Self-attention 比較 flexible,之前有講說比較 flexible 的 model,比較需要更多的 data,如果你 data 不夠,就有可能 overfitting
就會發現說,隨著資料量越來越多,那 Self-attention 的結果就越來越好,最終在資料量最多的時候,Self-attention 可以超過 CNN,但在資料量少的時候,CNN 它是可以比 Self-attention,得到更好的結果的

十一、Self-attention與RNN的比較

在 RNN 中:
- 左邊是你的 input sequence,你有一個 memory 的 vector
- 然后你有一個 RNN 的 block,這個 RNN 的 block 呢,它“吃” memory 的 vector“吃”第一個 input 的 vector
- 然后 output 一個東西,然后根據這個 output 的東西,我們通常叫做這個 hidden,這個 hidden 的 layer 的 output
- 然后通過這個 fully connected network,然后再去做你想要的 prediction
接下來當sequence里面,第二個 vector 作為 input 的時候,也會把前一個時間點吐出來的東西,當做下一個時間點的輸入,再丟進 RNN 里面,然后再產生新的 vector,再拿去給 fully connected network
然后第三個 vector 進來的時候,你把第三個 vector 跟前一個時間點的輸出,一起丟進 RNN,再產生新的輸出,然后在第四個時間點
第四個 vector 輸入的時候,把第四個 vector 跟前一個時間點,產生出來的輸出,再一起做處理,得到新的輸出,再通過 fully connected network 的 layer,這個就是 RNN
Recurrent Neural Network跟 Self-attention 做的事情其實也非常像,它們的 input 都是一個 vector sequence
Self-attention output 是另外一個 vector sequence,這里面的每一個 vector,都考慮了整個 input sequence 以后,再給 fully connected network 去做處理
RNN它也會 output 另外一群 vector,這另外一排 vector 也會給,fully connected network 做進一步的處理
那 Self-attention 跟 RNN 有什么不同呢?
當然一個非常顯而易見的不同,你可能會說,這邊的每一個 vector,它都考慮了整個 input 的 sequence,而 RNN 每一個 vector,只考慮了左邊已經輸入的 vector,它沒有考慮右邊的 vector,那這是一個很好的觀察
但是 RNN 其實也可以是雙向的,所以如果你 RNN 用雙向的 RNN 的話,其實這邊的每一個 hidden 的 output,每一個 memory 的 output,其實也可以看作是考慮了整個 input 的 sequence,
但是假設我們把 RNN 的 output,跟 Self-attention 的 output 拿來做對比的話,就算我們用 bidirectional 的 RNN,還是有一些差別的:
對 RNN 來說,假設最右邊這個黃色的 vector,要考慮最左邊的這個輸入,那它必須要把最左邊的輸入存在 memory 里面,然后接下來都不能夠忘掉,一路帶到最右邊,才能夠在最后一個時間點被考慮
但對 Self-attention 來說沒有這個問題,它只要這邊輸出一個 query,這邊輸出一個 key,只要它們 match 得起來你可以從非常遠的 vector,在整個 sequence 上非常遠的 vector,輕易地抽取資訊
還有另外一個更主要的不同是,RNN 今天在處理的時候, input 一排 sequence,output 一排 sequence 的時候,RNN 是沒有辦法平行化的
但 Self-attention 有一個優勢,是它可以平行處理所有的輸出,我們input 一排 vector,再 output 這四個 vector 的時候,這四個 vector 是平行產生的,并不需要等誰先運算完才把其他運算出來,output 的這個 vector,里面的 output 這個 vector sequence 里面,每一個 vector 都是同時產生出來的
所以在運算速度上,Self-attention 會比 RNN 更有效率
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300075.html
標籤:其他
上一篇:基于Qt的Opencv代碼加速
