back to index
【機器學習2021】Transformer (下)

link |
接下來我們要講Decoder,我們上上週已經講了Encoder,接下來我們要講Decoder。
link |
Decoder其實有兩種,等一下會花比較多時間介紹你比較常見的,這個叫做Auto-Regressive的Decoder。
link |
這個Auto-Regressive的Decoder是怎麼運作的呢?等一下我們是用語音辨識來當作例子跟大家說明,
link |
不過用在作業裡面的機器翻譯其實是一模一樣的,你只是把輸入輸出改成不同的東西而已。
link |
語音辨識是怎麼做的呢?你知道語音辨識就是輸入一段聲音輸出一串文字。
link |
你會把一段聲音輸入給Encoder,比如說你對機器說機器學習,機器收到一段聲音訊號,
link |
聲音訊號進入Encoder以後,輸出會是什麼呢?輸出會變成一排Vector。
link |
我們上週花了很多時間講Encoder裡面有什麼樣的內容,它裡面非常的複雜,
link |
如果你忘了的話就算了,你就記得Encoder做的事情就是輸入一個Vector Sequence,輸出另外一個Vector Sequence。
link |
接下來就輪到Decoder運作了,Decoder要做的事情就是產生輸出,接下來輪到Decoder產生語音辨識的結果。
link |
Decoder怎麼產生語音辨識的結果呢?Decoder做的事情就是把Encoder的輸出先讀進去。
link |
至於怎麼讀進去,這個我們等一下再講。你先假設商號有某種方法把Encoder的輸出讀到Decoder裡面,這部我們等一下再處理。
link |
Decoder怎麼產生一段文字呢?語音辨識機器的輸出就是一段文字,Decoder怎麼產生一段文字呢?
link |
首先你要先給它一個特殊的符號,這個特殊的符號代表開始。
link |
那在助教投影片裡面是寫Begin of Sentence,所寫是BOS。
link |
那我這邊因為怕你不知道BOS是什麼,所以我就把它的意思明確的寫出來,就是開始,就是Begin的意思。
link |
那這個是一個Special的Token,就是在你的Lesson裡面,就是在你本來Decoder可能產生的文字裡面,多加一個特殊的符號,多加一個特殊的字。
link |
那這個字就代表了Begin,代表了開始這個事情。
link |
好,所以Decoder就吃到這個特殊的符號,那在這個機器學習裡面,假設你要處理NLP的問題,每一個Token你都可以把它用一個One-Hot Vector來表示。
link |
One-Hot Vector就其中一位是1,其他都是0,所以Begin也是用One-Hot Vector來表示,其中一位是1,其他是0。
link |
那接下來Decoder會吐出一個項量,這個項量裡面有什麼呢?這個Vector裡面有什麼呢?
link |
這個Vector的長度,它很長,它的長度跟你的Vocabulary的Size是一樣的。
link |
這邊的Vocabulary指的是什麼意思呢?你就先想好說你的Decoder輸出的單位是什麼。
link |
假設我們今天做的是中文的語音辨識,我們Decoder輸出的是中文,那你這邊的Vocabulary的Size可能就是中文的方塊字的數目。
link |
那中文的方塊字有多少呢?不同的字典給你的數字可能是不一樣的。
link |
常用的中文的方塊字大概兩三千個,一般人可能認得的四五千個,再更多都是罕見字、冷僻的字,你可能看到也不知道它要怎麼念,你平常寫也寫不出來。
link |
所以你就看看說你要讓你的Decoder輸出哪些可能的中文的方塊字,你就把它列在這邊。
link |
舉例來說,你覺得這個Decoder能夠輸出常見的三千個方塊字就好了,你就把它列在這個地方。
link |
那不同的語言,它輸出的單位不會不一樣,這個取決於你對那個語言的理解。
link |
比如說英文,你可以選擇輸出字母A到Z,但你可能會覺得字母這個單位太小了,有人可能會選擇輸出英文的詞彙,英文的詞彙是用空白作為間隔的。
link |
但如果用詞彙當作輸出又太多了,所以你會發現剛才在助教投影片裡面,助教說他是用Subword當作英文的單位。
link |
就有一些方法可以把英文的字首字根切出來,拿字首字根當作單位。
link |
那如果中文的話,我覺得就比較單純,通常今天你可能就用中文的方塊字來當作單位。
link |
那在這個項量裡面,這個項量的長度就跟中文裡面的方塊字,你希望機器可以輸出的方塊字的數目是一樣多的。
link |
那每一個中文的字都會對應到一個數值。
link |
那因為在產生這個項量之前,你通常會先跑一個softmax,就跟做分類一樣,在得到最終的輸出前我們不是會跑一個softmax嗎?
link |
跑一個softmax,所以這個項量裡面的分數,它是一個distribution,也就是它這個項量裡面的值,它全部加起來總和會是1。
link |
那得到這個項量以後,還不是最終輸出的結果。
link |
這個項量會給每一個中文的字一個分數,那分數最高的那個中文字,它就是最終的輸出。
link |
在這個例子裡面,機的分數最高,所以機就當作是這個decoder第一個輸出。
link |
接下來,你把機當作是decoder新的input。
link |
原來decoder的input只有begin這個特別的符號,現在它除了begin以外,它還有機作為它的input。
link |
那機也是表示成一個one-hot vector當作decoder的輸入。
link |
所以decoder現在還有兩個輸入,一個是begin這個符號,一個是機。
link |
根據這兩個輸入,它就要得到一個輸出,它輸出一個藍色的項量。
link |
根據這個藍色的項量裡面給每一個中文字的分數,我們會決定第二個輸出是什麼。
link |
那decoder接下來會拿氣當作輸入。
link |
然後現在decoder看到了begin、看到了機、看到了氣。
link |
那它接下來還要再決定接下來要輸出什麼,那它可能就輸出學。
link |
所以現在decoder看到了begin、機、氣、還有學。
link |
那incoder這邊其實也有輸入啦,那我們等一下再講incoder的輸入,decoder是怎麼處理的。
link |
所以decoder看到incoder這邊的輸入,看到機、看到氣、看到學,決定接下來要輸出習。
link |
它會輸出一個項量,這個項量裡面習這個中文字的分數最高的,所以它就輸出習。
link |
那這邊有一個關鍵的地方,我們特別用紅色的虛線把它標出來。
link |
也就是說decoder看到的輸入,其實是它在前一個時間點自己的輸出。
link |
decoder會把自己的輸出當作接下來的輸入,會把自己的輸出當作接下來的輸入。
link |
所以當我們decoder在產生一個句子的時候,它其實有可能看到錯誤的東西。
link |
因為它看到的是自己的輸出嘛,那如果今天decoder有語音辨識的錯誤,
link |
它把機器的氣辨識錯成天氣的氣,那接下來decoder就會看到錯誤的辨識結果。
link |
它還是要想辦法根據錯誤的辨識結果產生它想要產生的,期待是正確的輸出。
link |
那你可能會覺得說,讓decoder看到錯誤的輸入,讓decoder看到自己產生出來的錯誤的輸入,
link |
再被decoder自己吃進去,會不會造成問題呢?會不會造成error propagation的問題呢?
link |
所謂error propagation的問題就是一步錯,步步錯。
link |
就是在這個地方,如果不小心把機器的氣不小心寫成天氣的氣,
link |
會不會接下來就整個句子都壞掉了,都沒有辦法再產生正確的詞彙了。
link |
有可能,那這個等一下我們最後會稍微講一下這個問題要怎麼處理。
link |
我們現在先無視這個問題,繼續走下去。
link |
我們來看一下這個decoder它內部的結構長什麼樣子。
link |
我們這邊把encoder的部分先暫時省略掉。
link |
在transformer裡面,decoder的結構長的是這個樣子的,
link |
看起來有點複雜,比encoder還稍微複雜一點。
link |
我們現在先把encoder跟decoder放在一起,稍微比較一下它們之間的差異。
link |
你會發現說,如果我們把decoder中間這一塊蓋起來,
link |
其實encoder跟decoder並沒有那麼大的差別。
link |
你看encoder這邊,multi-head attention,add and no,feedforward,add and no,重複n次。
link |
decoder其實也是一樣,當我們把中間這一塊遮起來以後,
link |
我們等一下再講遮起來這一塊裡面做了什麼事。
link |
當我們把中間這一塊遮起來以後,decoder也是有一個multi-head attention,
link |
add and no,feedforward,add and no。
link |
所以encoder跟decoder其實並沒有非常大的差別,
link |
除了中間這一塊不一樣的地方,被遮起來的地方以外。
link |
其實encoder跟decoder是一樣的,
link |
只是最後我們可能會再做一個softmax,使得它的輸出變成一個機率。
link |
在decoder這邊,multi-head attention這個block上面還加了一個mask。
link |
這個mask的意思是這樣子的,這是我們原來的self-attention。
link |
input一排vector,output另外一排vector。
link |
這一排vector每一個輸出都要看過完整的input以後才做決定。
link |
所以輸出B1的時候,其實是根據A1到A4所有的資訊去輸出B1。
link |
當我們把self-attention轉成mask-attention的時候,
link |
它的不同點是,現在我們不能再看右邊的部分。
link |
也就是產生B1的時候,我們只能考慮A1的資訊,
link |
產生B2的時候,你只能考慮A1、A2的資訊,不能再考慮A3、A4的資訊。
link |
產生B3的時候,你就不能考慮A4的資訊。
link |
產生B4的時候,你可以用整個input sequence的資訊。
link |
這個就是mask的self-attention。
link |
我們只拿第二個位置的query去跟第一個位置的key和第二個位置的key去計算attention。
link |
第三個位置跟第四個位置就不管它,不去計算attention。
link |
我們這樣子不去管A2右邊的地方,只考慮A1跟A2,只考慮Q1、Q2,只考慮K1、K2。
link |
Q2只跟K1跟K2去計算attention,最後只計算B1跟B2的weighted sum。
link |
當我們輸出B2的時候,B2就只考慮了A1跟A2,就沒有考慮到A3跟A4。
link |
那為什麼會這樣呢?為什麼需要加masking呢?
link |
你想想看我們一開始decoder的運作方式,它是一個一個輸出,它的輸出是一個一個產生的。
link |
所以是先有A1,再有A2,再有A3,再有A4。
link |
這跟原來的self-attention不一樣。原來的self-attention,A1跟A4是一次整個輸進去你的model裡面的。
link |
在我們講encoder的時候,encoder是一次把A1跟A4整個都讀進去。
link |
但是對decoder而言,先有A1,才有A2,才有A3,才有A4。
link |
所以實際上,當你有A2,你要計算B2的時候,你是沒有A3跟A4的。
link |
所以你根本就沒有辦法把A3、A4考慮進來。
link |
所以這就是為什麼在那個decoder的那個圖上面,transformer原始的paper特別跟你強調說,
link |
那不是一個一般的attention,這是一個masked self-attention。
link |
其實只是想要告訴你說,decoder,它的token,它輸出的東西是一個一個產生的。
link |
所以它只能考慮它左邊的東西,它沒有辦法考慮它右邊的東西。
link |
但是講到這裡,我們講了decoder的運作方式,但是這邊還有一個非常關鍵的問題。
link |
這個關鍵的問題是,decoder必須自己決定輸出的sequence的長度。
link |
可是到底輸出的sequence的長度應該是多少呢?我們不知道。
link |
你沒有辦法輕易地從輸入的sequence的長度就知道輸出的sequence的長度是多少。
link |
並不是說輸入是四個向量,輸出一定就是四個向量。
link |
這邊在這個例子裡面輸入跟輸出的長度是一樣的,但是你知道實際上在你真正的應用裡面並不是這樣。
link |
我們其實是期待機器可以自己學到今天給它一個input sequence的時候,output sequence應該要多長。
link |
但在我們目前的整個decoder的運作機制裡面,機器不知道它什麼時候應該停下來。
link |
它產生完C以後,它還可以繼續重複一模一樣的process,
link |
就把C當作輸入,然後也許decoder就會接一個慣,然後接下來就一直持續下去,永遠都不會停下來。
link |
這讓我想到推文接龍,我不知道大家知不知道是什麼。
link |
這是一個古老的民俗傳統,流傳在PTT上面。
link |
就是有一個人先推一個中文字,推一個超,然後接下來就會有另外一個鄉民去推另外一個字,然後可以接上去的。
link |
所以就可以產生一排的詞彙、一排字,就是超人、政大、中天、外非、仙草,我不知道在說些什麼。
link |
這個process可以持續好幾個月都不停下來,我也不知道為什麼。
link |
那怎麼讓這個process停下來呢?
link |
要怎麼讓它停下來呢?要有人冒險去推一個段,推一個段,它就停下來了。
link |
所以我們要讓decoder做的事情也是一樣,要讓它可以輸出一個段。
link |
所以你要準備一個特別的符號,這個符號就叫做段,這邊用end來表示這個特殊的符號。
link |
所以除了所有中文的方塊字還有begin以外,你還要準備一個特殊的符號叫做段。
link |
那其實在助教的程式裡面,它是把begin跟end,就是開始跟這個段用同一個符號來表示。
link |
反正這個begin只會在輸入的時候出現,段只會在輸出的時候出現。
link |
所以在助教程式裡面,如果你仔細研究一下的話,會發現說end跟begin用的其實是同一個符號。
link |
那你用不同的符號也是完全可以的,也完全沒有問題。
link |
所以我們現在讓decoder它可以輸出段這個符號,輸出end這個符號。
link |
那我們期待說,當今天產生完習以後,再把習當作decoder的輸入以後,decoder就要能夠輸出段。
link |
也就是說,當把習當作輸入以後,就decoder看到encoder輸出的embedding,看到了begin,然後機器學習以後。
link |
看到這些資訊以後,它要知道說,這個語音辨識的結果已經結束了,不需要再產生更多的詞彙了。
link |
它產生出來的向量裡面,這個end,就是段的那個符號,它的機率必須要是最大的,然後你就輸出段這個符號。
link |
那整個運作的過程,整個decoder產生sequence的過程就結束了。
link |
好,那這個就是autoregressive的decoder它運作的方式。
link |
好,那接下來呢,我們用兩頁投影片,非常簡短的講一下non-autoregressive的model。
link |
non-autoregressive的model通常縮寫成NAT,所以有時候autoregressive的model也縮寫成AT。
link |
non-autoregressive的model是怎麼運作的呢?
link |
這個non-autoregressive的model是先輸入begin,然後出現W1,然後再把W1當作輸入,再輸出W2,直到輸出end的為止。
link |
那NAT是這樣,它不是一次產生,就假設我們現在要產生的是中文的句子,它不是一次產生一個字,它是一次把整個句子都產生出來。
link |
NAT的decoder啊,它可能吃的是一整排的begin的token,你就把一堆一排begin的token都丟給它,讓它一次產生一排token就結束了。
link |
舉例來說,如果你丟給它四個begin的token,它就產生四個中文的字,變成一個句子,就結束了。
link |
所以它只要一個步驟就可以完成句子的生成。
link |
這邊你可能就會問一個問題,剛才不是說不知道輸出的長度應該是多少嗎?
link |
那我們這邊怎麼知道begin要放多少個當作NAT decoder的輸入呢?
link |
沒錯,這件事沒有辦法很自然的知道,沒有辦法很直接的知道。
link |
所以有幾個做法,一個做法是你另外認一個classifier,這個classifier它吃encoder的input,然後輸出是什麼?
link |
輸出是一個數字,這個數字代表decoder應該要輸出的長度。
link |
所以你就認一個classifier,這個classifier可能吃encoder的input,可能吃把encoder output的那些向量讀進去,它output一個數字,比如說output4,把它output4以後,NAT的decoder就會吃到四個begin的token,然後它就產生四個中文的字。
link |
另一種可能的做法就是,你就不管3721,給它一堆begin的token,你就假設說你現在輸出的句子的長度絕對不會超過300個字,你就假設一個句子長度的上限,然後begin你就給它300個begin,然後就會輸出300個字。
link |
然後你再看看說什麼地方輸出了段,什麼地方輸出end,輸出end的右邊的,就當作它沒有輸出,就結束了。這是另外一種處理NAT的decoder它應該輸出的長度的方法。
link |
NAT的decoder它有什麼樣的好處呢?它第一個好處是平行化。這個AT的decoder,它在輸出它的句子的時候,是一個一個一個字產生的。
link |
所以假設你要輸出長度100個字的句子,那你就需要做100次的decode。但是NAT的decoder不是這樣,不管句子的長度如何,都是一個步驟就產生出完整的句子。
link |
所以在速度上,NAT的decoder它會跑得比AT的decoder要快。你可以想像說,這個NAT的decoder的想法顯然是在由transformer以後,有這種SELM attention的decoder以後才有的。
link |
因為以前如果你是用LSTM、RNN的話,你就算給它一排begin,它也沒有辦法同時產生全部的輸出,它的輸出還是一個一個產生的。
link |
所以在沒有SELM attention之前,只有RNN、LSTM的時候,根本就不會有人想要做什麼NAT的decoder。不過自從有了SELM attention以後,NAT的decoder現在就算是一個熱門研究的主題了。
link |
NAT的decoder還有另外一個好處,就是你比較能夠控制它輸出的長度。
link |
怎麼說呢?舉語音合成為例好了。其實在語音合成裡面,NAT的decoder算是非常常用的,它並不是一個什麼稀罕罕見的招數。
link |
比如說語音合成,今天你都可以用sequence-to-sequence的模型來做,最知名的是一個叫做Tacotron的模型,它是AT的decoder。
link |
另外一個模型叫Fast Speech,它是NAT的decoder。
link |
NAT的decoder有一個好處,就是你可以控制你輸出的長度。我們剛才說,怎麼決定NAT的decoder輸出多長呢?你可能有一個classifier決定NAT的decoder應該輸出的長度。
link |
如果在做語音合成的時候,假設你現在突然想要讓你的系統講快一點、加速,那你就把classifier的output除以2,它講話速度就變兩倍快。如果你想要講話放慢速度,那你就把classifier輸出的長度,它predict出來的長度,乘兩倍。
link |
你的decoder說話的速度就變兩倍慢。如果有這種NAT的decoder,你有explicit的去model output的長度應該是多少的話,你就比較有機會去控制你的decoder輸出的長度應該是多少,你就可以做種種的變化。
link |
為什麼NAT的decoder最近是一個熱門的研究主題呢?它之所以是一個熱門的研究主題,就是它雖然表面上看起來有種種的厲害之處,尤其是平行化是它最大的優勢,但是NAT的decoder的performance往往都不如AT的decoder。
link |
所以發現有很多很多的研究試圖讓NAT的decoder的performance越來越好,試圖去逼近AT的decoder。不過今天你要讓NAT的decoder跟AT的decoder的performance一樣好,你必須要用非常多的trick才能辦到。
link |
NAT的decoder隨便train一下,NAT的decoder你要花很多力氣才有可能跟AT的performance差不多。
link |
為什麼NAT的decoder的performance不好呢?有一個問題我們今天就不細講了,叫做multi-modality的問題。
link |
如果你想要深入了解NAT,就把之前助教上課補充的內容連結放在這邊給大家參考。NAT也是一個大坑,助教也是講了一個半小時才稍微給大家一個大概大致的描述。所以這也是一個大坑,不是我們今天可以講的,就只是告訴大家說世界上有NAT這個東西而已。
link |
接下來我們就要講encoder跟decoder它們中間是怎麼傳遞資訊的了,也就是我們要講剛才我們刻意把它遮起來的那一塊。
link |
如果你仔細觀察這一塊的話,這一塊叫做cross-attention,它是連接encoder跟decoder之間的橋梁。這一塊裡面你會發現有兩個輸入來自於encoder,encoder提供兩個箭頭,decoder提供了一個箭頭。
link |
所以從左邊這兩個箭頭,decoder可以讀到encoder的輸出。
link |
那這個模組實際上是怎麼運作的呢?那我們就實際把它運作的過程跟大家展示一下。
link |
這個是你的encoder,輸入一排向量,輸出一排向量,我們叫它A1、A2、A3。
link |
接下來輪到你的decoder,你的decoder會先吃begin,當作begin這個special的token。那begin這個special的token讀進來以後,你可能會經過self-attention。
link |
這個self-attention是有做mask的,然後得到一個向量。
link |
就像self-attention就算是有做mask,還是一樣輸入多少長度的向量,輸出就是多少向量。
link |
所以輸入一個向量,輸出一個向量。然後接下來把這個向量乘上一個矩陣,做一個transform,得到一個query,叫做Q。
link |
然後這邊的A1、A2、A3也都產生key,key1、key2、key3。
link |
那把這個Q跟K1、K2、K3去計算attention的分數,得到α1、α2、α3。
link |
當然你可能一樣會做softmax,把它稍微做一下normalization,所以我這邊加一個π,代表它可能是做過normalization。
link |
接下來再把α1、α2、α3乘上V1、V2、V3,再把它weighted上加起來,你得到V。
link |
那這個V就是接下來會丟到fully connected的network做接下來的處理。
link |
那這個步驟就是Q來自於decoder,K跟V來自於encoder,這個步驟就叫做cross-attention。
link |
所以decoder就是憑藉著產生一個Q,去encoder這邊抽取資訊出來,當作接下來的decoder裡面的fully connected network的input。
link |
那這個就是cross-attention的運作的過程,當然現在假設產生第一個中文的字,產生一個G,接下來的運作也是一模一樣的。
link |
輸入begin,輸入G,產生一個向量,這個向量一樣乘上一個linear transform,得到Q'、得到一個query。
link |
這個query一樣跟K1、K2、K3去計算attention的分數,一樣跟V1、V2、V3做weighted上做加權,然後加起來得到V',交給接下來的fully connected network做處理。
link |
所以這就是這個cross-attention的運作的過程。
link |
那這邊有一個實際的文獻上的cross-attention,它所做的事情的效果展示,不過我這邊要稍微說明一下,這個圖並不是來自於Transformer。
link |
這篇paper它的title叫做Listen, Attend, Spill,是比較早的使用sequence-to-sequence model成功做語音辨識的一篇文章。
link |
它發表在ICAST 2016,2016年的ICAST,我記得那一次是在上海辦的,我還特別有親耳聽了這篇paper的報告,現場還是人山人海。
link |
大家都覺得,哇,這個非常的神奇,sequence-to-sequence,運作居然可以做語音辨識,而且跟state-of-the-art的結果當時也就只差了一點點而已。
link |
當時這篇paper裡面的結果,它展現的sequence-to-sequence model其實沒有贏過state-of-the-art,就是當時最好的語音辨識系統,但是只差一點點而已。
link |
所以讓大家覺得說,sequence-to-sequence用在語音辨識上似乎是有潛力的。
link |
所以它其實不是transformer,那時候的encoder跟decoder都是用LSTM,不過那個時候就已經有cross-attention這樣的機制了。
link |
所以在有transformer之前,其實就已經有cross-attention這樣的機制,只是沒有self-attention的機制,所以是先有cross-attention,後來才有self-attention。
link |
那個時候,如果你是用sequence-to-sequence的model,不知道為什麼paper的title一定要有三個動詞,才能夠代表你是在做sequence-to-sequence的model。
link |
所以像這邊,就是listen, attend, and spell,告訴他說機器要聽聲音,然後做attention,就是cross-attention,spell就是把他聽到的東西拼出來。
link |
我特別放這個圖是想要讓你比較容易想像這個cross-attention是怎麼運作的。
link |
這一段是聲音訊號,是機器的輸入。聲音訊號輸入給encoder的時候,它是用一串向量來表示,一排向量來表示。
link |
所以這是時間,然後這邊是一排一排一個一個的向量。然後這一排是decoder的輸出,decoder一次只吐一個英文的字母,所以它會吐H,吐O,吐W,就代表號。
link |
如果它已經到一個詞彙的邊界,它會自動吐出空白,空白當作是一個特殊的字母來處理。所以機器decoder有可能輸出空白,代表一個詞彙結束了,換一個新的詞彙。
link |
接下來輸出much,再輸出空白,再輸出W。
link |
這句話其實是一個英文的繞口令,這句話完整的句子是How much wood would a woodchuck charge?實際上內容是什麼其實不太重要,它就是一句繞口令就是了。
link |
很神奇,機器可以一次吐一個字母,而且它可以聽對正確的詞彙。
link |
這邊這個值是什麼呢?這個值就是Attention的分數,所以當你要產生這個H的時候,在產生這個H之前,你的decoder會去對encoder的輸出做Attention。
link |
所以它就Attent在這個地方,然後產生H,然後Attent在這個地方,產生O,Attent在這個地方,產生W。這邊顏色越深,就代表說那個Attention的分數,就是那個alpha的值越大。
link |
所以你會發現說它產生H的時候,它就是聽到這個地方有H的聲音,所以產生H。接下來再往右移一點,產生O,再往右移一點,產生W。接下來Attent在這個地方,產生Space,然後Attent在這個地方,產生N。
link |
你會看到說這個Attention的weight是由左上到右下移動的,跟你想像Attention應該運作的機制很像。因為當我們這邊每次產生一個詞彙的時候,我們想要專注、我們想要考慮的聲音訊號應該就是由左向右移動。
link |
所以確實,如果你看model的Attention的話,它的分數高的地方可能也是從左上一直排到右下。
link |
講到這邊,也許有同學會問說,那這個encoder有很多層啊,decoder也有很多層啊。從剛才的講解裡面,好像聽起來這個decoder不管哪一層,都是拿encoder最後一層的輸出,這樣對嗎?
link |
對,在原始paper裡面的實作是這樣子的。那一定要這樣嗎?不一定要這樣,你永遠可以自己兜一些新的想法。所以我這邊就是引用一篇論文告訴你說,也有人嘗試不同的cross-attention的方式。
link |
encoder這邊有很多層,decoder這邊有很多層,為什麼decoder這邊每一層都一定要看encoder最後一層的輸出呢?能不能夠有各式各樣不同的連接方式,這完全可以當作一個研究的問題來study。
link |
那最後呢,我們就要講訓練這件事了。我們已經講了encoder、decoder、encoder、decoder怎麼互動的,你已經清楚說inbringer sequence是怎麼得到最終的輸出。那接下來就進入訓練的部分。
link |
我們剛才都還沒有講訓練的部分喔,我們剛才講的都還只是假設你模型訓練好以後,它是怎麼運作的,它是怎麼做testing的,它是怎麼做inference的。inference就testing啦,所以當我說inference的時候,我指的就是testing,我指的是同一件事情。
link |
那是怎麼做訓練的呢?接下來就要講怎麼做訓練。那如果是做語音辨識,那你要有訓練資料,需要什麼樣的訓練資料呢?你要收集一大堆的聲音訊號,每一句聲音訊號都要有工讀生來聽打一下,打出說它對應的詞彙是什麼。
link |
工讀生聽這段是機器學習,他就把機器學習四個字打出來,所以就知道說你的transformer應該要學到聽到這段聲音訊號,它的輸出就是機器學習這四個中文字。
link |
那怎麼讓機器學到這件事呢?我們已經知道說輸入這段聲音訊號,第一個應該要輸出的中文字是機。所以今天當我們把begin丟給decoder的時候,它第一個輸出應該要跟機越接近越好。
link |
怎麼叫做跟機越接近越好呢?機這個字會被表示成一個one-hot vector,在這個vector裡面只有機對應的那個維度是1,其他都是0,這是正確的答案。
link |
那我們的decoder它的輸出是一個distribution,是一個機率的分布,我們會希望這個機率的分布跟這個one-hot vector越接近越好。所以你會去計算這個ground truth跟這個distribution它們之間的cross entropy,然後我們希望這個cross entropy的值越小越好,就這樣。
link |
那你可能會發現說,這件事情跟分類很像。沒錯,它就跟分類很像。剛才助教在講解作業的時候,也有提到這件事情。
link |
你可以想成,每一次decoder在產生一個中文字的時候,其實就是做了一次分類的問題。
link |
每一次中文字假設有四千個,那就是做有四千個類別的分類的問題。所以實際上訓練的時候這個樣子,我們已經知道輸出應該是機器學習這四個字。
link |
那你就告訴機器說,你就告訴你的decoder說,現在你第一次的輸出、第二次的輸出、第三次的輸出、第四次的輸出,應該分別就是機器學跟習這四個中文字的one-hot vector。我們希望我們的輸出跟這四個字的one-hot vector越接近越好。
link |
在訓練的時候,每一個輸出都會有一個cross entropy,每一個輸出跟one-hot vector,跟它對應的正確答案都有一個cross entropy。我們要希望所有的cross entropy的總和越小越好。
link |
所以這邊做了四次分類的問題,我們希望這些分類的問題,它總和起來的cross entropy越小越好。但這邊不要忘了,還有斷這個東西,還有end這個東西。
link |
所以其實今天假設這個句子中文的字是四個,但是你學習的時候,你要decoder輸出的不是只有這四個中文字。你還要叫它記得說,這四個中文字輸出完以後,你還要記得輸出斷這個特別的符號。
link |
所以你要告訴你的decoder說,你最終第五個位置輸出的這個向量,應該跟斷的one-hot vector它的cross entropy越小越好。
link |
那這個就是decoder的訓練。你把one-truth給它,正確答案給它,希望decoder的輸出跟正確答案越接近越好。
link |
那這邊有一件值得我們注意的事情,這件事是這樣的。你看看decoder的輸入是什麼?decoder的輸入是正確答案。
link |
我們會給decoder,在訓練的時候我們會給decoder看正確答案。
link |
也就是我們會告訴它說,在已經有begin、有g的情況下,你就要輸出g,有begin、有g、有g的情況下輸出g,有begin、有g、有g、有g的情況下輸出g,有begin、有g、有g、有g、有g的情況下,你就要輸出g。
link |
在decoder訓練的時候,我們會在輸入的時候給它正確的答案。
link |
這件事情叫做teacher forcing,其實我不太確定為什麼叫teacher forcing,好像是老師會強迫你做什麼事情一樣,聽起來好像沒有很好。
link |
但是這個技術就叫做teacher forcing,也就是我們把正確的答案當作decoder的輸入。
link |
這個時候你馬上就會有一個問題了,訓練的時候decoder有偷看到正確答案了,但是測試的時候顯然沒有正確答案可以給decoder看。
link |
剛才也有強調說在真正使用這個模型在influence的時候,decoder看到的是自己的輸入,這中間顯然有一個mismatch。
link |
對,這中間有一個mismatch,等一下我們會有一頁投影片說明有什麼樣可能的解決方式。
link |
接下來就是要講不侷限於transformer訓練與訓練這種sequence-to-sequence model的一些tips。
link |
第一個tips是copy mechanism,對很多任務而言,在我們剛才的討論裡面,我們都要求decoder自己產生輸出。
link |
但是對很多任務而言,也許decoder沒有必要自己創造輸出出來,它需要做的事情也許是從輸入的東西裡面複製一些東西出來。
link |
那我們有沒有辦法讓decoder複製從輸入複製一些東西出來呢?其實是有辦法的。
link |
像這種複製的行為在哪些任務會用得上呢?一個例子是做聊天機器人。
link |
舉例來說,人對機器說,你好,我是庫洛洛。庫洛洛就是團長啦,他是誰其實也沒那麼重要,已經很久沒有見到他了。
link |
我是庫洛洛。機器應該要回什麼呢?機器應該要回答說,庫洛洛,你好,很高興認識你。
link |
對機器來說,它其實沒有必要創造庫洛洛這個詞彙,這對機器來說一定會是一個非常怪異的詞彙。
link |
所以它可能很難,在訓練資料裡面可能一次也沒有出現過,所以它不太可能正確地產生這段句子出來。
link |
但是假設今天機器在學的時候,它學到的並不是它要產生庫洛洛這三個中文字,
link |
它學到的是看到輸入的時候說我是某某某,就直接把某某某,不管這邊是什麼,複製出來說某某某,你好。
link |
這樣子機器的訓練顯然會比較容易,它顯然比較有可能得到正確的結果。
link |
所以複製對於對話來說可能是一個需要的技術、需要的能力。
link |
我這邊舉另外一個例子,小傑不能用唸能力了,你可能會回答說,你所謂的不能用唸能力是什麼意思?
link |
對機器來說,它要做的事情去複述這一段它聽不懂的話,它不需要從頭去創造這一段文字,
link |
它要學的也許是從使用者人的輸入去copy一些詞彙當作它的輸出。
link |
或者是在做摘要的時候,你可能更需要copy這樣子的技能。
link |
所謂的摘要就是你要訓練一個模型,然後這個模型去讀一篇文章,然後產生這篇文章的摘要。
link |
這個任務完全是有辦法做的,你就是蒐集大量的文章,每一篇文章都有人寫的摘要,然後你就訓練一個sequence-to-sequence的模型,就結束了。
link |
你要做這樣的任務,只有一點點的資料是做不起來的。
link |
有同學蒐集幾萬篇文章,然後訓練一個這樣的sequence-to-sequence的模型,發現結果有點差,然後來問我為什麼。
link |
這時候我就告訴你說,你要叫機器說合理的句子,通常百萬篇文章是需要的。
link |
所以如果你有百萬篇文章,那些文章都有人標的摘要,那有時候你會直接把文章的標題當作摘要,那這樣就不需要花太多的人力來標了。
link |
你是可以訓練一個直接可以幫你讀一篇文章,就下一個標題做一個摘要的模型。
link |
但是我們知道,做摘要的時候,有時候很多的詞彙其實就是直接從原來的文章裡面複製出來的。
link |
小時候老師叫我們寫國文課的課文摘要的時候,其實你也沒有自己創造詞彙,你就是從課文裡面找一些句子出來,然後把它改寫一下,其實就變成摘要了。
link |
所以對摘要這個任務而言,其實從文章裡面直接複製一些資訊出來,可能是一個很關鍵的能力。
link |
那Sequence-to-Sequence Model有沒有辦法做到這件事呢?
link |
最早有從輸入複製東西的能力的模型叫做Pointer Network,這個過去上課是有講過的,我把錄影放在這邊給大家參考。
link |
後來還有一個變形叫做Copying Network,你可以看一下這篇Copying Mechanism in Sequence-to-Sequence Learning,看看Sequence-to-Sequence Model是怎麼做到從輸入複製東西到輸出來的。
link |
其實這個Sequence-to-Sequence Model,因為你知道機器就是一個黑盒子,有時候它裡面學到什麼東西,你實在是考不清楚。
link |
有時候它會犯非常低級的錯誤。什麼樣低級的錯誤呢?這邊就舉一個真實的低級錯誤的例子。
link |
今天語音合成,你完全可以訓練一個Sequence-to-Sequence Model。
link |
Sequence-to-Sequence Model大家都很熟嘛,Transformer就是一個例子。
link |
你就拿出來,然後輸入是什麼,你就收集很多的文字跟聲音訊號的對應關係,然後接下來告訴你的Sequence-to-Sequence Model說,看到這段中文的句子,你就輸出這段聲音。
link |
然後就沒有然後,就一圈一發,就結束了,然後機器就可以學會做語音合成了。
link |
那像這樣的方法做出來的結果怎麼樣呢?
link |
其實還不錯,舉例來說我叫機器連縮四次發財,看看它會怎麼講,機器輸出的結果是這樣子。
link |
發財,發財,發財,發財,發財,發財,發財,發財
link |
這很神奇耶,我輸入的發財明明是同樣的詞彙,只是重複四次,機器居然自己有一些意羊頓挫。
link |
你說它為什麼有意羊頓挫?你再仔細聽聽看。
link |
發財,發財,發財,發財,發財,發財,發財
link |
就是你的Sequence to Sequence Model
link |
就這個用Sequence to Sequence
link |
這招就叫做Guided Attention
link |
比如說Monotonic Attention
link |
或Location Aware的Attention
link |
還有一個東西叫做Bin Search
link |
The Curious Case of Neurotech Degeneration
link |
是sentence completion
link |
那如果你今天不是用bin search
link |
通常bin search就會比較有幫助
link |
sentence completion
link |
sequence to sequence model
link |
machine learning會做的想法
link |
你知道在machine learning
link |
對於TTS或sentence Completion來說
link |
Blue Score是你的decoder
link |
Minimize Cross Entropy
link |
真的可以Maximize Blue Score嗎
link |
所以我們Minimize Cross Entropy
link |
Cross Entropy最低的那個model
link |
那我們要Minimize那個Loss
link |
那你就是Maximize Blue Score
link |
這邊之所以採用Cross Entropy
link |
遇到你無法Optimize的Loss Function
link |
把你的Decoder當作是Agent
link |
Reinforcement Learning的問題
link |
這一招叫做Schedule Sampling
link |
它不是那個Schedule Learning Rate
link |
剛才助教有講Schedule Learning Rate
link |
這個是Schedule Sampling
link |
Schedule Sampling其實很早就有了
link |
很早就有Schedule Sampling
link |
就已經有Schedule Sampling了
link |
這個Schedule Sampling這一招
link |
Transformer的平行化的能力
link |
它的Schedule Sampling