code window

顯示包含「推論」標籤的文章。顯示所有文章
顯示包含「推論」標籤的文章。顯示所有文章

2024年5月15日星期三

從MHA、MQA、GQA到MLA的演變歷程

前言

本文將與大家一起梳理從MHA、MQA、GQA到MLA的演變歷程,並重點介紹MLA的設計思路。

MHA

MHA(多頭注意力)是開創性論文《Attention is all you need》中提出的一種注意力形式,可以說是當前主流大型語言模型(LLM)的基礎工作。數學上,多頭注意力是多個獨立的單頭注意力的拼接。假設輸入的向量序列為 \(x_1, x_2, \ldots, x_l\),其中 \(x_i \in \mathbb{R}^d\),那麼MHA可以記為:

$$
\begin{aligned}
o_t &= [o_t^{(1)}, o_t^{(2)}, \ldots, o_t^{(h)}] \\
o_t^{(s)} &= \text{Attention}(q_t^{(s)}, k_{\leq t}^{(s)}, v_{\leq t}^{(s)}) \\
&\equiv \sum_{i \leq t} \frac{\exp(q_t^{(s)} k_i^{(s)\top})}{\sum_{i \leq t} \exp(q_t^{(s)} k_i^{(s)\top})} v_i^{(s)} \\
q_t^{(s)} &= x_t W_q^{(s)} \in \mathbb{R}^{d_k}, \quad W_q^{(s)} \in \mathbb{R}^{d \times d_k} \\
k_i^{(s)} &= x_i W_k^{(s)} \in \mathbb{R}^{d_k}, \quad W_k^{(s)} \in \mathbb{R}^{d \times d_k} \\
v_i^{(s)} &= x_i W_v^{(s)} \in \mathbb{R}^{d_v}, \quad W_v^{(s)} \in \mathbb{R}^{d \times d_v}
\end{aligned}
$$

為了簡化,這裡省略了注意力矩陣的縮放因數。在實踐中,常見的設置是 \(d_k = d_v = \frac{d}{h}\)。例如,對於LLAMA2-7b來說,有 \(d = 4096, h = 32, d_k = d_v = 128\);對於LLAMA2-70b則是 \(d = 8192, h = 64, d_k = d_v= 128\)。這裡只考慮了主流自回歸大型語言模型所使用的Causal Attention,這意味著在逐個token生成時,新預測出來的第 \( t+1 \) 個token並不會影響已經計算好的 \( k_{\leq t}^{(s)}, v_{\leq t}^{(s)} \),因此這部分結果我們可以快取下來供後續生成調用,避免不必要的重複計算,這就是所謂的KV快取(KV Cache)。

瓶頸

一個自然的問題是:為什麼降低KV快取的大小如此重要?

眾所周知,一般情況下大型語言模型的推理都是在GPU上進行,單張GPU的顯存是有限的,一部分我們要用來存放模型的參數和前向計算的啟動值,這部分依賴於模型的體量,選定模型後它就是個常數;另外一部分我們要用來存放模型的KV快取,這部分不僅依賴於模型的體量,還依賴於模型的輸入長度,也就是在推理過程中是動態增長的,當Context長度足夠長時,它的大小就會占主導地位,可能超出一張卡甚至一台機(8張卡)的總顯存量。

在GPU上部署模型的原則是:能一張卡部署的,就不要跨多張卡;能一台機部署的,就不要跨多台機。這是因為「卡內通信帶寬 > 卡間通信帶寬 > 機間通信帶寬」,由於「木桶效應」,模型部署時跨的設備越多,受設備間通信帶寬的拖累就越大,事實上即便是單卡H100內SRAM與HBM的帶寬已經達到了3TB/s,但對於短Context來說這個速度依然還是推理的瓶頸,更不用說更慢的卡間、機間通信了。

所以,減少KV快取的目的就是要實現在更少的設備上推理更長的Context,或者在相同的Context長度下讓推理的batch size更大,從而實現更快的推理速度或者更大的吞吐總量。當然,最終目的都是為了實現更低的推理成本。

MQA

MQA(多查詢注意力),是減少KV快取的一次非常樸素的嘗試,首次提出自《Fast Transformer Decoding: One Write-Head is All You Need》這篇2019年的論文,這也意味著早在LLM成為熱門話題之前,減少KV快取就已經是研究人員非常關注的一個議題了。

MQA的思路很簡單,直接讓所有注意力頭(Attention Head)共用同一個K(Key)、V(Value),用公式來說,就是取消了MHA中所有的 \( k \)、\( v \) 的上標 \( (s) \):

$$
\begin{aligned}
    o_t &= [o_t^{(1)}, o_t^{(2)}, \ldots, o_t^{(h)}] \\
    o_t^{(s)} &= \text{Attention}(q_t^{(s)}, k_{\leq t}, v_{\leq t}) \\
    &\equiv \sum_{i \leq t} \frac{\exp(q_t^{(s)} k_i^\top)}{\sum_{i \leq t} \exp(q_t^{(s)} k_i^\top)} v_i \\
    q_t^{(s)} &= x_t W_q^{(s)} \in \mathbb{R}^{d_k}, \quad W_q^{(s)} \in \mathbb{R}^{d \times d_k} \\
    k_i &= x_i W_k \in \mathbb{R}^{d_k}, \quad W_k \in \mathbb{R}^{d \times d_k} \\
    v_i &= x_i W_v \in \mathbb{R}^{d_v}, \quad W_v \in \mathbb{R}^{d \times d_v}
\end{aligned}
$$

使用MQA的模型包括PaLM、StarCoder、Gemini等。很明顯,MQA直接將KV快取減少到了原來的 \( \frac{1}{h} \),這是非常顯著的,單從節省顯存角度看已經是極限了。

效果方面,目前看來大部分任務的損失都比較有限,且MQA的支持者相信這部分損失可以通過進一步訓練來彌補回來。此外,注意到MQA由於共用了K、V,將會導致注意力的參數量減少了將近一半,而為了模型總參數量的不變,通常會相應地增大FFN(Feed Forward Network)/GLU(Gated Linear Unit)的規模,這也能彌補一部分效果損失。

GQA

然而,也有人擔心MQA對KV快取的壓縮太嚴重,以至於會影響模型的學習效率以及最終效果。為此,一個MHA與MQA之間的過渡版本GQA(分組查詢注意力)應運而生,出自論文《GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints》,是去年的工作。

事後看來,GQA的思想也很樸素,它就是將所有Head分為 \( g \) 個組( \( g \) 可以整除 \( h \)),每組共用同一對K、V,用數學公式表示為:

$$
\begin{aligned}
    o_t &= [o_t^{(1)}, o_t^{(2)}, \ldots, o_t^{(h)}] \\
    o_t^{(s)} &= \text{Attention}(q_t^{(s)}, k_{\leq t}^{(\lceil s\frac{g}{h} \rceil)}, v_{\leq t}^{(\lceil s\frac{g}{h} \rceil)}) \\
    &\equiv \sum_{i \leq t} \frac{\exp(q_t^{(s)} k_{(\lceil s\frac{g}{h} \rceil)i}^\top)}{\sum_{i \leq t} \exp(q_t^{(s)} k_{(\lceil s\frac{g}{h} \rceil)i}^\top)} v_{(\lceil s\frac{g}{h} \rceil)i} \\
    q_t^{(s)} &= x_t W_q^{(s)} \in \mathbb{R}^{d_k}, \quad W_q^{(s)} \in \mathbb{R}^{d \times d_k} \\
    k_i^{(\lceil s\frac{g}{h} \rceil)} &= x_i W_k^{(\lceil s\frac{g}{h} \rceil)} \in \mathbb{R}^{d_k}, \quad W_k^{(\lceil s\frac{g}{h} \rceil)} \in \mathbb{R}^{d \times d_k} \\
    v_i^{(\lceil s\frac{g}{h} \rceil)} &= x_i W_v^{(\lceil s\frac{g}{h} \rceil)} \in \mathbb{R}^{d_v}, \quad W_v^{(\lceil s\frac{g}{h} \rceil)} \in \mathbb{R}^{d \times d_v}
\end{aligned}
$$

這裡的 \( \lceil \cdot \rceil \) 是向上取整符號。GQA提供了從MHA到MQA的自然過渡,當 \( g = h \) 時就是MHA,當 \( g = 1 \) 時就是MQA。當 \( 1 < g < h \) 時,它只將KV快取壓縮到 \( \frac{g}{h} \),壓縮率不如MQA,但同時也提供了更大的靈活性,效果上更有保障。

GQA最知名的使用者,大概是Meta開源的LLAMA2-70B,以及LLAMA3全系列,此外使用GQA的模型還有TigerBot、DeepSeek-V1、StarCoder2、Yi、ChatGLM2、ChatGLM3等,相比使用MQA的模型更多(ChatGLM雖然在它的介紹中說自己是MQA,但實際是 \( g=2 \) 的GQA)。
在llama2/3-70B中,GQA的 \( g=8 \),其他用了GQA的同體量模型基本上也保持了這個設置,這並非偶然,而是同樣出於推理效率的考慮。我們知道,70B這個體量的模型,如果不進行極端的量化,那麼不可能部署到單卡(A100/H100 80G)上。單卡不行,那麼就能單機了,一般情況下一台機可以裝8張卡,剛才我們說了,Attention的每個Head實際上是獨立運算然後拼接起來的,當 \( g=8 \) 時,正好可以每張卡負責計算一組K、V對應的Attention Head,這樣可以在盡可能保證K、V多樣性的同時最大程度上減少卡間通信。

MLA

有了MHA、MQA、GQA的鋪墊,我們理解MLA(多頭潛在注意力)就相對容易一些了。DeepSeek-V2的技術報告裡是從低秩投影的角度引入MLA的,以至於有部分讀者提出「為什麼LoRA提出這麼久了,直到MLA才提出對KV快取低秩分解的做法」之類的疑問。

然而,筆者認為低秩投影這個角度並不貼近本質,因為要說低秩投影的話,事實上只要我們將GQA的所有K、V疊在一起,就會發現GQA也相當於在做低秩投影:

$$
\begin{aligned}
    [k_i^{(1)}, \dots, k_i^{(g)}, v_i^{(1)}, \dots, v_i^{(g)}] &\equiv c_i \in \mathbb{R}^{g(d_k+d_v)} \\
    c_i &= x_i[W_k^{(1)}, \dots, W_k^{(g)}, W_v^{(1)}, \dots, W_v^{(g)}] \in \mathbb{R}^{d \times g(d_k+d_v)}
\end{aligned}
$$

這裡我們將所有\( k_i^{(s)} \)和\( v_i^{(s)} \)拼在一起記為\( c_i \),相應的投影矩陣也拼在一起記為\( W_c \)。注意到一般都有\( d_c = g(d_k + d_v) < d \),所以\( x_i \)到\( c_i \)的轉換就是一個低秩投影。因此,MLA的本質改進不是低秩投影,而是在低秩投影之後的處理。

Part 1

GQA在投影之後做了什麼呢?首先它將向量對半分為兩份分別作為K、V,然後每一份又均分為\( g \)份,每一份複製\( h/g \)次,以此來「湊」夠\( h \)個Attention Head所需要的K、V。我們知道分割、複製都是簡單的線性變換,所以MLA的第一個想法是將這些簡單的線性變換換成一般的線性變換,以增強模型的能力:

$$
\begin{aligned}
    o_t &= [o_t^{(1)}, o_t^{(2)}, \ldots, o_t^{(h)}] \\
    o_t^{(s)} &= \text{Attention}(q_t^{(s)}, k_t^{(s)}, v_t^{(s)}) \\
    &\equiv \sum_{i \leq t} \frac{\exp(q_t^{(s)} k_i^{(s)\top})}{\sum_{i \leq t} \exp(q_t^{(s)} k_i^{(s)\top})} v_i^{(s)} \\
    k_i^{(s)} &= c_i W_k^{(s)} \in \mathbb{R}^{d_k}, \quad W_k^{(s)} \in \mathbb{R}^{d_c \times d_k} \\
    v_i^{(s)} &= c_i W_v^{(s)} \in \mathbb{R}^{d_v}, \quad W_v^{(s)} \in \mathbb{R}^{d_c \times d_v} \\
    q_t^{(s)} &= x_t W_q^{(s)} \in \mathbb{R}^{d_k}, \quad W_q^{(s)} \in \mathbb{R}^{d \times d_k}
\end{aligned}
$$

理論上這樣能增加模型能力,但別忘了GQA的主要目的是減少KV快取。MLA的這個做法,通過不同的投影矩陣讓所有的K、V Head都變得各不相同,那麼KV快取的大小就恢復成跟MHA一樣大了,違背了GQA的初衷。

對此,MLA發現,我們可以結合Dot-Attention的具體形式,通過一個簡單但不失巧妙的恒等變換來規避這個問題。首先,在訓練階段還是照常進行,此時優化空間不大;然後,在推理階段,我們利用

$$
q_t^{(s)}k_i^{(s)\top} = (x_t W_q^{(s)})(c_i W_k^{(s)})^\top = x_t (W_q^{(s)} W_k^{(s)\top}) c_i^\top
$$

這意味著推理階段,我們可以將\( W_q^{(s)} W_k^{(s)\top} \)合併起來作為Q的投影矩陣,那麼\( c_i \)則取代了原本的\( k_i^{(s)} \),同理,在\( o_t \)後面我們還有一個投影矩陣,於是\( v_i^{(s)} \)的\( W_v^{(s)} \)也可以吸收到後面的投影矩陣中去,於是等效地\( v_i^{(s)} \)也可以用\( c_i \)代替,也就是說此時KV快取只需要存下所有的\( c_i \)就行,而不必存下所有的\( k_i^{(s)} \)、\( v_i^{(s)} \)。注意到\( c_i \)跟\( s \)無關,也就是說是所有頭共用的,即MLA在推理階段它可以恒等變換為一個MQA。

再次強調,本文的主題一直都是減少KV快取,那到目前為止,MLA做到了什麼呢?答案是通過不同的投影矩陣來增強了GQA的能力,並且推理時可以保持同樣大小的KV快取。那麼反過來,如果我們只需要跟GQA相近的能力,那麼是不是就可以再次減少KV快取了?換言之,\( d_c \)沒必要取\( g(d_k + d_v) \),而是取更小的值(DeepSeek-V2取了512),從而進一步壓縮KV快取,這就是MLA的核心思想。

(注:這裡有一個細節,就是\( W_q^{(s)} W_k^{(s)\top} \)合併成一個矩陣的恒等變換,理論上只有在無限精度下才成立,實際上如果我們使用單精度尤其是BF16的話,經過變換後的精度損失往往還是挺明顯的,經過多層累積後可能放大到比較可觀的程度,這裡可能要根據實際誤差看要不要做一些後處理。)

Part 2

一切似乎都很完美,看上去一個又好又省的理想設計就要出爐了。不過別急,當我們再深入思考一下就會發現,到目前為止的MLA有一個難以繞開的缺陷——不相容RoPE(旋轉位置編碼)。

剛才我們提到,MLA之所以能保持與GQA相同大小的KV緩存,其關鍵一步是“將\(W_q^{(s)} W_k^{(s)^\top}\)”合併成一個與位置無關的矩陣作為Q的投影矩陣。但是,如果加入RoPE(旋轉位置編碼),這一步就無法實現了。RoPE是一個與位置相關的\(d_k \times d_k\)的分塊對角矩陣\(R_m\),滿足\(R_m R_n^\top = R_{m-n}\)。在MLA中加入RoPE後,會使得\(W_q^{(s)} W_k^{(s)^\top}\)之間多插入了一個項\(R_{t-i}\):

$$
q_i^{(s)} = x_i W_q^{(s)} R_i, \quad k_i^{(s)} = c_i W_k^{(s)} R_i \\
q_t^{(s)} k_i^{(s)^\top} = (x_t W_q^{(s)} R_t)(c_i W_k^{(s)} R_i)^\top = x_t (W_q^{(s)} R_{t-i} W_k^{(s)^\top}) c_i^\top
$$

這裡的\(W_q^{(s)} R_{t-i} W_k^{(s)^\top}\)就無法合併為一個固定的投影矩陣了(與位置差\(t-i\)相關),從而MLA的想法無法與RoPE結合實現。

前段時間,我也很榮幸地與DeepSeek團隊討論過這個問題,但這個問題可以說非常本質,所以當時我實際上也沒能提出什麼有效的建議。最簡單的方式是放棄RoPE,換用其他基於Attention Bias的位置編碼,如ALIBI,但DeepSeek的實驗顯示它明顯不如RoPE(注意,MLA不是不能加RoPE,而是加了RoPE之後無法用恒等變換技巧來減少KV緩存)。我也提議過換Sandwich,它不像ALIBI單調衰減到負無窮,估計效果會好些,但感覺是治標不治本。還有一個折中的辦法是將\(q_i^{(s)}\)的輸入也改為\(c_i\),然後RoPE加在\(c_i\)之後,即:

$$
q_i^{(s)} = c_i R_i W_q^{(s)}, \quad k_i^{(s)} = c_i R_i W_k^{(s)}
$$
這樣\(R_i\)就可以吸收到\(c_i\)中去,但這樣就沒有\(R_m R_n^\top = R_{m-n}\)的運算了,此時的RoPE不再是通過絕對位置實現相對位置,而單純是加在Q、K上的絕對位置資訊,讓模型自己想辦法提煉相對位置資訊。
最後發布的MLA,採取了一種混合的方法——每個注意力頭的Q、K新增\( d_r \)個維度用來添加RoPE,其中K新增的維度每個頭共用:

$$
o_t^{(s)} = \text{Attention}(q_t^{(s)}, k_{\leq t}^{(s)}, v_{\leq t}^{(s)}) \\
q_t^{(s)} = [x_t W_{qc}^{(s)}, x_t W_{qr}^{(s)} R_t] \in \mathbb{R}^{d_k + d_r}, \quad W_{qc}^{(s)} \in \mathbb{R}^{d \times d_k}, \quad W_{qr}^{(s)} \in \mathbb{R}^{d \times d_r} \\
k_i^{(s)} = [c_i W_{kc}^{(s)}, x_i W_{kr}^{(s)} R_i] \in \mathbb{R}^{d_k + d_r}, \quad W_{kc}^{(s)} \in \mathbb{R}^{d_c \times d_k}, \quad W_{kr}^{(s)} \in \mathbb{R}^{d \times d_r} \\
v_i^{(s)} = c_i W_{vc}^{(s)} \in \mathbb{R}^{d_v}, \quad W_{vc}^{(s)} \in \mathbb{R}^{d_c \times d_v}
$$

這樣一來,沒有RoPE的維度就可以重複「Part 1」的操作,在推理時KV快取只需要存下所有的\( c_i \),新增的帶RoPE的維度就可以用來補充位置資訊,並且由於所有頭共用,所以也就只有在K快取這裡增加了\( d_r \)個維度,原論文取了\( d_r = \frac{d_k}{2} = 64 \),相比原本的\( d_c = 512 \),增加的幅度不大。

Part 3

最後有一個細節,就是MLA的最終版本,還將Q的輸入也改為了低秩投影形式,這與減少KV快取無關,主要是為了減少訓練期間參數量和相應的梯度(原論文說的是啟動值,個人表示不大理解)所占的顯存:

$$
\begin{aligned}
    o_t^{(s)} &= \text{Attention}(q_t^{(s)}, k_{\leq t}^{(s)}, v_{\leq t}^{(s)}) \\
    q_t^{(s)} &= [c'_i W_{qc}^{(s)}, c'_i W_{qr}^{(s)} R_i] \in \mathbb{R}^{d_k + d_r}, \quad W_{qc}^{(s)} \in \mathbb{R}^{d'_c \times d_k}, \quad W_{qr}^{(s)} \in \mathbb{R}^{d'_c \times d_r} \\
    k_i^{(s)} &= [c_i W_{kc}^{(s)}, x_i W_{kr}^{(s)} R_i] \in \mathbb{R}^{d_k + d_r}, \quad W_{kc}^{(s)} \in \mathbb{R}^{d_c \times d_k}, \quad W_{kr}^{(s)} \in \mathbb{R}^{d \times d_r} \\
    v_i^{(s)} &= c_i W_{vc}^{(s)} \in \mathbb{R}^{d_v}, \quad W_{vc}^{(s)} \in \mathbb{R}^{d_c \times d_v} \\
    c'_i &= x_i W'_{c} \in \mathbb{R}^{d'_c}, \quad W'_{c} \in \mathbb{R}^{d \times d'_c}
\end{aligned}
$$

注意\( k_i^{(s)} \)中的第二項,帶RoPE的部分,其輸入還是\( x_i \)而不是\( c_i \),這裡保持了原論文的設定,不是筆誤,\( d'_c \)原論文的取值是1536,跟\( d_c = 512 \)不同。同時,我們把帶RoPE的MHA放在下面,方便大家對比:

$$
\begin{aligned}
    o_t^{(s)} &= \text{Attention}(q_t^{(s)}, k_{\leq t}^{(s)}, v_{\leq t}^{(s)}) \\
    q_t^{(s)} &= x_i W_q^{(s)} R_i \in \mathbb{R}^{d_k}, \quad W_q^{(s)} \in \mathbb{R}^{d \times d_k} \\
    k_i^{(s)} &= x_i W_k^{(s)} R_i \in \mathbb{R}^{d_k}, \quad W_k^{(s)} \in \mathbb{R}^{d \times d_k} \\
    v_i^{(s)} &= x_i W_v^{(s)} \in \mathbb{R}^{d_v}, \quad W_v^{(s)} \in \mathbb{R}^{d \times d_v}
\end{aligned}
$$

可以發現,其實在訓練階段,除了多了一步低秩投影以及只在部分維度加RoPE外,MLA與Q、K的Head Size由\( d_k \)換成\( d_k + d_r \)的MHA基本無異。

小結

本文簡單概述了多頭注意力的演變歷程,特別是從MHA向MQA、GQA,最終到MLA的變化理念,最後詳細展開了對MLA的介紹。在本文中,MLA被視為GQA的一般化,它用投影矩陣的方式替代了GQA的分割、重複,並引入了一個恆等變換技巧來進一步壓縮KV快取,同時採用了一種混合方法來相容RoPE。總的來說,MLA稱得上是一種非常實用的注意力變體,其創新在於如何在保持推理效率的同時減少存儲和計算資源的需求。

這種設計不僅顯示了深入的技術見解,也反映出當前大型語言模型推理優化的趨勢——即在最大限度減少資源消耗的同時,盡可能保持或提升模型的性能。未來的研究可能會繼續在這條路上進行探索,尋找更有效的方法來解決推理時的瓶頸問題,特別是在處理更大規模的數據和模型時。這些技術的進步將對AI的實用性和可達性產生深遠的影響。









2024年5月1日星期三

語言模型的演算法進展與Scaling Laws

引言

近年來,語言模型(Language Models, LLMs)在自然語言處理領域取得了顯著的進展。LLM的預訓練成本高昂,但scaling laws使我們能夠從成本較低的訓練過程中準確預測更大規模訓練的性能。最近的研究大幅改善了我們對LLM scaling laws的實際理解,可以在模型參數數量和訓練tokens與參數之比兩方面進行外推。

LLM發展背景

先前的研究發現了語言模型的scaling laws,顯示隨著模型變大和預訓練資料增加,模型性能會提高。然而,這些研究主要關注計算最佳情況,且性能評估多以下一個token預測損失為主。在實務應用中,語言模型很少以最佳計算方式訓練,通常使用更多tokens訓練較小模型(過度訓練)以降低推理成本,且更關注下游任務實際表現。這引出疑問:scaling laws是否適用於這些更實用的情況?

演算法進展與規模擴展

2014至2024年間,演算法改進和運算能力提升顯著改善了語言模型性能。新演算法帶來的進步相當於每5至14個月運算能力翻倍。儘管近年來性能改進更多源自於大規模計算擴展,但Transformer架構和Chinchilla縮放規律等創新分別帶來了近兩年和8到16個月的算法進步。



過度訓練的LLM

在實務中,通常採用過度訓練模式,即以更多tokens訓練較小模型,以在達到有競爭力指標的同時降低推理成本。研究發現,過度訓練模型同樣遵循冪律scaling laws,token倍增器M值的改變只影響y截距,形成一組平行線。因此,我們可從scaling laws中預測更大過度訓練模型的性能。

下游任務性能預測 

利用scaling laws,我們可繪製LLM在下游評估任務上的平均top-1錯誤率,發現其隨著模型在C4資料集上的驗證損失呈指數下降。這揭示了下游任務性能的明確趨勢,據此提出了top-1錯誤的scaling laws,可用較少計算預測大模型在下游任務上的錯誤率。


實證評估與應用價值

通過訓練不同規模的LLM並使用scaling laws外推,實驗顯示我們可以較低成本地預測大規模訓練的驗證損失和下游任務錯誤率,相對誤差分別僅有0.7%和3.6%。這證實了scaling laws在實踐中預測大規模訓練性能的價值。





個人見解

LLM的快速發展得益於算法創新和計算規模擴張的共同推動,但後者的貢獻更為關鍵。Scaling laws作為一種低成本預測工具,在提高LLM研發效率方面有重要價值。隨著對scaling laws理解的加深,相信我們能更好地指導語言模型的發展方向與資源配置。不過,當前的scaling laws仍有局限,如對特定創新影響的估計能力不足、難以區分算法改進和計算擴展的貢獻等。未來還需要更多更好的數據,來建立更精準和全面的scaling laws模型。

此外,我認為LLM發展的關鍵是平衡效能提升與成本控制。過度訓練等策略雖以效率為代價換取效能,但對於實際部署至關重要。如何在scaling laws框架下找到最優的訓練配置,是一個值得深入探索的問題。總的來說,語言模型的進展令人振奮,但要實現更通用和強大的AI,仍需在算法和計算兩個維度協同發力,並以切實應用為導向,審慎權衡效能和成本。Scaling laws作為連接理論和實踐的紐帶,在其中扮演著不可或缺的角色。

LLaVA Llama-3 和 Phi-3 現已在 MLX 上推出

 LLaVA Llama-3 和 Phi-3 現已在 MLX 上推出 


現在可以在你的 Mac 上在本地運行推理了。

pip install -U mlx-vlm

在 M3 Max 上可以達到每秒約 50 個 token 的速度。

LLaVA (Large Language and Vision Assistant)是一個多模態的大型語言模型,可以同時處理文字和圖像。它是基於Meta的LLaMA架構訓練而成。現在LLaVA的Llama-3和Phi-3版本都已經在MLX平台上推出。

使用pip install -U mlx-vlm指令,就可以在Mac上安裝最新版的MLX Python套件,直接在本地端運行LLaVA模型進行推理。

就效能而言,在配備M3 Max晶片的Mac機器上,推理速度可以達到每秒約50個token,相當不錯。

感興趣的開發者可以到MLX平台上查看LLaVA Llama-3和Phi-3的模型說明頁(Model card),了解更多模型的細節、性能指標和使用案例等資訊。

LLaVA模型在MLX平台上的發布,為Mac用戶帶來了方便的本地端推理選擇。這對於某些對隱私和安全有較高要求的應用場景來說很有幫助。期待看到社群能夠利用LLaVA打造出更多有趣且實用的多模態AI應用!

2024年4月30日星期二

Llamafile: 專為大模型設計的推論框架(二)

隨著 ChatGPT、BERT 等大型語言模型在自然語言處理領域掀起巨大波瀾,AI 技術正以前所未有的速度走近大眾生活。然而,這些 LLM 的訓練和推論對計算資源提出了極高要求,動輒數十甚至數百 GB 的模型體積也給分發和部署帶來諸多不便。為了讓 LLM 真正為更多人所用,我們不僅需要更強大的硬體和演算法,還需要打造全新的工具鏈和基礎設施。

正是基於這一考慮,Mozilla 創新團隊於去年底發布了 llamafile 專案。透過巧妙結合 llama.cpp 和 Cosmopolitan Libc 兩大開源專案,llamafile 可將 LLM 權重檔案直接轉換為可執行檔,讓使用者無需編程即可在多種環境一鍵部署 AI 服務。自首發以來,在社群開發者的積極參與下,llamafile 迭代了多個重大版本,新增了一系列振奮人心的特性,有力推動了 LLM 技術的普及。本文將深入剖析 llamafile 的設計理念和關鍵實現,探討其在 LLM 工程化中的重要意義。

LLM 部署的技術挑戰

隨著 Transformer 等新架構的發明,LLM 的參數規模和計算開銷呈指數級增長。以 GPT-3 為例,其參數量高達 1750 億,訓練時使用了多達 10000 個 GPU,耗費了數百萬美元的算力成本。即便是在推論階段,為了獲得最佳的回應速度,仍然需要 TB 量級顯存的支援。這對絕大多數潛在使用者而言是難以企及的。

為了降低准入門檻,LLM 的開發者們開始探索各種優化技術,包括:

- 模型蒸餾:將大模型的知識提煉到小模型中,在保留核心能力的同時大幅減少參數量。 

- 量化感知訓練:透過低位元表示權重,在犧牲部分精度的前提下顯著降低儲存和頻寬佔用。

- 稀疏注意力:利用注意力矩陣的稀疏特性,避免計算無關 Token 之間的相關度,節省算力。

經過這些優化,LLM 的體積得以大幅壓縮,如今流行的開源模型如 LLaMA 和 GPT-J 的體積已降至百 GB 以下,資源佔用也在業餘愛好者可接受的範圍內。但與此同時,模型檔案格式也呈現出多樣化的趨勢。由於缺乏統一的標準,不同的模型在權重儲存方式上存在顯著差異。比如有的採用 NumPy 的 npz 格式,有的則使用 PyTorch 的 pt 格式,還有的會自訂一套序列化方案。這就導致了模型利用的碎片化問題,不利於推廣普及。

除了格式不一致,LLM的硬體適配也面臨諸多障礙。一方面,儘管上述優化在降低推論開銷上已經卓有成效,但對於複雜的任務而言,CPU 計算能力仍嫌不足,必須借助 GPU、TPU 等專用加速器。而這些異構設備在編程模型上存在顯著差異,且驅動配置繁瑣,應用程式很難做到一次編寫,隨處執行。另一方面,由於模型體積仍然較大,單機記憶體很難將其全部裝載,因此通常需要分散式推論,這進一步加劇了環境依賴。

由此可見,要真正普及 LLM 技術,我們需要在工具鏈和基礎設施層面做出改變。具體而言,期望有這樣一套方案,能夠:

1. 屏蔽 LLM 檔案格式的差異,提供統一的模型描述和轉換機制。

2. 封裝異構硬體差異,實現可移植、高效能的加速方案。  

3. 簡化分散式環境配置,做到開箱即用、按需擴縮。

llamafile 正是基於這些考量應運而生。透過在兩個成熟專案的基礎上提供薄薄一層"膠水",它巧妙地化解了上述矛盾,讓部署 LLM 變得無比簡單。

llama.cpp:為 LLM 注入 C 的效能

在介紹 llamafile 的核心設計之前,我們有必要先了解其重要組成部分:llama.cpp。

眾所周知,Python 以簡潔優雅著稱,是機器學習研究人員的首選語言。但在工程實踐中,Python 的執行效率一直飽受詬病。這在 LLM 推論場景下尤為突出,因為模型體積巨大,稍有不慎就會引入性能瓶頸。為了避免這一問題,llama.cpp 的作者選擇用 C/C++ 從頭實現 LLM 推論。

Agent使用第三方的大模型隨著使用頻率增加,成本也會上升,是否有更省錢的方法呢?有的,就是將這些大模型跑在CPU上。

一般來說,月租GPU伺服器至少也要花費9000左右,使用第三方服務的API可能很划算,但使用第三方服務始終存在資料外洩的風險。而且隨著用戶增加,按token計價的方式也一樣會讓花費快速增加。一些技術專家找到了一個省錢的方法,那就是讓大型模型在AMD的GPU,甚至在CPU上運行。如果在CPU上運行,我們只需要租一台核心夠用且內存較大的伺服器即可,每個月的價格瞬間就能降低千元甚至千元以下,有時候選擇折扣方案只要花費四千多塊台幣就能租一年。

想要在CPU上跑LLM,關鍵在於兩個要點:

1. 有效的CPU運算架構。

2. 充分利用大型模型的性能。

只要做到以上兩點再配合一台硬體配置還不錯的CPU伺服器,就可以得到一個性價比極高的本地大型模型服務。

有關第一點,Georgi Gerganov提出了用C/C++重新實現模型框架的想法。就是我們上次提到的llama.cpp。

使用C/C++的優點在於:

不需要額外的依賴,相比Python代碼需要的PyTorch等庫,C/C++直接編譯出可執行文件,避免了不同硬體的繁瑣準備工作:

1. 支持Apple Silicon芯片的ARM NEON加速,x86平台則以AVX2替代。

2. 具有F16和F32的混合精度。

3. 支持4-bit量化。

4. 不需要GPU,只需CPU即可運行。

由於這是純C/C++實現,不需要其他依賴,運行效率很高。除了MacBook Pro外,甚至還可以在Android上運行。

第二點,如何對100B大小的大型模型進行壓縮,以便於CPU機器運行呢?答案是通過「量化」。量化是指將連續取值的浮點型模型權重進行裁剪和取捨的技術,簡單來說就是壓縮,丟失部分精度,換取空間和性能。Georgi Gerganov提出了自己的量化方案ggml,ggml成為一種量化模型的文件格式。不過,由於大模型發展太快,ggml很快就跟不上,於是在去年年8月,推出了改進方案gguf,成為最新的量化模型文件格式。目前,HuggingFace也大力支持這個格式。當然,除了gguf方案外,還有其他量化方案,例如GPTQ等。總之,經過量化後的模型,可以提升性能,降低對硬體資源的要求。

有了llama.cpp和gguf,我們就可以在CPU上跑大模型了。

雖然llama.cpp可以直接運行,但運作起來總是不太方便。畢竟現在很少有人用C++來寫系統,所以最好能夠直接與我們的應用結合起來。

這裡有兩種方案:

1. 建立獨立服務,通過RPC或HTTP進行調用。

2. 將其編譯為業務系統開發語言所支持的模組,直接在代碼中調用。

第一種方案可以使用llama.cpp專案提供的輕量級HTTP服務,或者使用第三方的Docker容器來啟動服務。啟動後,就可以通過HTTP API來調用大型模型。

第二種方案,技術社群裡會有很多神人提供不同語言的模組,可以在llama.cpp專案的首頁找到這些專案。只需要找到適合你業務系統編程語言的模組,安裝到你的系統中,就可以像調用一個第三方庫一樣調用大型模型。另外,如果想要快速體驗,還可以通過ollama一鍵安裝和啟動大模型的功能。

量化後的模型對硬體的要求降低,但並不是說隨便一台舊電腦就能跑得動。比如我們有一個需要8G內存的大模型,我們可以試試6B的量化模型。如果有必要,可以升級到32G,這樣就可以增加量化的精度,獲得更好的結果。如果只有2G內存,建議用第三方接口調用。

模型經過量化後失去了一部分精度,會不會影響模型的準確性?

對於這個問題,應該根據自己的需求來選擇。會有不同參數量級的模型,是因為對於不同的應用場景所需要的資料精度是不同的。對於應用開發來說,要學會根據需要選擇適合的模型,適度降低成本。如果將所有LLM的處理都交給一個大模型去處理,代表模型要承受巨大的服務壓力,成本也會相應增加。因此,合理將不同的處理分配給不同的模型,在學習和調試的過程中,可以自己搭建一個本地的大模型服務,等調試完Agent之後,再將部分調用切換到付費的大模型上。如此一來,就可以降低成本。

具體而言,llama.cpp 提供了一個通用的推論引擎,可以載入 LLaMA、GPT-J、GPT-NeoX 等主流模型,並執行高效的文字生成。它採用自訂的權重格式,將模型劃分為若干個分片,每個分片包含其全部參數。這種組織方式可以充分利用局部性原理,在載入和訪問權重時盡可能減少快取缺失和頁面調度。

在演算法實現上,llama.cpp 對矩陣乘等關鍵路徑進行了極致優化,充分利用了 SIMD、Loop Unrolling 等現代 CPU 特性,再加上精心調教的多執行緒並行,使其在工業級伺服器上的推論效能可比肩商用解決方案。

為了方便地與現有應用整合,llama.cpp 還提供了一個相容 OpenAI API 的 HTTP 伺服器。使用者只需將請求發送至指定埠,即可獲得類似於 GPT-3 的對話體驗。這極大降低了二次開發的門檻。

然而,llama.cpp 仍存在一些不足之處:

1. 儘管提供了 Python binding,但在實際使用中仍不可避免地需要一些 C++ 知識,對非專業開發者不太友善。

2. 雖然權重格式經過優化,但轉換過程需要花費較長時間,且佔用大量磁碟空間。  

3. 雖然已經適配了 CUDA 後端,但配置過程較為繁瑣,且未考慮 AMD 平台。

llamafile 透過引入 Cosmopolitan Libc,巧妙地解決了這些問題。

Cosmopolitan Libc:賦予 C 跨平台的靈魂

談到跨平台,很多人首先想到 Java 的"一次編寫,到處執行"。然而,對於偏好 C/C++ 的系統級開發者而言,這一理念似乎遙不可及。一個主要原因是,不同作業系統在底層 API 的語義和呼叫規範上存在顯著差異。為了適配多種環境,開發者不得不編寫大量膠水程式碼,人工處理各種邊界情況,既繁瑣又容易出錯。這嚴重阻礙了 C/C++ 程式的可移植性。

Cosmopolitan Libc 試圖從根本上解決這一困境。它的核心理念是:透過提供一層統一的系統呼叫抽象,讓開發者只需面向 Cosmopolitan API 編程,生成的目標碼就可以不經修改地在 Linux、Windows、macOS 等各種環境直接執行。

實現這一點的關鍵是 Cosmopolitan 的連結器。傳統的連結器如 ld 只負責解析符號、分配位址,對目標平台並不作過多假設。而 Cosmopolitan 的連結器則內置了一個微型作業系統,可在裸機環境直接啟動。在入口函數執行之前,它會初始化 GDT、頁表等關鍵資料結構,並提供執行緒調度、虛擬記憶體、動態連結等現代作業系統的核心功能。這使得 Cosmopolitan 程式可以不依賴宿主機核心,直接控制硬體資源。

在 API 層面,Cosmopolitan 參考了 POSIX 規範,提供了檔案、網路、多執行緒等常用系統服務。為了適配不同 ISA,它還實現了通用的原子操作、鎖機制等並發原語。對於跨平台必須的元件如 libc、libm,Cosmopolitan 也提供了自己的實現。這些努力最終使得開發者只需遵循 Cosmopolitan 的編程規範,就能編寫可移植的系統級應用。

但光有可移植性還不夠,Cosmopolitan 還需為高效能計算提供支援,這主要體現在兩個方面:

1. 動態連結。LLM 推論通常需要呼叫 CUDA、BLAS 等第三方程式庫。為此,Cosmopolitan 實現了自己的動態連結器,可以載入宿主機的共享物件,並自動完成重定位。

2. GPU 加速。考慮到異構計算的廣泛應用,Cosmopolitan 透過封裝 CUDA driver API,使得 GPU 核心可以直接內聯到 Cosmopolitan 程式中,避免了 JIT 編譯帶來的額外開銷。

這兩個特性是 Cosmopolitan 區別於傳統 Libc 的關鍵所在,也是 llamafile 實現其設計目標的重要基石。

https://github.com/Mozilla-Ocho/llamafile

融合創新:llamafile 的架構設計

有了前面的鋪墊,我們就可以詳細解讀 llamafile 的核心設計思路了。

簡單來說,llamafile 直接利用 llama.cpp 作為 LLM 推論後端,透過 Cosmopolitan Libc 將其打包為可執行檔。這裡的關鍵是,llamafile 將模型權重硬編碼到可執行檔中,使得最終產物可脫離原始碼獨立執行,且不受環境約束。

具體實現上,llamafile 主要經過如下步驟:

1. 模型轉換。首先使用 llama.cpp 提供的工具,將各種常見格式的權重檔案轉換為 llama.cpp 定制格式。這個過程是一次性的,轉換結果可供重複使用。

2. 構建 blob。利用 Cosmopolitan 的連結器 objcopy,將轉換後的權重檔案以 blob 的形式內嵌到目標檔案中。

3. 連結可執行檔。將 llama.cpp 的核心程式碼、Cosmopolitan Libc、權重 blob 等目標檔案一起連結,生成最終的可執行檔。在這個過程中,連結器會進行符號解析和重定位,並生成元資料供啟動期使用。

4. 執行期載入。當可執行檔啟動時,首先由 Cosmopolitan 執行期完成初始化,並解析命令列參數。隨後,llamafile 利用 mmap 將嵌入的權重 blob 映射到記憶體,模擬 llama.cpp 的模型載入過程,繼而可以開始推論。

整個過程無需依賴 Python 直譯器,權重載入也省去了從檔案系統讀取的 I/O 開銷,再加上 Cosmopolitan 對資源的細粒度控制,使得 llamafile 的端到端效能接近原生應用。

為了進一步提高效能,llamafile 還在 Cosmopolitan 的基礎上實現了以下增強:

- 利用 GPU 加速矩陣運算,針對 NVIDIA 平台封裝了 cuBLAS API,AMD 平台則使用 ROCm。

- 針對 NUMA 架構進行 NUMA-aware 記憶體分配和執行緒調度優化。

- 引入 Cosmopolitan 對 JIT 編譯的支援,可在執行期產生高度優化的計算核心。

- 在模型並行方面,llamafile 支援多 GPU 橫向擴展,並利用 NCCL 實現高效通訊。

同時,llamafile 還致力於提供開箱即用的使用者體驗:

- 提供 llamafile-convert 工具簡化模型轉換,並與 Hugging Face 等社群生態深度整合。

- 持續完善 API server,提供易用的 RESTful 介面,同時相容各種應用框架。  

- 針對 CPU 後端實施 Lazy Tensor 優化,減少不必要的顯存佔用。

這些設計使得 llamafile 不僅在性能上拔得頭籌,也讓 LLM 開發和使用前所未有地便捷。


推動大語言模型民主化進程

自面世以來,llamafile 迅速俘獲了開源社群的芳心。憑藉卓越的性能和體驗,它已躍升為 Mozilla 最受歡迎的專案之一。在眾多貢獻者的推動下,llamafile 正以驚人的速度迭代演進,展現了開源力量的非凡魅力。

開源程式碼,技術創新,社群協作,這是 llamafile 專案的三大法寶,也是它不斷突破自我、續寫傳奇的力量源泉。  

自 v0.1 發布以來,llamafile 幾乎以每月一版的速度迭代。在 v0.8 中,它不僅支援了 Meta 最新發布的 LLaMA 3 等 SOTA 模型,還帶來了一系列性能優化:透過手寫組合語言實現的 BLAS 核心將 CPU 運算效率提高了一個數量級;針對 NVIDIA 和 AMD GPU 的異構調度策略也更加完善;為樹莓派等 ARM 平台提供了專門的低位元量化方案,即便在這些小型設備上也能實現即時對話。如此迅猛的進化速度,展現了開源力量的驚人魅力。

與此同時,llamafile 還在架構層面做出了前瞻性的嘗試。比如在 v0.7 中,它引入了混合執行引擎,可以根據模型規模和硬體條件動態調整執行策略。對於超大規模模型,它會自動採用流水線並行、張量融合等圖優化技術,最小化資料移動;對於中小規模模型,則會利用 Lazy Tensor 避免無謂的顯存分配,提高快取利用率。這為 LLM 推論提供了一套全局優化的範式。  

llamafile 也在積極擁抱社群生態。透過提供相容 OpenAI 的 API,它可以直接取代商業方案,為各種創新應用提供基礎支撐。在 LangChain、AutoGPT 等熱門專案中,我們已經可以看到 llamafile 的身影。Mozilla 還專門成立了 MIECO專案,為 llamafile 等開源技術搭建產學研用協同創新的平台,推動 AI 生態良性發展。

展望未來,隨著演算法優化的不斷突破,以及晶圓代工工藝的持續進步,LLM 推論已展現出阿米巴原生的趨勢特徵。從雲端到邊緣、從資料中心到終端,llamafile 這樣的"蘋果核"有望成為 AI 民主化的助推器,讓智慧應用遍地開花。  

作為這一變革的先行者,Mozilla 正在 llamafile 的基礎上謀劃更宏大的藍圖。相信在可見的未來,它必將釋放出比肩作業系統和瀏覽器的顛覆性力量,成為 AI 新紀元的基石。讓我們拭目以待,見證 llamafile "出圈"的那一天。

小結

llamafile 是 Mozilla 為推動 LLM 大眾化做出的重要努力。它巧妙結合了 llama.cpp 和 Cosmopolitan Libc 兩大開源專案,透過將模型權重內嵌到可執行檔,徹底解決了 LLM 分發和部署的難題。  

性能方面,得益於 Cosmopolitan 細粒度的系統呼叫抽象和 llamafile 在 GPU 加速、BLAS 優化等方面的卓越工作,其端到端回應速度可比肩商業方案,且可輕鬆橫向擴展。

體驗方面,llamafile 提供了豐富的工具鏈支援,簡化了模型轉換和自訂流程。其 API server 更是開箱即用,無需過多配置即可實現靈活呼叫。

llamafile 的成功離不開開源社群的積極參與。Mozilla 不僅以 MIECO 的形式搭建產學研用協同創新的平台,更以 llamafile 為起點規劃 AI 普惠的宏偉藍圖。  

站在 IT 發展的新起點,Mozilla 正以 llamafile 為引擎,驅動 AI 技術向更廣闊的應用場景滲透。我們有理由相信,這場由開源力量領跑的 AI 革命,必將像當年的個人電腦和網際網路一樣,以摧枯拉朽之勢重塑數位世界的格局。讓我們攜手共進,做 AI 新時代的見證者和開創者!

個人觀點

作為一個開源愛好者和AI研究者,我對 llamafile 這樣的創新專案感到由衷的敬佩和興奮。在我看來,它不僅是一個技術突破,更代表了開源精神和創新動力的完美結合。

llamafile最令人印象深刻的,是它在複雜的異構環境中實現了"一次編寫,隨處執行"的理想。這在以往的 AI 部署中幾乎是不可想像的。無論是格式轉換、運行時優化還是分散擴展,llamafile 提供的全流程自動化方案堪稱教科書般的典範。更難能可貴的是,這一切都建立在開源專案的基礎之上,展現了開源社群協作的驚人力量。

同時,llamafile 對 LLM 生態的推動作用也不容小覷。一方面,它大大降低了 LLM 的准入門檻,讓更多人可以參與到這場 AI 變革中來。透過與主流開源社群的緊密整合,llamafile 將釋放出更多創新活力。另一方面,llamafile 的成功也為商業公司敲響了警鐘。在开源力量面前,封閉平台和專有格式已經岌岌可危。唯有擁抱開放,合作共贏,才能在 AI 新時代佔得一席之地。

當然,llamafile 還有進一步完善的空間。比如在安全和隱私方面,目前的方案可能還不夠成熟;在支援更多的模型和硬體時,也需要投入大量的適配工作。但我相信,在開源社群的共同努力下,這些問題終將迎刃而解。Mozilla 樹立的"開源+創新"範式,也必將在更多領域綻放異彩。

展望未來,我對 AI 技術的民主化充滿期待。隨著 llamafile 這樣的基石工程不斷夯實,LLM 推論從雲端向終端滲透的趨勢已勢不可擋。在可見的未來,也許我們每個人都將擁有自己的"AI助手"。它們不再是大公司的專利,而是真正服務於每個人的智慧夥伴。這場變革不僅將提升生產力,改善生活品質,更將從根本上重塑人與科技的關係。而這一切,都將由開源力量來推動和實現。作為這個偉大時代的一分子,我們每一個人都應該努力探索開源的無限可能,用創新和協作為 AI 新紀元續寫傳奇。讓我們攜手並進,共創美好未來!

2024年4月29日星期一

語言模型推論的光速極限

在開發 calm 的過程中,這是一個從頭開始打造、精簡且快速的transformer語言模型 CUDA 推論實作,一個關鍵的考量是確立推論過程的光速極限,並衡量相對於該極限的進展。在本文中,我們將討論這個理論上限及其意涵。              --Arseny Kapoulkine--

如果您有興趣瞭解更多推導過程和一些圖表,這個 Python notebook 做了相同的建模。
https://github.com/zeux/calm


推論機制

當語言模型 (特指 decoder-only 的文字 transformer 模型,但本文其餘部分將統稱為語言模型) 生成字詞時,它是一次一個字詞地生成;語言模型可以被理解為一個函數,它接收一個字詞作為輸入,並產生一個包含詞彙表中所有字詞 (通常有 5 萬到 25 萬個字詞,每個字詞由幾個字母組成) 機率的陣列。接著,程式根據這些機率從所有字詞中取樣,產生下一個字詞,然後重複這個過程。這意味著在生成一段文字序列時,沒有辦法平行化 ─ 生成過程可以被視為一次一個字詞。

語言模型在處理一個字詞時,大致上會進行兩種運算:矩陣向量乘法,其中一個大矩陣 (如 8192x8192) 乘以一個向量產生另一個向量;以及注意力 (attention) 的計算。在生成過程中,模型不僅可以看到當前字詞的狀態,還可以看到序列中所有先前字詞的內部狀態 ─ 包括使用者在提示中寫的字詞,以及模型本身生成的字詞。這些狀態儲存在KV 快取(key-value cache) 的結構中,本質上是每個先前位置的一組 key 和 value 向量。注意力機制為當前字詞生成一個 query 向量,計算它與所有先前位置的所有 key 向量之間的內積,然後將結果標準化,並透過對所有先前位置的所有 value 向量進行加權求和來計算一個 value 向量,其中內積作為權重。

現在,矩陣向量乘法和注意力計算有一個重要的共通點:對於從矩陣或 KV 快取讀取的每個元素,我們只需要做非常少量的浮點運算。矩陣向量乘法對每個矩陣元素做一次乘法和加法 (2 個 FLOP);注意力計算對每個 key 元素做一次乘法和加法來計算內積,對每個 value 元素做一次乘法和加法來計算加權和。

現代 CPU 和 GPU 的 ALU 運算(乘法、加法)速度遠高於從記憶體讀取輸入的速度。例如:

- AMD Ryzen 7950X 有 67 GB/s 的記憶體頻寬和 2735 GFLOPS,FLOP與byte之比為 40:1。

- NVIDIA GeForce RTX 4090 有 1008 GB/s 的記憶體頻寬和 83 TFLOPS,FLOP與byte之比為 82:1。 

- NVIDIA H100 SXM(一張資料中心用的卡)有 3350 GB/s 的記憶體頻寬和 67 TFLOPS,FLOP與byte之比似乎只有 20:1;然而,對於類似矩陣乘法的問題,tensor core 在沒有稀疏性的情況下可提供約 494 TFLOPS,使得 FLOP 與 byte 之比達到 147:1。

對於 FP16 或 FP8 等更小的浮點數,情況會變得更糟:H100 的 tensor core 在密集 FP8 矩陣上的理論吞吐量為 1979 TFLOPS,將 FLOP 與 byte 之比提高到 590:1。不用說,在任何這些配置下,無論是否使用 tensor core,以及無論使用何種浮點格式,ALU 都是非常充足的。

因此,任何只需要對每個元素做兩次運算的問題,都一定會受到頻寬的限制,我們應該能夠根據模型配置、KV快取的大小和可用頻寬來估計推論過程所需的最小時間。

Mistral 的光速極限

在不過於深入討論確切公式和矩陣的情況下,讓我們看看像 Mistral 7B 這樣的模型,它有 72 億個參數 (因此所有矩陣元素的總數是 72 億)。

參數的組成如下:

- 4096 * 32000 = 1.31 億個嵌入矩陣的參數;這個矩陣不會用在矩陣向量乘法中,因為對每個字詞只會讀取矩陣的一行,所以我們不會將其納入頻寬計算。

- 32 * (4096 * (128 * 32 + 128 * 8 * 2) + 4096 * 128 * 32) = 13.42 億個用於計算注意力相關向量的參數。 

- 32 * (4096 * 14336 * 3) = 56.37 億個透過前饋網路轉換隱藏狀態的參數。

- 4096 * 32000 = 1.31 億個將隱藏狀態轉換為字詞機率的參數;這個矩陣會用在矩陣乘法中,與嵌入矩陣不同。

這加起來大約有 71.11 億個在矩陣乘法中使用的「活躍」參數。如果模型對矩陣元素使用 FP16,我們最終必須為每個字詞讀取約 14.2 GB 的資料。此外,雖然每個矩陣在為下一個字詞執行推論時都會再次使用,但快取的大小通常在幾十 MB 左右,因此我們可以假設這個過程無法比記憶體頻寬更快,因為權重在推論之間不會留在快取中。

這涵蓋了矩陣運算;注意力計算需要讀取直到當前字詞的 KV 快取,因此讀取的資料量取決於模型在生成新字詞時看到的字詞數量 ─ 包括系統提示 (通常對使用者隱藏)、使用者提示、先前的模型輸出,並且可以包括較長聊天階段的多個使用者提示。

對於 Mistral,KV 快取為每層的每個 key 儲存 8 個 128 維的向量,為每層的每個 value 儲存 8 個 128 維的向量,總共是每個字詞 32 * 128 * 8 * 2 = 65K 個元素;如果 KV 快取使用 FP16 儲存單個元素,那麼對於第 P 個字詞,我們需要讀取 P * 130 KB 的記憶體 ─ 例如,第 1000 個字詞需要從 KV 快取讀取 130 MB 的資料。

有了這些數字,現在很容易計算推論所需的最小時間。例如,在 NVIDIA RTX 4090 (1008 GB/s) 上,讀取 14.2 GB 大約需要 14.1 毫秒,因此我們可以預期對位置數較低的字詞,每個字詞大約需要 14.1 毫秒 (KV 快取的影響可以忽略不計)。如果我們使用 8 位元的權重,我們需要讀取 7.1 GB,這大約需要 7.0 毫秒。這些是下限 ─ 它們代表了理論上每個字詞可能的最小時間。


理論上限有用嗎?

我們做了一堆數學計算,得到了一些告訴我們推論速度無法超過給定閾值的數字 ─ 這有用嗎?讓我們看看為什麼它可能有用的幾個原因。

要真正達到該時間,你需要高品質的軟體實作,以及能夠達到理論峰值頻寬的硬體。這意味著,如果給定的實作遠低於最佳數字,就值得進行調查:效能可能遺留在軟體或硬體方面。例如,在 RTX 4090 上,使用 16 位元權重時,calm 可以達到每個字詞約 15.4 毫秒;使用 8 位元權重時,可以達到每個字詞約 7.8 毫秒 ─ 這大約是理論上可能效能的 90%。在使用 CPU 推論的 Apple M2 Air 上,calm 和 llama.cpp 都只達到了理論 100 GB/s 頻寬的約 65%,這表明引用的峰值頻寬只有在 iGPU 的幫助下才能完全利用。

頻寬與每個元素使用的位元組數呈線性關係;這意味著我們既可以從更小的權重格式 (量化) 估計理論效益,也可以透過將實際效能與理論極限進行比較來驗證實作的品質。例如,在 RTX 4090 上,使用 16 位元權重時,llama.cpp 可以達到每個字詞約 17.1 毫秒 (峰值的 82%);使用 8.5 位元權重時,可以達到每個字詞約 10.3 毫秒 (峰值的 71%);使用 4.5 位元權重時,可以達到每個字詞約 6.7 毫秒 (峰值的 58%),這表明對更小的格式還有很大的優化空間。

除了提供解碼時間的下限之外,上面的建模還表明,推論過程嚴重低估了 ALU 單元的利用率。要解決這個問題,需要改變 FLOP 與 byte 的平衡;投機解碼等技術試圖幫助解決這個問題,但對於多使用者的例子,我們可以注意到,當同時處理多個使用者請求時,我們可以在同一個矩陣上同時執行多個矩陣向量乘法(也就是矩陣矩陣乘法!)─ 矩陣矩陣乘法的最佳實作會在矩陣足夠大時變成ALU bound。這就是為什麼這種 ALU 與 byte 的不平衡對於生產環境的推論系統而言不是一個關鍵問題 ─ 當你要求 ChatGPT 幫助一項任務時,你的請求會與同一 GPU 上的許多其他請求同時進行評估,頻寬會被更有效地利用。至關重要的是,請求批次處理通常無法幫助減少 KV 快取的頻寬需求(除非這些請求共享非常大的前綴),因為 KV 快取的大小和頻寬會隨著請求數量增加,而權重矩陣保持不變。

像 Mixtral 這樣的專家混合模型有略微不同的縮放特性:批次處理最初只會增加所需的頻寬,但一旦專家利用率變得顯著,推論就會越來越受 ALU 的限制。

最後,如果無法進行批次處理,頻寬就成為預期推論效能的關鍵估算指標,它在不同的模型變體/設備類型或架構中保持不變,你可以用它來決定需要使用的硬體。例如,NVIDIA RTX 4080 有 716 GB/s 的頻寬,所以你可以預期它執行語言模型推論的速度大約是 RTX 4090 的 0.7 倍 ─ 這可能與其他工作負載(如遊戲、光線追蹤或其他類型神經網路的推論)的相對效能不同!

結論

對於像這樣計算量和記憶體訪問量已知的問題,將理論光速建模作為基準非常重要,因為它有助於驗證實作的品質並預測架構變化的影響。

理想情況下,你的推論實作應該仔細計算實現的有效頻寬,你應該在效能分析時將其作為主要指引 ─ 因為你知道這個值的極限!不過,一定要仔細計算 ─ calm 曾多次出現架構上的特殊情況,導致計算出的頻寬略有偏差:)


附錄:群組查詢注意力 (Group Query Attention)

Mistral-7B 是一個非常平衡的模型;在上面的所有計算中,KV 快取似乎並不是成本結構中不可或缺的部分。其中一個原因是相對較短的上下文(Mistral-7B 使用了視窗注意力,將頻寬消耗限制在 4096 個字詞的視窗中),但另一個可能更重要的原因,是使用了群組查詢注意力(Group Query Attention, GQA)。

在群組查詢注意力中(4倍比率),為了產生4個內積,我們不是使用4個查詢向量並與4個對應的鍵向量計算內積,而是取一個鍵向量但使用4個查詢向量,並執行4次內積運算。這使我們能夠減少KV快取的大小和所需的頻寬 ─ 我們不再是從KV快取中讀取每個元素並只對其進行一次乘加運算,而是現在進行4次運算,這在一定程度上重新平衡了ALU與頻寬的比率,對我們有利。

這對KV快取的記憶體大小也至關重要,但對於如此短的上下文可能並不明顯:4096個字詞的上下文在Mistral中佔用0.5 GiB,但沒有GQA的類似模型(如Llama 7B)「只」需要2 GiB。讓我們看看最近一個沒有使用GQA的模型,Cohere的Command-R。

該模型本身有約350億個參數,因此在每個權重16位元的情況下,我們在推論期間需要為每個字詞讀取70 GB的權重。對於每個字詞,它需要在KV快取中儲存40 * 128 * 64 * 2 = 655K個元素,在每個元素16位元的情況下,每個字詞是1.3 MB。

因此,4096個字詞的上下文將佔用約5.3 GB;與約70 GB的權重相比,這已經相當可觀了。然而,如果考慮到Cohere的模型號稱有20萬個字詞的上下文視窗,情況會變得更加可怕 ─ 要計算20萬個上下文視窗的最後一個字詞,你需要讀取260 GB!(讓我們暫時忽略你還需要260 GB的顯存來儲存它)

在典型的「生產」(仍然是單一使用者)環境中,情況會進一步改變。權重通常會使用4位元量化(通常實作為每個權重約4.5位元),而KV快取可能會使用8位元(FP8)值。如果我們「保守地」假設10萬個字詞的上下文(是宣稱最大值的一半),這將給我們帶來約19.7 GB的模型權重和約65 GB的KV快取,而要計算最後一個字詞,我們需要從記憶體中讀取所有這些資料。突然間,注意力計算從微不足道變成了佔用時間的約75%,假設兩者都以峰值頻寬執行!

儘管10萬個字詞的上下文可能看起來有點極端,但在多使用者的環境中,這也是預期工作負載的公平表示。批次處理允許我們使矩陣乘法變成ALU bound,並為每批值(即每64+個使用者請求)讀取一次模型權重,但每個使用者請求通常都有自己的KV快取,因此注意力計算仍然是頻寬bound ─ 並且需要大量記憶體才能將所有使用者的請求放在單個節點上!

如果這些模型使用了4倍GQA,KV快取所需的大小和頻寬就會小4倍;雖然對於數萬個字詞的上下文來說仍然很可觀,但會更容易管理。對於Cohere的預期使用情境,使用GQA可能會有一些品質下降 ─ 看看技術報告會很有趣,因為它可能包含相關的消融研究,但純粹從成本/效能的角度來看,每個基於transformer的語言模型都需要評估GQA,因為其優勢太顯著了,不容忽視。


個人見解:

在生成文字時,語言模型是逐字逐句依序產生,沒有辦法平行化處理。模型在處理每個字詞時,主要進行矩陣向量乘法和注意力(attention)計算。現代 CPU 和 GPU 的算術運算能力遠高於記憶體讀取速度,以至於推論過程的效能幾乎完全取決於記憶體頻寬。

藉由分析模型參數的組成和注意力機制的快取需求,我們可以預估推論每個字詞所需的最小時間。這個理論下限對於評估軟硬體效能非常有用:

  1. 如果實際效能遠低於理論值,代表軟硬體可能有優化空間。
  2. 不同精度(如FP16、INT8)的理論效能可以預估量化的潛在效益。
  3. 即使硬體架構不同,記憶體頻寬仍是一致的效能指標。

我認為作者提出了一個實用且具啟發性的效能模型。不只可以用來診斷效能瓶頸,也能輔助軟硬體設計的取捨。唯一的缺點是沒有涵蓋多使用者的情境,不過文中也簡單討論了批次處理(batching)的影響。

此外,作者特別強調了群組查詢注意力(Group Query Attention)的重要性。藉由增加每個注意力快取元素的運算量,GQA 顯著降低了快取占用的記憶體容量和頻寬。以 Cohere 的 Command-R 模型為例,如果使用 4x GQA,快取所需的記憶體和頻寬可以減少 4 倍之多。

我認為速度極限分析是效能工程不可或缺的一環。透過將實際效能與理論極限比較,我們可以系統性地找出優化方向,而不是憑直覺或運氣。當然,模型品質的權衡也不能忽視。畢竟再怎麼快,生成愚蠢的回覆也是沒有意義的。在效能與品質之間取得平衡,才是打造實用語言模型的不二法門。

不過,我也想補充幾點:

1. 文中假設讀取權重是效能的主要限制,但對某些硬體(如AI加速晶片)來說,這可能並不完全成立。晶片內部通常有專門的高速記憶體來儲存權重,因此讀取速度可能不是最關鍵的因素。

2. 推論速度只是語言模型實用性的一個面向。即使透過種種優化來逼近理論極限,品質和穩定性的問題仍然存在。生成不連貫或有害的內容,對使用者體驗的傷害可能大過延遲幾毫秒。品質和效能需要一起考量。

3. 文章聚焦於單一使用者的情境,但實際應用常常需要同時服務大量使用者。這時批次處理和記憶體效率的權衡會變得更加複雜。找出最佳的批次大小和排程策略,是一個值得深入研究的課題。

作者提出了一個實用的效能分析框架,揭示了當前語言模型推論的核心挑戰。這些洞見不僅有助於改進現有系統,也為未來的架構設計提供了方向。期待看到更多在效能、品質、應用場景等多方面尋求平衡的創新方案。

Chinchilla 擴展定律有缺陷?

 Epoch AI 的研究團隊最近發表了一篇有趣的論文,他們試圖複現 Hoffmann 等人在 2022 年提出的 Chinchilla 擴展定律。這個定律對於指導語言模型的訓練資源配置有著重要的參考價值。

https://arxiv.org/abs/2404.10102

Hoffmann 的團隊比較了三種方法來尋找最優的模型大小和訓練數據量的配比,其中一種是擬合一個參數化的損失函數。通過這個函數,可以直接推導出在給定計算預算下,應該如何平衡模型大小和數據量。這個定律本身在理論上就很有意思,引起了不少學者的關注。

但是,Epoch AI 的研究者發現,Hoffmann 的結果可能沒那麼可靠。由於原始資料不可得,他們只能從論文中的一張圖表著手,重建了一部分資料集。按照 Hoffmann 的方法去擬合參數,得到的結果與論文報告的數值差異很大。就算考慮到數據重建可能引入了一些誤差,擬合曲線與真實數據點的偏離也超出了合理的範圍。

此外,Hoffmann 給出的模型參數估計的置信區間極其狹窄,Epoch AI 計算出它們的寬度只有自己估計值的 1/50。要得到如此高的精度,大概需要幾十萬次的實驗,而 Hoffmann 的論文裡只提到了四百多個模型。

更令人疑惑的是,Hoffmann 估計出的最優 tokens/parameters 比例在 70 左右,但他們訓練 Chinchilla 模型時實際使用的卻是 20。這個結果也與論文中其他兩種方法得出的結論不一致。相比之下,Epoch AI 重新估計的參數得到的最優比例約為 20,反而與 Chinchilla 的實際設置和其他方法的結果更加吻合。

綜上所述,Epoch AI 的研究對 Hoffmann 的 Chinchilla 定律提出了質疑,認為其在統計擬合和蘊含的最優策略方面都存在一些問題。當然,這也可能是由於論文在繪製數據圖表時出現了失誤,導致重建數據時產生了偏差。無論如何,Hoffmann 的結果還需要進一步的驗證和澄清。


考慮到 Chinchilla 定律對於業界的重要影響,這一問題值得引起重視。許多研究者和工程師都參考了該定律來指導大模型的訓練,如果其中存在缺陷,可能會導致算力的浪費。因此,更多的複現和交叉驗證工作是非常必要的,只有經過嚴格的學術審視,才能確保研究成果的可靠性。

另一方面,Epoch AI 的分析也揭示了尋找最優配置策略的困難。在一個較大的計算預算區間內(如$10^{26}$~$10^{28}$ FLOP),tokens 和參數的最佳比例可能會在 4 到 40 這個範圍內波動。如果能進一步縮小這個區間,或許就能節省下可觀的計算開銷。

根據 Chinchilla 定律,對於計算資源最優的訓練方式,模型參數量應該與訓練 tokens 數同步增長,即每當模型大小翻倍,訓練數據量也應翻倍。這一洞見對業界產生了顯著的影響。許多知名的語言模型,如 Google 的 Gemini 系列,都參考了 Chinchilla 定律來設計訓練方案。可以說,它在一定程度上指引了近年來大模型的發展方向。

然而,Epoch AI 最近的一項複現研究對 Chinchilla 定律提出了質疑。他們發現,Hoffmann 的參數擬合結果很難在重建的數據集上複現,得到的最優 tokens/parameters 比例與實踐中的設置差異較大。這引發了人們對 Chinchilla 定律可靠性的討論。

儘管還需要更多的驗證和澄清,但 Epoch AI 的工作提醒我們,即便是有影響力的研究成果,也需要保持審慎的態度。盲目地遵循某個定律,而不考慮其適用性和局限性,可能會導致算力的浪費,甚至模型性能的損失。

另一方面,Epoch AI 的分析也揭示了尋找最優訓練策略的複雜性。在不同的計算預算區間內,最佳的 tokens/parameters 比例可能會有較大的波動。這意味著,Chinchilla 定律給出的 "20:1" 的經驗法則可能並非放之四海而皆準。對於不同的模型架構、數據領域和目標任務,可能需要進一步調整和優化這個比例。

Chinchilla 定律作為一個先驅性的工作,為大語言模型的訓練提供了寶貴的見解。它促使研究者和從業者更加深入地思考計算效率問題,並在實踐中不斷探索最優的資源配置策略。然而,我們也需要認識到,任何定律都有其適用範圍和局限性。隨著技術的發展和認知的深入,對 Chinchilla 定律的理解和應用也需要與時俱進。

Google的"大力出奇蹟"!!

這是我第三次評論這篇論文, 重要的報告我講三次, 很重要!很重要!很重要!我認為這個模型會超越Mamba!

https://arxiv.org/pdf/2402.19427.pdf

近年來,Transformer語言模型在多個自然語言處理任務上取得了巨大成功,但其全局注意力機制在處理超長序列時面臨計算瓶頸。另一方面,循環神經網絡(RNN)長期以來被認為更適合對長距離依賴進行建模,但其串行計算特性限制了訓練和推理效率。為了兼顧長程建模能力和計算效率,Google提出了Griffin——一種融合了門控線性遞迴單元(RG-LRU)和局部多頭注意力(Local Multi-head Attention)的混合語言模型。

Griffin模型

整體架構

Griffin的主體是一個堆疊的Transformer結構,包含L個殘差塊(L一般取12~40)。每個殘差塊包含兩個子結構:多層感知器(MLP)和時序混合塊。其中,MLP塊在所有殘差塊中共享,而時序混合塊在不同層中交替使用RG-LRU塊和局部注意力(Local Attention)塊。模型的輸入是一個長度為N的token序列,通過詞嵌入(Embedding)層映射為H維稠密向量。最終輸出通過嵌入矩陣的轉置進行復原,並計算softmax交叉熵損失。

MLP塊

Griffin的MLP塊基於門控線性單元(GLU),包含兩個并列的全連接層(尺寸為H->H)和一個GLU激活函數。計算公式為:
$$ f(x) = (W_1 x + b_1) \otimes \sigma(W_2 x + b_2) $$
其中$W_1,W_2 \in R^{H \times H}, b_1,b_2 \in R^H$分別為兩個全連接層的權重矩陣和偏置項,$\sigma$為Sigmoid函數,$\otimes$為按元素乘法。相比ReLU等激活函數,GLU可以更好地建模輸入之間的非線性交互作用。

時序混合塊

RG-LRU

RG-LRU是Griffin的核心創新之一,旨在改進傳統RNN捕捉長距離依賴的能力。給定輸入序列$x_1,\dots,x_N$,RG-LRU逐步計算隱狀態序列$h_1,\dots,h_N$。在時刻t,RG-LRU執行以下運算:
$$r_t = \sigma(W_{xr} x_t + b_r)$$
$$i_t = \sigma(W_{xi} x_t + b_i)$$
$$\tilde{A}_t = \text{diag}(r_t) A^T \text{diag}(r_t)$$
$$h_t = \tilde{A}t h{t-1} + \sqrt{1-\tilde{A}_t^2} \odot (i_t \odot x_t)$$
其中$r_t,i_t \in R^H$分別為遞迴門和輸入門,$W_{xr},W_{xi} \in R^{H \times H}$和$b_r,b_i \in R^H$ 為門控單元的參數,$A \in R^{H \times H}$為一個對角矩陣,對角線元素在(0,1)範圍內。運算$\odot$表示按元素乘法。
RG-LRU引入了兩個關鍵的改進:
(1) 遞迴門$r_t$控制了過去狀態$h_{t-1}$的保留程度,其中$\tilde{A}_t$是對$A$應用$r_t$進行插值的結果。當$r_t$接近1時,模型傾向於保留過去信息;當$r_t$接近0時,模型傾向於遺忘過去信息,只關注當前輸入$x_t$。這種自適應的記憶機制使RG-LRU能靈活地應對不同時間尺度的依賴關係。
(2) 輸入門$i_t$控制了當前輸入$x_t$對隱狀態$h_t$的貢獻。與LSTM等傳統RNN不同,RG-LRU的輸入門不依賴上一時刻的隱狀態,從而實現了$O(1)$的順序計算復雜度。

局部注意力

除了RG-LRU塊,Griffin還周期性地插入局部多頭注意力(Local Multi-head Attention)塊,用於捕捉中短距離的token級別交互。給定隱狀態序列$h_1,\dots,h_N$,局部注意力在每個位置$t$處計算加權平均表示$o_t$:
$$o_t = \sum_{i=t-M}^{t+M} \alpha_{ti} (W_V h_i)$$
其中$M$為注意力窗口的半徑,$W_V \in R^{H \times H}$為值(Value)映射矩陣。注意力權重$\alpha_{ti}$通過查詢向量$q_t$和鍵向量$k_i$的內積計算:
$$\alpha_{ti} = \frac{\exp(q_t^T k_i)}{\sum_{j=t-M}^{t+M} \exp(q_t^T k_j)}$$
其中$q_t = W_Q h_t, k_i = W_K h_i$,對應的投影矩陣為$W_Q,W_K \in R^{H \times H}$。為了建模多種類型的依賴關係,Griffin使用多頭注意力機制,計算公式為:
$$o_t = W_O[o_t^{(1)},\dots,o_t^{(K)}] + b_o$$
其中$o_t^{(k)}$是第$k$個注意力頭的輸出,$W_O \in R^{H \times KH},b_o \in R^H$為最終的線性變換參數。
在實踐中,我們發現設置注意力窗口大小$2M+1=1024$,注意力頭數$K=32$可以取得最佳的性能。這種局部注意力機制顯著降低了計算複雜度(從$O(N^2)$減少到$O(NM)$),且與RG-LRU形成了很好的互補。

作為堅定支持者,Google 的 Griffin 論文完美地展示了Scaling laws。當他們將模型參數擴大 7 倍時,在各項任務上的表現大約提升了 10%。所有模型都是在相同的 3000 億 tokens 數據上訓練的。隨著參數的增加,模型變得更加樣本有效,外推能力也更強。

位置編碼

為了將序列中的位置信息引入模型,Griffin沿用了Transformer中的相對位置編碼方案。具體來說,在局部注意力模塊中,我們將位置編碼信息添加到鍵向量和查詢向量內積中:
$$\alpha_{ti} = \frac{\exp(q_t^T k_i + q_t^T r_{i-t})}{\sum_{j=t-M}^{t+M} \exp(q_t^T k_j + q_t^T r_{j-t})}$$
其中$r_{\Delta t} \in R^H$是一個可學習的相對位置編碼向量,表示時間步$t$和$i$之間的距離$\Delta t = i-t$的影響。

這是 Google 的一項突破性研究成果。

Google 發布了具有新 Griffin 架構的模型,其性能優於 Transformer。


訓練與推理優化

參數高效性

得益於RG-LRU的線性計算特性,Griffin的參數量和計算復雜度與層數L呈線性關係。具體來說,設模型隱藏層維度為H,詞表大小為V,則Griffin的參數量近似為:

$$\text{Params} = 4LH^2 + 2VH$$

其中$4LH^2$項對應MLP塊、RG-LRU和注意力層的權重矩陣參數,$2VH$對應詞嵌入矩陣及其轉置。考慮到$H << V$,模型的參數量主要由詞嵌入矩陣主導。這意味著Griffin可以通過增加深度L來提高模型容量,而不會導致參數量過度膨脹。通過控制隱藏層維度H,在保持參數量不變的情況下比較Griffin和Transformer在不同層數L下的性能。


GPU/TPU並行化

雖然RG-LRU易於實現廉價的串行計算,但為了充分利用現代加速器(如GPU和TPU)的並行能力,還需要對其進行並行化改造。受益於RG-LRU的簡潔性,可以輕松地將其計算過程表示為一系列矩陣乘法和逐元素操作,從而實現高效的批量化(Batching)和張量化(Tensorization)加速。

在訓練時,將一個批次的輸入序列表示為形狀為$[B, N, H]$的三維張量,其中$B$為批次大小。通過將第二維(長度維)的計算映射到加速器的不同線程/內核上,Griffin可以實現與Transformer相當的訓練吞吐量。對於局部注意力層,使用了快速注意力(Fast Attention)算法,通過計算局部注意力權重的前綴和(Prefix Sum),將總體複雜度降低到$O(BNH)$。

在推理時,需要逐步生成輸出序列。與Transformer需要維護一個隨生成長度增長的鍵值緩存(Key-Value Cache)不同,RG-LRU只需要維護一個固定大小的隱狀態向量$h_t$,從而顯著節省了內存佔用。此外,Griffin還可以利用內存化(Memorization)技術,即將每一層的輸出都保存到一個大小固定的循環緩衝區中,供下一層計算時復用。這種做法避免了在深層模型中重複計算前幾層的結果,進一步提升了推理速度。

接下來,研究者還選取了三個專門用於評測長距離依賴建模能力的任務:LAMBADA、ListOps和Pathfinder。其中,LAMBADA是一個基於上下文的單詞預測任務,ListOps需要模型執行算術運算,而Pathfinder則考察模型在網格圖上進行推理的能力。實驗結果顯示,Griffin在這些任務上的表現也一致地超過了基線模型。值得注意的是,隨著序列長度的增加,Griffin的優勢變得更加明顯,這歸因於RG-LRU層強大的遞歸歸納能力。

在推理效率方面,Griffin展現出了明顯的優勢。得益於RG-LRU層恆定的內存佔用和局部注意力的線性計算複雜度,Griffin在生成超長文本時的推理速度比Transformer-XL等模型快2~3倍,且內存佔用減少了50%以上。這使得Griffin非常適合應用於資源受限的場景,如移動設備或實時系統。

混合精度訓練

為了進一步提高訓練效率並節省顯存,採用了混合精度(Mixed Precision)訓練策略。具體來說,模型的前向和反向傳播過程使用半精度浮點數(FP16),而模型權重的更新則在單精度(FP32)下進行。通過這種設置,可以將訓練所需的顯存減少近50%,同時保持模型的收斂性和最終性能。我們還發現,對梯度應用動態缩放(Dynamic Scaling)技術可以進一步提高混合精度訓練的穩定性。

為了深入分析Griffin的行為特徵,研究者還進行了一系列消融實驗。首先,他們探究了不同超參數(如層數、隱藏狀態維度、注意力頭數等)對模型性能的影響。結果表明,增加Griffin的層數和寬度都能帶來性能的提升,且效果優於同等大小的Transformer模型。其次,研究者還考察了不同注意力範圍對Griffin的影響。他們發現,當注意力窗口大小在1024左右時,模型在各個任務上的表現最優,且即使在更長的序列長度下也能保持優勢。

他們在WikiText-103、One Billion Word和PG-19等語言建模數據集上測試了Griffin的泛化能力。這些數據集包含了不同長度、主題和風格的文本,可以全面評估模型在長距離依賴關係上的建模能力。實驗中,研究者控制了模型的參數量,以公平地比較Griffin與其他基線模型的性能。結果表明,Griffin在所有數據集上都取得了最優的perplexity(PPL)分數,顯著優於Transformer-XL、Compressive Transformer等現有方法。

接下來,研究者還選取了三個專門用於評測長距離依賴建模能力的任務:LAMBADA、ListOps和Pathfinder。其中,LAMBADA是一個基於上下文的單詞預測任務,ListOps需要模型執行算術運算,而Pathfinder則考察模型在網格圖上進行推理的能力。實驗結果顯示,Griffin在這些任務上的表現也一致地超過了基線模型。值得注意的是,隨著序列長度的增加,Griffin的優勢變得更加明顯,這歸因於RG-LRU層強大的遞歸歸納能力。

為了深入分析Griffin的行為特徵,研究者還進行了一系列消融實驗。首先,他們探究了不同超參數(如層數、隱藏狀態維度、注意力頭數等)對模型性能的影響。結果表明,增加Griffin的層數和寬度都能帶來性能的提升,且效果優於同等大小的Transformer模型。其次,研究者還考察了不同注意力範圍對Griffin的影響。他們發現,當注意力窗口大小在1024左右時,模型在各個任務上的表現最優,且即使在更長的序列長度下也能保持優勢。

在推理效率方面,Griffin展現出了明顯的優勢。得益於RG-LRU層恆定的內存佔用和局部注意力的線性計算複雜度,Griffin在生成超長文本時的推理速度比Transformer-XL等模型快2~3倍,且內存佔用減少了50%以上。這使得Griffin非常適合應用於資源受限的場景,如移動設備或實時系統。

結論

1. RG-LRU(Real-Gated Linear Recurrent Unit):

RG-LRU是Griffin模型的核心組件之一。它是一種新型的門控線性遞迴層,其設計靈感來自於標準的LRU(Linear Recurrent Unit)和LSTM/GRU中使用的門控機制。 

具體來說,RG-LRU引入了兩個門:遞迴門r_t和輸入門i_t,它們分別控制前一時刻隱狀態h_{t-1}和當前輸入x_t對新隱狀態h_t的貢獻。與LSTM/GRU不同的是,RG-LRU的門不依賴於前一時刻的隱狀態,這樣可以顯著提高計算效率。

遞迴門r_t進一步調節一個對角矩陣A_t,使其在保留歷史信息(r_t->1時A_t->I)和遺忘歷史信息(r_t->0時A_t->0)之間進行非線性插值。這種獨特的門控方式使RG-LRU能學會在長序列上選擇性地汲取信息。

RG-LRU還有一個復數版本CG-LRU(Complex-Gated Linear Recurrent Unit),它將輸入和隱狀態表示為復數,並使用復數矩陣參數,以提高层的表示能力。但實驗發現,在語言建模任務上,實數版本的RG-LRU性能並不亞於CG-LRU。

2. 時序混合(Temporal Mixing): 

Griffin採用分層的時序混合方式,在12-40層的網路中,每3層就混合一個RNN塊(含3個RG-LRU層)和一個局部MQA(Multi-Query Attention)層。這樣的結構讓模型在捕捉長距離依賴的同時,也能很好地對局部範圍內的信息進行匹配。

實驗顯示,對於序列長度為2048的預訓練,局部MQA的最優窗口大小在1024左右。當序列長度增加到4096、8192時,1024的窗口大小仍然能取得比全局注意力Transformer更好的效果。這表明Griffin利用RNN積累長程信息的能力可以很好地彌補局部注意力的不足。

3. 硬體加速:

為了高效地在TPU-v3上訓練RG-LRU,研究者實現了定製的Pallas內核,將線性掃描運算中的內存讀寫次數降到最低。這使得RG-LRU在訓練加速比上可以達到Transformer的水平(記憶體帶寬約為900GB/s)。

同時,由於RG-LRU的隱狀態大小和局部MQA的KV cache大小遠小於Transformer的KV cache,Griffin在推理階段表現出了顯著的延遲優勢(低20%以上)和吞吐量優勢(高3倍以上)。這在生成超長序列時尤為明顯。

4. 外推和零樣本學習:

研究者在一個書籍語料(Books)和arXiv語料上評估了Griffin的外推(extrapolation)能力,即在遠長於訓練序列的長度上生成文本的能力。實驗表明,Griffin可以在長達訓練序列4倍的序列上穩定地利用更長上下文改進預測。而Transformer受限於其位置編碼,很難在超出訓練序列長度時維持較好表現。

此外,Griffin還在幾個合成的復制/檢索任務(Selective Copying、Induction Heads、Phone Number Lookup)上接受了測試。結果顯示,Griffin可以在監督訓練下快速學會這些任務所需的復制檢索技能。但在零樣本(zero-shot)設定下,預訓練的Griffin模型在這些任務上的外推能力仍然不及Transformer。這可能與局部注意力和RNN對字面匹配(verbatim match)的能力有限有關。

5. 訓練規模與下游任務性能:

研究者在100M到14B參數規模下訓練了Griffin,Hawk和Transformer模型,並在MMLU、HellaSwag、PIQA等7個下游任務上進行了評估。結果顯示,在只用300B tokens訓練的情況下:

- Griffin和Hawk在所有任務上的平均得分隨模型規模增大而穩定上升,其中Griffin在所有規模下都超過Transformer。

- Hawk-3B顯著超過了用600B tokens訓練的Mamba-3B。

- Griffin-7B/14B則在多數任務上達到甚至超過了用2T tokens訓練的Transformer模型Llama-2的水平。

這充分展現了Griffin超越Transformer的樣本效率。

綜上所述,Griffin通過巧妙融合RNN和局部注意力,在計算效率、樣本效率、長程建模等多方面取得了超越Transformer的效果,是一種非常有前景的新型語言模型架構。未來還可以進一步探索如何改進其在超長序列上的注意力機制,以及在零樣本語言任務上的外推和泛化能力。在工程實踐中,Griffin有望憑藉其出色的推理性能在長文本應用場景大放異彩。

解決長篇語音轉譯中的斷句問題

Google Research與Johns Hopkins共同˙發表了這篇論文:

「Long-Form Speech Translation through Segmentation with Finite-State Decoding Constraints on Large Language Models」,探討如何利用大型語言模型(Large Language Models, LLMs)來進行長篇語音轉譯的斷句,以提升整體翻譯品質。

語音轉譯通常採用串聯式(cascade)方法,將語音辨識(ASR)和機器翻譯(MT)分開處理。但MT模型大多以句子為單位進行獨立翻譯,對於冗長的段落或語音輸入,往往會產生錯誤或品質下降。因此,如何將長篇語音轉譯內容適當斷句,使其成為可獨立翻譯的片段,是一個重要的研究課題。


實驗方法:

1. 滑動視窗法(Windowing Approach):考慮到輸入序列可能非常長,作者採用滑動視窗將其切分為固定長度的片段,每個片段有部分重疊以獲取上下文資訊。此方法兼顧雙向資訊和計算效率。

2. 大型語言模型(LLMs):作者將斷句任務視為序列到序列(sequence-to-sequence)問題,利用T5和PaLM等預訓練大型語言模型進行few-shot或fine-tuning學習。透過prompt engineering引導模型生成帶有斷句標記的輸出序列。

3. 有限狀態約束(Finite-State Constraints):為確保LLM生成的輸出格式正確(well-formed),作者引入有限狀態約束進行解碼,排除不合法的輸出,無需額外訓練。此外,也可用Levenshtein對齊演算法進行後處理校正。  

4. 訓練資料擴增:作者以真實語音辨識結果(含語音錯誤)fine-tune LLM,提升對非流暢輸入的豐富性(Robustness, 我不是很喜歡翻譯成魯棒姓)。


實驗結果:

在三個語言(英文到德文、西班牙文、阿拉伯文)的IWSLT語音翻譯測試集上,作者的方法相較傳統基線(先斷句再翻譯),平均可提升2.9 BLEU分數,大幅縮減與上界(先斷句再以人工斷句projected到ASR output)的差距。

- 有限狀態約束對模型輸出品質的影響顯著,尤其是在小模型、prompt tuning、few-shot等情境。

- 以ASR結果fine-tune LLM可提升斷句準確率,但對翻譯品質的進一步提升有限。

- 定性分析發現,ASR錯誤仍是LLM剩餘斷句錯誤的主因。增大sliding window可減少extra-long phrases。 

本文展示了如何利用大型語言模型搭配有限狀態約束,解決長篇語音轉譯中的斷句問題,在多個測試集上取得顯著效果提升。在現有串聯式語音轉譯架構下,此方法可即插即用,不需修改下游MT模型。

https://arxiv.org/pdf/2310.13678.pdf

IWSLT (International Workshop on Spoken Language Translation) 是一個專注於口語翻譯研究的年度研討會,其目的是促進語音轉譯技術的發展。作為研討會的一部分,IWSLT提供了多種語言pair的語音翻譯測試集,供研究者評估和比較他們的系統性能。

IWSLT語音翻譯測試集的主要特點如下:

1. 語料類型:測試集的語音資料主要來自TED演講,內容涵蓋科技、娛樂、設計等多個領域。這些演講通常篇幅較長,語速適中,且經過人工轉錄和翻譯。

2. 語言pairs:IWSLT提供了多種源語言到目標語言的組合,如英語到德語、英語到中文、英語到日語等。每個語言pair都有獨立的語音轉譯測試集。

3. 評估方式:參與者需要將源語言語音轉錄為文字(ASR),再將文字翻譯為目標語言(MT)。最終的翻譯結果將與人工翻譯參考答案進行比較,通常使用BLEU等自動評估指標計算分數。

4. 數據集劃分:每年的IWSLT語音翻譯測試集通常分為三部分:訓練集(train)、開發集(dev)和測試集(test)。訓練集用於模型訓練,開發集用於調參和模型選擇,測試集則用於評估最終系統性能。

5. 延續性:IWSLT測試集每年都會更新和發布,因此研究者可以在同一基準上追踪語音翻譯技術的進展。部分測試集(如IWSLT 2018)會被重復使用,以保證橫向比較的可能性。


舉例而言,在本文中作者使用了IWSLT英德、英西、英阿三個語言pair的語音翻譯測試集,其中訓練集和開發集來自IWSLT 2014,測試集包括IWSLT 2015和2018。通過在這些公開測試集上評估斷句方法,作者展示了其技術相較基線的優越性能。

總的來說,IWSLT語音翻譯測試集為口語翻譯研究提供了標準化的評估平台,推動了該領域的技術進步。不過受限於語料類型和領域,結果還需要結合更多實際應用場景進行驗證和調適。

儘管LLM在該任務表現優異,但其推論成本高、延遲長,尚不適合線上即時系統。未來可朝向更長篇章、端到端、ASR錯誤修正等方向繼續研究。本研究豐富了長篇語音轉譯的解決方案,對後續研究相當具有啟發性。


BLEU (Bilingual Evaluation Understudy) 是一種常用於評估機器翻譯品質的指標。它通過比較機器翻譯輸出與人工參考翻譯之間的相似度來給出一個數值分數,範圍通常在0到1之間(或0到100)。分數越高,表示機器翻譯輸出與人工翻譯越接近,品質也越好。

BLEU的計算方式如下:

1. N-gram精確度(N-gram precision):計算機器翻譯輸出中,有多少N-gram(通常N=1,2,3,4)出現在參考翻譯中。這衡量了翻譯的精確度。

2. 修正的N-gram精確度:為避免機器翻譯輸出過度重複高頻N-gram以獲得較高分數,BLEU對每個N-gram在參考翻譯中的出現次數設置了上限(clipped)。

3. 懲罰因子(Brevity Penalty):若機器翻譯輸出長度遠小於參考翻譯,即使N-gram精確度高,也會受到懲罰。這是為了避免過短的翻譯獲得較高分數。

4. 加權幾何平均值:將不同N的精確度(N=1,2,3,4)取加權幾何平均,再乘以懲罰因子,得到最終的BLEU分數。

舉例來說,假設機器翻譯輸出為 "the cat is on the mat",參考翻譯為 "there is a cat on the mat",則:

- 1-gram精確度為3/6(the,cat,on)

- 2-gram精確度為1/5(the cat)

- 3-gram精確度為0/4

- 4-gram精確度為0/3

假設加權為平均權重,懲罰因子為1(長度相等),則BLEU分數約為0.47。

需要注意的是,BLEU僅基於N-gram重疊度,無法考慮語義、語法等因素,因此並非完美指標。但由於其簡便性和與人工評估的高度相關性,仍被廣泛用於機器翻譯的評估和比較。在實務上,通常會搭配其他指標(如METEOR、TER)和人工評估一起使用。

SPECTRA: 評估AI模型在真實世界中的泛化能力

這篇報告很有價值,因為我曾經參與生物晶片公司的經營,而這篇報告中發表的麻州總院醫師是我很要好的朋友, 不過因為涉及更多的不同的專業知識領域, 因此我嘗試介紹大家從生命科學研究及新藥突破的角度如何更多的讓AI幫助現在醫學有效完成創新工作來讀這篇報告,如果您覺得很艱澀或與工作無直接相關可以跳過。

https://www.biorxiv.org/....../2024.02.25.581982v1......

這篇研究論文的主題在探討如何更有效率地評估人工智慧(AI)模型在分子序列資料集上的泛化能力。現有的評估方法往往只考慮元數據(metadata)或序列相似性,來將資料集切分成訓練集和測試集,但這種作法無法完整評估模型的泛化性。

作者提出了一個叫做SPECTRA的新評估框架,主要有三大特色:

1. 引入了光譜性質(spectral property)的概念,泛指那些會影響模型泛化性的分子序列特性。透過定義任務相關的光譜性質,就能更全面地衡量模型的表現。

2. 利用光譜性質圖(spectral property graph)來生成一系列具有不同訓練測試集重疊程度的資料切分。這樣就能觀察模型在各種情境下的表現,而不侷限在單一的切分方式。 

3. 定義了光譜性能曲線(spectral performance curve)和曲線下面積(AUSPC),將模型在不同重疊程度下的測試結果整合成單一指標,方便進行橫向比較。


研究團隊將SPECTRA應用在18個分子序列資料集上,涵蓋結核桿菌抗藥性、新冠病毒疫苗逃逸、蛋白質螢光等任務。他們評估了多種主流AI模型,包括大語言模型、圖神經網路、擴散模型等。實驗結果顯示:

1. 現有的基於元數據或序列相似性的切分方法只能反映光譜性能曲線上的個別點,無法全面評估模型泛化力。

2. 隨著訓練測試集重疊程度降低,所有模型的性能都會下降,但下降幅度因任務和模型而異。沒有哪種模型能在所有任務上都保持最佳表現。

3. 藉由觀察光譜性能曲線,研究人員還發現了一些之前被忽略的光譜性質,例如結核桿菌中rifampicin抗藥性的突變位置差異(diff-RRDR),進一步證實SPECTRA的實用價值。

此外,作者也展示了如何用SPECTRA來評估蛋白質基礎模型(如ESM2)的泛化能力。他們發現基礎模型在跟預訓練資料集相似度高的下游任務上表現較好,呼應了其他研究者的觀察。

總的來說,這項研究提出了一種更嚴謹、更全面的AI模型評估方法,填補了現有基準測試的不足。SPECTRA框架有助於研究人員深入理解模型的泛化行為,揭示潛在的影響因子,為開發更魯棒的AI系統鋪路。

作者也坦承SPECTRA在計算成本上比較高,但指出這是值得的投資,畢竟模型評估跟模型訓練一樣重要,攸關AI技術能否安全可靠地應用到重大場景中。未來SPECTRA還能擴展到多模態資料和其他領域,有很大的應用潛力。


以下是我個人觀點:

這篇論文雖然沒有直接談到新藥開發或簡易試劑產業,但其提出的SPECTRA框架對這兩個領域結合AI技術都有重要啟示:

1. 新藥開發方面:

藥物設計高度仰賴對蛋白質結構、性質及其與小分子ligand的交互作用的預測。而AI模型在這方面已經展現了巨大潛力,例如AlphaFold 2在蛋白質結構預測上的突破。然而,要讓AI模型真正可靠地應用於新藥開發流程,我們必須徹底評估其泛化能力。

SPECTRA框架為這個挑戰提供了新思路。藥物化學家可以根據先驗知識,定義与药效、毒性、藥代動力學相關的光譜性質,用SPECTRA生成全面的資料切分,深入分析模型在各種情境下的表現。這有助於揭示AI模型的侷限性,找出可能導致臨床試驗失敗的潛在因素。

藉由SPECTRA,我們可以建立更嚴謹的新藥AI模型評估標準,加速可解釋、可遷移的AI輔助藥物設計系統的發展,提高新藥研發的成功率。

2. 簡易試劑產業方面:

簡易試劑如新冠家用快篩,在疾病防控中扮演了關鍵角色。但要設計出穩定、靈敏、特異性高的快篩試劑,同樣需要精準預測抗原抗體的互動。AI模型在這方面大有可為,但也面臨泛化能力的挑戰。

運用SPECTRA框架,試劑廠商可以模擬各種可能影響快篩效能的因素,如抗原變異、環境干擾等,全面評估AI模型的魯棒性。這可以幫助優化試劑配方,找出最佳的抗原表位和抗體組合,降低批次差異。

此外,SPECTRA還能用於診斷模型的評估,揭示AI系統在不同人群、地區、疾病階段的表現差異,提前發現潛在的偽陰性、偽陽性風險。這對開發更可靠的快篩試劑和診斷算法至關重要。

總之,SPECTRA框架為生物醫藥產業AI落地提供了新思路和工具。藉由全面、嚴謹地評估AI模型在真實世界中的泛化能力,我們可以加速建立可信、可用的AI系統,推動新藥研發和簡易試劑產業的創新發展,造福大眾健康。

《普羅米修斯: Prometheus》中的「工程師」創造了「異形」?

在《異形》系列的世界觀中,有個創造「人類」和「異形」,綽號被稱為「工程師」的種族,在《異形》電影第一集的人們還叫他們為「太空騎師」,也有人稱他們為 Mala’kaks。我這裡可以直接說他就是LLM工程師。(請原諒我這麼形容工程師)


所以「工程師」可能是「異形」的創作者,但也有可能只是將「異形」弄成自己兵器的「改良者」? AI大模型時代的「工程師」是不是在打造異形呢?

評估機器生成文本的品質一直是自然語言處理(NLP)領域的長期挑戰,在大語言模型(LLM)時代更顯得至關重要。我們需要深入了解 LLM 的特性和行為,才能更好地應用和改進它們。過去,人工評估一直是主要方法,因為人類能夠可靠地評估文本中的細微差別。例如簡潔性、創造力、語氣和文化差異。相比之下,傳統的自動評估指標(如BLEU、ROUGE)無法捕捉到人工評估的深度和精細度。

最近,使用大型語言模型(如GPT-4)作為評估工具受到了廣泛關注,因為它有可能達到與人工評估相當的水準。初步研究表明,如果提示得當,LLM可以模仿人類評估的精細程度。然而,儘管使用專有LLM作為評估工具的優點是顯而易見的,但也存在一些關鍵缺點:

1. 封閉原始碼:專有LLM的內部運作沒有向更廣泛的學術界披露,缺乏透明度,阻礙了集體學術努力來改進或提升其評估能力。此外,這將學術界的核心原則──公平評估,置於營利實體的控制之下,引發了中立性和自主性的擔憂。

2. 無法控制版本:專有模型經常進行版本更新,但用戶無法掌控。這帶來了再現性挑戰。再現性是科學探究的基石,版本變化導致的任何不一致都可能破壞依賴特定模型版本的研究發現的穩健性,尤其是在評估領域。

3. 高昂成本:LLM API的財務約束並非無足輕重。例如,在1000個評估實例上使用GPT-4評估四種大小(從7B到65B)的四種LLM變體,成本可能超過2000美元。這種規模的成本對學術機構或預算有限的研究人員來說可能是難以承受的。

儘管有這些局限性,專有的LLM(如GPT-4)能夠根據定制的評分規則來評估分數。具體而言,目前的資源局限於通用的、單一維度的評估指標,要麼過於特定領域/任務(例如EM、Rouge),要麼過於粗糙(例如helpfulness/harmlessness)。

例如,AlpacaFarm的提示給出了偏好的單一定義,要求模型選擇普遍偏好的模型響應。然而,響應偏好會因具體應用和價值觀而有所不同。在現實世界中,用戶可能對定制的評分規則更感興趣,例如「哪種LLM生成的響應更有趣、幽默」或「哪種LLM在回答時特別注重文化敏感性」。然而,在我們的初步實驗中,我們發現即使是最大的開源LLM(70B)與專有LLM相比,也不足以根據定制的評分規則進行評估。

這個論點也與我們經常在AI Agent中辯論的AI應該"更有用"還是"更有趣"非常相似。坦白說電影中出現的具身智能機器人都是"有靈魂"的, 但現實中我們寧願AI是個"工具助理"。儘管他已經可以幹不少"Copilot"的事情。

為了解決這些問題,KAIST AI, NAVER AI Lab,  NAVER Cloud,  Washington大學, MIT共同提出了Prometheus,一個13B參數的語言模型,旨在引入GPT-4的細粒度評估能力,同時保持開源、可重現和低成本。

https://arxiv.org/pdf/2310.08491.pdf

這篇文章探討了如何在沒有昂貴GPU的情況下,利用各種開源軟體元件來進行「LLM as Judge」的評估。在當前快速發展的AI領域中,成本和評估往往不像新模型的發表那樣受到關注,但它們對開發者和企業應用AI系統至關重要。眾所周知,預訓練LLM的成本極高;而像OpenAI這樣封閉原始碼的LLM使用起來也很昂貴。


評估不僅對了解模型的效能表現至關重要,也有助於確定哪種模型最適合特定場景。當LLM被用來評估其他模型時(即所謂的LLM as Judge),評估本身的成本也可能很高。雖然推論優化技術也適用於LLM Judge,但似乎沒有多少人對此感興趣。

Justine Tunney推薦了一篇博文,我認為非常值得一看:

https://blog.mozilla.ai/local-llm-as-judge-evaluation....../

本文作者檢視了幾個軟體元件如何組合在一起,實現了無需昂貴GPU的LLM as Judge評估。這些元件在設計時就強調了使用者控制、開源特性和互通性。

其中包括了用於LLM as Judge評估的開源模型Prometheus(所以擔心LLM工程師造出了AI異形?)、作者參與的mzai團隊開發並開源lm-buddy工具(用於擴展微調和評估任務)以及Mozilla創新項目llamafile(將LLM打包成單一可攜式檔案)。作者展示了這些元件如何協同運作,在相對便宜的硬體上評估LLM,以及他們如何衡量評估模型本身的性能來做出明智的選擇。

作者特別欣賞Firefox的一個功能:在網址列輸入「moz://a」,就會自動跳轉到Mozilla的宣言。Mozilla誕生自開源理念,其宣言談到了對AI演算法的控制權和用戶體驗的原則。在目前由封閉的AI即服務平台主導的市場中,這一點格外重要。

Mozilla的宣言引起了作者的共鳴,讓他重新審視這些原則在日益被AI演算法影響的現代網路中的意義。如果將「網際網路」替換為「AI演算法/框架」,Mozilla宣言中的原則仍然非常貼切。舉例來說,可以解讀為:

- 個人應該能主導AI演算法,塑造自己的使用體驗

- AI框架的效能取決於互通性、創新力和去中心化的參與

- 自由開源軟體能推動AI成為公共資源

若專注在LLM這個AI的子領域,就能看出這些原則在目前由封閉、中心化AI即服務平台主導的市場中有多麼重要。事實上,我們已經看到更開放的替代方案如雨後春筍般湧現。

儘管業界可能還未形成對開源AI的共識,但新模型持續以開源授權的方式發布在HuggingFace上。它們附上了預訓練的權重,可以直接使用或進行微調。有時也會發表論文,詳述模型訓練和使用的資料。但考慮到研究和再現性而分享訓練代碼、檢查點和訓練資料的模型非常少。這少數的例子包括BLOOM、Pythia系列、TinyLlama和Olmo。

在企業應用方面,也出現了類似的趨勢,企業傾向選用小型、開放、專門的模型,而非大型封閉的模型。Sarah Wang和Shangda Xu的報告指出,成本只是企業做出這種選擇的原因之一,且不是最重要的。其他原因包括控制力(企業既要確保資料安全,也要能理解模型的行為)和客製化能力(針對特定用例微調模型)。

關於微調,Predibase工程師在最近的LoRA Bake Off簡報中展示,小型開源微調模型在特定任務上的表現可以超越GPT-4。雖然理論上GPT-4也能微調,但OpenPipe等新創公司能籌得資金,正是因為企業需要控制力和客製化,要「以自己的微調模型取代GPT-4」。

當然,要取代一個模型,光有互通性還不夠,我們需要評估模型,比較它們的性能,才能選出最適合的那一個。

作者在mzai從事評估任務時(包括NeurIPS LLM Efficiency Challenge和內部專案),直接體驗到離線和線上模型性能(或用Context.ai指南中的說法:模型性能和產品性能)經常有重大差異,前者常無法預測後者。

離線評估是在模型上進行,使用公認可預測模型特定任務表現的學術基準和指標。線上評估則是針對基於LLM的產品,通常以人工方式在客製化資料集上進行,目的是評估回應品質,包括幻覺程度、品牌語調契合度、面對對抗性輸入的反應等更符合產品本身的指標。  

這種「離線-線上落差」在其他領域也很常見。有趣的是,它在社交網路的推薦系統中尤其嚴重。

為了縮小這個落差,「LLM as Judge」的方法應運而生。它利用另一個LLM來評估你的LLM應用的回應。假設經過適當訓練,它們比離線評估更能貼近線上性能,但成本又比人工線上評估低。 

和其他基於LLM的應用一樣,這方面也有多種仰賴GPT-4的工具。比方說,Anyscale的Goku Mohandas和Philipp Moritz撰寫的這篇文章,記錄了一個作者很欣賞的GPT-4評估流程。作者之所以喜歡,是因為它有條不紊地分解每個步驟,附上了參考代碼,並有詳盡的結果分析。

值得慶幸的是,業界也陸續推出了依賴開源模型、性能媲美「GPT-4 as Judge」、但價格只是零頭的替代方案。Prometheus和Ragas就是兩個例子,可分別用於評估基於LLM和基於檢索增強生成的系統。本文將聚焦在前者。

Prometheus是個完全開源的LLM(在HuggingFace以Apache 2.0授權發布),作為長篇內容的評估者,其能力與GPT-4不相上下。它能依照使用者提供的評分規則,評估任何給定的長篇文字。實驗顯示,它與人類評估者的皮爾森相關係數高達0.897。介紹Prometheus的論文已被NeurIPS 2023的Instruction Workshop所接受,而且已有後續研究瞄準視覺-語言模型。

作者以一張圖高度概括了Prometheus評分的運作方式。實務上,餵給Prometheus的每個提示(prompt)都由四部分組成:

1. 要評估模型所接收的指示(instruction) 

2. 該模型的回應

3. 一個得分最高的參考答案

4. 自訂的評分規則,描述回答指示所需的主要面向

作者以方塊展示了一個來自Prometheus專案中mt_bench資料集的例子。這個資料集利用了MT Bench Human Judgements資料,後者收集了六個模型針對一系列開放式問題所生成的回答,並由人類專家評分。

當Prometheus收到這樣的提示,它的回應會包含針對所提供回答的評估意見(以自然語言表達),以及一個符合評分規則範圍的數字分數。 

Prometheus的程式碼、論文和訓練資料都可以在GitHub取得。安裝必要的相依性,在run.py中填入提示模板後,就可以從命令列執行範例評估。此外,專案也提供了完整的基準測試腳本,可透過TGI調用模型服務來執行。

值得注意的是,Prometheus是Llama-2-Chat-13B模型的微調版本,因此非常吃記憶體:它需要GPU才能運作(原版模型需要超過70GB RAM的高階GPU),這是在評估模型所需的硬體之外,還得額外考量的成本。為了克服這個限制,作者展示了如何執行此模型的量化版本,並評估它在與原版模型輸出的相關性方面的性能。

在NeurIPS LLM Efficiency Challenge期間,作者體認到擁有簡單且可擴展的LLM微調和評估系統至關重要。挑戰預設提供的工具(微調用LitGPT,評估用HELM)可滿足個別提交的需求。然而,作者同時微調和評估多個模型的經驗,凸顯了一些可以改進和通用化的機會。

具體來說,作者想要:

- 建立可在本機筆電或遠端叢集上執行的任務流程;

- 提供實驗追蹤功能,讓同個實驗中的不同任務能共享成品和設定參數,並透過記錄追溯成品的來源; 

- 讓任務規格保持簡單,方便使用者建立新規格;

- 讓不同元件透過開放或事實標準互通訊息。

LM Buddy是作者在mzai內部打造,並已開源到GitHub的框架,就是為了提供以上這些功能。在為開發者提供平台,去建置專用且值得信賴的AI代理的路上,這是一個核心元件,作者決定及早分享、公開開發。它目前提供了利用抽象化任務來微調和評估LLM的能力。

雖然還在早期階段,該函式庫已具備一些有用的特色:

- 基於命令列介面和YAML設定檔,提供簡單的任務介面

- 透過Weights & Biases進行輸入/輸出成品的追蹤  

- 能在本機執行任務,也能利用Ray輕鬆擴展到遠端叢集

這個套件目前提供兩種任務類型:  

1. 微調任務:利用HuggingFace的模型和訓練實作,以及Ray Train來擴展運算

2. 評估任務:可用Ray來擴展,目前仰賴lm-evaluation-harness進行離線評估,以及Prometheus和Ragas進行LLM as Judge評估 

當需要進行推論時,不論是要評估的模型或是作為LLM Judge,作者都使用vLLM提供模型服務,並確保他們使用和開發的函式庫都支援OpenAI API。

作為LM Buddy任務的Prometheus評估,會讀取一個包含要評估提示的輸入資料集,將那些提示傳送給透過vLLM提供服務的LLM Judge,輸出的是另一個版本的資料集,內容增加了Prometheus的意見和分數。使用原版Prometheus模型時,要為它分配一個GPU,然後從(可能很多台)只有CPU的機器執行評估任務。

有沒有辦法讓終端使用者做起來更簡單呢?

llamafile旨在「將LLM聊天機器人的所有複雜性,壓縮到單一個可在六種作業系統上執行的檔案中」。它利用了兩個開源專案:llama.cpp專注於在消費級硬體上執行LLM,Cosmopolitan則是將C語言程式編譯成可在多種作業系統上執行的通用執行檔。

llamafile讓單一檔案在筆電上執行模型:透過簡單的Flask中介層代理llama.cpp自己的伺服器,可以透過OpenAI相容的API存取。多虧了Justine Tunney最近為llamafile改進的矩陣乘法核心,提示處理速度大幅提升,表現優於單獨使用llama.cpp和ollama。  

這對作者的意義是,(1)可以無縫地將vLLM提供的Prometheus服務替換為llamafile版本,(2)它可以在各式各樣的硬體設定上執行。

llamafile的GitHub專案已經提供了多種模型可供下載,而HuggingFace最近也開始正式支援llamafile格式的模型。在論文作者做實驗之前,還沒有llamafile格式的Prometheus模型,所以他必須自己建構。步驟大致分為(1)編譯llamafile、(2)下載GGUF格式的Prometheus模型、(3)把所有東西打包在一起。

一旦執行了Prometheus的llamafile,它會將模型載入記憶體並開啟一個包含聊天UI的瀏覽器分頁。可以開始聊天,測試一切運作正常(畢竟Prometheus模型就是個微調版的Llama)。

由於lm-buddy任務要求透過OpenAI相容的API提供Prometheus服務,可以執行幾個命令讓llamafile相容於API。這會啟動一個在本機監聽指定URL的伺服器。現在只需將prometheus.inference.url設定為此URL,就能使用Prometheus的llamafile版本進行評估了。  

報告分享了一些實驗結果。首先是量化對品質的影響。和TheBloke在HuggingFace上發布的其他GGUF格式模型一樣,他們的Prometheus頁面有個Provided files區塊,提供了根據量化程度而有所不同的模型變體。

量化是一種透過使用更低精度的資料類型來表示模型權重和啟動值,藉此減少記憶體需求和計算成本的技術。使用的位元數越少,模型就越小,能在更便宜的硬體上執行;但同時在近似原始模型權重時的品質也會變差,影響整體表現。

TheBloke的表格在這方面很有幫助,除了顯示用於量化的位元數和整體模型大小外,還有個「use case」欄位,以高層次描述了模型的品質。為了讓結果更具解釋力,衡量了不同量化程度的模型在評分上與原版模型的一致性。  

他們取了Vicuna基準,用lm-buddy執行了三次評估,分別使用vLLM提供的Prometheus服務和本機的量化版llamafile模型,然後計算它們平均分數的皮爾森相關係數(PCC)。PCC介於[-1, 1]區間,數值越高代表越相關。

結果顯示,用於量化的位元數越多,llamafile模型與原版越一致,PCC值也越高。雖然Q8模型與原版最相似,但Q5的PCC值也相當高,卻只需16GB RAM。

接著測試了Prometheus和llamafile在簡單的自訂場景中的一致性。在RAG情境中測試了不同模型,從預定義問題生成模型答案,然後用Prometheus進行人工評估和自動評估,使用自訂評分規則,分別執行原版模型和llamafile版本。

結果顯示,手動標註與原版Prometheus模型的PCC為0.73,顯示兩種評估整體上是一致的。原版Prometheus模型與llamafile版本的PCC則高達0.9。

最後是評估速度和成本的比較。作者在配備A100 GPU的機器上使用原版Prometheus模型,以及在不同架構上使用基於特定llamafile的Prometheus,執行了相同的Vicuna基準測試。該基準包含320個提示,各自評估3次,總計960個HTTP請求。

要判斷哪種模型最符合成本效益並不容易。它需要綜合考慮不同變數,包括絕對成本(不只是每小時價格,在該硬體上執行特定評估任務需要多少小時,也是相關資訊)和隨需、預留或自備硬體的價格(即需要執行多少次這樣的推論)。視需求而定,使用隨需GPU或買台新筆電可能會便宜許多。

本地LLM as Judge評估是許多開放專案共同努力的成果。時間軸上展示的專案雖然只是其中一部分,但已足以說明讓作者的工作成為可能的祕方:這些專案不僅要開源,更要在設計之初就考慮互通性。從打造可攜式執行檔到定義發布LLM的標準二進位格式,從分享預量化模型到以通用API提供模型服務,所有這些努力都是為了鼓勵軟體模組化和人與人之間的協作。

Prometheus只是眾多LLM as Judge方法之一,更重要的是,LLM as Judge本身並非萬靈丹:畢竟我們還是在跟LLM打交道!其表現取決於提供的評分規則品質,以及我們用作評估者的模型之泛化能力。還有個非常重要的問題:「誰來審核審核者?」這裡只有將不同模型的表現與一些基準做了部分比較。儘管我們最信賴的還是人類做的ML評估,展示一些我們可以試驗的開放、平價的人工評估替代品仍然重要:不論是為了在特定使用案例中做出明智的模型選擇,或是為了在模型品質和成本間取得最佳平衡。

就像...臉書上有位朋友懷疑這篇文章是不是GPT自動生成的...其實我還真的很希望是, 但願AI不但會歸納也能做複雜推理, 考慮我也是Justine的sponsor之一, 這麼做似乎對她不敬。內容已經重新校稿。

2024年4月28日星期日

Apple的逆襲: OpenELM大模型

Apple的新報告提出了開源的高效語言模型及訓練推理架"OpenELM: An Efficient Language Model Family with Open-source Training and Inference Framework"論文,跟之前Meta的OLMo一樣令人耳目一新。因為它詳細分享了模型架構、訓練方法和訓練數據,這在業界並不多見。

蘋果公司最近開源了一個名為OpenELM的大型語言模型(LLM)家族,旨在通過公開模型架構、訓練方法和資料集,提高LLM研究的可重複性和透明度。這不僅有助於學界驗證結果、研究數據和模型偏差,也為探索潛在風險提供了機會。   

OpenELM採用了一種逐層縮放(layer-wise scaling)策略,在transformer模型的每一層中高效分配參數,從而在給定參數預算下實現更高的精度。例如,在約10億參數規模下,OpenELM的精度比最近開源的OLMo高出2.36%,而訓練token數量只有後者的一半。

有別於此前只提供模型權重和推理程式碼,或在私有資料集上預訓練的做法,Apple的開源內容包括了在公開資料集上進行訓練和評估的完整框架,涵蓋訓練日誌、多個檢查點和預訓練配置。他們還發布了將模型轉換為MLX庫的程式碼,方便在蘋果設備上進行推理和微調。這種全面的開源有望賦能和加強開放研究社區,為未來的開放研究鋪平道路。

論文連結: https://arxiv.org/pdf/2404.14619

模型架構

OpenELM採用了decoder-only的transformer架構。參考SOTA的LLM,它在設計中融入了以下特點:  

1. 所有全連接層(線性層)不使用可學習的偏置參數

2. 使用RMSNorm進行預規範化,使用RoPE編碼位置信息  

3. 用分組查詢注意力(GQA)取代多頭注意力(MHA)

4. 用SwiGLU FFN取代前饋網絡(FFN)  

5. 使用flash attention計算點積注意力

6. 沿用LLama的分詞器

與現有LLM在每層採用相同配置、均勻分配參數不同,OpenELM根據逐層縮放策略,讓每層transformer的配置(如注意力頭數、前饋維度)各不相同,從而在整個模型中實現參數的非均勻分配。這種做法讓OpenELM能在相同參數量下,實現更高的精度。

訓練資料和方法

OpenELM在約1.8萬億token的公開資料集上進行了預訓練,包括RefinedWeb、去重的PILE、RedPajama和Dolma的子集。與之前使用預分詞數據的方法不同,OpenELM採用了即時過濾和分詞。這大大簡化了使用不同分詞器進行實驗的流程。 

訓練採用AdamW優化器,使用餘弦退火學習率調度,訓練35萬步。他們訓練了270M、450M、1.1B和3B四個不同規模的變體,對於某些模型還啟用了FSDP和activation checkpointing技術。

評估結果

研究者在三個評估框架下測試了OpenELM:標準zero-shot任務、OpenLLM排行榜任務和LLM360排行榜任務。結果顯示,不論在推理、知識理解還是識別錯誤信息和偏見方面,OpenELM都優於現有的開源LLM。尤其是在規模相當的情況下,OpenELM在精度上顯著領先OLMo,且只用了一半的訓練資料。  

進一步的指令微調實驗表明,在6萬個指令樣本上微調,可使OpenELM在各種任務上的平均精度提高1-2個百分點。此外,LoRA和DoRA等參數高效微調方法也被證明可用於OpenELM,在維持模型大小不變的情況下顯著提升下游任務性能。

OpenELM的源碼、預訓練權重和訓練配方已在GitHub上開源。模型本身也已上傳到HuggingFace,方便研究者使用。值得一提的是,蘋果還開源了將模型轉換為MLX的代碼,MLX是一個在Apple矽晶片上進行高效機器學習的庫。這為在蘋果設備上部署OpenELM掃清了障礙。  

OpenELM的發布代表了Apple在開放研究道路上又邁出的一大步。逐層縮放策略和全面的開源內容是其兩大亮點。儘管目前的推理速度還有待優化,但OpenELM在精度和資料效率上已經展現了巨大的潛力。未來,隨著更多的研究者參與改進和分析,OpenELM有望在各類自然語言任務上樹立新的標杆,為LLM的發展注入新的活力。

心得:

1. OpenELM有4種相對較小且方便使用的規模:270M、450M、1.1B和3B。

2. 儘管OpenELM的訓練token數量只有OLMo的一半,但性能略優於後者。

3. 主要的架構創新是一種逐層縮放策略。

這種逐層縮放策略非常有意思。希望他們做一個消融實驗,在同樣的資料集上訓練兩個版本的模型,一個用這種策略,一個不用,看看效果有何不同。但這樣的實驗成本很高。

另外, 他們也比較了LoRA和DoRA在參數高效微調上的表現!不過結果顯示,這兩種方法並沒有明顯差異。



SambaNova SN40L: 利用Dataflow和專家組合(COE)來克服AI記憶牆的大模型

摘要 GPT-4等整體式大型語言模型(LLM)為現代生成AI應用鋪路。然而,大規模訓練、服務及維護整體式LLM仍然極其昂貴和充滿挑戰。現代AI加速器計算能力與記憶體比例的不成比例增長已經造成了記憶體壁障,需要新的方法來部署AI。最近的研究顯示,許多小型專家模型的組合,每個模型參數...