構建 LLM 應用:大語言模型 LLM(第六部分)
作者:Vipra Singh
編譯:ronghuaiyang
導讀
接下來,我們將轉向 RAG 應用的生成部分。在文本生成方面,我們將運用大型語言模型。
到此爲止,我們已經瞭解到原始數據是如何被轉化並存入向量數據庫的,隨後再依據用戶的提示從數據庫中檢索出相關的數據片段。這標誌着應用程序檢索部分的工作已經完成。
接下來,我們將轉向 RAG 應用的生成部分。在文本生成方面,我們將運用大型語言模型。
- 什麼是大語言模型?
大型語言模型(LLM)是基於海量數據預訓練的大型深度學習模型。其底層架構 Transformer,是由包含編碼器和解碼器的神經網絡集合組成,這些組件具備自注意機制。編碼器與解碼器從文本序列中抽取意義,並理解文本內單詞及短語之間的關聯性。
大語言模型家族
以下是一些最具代表性的大型語言模型(LLM)框架的時間線(截至目前)
Transformer 神經網絡架構使得使用參數量極高的大型模型成爲可能,這些模型的參數數量往往達到數百億。如此大規模的模型可以處理海量數據,數據來源通常包括互聯網,以及像 “Common Crawl” 這樣的資源,該資源包含了超過 500 億個網頁,還有 Wikipedia,其頁面總數大約爲 5700 萬。
自然語言處理(NLP)應用中的關鍵工具之一就是語言建模。
這張圖展示了大型語言模型(LLMs)的不同組成部分。
- 語言建模 (LM) ============
語言和溝通的過程能否被簡化爲計算?
語言模型通過從一個或多個文本語料庫中學習來生成概率。文本語料庫是一種語言資源,由大量的、結構化的、一種或多種語言的文本集合構成。文本語料庫可以包含一種或多種語言的文本,並且通常會進行標註。
一個語言模型可以根據在訓練過程中學到的統計模式,預測最有可能跟隨某個短語出現的詞(或詞組)。在圖中,語言模型可能會估計出有 91% 的概率,詞 blue 會跟在序列 The color of the sky is 之後。
構建語言模型的最早方法之一是基於 n-gram。n-gram 是從給定文本樣本中提取的連續的 n 個項的序列。在此模型中,假設序列中下一個詞的概率僅僅依賴於固定大小的前幾個詞的窗口。
然而,n-gram 語言模型已經被神經網絡語言模型取代。神經網絡語言模型基於神經網絡,這是一種受生物神經網絡啓發的計算系統。這些模型利用詞的連續表示或嵌入來做出預測:
神經網絡將詞以權重的非線性組合分佈形式表示。因此,它可以避免在語言建模中的維度災難問題。對於語言建模,已經提出了幾種神經網絡架構。
- 基礎模型和大語言模型 =============
這與早期的自然語言處理應用中的方法大相徑庭,在早期應用中,專門的語言模型被訓練來執行特定任務。相反,研究者們在大型語言模型(LLMs)中觀察到了許多湧現的能力,即模型未曾被專門訓練過的能力。
例如,大型語言模型已被證明能夠執行多步算術運算,解開單詞字母的混亂順序,以及識別口語中的冒犯性內容。最近,基於 OpenAI 的 GPT 系列大型語言模型構建的熱門聊天機器人 ChatGPT,已經通過了諸如美國醫學執照考試(USMLE)等專業考試!
基礎模型通常指的是在廣泛數據上訓練,能夠適應大量下游任務的模型。這些模型通常採用深度神經網絡創建,並使用自監督學習在大量無標籤數據上進行訓練。
在訓練過程中,從語料庫中提取文本序列並進行截斷。語言模型計算後續缺失單詞的概率,然後通過基於梯度下降的優化機制對這些概率進行微調,並反饋給模型以匹配真實值。這一過程在整個文本語料庫上反覆進行。
然而,大型語言模型(LLMs)通常是在如文本等語言相關數據上進行訓練的。但基礎模型通常是基於多模態數據訓練的,這種數據包含了文本、圖像、音頻等多種類型。更重要的是,基礎模型旨在作爲更具體任務的基礎或基石:
基礎模型通常通過進一步的訓練針對各種下游認知任務進行微調。微調是指採用一個預訓練的語言模型,並使用特定數據對其進行不同但相關任務的再訓練過程。這一過程也被稱爲遷移學習。
- 大語言模型的結構 ===========
大多數早期的大型語言模型(LLMs)都是使用帶有 LSTMs 和 GRUs 的循環神經網絡(RNN)模型創建的。然而,它們在進行大規模自然語言處理任務時遇到了挑戰。但正是在這種大規模任務上,人們期望大型語言模型能夠表現出色。這促使了變換器(Transformers)的誕生!
早期的 LLM 架構
起初,大型語言模型主要是使用自監督學習算法創建的。自監督學習指的是處理無標籤數據以獲得有助於下游學習任務的有用表示。
自監督學習算法經常使用基於人工神經網絡(ANN)的模型。我們可以用多種架構來創建人工神經網絡,但在大型語言模型中最廣泛使用的架構是循環神經網絡(RNN)。
現在,循環神經網絡(RNNs)能夠利用其內部狀態來處理可變長度的輸入序列。RNN 既具有長期記憶也具有短期記憶。RNN 的一些變體包括長短時記憶(LSTM)和門控循環單元(GRU)。
LSTM 與 GRU 的問題
使用 LSTM 單元的 RNN 訓練速度非常慢。此外,對於這類架構,我們需要按順序或串行地輸入數據。這不允許我們並行化處理,也無法充分利用可用的處理器核心。
另一方面,帶有 GRU 的 RNN 模型雖然訓練速度較快,但在較大數據集上的表現卻較差。不過,很長一段時間裏,LSTMs 和 GRUs 仍然是構建複雜自然語言處理系統的首選。然而,這些模型同樣遭受梯度消失問題的困擾:
注意力機制
通過在 RNN 的架構中加入注意力機制,部分解決了 RNN 存在的問題。在像 LSTM 這樣的循環架構中,信息傳播的量是有限的,且保留的信息窗口較短。
然而,有了注意力機制,這個信息窗口可以顯著增加。注意力是一種增強輸入數據某些部分同時削弱其他部分的技術。其背後的動機是網絡應該更多地關注數據的重要部分:
注意力和自注意力之間存在微妙的區別,但它們的動機是相同的。注意力機制指的是關注另一個序列的不同部分的能力,而自注意力指的是關注當前序列不同部分的能力。
自注意力允許模型從任意輸入序列元素中獲取信息。在自然語言處理應用中,這提供了關於遠距離詞彙的相關信息。因此,模型可以在不需要固定或滑動窗口的情況下捕捉整個序列的依賴關係。
Transformer 的出現
帶有注意力機制的循環模型在其性能上看到了顯著的提升。然而,循環模型本質上難以擴展。但是,自注意力機制很快證明了它的強大,以至於它甚至不需要循環的順序處理。
2017 年 Google Brain 團隊引入的 Transformer 也許是大型語言模型歷史上最重要的轉折點之一。變換器是一種採用自注意力機制的深度學習模型,能夠一次性處理整個輸入:
與早期基於 RNN 的模型相比,Transformer 沒有循環結構。只要有足夠的訓練數據,Transformer 架構中的注意力機制單獨就能匹敵帶注意力的 RNN 模型的性能。
使用 Transformer 模型的另一個重要優勢在於,它們更加並行化,需要的訓練時間顯著減少。這正是我們利用現有資源在大量基於文本的數據上構建大型語言模型所需要的優點。
編碼器 - 解碼器架構
許多基於人工神經網絡的自然語言處理模型都是使用編碼器 - 解碼器架構構建的。例如,seq2seq 是一系列最初由 Google 開發的算法家族。它通過使用帶有 LSTM 或 GRU 的 RNN,將一個序列轉換成另一個序列。
最初的 Transformer 模型也採用了編碼器 - 解碼器架構。編碼器由一系列的編碼層組成,它們逐層迭代處理輸入。解碼器則由解碼層組成,對編碼器的輸出做同樣的事情:
每個編碼層的作用是生成編碼,這些編碼包含了輸入各部分之間相關性的信息。然後,這些輸出編碼被傳遞給下一個編碼層作爲其輸入。每個編碼器都包含一個自注意力機制和一個前饋神經網絡。
此外,每個解碼層接收所有的編碼,並利用其所包含的上下文信息來生成輸出序列。與編碼器類似,每個解碼器也包含一個自注意力機制、一個對編碼的注意力機制,以及一個前饋神經網絡。
- 預訓練
在這個階段,模型以自監督的方式在大量非結構化文本數據集上進行預訓練。預訓練的主要挑戰是計算成本。
所需 GPU 內存以存儲 10 億參數模型:
=> 1 參數 -> 4 字節(32 位浮點數)
=> 10 億參數 -> 4 * 10^9 字節 = 4GB
10 億參數模型所需的 GPU 內存 = 4GB @ 32 位全精度
讓我們來計算訓練 10 億參數模型所需的內存:
Model Parameter --> 4 bytes per parameter
Gradients --> 4 bytes per parameter
ADAM Optimizer (2 states) --> 8 bytes per parameter
Activations and temp memory (variable size) --> 8 bytes per parameter (high-end estimate)
==> 4 bytes parameter + 20 extra bytes per paramter
因此,訓練所需的內存大約是存儲模型所需內存的 20 倍。
存儲 10 億參數模型所需的內存 = 4GB @ 32 位全精度
訓練 10 億參數模型所需的內存 = 80GB @ 32 位全精度
- 數據並行訓練技術 ===========
6.1. 分佈式數據並行 (DDP)
分佈式數據並行(DDP)要求模型權重以及訓練所需的所有其他附加參數、梯度和優化器狀態必須能夠裝入單個 GPU 中。如果模型過大,應改用模型分片技術。
6.2. 完全分片數據並行 (FSDP)
完全分片數據並行(FSDP)通過在 GPU 之間分配(分片)模型參數、梯度和優化器狀態來減少內存需求。
- 微調
微調幫助我們從預訓練的大型語言模型(LLMs)中獲得更多的效益,通過調整模型權重使其更貼合特定的任務或領域。這意味着你可以以更低的成本和延遲,獲得比單純的提示工程更高質量的結果。
近年來微調方法的演變發展。同一分支上的模型具有一些共同的特點。模型的垂直位置顯示了它們發佈時間的時間線。請注意,由於當前環境的限制,我無法提供實際的視覺圖表或圖像,但這段描述意在解釋一個展示微調技術隨時間演進的圖表。
爲何要對 LLM 進行微調?
相比於提示工程,微調通常在引導大型語言模型(LLM)的行爲方面更爲有效和高效。通過對模型進行一系列示例訓練,你能縮短精心設計的提示,節省寶貴的輸入 tokens,同時不犧牲質量。此外,你還可以經常使用更小的模型。這反過來意味着降低延遲和推理成本。
例如,與現成的 GPT-3.5 模型相比,微調過的 Llama 7B 模型在每 token 基礎上的成本效益更高(大約 50 倍),並且性能相當。
微調是如何工作的?
正如之前提到的,微調是將一個已訓練好的模型調整用於其他任務。其工作原理是通過取原始模型的權重,並根據新任務進行調整。
模型在訓練過程中學會執行某些特定任務,例如,GPT-3 在一個龐大的數據集上進行了訓練,結果它學會了生成故事、詩歌、歌曲、信件以及很多其他內容。人們可以利用 GPT-3 的這種能力,並將其微調到一個特定任務上,比如以特定方式生成對客戶查詢的答案。
有不同的方法和技術來微調模型,其中最流行的是遷移學習。遷移學習起源於計算機視覺領域,它是凍結網絡初始層的權重,只更新後層權重的過程。這是因爲較低層,即靠近輸入的層,負責學習訓練數據集的一般特徵。而較高層,靠近輸出的層,學習更具體的信息,這些信息直接與生成正確輸出相關聯。
下面是微調工作原理的快速可視化示意:請注意,由於當前環境限制,我無法提供實際的視覺圖表或圖像,但這段描述旨在解釋微調如何改變模型的權重以適應新任務。在微調過程中,模型的頂層權重被更新以適應新的輸出需求,而底層的通用特徵識別能力保持不變。
7.1. 參數高效微調(PEFT)
PEFT,即參數高效微調,是一系列技術和方法的集合,旨在以最高效的方式對大型模型進行微調,同時不會損失全量微調可能帶來的任何性能。這是因爲隨着模型規模不斷增大,如 BLOOM 擁有驚人的 1760 億參數,如果不花費數萬美元,幾乎不可能對其進行微調。但有時爲了獲得更好的性能,使用這樣大的模型幾乎是必要的。這時,PEFT 就發揮作用了。它幫助解決在處理超大規模模型時所面臨的問題。
這裏列舉一些 PEFT 技術:
7.2. 遷移學習
遷移學習是指我們將模型的一部分已學習參數應用於其他任務。這聽起來與微調相似,但實際上有所不同。在微調中,我們重新調整模型的所有參數,或者凍結一部分權重,然後調整其餘參數。而在遷移學習中,我們從一個模型中使用其部分已學習的參數,並將它們應用於其他網絡中。這爲我們提供了更多的靈活性,尤其是在我們能做的事情上。例如,在微調時,我們不能改變模型的架構,這在很多方面限制了我們。但使用遷移學習時,我們只使用訓練模型的一部分,然後可以將其連接到任何其他具有任意架構的模型上。
遷移學習常出現在自然語言處理(NLP)任務中,特別是在大型語言模型(LLMs)中,人們會使用預訓練模型(如 T5)的變換器網絡的編碼器部分,並訓練後續的層。這種方法允許利用預訓練模型的強大特徵提取能力,同時結合新任務的具體需求進行定製化訓練,從而在保持高效和靈活性的同時提高性能。
7.3. 適配器
適配器是最早發佈的參數高效微調技術之一。研究者表明可以在現有的 Transformer 架構中添加更多的層,並且只對這些新增的層進行微調,而不是對整個模型進行微調。他們證明了這種方法在與完全微調相比時,能夠產生相似的性能。這種方法的核心在於插入的適配器層可以學習到任務特定的轉換,而無需修改原有模型的大部分參數,從而實現了高效的微調過程。
在左邊,展示的是加入了適配器層的修改後的 Transformer 架構。可以看到,適配器層被添加在注意力層和前饋層之後。而在右邊,我們可以看到適配器層本身的架構。適配器層採用 bottolneck 架構,它接收輸入並將之縮減到一個較小維度的表示,然後通過非線性激活函數,再將其擴展回輸入的維度。這樣確保了 Transformer 堆棧中的下一層能夠接收到來自適配器層產生的輸出。
作者表明這種微調方法與完全微調相比性能相當,但消耗的計算資源和訓練時間要少得多。他們能夠在 GLUE 基準測試上只比完全微調性能的差 0.4%,而僅增加了 3.6% 的參數。這種方法不僅極大地降低了計算成本,還保持了模型的高性能,展現了參數高效微調技術的有效性和潛力。
7.4. LoRA — 低秩適配器(Low-Rank Adaptation)
LoRA 是一種類似於適配器層的策略,但其目標是進一步減少可訓練參數的數量。它採取了一種更爲嚴謹的數學方法。LoRA 的工作原理是改變了神經網絡中可更新參數的訓練和更新方式。
從數學角度來解釋。我們知道,預訓練神經網絡的權重矩陣是滿秩的,意味着每個權重都是獨特的,不能通過組合其他權重得到。但在這篇論文中,作者指出當預訓練的語言模型調整到新任務時,權重具有較低的 “內在維度”。也就是說,權重可以用一個更小的矩陣來表示,或者說是具有較低的秩。這意味着在反向傳播過程中,權重更新矩陣具有較低的秩,因爲預訓練過程已經捕獲了大部分必要信息,而在微調期間僅需進行任務特定的調整。
一個更簡單的解釋是,在微調過程中,只有非常少的權重會被大量更新,因爲大部分的學習發生在神經網絡的預訓練階段。LoRA 利用這一信息來減少可訓練參數的數量。
LoRA 通過分解原有的權重矩陣爲兩個低秩矩陣的乘積,其中一個矩陣代表任務無關的特性,另一個矩陣則捕捉任務相關的調整。這樣,LoRA 僅需要訓練這兩個低秩矩陣,從而大大減少了參數的數量,同時保持了模型在新任務上的性能。這種方法在保證模型效果的同時,顯著降低了計算成本和訓練時間。
以 GPT-3 175B 爲例,LoRA 研究團隊證明了即使完整矩陣的秩(即 d)高達 12,288,一個非常低的秩(即圖 1 中的 r 可以是一或二)也足以滿足需求,這使得 LoRA 在存儲和計算上都非常高效。
上圖展示了矩陣 A[d X r] 和 B[r X k] 的乘積將是 [d X k],而我們可以變化 r 的值。一個非常小的 r 會導致更少的參數需要調整。雖然這會縮短訓練時間,但也可能導致信息丟失,隨着 r 變得更小,模型性能可能會下降。然而,即使在低秩階下,LoRA 的表現也與完全訓練的模型一樣好,甚至更好。
使用 HuggingFace 進行 LoRA 微調
要使用 HuggingFace 實施 LoRA 微調,你需要使用 PEFT 庫將 LoRA 適配器注入模型中,並將它們用作更新矩陣。這允許你以參數高效的方式微調模型,只需調整 LoRA 適配器中的參數,而不是整個模型。HuggingFace 的 PEFT 庫簡化了 LoRA 微調的過程,使得即使是大型預訓練模型也能以較少的計算資源和時間成本進行高效微調。
from transformers import AutoModelForCausalLM
from peft import get_peft_config, get_peft_model, LoraConfig, TaskType
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, device_map="auto", trust_remote_code=True) # load the model
peft_config = LoraConfig(
task_type=TaskType.CAUSAL_LM, inference_mode=False, r=32, lora_alpha=16, lora_dropout=0.1,
target_modules=['query_key_value'] # optional, you can target specific layers using this
) # create LoRA config for the finetuning
model = get_peft_model(model, peft_config) # create a model ready for LoRA finetuning
model.print_trainable_parameters()
# trainable params: 9,437,184 || all params: 6,931,162,432 || trainable%: 0.13615586263611604
完成以上步驟後,你可以像平常一樣訓練模型。但這一次,由於只需要調整 LoRA 適配器中的參數,所以會大大減少時間和計算資源的消耗。
LoRA 的高效性
論文中的作者表明,LoRA 僅使用總可訓練參數的 2% 就能超越完全微調的效果。
至於訓練的參數數量,我們可以通過秩 r 參數來很大程度上控制它。例如,假設權重更新矩陣有 100,000 個參數,A 是 200,B 是 500。權重更新矩陣可以分解爲維度更低的小矩陣,A 是 200 x 3,B 是 3 x 500。這給我們帶來了 200 x 3 + 3 x 500 = 2100 個可訓練參數,這只是總參數數量的 2.1%。我們還可以進一步減少參數數量,因爲我們可以選擇只對特定層應用 LoRA。
由於訓練和應用的參數數量遠遠小於實際模型,文件可以小至 8MB。這使得加載、應用和遷移所學模型變得更加容易和快速。
如果你想了解更多並深入探討這個主題,可以閱讀 LoRA 論文。
LoRA 在穩定擴散(Stable Diffusion)中的應用
LoRA 最有趣的用例之一可以在圖像生成應用中體現。圖像固有的一種風格是可以直觀看到的。現在,用戶不再需要訓練龐大的模型來從模型中獲取特定風格的圖像,而是可以直接訓練 LoRA 權重,並使用像 Dreambooth 這樣的技術來實現高質量圖像,同時還具有很大的定製性。
LoRA 權重也可以與其他 LoRA 權重結合,並以加權組合的方式使用,生成攜帶多種風格的圖像。你可以在網上找到大量的 LoRA 適配器,並在 CivitAI 上將它們加載到你的模型中。
在圖像生成領域,LoRA 的應用不僅簡化了模型訓練流程,還極大地增強了用戶的創造性和個性化能力。通過微調 LoRA 權重,用戶可以根據自己的需求和偏好生成獨特風格的圖像,這在藝術創作、設計和娛樂行業有着廣闊的應用前景。
7.5. QLoRA
它與 LoRA 有何不同
-
它是一個 4 位的 Transformer。
-
QLoRA 是一種微調技術,它結合了高精度計算技術和低精度存儲方法。這有助於保持模型尺寸小巧,同時確保模型仍具有高性能和準確性。
-
QLoRA 使用 LoRA 作爲一種輔助手段,用於修正量化過程中引入的誤差。
QLoRA 的工作原理
- QLoRA 通過引入三個新概念來幫助在保持相同質量性能的同時減少內存佔用。這些概念是 4 位標準浮點數、雙重量化_和_分頁優化器。
4 位標準浮點數(NF4)
-
4 位標準浮點數是一種新的數據類型,是維持 16 位性能水平的關鍵成分。其主要特性如下:數據類型中的任何位組合,例如 0011 或 0101,都會從輸入張量中分配相同數量的元素。
-
4 位量化權重和 PEFT,以 32 位精度訓練注入的適配器權重(LoRA)。
-
QLoRA 有一個存儲數據類型(NF4)和一個計算數據類型(16 位 BrainFloat)。
-
我們將存儲數據類型反量化爲計算數據類型,以執行前向和後向傳播,但我們僅計算使用 16 位 BrainFloat 的 LoRA 參數的權重梯度。
**1. 標準化:**首先將模型的權重標準化,使其具有零均值和單位方差。這確保了權重圍繞零分佈,並處於一定範圍內。
**2. 量化:**然後將標準化的權重量化爲 4 位。這涉及到將原始高精度權重映射到一組較小的低精度值。在 NF4 的情況下,量化級別在標準化權重的範圍內均勻間隔。
**3. 反量化:**在前向傳播和反向傳播期間,將量化後的權重反量化回全精度。這是通過將 4 位量化值映回其原始範圍完成的。反量化的權重用於計算中,但在內存中是以 4 位量化形式存儲的。
通過以上步驟,QLoRA 能夠在保持模型性能的同時顯著減少內存佔用和計算資源需求,特別適合於處理大尺寸模型和有限計算資源的情況。
在量化過程中,數據被分爲 “桶” 或“箱”,其中的數據被量化。例如,數字 2 和 3 都落入了相同的量化區間,也就是 2。這一量化過程通過 “四捨五入” 到最近的量化區間,允許你使用更少的數值來表示數據。
反量化
- 雙重量化是指在 4 位 NF 量化過程中對所使用的量化常數進行量化的獨特實踐。雖然乍看之下可能不起眼,但根據相關研究論文的亮點,這種方法有可能爲每個參數平均節省 0.5 位。這種優化在 QLoRA 的背景下尤其有益,該技術使用 Block-wise k-bit Quantization。與集體量化所有權重不同,這種方法涉及將權重分割成不同的塊或片段,這些塊或片段獨立地進行量化。
通過雙重量化,QLoRA 進一步壓縮了模型的存儲需求,同時保持了模型的預測精度。這是因爲,通過量化量化常數,QLoRA 有效地減少了用於表示權重的比特數,而不會顯著影響模型的性能。這種方法尤其適用於處理大型模型,因爲它允許在有限的計算資源下運行更復雜的模型,同時保持較高的預測能力。
- 塊量化方法導致生成多個量化常數。有趣的是,這些常數可以進行第二輪量化,爲額外的空間節省提供了機會。由於量化常數的數量有限,這種策略依然有效,緩解了與該過程相關的計算和存儲需求。
分頁優化器
-
正如前面所示,分位數量化涉及創建桶或箱來覆蓋廣泛的數值。這一過程導致多個不同的數字被映射到同一個桶中,例如,在量化過程中,2 和 3 都被轉化爲 3。因此,權重的反量化會引入 1 的誤差。
-
在神經網絡更廣泛的權重分佈中可視化這些誤差揭示了分位數量化固有的挑戰。這種差異強調了爲什麼 QLoRA 更像是一種微調機制而非獨立的量化策略,儘管它適用於 4 位推理。在使用 QLoRA 進行微調時,LoRA 調優機制開始發揮作用,涉及創建兩個較小的權重更新矩陣。這些以較高精度格式(如 brain float 16 或 float 16)維護的矩陣隨後被用來更新神經網絡的權重。
通過這種機制,QLoRA 能夠在保持模型性能的同時,顯著降低模型大小和計算成本,特別是在微調大型預訓練模型時。分頁優化器和雙重量化等技術確保了在低精度表示下,模型仍能保持良好的泛化能力和預測準確性。
- 值得注意的是,在整個反向傳播和前向傳播過程中,網絡的權重會進行反量化,確保實際訓練是在更高精度的格式中進行的。雖然存儲仍然是低精度的,但這種刻意的選擇引入了量化誤差。然而,模型訓練過程本身展現出能夠適應和緩解量化過程中固有不精確性問題的能力。實質上,高精度的 LoRA 訓練方法幫助模型學習並主動減少量化誤差。
使用 HuggingFace 進行 QLoRA 微調
要使用 HuggingFace 進行 QLoRA 微調,你需要安裝 BitsandBytes 庫和 PEFT 庫。BitsandBytes 庫負責 4 位量化以及整個低精度存儲和高精度計算的部分。PEFT 庫將用於 LoRA 微調部分。
通過結合使用這兩個庫,你可以在 HuggingFace 的環境中輕鬆地應用 QLoRA 技術,對大型預訓練模型進行微調。BitsandBytes 庫處理量化和計算精度的問題,而 PEFT 庫專注於 LoRA 的微調,兩者的結合確保了在降低模型存儲需求的同時,能夠保持甚至提升模型的性能。這種方式特別適合於那些需要處理大量數據和複雜模型,但受限於計算資源和存儲空間的應用場景。
import torch
from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
model_id = "EleutherAI/gpt-neox-20b"
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
# setup bits and bytes config
model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=bnb_config, device_map={"":0})
model.gradient_checkpointing_enable()
model = prepare_model_for_kbit_training(model) # prepares the whole model for kbit training
config = LoraConfig(
r=8,
lora_alpha=32,
target_modules=["query_key_value"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
model = get_peft_model(model, config) # Now you get a model ready for QLoRA training
然後,你可以再次切換到使用 HF Trainer 的常規訓練流程。
7.6. IA3
IA3(通過抑制和放大內部激活進行融合的適配器)是一種基於適配器的技術,它在某種程度上類似於 LoRA。作者的目標是複製 ICL(即境學習或 Few-Shot 提示)的優點,同時避免伴隨而來的問題。ICL 在成本和推理方面可能會變得複雜,因爲它需要通過示例提示模型。較長的提示需要更多的時間和計算來處理。但 ICL 可能是開始使用模型的最簡單方式。
IA3 通過引入重縮放向量來針對模型的激活。總共引入了 3 個向量,lv, ik 和 lff。這些向量分別針對注意力層中的 value,key 以及密集層中的非線性層。這些向量與模型中的默認值逐元素相乘。一旦注入,這些參數就會在訓練過程中被學習,而模型的其餘部分保持凍結。這些學習到的向量本質上是對目標預訓練模型權重進行重新縮放或優化,以適應手頭的任務。
通過這種方式,IA3 能夠在保持模型大部分固定的同時,通過調整關鍵組件的激活,有效地對模型進行微調。這種方法不僅減少了計算成本,還提高了模型在特定任務上的性能,尤其是對於那些希望利用預訓練模型強大能力但又受限於計算資源的場景來說。IA3 提供了一個靈活且高效的解決方案,使模型能夠快速適應新任務,而無需從頭開始訓練。
迄今爲止,這看起來像是基本的適配器類型的 PEFT 方法。但這並非全部。作者還使用了三種損失項來增強學習過程。這三種損失分別是 LLM, LUL, 和 LLN。LLM 是標準的交叉熵損失,它增加了生成正確響應的可能性。然後是 LUL,即 Unlikelihood Loss。這個損失項通過等級分類減少了錯誤輸出的概率。最後,我們有 LLN,這是一種長度歸一化損失,它將長度歸一化的所有輸出選擇的 log 概率的 softmax 交叉熵損失應用到模型上。在這裏使用多種損失是爲了確保模型更快、更好地學習。因爲我們試圖使用少量示例進行學習,這些損失項是必要的。
現在,讓我們討論 IA3 中兩個非常重要的概念:等級分類和長度歸一化。
在等級分類中,模型被要求通過其正確性對一組響應進行排名。這是通過計算潛在響應的概率得分來完成的。然後使用 LUL 來減少錯誤響應的概率,從而增加正確響應的概率。但是,使用等級分類,我們會遇到一個關鍵問題,那就是響應的標記越少,排名越高,這是由概率的運作方式決定的。較少的生成標記確保了更高的概率,因爲每個生成標記的概率都 < 1。爲了解決這個問題,作者建議將響應的得分除以響應中的標記數。這樣做將對得分進行歸一化。這裏需要注意的一個非常重要的事情是,歸一化是在對數概率上進行的,而不是原始概率。對數概率是介於 0 到 1 之間的負數,。
示例使用
對於序列分類任務,可以按照以下方式初始化 Llama 模型的 IA3 配置:
peft_config = IA3Config(
task_type=TaskType.SEQ_CLS, target_modules=["k_proj", "v_proj", "down_proj"], feedforward_modules=["down_proj"]
)
7.7. P-Tuning
P-tuning 方法旨在優化傳遞給模型的提示的表示。在 P-Tuning 論文中,作者強調了在處理大型語言模型時,提示工程是一項非常強大的技術。P-tuning 方法在此基礎上構建,試圖進一步提高優質提示的有效性。
P-tuning 通過爲你的提示創建一個小的編碼網絡來工作,該網絡爲你的傳遞提示創建一個軟提示。要使用 P-tuning 調整你的 LLM,你應該創建一個提示模板來表示你的提示。以及一個上下文 x,它在模板中用於獲取標籤 y。這是論文中提到的方法。用於提示模板的 tokens 是可訓練和可學習的參數,這些被稱爲 pseudo tokens。我們還添加了一個提示編碼器,它幫助我們將 pseudo tokens 更新到手頭的具體任務。提示編碼器通常是一個雙向 LSTM 網絡,它學習模型的提示最優表示,然後將表示傳遞給模型。LSTM 網絡附加到原始模型上。這裏只訓練編碼網絡和 pseudo tokens,原始網絡的權重不受影響。一旦訓練完成,LSTM 頭部就被丟棄,因爲我們已經有了可以直接使用的 hi。
簡而言之,提示編碼器僅改變傳遞提示的嵌入,以更好地表示任務,其他一切保持不變。通過這種方式,P-tuning 能夠在不改變模型結構的情況下,優化模型對特定任務的理解和處理能力,從而提高模型的性能和適應性。
7.8. Prefix Tuning
Prefix tuning 可以被認爲是 P-tuning 的升級版。P-tuning 的作者們發表了一篇關於 P-Tuning V-2 的論文,旨在解決 P-tuning 存在的問題。在這篇論文中,他們實現了在這篇論文中引入的 Prefix tuning。雖然 Prefix tuning 和 P-tuning 之間沒有太大的區別,但它們仍然可能導致不同的結果。讓我們深入瞭解一下。
在 P-Tuning 中,我們僅在輸入嵌入中添加了可學習參數,但在前綴調優中,我們將它們添加到了網絡的所有層。這確保了模型本身對其正在微調的任務有更深入的瞭解。我們在提示和 Transformer 層的每一層激活中附加可學習參數。與 P-Tuning 的不同之處在於,我們不是完全修改提示嵌入,而是在每一層提示的開始處僅添加非常少的可學習參數。
下面是一個視覺上的解釋:
在 Transformer 的每一層中,我們將帶有可學習參數的軟提示與輸入拼接在一起。這些可學習參數是通過一個非常小的多層感知器(MLP),只有 2 個全連接層來進行調整的。這樣做的原因是,作者在論文中指出,直接更新這些提示 token 對學習率和初始化非常敏感。軟提示雖然增加了可訓練參數的數量,但也實質上提升了模型的學習能力。在後期,我們可以捨棄 MLP 或全連接層,因爲我們只關心軟提示,這些將在推理時附加到輸入序列上,以引導模型的行爲。
7.9. Prompt Tuning (不是提示工程)
Prompt tuning 是最早基於僅使用軟提示進行微調的概念建立的論文之一。Prompt tuning 是一個非常簡單且易於實現的想法。它涉及在輸入前添加一個特定的提示,並使用虛擬 tokens 或針對該特定提示的新可訓練 tokens。這些新的虛擬 tokens 可以在過程中進行微調,以學習提示的更好表示。這意味着模型被調整以更好地理解提示。以下是來自論文的 prompt tuning 與完全微調的比較:
在這裏,你可以看到,如果我們想讓模型用於多個任務,完全模型微調需要存在模型的多個副本。但使用 Prompt Tuning,你只需要存儲學習到的提示 token 的虛擬 token。所以,例如,如果你使用一個像 “Classify this tweet: {tweet}” 這樣的提示,目標將是學習提示的新、更好的嵌入。而在推理過程中,只有這些新嵌入會被用來生成輸出。這使得模型能夠調整提示,幫助自己在推理時生成更好的輸出。
Prompt Tuning 的效率
使用 Prompt Tuning 的最大優勢是學習參數的小尺寸。文件可以是 KB 級別的。由於我們可以確定新 token 的維度大小和要使用的參數數量,我們可以很好地控制我們將要學習的參數數量。在論文中,作者展示了即使使用非常少的可訓練 token,該方法的表現也非常好。並且隨着使用更大模型,性能只會提升。
另一個巨大優勢是我們可以無需任何改動就使用同一模型處理多個任務,因爲唯一被更新的是提示令牌的嵌入。這意味着,只要模型足夠大且足夠複雜以執行這些任務,你就可以使用同一模型進行推文分類任務和語言生成任務,而無需對模型本身進行任何更改。但一個重大限制是模型本身並沒有學到任何新東西。這是一個純粹的提示優化任務。這意味着如果模型從未在情感分類數據集上進行過訓練,那麼提示調優可能不會帶來任何幫助。非常重要的一點是,這種方法優化的是提示,而不是模型。因此,如果你無法手工製作一個能相對較好地完成任務的硬提示,嘗試使用提示優化技術來優化軟提示就沒有意義了。
硬提示與軟提示
硬提示可以被視爲定義明確、靜態的提示,或者最多是一個模板。生成式 AI 應用也可以擁有多個可用的提示模板。
硬提示是手動精心製作的文字提示,具有離散的輸入 token。~ HuggingFace
提示模板允許提示被_存儲_、_重複使用_、_共享_和_編程_。生成式提示可以被整合進程序中,用於編程、存儲和重複使用。
軟提示是在提示調優的過程中創建的。
與硬提示不同,軟提示不能以文本形式查看和編輯。提示由嵌入組成,即一系列數字,這些數字從更大的模型中獲取知識。
因此,一個缺點是軟提示缺乏可解釋性。AI 發現了與特定任務相關的提示,但無法解釋爲何選擇了那些嵌入。就像深度學習模型本身一樣,軟提示是不透明的。
軟提示充當了額外訓練數據的替代品。在訓練數據有限或收集成本高昂的情況下,軟提示可以提供一種有效的方法來增強模型的性能,通過優化模型對現有數據的理解和利用。軟提示的使用,尤其是與提示調優技術結合時,可以顯著改善模型在特定任務上的表現,而無需大量額外的標註數據。
7.10. LoRA vs Prompt Tuning
現在我們已經探討了各種 PEFT 技術。接下來的問題是應該使用像 Adapter 和 LoRA 這樣的加性技術,還是使用基於提示的技術,如 P-Tuning 和前綴調優。
在比較 LoRA 與 P-Tuning 和前綴調優時,可以說在充分利用模型潛力方面,LoRA 無疑是最佳策略。但是否最高效則取決於你的具體需求。如果你想在與模型原本訓練任務截然不同的任務上訓練模型,毫無疑問,LoRA 是最有效的模型調優策略。但如果你的任務在很大程度上已經被模型理解,而挑戰在於如何正確地提示模型,那麼你應該使用基於提示的調優技術。基於提示的調優技術不會在模型中修改太多參數,而是主要集中在傳遞給模型的提示上。
值得注意的一點是,LoRA 將權重更新矩陣分解爲更小的秩矩陣,並使用它們來更新模型的權重。儘管可訓練參數較少,但 LoRA 會更新神經網絡目標部分的所有參數。而在基於提示的調優技術中,會在模型中添加一些可訓練參數,這通常有助於模型調整和更好地理解任務,但並不利於模型學習新屬性。
選擇哪種技術取決於你的目標和約束條件。LoRA 適合於需要模型在新任務上做出較大調整的情況,而基於提示的技術更適合於模型已經具備基本能力,只需通過優化提示來提升性能的場景。每種技術都有其適用範圍和優勢,正確選擇將對模型性能產生顯著影響。
7.11. LoRA 和 PEFT 與完全微調的對比
PEFT(Parameter-Efficient Fine-Tuning)作爲一種替代完全微調的方案,已經在多項任務中展示出與完全微調相當甚至更好的效果。然而,當你要使模型適應的任務與模型預訓練時接觸的任務完全不同,PEFT 可能就顯得力不從心了。在這種情況下,有限的可訓練參數可能會導致顯著的問題。
例如,如果我們試圖使用基於文本的模型,如 LLaMA 或 Alpaca,來構建一個代碼生成模型,我們可能應該考慮對整個模型進行微調,而不是僅僅使用 LoRA 來調整模型。這是因爲任務與模型已有知識和訓練背景相差甚遠。另一個類似的例子是訓練一個僅理解英語的模型來生成尼泊爾語文本。這類任務要求模型學習全新的語言結構和語法,這遠遠超出了 PEFT 技術通過少量參數調整所能達到的效果。
- LLM 推理 =========
在使用大型語言模型(LLM)進行推理時,我們經常可以通過配置不同的參數來精細調整其輸出和性能。以下是一些關鍵參數的詳細說明:
1. Top-k 採樣:
- 每一步只採樣可能性最高的前 k 個詞彙,促進多樣性並防止重複。更高的 k 值會導致更多樣化的輸出,但可能連貫性稍差。
2. 溫度:
-
影響下一個可能詞彙的概率分佈,控制隨機性和 “創造性”。
-
較低的溫度生成更可能但可能重複的文本,而較高的溫度鼓勵多樣性和不可預測的輸出。
3. Top-P(核)採樣:
- Top-P 或核採樣將詞彙選擇限制在累積概率質量達到閾值值的詞彙子集中。它有助於控制生成輸出的多樣性。
4. 最大長度:
- 設置 LLM 生成的詞彙最大數量,防止輸出過長。
5. 上下文提示:
- 通過提供特定的上下文提示或輸入,你可以引導模型生成與該上下文一致的文本。這有助於確保生成的輸出在給定的上下文中是相關和連貫的。
6. 重複懲罰:
- 對含有重複 n-gram 的序列進行懲罰,鼓勵多樣性和原創性。
7. 採樣:
-
在確定性(貪婪)和基於隨機採樣的生成之間進行選擇。貪婪模式在每一步選擇最可能的詞彙,而隨機採樣引入隨機性。
-
貪婪模式優先考慮準確性,而隨機採樣鼓勵多樣性和創造性。
-
束搜索: 維持多個潛在序列,每一步擴展最有前景的序列,與 top-k 採樣相比,旨在獲得更連貫和更準確的輸出。
通過調整這些參數,用戶可以根據具體需求定製模型的輸出,無論是追求高度準確的文本生成,還是尋求更具創造性和多樣性的結果。這些參數的靈活運用是大型語言模型能夠適應廣泛應用的關鍵所在。
- 提示工程
Prompt Engineering,也被稱作 In-Context Prompting,指的是在不更新模型權重的情況下,通過特定方法與大型語言模型(LLM)交流,以引導其行爲達到期望結果的技巧。這是一門經驗科學,不同的模型對提示工程方法的反應可能大相徑庭,因此需要大量的實驗和直覺判斷。
什麼是提示?
我們與大型語言模型交互時使用的自然語言指令被稱爲提示。構建這些提示的過程就是提示工程。
提示可以被視爲一種橋樑,它連接了人類的意圖和模型的理解。一個好的提示能夠清晰地傳達任務的細節和上下文,幫助模型生成符合期望的響應。提示工程不僅涉及到如何構造一個有效的指令,還包括如何組織和呈現信息,以便模型能夠更好地理解和處理。
提示工程的關鍵在於理解和利用模型的工作原理。例如,通過在提示中包含類似任務的例子,可以激活模型的類比思維,使其更準確地完成任務。此外,通過調整提示的結構、語氣和具體詞彙,可以影響模型生成的輸出類型和風格。
在實踐中,提示工程往往需要經過多次迭代和測試,以找到最適合特定模型和任務的提示形式。這包括試驗不同的指令框架、調整詞彙選擇,以及探索如何通過上下文信息來引導模型的響應。通過不斷優化提示,可以顯著提高模型的性能和響應質量,使其更貼合用戶的需求和期望。
大型語言模型(LLM)根據提示中給出的指令進行推理並完成任務的過程被稱爲 In-Context Learning(在情境中學習)。
少量樣本提示
大型語言模型(LLM)在沒有任何示例的情況下,能夠根據提示中的指令作出響應的能力被稱爲 Zero-Shot Learning(零樣本學習)。
當提供了一個示例時,這種情況被稱爲 One-Shot Learning(一樣本學習)。
如果提供了多個示例,則稱爲 Few-Shot Learning(少量樣本學習)。
Context Window,即大型語言模型能夠提供和推理的最大令牌數量,在 Zero/One/Few Shot Learning 中起着關鍵作用。這個窗口大小決定了模型能夠處理的上下文信息的範圍,直接影響了模型在不同學習模式下的表現。
9.1. 思維鏈提示(Chain-of-Thought (CoT) Prompting)
思維鏈(Chain-of-Thought,CoT)提示 (Wei et al. 2022) 是一種生成一系列短句的方法,這些短句逐步描述推理邏輯,形成所謂的 “推理鏈” 或“理由”,最終導向最終答案。CoT 提示的主要優勢在於,當使用大型模型(例如,參數量超過 500 億)處理複雜推理任務時更爲明顯。對於簡單任務,CoT 提示的益處則相對較小。
9.2. 程序輔助語言模型
Gao et al., (2022) 提出了一種方法,利用大型語言模型(LLM)閱讀自然語言問題,並生成程序作爲中間推理步驟。這種方法被稱爲程序輔助語言模型(Program-Aided Language Models,PAL),它與思維鏈(Chain-of-Thought,CoT)提示的區別在於,PAL 不是使用自由格式的文本來獲得解決方案,而是將解決方案的步驟搬到了程序運行時環境,如 Python 解釋器。
9.3. ReAct Prompting
ReAct 靈感來源於 “行動” 與“推理”之間的協同作用,這種作用使得人類能夠學習新任務並做出決策或推理。
CoT(Chain of Thought)無法訪問外部世界或無法更新其知識,這可能導致幻覺和錯誤傳播等問題。
ReAct 是一種結合了推理和行動的通用範式,與大型語言模型(LLMs)相結合。ReAct 激勵 LLMs 爲任務生成言語推理軌跡和行動。這使得系統能夠進行動態推理,以創建、維持和調整行動計劃,同時還能與外部環境(例如,維基百科)進行互動,將額外信息融入推理過程。下圖展示了一個 ReAct 的示例,以及涉及的不同步驟,用於執行問題回答。
- 模型優化技術
10.1. 量化
模型量化是一種技術,用於通過修改大型神經網絡(包括大型語言模型(LLMs))的權重精度來減小其規模。大型語言模型的量化得以實現,這得益於實證結果表明,雖然神經網絡訓練和推理的一些操作必須利用高精度,但在某些情況下,可以使用顯著較低的精度(例如 float16),從而減少模型的整體大小,使其能夠在功能較弱的硬件上運行,同時能力與準確性可接受地下降。
通常來說,在神經網絡中使用高精度與更高的準確性和更穩定的訓練相關。使用高精度也意味着更高的計算成本,因爲它需要更多的硬件和更昂貴的硬件。谷歌和英偉達進行的研究主要關注在某些神經網絡操作中使用較低精度的可能性,結果顯示,較低精度可以用於一些訓練和推理操作。
除了研究之外,這兩家公司還開發了硬件和框架來支持較低精度的操作。例如,NVIDIA 的 T4 加速器是具有 Tensor Cores 技術的低精度 GPU,其效率遠高於 K80。谷歌的 TPU 引入了 bfloat16 的概念,這是一種針對神經網絡優化的特殊原始數據類型。較低精度的基本理念是神經網絡並不總是需要使用 64 位浮點數的全部範圍,以允許它們表現良好。
隨着神經網絡日益龐大,利用較低精度的重要性對使用這些網絡的能力產生了重大影響。對於大型語言模型(LLMs),這一點變得更加關鍵。
作爲參考,英偉達的 A100 GPU 在其最先進版本中擁有 80GB 的內存。從下表我們可以看到,LLama2-70B 模型大約需要 138GB 的內存,這意味着要承載它,我們需要多塊 A100 GPU。將模型分佈在多塊 GPU 上意味着不僅要支付更多的 GPU 費用,還要承擔額外的基礎設施開銷。相反,量化的版本大約只需要 40GB 的內存,因此它可以輕鬆裝入一塊 A100 中,顯著降低了推理的成本。這個例子還沒有提及,在單一 A100 內,使用量化模型會導致大部分單獨計算操作的執行速度更快。
量化如何縮小模型體積?
量化通過減少表示每個模型權重所需的比特數來大幅減小模型的大小。一個典型場景是從 FP16(16 位浮點數)減少到 INT4(4 位整數)。這使得模型能夠在更便宜的硬件上運行,或者以更高的速度運行。通過降低權重的精度,大型語言模型(LLM)的整體質量也可能受到一定影響。
研究表明,這種影響因所使用的技術而異,並且較大的模型受精度變化的影響較小。對於更大的模型(超過約 700 億參數),即使轉換爲 4 位,它們也能保持其性能,有些技術如 NF4 表明對它們的性能沒有影響。因此,對於這些大模型而言,4 位似乎是在性能與大小 / 速度之間最好的折衷方案,而對於較小的模型,6 位或 8 位可能更爲合適。
大型語言模型量化類型
可以將獲得量化模型的技術分爲兩類:
-
後訓練量化(PTQ):將已經訓練好的模型的權重轉換爲更低的精度,無需重新訓練。儘管 PTQ 實施簡單,但由於權重值精度的損失,可能會輕微降低模型的性能。
-
量化感知訓練(QAT):與 PTQ 不同,QAT 在訓練階段就整合了權重轉換的過程。這通常能帶來更好的模型性能,但計算需求更高。一個廣泛使用的 QAT 技術是 QLoRA。
本篇帖子將專注於**後訓練量化(PTQ)**策略及其之間的核心區別。
大量化模型與小非量化模型對比
認識到降低精度會減少模型的準確性,你是應該選擇一個較小的全精度模型,還是一個具有相當推理成本的較大量化模型?儘管理想的選擇可能因多種因素而異,Meta 近期的研究提供了一些深刻的指導原則。
我們原本預期降低精度會導致準確性下降,但 Meta 的研究人員證明,在某些情況下,量化模型不僅展現出更優的性能,還允許減少延遲並提高吞吐量。同樣的趨勢在比較 8 位 130 億參數模型與 16 位 70 億參數模型時也能觀察到。實質上,當比較具有相似推理成本的模型時,較大的量化模型可以勝過它們較小的、非量化版本。這一優勢在更大規模的網絡中更爲明顯,因爲它們在量化時表現出的質量損失更小。
在哪裏能找到已量化的模型?
幸運的是,可以在 Hugging Face Hub 找到許多使用 GPTQ(部分兼容 ExLLama)、NF4 或 GGML 已經量化的模型版本。快速瀏覽一下就會發現,這些模型中的很大一部分是由 TheBloke 量化的,他是 LLM 社區中一個有影響力且受尊敬的人物。該用戶發佈了多種量化方法的模型,因此人們可以根據每個特定用例選擇最適合的模型。
爲了輕鬆地試驗這些模型,打開 Google Colab,並確保你的運行環境設置爲 GPU(有一個免費的 GPU 可供使用)。首先安裝由 Hugging Face 維護的 transformers 庫和所有必要的庫。因爲我們將會使用使用 Auto-GPTQ 量化的模型,相應的庫也將被需要:
!pip install transformers
!pip install accelerate
# Due to using GPTQ
!pip install optimum
!pip install auto-gptq
你可能需要重啓運行環境,以便讓安裝的庫生效。然後,只需加載已經量化的模型。在這個例子中,我們將加載一個之前使用 Auto-GPTQ 量化的 Llama-2 7B Chat 模型,如下所示:
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model_id = "TheBloke/Llama-2-7b-Chat-GPTQ"
tokenizer = AutoTokenizer.from_pretrained(model_id, torch_dtype=torch.float16, device_map="auto")
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.float16, device_map="auto")
量化大型語言模型
正如前面提到的,Hugging Face Hub 上已經存在大量的量化模型,這在很多情況下消除了個人手動壓縮模型的需求。然而,在某些情況下,你可能想要使用尚未量化的模型,或者你可能想要自己壓縮模型。這可以通過使用針對你特定領域定製的數據集來實現。
爲了演示如何輕鬆地使用 AutoGPTQ 和 Transformers 庫來量化模型,我們採用了一種 Optimum 中簡化的 AutoGPTQ 接口——Optimum 是 Hugging Face 針對訓練和推理優化的解決方案:
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_id = "facebook/opt-125m"
tokenizer = AutoTokenizer.from_pretrained(model_id)
quantization_config = GPTQConfig(bits=4, dataset = "c4", tokenizer=tokenizer)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=quantization_config)
模型壓縮可能耗時較長。例如,一個 1750 億參數的模型至少需要 4 小時的 GPU 時間,特別是在使用像 “c4” 這樣龐大的數據集時。值得注意的是,量化過程中的比特數或數據集可以通過 GPTQConfig 的參數輕易調整。改變數據集會影響量化的方式,因此如果可能的話,使用與推理中見到的數據類似的數據集,以最大化性能。
量化技術
在模型量化領域,出現了幾種前沿的方法。讓我們深入瞭解一下其中一些顯著的技術:
-
GPTQ: 包括 AutoGPTQ、ExLlama 和 GPTQ-for-LLaMa 等實現選項,這種方法主要側重於 GPU 執行。
-
NF4: 它在 bitsandbytes 庫中實現,與 Hugging Face 的 transformers 庫緊密合作。它主要被 QLoRA 方法使用,以 4 位精度加載模型進行微調。
-
GGML: 這個 C 庫與 llama.cpp 庫緊密配合。它爲 LLMs 設計了一種獨特的二進制格式,允許快速加載和易於讀取。值得注意的是,它最近轉向 GGUF 格式,確保了未來的可擴展性和兼容性。
許多量化庫支持多種不同的量化策略(例如 4 位、5 位和 8 位量化),每種策略在效率和性能之間提供了不同的權衡。
10.2. 蒸餾
知識蒸餾(KD;Hinton 等人,2015,Gou 等人,2020)是一種簡單有效的方法,通過將預訓練的昂貴模型(“教師模型”)的技能轉移到更小、更經濟的模型(“學生模型”)上來加速推理。除了要求學生模型與教師模型有匹配的輸出空間以構建適當的訓練目標外,對學生架構的構建並沒有太多限制。
教師模型已經在訓練數據上進行了微調。因此,概率分佈很可能與真實數據非常接近,且在 tokens 上的變化不會太多。
所以,當溫度 > 1 時,概率分佈變得更寬泛。T > 1 => 教師模型的輸出 -> 軟標籤,學生模型的輸出 -> 軟預測 T = 1 => 教師模型的輸出 -> 硬標籤,學生模型的輸出 -> 硬預測
蒸餾對於生成解碼模型並不是特別有效。它更適合於只有編碼器的模型,比如 BERT,這類模型具有大量的表示冗餘。
10.3. 剪枝
網絡剪枝是通過修剪模型中不重要的權重或連接來減小模型大小,同時保持模型的容量。剪枝可能需要重新訓練,也可能不需要。剪枝可以是無結構的或有結構的。
-
_無結構剪枝_允許刪除任何權重或連接,因此不會保留原始網絡架構。無結構剪枝通常與現代硬件不太兼容,也不會導致實際的推理加速。
-
有結構剪枝_旨在保持密集矩陣乘法的形式,其中某些元素爲零。它們可能需要遵循一定的模式限制,以適應硬件內核支持的特性。在這裏,我們專注於有結構剪枝,以在 Transformer 模型中實現_高稀疏度。
構建剪枝網絡的一般工作流程包含三個步驟:
-
訓練一個稠密網絡直到收斂;
-
剪枝網絡以移除不必要的結構;
-
可選地,重新訓練網絡以使用新的權重恢復性能。
通過網絡剪枝在稠密模型中發現稀疏結構的想法,同時稀疏網絡仍能保持相似性能,源於彩票假設(LTH):隨機初始化的、稠密的、前饋網絡包含了一組子網絡,其中只有一部分(稀疏網絡)是 “中獎票”,當孤立訓練時,可以達到最優性能。
在我們的下一篇博客中,我們將繼續討論大型語言模型(LLM)的評估。
結論
在這篇博文中,我們探討了檢索增強生成(RAG)應用中的文本生成部分,重點在於大型語言模型(LLM)的使用。它涵蓋了語言建模、預訓練挑戰、量化技術、分佈式訓練方法以及 LLM 的微調。討論了 Parameter Efficient Fine-Tuning(PEFT)技術,包括 Adapters、LoRA 和 QLoRA。介紹了提示策略、模型壓縮方法如剪枝和量化,以及各種量化技術(GPTQ、NF4、GGML)。博文以對模型尺寸縮減的蒸餾和剪枝的見解結束。
英文原文:https://medium.com/@vipra_singh/building-llm-applications-large-language-models-part-6-ea8bd982bdee
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/TqROP_HcfCw0VtwjcyMJ0Q