矩陣模擬!Transformer大模型3D可視化,GPT-3、Nano-GPT每一層清晰可見
模擬人類神經(jīng)元,不斷進(jìn)化的Transformer模型,一直以來都深不可測。
許多科學(xué)家都試著打開這個(gè)黑盒,看看究竟是如何工作的。
而現(xiàn)在,大模型的矩陣世界,真的被打開了!
一位軟件工程師Brendan Bycroft制作了一個(gè)「大模型工作原理3D可視化」網(wǎng)站霸榜HN,效果非常震撼,讓你秒懂LLM工作原理。
圖片
1750億參數(shù)的GPT-3,模型層足足有8列,密密麻麻沒遍布了整個(gè)屏幕。
圖片
GPT-2模型不同參數(shù)版本的架構(gòu)可視化,差異巨大。如下是有150億參數(shù)GPT-2(XL),以及有1.24億參數(shù)GPT-2(Small)。
圖片
圖片
這個(gè)3D模型可視化還展示了,大模型生成內(nèi)容的每一步。
這里,Bycroft主要分解了OpenAI科學(xué)家Andrej Karpathy打造的輕量級的GPT模型——NanoGPT,參數(shù)量為85000。
圖片
地址:https://bbycroft.net/llm
看過這個(gè)可視化圖,你就可以了解ChatGPT的大腦。
從GPT-2(Small)到GPT-3的參數(shù)規(guī)模的跨越,讓人嘆為觀止。
圖片
Bycroft稱,這個(gè)指南側(cè)重于模型的推理,而非訓(xùn)練,只是機(jī)器學(xué)習(xí)中的一小部分。在具體例子中,模型的權(quán)重已經(jīng)預(yù)訓(xùn)練完成,使用推理過程來生成輸出。
當(dāng)然了,這個(gè)可視化網(wǎng)站也是收到了Karpathy在PyTorch中創(chuàng)建的minGPT,以及YouTube視頻系列「Neural Networks: Zero to Hero」的啟發(fā)。
接下來,一起深入來了解,Transformer模型每一層。
介紹
為了方便進(jìn)行演示,Brendan Bycroft給NanoGPT布置了一個(gè)非常簡單的任務(wù):
獲取一個(gè)由六個(gè)字母組成的序列:C B A B B C,并按字母順序排序,即「ABBBCC」。
圖片
我們將每一個(gè)字母稱為token,模型的不同token集合構(gòu)成了它的詞匯表:
圖片
這個(gè)表中,每個(gè)token都被分配了一個(gè)數(shù)字,它是token index。現(xiàn)在我們可以將這一系列數(shù)字輸入到模型中:「2 1 0 1 1 2」
圖片
在3D視圖中,每個(gè)綠色單元格表示一個(gè)正在處理的數(shù)字,每個(gè)藍(lán)色單元格表示權(quán)重。
圖片
序列中的每個(gè)數(shù)字首先被轉(zhuǎn)換為一個(gè)48元素向量,這就是所謂的「嵌入」(embedding)。
圖片
然后,「嵌入」被輸入模型,傳遞通過一系列Transformer層,最后到達(dá)底層。
圖片
那么輸出是什么呢?
對序列中下一個(gè)token的預(yù)測。因此,在序列中第6個(gè)token處,得到了下一個(gè)token將是「A」、「B」或「C」的概率。
在這種情況下,模型非常確定會(huì)是「A」。
現(xiàn)在,我們可以將這一預(yù)測反饋到模型的頂層,并重復(fù)整個(gè)過程。
嵌入
我們之前看到過,如何使用一個(gè)簡單的查找表(lookup table)將token映射為一串整數(shù)。
這些整數(shù),即標(biāo)記token index,是我們在模型中第一次,也是唯一一次看到的整數(shù)。從這里開始,我們將使用浮點(diǎn)數(shù)(十進(jìn)制數(shù))進(jìn)行運(yùn)算。
以第4個(gè)token(index 3)為例,看看是如何被用來生成輸入嵌入的第4列向量的。
圖片
我們使用token index(在本例中為B = 1)來選擇左側(cè)token嵌入矩陣的第二列。請注意,我們在這里使用的是從0開始的index,因此第一列位于index 0處。
這將產(chǎn)生一個(gè)大小為C=48的列向量,我們將其描述為「token嵌入」(token embedding)。
圖片
由于我們主要查看的是位于第4個(gè)位置的 (t = 3) token B,因此我們將采用「位置嵌入矩陣」的第4列。
這也會(huì)產(chǎn)生一個(gè)大小為C=48的列向量,我們將其描述為位置嵌入(position embedding)。
圖片
請注意,這兩個(gè)位置和token嵌入都是在訓(xùn)練期間學(xué)習(xí)的(由藍(lán)色表示)。
現(xiàn)在我們有了這兩個(gè)列向量,我們只需將它們相加即可生成另一個(gè)大小為C=48的列向量。
圖片
現(xiàn)在,我們對輸入序列中的所有token運(yùn)行相同的過程,創(chuàng)建一組包含token值及其位置的向量。
圖片
(隨意停在輸入嵌入矩陣上的單個(gè)單元格上,可以查看計(jì)算及其來源。)
我們看到,對輸入序列中的所有token運(yùn)行此過程,會(huì)產(chǎn)生一個(gè)大小為TxC的矩陣。
T代表時(shí)間,也就是說,你可以將序列中稍后的token看作是時(shí)間上稍后的token。C代表通道(channel),但也稱為「特征」或「維度」或「嵌入大小」。
這個(gè)矩陣,我們稱之為「輸入嵌入」(input embedding),并通過模型向下傳遞。
在本指南中,我們將看到由T列(每列長度為 C)組成的矩陣集合。
圖片
Layer Norm
上一節(jié)的「輸入嵌入」矩陣是第一個(gè)Transformer模塊的輸入。
Transformer模塊的第一步是對該矩陣進(jìn)行「層歸一化」(Layer Norm)處理。這是對矩陣每列的值分別進(jìn)行歸一化的操作。
圖片
歸一化是深度神經(jīng)網(wǎng)絡(luò)訓(xùn)練中的一個(gè)重要步驟,它有助于提高模型在訓(xùn)練過程中的穩(wěn)定性。
我們可以分別看待每一列,所以現(xiàn)在先關(guān)注第4列(t=3)。
圖片
我們的目標(biāo)是使該列的平均值等于0,標(biāo)準(zhǔn)偏差等于1。為此,我們要找出該列的這兩個(gè)量(平均值 (μ) 和標(biāo)準(zhǔn)偏差 (σ)),然后減去平均值,再除以標(biāo)準(zhǔn)偏差。
圖片
這里我們使用E[x]表示平均值,Var[x]表示方差(長度為C的列)。方差就是標(biāo)準(zhǔn)差的平方。ε項(xiàng)
是為了防止除以零。
我們在聚合層中計(jì)算并存儲這些值,因?yàn)槲覀円獙⑺鼈儜?yīng)用于列中的所有值。
最后,在得到歸一化值后,我們將列中的每個(gè)元素乘以學(xué)習(xí)權(quán)重 (γ),然后加上偏置 (β),最終得到歸一化值。
圖片
我們在「輸入嵌入」矩陣的每一列上執(zhí)行這一歸一化操作,得到的結(jié)果就是歸一化后的「輸入嵌入」,并將其傳遞給自注意力層。
圖片
自注意力
自注意力層或許是Transformer和GPT的核心。在這一階段,「輸入嵌入」矩陣中的各列相互「對話」。到目前為止,在所有其他階段,各列都是獨(dú)立存在的。
自注意力層由幾個(gè)頭組成,我們現(xiàn)在只關(guān)注其中一個(gè)。
圖片
第一步是從歸一化輸入嵌入矩陣的C列中為每一列生成三個(gè)向量。這些向量分別是Q、K和V向量:
Q:查詢向量
K:鍵向量
V:值向量
要生成這些向量中的一個(gè),我們要執(zhí)行矩陣-向量乘法,并加上偏置。
每個(gè)輸出單元都是輸入向量的線性組合。例如,對于Q向量,這是用Q權(quán)重矩陣的一行和輸入矩陣的一列之間的點(diǎn)積來完成的。
圖片
我們會(huì)經(jīng)??吹降狞c(diǎn)乘運(yùn)算非常簡單:我們將第一個(gè)向量中的每個(gè)元素與第二個(gè)向量中的相應(yīng)元素配對,將這對元素相乘,然后將結(jié)果相加。
圖片
這是一種確保每個(gè)輸出元素都能受到輸入向量中所有元素影響的通用而簡單的方法(這種影響由權(quán)重決定)。因此,它經(jīng)常出現(xiàn)在神經(jīng)網(wǎng)絡(luò)中。
我們對Q、K、V向量中的每個(gè)輸出單元重復(fù)這一操作:
圖片
我們該如何處理Q、K和V向量呢?命名給了我們一個(gè)提示:「key」和「value」讓人聯(lián)想到軟件中的字典,
鍵(key)映射到值(value)。然后「query」就是我們用于查找值的東西。
圖片
在自注意力的情況下,我們返回的不再是單個(gè)詞條,而是詞條的加權(quán)組合。
為了找到這個(gè)加權(quán),我們在Q向量和K向量之間進(jìn)行點(diǎn)乘。我們將加權(quán)歸一化,最后用它與相應(yīng)的V向量相乘,再將它們相加。
圖片
舉個(gè)更具體的例子,讓我們看看第6列(t=5),我們將從這一列開始查詢:
圖片
我們查找的 {K, V} 項(xiàng)是過去的6列,Q值是當(dāng)前時(shí)間。
我們首先計(jì)算當(dāng)前列(t=5)的Q向量與之前各列的K向量之間的點(diǎn)積。然后將其存儲在注意力矩陣的相應(yīng)行(t=5)中。
圖片
這些點(diǎn)積是衡量兩個(gè)向量相似度的一種方法。如果它們非常相似,點(diǎn)積就會(huì)很大。如果兩個(gè)向量非常不同,點(diǎn)積就會(huì)很小或?yàn)樨?fù)。
只將query向量與過去的key向量進(jìn)行運(yùn)算,使得它成為因果自注意力。也就是說,token無法「預(yù)見未來」。
另一個(gè)要素是,在求出點(diǎn)積后,我們要除以sqrt(A),其中A是Q/K/V向量的長度。進(jìn)行這種縮放是為了防止大值在下一步的歸一化(softmax)中占主導(dǎo)地位。
我們將跳過softmax操作(稍后解釋),只需說明每一行的歸一化總和為1即可。
圖片
最后,我們就可以得出這一列(t=5)的輸出向量。我們查看歸一化自注意力矩陣的(t=5)行,并將每個(gè)元素與其他列的相應(yīng)V向量相乘。
圖片
然后,我們可以將這些向量相加,得出輸出向量。因此,輸出向量將以高分列的V向量為主。
現(xiàn)在我們知道了這個(gè)過程,讓我們對所有列進(jìn)行運(yùn)行。
這就是自注意力層中的一個(gè)頭的處理過程。
所以自注意力的主要目標(biāo)是,每個(gè)列向量希望從其他列向量中找到相關(guān)信息,提取它們的值,方法是將其查詢向量與其他列向量的鍵值進(jìn)行比較。但有一個(gè)附加限制,即它只能查找過去的信息。
投影
在自我注意力過程之后,我們會(huì)從每個(gè)頭得到一個(gè)輸出。這些輸出是受Q和K向量影響而適當(dāng)混合的V向量。
要合并每個(gè)頭的輸出向量,我們只需將它們堆疊在一起即可。因此,在時(shí)間t=4時(shí),我們將從3個(gè)長度為A=16的向量疊加到1個(gè)長度為C=48的向量。
圖片
值得注意的是,在GPT中,頭(A=16)內(nèi)向量的長度等于 C/num_heads。這確保了當(dāng)我們將它們重新堆疊在一起時(shí),能得到原來的長度C。
在此基礎(chǔ)上,我們進(jìn)行投影,得到該層的輸出。這是一個(gè)簡單的矩陣-向量乘法,以每列為單位,并加上偏置。
圖片
現(xiàn)在,我們得到了自注意力層的輸出結(jié)果。
我們不會(huì)直接將這一輸出傳遞到下一階段,而是將其按元素順序添加到輸入嵌入中。綠色垂直箭頭表示的這一過程被稱為殘差連接(residual connection)或殘差路徑(residual pathway)。
圖片
與「層歸一化」一樣,殘差路徑對于實(shí)現(xiàn)深度神經(jīng)網(wǎng)絡(luò)的有效學(xué)習(xí)非常重要。
有了自注意力的結(jié)果,我們就可以將其傳遞到Transformer的下一個(gè)部分:前饋神經(jīng)網(wǎng)絡(luò)。
MLP
在自注意力層之后,Transformer模塊的下半部分是MLP(多層感知器)。雖然有點(diǎn)拗口,但在這里它是一個(gè)有兩層的簡單神經(jīng)網(wǎng)絡(luò)。
與自注意力一樣,在向量進(jìn)入MLP之前,我們要進(jìn)行層歸一化處理。
在MLP中,我們將每個(gè)長度為C=48的列向量(獨(dú)立地)進(jìn)行以下處理:
1. 添加偏置的線性變換,轉(zhuǎn)換為長度為4*C的向量。
2. 一個(gè)GELU激活函數(shù)(按元素計(jì)算)
3. 進(jìn)行線性變換并添加偏置,返回長度為C的向量
讓我們追蹤其中一個(gè)向量:
圖片
我們首先進(jìn)行帶偏置的矩陣-向量乘法運(yùn)算,將向量擴(kuò)展為長度為4*C 的矩陣。(請注意,輸出矩陣在這里進(jìn)行了轉(zhuǎn)置,這純粹是為了更加形象化)
圖片
接下來,我們對向量的每個(gè)元素應(yīng)用GELU激活函數(shù)。
這是任何神經(jīng)網(wǎng)絡(luò)的關(guān)鍵部分,我們要在模型中引入一些非線性。使用的特定函數(shù)GELU看起來很像ReLU函數(shù)(計(jì)算公式為max(0,x)),但它有一條平滑的曲線,而不是一個(gè)尖角。
圖片
圖片
然后,我們通過另一個(gè)帶偏置的矩陣-向量乘法,將向量投影回長度C。
圖片
與自注意力+投影部分一樣,我們將MLP的結(jié)果按元素順序添加到輸入中。
圖片
現(xiàn)在,我們可以對輸入內(nèi)容中的所有列重復(fù)這一過程。
圖片
至此,MLP 完成?,F(xiàn)在我們有了Transformer模塊的輸出,可以將其傳遞給下一個(gè)模塊了。
Transformer
這就是一個(gè)完整的Transformer模塊!
它們構(gòu)成了任何GPT模型的主體,并且會(huì)重復(fù)多次,一個(gè)塊的輸出會(huì)輸入到下一個(gè)塊,繼續(xù)殘差路徑。
與深度學(xué)習(xí)中常見的情況一樣,很難說清楚這些層中的每一層在做什么,但我們有一些大致的想法:前面的層往往側(cè)重于學(xué)習(xí)較低層次的特征和模式,而后面的層則學(xué)習(xí)識別和理解較高層次的抽象概念和關(guān)系。
在自然語言處理中,底層可能學(xué)習(xí)語法、句法和簡單的詞匯關(guān)聯(lián),而高層可能捕捉更復(fù)雜的語義關(guān)系、話語結(jié)構(gòu)和上下文相關(guān)的含義。
圖片
Softmax
softmax運(yùn)算不僅是自注意力機(jī)制的一部分,如前文所述,它還會(huì)出現(xiàn)在模型的最后階段。
概括來說,softmax的目的是將向量中的值歸一化,使它們加起來等于1.0。但這并不是簡單地將各值除以總和那么簡單。相反,每個(gè)輸入值都會(huì)先被求指數(shù)。
a = exp(x_1)
這樣處理的效果是讓所有值變?yōu)檎龜?shù)。一旦得到了一個(gè)指數(shù)化的值向量,就可以將每個(gè)值除以所有值的總和,從而確保所有值的和為1.0。由于所有指數(shù)化的值都是正的,那么最終的值將介于0.0和1.0之間,也就是為原始值提供了一個(gè)概率分布。
softmax的過程就是這樣:簡單地對值進(jìn)行指數(shù)化處理,然后除以它們的總和。
不過,這里有一個(gè)小麻煩。
如果輸入值很大,那么指數(shù)化后的值也會(huì)很大。這時(shí),就將面臨一個(gè)大數(shù)除以另一個(gè)大的數(shù)的情況,進(jìn)而導(dǎo)致浮點(diǎn)運(yùn)算出現(xiàn)問題。
softmax運(yùn)算有一個(gè)有用的特性:如果向所有輸入值添加一個(gè)常數(shù),最終結(jié)果將保持不變。因此,可以在輸入向量中找到最大值,并從所有值中減去這個(gè)它,這樣可以確保最大值變?yōu)?.0,從而保持softmax運(yùn)算的數(shù)值穩(wěn)定。
在自注意力層,每個(gè)softmax運(yùn)算的輸入向量是自注意力矩陣的一行(但只到對角線為止)。
與「層歸一化」類似,有一個(gè)中間步驟來存儲一些聚合值來提高處理效率。
對于每一行,需要記錄該行的最大值和經(jīng)過移位與指數(shù)化處理后的值的總和。然后,為了得到相應(yīng)的輸出行,可以執(zhí)行一系列操作:減去最大值,進(jìn)行指數(shù)化處理,再除以總和。
那么,為什么叫「softmax」呢?
這個(gè)運(yùn)算的「hard」版本,稱為argmax,簡單地找到最大值,將其設(shè)為1.0,其他所有值設(shè)為0.0。相比之下,softmax運(yùn)算是一種更「soft」的版本。
由于涉及指數(shù)運(yùn)算,softmax運(yùn)算會(huì)突出最大值,并將其推向1.0,同時(shí)還保持了對所有輸入值的概率分布。這樣的處理方式不僅能捕獲到最可能的選項(xiàng),還能捕獲到其他選擇的相對可能性,實(shí)現(xiàn)了更細(xì)微的表示。
圖片
輸出
最后一個(gè)Transformer塊的輸出,首先會(huì)經(jīng)過層歸一化,然后再進(jìn)行線性變換(矩陣乘法),不過這次沒有加入偏置項(xiàng)。
圖片
最后的transformation會(huì)將每個(gè)列向量的長度從C變?yōu)閚vocab。因此,實(shí)際上是在為每一列的詞匯庫中的每個(gè)詞產(chǎn)生一個(gè)得分——logits。
「logits」這個(gè)術(shù)語源自「log-odds」,也就是每個(gè)token的對數(shù)幾率。之所以會(huì)使用「Log」(對數(shù)),是因?yàn)榻酉聛響?yīng)用的softmax會(huì)進(jìn)行指數(shù)轉(zhuǎn)換,從而把這些得分變成「幾率」或者說概率。
為了把這些得分轉(zhuǎn)化為更加直觀的概率值,需要先通過softmax來進(jìn)行處理。現(xiàn)在,每一列都得到了模型對詞匯表中每個(gè)詞所分配的概率。
在這個(gè)特定的模型中,它已經(jīng)有效地學(xué)會(huì)了所有關(guān)于如何排序三個(gè)字母的問題的答案,因此給出的概率值,也很大概率會(huì)傾向于正確答案。
在對模型進(jìn)行時(shí)間步進(jìn)時(shí),需要利用最后一列的概率值來決定下一個(gè)要添加到序列中的token。舉個(gè)例子,如果已經(jīng)向模型輸入了6個(gè)token,那么就會(huì)用第6列的輸出概率來決策。
這一列輸出的是一系列概率值,因此必須從中選擇一個(gè)作為序列的下一個(gè)元素。這需要通過「從分布中采樣」來實(shí)現(xiàn)。也就是說,會(huì)根據(jù)概率值的權(quán)重隨機(jī)選擇一個(gè)token。例如,一個(gè)概率為0.9的token有90%的概率被選中。
當(dāng)然,還有其他選擇方法,比如始終選擇概率最高的token。
此外,還可以通過使用溫度參數(shù)來控制分布的「平滑度」。較高的溫度會(huì)讓分布更均勻,而較低的溫度則會(huì)讓分布更集中于概率最高的token。
在應(yīng)用softmax之前,先用溫度除以logits(線性變換的輸出)。由于softmax中的指數(shù)化對較大的數(shù)值影響較大,因此將所有數(shù)字拉近會(huì)減少這種影響。
圖片
網(wǎng)友驚掉下巴
有網(wǎng)友表示,看到算法復(fù)雜度能夠在三維空間中,以如此清晰的方式呈現(xiàn)出來,讓我驚掉了下巴!
圖片
與NanoGPT相比,GPT-3簡直是一個(gè)怪物。
圖片
這看起來比我們在 2005 年在大學(xué)里看到的簡單神經(jīng)網(wǎng)絡(luò)要復(fù)雜1000倍。我正在考慮未來5-10年,通用人工智能 (AGI)將要走向哪里?
圖片
參考資料: