目錄
- 大模型-Transformer(解碼器層)
- 大模型-參數(shù)
- 其他補(bǔ)充
大模型-Transformer(解碼器層)
前面我們已經(jīng)了解了Transformer架構(gòu)的編碼器層的步驟,接下來我們來了解Transformer的后半部解碼器層。
Transformer架構(gòu)圖
解碼器層
解碼器層的作用是生成輸出文本,通過概率計算預(yù)測下一個最有可能的詞,從而生成輸出文本。
第一步:輸出(右移)
解碼器層的“輸出(右移)”中的“輸出”本質(zhì)是輸入,之所以叫“輸出”是因為在訓(xùn)練階段中該步驟的輸入內(nèi)容本質(zhì)是需要生成的答案,也就是解碼器層最終的輸出結(jié)果,并且解碼器層中每次完成單元計算的輸出結(jié)果,將作為下一次單元計算的輸入,所以這里的輸入叫成了輸出。
解碼器層的“輸出(右移)”中的“右移”只會在訓(xùn)練階段出現(xiàn),而訓(xùn)練階段是將答案作為的輸出,輸入到解碼器層中的,右移的目的是為了防止模型提前知道這次單元計算的答案。如果不是推理階段則不需要右移,輸出內(nèi)容則是上一次解碼器層計算單元的輸出結(jié)果,而第一次計算的“輸出(本質(zhì)是輸入)”則是僅包含<bos>的起始符號。
以翻譯訓(xùn)練的案例來看,假如我們要翻譯“我愛你”,答案是"i love you"
1、標(biāo)簽序列
答案是解碼器的目標(biāo)序列是"i love you"(長度 3),訓(xùn)練階段稱之為 “標(biāo)簽序列”,僅用于與模型預(yù)測結(jié)果對比,計算準(zhǔn)確率(損失),不參與解碼器任何前向計算(如掩碼自注意力)。
2、加上起始符號
首先會在輸入內(nèi)容中加上起始符號,變?yōu)椤?lt;bos>i love you”,內(nèi)容長度為4。在訓(xùn)練階段添加起始符號的目的是為了與推理階段邏輯保持一致,并且讓右移后序列長度與原始長度一致。在推理階段起始符號是為了標(biāo)記生成的開始。
3、右移(最終輸出)
為了保持輸入序列的長度一致,這個時候會將內(nèi)容長度進(jìn)行尾部截斷,變?yōu)?,變成“<bos>i love”
4、將token序列轉(zhuǎn)為ID序列
跟編碼器層的“輸入”步驟一樣,最終的結(jié)果是需要轉(zhuǎn)為ID序列的,例如["2","432421","988331"],一般<bos>起始符號的ID是2
由于訓(xùn)練時的標(biāo)簽序列長度為3,而右移截斷后的輸入序列也是3,所以在訓(xùn)練階段中并不需要像編碼器“輸入”步驟一樣對輸入序列進(jìn)行PAD填充。
單從“輸出(右移)”的步驟來看,右移的本質(zhì)是為了讓添加起始符號后的序列長度與原始輸入序列長度保持一致,避免因為長度不匹配導(dǎo)致無法訓(xùn)練。
將“輸出(右移)”和“掩碼自注意力”兩步合在一起來看,右移的本質(zhì)是為了防止模型提前知道答案,通過添加起始符號,讓添加起始符號的序列中每個位置的詞與標(biāo)簽序列對應(yīng)位置的詞都不一樣,相當(dāng)于新序列中每個詞右移了一個位置,從而讓基于當(dāng)前位置的計算過程,變得不可預(yù)見性,再配合掩碼自注意力中的下三角掩碼實現(xiàn)防止模型提前知道答案。
繼續(xù)以上面“今天天氣真好”的推理案例來看
1、加上起始符號
推理階段只有在第一次單元計算是才會添加起始符號,由于第一次單元計算時還沒有任何輸入內(nèi)容,所以第一次計算時只會添加起始符號,變成“<bos>”,長度為1,表示計算的啟動信號。
2、將token序列轉(zhuǎn)為ID序列
輸出結(jié)果["2"]
推理階段的“輸出(右移)”就非常簡單,沒有“右移”的步驟。由于解碼器層的設(shè)計是逐字生成,所以在推理階段中序列長度也是逐步增加的,第一次單元計算中,序列長度為1,表示要生成一個詞,而因為在“輸入(右移)”的步驟中已經(jīng)加入了起始符號<bos>,讓輸入序列的長度已經(jīng)變?yōu)榱?,所以不需要PAD填充(批量推理時是需要PAD填充保持批量計算中的張量一致)。
第二步:輸出嵌入層
與編碼器層的“輸入嵌入”步驟一樣,核心是將ID序列通過嵌入矩陣轉(zhuǎn)換為詞向量序列
后面我們統(tǒng)一都按照推理階段進(jìn)行講解,以翻譯“我愛你”為示例。為了方便展示計算過程,統(tǒng)一將維度調(diào)整為8維,并且模型已經(jīng)完成2次單元計算,已生成的輸出內(nèi)容為“<bos>i love”
該步驟最終輸出的是
[
[0.12, 0.34, -0.05, 0.27, -0.18, 0.41, -0.23, 0.09],#<bos>
[0.56, -0.17, 0.32, -0.08, 0.29, -0.45, 0.16, -0.31],# i
[0.38, 0.25, -0.19, 0.42, -0.07, 0.33, -0.28, 0.14]# love
]
第三步:位置編碼
與編碼器層的“位置編碼”步驟一樣,核心是為詞向量矩陣加上位置信息。計算公式也一樣
該步驟最終的輸出結(jié)果是
[
[0.12,1.34,?0.05,1.27,?0.18,1.41,?0.23,1.09],
[1.40,078,0.63,0.90,0.39,0.54,0.19,0.69],
[1.29,1.05,0.41,1.35,0.13,1.32,-0.22,1.13]
]
第四步:掩碼多頭自注意力層
掩碼多頭自注意力層的實現(xiàn)步驟與多頭自注意力基本一樣,唯一的區(qū)別是在掩碼步驟的不同,多頭自注意力中的掩碼矩陣是僅屏蔽 PAD 位置的無效信息,而解碼器階段在非批量推理情況下,掩碼多頭自注意力層因為不需要進(jìn)行PAD填充,所以掩碼矩陣中并不需要去屏蔽PAD位置,而是增加了下三角掩碼來防止計算過程中關(guān)注到未來的詞的特性而產(chǎn)生預(yù)見性。
掩碼多頭自注意力層之所以是增加的下三角掩碼的核心原因是因為注意力得分公式中Q向量矩陣每一行是一個詞,每一列是不同詞的同一維,而K矩陣轉(zhuǎn)置后,每一列是一個詞,每一行是一個詞的不同維,兩者相乘得到的矩陣中每一個行表示一個詞與其他詞在同一個維度上的注意力關(guān)系。而下三角則是剛好能屏蔽每一行所代表單詞與其之后的單詞的注意力得分,來避免后續(xù)的計算過程中提前預(yù)知未來。
步驟1 : 計算Q(查詢)、K(鍵)、V(值)矩陣
這里我們假定W_k、W_q、W_v權(quán)重矩陣如下
W_Q = [
[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],
[0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.1],
[0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.1, 0.2],
[0.4, 0.5, 0.6, 0.7, 0.8, 0.1, 0.2, 0.3],
[0.5, 0.6, 0.7, 0.8, 0.1, 0.2, 0.3, 0.4],
[0.6, 0.7, 0.8, 0.1, 0.2, 0.3, 0.4, 0.5],
[0.7, 0.8, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
[0.8, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]
]
W_K = W_Q # 簡化:Q和K共享權(quán)重(實際可不同)
W_V = [
[0.1, 0.1, 0.2, 0.2, 0.3, 0.3, 0.4, 0.4],
[0.1, 0.2, 0.2, 0.3, 0.3, 0.4, 0.4, 0.1],
[0.2, 0.2, 0.3, 0.3, 0.4, 0.4, 0.1, 0.1],
[0.2, 0.3, 0.3, 0.4, 0.4, 0.1, 0.1, 0.2],
[0.3, 0.3, 0.4, 0.4, 0.1, 0.1, 0.2, 0.2],
[0.3, 0.4, 0.4, 0.1, 0.1, 0.2, 0.2, 0.3],
[0.4, 0.4, 0.1, 0.1, 0.2, 0.2, 0.3, 0.3],
[0.4, 0.1, 0.1, 0.2, 0.2, 0.3, 0.3, 0.4]
]
根據(jù)公式相乘后得到的Q、K、V矩陣如下
Q = [
[3.02, 2.84, 2.07, 1.89, 1.71, 1.53, 1.35, 1.17],
[2.76, 2.59, 2.02, 1.85, 1.68, 1.51, 1.34, 1.17],
[3.83, 3.62, 2.61, 2.40, 2.19, 1.98, 1.77, 1.56]
]
Q = K
V = [
[1.53, 1.35, 1.17, 0.99, 0.81, 0.63, 0.45, 0.27],
[1.36, 1.20, 1.04, 0.88, 0.72, 0.56, 0.40, 0.24],
[1.92, 1.70, 1.48, 1.26, 1.04, 0.82, 0.60, 0.38]
]
步驟2 : 分割Q、K、V到多個注意力頭
這里我們假設(shè)拆分為2個4維的頭
Q1 = K1 = [
[3.02,2.84,2.07,1.89],
[2.76,2.59,2.02,1.85],
[3.83,3.62,2.61,2.40]]
Q2 = K2 = [
[1.71,1.53,1.35,1.17],
[1.68,1.51,1.34,1.17],
[2.19,1.98,1.77,1.56]
]
V1 = [
[1.53,1.35,1.17,0.99],
[1.36,1.20,1.04,0.88],
[1.92,1.70,1.48,1.26]
]
V2 = [
[0.81,0.63,0.45,0.27],
[0.72,0.56,0.40,0.24],
[1.04,0.82,0.60,0.38]
]
步驟3 : 計算每個頭的注意力分?jǐn)?shù)

Q1×K1^T = [
[25.04, 23.37, 31.79],
[23.37, 21.83, 29.66],
[31.79, 29.66, 40.34]
]
scores = Q1×K1^T / 2 = [
[12.52, 11.68, 15.90], # 行0(<bos>)
[11.68, 10.92, 14.83], # 行1(i)
[15.90, 14.83, 20.17] # 行2(love)
]
步驟4 : 應(yīng)用下三角掩碼
mask = [
[0, -∞, -∞], # 行0(<bos>):只能關(guān)注列0(自身)
[0, 0, -∞], # 行1(i):只能關(guān)注列0、列1(自身及之前)
[0, 0, 0]] # 行2(love):可關(guān)注列0、1、2(所有前序及自身)
masked_scores = [
[12.52, -∞, -∞],
[11.68, 10.92, -∞],
[15.90, 14.83, 20.17]
]

步驟5 : 應(yīng)用softmax函數(shù)
weights = [
[1.00, 0.00, 0.00], # 位置0:僅關(guān)注自身
[0.69, 0.31, 0.00], # 位置1:主要關(guān)注<bos>(0.69),次要關(guān)注自身(0.31)
[0.01, 0.00, 0.98] # 位置2:幾乎關(guān)注自身(0.98),輕微關(guān)注前序詞
]
步驟6 : 每個頭的輸出 = 權(quán)重 x V
V1_out = [
[1.53, 1.35, 1.17, 0.99], # 位置0(<bos>)
[1.48, 1.30, 1.13, 0.95], # 位置1(i)
[1.90, 1.68, 1.46, 1.24] # 位置2(love)
]
步驟7 : 合并所有頭的結(jié)果,進(jìn)行線性變換,得到最終的注意力得分矩陣
頭2的計算結(jié)果如下
V2_out = [[0.81, 0.63, 0.45, 0.27], # 位置0(<bos>)
[0.76, 0.59, 0.43, 0.26], # 位置1(i)
[0.95, 0.75, 0.54, 0.34]] # 位置2(love)
假設(shè)W_o如下
W_O = [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],
[0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.1],
[0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.1, 0.2],
[0.4, 0.5, 0.6, 0.7, 0.8, 0.1, 0.2, 0.3],
[0.5, 0.6, 0.7, 0.8, 0.1, 0.2, 0.3, 0.4],
[0.6, 0.7, 0.8, 0.1, 0.2, 0.3, 0.4, 0.5],
[0.7, 0.8, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
[0.8, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]]
最終計算輸出的注意力得分矩陣
Z = [ [2.50, 3.01, 3.35, 3.56, 3.65, 3.57, 3.35, 2.99], # 位置0(<bos>) [2.37, 2.84, 3.18, 3.42, 3.50, 3.43, 3.23, 2.86], # 位置1(i) [3.05, 3.63, 4.10, 4.40, 4.52, 4.41, 4.12, 3.67]] # 位置2(love)
第五步:殘差連接&層歸一化
這里的殘差連接&層歸一化與之前編碼器層的殘差連接&層歸一化作用完全一樣,唯一的區(qū)別僅因前置步驟的不同,導(dǎo)致其執(zhí)行的意義有所不同,這里不在重復(fù)說明
殘差連接計算結(jié)果
residual = [
[2.62, 4.35, 3.30, 4.83, 3.47, 4.98, 3.12, 4.08],
[3.77, 3.62, 3.81, 4.32, 3.89, 3.97, 3.42, 3.55],
[4.34, 4.68, 4.51, 5.75, 4.65, 5.73, 3.90, 4.80]
]
層歸一化計算結(jié)果
ln_output = [
[-1.54, 0.64, -0.68, 1.24, -0.47, 1.43, -0.91, 0.30], # 位置0(<bos>)
[-0.08, -0.65, 0.08, 2.04, 0.38, 0.69, -1.39, -0.92], # 位置1(i)
[-0.77, -0.20, -0.48, 1.58, -0.25, 1.55, -1.50, 0.00] # 位置2(love)
]
最終輸出就是層歸一化的計算結(jié)果
第六步:多頭自注意力層
這里的多有自注意力層的執(zhí)行過程與編碼器層的完全一樣,唯一的不同點(diǎn)在于,編碼器層的多頭自注意力層中的Q、K、V是W_q、W_k、W_v的權(quán)重矩陣與上一步的輸出點(diǎn)積運(yùn)算得到的,而解碼器層的多頭自注意力層中的K、V是編碼器層的最終輸出與W_k、W_v點(diǎn)積運(yùn)算得到的,Q是其上一步的最終輸出與W_q點(diǎn)積運(yùn)算得到的。
步驟1 : 計算Q(查詢)、K(鍵)、V(值)矩陣
我們先假定W_q、W_k、W_v、W_o值如下
# W_q(查詢矩陣)
W_q = [
[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],
[0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.1],
[0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.1, 0.2],
[0.4, 0.5, 0.6, 0.7, 0.8, 0.1, 0.2, 0.3],
[0.5, 0.6, 0.7, 0.8, 0.1, 0.2, 0.3, 0.4],
[0.6, 0.7, 0.8, 0.1, 0.2, 0.3, 0.4, 0.5],
[0.7, 0.8, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
[0.8, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]
]
# W_k(鍵矩陣)
W_k = [
[0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1],
[0.1, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2],
[0.2, 0.1, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3],
[0.3, 0.2, 0.1, 0.8, 0.7, 0.6, 0.5, 0.4],
[0.4, 0.3, 0.2, 0.1, 0.8, 0.7, 0.6, 0.5],
[0.5, 0.4, 0.3, 0.2, 0.1, 0.8, 0.7, 0.6],
[0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.8, 0.7],
[0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.8]
]
# W_v(值矩陣)
W_v = [
[0.5, 0.1, 0.2, 0.3, 0.4, 0.6, 0.7, 0.8],
[0.6, 0.5, 0.1, 0.2, 0.3, 0.4, 0.7, 0.8],
[0.7, 0.6, 0.5, 0.1, 0.2, 0.3, 0.4, 0.8],
[0.8, 0.7, 0.6, 0.5, 0.1, 0.2, 0.3, 0.4],
[0.1, 0.8, 0.7, 0.6, 0.5, 0.1, 0.2, 0.3],
[0.2, 0.1, 0.8, 0.7, 0.6, 0.5, 0.1, 0.2],
[0.3, 0.2, 0.1, 0.8, 0.7, 0.6, 0.5, 0.1],
[0.4, 0.3, 0.2, 0.1, 0.8, 0.7, 0.6, 0.5]
]
# W_o(輸出投影矩陣)
W_o = W_q
掩碼矩陣為
pad_mask = [
[0, 0, 0, 0, -float('inf'), -float('inf'), -float('inf'), -float('inf')], # 解碼器位置0
[0, 0, 0, 0, -float('inf'), -float('inf'), -float('inf'), -float('inf')], # 解碼器位置1
[0, 0, 0, 0, -float('inf'), -float('inf'), -float('inf'), -float('inf')] # 解碼器位置2
]
這里說明一下為什么掩碼矩陣中掩的是4-7列,掩碼的核心是 “屏蔽‘被關(guān)注方’的無效位置(PAD)”,計算注意力權(quán)重得分時,點(diǎn)積運(yùn)算中每個頭需要關(guān)注的是自己與其他鍵的注意力關(guān)系,這里“被關(guān)注方”就是K,而K在計算中是被轉(zhuǎn)置了的,轉(zhuǎn)置矩陣對應(yīng)的PAD位是交叉注意力層中 “被關(guān)注方無效位置” 的具體映射結(jié)果,所以掩碼矩陣中掩掉的是4-7列。
Q矩陣 = ln_output x W_q
Q = [
[0.52, 0.68, 0.83, 0.97, 1.12, 1.25, 1.38, 1.50], # 位置0
[0.49, 0.65, 0.80, 0.94, 1.09, 1.22, 1.35, 1.47], # 位置1
[0.55, 0.71, 0.86, 1.00, 1.15, 1.28, 1.41, 1.53] # 位置2
]
K = output(編碼器層最終輸出) x W_k
K = [
[1.63, 1.75, 1.87, 1.99, 2.11, 2.23, 2.35, 2.47], # 位置0(有效)
[1.71, 1.83, 1.95, 2.07, 2.19, 2.31, 2.43, 2.55], # 位置1(有效)
[1.79, 1.91, 2.03, 2.15, 2.27, 2.39, 2.51, 2.63], # 位置2(有效)
[1.87, 1.99, 2.11, 2.23, 2.35, 2.47, 2.59, 2.71], # 位置3(有效)
[1.95, 2.07, 2.19, 2.31, 2.43, 2.55, 2.67, 2.79], # 位置4(PAD,非零)
[2.03, 2.15, 2.27, 2.39, 2.51, 2.63, 2.75, 2.87], # 位置5(PAD,非零)
[2.11, 2.23, 2.35, 2.47, 2.59, 2.71, 2.83, 2.95], # 位置6(PAD,非零)
[2.19, 2.31, 2.43, 2.55, 2.67, 2.79, 2.91, 3.03] # 位置7(PAD,非零)
]
V = output(編碼器層最終輸出) x W_v
V = [
[1.02, 1.14, 1.26, 1.38, 1.50, 1.62, 1.74, 1.86], # 位置0(有效)
[1.10, 1.22, 1.34, 1.46, 1.58, 1.70, 1.82, 1.94], # 位置1(有效)
[1.18, 1.30, 1.42, 1.54, 1.66, 1.78, 1.90, 2.02], # 位置2(有效)
[1.26, 1.38, 1.50, 1.62, 1.74, 1.86, 1.98, 2.10], # 位置3(有效)
[1.34, 1.46, 1.58, 1.70, 1.82, 1.94, 2.06, 2.18], # 位置4(PAD,非零)
[1.42, 1.54, 1.66, 1.78, 1.90, 2.02, 2.14, 2.26], # 位置5(PAD,非零)
[1.50, 1.62, 1.74, 1.86, 1.98, 2.10, 2.22, 2.34], # 位置6(PAD,非零)
[1.58, 1.70, 1.82, 1.94, 2.06, 2.18, 2.30, 2.42] # 位置7(PAD,非零)
]
步驟2 :分割Q、K、V到多個注意力頭
這里我們依然假設(shè)拆分為2個4維的頭,下面僅展示頭1的計算過程
Q1 = [
[0.52, 0.68, 0.83, 0.97], # 位置0
[0.49, 0.65, 0.80, 0.94], # 位置1
[0.55, 0.71, 0.86, 1.00] # 位置2
]
K1 = [
[1.63, 1.75, 1.87, 1.99], # 位置0(有效)
[1.71, 1.83, 1.95, 2.07], # 位置1(有效)
[1.79, 1.91, 2.03, 2.15], # 位置2(有效)
[1.87, 1.99, 2.11, 2.23], # 位置3(有效)
[1.95, 2.07, 2.19, 2.31], # 位置4(PAD)
[2.03, 2.15, 2.27, 2.39], # 位置5(PAD)
[2.11, 2.23, 2.35, 2.47], # 位置6(PAD)
[2.19, 2.31, 2.43, 2.55] # 位置7(PAD)
]
V1 = [
[1.02, 1.14, 1.26, 1.38], # 位置0(有效)
[1.10, 1.22, 1.34, 1.46], # 位置1(有效)
[1.18, 1.30, 1.42, 1.54], # 位置2(有效)
[1.26, 1.38, 1.50, 1.62], # 位置3(有效)
[1.34, 1.46, 1.58, 1.70], # 位置4(PAD)
[1.42, 1.54, 1.66, 1.78], # 位置5(PAD)
[1.50, 1.62, 1.74, 1.86], # 位置6(PAD)
[1.58, 1.70, 1.82, 1.94] # 位置7(PAD)
]
步驟3 :計算每個頭的注意力分?jǐn)?shù)
scores1= Q1×K1^T / 2 = [
[2.60, 2.74, 2.88, 3.02, 3.16, 3.30, 3.44, 3.58],
[2.52, 2.66, 2.80, 2.94, 3.08, 3.22, 3.36, 3.50],
[2.68, 2.82, 2.96, 3.10, 3.24, 3.38, 3.52, 3.66]
]
步驟4 :應(yīng)用下三角掩碼
masked_scores1 = [
[2.60, 2.74, 2.88, 3.02, -inf, -inf, -inf, -inf],
[2.52, 2.66, 2.80, 2.94, -inf, -inf, -inf, -inf],
[2.68, 2.82, 2.96, 3.10, -inf, -inf, -inf, -inf]
]
步驟5 : 應(yīng)用softmax函數(shù)
weights1 = [
[0.20, 0.23, 0.27, 0.30, 0.00, 0.00, 0.00, 0.00],
[0.21, 0.24, 0.26, 0.29, 0.00, 0.00, 0.00, 0.00],
[0.19, 0.22, 0.25, 0.34, 0.00, 0.00, 0.00, 0.00]
]
步驟6 : 每個頭的輸出 = 權(quán)重 x V
head1_output = [
[1.16, 1.28, 1.40, 1.52],
[1.15, 1.27, 1.39, 1.51],
[1.17, 1.29, 1.41, 1.53]
]
步驟7 : 合并所有頭的結(jié)果,進(jìn)行線性變換,得到最終的注意力得分矩陣
頭2最終的計算得分為
head2_output = [
[1.66, 1.78, 1.90, 2.02],
[1.65, 1.77, 1.89, 2.01],
[1.67, 1.79, 1.91, 2.03]
]
合并后為
concat_output = [
[1.16, 1.28, 1.40, 1.52, 1.66, 1.78, 1.90, 2.02], # 位置0
[1.15, 1.27, 1.39, 1.51, 1.65, 1.77, 1.89, 2.01], # 位置1
[1.17, 1.29, 1.41, 1.53, 1.67, 1.79, 1.91, 2.03] # 位置2
]
由于W_o = W_q,所以最終該步驟的輸出結(jié)果為
cross_attention_output = [ [2.42, 2.59, 2.76, 2.93, 3.10, 3.27, 3.44, 3.61], # 位置0 [2.40, 2.57, 2.74, 2.91, 3.08, 3.25, 3.42, 3.59], # 位置1 [2.44, 2.61, 2.78, 2.95, 3.12, 3.29, 3.46, 3.63] # 位置2 ]
第七步:殘差連接&層歸一化
與之前的計算過程一樣,這里不重復(fù)說明
殘差連接計算結(jié)果為
residual = [
[0.88, 3.23, 2.08, 4.17, 2.63, 4.70, 2.53, 3.91], # 位置0
[2.32, 1.92, 2.82, 4.95, 3.46, 3.94, 2.03, 2.67], # 位置1
[1.67, 2.41, 2.30, 4.53, 2.87, 4.84, 1.96, 3.63] # 位置2
]
層歸一化計算結(jié)果為
decoder_cross_attn_final = [
[-1.836, 0.181, -0.802, 0.991, -0.336, 1.448, -0.422, 0.767], # 位置0
[-0.708, -1.118, -0.195, 1.988, 0.462, 0.954, -1.005, -0.349], # 位置1
[-1.226, -0.559, -0.658, 1.353, -0.144, 1.632, -0.965, 0.541] # 位置2
]
第八步:前饋網(wǎng)絡(luò)層
該步驟與編譯器層中的前饋網(wǎng)絡(luò)層執(zhí)行過程與作用完全一致,這里步重復(fù)說明
假設(shè)W1、W2、b1、b2如下
W1 = [
[0.1, 0.2, 0.3, 0.4, ..., 0.1], # 輸入第0維→32維映射(共32列)
[0.2, 0.3, 0.4, 0.5, ..., 0.2], # 輸入第1維→32維映射
[0.3, 0.4, 0.5, 0.6, ..., 0.3], # 輸入第2維→32維映射
[0.4, 0.5, 0.6, 0.7, ..., 0.4], # 輸入第3維→32維映射
[0.5, 0.6, 0.7, 0.8, ..., 0.5], # 輸入第4維→32維映射
[0.6, 0.7, 0.8, 0.1, ..., 0.6], # 輸入第5維→32維映射
[0.7, 0.8, 0.1, 0.2, ..., 0.7], # 輸入第6維→32維映射
[0.8, 0.1, 0.2, 0.3, ..., 0.8] # 輸入第7維→32維映射
]
b1 = [0.1] * 32 # 偏置(32維,均為0.1)
W2 = [
[0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1], # 中間第0維→輸出8維映射
[0.1, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2], # 中間第1維→輸出8維映射
[0.2, 0.1, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3], # 中間第2維→輸出8維映射
[0.3, 0.2, 0.1, 0.8, 0.7, 0.6, 0.5, 0.4], # 中間第3維→輸出8維映射
... # 共32行
]
b2 = [0.2] * 8 # 偏置(8維,均為0.2)
步驟1 :線性變換升維
依據(jù)是擴(kuò)充4倍
#這里計算保留到了小數(shù)點(diǎn)后四位
linear1_output = [
# 位置0(32維):[z0, z1, z2, ..., z31]
[1.2300, 1.3500, 1.4700, 1.5900, 1.7100, 1.8300, 1.9500, 2.0700,
2.1900, 2.3100, 2.4300, 2.5500, 2.6700, 2.7900, 2.9100, 3.0300,
3.1500, 3.2700, 3.3900, 3.5100, 3.6300, 3.7500, 3.8700, 3.9900,
4.1100, 4.2300, 4.3500, 4.4700, 4.5900, 4.7100, 4.8300, 4.9500],
# 位置1(32維):[z0, z1, ..., z31]
[1.1500, 1.2700, 1.3900, 1.5100, 1.6300, 1.7500, 1.8700, 1.9900,
2.1100, 2.2300, 2.3500, 2.4700, 2.5900, 2.7100, 2.8300, 2.9500,
3.0700, 3.1900, 3.3100, 3.4300, 3.5500, 3.6700, 3.7900, 3.9100,
4.0300, 4.1500, 4.2700, 4.3900, 4.5100, 4.6300, 4.7500, 4.8700],
# 位置2(32維):[z0, z1, ..., z31]
[1.3100, 1.4300, 1.5500, 1.6700, 1.7900, 1.9100, 2.0300, 2.1500,
2.2700, 2.3900, 2.5100, 2.6300, 2.7500, 2.8700, 2.9900, 3.1100,
3.2300, 3.3500, 3.4700, 3.5900, 3.7100, 3.8300, 3.9500, 4.0700,
4.1900, 4.3100, 4.4300, 4.5500, 4.6700, 4.7900, 4.9100, 5.0300]
]
步驟2:非線性變換激活函數(shù)(GULE)
gelu_output = [
# 位置0(32維,前8維示例)
[1.0930, 1.2015, 1.3082, 1.4131, 1.5162, 1.6175, 1.7170, 1.8147,
1.9106, 2.0048, 2.0972, 2.1878, 2.2767, 2.3639, 2.4494, 2.5332,
2.6153, 2.6958, 2.7746, 2.8518, 2.9274, 3.0014, 3.0738, 3.1446,
3.2139, 3.2817, 3.3479, 3.4126, 3.4758, 3.5375, 3.5977, 3.6565],
# 位置1(32維,前8維示例)
[1.0210, 1.1265, 1.2302, 1.3321, 1.4322, 1.5305, 1.6270, 1.7217,
1.8146, 1.9058, 1.9952, 2.0828, 2.1687, 2.2529, 2.3354, 2.4162,
2.4953, 2.5728, 2.6486, 2.7228, 2.7954, 2.8664, 2.9358, 3.0037,
3.0701, 3.1350, 3.1984, 3.2604, 3.3210, 3.3802, 3.4380, 3.4944],
# 位置2(32維,前8維示例)
[1.1580, 1.2685, 1.3772, 1.4841, 1.5892, 1.6925, 1.7940, 1.8937,
1.9916, 2.0878, 2.1822, 2.2748, 2.3657, 2.4549, 2.5424, 2.6282,
2.7123, 2.7948, 2.8756, 2.9548, 3.0324, 3.1084, 3.1828, 3.2556,
3.3269, 3.3967, 3.4650, 3.5318, 3.5972, 3.6611, 3.7236, 3.7847]
]
步驟3 : 降維
ffn_output = [
[3.824, 3.992, 4.160, 4.328, 4.496, 4.664, 4.832, 5.000], # 位置0(8維)
[3.672, 3.836, 4.000, 4.164, 4.328, 4.492, 4.656, 4.820], # 位置1(8維)
[3.976, 4.148, 4.320, 4.492, 4.664, 4.836, 5.008, 5.180] # 位置2(8維)
]
第九步:殘差連接&層歸一化
該步驟與前面的一樣
殘差連接計算結(jié)果為
residual_ffn = [
[1.988, 4.173, 3.358, 5.319, 4.160, 6.112, 4.410, 5.767], # 位置0
[2.964, 2.718, 3.805, 6.152, 4.790, 5.446, 3.651, 4.471], # 位置1
[2.750, 3.589, 3.662, 5.845, 4.520, 6.468, 4.043, 5.721] # 位置2
]
層歸一化計算結(jié)果為
decoder_layer_final = [
[-1.4823, 0.3867, -0.0612, 1.1895, 0.0124, 1.6542, 0.5831, 0.8876], # 位置0
[-0.0215, -0.7983, 0.3768, 1.8217, 0.7549, 1.2986, -0.0453, 0.1221], # 位置1
[-0.7215, 0.2098, 0.2873, 1.3987, 0.5324, 1.9568, 0.1605, 1.2070] # 位置2
]
第十步:多層循環(huán)
這里的多層循環(huán)堆疊與編碼器層的一樣,這里不再重復(fù)說明
這里我們依然假設(shè)執(zhí)行6次后最終的輸出結(jié)果為
output = [
[-1.4823, 0.3867, -0.0612, 1.1895, 0.0124, 1.6542, 0.5831, 0.8876], # 位置0
[-0.0215, -0.7983, 0.3768, 1.8217, 0.7549, 1.2986, -0.0453, 0.1221], # 位置1
[-0.7215, 0.2098, 0.2873, 1.3987, 0.5324, 1.9568, 0.1605, 1.2070] # 位置2
]
解碼器層多層堆疊計算得到的最終輸出,本質(zhì)也是一個綜合語義的特征矩陣,但是編碼器層所綜合的并不是單純的用戶輸入,而是包含用戶輸入和已生成內(nèi)容的綜合語義,它更加的豐富,這樣的原因是為了讓生成的內(nèi)容更加的符合用戶輸入的語義,讓生成的內(nèi)容更加的連貫,前后呼應(yīng)。
第十一步:線性層
線性層是生成任務(wù)的最后一公里,其核心作用是通過簡單的線性變換將解碼器多次堆疊輸出的高維特征矩陣映射到詞匯表維度,所謂的詞匯表維度指的是通過線性層計算得到的原始分?jǐn)?shù)能夠體現(xiàn)每個詞與當(dāng)前語義特征的匹配程度得分,這些分?jǐn)?shù)經(jīng)下一步的softmax歸一化后,就能轉(zhuǎn)化為每個詞出現(xiàn)在當(dāng)前位置的概率,所以線性層最終得到一個未歸一化的分?jǐn)?shù)矩陣,所謂的未歸一化是指沒有進(jìn)過softmax進(jìn)行歸一化操作,讓分?jǐn)?shù)矩陣中的數(shù)值的總和變?yōu)?,更加精準(zhǔn)穩(wěn)定的體現(xiàn)下一個詞在詞匯表中的概率分布。
計算公式:
線性層計算公式
X:線性層的輸入,也就是第十步多層循環(huán)堆疊計算輸出的結(jié)果
W(權(quán)重矩陣):形狀為[d_model, vocab_size],d_model是模型統(tǒng)一的維度,其中vocab_size是輸出詞匯表的大小意味著如果詞匯有10萬個詞,那么vocab_size就等于10萬,因為需要通過vocab_size的維來映射對應(yīng)詞匯表中每一個詞,計算出每個詞的得分權(quán)重。W的每一列對應(yīng)詞匯表中一個詞的 “投影權(quán)重”,用于將d_model維特征映射到該詞的分?jǐn)?shù)。
B(偏置向量):形狀為[vocab_size](可選,部分實現(xiàn)可能省略),每個元素對應(yīng)詞匯表中一個詞的 “偏移量”,用于微調(diào)該詞的分?jǐn)?shù)。
這里我們假定詞匯表中總共有10個詞如下,這也意味著vocab_size為10
| 索引 | 對應(yīng)的詞 |
|---|---|
| 0 | <pad>:占位符 |
| 1 | <unk>:未知符號 |
| 2 | <bos>:起始符號 |
| 3 | <eos>:結(jié)束符號 |
| 4 | me |
| 5 | it |
| 6 | this |
| 7 | the |
| 8 | that |
| 9 | you |
# 線性層權(quán)重W(8×10)
W = [
[0.2134, 0.1856, 0.3421, 0.4178, 0.0987, 0.5234, 0.2765, 0.3912, 0.1543, 0.4890], # 輸入第0維→詞表10維
[0.1765, 0.2987, 0.0892, 0.3541, 0.5123, 0.1456, 0.4237, 0.2689, 0.3871, 0.1298], # 輸入第1維→詞表10維
[0.3219, 0.0765, 0.2843, 0.1598, 0.3972, 0.2468, 0.1890, 0.4532, 0.0987, 0.3654], # 輸入第2維→詞表10維
[0.4682, 0.3157, 0.1984, 0.0876, 0.2543, 0.3891, 0.5126, 0.1745, 0.2963, 0.0689], # 輸入第3維→詞表10維
[0.1432, 0.4896, 0.3657, 0.2189, 0.0745, 0.1987, 0.3214, 0.4568, 0.5092, 0.2876], # 輸入第4維→詞表10維
[0.5012, 0.2345, 0.1678, 0.3921, 0.4765, 0.0893, 0.2154, 0.1387, 0.3642, 0.4291], # 輸入第5維→詞表10維
[0.2679, 0.3841, 0.4562, 0.1237, 0.2984, 0.3516, 0.0798, 0.4123, 0.1854, 0.2467], # 輸入第6維→詞表10維
[0.3987, 0.1542, 0.2763, 0.4891, 0.1357, 0.2684, 0.3192, 0.0985, 0.4321, 0.1768] # 輸入第7維→詞表10維
]
# 線性層偏置b(10維)
b = [0.05, 0.03, 0.07, 0.02, 0.06, 0.04, 0.01, 0.08, 0.09, 0.02]
最終根據(jù)公式計算出的結(jié)果為
# 輸入中第0行為[-1.4823, 0.3867, -0.0612, 1.1895, 0.0124, 1.6542, 0.5831, 0.8876]
# logits [0][0] = input[0][0] x W[0][0] + input[0][1] x W[1][0] + input[0][2] x W[2][0] + input[0][3] x W[3][0] + input[0][4] x W[4][0] + input[0][5] x W[5][0] + input[0][6] x W[6][0] + input[0][7] x W[7][0] + b[0]
# logits [0][0] = (?1.4823×0.2134)+(0.3867×0.1765)+(?0.0612×0.3219)+(1.1895×0.4682)+(0.0124×0.1432)+(1.6542×0.5012)+(0.5831×0.2679)+(0.8876×0.3987) + 0.05
# logits [0][0] = 1.6893
# 線性層輸出logits(3×10):每行對應(yīng)一個位置,每列對應(yīng)詞表一個詞的分?jǐn)?shù)
logits = [
# 位置0(<bos>):詞表0-9的logits
[1.6893, 1.2457, 0.9872, 1.8321, 0.7654, 2.0146, 1.3589, 1.5762, 0.6983, 1.9215],
# 位置1(i):詞表0-9的logits
[1.4321, 1.7654, 1.1298, 0.8976, 1.9345, 1.2873, 0.7542, 1.6891, 1.3567, 0.9872],
# 位置2(love):詞表0-9的logits
[2.1568, 1.3987, 1.8765, 0.9342, 1.5678, 0.8912, 1.7435, 1.2896, 1.9873, 2.3145]
]
第十二步:softmax層
線性層計算出的結(jié)果是一個為歸一化的,最后通過softmax函數(shù)進(jìn)行歸一化操作,轉(zhuǎn)化為0~1 之間、總和為 1 的概率分布,最終明確每個詞在當(dāng)前位置的出現(xiàn)概率。
計算公式:
softmax計算公式
logits_i : logits對應(yīng)位置向量中的第i個元素(對應(yīng)詞表第i個詞的原始分?jǐn)?shù)),每個位置(行)會單獨(dú)進(jìn)行計算
e^logits_i : 自然指數(shù)運(yùn)算(將正負(fù)分?jǐn)?shù)轉(zhuǎn)化為非負(fù)值,保留分?jǐn)?shù)相對差異)
分母:logits 向量所有元素的指數(shù)和(確保歸一化后總和為 1)
# 這里我僅展示logits[0]的計算過程
# 先計算指數(shù)以及指數(shù)之和
# logits [0] = [1.6893, 1.2457, 0.9872, 1.8321, 0.7654, 2.0146, 1.3589, 1.5762, 0.6983, 1.9215]
# e^logits_0 = e^1.6893 ≈ 5.418
# e^logits_1 = e^1.2457 ≈ 3.474
# e^logits_2 = e^0.9872 ≈ 2.685
# e^logits_3 = e^1.8321 ≈ 6.254
# e^logits_4 = e^0.7654 ≈ 2.150
# e^logits_5 = e^2.0146 ≈ 7.598
# e^logits_6 = e^1.3589 ≈ 3.892
# e^logits_7 = e^1.5762 ≈ 4.836
# e^logits_8 = e^0.6983 ≈ 2.010
# e^logits_9 = e^1.9215 ≈ 6.8320
# 分母為指數(shù)之和 = 5.418 + 3.474 + 2.685 + 6.254 + 2.150 + 7.598 + 3.892 + 4.836 + 2.010 + 6.8320
# 分母為指數(shù)之和 = 45.149
# 指數(shù)百分比計算
softmax_fina[0][0] = 5.418 / 45.149 ≈ 0.1200
softmax_fina[0][1] = 3.474 / 45.149 ≈ 0.0770
softmax_fina[0][2] = 2.68 / 45.149 ≈ 0.0595
softmax_fina[0][3] = 6.254 / 45.149 ≈ 0.1385
softmax_fina[0][4] = 2.150 / 45.149 ≈ 0.0476
softmax_fina[0][5] = 7.598 / 45.149 ≈ 0.1683(概率最高)
softmax_fina[0][6] = 3.892 / 45.149 ≈ 0.0862
softmax_fina[0][7] = 4.836 / 45.149 ≈ 0.1071
softmax_fina[0][8] = 2.010 / 45.149 ≈ 0.0445
softmax_fina[0][9] = 6.8320 / 45.149 ≈ 0.1513
softmax_final = [
[0.1200, 0.0770, 0.0595, 0.1385, 0.0476, 0.1683, 0.0862, 0.1071, 0.0445, 0.1513], # 位置0(<bos>)
[0.1039, 0.1449, 0.0767, 0.0608, 0.1717, 0.0898, 0.0527, 0.1342, 0.0963, 0.0665], # 位置1(i)
[0.1551, 0.0727, 0.1170, 0.0456, 0.0860, 0.0437, 0.1024, 0.0651, 0.1308, 0.1816] # 位置2(love)
]
softmax_final[0]:表示<bos>之后需要生成的第一個詞,對應(yīng)“i”
softmax_final[1]:表示i之后需要生成的第二個詞,對應(yīng)“l(fā)ove”
softmax_final[2]:表示love之后需要生成的第三個詞,其概率最高的是softmax_final[2][9] = 0.1816。該位置映射的是詞匯表中的“you”
因此最終生成的詞是 you
大模型參數(shù)
之所以先說Transformer架構(gòu),再說大模型參數(shù)是因為要更為直觀的理解大模型參數(shù),還是得通過了解模型參數(shù)在架構(gòu)中具體是應(yīng)用在什么地方的。
大模型中的參數(shù)分為兩大類,模型參數(shù)和超參數(shù),其核心區(qū)別是,是否參與訓(xùn)練過程的梯度更新。
超參數(shù):指得是模型設(shè)計階段,由開發(fā)者設(shè)計固定值的參數(shù),例如Transformer架構(gòu)原文中堆疊的層數(shù)為6,位置編碼的周期范圍10000等
模型參數(shù):指得是模型在通過訓(xùn)練能不斷的自主優(yōu)化調(diào)整的參數(shù),例如多頭自注意力中的W_q、W_k、W_v、W_o權(quán)重矩陣?yán)锩娴膮?shù)等
模型超參數(shù)組成
- 1、詞匯表大?。╲ocab_size)
- 2、模型隱藏層維度(d_model)
- 3、堆疊層數(shù)(編碼器 N / 解碼器 N)
- 4、多頭注意力頭數(shù)(h)
- 5、前饋網(wǎng)絡(luò)隱藏層維度(d_ff)
- 6、輸入輸出最大序列長度(max_seq_len)
- 7、位置編碼周期范圍(如 10000)
- 8、Dropout 率(dropout_rate)
- 9、注意力縮放因子(√d_k)
- 10、批大?。╞atch_size)
- 11、學(xué)習(xí)率(learning_rate)
- 12、優(yōu)化器參數(shù)(如 Adam 的β1/β2)
- 13、訓(xùn)練輪數(shù)(epochs)。
由于本文是基于推理流程進(jìn)行Transformer架構(gòu)說明的,所以第10-13個參數(shù)沒有涉及到,這幾個參數(shù)是訓(xùn)練是會用到的超參數(shù),并且不同模型中會用的超參數(shù)會有所不同
模型參數(shù)組成(編碼器層 + 解碼器層)
編碼器層(共 N 層,每層獨(dú)立參數(shù)):
- 1、輸入嵌入層:嵌入矩陣Embedding,形狀[vocab_size, d_model]
- 2、多頭自注意力層:權(quán)重矩陣 W_q/W_k/W_v/W_o,形狀均為[d_model, d_model],可選偏置 bq/bk/bv/bo,形狀均為[d_model]
- 3、層歸一化:縮放因子γ、偏移因子β,形狀均為[d_model]
- 4、前饋網(wǎng)絡(luò)層:權(quán)重矩陣 W1[d_model, d_ff]、W2[d_ff, d_model],可選偏置 b1[d_ff]、b2[d_model])
- 5、歸一化層:縮放因子γ、偏移因子β,形狀均為[d_model])
解碼器層(共 N 層,每層獨(dú)立參數(shù))
- 1、輸入嵌入層:嵌入矩陣Embedding,與編碼器輸入嵌入層共享,形狀[vocab_size, d_model])
- 2、掩碼自注意力層:權(quán)重矩陣 W_q/W_k/W_v/W_o[d_model, d_model],可選偏置 bq/bk/bv/bo[d_model])
- 3、歸一化層:縮放因子γ、偏移因子β,形狀均為[d_model])
- 4、多頭自注意力層:權(quán)重矩陣 W_q/W_k/W_v/W_o[d_model, d_model],可選偏置 bq/bk/bv/bo[d_model])
- 5、歸一化層:縮放因子γ、偏移因子β,形狀均為[d_model])
- 6、前饋網(wǎng)絡(luò)層(FFN):權(quán)重矩陣W1[d_model, d_ff]、W2[d_ff, d_model],可選偏置 b1[d_ff]、b2[d_model])
- 7、歸一化層:縮放因子γ、偏移因子β,形狀均為[d_model])
- 8、輸出投影層:權(quán)重矩陣 W[d_model, vocab_size],與嵌入矩陣共享;可選偏置 b[vocab_size])
在Transformer原文《Attention Is All You Need》的注意力層中并沒有提及偏置參數(shù),
雖然目前所有主流大模型都是基于Transformer架構(gòu)而誕生的,但卻都在Transformer的基礎(chǔ)上做了非常大的改變,例如大部分主流的大模型目前都只有解碼器層了,而沒有了編碼器層,例如Deepseek和GPT。為了結(jié)合文章上下文,這里我以Transformer原文《Attention Is All You Need》中模型的參數(shù)來展示模型參數(shù)的計算過程
| 超參數(shù)類別 | 數(shù)值 |
|---|---|
| 詞匯表大?。╲ocab_size) | 32,768 |
| 編碼器層數(shù) | 6 |
| 解碼器層數(shù) | 6 |
| 每個 token 維度 | 512 |
| 位置編碼周期范圍 | 10000 |
| 分割頭數(shù) | 8 |
| 輸入輸出長度限制 | 512 |
| 前饋網(wǎng)絡(luò)維度 | 2048 |
編碼器層
嵌入矩陣層參數(shù)數(shù)量 :16777216, vocab_size x d_model = 32768 x 512
多頭自注意力層參數(shù)數(shù)量:1048576,權(quán)重矩陣 W_q/W_k/W_v/W_o 參數(shù)數(shù)量(3 x d_model x d_model = 3 x 512 x 512 = 786432)+ 投影參數(shù) ( d_model × d_model = 512 x 512 = 262144)
前饋網(wǎng)絡(luò)層參數(shù)數(shù)量:2097152,W1參數(shù)(d_model × d_ff = 512 x 2048 = 1048576)+W2參數(shù)(d_ff × d_model = 512 x 2048 = 1048576)
2次層歸一化:2048,2 x 2 x d_model
單層編碼器層參數(shù)總數(shù):3147776
所有編碼器參數(shù)總數(shù):18886656, 6 x 3147776
編碼器層參數(shù)總數(shù):35663872,嵌入矩陣層參數(shù)數(shù)量 + 所有編碼器參數(shù)總數(shù) = 16777216 + 18886656
解碼器層
嵌入矩陣參數(shù)數(shù)量:16777216
掩碼自注意力層:1048576
多頭自注意力層:1048576
前饋網(wǎng)絡(luò)層:2097152
3次歸一化層:3072
單層解碼器層參數(shù)總數(shù):4197376
所有解碼器層參數(shù)總數(shù):25184256,6 x 4197376
線性層線性輸出層參數(shù):d_model x V = 512 x 32768 = 16777216
解碼器層參數(shù)總數(shù):41961472,嵌入矩陣參數(shù)數(shù)量 + 所有解碼器層參數(shù)總數(shù)(由于解碼器層中嵌入矩陣參數(shù)數(shù)量與線性層線性輸出層參數(shù)是共享的權(quán)重矩陣,因此不需要重復(fù)相加)
Transformer總參數(shù) =0.0776B,77625344, 編碼器層參數(shù)總數(shù) + 解碼器層參數(shù)總數(shù) = 35663872 + 41961472
其他補(bǔ)充
什么是BPE
BPE分詞算法相對來說是比較簡單的,其本質(zhì)也是一個統(tǒng)計模型,核心是統(tǒng)計字詞頻率進(jìn)行的合并的貪心算法,一般是先將語料拆分為最小單位的字符集,去重形成初始的詞匯表,然后在語料中統(tǒng)計字符出現(xiàn)頻率,以及字符之間“相鄰字符對 / 子詞對”出現(xiàn)的頻率,當(dāng)頻率達(dá)到高頻條件后,將其合并為新的子詞并加入詞匯表,最后重復(fù)該過程直到達(dá)到預(yù)設(shè)詞匯表大小或迭代次數(shù),最終形成包含“字符”+“詞”組成的詞匯表。
從數(shù)據(jù)的角度來看 Transformer 中的Encoder(編碼器)和Decoder(解碼器)的依存關(guān)系
Transformer中Encoder與Decoder的依存關(guān)系,是Encoder產(chǎn)生的“語義理解數(shù)據(jù)”對Decoder“語義生成數(shù)據(jù)”的單向支撐關(guān)系:
Encoder是“數(shù)據(jù)理解端”:將輸入數(shù)據(jù)轉(zhuǎn)化為“可被 Decoder讀取的語義數(shù)據(jù)”,是整個架構(gòu)的“數(shù)據(jù)源頭”。
Decoder是“數(shù)據(jù)生成端”:以 Encoder的語義數(shù)據(jù)為約束,結(jié)合自身生成數(shù)據(jù),逐步產(chǎn)出目標(biāo)序列,是整個架構(gòu)的“數(shù)據(jù)出口”。
數(shù)據(jù)是二者連接的唯一橋梁:Encoder的輸出數(shù)據(jù)決定了Decoder生成的“語義邊界”,Decoder的生成過程是對 Encoder語義數(shù)據(jù)的“具象化表達(dá)”。
因為是單向支撐關(guān)系,并不是互相依賴關(guān)系,所以兩者并不是強(qiáng)依賴不可拆分的。
在自注意力和前饋網(wǎng)絡(luò)層中增加偏置參數(shù)的作用
偏置參數(shù)的核心作用是用于提升模型編碼器階段對原文的理解能力,解碼器階段對表達(dá)能力和自回歸上下文的適應(yīng)能力,能通過極小的參數(shù)量代價 (<1% 總參數(shù)) 帶來較大幅度的提升。
為何需要 Q、K、V 三個矩陣?只用 V 矩陣為何不可行?
自注意力機(jī)制的本質(zhì)是通過計算明確 token 之間的關(guān)聯(lián)性,就好比相親:首先,一方父母(當(dāng)前 token 的 Q)根據(jù)自家孩子的需求,去了解所有潛在對象的條件(其他 token 的 K),篩選出匹配度高的對象(Q x K^T 計算相似度)。匹配成功后,再通過約見深入了解對方的真實情況(比如性格、愛好,對應(yīng) V 里的核心語義信息),結(jié)合之前的匹配度,最終判斷是否合適。這就好比 Q、K、V:Q 是‘我的需求’,K 是‘對方的條件’,V 是‘對方的真實人設(shè)’,三者缺一不可。如果只用 V,就相當(dāng)于沒有父母篩選,盲目和所有人相親,既丟失了‘按需匹配’的能力,又導(dǎo)致效率極低、試錯成本極高,最終還不一定能找到滿意的對象(對應(yīng)注意力機(jī)制失效)。
為什么現(xiàn)在主流的大模型都采用純解碼器架構(gòu)?
1、任務(wù)適配:LLM 的核心任務(wù)是自回歸生成,一般用于續(xù)寫、對話、創(chuàng)作等,需要基于前文預(yù)測下一個 token,解碼器的掩碼自注意力層天然限制模型只能看到當(dāng)前及之前的 token,完全契合自回歸邏輯,所以純解碼器從架構(gòu)上更加適合這類任務(wù)。
2、數(shù)據(jù)效率:純解碼器僅需單序列文本數(shù)據(jù)即可訓(xùn)練,而編碼器 - 解碼器需要輸入+輸出成對數(shù)據(jù)來訓(xùn)練,從數(shù)據(jù)的獲取成本來看,純解碼器更便捷,效率更高
3、工程成熟度:純解碼器的訓(xùn)練 / 推理優(yōu)化更成熟,能支撐千億級參數(shù)規(guī)模,而編碼器 - 解碼器的雙結(jié)構(gòu)優(yōu)化更復(fù)雜
4、性能優(yōu)勢:純解碼器在長文本生成、語義連貫性上表現(xiàn)更優(yōu),而編碼器 - 解碼器更擅長序列轉(zhuǎn)換,更適合做文章內(nèi)容摘要、翻譯任務(wù),而非開放式生成任務(wù)。
目前幾乎所有主流大模型都是采用的純解碼器架構(gòu)
| 模型名稱 | 架構(gòu)類型 |
|---|---|
| Qwen系列 | 純解碼器架構(gòu) |
| Deepseek系列 | 純解碼器架構(gòu),從 GPT-1 到 GPT-4,全部采用純解碼器架構(gòu) |
| GPT系列 | 純解碼器架構(gòu) |
| Gemini系列 | 純解碼器架構(gòu) |
| Hunyuan系列 | 純解碼器架構(gòu) |
| PanguLM系列 | 純解碼器架構(gòu) |
| Doubao系列 | 純解碼器架構(gòu) |
| Claude系列 | 純解碼器架構(gòu) |
| Llama系列 | 純解碼器架構(gòu) |
| ERNIE系列 | 純解碼器架構(gòu),早起的1.0-3.0版本是純編碼器架構(gòu),用于專注于文本理解任務(wù),后續(xù)都采用的純解碼器架構(gòu) |
什么是張量?
張量的本質(zhì)是一個“帶維度的數(shù)值容器”,它通過固定的維度結(jié)構(gòu)組織數(shù)值,讓零散的單個數(shù)據(jù)形成有邏輯關(guān)聯(lián)的整體,其中維度結(jié)構(gòu)決定了數(shù)據(jù)的組織方式,數(shù)據(jù)數(shù)量是各維度長度的乘積。比如小王的單場考試分?jǐn)?shù)為“95分”,這里的“95分”就無需額外維度描述,是一個純粹的數(shù)值,是一個0維的張量。而我們用班級作為維度去統(tǒng)計,比如記錄一個班同學(xué)考試的分?jǐn)?shù),[90,85,95,78,88]這就是一個1維張量,這里的維度指的就是分?jǐn)?shù)。例如我們要形容2D地圖中的位置,我們可以用經(jīng)度和緯度兩個維度的數(shù)據(jù)來表示一個信息[116.4°E, 39.9°N],這就是2維張量。由此可見,維度越多,意味著描述數(shù)據(jù)所需的“參照維度”越多,數(shù)據(jù)間的關(guān)聯(lián)關(guān)系也越復(fù)雜,但張量的“大小”并非由維度數(shù)量決定,而是各維度長度的乘積決定。比如3維張量[2,3,4],其中2所在位置的維度是班級,因此這里2表示2班,3所在位置的維度表示小組個數(shù),3表示每個班級中有3個小組,4所在的位置的維度表示學(xué)生數(shù)量,4表示每個小組中有4個學(xué)生,因此共有24個學(xué)生也就是共有24個元素,而2維張量[10,10](10行10列的表格)共有100個元素,后者維度更少,但“大小”反而更大。維度數(shù)量影響的是計算的“復(fù)雜度”而非“規(guī)模”,因為高維張量的運(yùn)算需要兼顧每個維度的匹配關(guān)系。在大模型中一般都是一些高維結(jié)構(gòu)的向量數(shù)據(jù),例如文本內(nèi)容“[批量數(shù), 句子長度, 詞向量維度]”的3維張量(32個句子×128個詞×512維特征),處理圖像時,則是“[批量數(shù), 像素高度, 像素寬度, 顏色通道]”的4維張量(64張圖片×256×256像素×3個RGB通道)。這些高維結(jié)構(gòu)能完整保留數(shù)據(jù)的空間、時序或語義關(guān)聯(lián),是模型學(xué)習(xí)規(guī)律的基礎(chǔ)。
正因如此,張量的“一致性”至關(guān)重要。這里的“一致性”并非指所有張量完全相同,而是指參與計算的張量必須滿足“維度匹配規(guī)則”。如果批量計算時張量不一致,會直接導(dǎo)致兩種嚴(yán)重問題:
元素級運(yùn)算直接報錯:像模型中常見的“殘差連接”(特征輸出與原始輸入相加),要求兩個張量的維度和各維度長度完全一致。若一個是[32,128,512]的特征張量,另一個是[32,64,512]的輸入張量,就像“把3行數(shù)據(jù)和2行數(shù)據(jù)逐行相加”,對應(yīng)位置完全錯位,框架會直接拋出維度不匹配錯誤。
矩陣類運(yùn)算結(jié)果混亂:Transformer的注意力計算(如Q×K^T)要求“前一個張量的最后一維長度 = 后一個張量的倒數(shù)第二維長度”。若Q張量是[32,128,64],K張量誤設(shè)為[32,128,128],兩者無法正常相乘,要么運(yùn)算失敗,要么強(qiáng)行兼容后輸出毫無意義的數(shù)值,導(dǎo)致模型預(yù)測精度驟降甚至完全失效。
因此Transformer中,為避免這種問題,會通過“填充(Padding)”“裁剪(Truncation)”或“維度重塑(Reshape)”等操作確保一致性。比如批量輸入文本時,對短句子補(bǔ)0到統(tǒng)一長度,讓所有樣本的張量都符合[32,128,512]的標(biāo)準(zhǔn)形狀——這就像快遞運(yùn)輸前要將包裹整理成統(tǒng)一規(guī)格,才能高效分揀和傳送,張量的一致性正是模型高效、準(zhǔn)確計算的“物流標(biāo)準(zhǔn)”。
什么是大模型的涌現(xiàn)力?
大模型涌現(xiàn)力的本質(zhì)是:模型涌現(xiàn)出小模型所不具備的全新能力,在Transformer 架構(gòu)下,模型為了完成 “預(yù)測下一個詞” 的核心訓(xùn)練目標(biāo),通過超大參數(shù)規(guī)模承載更多知識、海量多領(lǐng)域數(shù)據(jù)覆蓋更全規(guī)律,最終涌現(xiàn)生成超出訓(xùn)練目標(biāo)的全新結(jié)果,例如模型可以根據(jù)因果關(guān)系,多維數(shù)據(jù)的融合分析輸出一個具有創(chuàng)新性的內(nèi)容,這種涌現(xiàn)能力是小模型完全不具備、且無法提前設(shè)計的全新能力。涌現(xiàn)力的前提是模型擁有“更好的理解能力”,因此需要更大規(guī)模的參數(shù),其次涌現(xiàn)力的體現(xiàn)是具備全新的能力,表現(xiàn)是生成“創(chuàng)新性內(nèi)容”,因此要給大模型訓(xùn)練超大規(guī)模的數(shù)據(jù)才能讓模型具備這樣突破臨界值的涌現(xiàn)力的表現(xiàn)。
模型的算力要求計算方式
一般在模型部署時我們主要考慮四類資源,GPU 顯存、算力、主機(jī)內(nèi)存、存儲。接下來我們以Transformer原文架構(gòu)模型進(jìn)行這四類資源需求計算,分為單次計算和并發(fā)100次來說明
一、單詞計算的資源需求計算
資源需求聚焦 “模型加載 + 單請求計算”,核心是顯存(GPU),算力決定推理速度。
- GPU 顯存(核心資源)
顯存消耗 = 模型參數(shù)顯存 + 運(yùn)行時顯存(中間激活值) + 輸入輸出顯存 + 20% 余量(部署預(yù)留)。
模型參數(shù)顯存(靜態(tài),僅加載一次):
公式:參數(shù)總數(shù) × 單參數(shù)字節(jié)數(shù) ÷ 10243(轉(zhuǎn)換為 GB)
計算:77,600,000 × 2(FP16) ÷ 10243 ≈ 155.2MB ≈ 0.145GB。
運(yùn)行時顯存(動態(tài),單請求中間計算結(jié)果):
公式:n_layer(編 / 解碼器層數(shù)) × d_model (模型維度)× max_seq_len(最大序列長度) × 2(FP16) ÷ 10243
計算:6×512×512×2 ÷ 10243 ≈ 3.14MB ≈ 0.003GB(77.6M 模型此部分可忽略)。
輸入輸出顯存(動態(tài),單請求 token Embedding):
公式:max_seq_len(輸出或輸入序列最大長度) × d_model (模型維度)× 2(FP16) ÷ 10243
計算:512×512×2 ÷ 10243 ≈ 0.5MB ≈ 0.0005GB。
總顯存(含 20% 余量):
(0.145+0.003+0.0005(輸出顯存)+0.0005(輸入顯存)) × 1.2 ≈ 0.178GB ≈ 0.18GB(FP16);
- GPU 算力(決定推理速度)
推理算力需求 = Transformer 推理 FLOPs(浮點(diǎn)運(yùn)算次數(shù)),核心公式為:推理 FLOPs = 2 × 參數(shù)總數(shù) × max_seq_len(Transformer 推理核心經(jīng)驗公式,2 倍對應(yīng)前向傳播的注意力 + 前饋網(wǎng)絡(luò)計算)。
算力數(shù)值:2×77,600,000×512 = 79,411,200,000 FLOPs = 79.41 TFLOPs(FP16)。
GPU 選型 & 耗時(與算力對應(yīng)):
推理耗時(秒)= 推理 FLOPs ÷ (GPU 峰值算力 × 算力利用率)
舉例:
入門級 GPU(NVIDIA T4,F(xiàn)P16 峰值 65 TFLOPs,利用率 70%):
耗時 = 79.41 ÷ (65×0.7) ≈1.74 秒;
國產(chǎn) GPU(平頭哥含光 800,F(xiàn)P16 峰值 128 TFLOPs,利用率 70%):
耗時 = 79.41 ÷ (128×0.7) ≈79.41 ÷ 89.6 ≈0.886 秒。
主機(jī)內(nèi)存(CPU 內(nèi)存)
主機(jī)內(nèi)存用于:加載模型配置、tokenizer 預(yù)處理 / 后處理(如巡檢文本分詞)、臨時數(shù)據(jù)存儲。
公式:主機(jī)內(nèi)存需求 = 模型參數(shù)顯存 × 3(預(yù)留數(shù)據(jù)處理空間)。
計算:0.145×3≈0.435GB,實際部署預(yù)留余大概≈1GB 即可。存儲(磁盤 / SSD)
存儲用于保存:模型權(quán)重文件、配置文件(json)、詞表文件(txt)等。
公式:存儲需求 = 模型參數(shù)文件大小 + 配置 / 詞表文件大?。ā?00MB)。
計算:
1、模型參數(shù)文件(FP16):77.6M(模型參數(shù)大?。?(FP16)=155.2MB
2、輔助文件大?。涸~表文件+配置文件+適配文件+校準(zhǔn) / 示例文件+余量預(yù)留≈100MB
總存儲:155.2MB + 100MB≈255MB≈0.25GB。
二、并行執(zhí)行100計算量時的資源需求計算
核心邏輯是 “模型參數(shù)顯存共享,運(yùn)行時 / 輸入輸出顯存按并行數(shù)線性增加”,在加深并行是需要的額外開銷(5%-10%)。
GPU 顯存(單卡并行)
關(guān)鍵:模型參數(shù)顯存只需加載 1 次(共享),運(yùn)行時 / 輸入輸出顯存每條請求獨(dú)立。
公式:總顯存 = (模型參數(shù)顯存 + 運(yùn)行時顯存 ×100 + 輸入輸出顯存 ×100) × 1.1(10% 并行開銷)。
計算(FP16):(0.145 + 0.003×100 + 0.0005×100) ×1.1 = (0.145+0.3+0.05)×1.1≈0.545GB≈0.55GB
若用多卡并行(如 2 卡,每卡 50 條):每卡顯存 = (0.145 + 0.003×50 + 0.0005×50)×1.1≈0.35GB,2 卡總顯存≈0.7GB。GPU 算力
公式:總推理 FLOPs = 單次FLOPs × 并行數(shù),推理耗時≈單次耗時 × 1.1(并行開銷)。
計算:
總算力:79.41 TFLOPs ×100=7941 TFLOPs=7.94 PFLOPs
耗時(NVIDIA T4):1.74×1.1≈1.91 秒(吞吐量≈100/1.91≈52 條 / 秒),一般為了體現(xiàn)推理的實時性,耗時要小于1秒主機(jī)內(nèi)存
需支撐 100 條請求的預(yù)處理 / 后處理
公式:主機(jī)內(nèi)存 = 單條主機(jī)內(nèi)存 × 并行數(shù) ×1.2(批量開銷)。
計算:1GB×100×1.2=120GB
若分批次處理(如每批 20 條),可優(yōu)化至≈20GB。存儲
存儲需求與并行數(shù)無關(guān)(模型文件只需保存 1 份),仍≈0.25GB(FP16)。
什么是向量庫,向量庫與大模型的關(guān)系?
向量數(shù)據(jù)庫是專門用于存儲、索引、檢索高維向量的數(shù)據(jù)庫,其核心是提供通過語義相似性去匹配內(nèi)容。傳統(tǒng)的數(shù)據(jù)庫是用來存儲結(jié)構(gòu)化數(shù)據(jù),并通過關(guān)鍵詞去做精準(zhǔn)或模糊匹配,這樣的搜索并不具備對搜索內(nèi)容從語義以及特征的匹配,例如搜索“生孩子可以領(lǐng)哪些補(bǔ)貼”,那么答案中必須有“生孩子可以領(lǐng)哪些補(bǔ)貼”這樣的話在才會匹配,而向量數(shù)據(jù)庫是聚焦存儲大模型處理的非結(jié)構(gòu)化數(shù)據(jù)時生成的高維數(shù)值序列即向量,這類向量通過數(shù)值維度的特征分布與表征數(shù)據(jù)的語義或特征,可以搜索例如 “占道經(jīng)營” 時匹配“違規(guī)擺攤” 等向量相似度極高的內(nèi)容,而不僅限于關(guān)鍵字匹配。其中最典型的落地場景是 RAG(檢索增強(qiáng)生成)工程:
1、其首先將知識庫中的文檔切分為片段,通過與大模型配套的編碼器嵌入模型轉(zhuǎn)為向量,存入向量庫并構(gòu)建專用索引
2、接著當(dāng)用戶提出問題時,先將問題文本通過同一嵌入模型轉(zhuǎn)為向量
3、然后通過向量數(shù)據(jù)庫基于 “語義相似度” 快速檢索出與問題向量最匹配的知識庫片段向量,并還原為對應(yīng)的文本片段
4、最后大模型結(jié)合檢索到的知識庫片段(增量知識)與自身的參數(shù)記憶(固有知識),生成貼合用戶訴求且信息準(zhǔn)確的回答文本
這類檢索生成的回答,是大模型融合語義特征匹配的增量知識與自身訓(xùn)練固化的知識所得,而非傳統(tǒng)數(shù)據(jù)庫通過關(guān)鍵詞匹配得到的固化答案,或僅通過大模型自主生成的過時知識或幻覺答案。


