back to index
Transformer

link |
各位同學大家好,那我們現在要來講這個Transformer。那Transformer是什麼呢?Transformer它的英文的意思就是變形金剛。
link |
那這個變形金剛呢,這個Transformer呢,現在有一個非常知名的應用,這個非常知名的應用呢,叫做Bird。
link |
我們把它畫成像是一個巨大,超巨大巨人一樣,從城牆後面探出來,這個東西呢,就是Bird。
link |
好,那我們今天還不會講到Bird,我們就先講Transformer就好了。那Bird是什麼呢?Bird就是Unsupervised Trend的Transformer。
link |
那Transformer是什麼呢?Transformer它是一個Sequence-to-Sequence Model,那我們在上課錄影裡面已經有講過Sequence-to-Sequence Model了,所以我假設在座各位都知道什麼是Sequence-to-Sequence Model。
link |
那Transformer這種Sequence-to-Sequence Model它特別的地方是什麼呢?Transformer這個特別的地方是它在這個Sequence-to-Sequence Model裡面大量用到了Self-Attention這種特別的Layer。
link |
接下來我們就是要講Self-Attention這個Layer它裡面在做的事情是什麼。那一般講到要處理一個Sequence,我們最常想到要拿來用的Navigable架構就是這個RNN,對不對?
link |
那有時候你會用Single Direction的,有時候你會用Bidirectional的RNN。那RNN基本上它做的事情,那因為我們在上課錄影裡面已經有跟大家很仔細的講過了,我們這邊就不反覆再提。
link |
RNN你已經在很多很多地方都已經有看過這種Navigable架構,RNN的輸入就是一串Vector Sequence,它的輸出就是另外一串Vector Sequence。
link |
Single Directional的RNN,你在輸入B4的時候,你會已經把A1到A4通通都看過,你輸出B3的時候,你會把A1到A3都看過。如果你是Bidirectional雙向的RNN的話,那當你輸出這邊的每一個B1到B4的時候,你已經把整個Input Sequence通通都看過,才輸出B1到B4。
link |
RNN非常常被用在處理Input,是有序列的,Input是一個Sequence的狀況。那RNN有什麼樣的問題呢?它的問題就是它不容易被平行化。
link |
怎麼說它不容易被平行化呢?因為你會發現說,假設你今天要算出B4,那你要算出B4怎麼做呢?在Single Directional的情況下,你要先看A1,再看A2,再看A3,再看A4,才能夠把B4算出來。
link |
所以今天這個計算不容易是平行的,並不容易平行化RNN的運算。所以怎麼辦呢?接下來就有人提出了把CNN拿來取代RNN的想法。
link |
現在Input一樣是一個Sequence,A1到A4,但我們不用RNN來處理它,而用CNN來處理它。現在這邊每一個三角形就代表一個Builder,那這個Builder它的輸入就是Sequence中的其中一小段。
link |
比如說現在我們的Builder,它就吃三個Vector當作輸入,然後輸出一個數值。這個Builder就把這三個Vector裡面的內容串起來,然後跟Builder裡面的參數做Inner Product,然後得到一個數值。
link |
然後你要把這個Builder掃過這個Sequence,掃過這個Sequence。那Builder會不只一個,這邊有紅色的Builder,那你也有黃色的Builder,它產生另外一排不同的數值。
link |
所以用CNN,你確實也可以做到跟RNN的輸入跟輸出類似的關係,RNN輸入是一個Sequence,輸出是一個Sequence。用CNN,你有一堆Builder,你也可以做到輸入是一個Sequence,輸出是另外一個Sequence。
link |
所以表面上CNN跟RNN,它們可以做到有同樣的輸入跟輸出的Format,但是現在問題是,這邊的每一個CNN,它只能夠考慮非常有限的內容,這邊每一個CNN,它只考慮了三個Vector,不像這邊的RNN,你可以考慮整個句子才決定你的輸出。
link |
但CNN也不是沒有辦法考慮更長時間的資訊的,它也不是沒有辦法考慮更長的Dependency的,你只要疊很多層CNN,上層的Builder就可以考慮比較多的資訊。
link |
舉例來說,我們先疊了第一層CNN以後,再疊第二層CNN,第二層CNN的Builder會把第一層的Output當作它的Input。這邊這個藍色的Builder,它會看B1、B2、B3來決定它的輸出,而B1、B2、B3是根據A1到A4來決定它們的輸出。
link |
所以等同於是這個藍色的Builder,它其實已經看了整個句子裡面所有的內容。所以如果RNN疊很多層,它其實也可以看非常長時間的資訊。
link |
而RNN的一個好處是,它是可以平行化的。在這個圖片上,每一個三角形在做計算的時候,它都可以是平行的。你並不需要等第一個三角形,第一個Builder算完才算第二個Builder,你可以全部的Builder同時計算。
link |
你也不需要等紅色的Builder算完才算黃色的Builder,它們可以同時計算。所以今天CNN是比較容易平行化。但是它有一個缺點就是,今天你一定要疊很多層,它才能夠看到長期的資訊。
link |
如果今天第一個層的Builder,它就需要長時間的資訊,那做不到,因為它只能夠看很小的範圍。所以怎麼辦?有一個新的想法叫做Self-Attention。
link |
Self-Attention它做的事情就是想要取代RNN原來可以做的事情。假設等一下講的東西你聽不下去的話,你就記得今天的關鍵就是,我們有一種新的Layer叫做Self-Attention Layer,它的輸入跟輸出跟RNN是一樣的。
link |
以前RNN是一個Sequence,Output一個Sequence。現在有一種新的Layer,它不是RNN,但它也可以輸入一個Sequence,Output一個Sequence。它特別的地方是,它跟Bidirectional RNN可以有同樣的能力,Bidirectional RNN每一個輸出都看過整個Sequence。
link |
Self-Attention Layer每一個輸出,這邊的B1到B4,每一個輸出它也看過了整個Input的Sequence。但是神奇的地方是,今天B1到B4它們是同時計算的,它們可以同時被算出來,不需要先算完B1再算B2再算B3才算B4,不需要B1跟B4是同時被計算出來的。
link |
如果等一下講的東西你聽不進去的話,你就記得說,今天我們學到的關鍵就是,我們可以用Self-Attention Layer來取代RNN。
link |
基本上這個Self-Attention Layer2017年就已經被Proposed出來了,所以今天本來可以用RNN做的東西都已經有人用Self-Attention試過了,都狂洗一輪paper這樣子。
link |
你可以用RNN做的事情都已經有人用Self-Attention幫你洗過一輪了,今天我已經有點難想到沒有用Self-Attention洗過的東西了。
link |
Self-Attention這個概念最早出現在Google的一篇paper裡面,它的Title是Attention is all you need,意思就是說你不需要用RNN也不需要用CNN,你唯一需要的東西就是Attention。
link |
這個東西怎麼做的呢?首先我們現在的input是X1到X4,是一個sequence。
link |
input X1到X4,每一個input先通過一個embedding,先乘上一個metric,通過一個embedding變成A1到A4,然後我們要把它丟進Self-Attention Layer。
link |
Self-Attention Layer裡面是做什麼呢?這個在Self-Attention Layer裡面,每一個input我們都分別乘上三個不同的transformation,都分別乘上三個不同的metric,產生三個不同的vector。
link |
這三個不同的vector,我們分別把它命名為Q、K跟V。Q代表什麼意思呢?等一下我們會更清楚這個Q、K跟V,它們是怎麼運作的。
link |
Q代表的是query,它是要去match其他人的,等一下我們會講說所謂的match其他人是什麼意思。
link |
你就把每一個input的A都乘上某一個metric WQ,然後你就得到Q1到Q4,有得到Q1、Q2、Q3跟Q4,這些東西叫做query。
link |
接下來用同樣的方法,但是你把A乘上不同的metric WK,你得到K1到K4,這些K叫做Key,它們是要拿來被match的,被這個query match的。
link |
這個等一下我們也會再看到說Key是怎麼用的。
link |
然後還有一個東西叫做value,這個V,V就是要被抽取出來的information。
link |
我們一樣把A1到A4乘上不同的WV,我們得到V1、V2、V3跟V4。
link |
好,那現在呢,我們現在每一個input、每一個A、每一個timestamp,現在都有Q、K、V三個不同的vector。
link |
接下來我們要做的事情是什麼呢?接下來要做的事情就是,拿每一個query Q去對每一個Key K做attention這件事情。
link |
我們就把每一個Q去對每一個K做attention。
link |
我們先把Q1拿出來,等一下每一個Q都要被用一次,從Q1到Q4,每一個Q都要被用一次。
link |
我們先把Q1拿出來,好,那我們把Q1去對K1做attention。
link |
那等一下下一頁投影片會告訴你說attention的式子長的是什麼樣子。
link |
那過去我們上課錄影也已經有講過attention了,我們說講attention有各式各樣不同的算法。
link |
它要做的事情本質上就是吃兩個向量,輸出就是告訴你說這兩個向量有多匹配。
link |
總之吃兩個向量,輸出一個分數,就是attention做的事情。
link |
而至於怎麼吃兩個向量輸出一個分數,有各式各樣不同的做法。
link |
等一下下一頁投影片告訴你說,在Google的Self-Attention的layer裡面,他們做的事情是什麼。
link |
好,總之我們把Q1跟K1做attention,比如說你可以做inner product,你就得到一個數值,代表Q1跟K1之間的attention的weight。
link |
我們叫做α11,代表1Q1對K1的attention。
link |
然後接下來你拿Q1也對K2做attention,得到α12。
link |
你拿Q1對K3也做attention,得到α13。
link |
你拿Q1對K4也做attention,得到α14。
link |
這個attention怎麼算的呢?在這個Self-Attention的layer裡面,用的叫做scale的double product attention。
link |
也就是說,這下面的α1i是怎麼來的呢?
link |
就是拿Q1對K1做inner product,然後再除以√d。
link |
這邊比較難理解的是,為什麼要除以√d呢?
link |
d是什麼?d是Q跟K的dimension。
link |
這邊因為你跟Q跟K要做inner product,所以Q跟K的dimension會是一樣的,d就是Q跟K的dimension。
link |
你要把Q跟K做inner product以後再除以√d。
link |
這邊一個直觀的解釋是說,你知道Q跟K做double product的數值,會隨著它們的dimension越大,它的variance就越大。
link |
這是直觀嘛,就是Q跟K的dimension越大,那你做double product的時候,相加的element就越多,所以variance就越大。
link |
那為什麼是除以√d而不是除其他的東西呢?
link |
在Self-Attention的layer的paper裡面有用一個註腳來解釋這件事,那你自己再看看。
link |
我沒有做過實驗說除√d,有沒有除√d到底影響有多大。
link |
原始的論文應該也沒有做這個實驗,那如果有同學有做這個實驗的話,你再來告訴我說這件事情影響有多大。
link |
我明年就把你的名字加到這個投影片上面這樣子。
link |
總之我覺得這邊你也不一定要用scale double product的attention,attention的方法有很多種,總之只要吃兩個meta,out一個分數,應該就可以了。
link |
但是我其實不知道說,因為我們一般現在在做這個Self-Attention的layer的時候,就直接套用原始paper的做法,也不會做太多的更動。
link |
那我其實不知道說如果把double product的attention換成其他種類的attention,會有多大的影響。
link |
這邊都是按照原始paper的講法來跟大家陳述一下。
link |
接下來你會做一個東西叫做softmax,也就是你會把α11到α14通過一個softmax的layer,得到α11head到α14head。
link |
那self-attention通過一個softmax的layer,softmax我們之前也已經講過很多次了,softmax做的事情就是把這邊的每一個α都取exponential,然後再除掉所有α取exponential的總和,做一下normalization,就得到αhead。
link |
做完softmax以後,接下來我們有了αhead以後,我們拿αhead去跟每一個V去相乘,我們就把α11head乘上V1,把α12head乘上V2,把α13head乘上V3,把α14head乘上V4。
link |
這邊做的事情等於就是把V1到V4用α11head到α14head做weighted sum,而你把所有的V1乘上α11head,再通通加起來,你就得到一個vector,這個vector就是V1。
link |
我們剛才講說self-attention就是輸出一個sequence,輸入一個sequence,輸出也是一個sequence,那我們現在已經得到我們要輸出的那個sequence的第一個vector就是V1。
link |
但是你會發現說,今天我們在產生這個V1的時候,它其實用了整個sequence的資訊,因為V1是哪來?
link |
它是V1到V4做weighted sum得到,而V1到V4又是從A1到A4做一個transformation得到,所以等於是你產生V1的時候,你已經看到了A1到A4之間的資訊。
link |
如果你今天產生V1的時候,你不想考慮整個句子的資訊,只想考慮local的information,對self-attention layer來說也是做得到的,它只要讓這邊的α產生出來的值變成0,它就考慮local的information。
link |
如果它要考慮global的information,它要考慮跟它最遠的這個input,跟它最遠的這個vector的資訊的話,它只要把這個attention讓它有值,它就可以考慮A4的資訊。
link |
對這個V1來說,就是天涯落壁林,對它來說不管是近的東西還是遠的東西,只要它想,它就可以用attention去把它看到,它就可以用attention去把再遠的vector,它的information都可以用attention被擷取出來。
link |
至於要看近看遠,要看哪一個input sequence的哪一個部分用attention,自己用學的來決定,這就是self-attention的妙用。
link |
剛才算出來的是B1,其實今天在同一時間,你也可以算B2,在output sequence裡面的每一個B,他們計算出來都是平行的,他們是可以同時做運算的,這邊算出B1,同時也算B2。
link |
B2就是拿query Q2去對其他的K做attention,所以我們就把Q2對K1算一下它的attention,Q2對K2做attention,Q2對K3做attention,Q2對K4做attention。
link |
你要做softmax得到一串alpha hat,接下來再拿這些alpha hat對input的B做weighted sum,你就把alpha21 hat乘B1,alpha22 hat乘B2,alpha23 hat乘B3,alpha24 hat乘B4,把它們全部加起來得到B2就結束了。
link |
所以現在我們就算出了output sequence的第二個vector就是B2,用同樣的方法,你就可以把B3跟B4都算出來。
link |
那如果講剛才講的東西你沒有跟上的話,你就記得說現在input的一個sequenceA1到A4,我們得到了另外一個sequenceB1到B4。Self-attention layer它做的事情跟RNN是一樣的,只是B1到B4它們可以平行的被計算出來。
link |
接下來我們要把剛才的一連串的運算過程,Self-attention裡面的一連串的運算過程用矩陣運算來表示,這樣你就會更有感覺說為什麼剛才那一連串的運算過程是容易被平行化容易被加速。
link |
接下來我們要再跟大家更清楚的說明說Self-attention是怎麼做平行化的。我們剛才有說A1乘以一個matrix WQ就會變成Q1,
link |
A2再乘以WQ就會變成Q2,A3再乘以WQ也會變成Q3,A4除以WQ會變成Q4。所以你可以把A1到A4拼起來變成一個matrix。
link |
這個matrix我們這邊用大I來表示,我們用大I乘上WQ一次就可以得到matrix Q,matrix Q裡面的每一個column就代表一個小Q,就代表某一個position的query。
link |
同理,我們把A1到A4串起來乘上WK就可以得到每個position的key,我們把I乘上WK就得到matrix K,K的每一個column就是每一個位置的key。
link |
對value來說也是一樣,把所有的A串起來變成大I,大I乘以WV就得到所有position的value,這邊用V來表示。
link |
接下來,我們剛才說我們拿Q1去對每一個K做attention,其實就是做data product,這邊我們省略了根號K,可以讓notation更簡潔一點。
link |
Q1做data product,所謂K1跟Q1做data product的意思就是把K1做一個transpose,把K1倒下來做transpose,跟Q1做data product得到α11,K2跟Q2做data product得到α12,K3跟Q1做data product得到α13,K4跟Q1做data product得到α14。
link |
那你會發現說當我們計算α11到α14的時候,其實都是拿Q1來做計算,只是跟不同的K,跟K1到K4來做data product。
link |
所以我們現在可以把所有的K統統集合在一起,你把所有的K當作是某一個matrix的row,所以把K1到K4統統疊在一起變成一個matrix,直接把這個matrix乘上Q1,
link |
你得到的結果就是一個向量,那這個向量裡面的值就是α11到α14。
link |
所以α11到α14的計算其實也是可以平行的。
link |
接下來你還有其他的Q,把Q2拿出來,其實Q2做的事情也是一樣跟K1到K4做data product,所以就把Q2跟這個由K所組成的matrix做一下相乘,然後你就得到αQ1到αQ4。
link |
同理,Q3拿出來跟這個matrix做個相乘,得到α31到α34,Q4拿出來做個相乘,得到α41到α44。
link |
所以今天這整個運算的過程,這整個計算出attention的過程,其實就等於是把我們得到的matrix K做一個transpose,直接乘上Q,就得到attention A。
link |
每一個time step,兩兩之間都有attention,那這邊我們如果有四個input,那這個attention的matrix就是這四個。
link |
你input sequence長度如果是N,那這個attention它就變成一個matrix是N乘以N。
link |
接下來你會做softmax,得到α hat,這就沒有什麼好說的,你就對每一個column做一下softmax,把A變成A hat就結束了,把matrix A變成matrix A hat就結束了。
link |
接下來我們要把這些V1到V4根據α hat做weighted sum,那怎麼做weighted sum呢?
link |
我們把我們剛才計算出來的matrix V拿出來,matrix V裡面的每一個column都是一個value的vector小V。
link |
那怎麼計算V1呢?我們就把α11 hat乘上V1,把α12 hat乘上V2,把α13 hat乘上V3,把α14 hat乘上V4,就是把V1到V4對α11到α14做weighted sum就得到V1。
link |
那這個就是簡單的線性代數,我覺得對大家來說應該都非常熟悉。
link |
你把這個matrix A hat的第二個column拿出來,對V做相乘你就得到V2,你把第三個column拿出來,對V做相乘就得到V3,你把最後一個column拿出來,對V做相乘就得到V4。
link |
那V1到V4串起來就是最終整個self-attention layer的輸出,我們叫它O。所以最後怎麼得到self-attention的輸出呢?
link |
你就把A hat乘上V,這兩個取證相乘就得到O,最後layer的輸出就結束了。
link |
好,那我們再把剛才的整個運算再很快的看過一次,整個self-attention layer它的輸入是一個matrix,我們叫它I,輸出是一個matrix叫做O。
link |
接下來我們要看看從input的matrixI到output的matrixO,這中間self-attention的layer做了哪些事情。
link |
首先input的matrixI會分別乘上三個不同的matrix,WQ,WK,跟WB,然後你就得到一個matrixQ,matrixK,跟matrixV。
link |
這三個matrix它們的每一個column就分別代表了某一個位置的query,key,跟value。
link |
接下來你把K做transpose乘上Q就會得到attention的matrix,這邊用大A來表示。
link |
這個attention matrix裡面每一個element就代表了現在input的sequence,這個input的sequence,這個兩兩之間,input的sequence每一個位置兩兩之間的attention。
link |
A接下來做softmax得到A hat,然後再把A hat乘上V就得到最終的O。
link |
所以你要發現在self-attention layer裡面我們做的就是一連串的矩陣乘法,而矩陣乘法可以輕易地用GPU來加速。
link |
這個self-attention有一個變形叫做multi-hat的self-attention,什麼叫multi-hat的self-attention呢?我們這邊用有兩個hat的情況來做舉例。
link |
我剛才說每一個Ai都會得到Qi,Ki,跟Vi,這是我們剛才講的例子。
link |
在有兩個hat的情況下,你會進一步把Q再把它分裂變成有兩個Q。
link |
那你這邊的做法可以是,我把Qi乘上一個matrix變成Qi1,我把Qi乘上一個matrix變成Qi2,我把Qi乘上兩個不同的matrix分別變成Qi1跟Qi2。
link |
A也一樣,K也產生出Ki1、Ki2,B也一樣,也產生Vi1跟Vi2。
link |
接下來一樣做跟剛才一樣的self-attention,只是現在Qi1只會對Ki1、Kj1,它只會對跟它同樣是第一個的vector做attention。
link |
舉例來說,假設你要拿Qi1去跟別人做attention,你算大father的Key,你只會跟Ki1跟Kj1去做計算,你得到你的attention,然後你最後計算出Vi1。
link |
那Qi2也是一樣,Qi2它只跟Ki2、Kj2去做attention,得到Vi2。
link |
那你會把Vi1跟Vi2直接concatenate起來,如果concatenate完以後,你的dimension你不喜歡的話,你會再乘上一個transform,把它做一下降維,得到Vi1跟Vi2,接起來乘上Wo就得到Vi,這個就是你的self-attention layer最終的輸出。
link |
那做這個multi-head有什麼好處呢?有可能不同的head,等一下我們會看到原始paper裡面的例子,有可能不同的head,他們關注的點就是不一樣。
link |
舉例來說,可能有的head他想要看的就是local的資訊,看的就是鄰居的資訊,有的head他想要看的是比較長時間的資訊,他想要看的是比較global的資訊。
link |
你有了multi-head以後,每個head可能就可以各司其職,自己去做自己想做的事情,這是multi-head的self-attention。
link |
這邊是用兩個head做例子,在實作的時候,head的數目也是一個參數要調的,你可以做八個head、十個head等等都可以。
link |
再來還有一個問題,如果你仔細看一下,講一下這個self-attention的layer的話,你會發現說對self-attention來說,input的sequence的順序是不重要的。
link |
為什麼?對他來說,他做的事情就是跟每一個input的vector都做self-attention。所以對每一個時間點來說,跟他是鄰居的東西,還是跟他是在天涯的東西,對他來說都是一樣的。
link |
這個就是天涯若比鄰,對他來說鄰居跟天涯其實是一樣的,所以在他心裡並沒有所謂的未知的資訊。所以對self-attention的layer來說,如果你input a打了b跟b打了a是一樣的,
link |
因為他並不考慮這個input sequence的順序,這個顯然不是我們要的。我們希望能夠把input sequence的順序考慮進去self-attention的layer裡面。
link |
那所以在原始的paper,他是怎麼說的呢?他說現在你把input si通過一個乘風變成ai以後,他還要再加上一個ei,再加上一個神奇的vector叫做ei。
link |
那這個ei要跟ai的dimension是一樣的,他dimension是一樣的才能夠加上去。好,那這個ei他是手設的,他是handcrafted的,在原始的self-attention,all unique那篇paper裡面,
link |
ai不是學出來的,是直接人手設的。而這個ei代表了未知的資訊,每一個資訊,每一個未知都有一個不同的ei,就是第一個未知有一個E1,第二個未知有一個E2,第三個未知有一個E3。
link |
只要看這個E長什麼樣子,看這個vector長什麼樣子,就知道說現在的ai他的資訊他是在第幾個position。好,所以這邊原來的paper他做的事情就是把ei加到ai裡面,得到一個新的vector。
link |
接下來就沒有什麼不同,就直接apply一模一樣的self-attention的operation。那講到這邊,通常大家會有的一個問題就是,為什麼是相加,為什麼不是concatenate?
link |
你把ei跟ai加起來,原來未知的資訊不就混到ai裡面去了嗎?不就很難被找到了嗎?如果直接把它們接起來,會不會更爽一點?那我這邊提供了一個跟原來的paper不一樣的講法,
link |
就是整個最終得到的運算是一樣的,但講法不太一樣。我們這邊可以想像說,我們把input xi再貼一個,再append,再concatenate,一個one-hot的vector叫做pi,這個pi代表了未知的資訊。
link |
今天pi就是一個很長的vector,這個vector是one-hot的vector,只有一維是1,其他都是0。那pi的話就是定i為是1,其他都是0。
link |
如果是p1,就是第一維就是1,其他都是0。如果是p2,就是第二維是1,其他都是0。
link |
一看這個one-hot vector就知道這個vector是落在哪一個位置,它要跟xi的哪一個x做concatenate。我們現在把xi跟pi做concatenate,然後把它乘上一個matrix,得到它的embedding,做一個transform。
link |
你可以想像說,這個w可以拆成兩個vector,我們這邊寫成wi跟wp,那就把wi跟xi相乘,wp跟pi相乘。
link |
這個就是一般的,如果你有學線性代數的話,就是matrix partition的概念,這個沒有什麼特別的。所以這件事情就把xi跟pi串起來,再乘上一個matrix這件事情,等於把xi乘上一個matrix wi,加上pi乘上一個matrix wp。
link |
這個部分,xi乘上wi的部分就是ai,那把pi乘上wp的部分就是ei,然後把ai跟ei加起來,等同於我們把原來input的x,append一個one-hot的資訊,再做一個transformation。
link |
所以我覺得直接把ei加到ai裡面,並沒有什麼特別奇怪的地方是可以說得通的。這邊讓人匪夷所思的地方就是,你當然可以認這個wp,這個wp是可以認的。
link |
那在Self-Attention的paper,在Attention is only in a paper裡面有說,wp認的這件事情,當然有人做過了,之前做convolution的sequence-to-sequence model的時候就有人嘗試過類似的做法,讓他們試一下,沒有比較好。
link |
那他們的wp是怎麼來的?他們的wp是人手設的,他們有一個非常奇怪的式子可以去產生那個wp,這個wp這個matrix就長這樣子啦,就長右邊這樣,這個圖我相信你一定在網路上很多地方都看過了,很多人都已經試著把那個wp畫出來,看看它長什麼樣子。
link |
所以這個wp它就長這個樣子。那為什麼會長這個樣子呢?我不知道說如果你設計別的樣子,最後結果會有多大的差別,如果你自己做了一下,你有什麼心得,你再告訴我,或者是在社團上分享。
link |
如果你有好的想法,我明年用你的講法的話,那我就把你的名字加在投影片上來。
link |
好,剛才講的是說,我們可以把self-attention拿來取代一個RNN,接下來我們繼續看說,self-attention在一個sequence-to-sequence的model裡面,它是怎麼被使用。
link |
那一般的sequence-to-sequence model,一般用RNN做的sequence-to-sequence model,我們已經講過了,我們說sequence-to-sequence model裡面有兩個RNN,一個是encoder,一個是decoder。
link |
在這邊很快地幫大家複習一下,你input一個sequence x1到x4,你最終decoder要output一個sequence o1到o3,那這個sequence-to-sequence model有什麼妙用,有太多妙用,比如說你可以拿它來訓練一個翻譯器,輸入中文機器學習輸出,就是machine learning這樣子。
link |
那input這個sequence x1到x4要通過一個bi-directional RNN變成h1到h4,那這個bi-directional RNN現在你已經知道可以用self-attention把它取代掉,如果你不喜歡RNN,覺得它運算太慢,無法平行化的話,用self-attention來取代它。
link |
decoder的部分也是一個RNN,原來我們做的事情是,我們會做attention,從每一個decoder time state,你都會根據之前encoder的output做一下attention,每一個time state都有一個attention,然後你每一個time state都會輸出的東西。
link |
這也是一個RNN,這個RNN也可以用self-attention的layer把它取代掉,簡單的概念就是這個樣子,總之看到RNN,就用self-attention把它換掉,就結束了。
link |
接下來,這邊有一個Google的blog上面的動畫,現在Google的blog上面都會有一些很清楚的動畫,這個動畫就是告訴你說,如果我們今天用self-attention的時候,做在sequence-to-sequence的model上,看起來像是什麼樣子。
link |
input一個sequence,每一個time state互相之間都做attention,從下一個time state起,它會告訴你說這些attention是平行運算的,是平行運算的,每一層都做self-attention。
link |
接下來decode了,decode的時候會對input的encoder做attention,但是在decode第二個word的時候,它不只是對input做attention,它也會對之前已經產生出來的東西做attention,最後就呈出一個句子,input是英文,output是另外一個語言的翻譯結果。
link |
我們再看一次,現在是incode的狀況,incode的時候,所有input sequence的word,兩兩之間都要做attention,這些attention是平行的,做三次,有三個attention的layer。
link |
接下來做decode,在做decode的時候,不只會attent之前的input,也會attent之前已經輸出的部分,之前已經輸出的部分,之前已經輸出三個word,所以這三個word都有attent,都有射東西過來。
link |
就這樣,所以這個就是拿self-attention做在sequence-to-sequence model上的樣子。
link |
接下來就很快的看一下這個network架構,這個圖你一定看到不想再看了對不對?這個圖出現在各式各樣的地方,通常在講transformer的時候,就會跟你說transformer就是長這樣,不懂的人你還是看不懂,就是這個回事。
link |
現在我們來看一下這個圖裡面有什麼樣的東西,這個圖講的是一個sequence-to-sequence的model,左半部是encoder,右半部是decoder。
link |
這個sequence-to-sequence的model,我們這邊舉例用中文翻英文當做例子,你就輸入中文的character sequence,希望它的輸出就是英文的word sequence。所以現在encoder的輸入是一個中文的character sequence,比如說機器學習。
link |
然後在decoder,你先給它一個begin of sentence的token,然後它就輸出一個machine。然後在下一個time step,你要把machine當作輸入,它就輸出learning,然後直到它輸出句點的時候,整個翻譯的過程就結束了。這是transformer,input,output,它的format長這個樣子。
link |
接下來我們看裡面的每一個layer在做什麼事情。接下來我們來看看這個encoder decoder分別裡面做了什麼事情。
link |
先看左半部的encoder的部分,現在input會通過一個input的embedding layer變成一個vector,這個vector會加上positional的encoding,這個positional的encoding接下來會進入這個灰色的block,這個灰色的block會重複n次。
link |
那這個灰色的block裡面有什麼呢?灰色的block裡面的第一層是multi-head的attention,也就是說你現在input是一個sequence,通過這個multi-head attention layer,你會得到另外一個sequence。
link |
接下來下一個layer叫做add and null,add and null是什麼意思呢?add and null的意思是說你現在會把multi-head attention的output跟multi-head attention的input把它加起來,你會把multi-head attention的inputA跟它的outputB加起來得到b'這個是add的意思。
link |
再來這邊null的部分指的意思是說你會把這個b'再做layer normalization,那layer normalization是什麼呢?我們之前上課並沒有講過,那假設你想知道layer normalization是什麼的話,請參考以下文獻。
link |
那我們上課倒是提過另外一種normalization叫做batch normalization,那我們這邊很簡短的幫大家比較一下layer normalization跟batch normalization有什麼不同。
link |
在batch normalization裡面,我們會假設我們有一個batch,那這個batch,假設這邊我們的batch size是4,那在做batch normalization的時候,我們是對同一個batch裡面不同data的同樣的dimension做normalization,我們希望整個batch裡面同一個dimension的mean等於0,variance等於1,這個是batch normalization。
link |
如果是layer normalization的話,layer normalization是不需要考慮batch的,layer normalization是說給一筆data,我們希望它各個不同dimension的mean是0,variance是1,這個是layer normalization。
link |
那一般layer normalization會搭配RNN一起使用,那transformer很像是RNN,我想這就是為什麼這邊會使用layer normalization的理由。
link |
好,那接下來呢,我們繼續看add and none之後會發生什麼事,add and none之後呢,我們會有一個feedforward layer,那這個feedforward layer會把這個input sequence的每一個vector,每一個input sequence的每一個vector都進行處理,然後會還有另外一個add and none的layer。
link |
好,那接下來我們看右半部,右半部是decoder的部分,好,那現在這個decoder的input是它前一個timestamp所產生的output,那一樣通過output embedding加上positional encoding,加入positional information進入灰色的block,這個灰色的block一樣會重複N次。
link |
在這個灰色的block的第一層呢,叫做mask的multi-head attention,這邊加一個mask是什麼意思呢,加一個mask的意思是說,現在我們在做self-attention的時候,這個decoder只會attend到它已經產生出來的sequence,那這個非常合理嘛,因為還沒有產生出來的東西根本就不存在,你根本沒有辦法對它做attention。
link |
那這邊會使用mask attention,是attend已經產生出來的部分,好,那這邊一樣有一個add and none的layer,那接下來還有一個multi-head attention的layer,這個multi-head attention的layer它是attend到之前encoder的部分的輸出,然後還有一個add and none layer,還有一個before layer,再做add and none,最後做linear,做self-max,得到最終的output,這就是整個transformer所做的事情。
link |
好,那接下來呢,我們要看的是在transformer原始paper的最終版本,它有附上了一些attention的visualization,那這個attention怎麼看呢,attention其實是最終attention,每兩個word之間都會有一個attention,所以那個attention就像是一個matrix一樣。
link |
那在這個圖上呢,attention的weight越大,這個線條就越粗,attention的weight越小,它的線條就越細,那在這個圖上呢,每個word兩兩之間都是有attention的。
link |
這邊有一個非常神奇的現象,是在Google的blog上找到的,現在引述一個句子,the animal didn't cross the street because it was too tired,這個動物它沒有走過這一條路,因為它太累了。
link |
好,今天在做attention的時候,你就會發現說it它是attend到animal,那這個是一個很自然的結果,因為今天這個it它所指涉的就是動物,它說it was too tired,什麼東西too tired呢,是動物太累了,所以它沒有辦法走過這條街,而itmachine自動學到說在做attention的時候,it要attend到animal。
link |
而如果我們今天稍微換了一個句子,我們只是把tire改成why,就這個句子變成the animal didn't cross the street because it was too wide,這個動物沒有走過這條路,因為這一條路太寬了,這邊的it指的不再是動物,你一改了這個字以後,machine居然就自動知道說it要attend到street,現在it指的是street而不是指animal。
link |
他們在訓練transformer的時候都是用translation,訓練完一個可以做translation的transformer以後,把它中間的hidden layer,把它中間的self-attention的layer拿出來分析以後所得到的結果。
link |
剛才我們有講到multi-head的attention,我們說在multi-head的attention裡面,每一個Q,每一組QKV,它們都做不同的事情。這邊只是想告訴你說,確實每一組QKV都做不同的事情,比如說你用某一組的query跟key做出來的attention是長這樣,你用另外一組query跟key做出來的attention是長這樣。
link |
顯然下面這一組query跟key,它們想要找的是local的information,每一個word都要attend到它之後的某幾個word,每一個word都會attend到它之後的下一個word。
link |
而在這一組Q跟K裡面,它們做的事情是比較複雜的,每一個word不是只attend到下一個word,而是attend到很長一段時間點之後的word。所以這個是multi-head的attention可以達成的效果。
link |
這個transformer可以拿來用在哪裡呢?基本上只要原來可以做sequence-to-sequence model的東西,都可以換成transformer。基本上現在也都被洗過一輪了,你看到原來用sequence-to-sequence model的東西,應該都有人用transformer幫你洗過一輪了。
link |
讓我覺得驚人的是做summarization,有人train了一個summarizer,做summarization其實是很常見的,過去常常說我們可以train一個sequence-to-sequence model,input一篇文章,output就是這篇文章的摘要。
link |
在這邊驚人的地方是,這也是Google做的,他們train的summarizer,input不是一篇文章,而是一整一堆文章,而是一個文章的set。
link |
他們的output是什麼?他們的output也是一篇文章,他們希望有Wikipedia的風格,也就是希望機器在讀了搜尋引擎搜尋到的文章以後,自動寫出Wikipedia的文章。
link |
他們確實收集了這樣的資料,他們就把Wikipedia的文章爬一堆出來,這是他們的正確答案。
link |
再說,Wikipedia裡面有一篇文章講的是臺灣大學,就把臺灣大學當作關鍵字去搜尋Google,找前十篇文章出來,看看臺灣大學的那個icon裡面有哪些reference,把那些reference的網頁爬一爬,就得到一個document set。
link |
臺灣大學的Wikipedia裡面的內容就是它的光處,然後就硬券下去,希望機器自動學會產生Wikipedia的文章,你可以自己去看看它做出來的結果如何。
link |
比較讓人驚嘆的是,在過去沒有transformer的時候,這個task大概是做不起來的,因為你看看它input的word sequence的長度,他說input的這些文章的長度算起來,有10的二次方到10的六次方的word那麼多。
link |
那你今天如果說,那一個RNN讀過10個六次方的word還不爛掉,我覺得應該是不太可能的。
link |
那output是從10個word到上千個word都有可能,如果你過去沒有用self-attention,沒有用transformer,直接用RNN產生10個三次方的sequence,我看也是很容易爛掉。
link |
所以今天它有了transformer以後,它可以硬券一個summarizer,input可以是上萬個word,output是上千個word,自動寫一個Wikipedia的文章,你可以自己去看看這個reference,看看它做得怎麼樣。
link |
好,那transformer後來有一個更進一步的變形,叫做universal的transformer,光聽名字就覺得很屌。
link |
那它簡單的概念是說,本來transformer每一層都是不一樣,現在它在這個縱軸上,在深度上面做RNN,每一層都是一樣的transformer,在深度上是RNN。
link |
本來橫的地方,本來時間上,position的方向是RNN,現在換成transformer,但是深度上換成RNN,所以就是同一個transformer的block不斷的被反覆使用。至於它的細節,你就可以參考Google的blog,或者是看一下universal transformer的文章。
link |
好,那transformer最早被提出來是用在文字上,現在它也可以被用在影像上。舉例來說,有一個self-attention的game,你在用self-attention處理影像的時候,你可以讓每一個pixel都去attach其他的pixel,這樣你在處理影像的時候可以考慮比較global的資訊。