零基礎(chǔ)入門深度學(xué)習(xí)(8) - Transformer (1/3)

時(shí)隔八年,再次提筆續(xù)寫這個(gè)系列。毫無(wú)疑問(wèn),智能時(shí)代已經(jīng)到來(lái),AGI(通用人工智能)似乎也不再是遙不可及的夢(mèng)想。大模型,作為目前最接近實(shí)現(xiàn)AGI的技術(shù),甚至已經(jīng)可以寫代碼了!這對(duì)于程序員真是數(shù)十年未有之大變局,因此學(xué)好、用好大模型,就將一步跨過(guò)JavaScript、Java、C++直接走到鄙視鏈的頂端,用自然語(yǔ)言編程,成為超級(jí)程序員。希望這個(gè)系列幫助你快速?gòu)牧慊A(chǔ)達(dá)到真入門級(jí)水平,理解大模型才能用好大模型。零基礎(chǔ)意味著你不需要太多的數(shù)學(xué)知識(shí),只要會(huì)寫程序就行了。雖然文中會(huì)有很多公式你也許看不懂,但同時(shí)也會(huì)有更多的代碼,程序員的你一定能看懂的(我周圍是一群狂熱的Clean Code程序員,所以我寫的代碼也不會(huì)很差)。

往期回顧

在前面的文章中,我們介紹了全連接神經(jīng)網(wǎng)絡(luò)、卷積神經(jīng)網(wǎng)絡(luò)、循環(huán)神經(jīng)網(wǎng)絡(luò)等,可以它們看做是不同結(jié)構(gòu)的神經(jīng)網(wǎng)絡(luò)。本文將繼續(xù)從結(jié)構(gòu)這個(gè)角度出發(fā),介紹一種新的、極其重要的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu):Transformer。從時(shí)間來(lái)看,它也不是那么新,畢竟是2017年出現(xiàn)的,到現(xiàn)在(2025年)也將近十年了。然而,沒(méi)有一個(gè)更新的網(wǎng)絡(luò)結(jié)構(gòu)比它還成功,也說(shuō)明其結(jié)構(gòu)設(shè)計(jì)是極為優(yōu)秀的。Transformer出現(xiàn)后,用了5年左右的時(shí)間,逐漸取代卷積神經(jīng)網(wǎng)絡(luò)成為當(dāng)紅一哥,又用另外5年開辟了一個(gè)全新的時(shí)代:大模型時(shí)代。可以說(shuō),目前所有的大模型,都是以Transformer結(jié)構(gòu)為基礎(chǔ)的各種變體。如果您剛剛開始學(xué)習(xí)AI,可以嘗試快速跳過(guò)Transformer之前的部分,把主要的精力放在Transformer的學(xué)習(xí)上。

由于Transformer內(nèi)容較多,為了保持一個(gè)良好的節(jié)奏,我將整個(gè)內(nèi)容分成三個(gè)部分。第一部分比較簡(jiǎn)單,是一些基礎(chǔ)知識(shí)的介紹;第二部分重點(diǎn)講述transformer的注意力機(jī)制,這也是它的核心部分;第三部分講述模型的整體結(jié)構(gòu),以及訓(xùn)練和推理。

Transformer為什么牛

Transformer是作為RNN的競(jìng)爭(zhēng)對(duì)手被發(fā)明出來(lái)的,它們所要解決的問(wèn)題是一樣的,即對(duì)序列數(shù)據(jù)進(jìn)行建模。關(guān)于序列數(shù)據(jù)建模,大家可以回看零基礎(chǔ)入門深度學(xué)習(xí)(5) - 循環(huán)神經(jīng)網(wǎng)絡(luò),語(yǔ)言模型就是一個(gè)很好的例子。也如同我們?cè)谥拔恼轮姓f(shuō)的,在序列長(zhǎng)度較長(zhǎng)的時(shí)候,RNN會(huì)面臨嚴(yán)重梯度消失和梯度爆炸,導(dǎo)致其對(duì)長(zhǎng)序列建模效果很差。LSTM(回看零基礎(chǔ)入門深度學(xué)習(xí)(6) - 長(zhǎng)短時(shí)記憶網(wǎng)絡(luò)(LSTM))使這個(gè)問(wèn)題得到了一些改善,并在相當(dāng)長(zhǎng)的一段時(shí)間里成為序列建模的主要模型,廣泛用于機(jī)器翻譯、文檔摘要、代碼生成等各種任務(wù)中。Transformer最初是用來(lái)做機(jī)器翻譯的,一經(jīng)發(fā)明便一鳴驚人,迅速取代了LSTM成為序列建模的首選模型,在隨后幾年更是被成功用在其它領(lǐng)域(如聲音、圖像、視頻處理等),最終開辟了一個(gè)叫做多模態(tài)模型的全新賽道。這說(shuō)明Transformer結(jié)構(gòu)具備極佳的通用性

Transformer架構(gòu)的另一個(gè)優(yōu)點(diǎn)是極佳的可擴(kuò)展性,即模型的能力隨著模型參數(shù)量增加而增強(qiáng)的能力。可擴(kuò)展性在深度神經(jīng)網(wǎng)絡(luò)中是普遍存在的,但Transformer格外優(yōu)秀。例如,卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)量通常是在幾百萬(wàn)到幾億之間,再大也不是不行,但在性能上看不到收益。也就是說(shuō),數(shù)十億參數(shù)的卷積神經(jīng)網(wǎng)絡(luò)并不比數(shù)億參數(shù)強(qiáng)多少,模型參數(shù)規(guī)模擴(kuò)展收益很低,達(dá)到了規(guī)模瓶頸。和卷積神經(jīng)網(wǎng)絡(luò)相比,Transformer的可擴(kuò)展性要強(qiáng)得多,當(dāng)模型參數(shù)量擴(kuò)展到數(shù)千億時(shí),仍然能夠得到明顯性能增益。正是由于這個(gè)優(yōu)點(diǎn),模型變得越來(lái)越大,從而又開辟了一個(gè)叫做大模型新賽道。

Transformer結(jié)構(gòu)攜通用型可擴(kuò)展性兩大優(yōu)勢(shì),再加上后來(lái)預(yù)訓(xùn)練技術(shù)加持,產(chǎn)生了基礎(chǔ)模型,即可以同時(shí)滿足成百上千個(gè)任務(wù)需求的、強(qiáng)大的單一模型。從此,開發(fā)AI應(yīng)用時(shí)再也不用為每一個(gè)應(yīng)用場(chǎng)景單獨(dú)訓(xùn)練一個(gè)模型,而是直接使用基礎(chǔ)模型或在其基礎(chǔ)上精調(diào)訓(xùn)練專用模型,從而極大降低了每個(gè)場(chǎng)景AI開發(fā)難度和成本,使AI真正賦能千行百業(yè)并走進(jìn)我們的生活、娛樂(lè)、學(xué)習(xí)和工作。因此,毫不夸張的說(shuō),Transformer改變了整個(gè)深度學(xué)習(xí)的歷史。

序列的表示

既然Transfomer是給序列建模的模型,我們講解Transformer之前,首先要把如何表示序列講清楚。序列可以是一段文本,例如:

我昨天上學(xué)遲到了,老師批評(píng)了____。

為了表示這段文本,我們首先需要一個(gè)詞表,它是可能出現(xiàn)的詞的全集。詞表中放入哪些詞(Token),可以完全由設(shè)計(jì)者決定。例如,如果想表達(dá)所有的中文,那么把所有的中文字放進(jìn)詞表就可以;如果還想表達(dá)多語(yǔ)種,那么就需要把各個(gè)語(yǔ)言中的詞放進(jìn)去;如果還想表達(dá)數(shù)學(xué)公式、制表符、表情符號(hào)、顏文字...那么詞表里面就需要放入更多的詞。當(dāng)前大模型的詞表,通常的大小為數(shù)萬(wàn)到十幾萬(wàn)。有了詞表之后,我們可以通過(guò)一個(gè)詞在詞表中的位置來(lái)表示這個(gè)詞。

如上圖所示,假設(shè)我們有一個(gè)長(zhǎng)度為30000的詞表,其中,“我”在詞表2019這個(gè)位置,“昨天”在詞表19234這個(gè)位置,“遲到”在23103這個(gè)位置,那么,“我昨天遲到”就可以用一個(gè)包含三個(gè)數(shù)字的序列來(lái)表示:

2019, 19234, 23103

大家可能發(fā)現(xiàn)一個(gè)問(wèn)題,就是序列的可組合性,即序列和序列可以組成新的序列。由于可組合性的存在,詞表的方案就不是唯一的。例如,此表中可能沒(méi)有“昨天”這個(gè)詞,但是有“昨”和“天”兩個(gè)字,那么,就可以用“昨”和“天”那個(gè)字所對(duì)應(yīng)的數(shù)字,來(lái)組合表示“昨天”,當(dāng)然同“昨天”相比,編碼“我昨天遲到”就需要4個(gè)Token而不是3個(gè)。顯然,不同的方案編碼效率是不同的,好的編碼方案可以用更少Token數(shù)量表達(dá)更多的語(yǔ)義。目前獲得一個(gè)“好”詞表的方法,基本上是還海量語(yǔ)料中統(tǒng)計(jì)不同每個(gè)詞的詞頻,優(yōu)先把更高詞頻的詞放到詞表中。這里面的“詞”也比我們自然語(yǔ)言中的“詞”含義更為廣泛,它可以是一個(gè)字、一個(gè)詞、一個(gè)短語(yǔ)、甚至只是一個(gè)詞綴或單個(gè)字母。例如,英語(yǔ)中ing這個(gè)后綴經(jīng)常出現(xiàn),很多時(shí)候都會(huì)把ing放到詞表中。從語(yǔ)料生成詞表的算法很多,例如BPE(Byte Pair Encoder,字節(jié)對(duì)編碼),大家感興趣可以從專門的資料中學(xué)習(xí),本文不再贅述。

只用一個(gè)數(shù)字表示詞,并沒(méi)有太多的語(yǔ)義信息,例如,模型很難僅僅從2019這個(gè)數(shù)字中挖掘出“我”這個(gè)詞所代表的語(yǔ)義。為此,詞嵌入這個(gè)方法被發(fā)明出來(lái)。所謂嵌入,就是構(gòu)造一個(gè)高維語(yǔ)義空間,然后將每個(gè)詞嵌入到語(yǔ)義空間中(即每個(gè)詞都是語(yǔ)義空間中的一個(gè)點(diǎn))。常用的訓(xùn)練詞嵌入算法有Word2VecGlove、BERT(后續(xù)文章會(huì)講)等,感興趣可以從專門資料中學(xué)習(xí),本文不再贅述。

通過(guò)詞嵌入,為詞表中的每個(gè)詞分配一個(gè)向量(即詞向量),詞向量的維度就是語(yǔ)義空間的維度,可能是512(Transformer),甚至是12288(GPT3),語(yǔ)義空間的維度越高,語(yǔ)義表達(dá)能力越強(qiáng)。語(yǔ)義空間通常被定義為連續(xù)空間,因此詞向量的每個(gè)值都是浮點(diǎn)數(shù)。例如,語(yǔ)義空間維度是512時(shí),每個(gè)詞向量就包含了512個(gè)浮點(diǎn)數(shù),而不是之前的單一一個(gè)數(shù)字。同時(shí),詞向量之間的距離也和詞的語(yǔ)義距離相關(guān),語(yǔ)義相似的詞,詞向量之間的距離??;反之詞向量的距離就大。通過(guò)使用帶語(yǔ)義的詞向量,而非單一數(shù)字來(lái)表征每個(gè)Token,模型就可以獲取到豐富的語(yǔ)義的信息。下圖是語(yǔ)義空間的一個(gè)例子:

假設(shè)語(yǔ)義空間維度為D,詞表大小為V,則全部詞向量可以保存在一個(gè)M\in\mathbb{R}^{V\times D}的矩陣?yán)?,矩陣每一行保存一個(gè)詞向量,一個(gè)詞在詞表中是第幾個(gè),那么它對(duì)應(yīng)的詞向量就保存在矩陣的第幾行。通過(guò)查表操作,就可以很方便的將表示一個(gè)詞的數(shù)字轉(zhuǎn)換為詞向量。假設(shè)有如下的詞嵌入矩陣:

那么,“我昨天遲到”會(huì)被表示為:

[0.312, 0.395, -1.343, 2.102], [1.232, 2.567, -0.123, 0.838], [2.134, -3.123, 0.123, -0.271]

這三個(gè)詞向量可以被放到一個(gè)矩陣中:

X=\begin{bmatrix} 0.312 & 0.395 & -1.343 & 2.102\\ 1.232 & 2.567 & -0.123 & 0.838\\ 2.134 & -3.123 & 0.123 & -0.271\\ \end{bmatrix}

大功告成!讀者至此可以了解,每一個(gè)文字序列,最終都可以被表達(dá)為一個(gè)詞向量組成的矩陣,我們每次向Transformer輸入一個(gè)文字序列時(shí),實(shí)際上輸入的就是這個(gè)矩陣。

位置編碼

把序列表示為詞向量矩陣就可以為模型提供足夠的信息了么?答案是否定的。我們需要思考一個(gè)問(wèn)題:如何告訴模型序列內(nèi)各個(gè)元素的順序?我們知道,語(yǔ)言中每個(gè)詞的順序是極其重要的,順序變了,那意思肯定就全亂套了。最容易想到的辦法,就是我要給序列中的每個(gè)字一個(gè)編號(hào),這樣模型不就知道順序了么?這個(gè)想法類似這樣,當(dāng)我想向模型輸入“我昨天遲到”時(shí),我會(huì)輸入:

1我 2昨天 3遲到

我可真是個(gè)大聰明,通過(guò)給每個(gè)字打上它的位置編號(hào),就能夠?qū)⑿蛄械捻樞蜉斎虢o模型了。當(dāng)然,模型理不理解、如何理解是另一回事,至少該傳遞的信息我都傳遞了。

那么,接下來(lái)就是要考慮如何編碼這個(gè)位置編號(hào)了。前面我們講過(guò),詞是通過(guò)詞嵌入的方式,將其編碼為詞向量來(lái)表達(dá)的。那么,位置該如何編碼呢?實(shí)際上位置編碼方案非常多,后面的文章會(huì)介紹。本文只介紹一種非常簡(jiǎn)單的位置編碼方式(也是Transformer最初使用的)。

采用不同頻率的正弦和余弦函數(shù):
PE_{(pos,2i)} = \sin(\frac{pos}{10000^{2i/d}})\\ PE_{(pos,2i+1)} = \cos(\frac{pos}{10000^{2i/d}})
其中pos表示位置,i表示詞向量維度,即每個(gè)位置編碼維度對(duì)應(yīng)一個(gè)正弦波,波長(zhǎng)從2π10000·2π呈幾何級(jí)數(shù)遞增。Transformer選擇這一函數(shù)是因?yàn)榧僭O(shè)它能方便模型學(xué)習(xí)基于相對(duì)位置的注意力機(jī)制,因?yàn)閷?duì)于任何固定偏移量k,PE_{pos+k}可以表示為PE_{pos}的線性函數(shù)。

假設(shè)詞向量維度D=4,則前三個(gè)Token的位置編碼向量為(代入上述公式計(jì)算即可):

[0, 0, 1, 1], [0.84, 0.0001, 0.54, 1], [0.91, 0.0002, 0.42, 1]

和詞向量一樣,我們也可以把它們放到一個(gè)矩陣中:

P=\begin{bmatrix} 0 & 0 & 1 & 1\\ 0.84 & 0.0001 & 0.54 & 1\\ 0.91 & 0.0002 & 0.42 & 1\\ \end{bmatrix}

那么,如何把位置編碼和詞向量合并到一起輸入給模型呢?Transfomer采用的方式就是直接將兩個(gè)矩陣相加:

X' = X + P

并將得到的X'作為模型的輸入,這樣,模型就同時(shí)得到了文本序列的詞和詞序信息。

小節(jié)

本文介紹了一些非?;A(chǔ)的知識(shí),包括如何表征序列,什么是Token,以及如何通過(guò)位置編碼表達(dá)序列中Token的順序。這些知識(shí)是學(xué)習(xí)Transformer的基礎(chǔ),希望讀者能夠理解。下篇文章,我們將介紹Transformer的核心:注意力機(jī)制。

參考資料

  1. Attenion Is All You Need

相關(guān)文章

零基礎(chǔ)入門深度學(xué)習(xí)(8) - Transformer (1/3)
零基礎(chǔ)入門深度學(xué)習(xí)(9) - Transformer (2/3)
零基礎(chǔ)入門深度學(xué)習(xí)(10) - Transformer (3/3)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容