llama3簡介
llama3 是meta 2024年4月18日釋出的開源的大語言模型, 釋出當時是state-of-art(最牛逼)的開源LLM,下圖是llama3和其他主流模型評測對比:
llama3官方釋出了兩個模型的引數:8B和70B(B代表Billion, 10億),以及釋出了用於推理的原始碼,官方github地址:https://github.com/meta-llama/llama3
下載程式碼後,我們主要講解8B模型, 其中model.py就是模型的核心程式碼,generation.py是推理程式碼(我們把模型接收使用者輸入, 然後吐出輸出的計算過程叫做推理:inference)。 接下來上乾貨, 跟著作者一步一步來拆解這個模型。
llama3主體介紹
llama3主要的技術框架為Transformer, 具體是decode-only transformer, 主體框架和GPT-2差不多.
generation.py的class Llama的build方法來建立model
model = Transformer(model_args)
Transformer是model.py裡的Transformer類
model_args是模型引數:
-
max_seq_len: 最大序列長度, 這個長度是推理計算中最長的token長度,後面還會講到這個長度
-
max_batch_size:最大一批大小,模型一次處理多少次推理(這個可有講, 以後有機會再講)
-
vocab_size : token 表大小
模型接受使用者輸入, 該輸入稱為prompt(中文為提示,大家知道為什麼將大模型使用者叫做提示工程師嗎🤣)
tokenizer
首先使用tokenizer, 把輸入分割成一個一個token, token並不是和字或者字母一對一對應,有可能是幾個單詞對應一個token,有可能一個字拆分為幾個token,為什麼要分割以及根據什麼依據來分割, 大家可以問下chatGPT
llama3使用了自己的tokenizer, 每個LLM都會自己的tokenizer.
然後模型根據輸入來推理, 然後輸出一個token,然後再把輸出的token, 拼接到輸入後面, 再計算下一個token. 直到遇到代表輸出停止的符號(
所以LLM又叫做自迴歸模型(Auto Regression Model). 那你想問為什麼使用者問LLM問題, LLM能夠回答問題.
LLM的訓練過程
粗略的來理解一下,LLM在訓練的過程中使用了海量文字的資料, 海量的文字資料先切成最大為max_seq_len大小, 切出的分片一般具有完整的語義資訊(比如一篇文章的其中一個自然段具有完整的語義資訊), 然後以前面的一句或幾句話作為輸入, 讓模型計算下一個token, 模型計算的token 和真實文字的token一般都是不一樣的, 這樣就產生了誤差(loss), 然後再用真實的token新增到輸入的後面(是真實的token不是模型產生的token, 該過程在專業術語叫做指導學習), 就這樣一個一個token的計算, 直至遇到
給定輸入token \(X_{1...i}\), 與模型的引數\(\Theta\)運算,然後輸出下一個token \(X_{i+1}\)的機率
模型輸出的大小為vocab_size大小的機率分佈, 每個機率值代表著對應的token做為下一個token輸出的機率大小, 訓練的目標就是使得模型輸出下一個真實的(ground truth)token的機率最大化, 如果模型輸出下一個token機率分佈中真實的token機率為1, 其他的token為0, 那將不會產生loss, loss等於0,不會進行反向傳播, 反之輸出的真實的token機率不是1, 甚至不是最大的, 那麼loss不等於0, loss將會進行反向傳播, 逐級傳遞到每層引數中,然後按照梯度下降的方向調整引數, 使得模型學會輸出正確的token。
llama3預測下一個token
llama3還不太一樣, 沒有完全用最大機率預測下個token
logits = self.model.forward(tokens[:, prev_pos:cur_pos], prev_pos)
if temperature > 0:
probs = torch.softmax(logits[:, -1] / temperature, dim=-1)
next_token = sample_top_p(probs, top_p)
else:
next_token = torch.argmax(logits[:, -1], dim=-1)m=-1)
logits是未歸一化(歸一化就是使得所有元素之和等於1)的分數, 經過softmax運算後才是機率。temperature就是各種大語言模型裡API中的temperature引數,用於控制生成token時的隨機性和多樣性,透過調整 temperature,可以影響模型生成token的確定性和創造性。sample_top_p是top p演算法函式, 原理為輸出的token機率按從大到小排序, 選擇前m項token,其機率的和剛超過了設定的閾值top_p, 然後再從選擇的token中按照其歸一化後的機率大小取樣(玩過統計機率的都知道取樣是什麼意思, 通俗的來講就是抽獎,token機率越大, 被抽中的可能性越高)。
如果temperature為0, 就是簡單的取最大機率的token。
生成的token再經過 tokenizer.decode(t) 就可以解碼成對應的單詞。
llama3結構圖
接下來我們講深入模型內部, 一探究竟。
我們先看下模型的結構圖
Nx表示重複N層
⊕ 表示殘差連線
太極符號表示旋轉位置編碼, 每一層的自注意力運算前q和k都加入位置編碼資訊
中間的自注意力機制使用的是分組查詢注意力機制, 並且使用了kv cache快取
llama3 8B 模型超引數
我們以Meta-Llama-3-8B-Instruct模型為例, 看下模型的超參, 就是params.json
{
"dim": 4096,
"n_layers": 32,
"n_heads": 32,
"n_kv_heads": 8,
"vocab_size": 128256,
"multiple_of": 1024,
"ffn_dim_multiplier": 1.3,
"norm_eps": 1e-05,
"rope_theta": 500000.0
}
dim是token向量的維度
n_layers表示有多少層TransformerBlock
n_heads表示多頭注意力機制(Multi-Head Attention)裡的頭數
n_kv_heads表示分組查詢注意力機制(Group Query Attention)裡的kv頭數
vocab_size表示字典大小
multiple_of表示TransformerBlock中最後的全連線FeadForward中的隱藏層維度hidden_dim的倍數因子(注意哈, 是倍數因子不是倍數, hidden_dim 為 multiple_of 的整數倍)
ffn_dim_multiplier表示上面的hidden_dim放大倍數
norm_eps歸一化層用到的很小的數, 以免出現除以0的錯誤
rope_theta是位置編碼用到的引數θ
欲知詳情, 請見下回分解