一個空間兩個wordpress湖北短視頻搜索seo
Llama 2 是預(yù)訓(xùn)練和微調(diào)的LLM系列,Llama 2 和 Llama 2-Chat 模型的參數(shù)規(guī)模達到 70B。Llama 2-Chat 模型專門為對話場景進行了優(yōu)化。
這是一個系列的文章,會分別從LLAMA2的預(yù)訓(xùn)練,微調(diào),安全性等方面進行講解。
1.數(shù)據(jù)來源
- 數(shù)據(jù)集:LLaMA 2 的訓(xùn)練數(shù)據(jù)來源于公開可用的數(shù)據(jù)集,并未使用來自 Meta 產(chǎn)品或服務(wù)的數(shù)據(jù)。為了避免隱私泄露,數(shù)據(jù)集中剔除了來自某些網(wǎng)站的高風(fēng)險個人信息。
- 數(shù)據(jù)量:模型共預(yù)訓(xùn)練了 2 萬億個 token,比 LLaMA 1 增加了約 40%。同時,數(shù)據(jù)集上調(diào)了最具事實性的來源,以提升模型知識儲備,減少幻覺(hallucination)的發(fā)生。
- 去重和清洗:數(shù)據(jù)經(jīng)過了更嚴格的清洗和去重處理,旨在提供更干凈且更具代表性的數(shù)據(jù)集。
2.訓(xùn)練細節(jié)
模型架構(gòu)
LLaMA 2 使用了標準的 Transformer 架構(gòu)(Vaswani et al., 2017),并基于 LLaMA 1 進行了優(yōu)化,包括使用預(yù)歸一化(pre-normalization)RMSNorm、SwiGLU 激活函數(shù)(Shazeer, 2020)以及旋轉(zhuǎn)位置嵌入(RoPE, Su et al. 2022)。這些優(yōu)化提升了模型處理長上下文的能力。
(1) 基礎(chǔ)架構(gòu)
- LLaMA 2 使用的是自回歸語言模型(Auto-regressive Language Model),這意味著模型是通過預(yù)測每個詞在給定上下文中的下一個詞來進行訓(xùn)練的。
- 標準的 Transformer 架構(gòu):模型使用經(jīng)典的 Transformer 架構(gòu) ,最初由 Vaswani 等人提出,這是一種基于自注意力機制的架構(gòu),能夠處理長距離依賴關(guān)系并捕捉句子中的語義結(jié)構(gòu)。
- 歸一化層:LLaMA 2 采用了預(yù)歸一化策略(Pre-normalization),具體使用了 RMSNorm 來替代傳統(tǒng)的 LayerNorm。這使得模型的訓(xùn)練更為穩(wěn)定,尤其是在處理深層網(wǎng)絡(luò)時。
(2) 改進的激活函數(shù)
LLaMA 2 使用了 SwiGLU 激活函數(shù),而不是傳統(tǒng)的 ReLU 或 GeLU。SwiGLU 是一種更復(fù)雜的非線性激活函數(shù),能夠提高模型的表現(xiàn),特別是在大規(guī)模模型中 。
為什么要使用SwiGLU激活函數(shù)?
SwiGLU 的公式如下:
S w i G L U ( x ) = ( L i n e a r ( x ) ? S i L U ( L i n e a r ( x ) ) ) SwiGLU(x)=(Linear(x)?SiLU(Linear(x))) SwiGLU(x)=(Linear(x)?SiLU(Linear(x)))
其中,SiLU(Sigmoid Linear Unit)是一個常用的非線性激活函數(shù),定義為:
S i L U ( x ) = x ? σ ( x ) SiLU(x)=x?σ(x) SiLU(x)=x?σ(x)
其中 σ ( x ) σ(x) σ(x) 是 Sigmoid 函數(shù) 1 1 + e ? x \frac{1}{1+e^{?x}} 1+e?x1?
因此,SwiGLU 實際上是對輸入進行了兩次線性變換,并通過 SiLU 將兩個結(jié)果結(jié)合起來,這種組合使得模型可以捕獲更豐富的特征表示。
-
SwiGLU有更高的表達能力
SwiGLU 通過雙線性變換和 SiLU 非線性結(jié)合,提供了更強的表達能力。具體體現(xiàn)在:
- 非線性表現(xiàn)更強:SwiGLU 在輸入空間上提供了更復(fù)雜的非線性映射,能夠捕獲數(shù)據(jù)中更加復(fù)雜的模式。相比于傳統(tǒng)的 ReLU,它避免了“梯度消失”或“梯度爆炸”的問題,同時也比 GeLU 更能靈活地處理不同輸入。
- 激活函數(shù)的平滑性:SiLU 是一種平滑的激活函數(shù),這意味著它在小輸入值附近表現(xiàn)平穩(wěn),輸出變化相對緩和。與 ReLU 不同,SiLU 不會像 ReLU 那樣在負數(shù)部分輸出恒為零,這有助于模型更好地處理負值輸入,從而提高訓(xùn)練穩(wěn)定性。
-
計算效率更高
雖然 SwiGLU 包含了兩次線性變換,但由于它與 SiLU 激活函數(shù)結(jié)合,SwiGLU 可以充分利用并行計算硬件(如 GPU 和 TPU)來高效執(zhí)行。因此,它相比于一些復(fù)雜的非線性函數(shù)(如 ReLU 或 Tanh)在計算開銷上并沒有顯著增加,同時提升了模型的性能。
-
更好的梯度流動
SwiGLU 結(jié)合了 SiLU 的平滑性和雙線性變換的組合,使得它能夠在梯度反向傳播時提供更好的梯度流動,這尤其在深層網(wǎng)絡(luò)中表現(xiàn)出色。在 LLaMA 2 這樣的大規(guī)模 Transformer 模型中,模型層數(shù)很多,使用 SwiGLU 可以有效地緩解梯度消失問題,確保模型能夠在訓(xùn)練過程中更好地學(xué)習(xí)到深層次的特征。
(3)位置嵌入
? 旋轉(zhuǎn)位置嵌入(RoPE):LLaMA 2 使用了旋轉(zhuǎn)位置嵌入(Rotary Positional Embeddings, RoPE),這是一種改進的相對位置編碼方式,能夠處理更長的上下文信息,并提高模型在長文本上的性能 。
-
位置編碼的重要性
Transformer 模型本質(zhì)上是不具備順序感的,因為它們并沒有卷積或遞歸結(jié)構(gòu),而是通過自注意力機制(Self-Attention)在序列中的所有詞之間計算注意力權(quán)重。因此,在處理語言任務(wù)時,必須顯式地告訴模型每個詞在序列中的位置,以便模型能夠理解句子中的詞序。
傳統(tǒng)的 Transformer 使用絕對位置編碼(Absolute Positional Encoding),這意味著每個位置(token)的信息是通過一個固定的向量表示,該向量在訓(xùn)練開始時被注入到輸入中。然而,絕對位置編碼無法很好地建模詞與詞之間的相對位置關(guān)系,特別是當序列長度增加時,絕對位置編碼的表現(xiàn)會下降。
-
RoPE的核心思想
旋轉(zhuǎn)位置嵌入(RoPE) 通過引入旋轉(zhuǎn)操作來嵌入相對位置信息。它通過對輸入的查詢和鍵(Query 和 Key)向量進行逐元素的旋轉(zhuǎn)變換,將位置信息嵌入到自注意力機制的計算中,從而保留了序列中詞之間的相對位置。
RoPE 的核心思想是將每個 token 的查詢和鍵向量按照其位置進行旋轉(zhuǎn),而這種旋轉(zhuǎn)是連續(xù)的,能夠保持詞與詞之間的相對距離信息。這意味著,相比于絕對位置編碼,RoPE 不需要依賴固定的位置編碼表格,而是通過對向量進行旋轉(zhuǎn)操作來隱式地表示相對位置。
RoPE 的數(shù)學(xué)定義如下:
旋轉(zhuǎn)變換
給定二維向量 [ x 1 , x 2 ] [x1,x2] [x1,x2],我們可以定義它的旋轉(zhuǎn)變換為:
[ x 1 ′ x 2 ′ ] = [ cos ? ( θ ) ? sin ? ( θ ) sin ? ( θ ) cos ? ( θ ) ] [ x 1 x 2 ] \begin{bmatrix} x'_1 \\ x'_2 \end{bmatrix} =\begin{bmatrix} \cos(\theta) & -\sin(\theta) \\ \sin(\theta) & \cos(\theta) \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} [x1′?x2′??]=[cos(θ)sin(θ)??sin(θ)cos(θ)?][x1?x2??]
在 RoPE 中,這種旋轉(zhuǎn)操作會應(yīng)用到高維向量的每對相鄰維度上(如第 1 維和第 2 維,第 3 維和第 4 維),每對維度的旋轉(zhuǎn)角度由位置和頻率確定。具體來說,RoPE 對每個位置 ppp 以逐維不同的頻率來進行旋轉(zhuǎn)變換,確保較低維度捕捉較短距離的依賴,較高維度捕捉較長距離的依賴。
相對位置優(yōu)勢
這種基于旋轉(zhuǎn)的位置編碼能夠隱式地表示相對位置。RoPE 的一個關(guān)鍵優(yōu)勢在于,經(jīng)過旋轉(zhuǎn)編碼后,兩個位置 p p p 和 p + k p+k p+k 的旋轉(zhuǎn)向量之間的差異只取決于相對位置 k k k,而不是絕對位置。這意味著即使文本序列長度增加,RoPE 也能保持相對位置的關(guān)系,使其更具泛化能力,特別是在長文本處理上表現(xiàn)優(yōu)異。
-
RoPE的具體實現(xiàn)步驟
RoPE 的實現(xiàn)涉及以下幾個步驟:
- 輸入處理:輸入的查詢向量 q q q 和鍵向量 k 是沒有位置信息的高維向量。
- 位置嵌入:對每個位置 p p p 的查詢和鍵向量,按照位置 p p p 對查詢 q q q 和鍵 k k k 的偶數(shù)維和奇數(shù)維進行不同的旋轉(zhuǎn)嵌入。
- 自注意力機制計算:經(jīng)過旋轉(zhuǎn)嵌入后,查詢和鍵向量會進入自注意力機制進行打分計算,這個過程中,自然地引入了位置相關(guān)性和相對位置偏置。
- 輸出生成:自注意力機制根據(jù)注意力權(quán)重生成新的向量表示,傳遞到后續(xù)的 Transformer 層。
-
RoPE 相比傳統(tǒng)位置編碼的優(yōu)勢
1. 處理長序列的能力
RoPE 的設(shè)計使其可以擴展到更長的序列而不會丟失位置信息。傳統(tǒng)的絕對位置編碼在序列長度超過訓(xùn)練時的長度后,模型的表現(xiàn)會顯著下降,因為位置編碼無法很好地泛化。而 RoPE 通過旋轉(zhuǎn)方式嵌入相對位置,具備良好的泛化能力,適用于長序列文本處理。
2. 相對位置建模
RoPE 的另一個顯著優(yōu)勢是相對位置編碼。對于許多 NLP 任務(wù),詞與詞之間的相對距離往往比絕對位置更為重要。例如,在機器翻譯或長文本生成任務(wù)中,模型必須理解詞語之間的相對關(guān)系,而不僅僅是它們的固定位置。
3. 計算效率
RoPE 的旋轉(zhuǎn)計算相對簡單,能夠高效地并行化計算。相較于需要額外層次處理的相對位置編碼方案(如 Transformer-XL 中的相對位置編碼),RoPE 在引入相對位置偏置的同時,保持了自注意力機制的計算效率。
-
具體使用例子
給定一個查詢向量 qqq 或鍵向量 kkk,我們通過以下旋轉(zhuǎn)公式將位置信息嵌入:
RoPE ( q 2 i , q 2 i + 1 ) = [ cos ? ( θ p ) ? sin ? ( θ p ) sin ? ( θ p ) cos ? ( θ p ) ] [ q 2 i q 2 i + 1 ] \text{RoPE}(q_{2i}, q_{2i+1}) = \begin{bmatrix} \cos(\theta_p) & -\sin(\theta_p) \\ \sin(\theta_p) & \cos(\theta_p) \end{bmatrix} \begin{bmatrix} q_{2i} \\ q_{2i+1} \end{bmatrix} RoPE(q2i?,q2i+1?)=[cos(θp?)sin(θp?)??sin(θp?)cos(θp?)?][q2i?q2i+1??]
這里:- q 2 i q_{2i} q2i?和 q 2 i + 1 q_{2i+1} q2i+1?分別是查詢向量 q q q 的第 2 i 2i 2i 和第 2 i + 1 2i+1 2i+1 維。
- θ p = p ? θ \theta_{p}=p·\theta θp?=p?θ是與位置 p p p 相關(guān)的旋轉(zhuǎn)角度,通常設(shè)定為與維度相關(guān)的常數(shù)(如 θ = 1000 0 ? 2 i d \theta=10000^{\frac{-2i}vxwlu0yf4} θ=10000d?2i?,其中 d d d是查詢向量的維度)
- 這個變換將每對相鄰維度 ( 2 i , 2 i + 1 ) (2i,2i+1) (2i,2i+1)旋轉(zhuǎn)一個與位置 p p p 相關(guān)的角度。
注意力機制的改進
引入了分組查詢注意力機制(Grouped-Query Attention, GQA),特別是用于處理參數(shù)規(guī)模較大的模型(例如 34B 和 70B)。這一改進提升了推理的可擴展性,降低了注意力計算時的內(nèi)存消耗。
查詢注意力機制(Grouped-Query Attention, GQA) 是 LLaMA 2 模型中引入的一種優(yōu)化注意力計算的機制,特別是在處理大規(guī)模模型(如 34B 和 70B 參數(shù)模型)時,GQA 大幅減少了注意力計算的內(nèi)存開銷,并提高了模型的推理效率。
為了理解 GQA,首先需要了解傳統(tǒng)的多頭自注意力機制(Multi-Head Self-Attention, MHA),然后我們會介紹 GQA 是如何改進 MHA 的。
回顧多頭自注意力機制(MHA)
在傳統(tǒng)的多頭自注意力機制中,自注意力計算分為多個“頭”(attention heads)。每個注意力頭會為輸入序列生成查詢(Query, Q)、鍵(Key, K)和值(Value, V),并分別進行自注意力計算。具體流程如下:
-
線性投影:每個輸入向量(token embedding)會通過線性投影生成對應(yīng)的 Q、K、V 向量。這意味著每個注意力頭有自己獨立的線性投影矩陣。
-
注意力計算:每個頭都會獨立地進行注意力計算,計算公式如下:
Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q, K, V) = \text{softmax}\left( \frac{QK^T}{\sqrt{d_k}} \right) V Attention(Q,K,V)=softmax(dk??QKT?)V
其中 Q Q Q 是查詢, K K K 是鍵, V V V 是值, d k d_k dk? 是鍵向量的維度。 -
多頭組合:所有注意力頭的輸出會被拼接起來,經(jīng)過一個線性變換后,生成最后的輸出。
傳統(tǒng)的 MHA 通過引入多個注意力頭,允許模型在不同的子空間中學(xué)習(xí)不同的注意力模式。然而,MHA 的一個缺點是,當模型參數(shù)增加時(如 34B 或 70B 參數(shù)模型),每個頭都有獨立的 Q、K、V 線性投影矩陣,這會顯著增加內(nèi)存和計算開銷。
傳統(tǒng)多頭注意力機制的代碼:
import torch
import torch.nn as nn
import torch.nn.functional as Fclass MultiHeadSelfAttention(nn.Module):def __init__(self, embed_size, num_heads):super(MultiHeadSelfAttention, self).__init__()self.embed_size = embed_sizeself.num_heads = num_headsself.head_dim = embed_size // num_headsassert self.head_dim * num_heads == embed_size, "Embedding size needs to be divisible by heads"# 為每個頭獨立生成 Q、K、Vself.query = nn.Linear(embed_size, embed_size, bias=False)self.key = nn.Linear(embed_size, embed_size, bias=False)self.value = nn.Linear(embed_size, embed_size, bias=False)# 最后的全連接層self.fc_out = nn.Linear(embed_size, embed_size)def forward(self, values, keys, query, mask):N = query.shape[0]value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]# 對每個輸入進行線性變換得到 Q、K、Vqueries = self.query(query)keys = self.key(keys)values = self.value(values)# 將維度 (N, seq_length, embed_size) -> (N, num_heads, seq_length, head_dim)queries = queries.view(N, query_len, self.num_heads, self.head_dim).transpose(1, 2)keys = keys.view(N, key_len, self.num_heads, self.head_dim).transpose(1, 2)values = values.view(N, value_len, self.num_heads, self.head_dim).transpose(1, 2)# 注意力得分計算: QK^T / sqrt(d_k)energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])if mask is not None:energy = energy.masked_fill(mask == 0, float("-1e20"))attention = torch.softmax(energy / (self.head_dim ** (1 / 2)), dim=3)# 使用注意力權(quán)重加權(quán) Vout = torch.einsum("nhql,nlhd->nqhd", [attention, values]).reshape(N, query_len, self.embed_size)return self.fc_out(out)
查詢注意力機制(Grouped-Query Attention, GQA)
Grouped-Query Attention (GQA) 通過對查詢(Q)的投影進行分組優(yōu)化,大幅減少了計算和內(nèi)存的使用。具體來說,GQA 保留了多個注意力頭的設(shè)計,但共享查詢的投影矩陣,而不是為每個頭都獨立投影查詢向量。GQA 的核心思想是將多個注意力頭分成幾組,每組內(nèi)的所有注意力頭共享同一個查詢投影矩陣。
GQA 的主要改進點:
共享查詢投影:在 GQA 中,多個注意力頭會共享一個查詢投影矩陣,而不再為每個頭都單獨分配一個查詢投影矩陣。這樣減少了查詢投影的計算復(fù)雜度和內(nèi)存需求。
- 例如,如果有 64 個注意力頭,GQA 可能將這些頭分為 4 組,每組 16 個頭。組內(nèi)的所有 16 個頭共享同一個查詢投影矩陣,而鍵和值仍然各自獨立。
保持多頭注意力的靈活性:盡管查詢投影被分組共享,鍵(K)和值(V)的投影仍然是獨立的。這意味著每個注意力頭仍然可以在不同的子空間中捕捉不同的注意力模式,而不會喪失多頭注意力機制的多樣性。
GQA 的工作原理
查詢投影分組:多個注意力頭被分成幾組(例如每組 8 或 16 個頭),組內(nèi)的所有注意力頭共享同一個查詢投影矩陣。這減少了模型中查詢投影的總量。
鍵和值的獨立投影:每個頭仍然會獨立生成鍵和值向量,從而保留每個頭獨立關(guān)注不同信息的能力。
自注意力計算:GQA 使用共享的查詢投影矩陣來計算查詢向量 QQQ,然后與獨立的鍵和值一起進行標準的自注意力計算。盡管查詢投影被共享,但每個頭的鍵和值是不同的,因此每個頭的注意力分數(shù)仍然可以有自己的模式。
多頭組合:與傳統(tǒng) MHA 類似,所有注意力頭的輸出會被拼接起來,經(jīng)過線性變換后生成最終的輸出。
GQA 的優(yōu)點
相比于傳統(tǒng)的 MHA,GQA 在大規(guī)模模型中具有以下幾個顯著優(yōu)點:
1. 減少內(nèi)存占用
- 由于查詢投影矩陣被分組共享,GQA 顯著減少了查詢投影矩陣的總量。這在處理大規(guī)模模型(如 LLaMA 2 的 34B 和 70B 參數(shù)模型)時,能有效降低內(nèi)存占用。
2. 提高推理效率
- 通過減少查詢投影的計算,GQA 可以加速推理過程,尤其是在大型模型中。傳統(tǒng)的 MHA 隨著注意力頭的增加,計算量線性增長,而 GQA 通過共享查詢投影減少了計算量,提升了推理效率。
3. 更好的可擴展性
- GQA 尤其適用于大規(guī)模模型。在大模型中,MHA 的計算和內(nèi)存瓶頸會變得更加明顯,而 GQA 通過減少查詢的獨立投影,可以更好地擴展模型參數(shù),同時保持較高的計算效率。
4. 保持多頭的靈活性
- 盡管 GQA 共享了查詢的投影,但仍然保留了多頭注意力機制的多樣性。每個頭的鍵和值投影仍然是獨立的,因此 GQA 不會犧牲模型在不同子空間中學(xué)習(xí)不同模式的能力。
查詢注意力機制(GQA)的代碼
class GroupedQueryAttention(nn.Module):def __init__(self, embed_size, num_heads, num_groups):super(GroupedQueryAttention, self).__init__()self.embed_size = embed_sizeself.num_heads = num_headsself.num_groups = num_groups # 分組數(shù)self.head_dim = embed_size // num_headsassert self.head_dim * num_heads == embed_size, "Embedding size needs to be divisible by heads"assert num_heads % num_groups == 0, "Number of heads must be divisible by the number of groups"# 共享查詢的投影矩陣self.shared_query = nn.Linear(embed_size, embed_size // num_groups, bias=False) # 每組共享# 為每個頭單獨生成 K 和 Vself.key = nn.Linear(embed_size, embed_size, bias=False)self.value = nn.Linear(embed_size, embed_size, bias=False)# 最后的全連接層self.fc_out = nn.Linear(embed_size, embed_size)def forward(self, values, keys, query, mask):N = query.shape[0]value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]# 為每個頭生成 K 和 Vkeys = self.key(keys)values = self.value(values)# 將每組內(nèi)的所有頭共享查詢投影矩陣queries = []group_size = self.num_heads // self.num_groupsfor i in range(self.num_groups):# 對查詢進行分組計算q = self.shared_query(query)q = q.repeat(1, 1, group_size) # 共享矩陣復(fù)制給組內(nèi)的所有頭queries.append(q)queries = torch.cat(queries, dim=-1) # 將分組后的 Q 拼接起來# 調(diào)整維度以適應(yīng)注意力計算: (N, seq_length, embed_size) -> (N, num_heads, seq_length, head_dim)queries = queries.view(N, query_len, self.num_heads, self.head_dim).transpose(1, 2)keys = keys.view(N, key_len, self.num_heads, self.head_dim).transpose(1, 2)values = values.view(N, value_len, self.num_heads, self.head_dim).transpose(1, 2)# 注意力得分計算: QK^T / sqrt(d_k)energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])if mask is not None:energy = energy.masked_fill(mask == 0, float("-1e20"))attention = torch.softmax(energy / (self.head_dim ** (1 / 2)), dim=3)# 使用注意力權(quán)重加權(quán) Vout = torch.einsum("nhql,nlhd->nqhd", [attention, values]).reshape(N, query_len, self.embed_size)return self.fc_out(out)
代碼解釋:
energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])
該行代碼使用了 torch.einsum
來計算注意力得分矩陣,其中 queries
和 keys
是多頭自注意力機制中的查詢和鍵張量。
queries
和 keys
的形狀為 (N, S, num_heads, head_dim)
,經(jīng)過變換,當前它們的形狀為:
queries
:(N, query_len, num_heads, head_dim)
,即nqhd:
N
:批次大小(batch size)
q
:查詢序列長度(query length)
h
:注意力頭的數(shù)量(number of heads)
d
:每個頭的嵌入維度(embedding size per head)
keys`:`(N, key_len, num_heads, head_dim)`,即 `nkhd
N
:批次大小k
:鍵的序列長度(key length)h
:注意力頭的數(shù)量d
:每個頭的嵌入維度
愛因斯坦求和約定
torch.einsum
使用字符串形式的愛因斯坦求和約定,"nqhd,nkhd->nhqk"
,用來描述張量的運算規(guī)則。這個規(guī)則可以分為幾個部分:
-
輸入部分
"nqhd,nkhd"
描述了輸入張量的維度:
queries
的維度是nqhd
,即(N, query_len, num_heads, head_dim)
。keys
的維度是nkhd
,即(N, key_len, num_heads, head_dim)
。
-
輸出部分
"nhqk"
描述了輸出張量的維度:
n
:批次大小。h
:注意力頭的數(shù)量。q
:查詢序列長度。k
:鍵序列長度。
在這個表達式中,d
(head_dim,嵌入維度)被省略掉了,因為 d
是被求和維度。torch.einsum
將在 d
維上進行內(nèi)積操作,然后輸出 (N, num_heads, query_len, key_len)
形狀的張量。
注意力得分矩陣
這一步的結(jié)果 energy
是一個形狀為 (N, num_heads, query_len, key_len)
的張量,它包含每個注意力頭中每個查詢位置與所有鍵位置之間的點積結(jié)果。該點積值表示查詢和鍵之間的相似度,也就是注意力機制中的原始得分。
接下來,通常會對這個 energy
張量進行 softmax 歸一化,以計算注意力權(quán)重,從而決定每個查詢應(yīng)該重點關(guān)注哪些鍵值。
傳統(tǒng)多頭自注意力機制(MHA)與 GQA 的區(qū)別
特性 | 傳統(tǒng)多頭自注意力機制(MHA) | 查詢注意力機制(GQA) |
---|---|---|
查詢(Q)投影矩陣 | 每個注意力頭都有獨立的查詢投影矩陣 | 查詢投影矩陣在分組內(nèi)的所有頭中共享,減少了查詢投影的計算量 |
鍵(K)和值(V)投影矩陣 | 每個頭有獨立的鍵和值投影矩陣 | 每個頭仍然有獨立的鍵和值投影矩陣,保持注意力頭的靈活性 |
內(nèi)存需求 | 隨著注意力頭的數(shù)量線性增加 | 通過共享查詢投影減少內(nèi)存占用 |
計算效率 | 當注意力頭數(shù)較多時,計算復(fù)雜度和內(nèi)存開銷大 | 通過共享查詢投影,計算效率更高,尤其是在大模型中 |
靈活性 | 每個頭都有獨立的查詢投影,因此具有較大的靈活性 | 查詢投影共享在一定程度上減少了靈活性,但仍保持鍵和值的獨立性 |
上下文長度
LLaMA 2 將上下文長度從 2048 token 增加到 4096 token,這使模型能夠處理更長的文本段落,特別是在對話場景和長文本總結(jié)中表現(xiàn)更好。
3.訓(xùn)練超參數(shù)
- 使用了 AdamW 優(yōu)化器,參數(shù)為 β1=0.9、β2=0.95,學(xué)習(xí)率使用余弦衰減調(diào)度,初始預(yù)熱 2000 步,最終學(xué)習(xí)率衰減至峰值的 10%。模型使用了權(quán)重衰減(weight decay)0.1 和梯度裁剪(gradient clipping)1.0。
- 訓(xùn)練時長和資源:為了減少訓(xùn)練時間,LLaMA 2 采用了 Meta 的研究超級計算集群(RSC),并使用 NVIDIA A100 GPUs。每個 GPU 的功率限制為 350-400W,總共花費 330 萬 GPU 小時 進行預(yù)訓(xùn)練,碳排放總計 539 噸 CO2,100% 通過 Meta 的可持續(xù)性計劃進行了抵消 。
4.優(yōu)化點
更強的泛化能力:LLaMA 2 的設(shè)計在處理長上下文、減少幻覺、提升模型推理速度和內(nèi)存效率等方面做了大量優(yōu)化。這些優(yōu)化使得模型在對話生成、文本總結(jié)等任務(wù)中表現(xiàn)優(yōu)異,特別是在需要保持上下文一致性的場景下效果更好。