靈哥講llama3(上)

灵哥讲AI發表於2024-06-14

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是劃分切片的時候人為新增的, 目的是為了讓模型學習如何停止). 整個batch結束後, 然後根據累加的loss求出平均loss, 然後反向傳播調整模型的引數(反向傳播演算法是機器學習的靈魂演算法).至此模型學會了一種能力,預測下一個token,整個模型可以看作是如下預測下一個token的機率模型

\[P(X_{i+1}|X_{1...i},\Theta) \]

給定輸入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是位置編碼用到的引數θ

欲知詳情, 請見下回分解

相關文章