今天小編分享的科學經驗:王小川的大模型打造秘籍首次曝光:五步走,兩個月煉成,歡迎閲讀。
王小川兩個月交卷的大模型,是怎麼煉成的?
現在,這個問題有了更為詳細的解。
70 億參數、一經發布就開源可商用,百川智能的中英文大模型 baichuan-7B,近期在圈内備受矚目。
從公開的 benchmark 測試效果以及社區的使用反饋來看,baichuan-7B 的表現非常優秀,據説清北也已經用上了。
其源代碼也已在 Github、Huggingface 等平台發布。
有趣的是,開源社區在圍繞 baichuan-7B 進行實驗和應用構建時,GitHub 項目 LLM-Tuning 的作者郭必揚(beyondguo)發現了 baichuan-7B 的一個特殊能力。
他在做信息抽取實驗的時候,自己胡編亂造了一段 " 新聞 ",然後故意将 " 微軟 " 寫成 " 巨硬 "," 亞馬遜 " 寫成 " 亞牛遜 "," 谷歌 " 改為 " 谷嘎 " ……
然後使用下面的的 instruction:
ChatGPT(3.5)的表現是這樣嬸兒的:
接下來就是鵝妹子嘤的時刻了:
特殊微調之後的 baichuan-7B 把作者胡編亂造的公司名字,全都掰了回來!!!
看到這,直接給郭必揚(beyondguo)驚喜(驚吓)住:
本來是亂編的新聞,這這這就説不清了啊!
baichuan-7B 的能力我們是看到了,但它開源也并不意味着人人都可以輕易復刻一個大模型出來。
源代碼只是算法的核心,也就是能夠看到模型結構而已。
" 一開源就能人手一份,進行各種換皮魔改,同人逼死官方 " 這事兒,在大模型這兒行不通。
要得到一款和 ChatGPT 效果相仿的大模型,算法、算力和數據缺一不可。
抛開算力不講,從 0 到 1 構建一款大模型,都需要哪些步驟?
這不,baichuan-7B 給出了一份 " 高分案例 "。
訓練大模型五步走
官方透露,baichuan-7B 的 " 煉化 " 過程可以歸納為五步。
第一步,構建優質的數據集
數據是大模型的三要素之一。
語言模型是一種用于計算 " 一段文本 " 出現可能性的統計模型,其本質是建模字、詞之間的關聯性。
這種字、詞之間的關聯性必須通過大量數據的分析和學習才能得到,因此數據對于大模型而言可以説是最重要的元素,預訓練數據的質量、多樣性、規模、代表性以及公平性和偏見等因素對模型性能有着決定性影響。
baichuan-7B 模型在數據方面作了以下處理:
數據規模和多樣性:baichuan-7B 的原始數據包括開源的中英文數據和自行抓取的中文互聯網數據,以及部分高質量知識性數據。這種構建方式使其原始數據集包含了大量 source 的數據,在過濾後也能有 1.2T 的量級,同時也保證了數據的多樣性。
數據的公平性和偏見:為避免模型輸出有害性内容,提升模型效果,baichuan-7B 通過人工規則等方式過濾髒數據,去掉了數據中的噪聲和有害數據。
數據質量和代表性:經過低質過濾之後,baichuan-7B 對得到的數據還進行了去重處理和有代表性數據的選取。具體表現為,基于啓發式規則和質量模型打分,對原始數據集進行篇章和句子粒度的過濾;在全量數據上,利用局部敏感哈希方法,對篇章和句子粒度做濾重,從而減少數據中的重復 pattern 和不具備代表性的數據,進一步提升數據質量。
整體流程如下圖所示:
此外,為了實現模型在多語言上的良好表現,得到高質量的數據集之後,baichuan-7B 又采用了自動化的數據采樣策略,最終确認了一個在下遊任務上表現最好的中英文配比。
第二步,制定合理的分詞策略
擁有了一個優質的數據集之後,需要思考的便是:
如何将數據集裏面的語料充分利用起來?
目前大部分開源模型主要基于英文優化,因此對中文語料存在效率較低的問題,這也是一些國外的大模型在中文生成方面表現相比英文較差的原因。
baichuan-7B 采用了 SentencePiece 中的 Byte-Pair Encoding ( BPE ) 作為分詞算法,并且進行了以下的優化:
首先,使用 2000 萬條以中英為主的多語言語料訓練分詞模型,顯著提升對于中文的壓縮率。
其次,在數學領網域參考了 LLaMA 和 Galactica 中的方案,對數字的每一位單獨分開,避免出現數字不一致的問題。
再次,針對罕見字詞(如特殊符号等),支持 UTF-8 characters 的 byte 編碼,做到了未知字詞的全覆蓋。
對比不同分詞器對語料的壓縮率,可見其分詞器明顯優于 LLaMA、Falcon 等開源模型,在壓縮率相當的情況下,訓練和推理效率更高。
第三步,打造良好的模型結構
提到大模型," 大力出奇迹 " 是我們經常挂在嘴邊的一句話," 力大磚飛 " 隐藏的含義是大模型并未在技術路線上取得革命性的突破,其底層技術基礎依舊是 Transformer。
換言之,當下的絕大部分大語言模型依舊是 Transformer 模型,只不過模型全部由 Transformer 的 Decoder 層構成,具體分為以下幾個部分:
1、Position Embedding,即位置編碼。
在 Transformer 中所有 token 都被同樣的對待,沒有前後順序之分,因此需要加入一個 Position Embedding 用于表征詞之間的位置關系。
目前的位置編碼有絕對位置編碼和相對位置編碼兩種形式:
絕對位置編碼指的是直接将位置信息通過向量的形式融合到模型輸入中。
常用的兩種絕對位置編碼方法主要是在 Transformers 中使用的 Sinusoidal Positional Encoding 以及 Convolutional Sequence-to-Sequence 模型中使用的 Learned Position Embeddings。
其中,Sinusoidal Positional Encoding 在原始的 Transformer 模型(Vaswani 等人,2017)中,引入了一種預定義的正弦函數作為位置編碼。這種方法會為每個位置生成一個固定向量,該向量的維度跟詞嵌入向量相同。
其優點在于,它可以處理任意長度的序列,不需要額外的學習過程,并且對于相對位置關系有一定的編碼能力。
Learned Position Embeddings 由 Gehring 等人于 2017 年在 Convolutional Sequence-to-Sequence 模型中首次提出。
對于每個位置,模型都有一個對應的嵌入向量,這個向量會在模型訓練的過程中學習和優化。
該方法的優點在于,它可以根據具體的任務和數據集學習位置信息。然而,它的一大缺點是,由于位置嵌入數量固定,因此模型可能無法處理超過預先設定數量位置的序列。
相對位置編碼指的是在自注意力機制中引入兩個 Token 的相對位置信息。
目前,相對位置編碼主要有兩種常用方法:ROPE ( Rotary Positional Embedding ) 和ALiBi ( Attention with Linear Biases ) 。
ROPE 可以不受固定長度限制處理任意長度的序列。其工作原理是,通過一個基于位置的旋轉矩陣将每個位置的嵌入旋轉到一個新的位置。
這種方法的優點是,可以保持相對位置信息的一致性,在旋轉後,相鄰的位置仍然會有相似的嵌入。
ALiBi 能夠讓 Transformer 語言模型在推理時可以處理比訓練時更長的序列。
它在處理文本序列時不使用實際的位置嵌入,而是在計算某個鍵和查詢之間的注意力時,根據鍵和查詢之間的距離對查詢可以分配給鍵的注意力值進行懲罰。當鍵和查詢靠近時,懲罰非常低,當它們遠離時,懲罰非常高。
這種方法的動機是,靠近的詞比遠離的詞更重要。
2、Attention Layer,即注意力層。
其原理是通過加入注意力層使得不同 Token 之間能夠互動信息,進而獲得整句話的表征。
目前大模型使用的 Attention Layer 分為多頭自注意力(Multi-Head Self-Attention)和稀疏自注意力(Sparse Self-Attention)兩種。
Multi-Head Self-Attention 機制最早出現在 "Attention is All You Need"(Vaswani et al., 2017)論文中,是 Transformer 模型的核心組成部分。
在多頭自注意力中,模型首先将輸入的嵌入向量分割成多個 " 頭 ",每個頭都會獨立地進行自注意力計算,最後所有頭的輸出會被連接起來并通過一個線性變換,形成最終的輸出。
其優點是,每個頭都可以學習并關注輸入的不同方面,模型能夠同時關注來自不同位置的信息,從而捕獲更豐富的上下文信息。
Sparse Self-Attention 是一種改進的自注意力機制,它只關注輸入中的一部分元素。
這種方法的優點是,可以顯著減少計算復雜性,使得模型能夠處理更長的序列。
3、FFN Layer,即前饋神經網絡。
其主要任務是處理來自 Attention 層的信息。
Attention 機制能夠處理詞語之間的相互關系,但是它無法進行更為復雜的、非線性的數據處理。
而 FFN 層可以在每個 Transformer 模塊中增加非線性處理能力,增強模型的整體表達能力。
在原始的 Transformer 模型中,FFN 層通常由兩個線性變換和一個非線性激活函數(如 ReLU 或 GELU)組成。
以下是一些 FFN 層的變種:
标準的 FFN 層:在 "Attention is All You Need"(Vaswani et al., 2017)中,FFN 層由兩個線性變換和一個非線性激活函數組成。具體來説,給定輸入 x,FFN 層的計算過程為:FFN ( x ) = max ( 0, xW1 ) W2,其中 W1,b1,W2,b2 是模型參數,max ( 0, * ) 表示 ReLU 激活函數。
Gated Linear Units ( GLU ) 變種:在 "Language Modeling with Gated Convolutional Networks"(Dauphin et al., 2017)中提出,GLU 是一種特殊的激活函數,它通過引入一個門控機制來控制信息的流動。在 FFN 層中使用 GLU 可以幫助模型更好地捕捉輸入數據的復雜模式。GLU 的計算公式為:GLU ( x ) = ( xV + c ) ⊗ sigmoid ( xW + b ) ,其中⊗表示元素級别的乘法,sigmoid 是 sigmoid 激活函數。
Swish 變種:在 "Searching for Activation Functions"(Ramachandran et al., 2017)中提出,Swish 是一種自門控的激活函數,它的計算公式為:Swish ( x ) = Swish1 ( xW1 ) W2。在 FFN 層中使用 Swish 可以幫助模型更好地捕捉輸入數據的復雜模式。
SwiGLU 變種:在 GLU Variants Improve Transformer 中,作者提出了一種新的激活函數 SwiGLU,它結合了 Swish 和 GLU 的優點。SwiGLU 的計算公式為:SwiGLU ( x ) = ( xV + c ) ⊗ Swish1 ( xW + b ) ,其中⊗表示元素級别的乘法,sigmoid 是 sigmoid 激活函數。
baichuan-7B 的模型結構同樣基于Transformer。
在模型研發過程中,為了能夠讓模型在 4096 的視窗長度内擁有最好效果,同時在 4096 長度外也具備較好的外推性能,baichuan-7B 采取了和 LLaMA 相同的結構設計,而這些關鍵要素上的設計也和很多其他模型選擇的設計相類似。
社區中 Saleforces 所提出的 XGen-7B 和由 Berkeley 所提出的 OpenLLaMA 也是同樣的選擇,具體而言:
Position Embedding 采用ROPE 相對位置編碼,相對編碼能夠讓模型獲得較好的外推能力。Meta 的 LLaMA、Google 的 PaLM、清華團隊的 ChatGLM2 都使用了 ROPE 相對位置編碼。
Attention Layer 采用标準的Multi-Head Self-Attention,雖然目前很多稀疏自注意力層能夠在超長文本中獲得較好的效果,但是這些方案由于使用了稀疏計算,對于 4096 長度内的效果會有一定的犧牲,使用标準的 Multi-Head Self-Attention 能夠讓大部分結果擁有更好的效果。
FFN Layer 采用SwiGLU,目前大部分 SOTA 模型都選擇使用 SwiGLU 作為 FFN 層,如 2022 年 Google 提出的 PaLM 模型,2023 年 META 提出的 LLaMA,最近清華團隊發布的 ChatGLM2 等。
第四步,采用恰當的優化訓練策略
訓練策略也是模型取得較好結果的重要組成部分。
例如,初代 GPT-3 在當時的訓練框架下,基于 V100 訓練 1750 億參數模型的整體機器利用率大概只有 21.3%。這種極低的利用率會拉長模型訓練周期,影響模型迭代進度。
為更好提升模型訓練過程中的機器利用率,baichuan-7B 針對訓練策略也提出了很多優化手段,具體包括:
首先,優化了算子技術,通過應用更有效率的算子提高運算效率,例如 Flash-Attention 和 NVIDIA apex 的 RMSNorm,優化後的 Attention 方法在非近似的基礎上可以顯著降低模型的顯存消耗。
其次,baichuan-7B 利用算子切分技術,對部分計算算子進行切分,這樣在通信的時候會以更高效的 nccl 操作進行通信,同時降低内存峰值使用,以進一步提升處理速度。
同時,baichuan-7B 還使用了混合精度技術,在不犧牲模型準确性的前提下,加速了計算過程。
此外,為了進一步提高效率,baichuan-7B 還采用了通信優化技術,具體包括:利用拓撲感知的集合通信算法避免網絡擁堵問題,提高通信效率;根據卡數自适應設定 bucket size,提高帶寬利用率;根據模型和集群環境,調優通信原語的觸發時機,從而實現計算和通信的有效重疊。
最後,baichuan-7B 還自研了一種名為訓練容災的技術。
訓練大模型,需要的時間通常很長,很難保證 GPU 在訓練過程中不出問題,特别是集群訓練的時候,單卡硬體或者網絡錯誤會導致整個集群停擺。因此在訓練中斷後快速、自動化定位故障、恢復服務非常重要。
通過訓練平台和訓練框架的聯合優化以及 IaaS+PaaS 的應用,baichuan-7B 實現了分鍾級的故障定位和任務恢復,從而保證了訓練的穩定性和效率。
第五步,選擇合适的模型評價方法
完成數據集構建,對數據集中的語料進行分詞并在構建好的模型中進行預訓練之後,為了解模型的各方面能力,還需要對模型進行測試和評價。
不同于微調後的模型直接采用 zero-shot(直接給 prompt)的評估方式,預訓練基座模型通常采取 few-shot(給一些示例 prompt)的評價方式來評估效果。
目前,比較權威的幾個評估數據集主要有中文數據集 C-Eval 數據集、Gaokao、AGIEval,英文數據集 MMLU,代碼能力評估集 Human Eval 和數學能力評估集 GSM8K、MATH 等。
其中,C-Eval 數據集是最全面的中文基礎模型評測數據集,涵蓋了 52 個學科和四個難度的級别;
Gaokao 是以中國高考題作為評測大語言模型能力的數據集,用以評估模型的語言能力和邏輯推理能力;
AGIEval 旨在評估模型在中文環境下,認知和解決問題等相關的任務的能力;
MMLU 是一個包含 57 個多選任務的英文評測數據集,涵蓋了初等數學、美國歷史、計算機科學、法律等,難度覆蓋高中水平到專家水平,是目前主流的 LLM 評測數據集。
中文評測方面,baichuan-7B 在 C-Eval、Gaokao 和 AGIEval 的綜合評估中均獲得了優異成績,不僅遠超其他同規模參數的大模型,甚至比某些參數規模更大的模型還要出色。
在英文能力上,選擇 MMLU 數據集進行評測,baichuan-7b 的表現在同尺寸上也大幅領先。
值得一提的是,根據官方的 github 開源協定説明上,baichuan-7B 開源的推理代碼采用了 Apache2.0 協定。
不同于其他基于 LLaMA 繼續訓練(比如 IDEA 的 ziya、鏈家的 BELLE 等)無法商用的模型,baichuan-7 是原生訓練的模型,可以自主定義模型權重的開源協定。
值得稱贊的是百川智能采用的是免費可商用協定,比其他需要付費商用有更大的自由度,開發者們可以直接使用預訓練模型進行各種實驗研究,并完成部署和應用。
開源 VS 閉源,哪一種模式最有效?
説完了大模型的訓練步驟,最後來談一談開源的問題。
五月初,谷歌曾泄露出一份内部檔案,這份檔案聲稱:" 我們沒有護城河,OpenAI 也沒有。當我們還在争吵時,開源第三方已經悄悄地搶了我們的飯碗 "。
谷歌顯然已經意識到了開源的影響,那麼開源和閉源究竟哪一種模式更有效?
百川智能給出了他們的回答:
眾所周知大模型的訓練成本極高,因此以閉源保證商業投入是比較有效的方式。
不過,開源創新早就已經成為了軟體發展乃至于 IT 技術發展的一種主流技術形态,超級計算機的作業系統幾乎都是用 Linux 這樣的開源軟體作業系統進行構建,智能手機的作業系統 80% 以上都由開源的安卓系統支持。
在大模型出現之前,深度神經網絡的學習框架也幾乎都是開源的。
雖然目前 OpenAI 和谷歌都選擇了 " 閉門造車 ",但是 Meta 卻走上了開源的道路,LLaMA 開源之後迅速地吸引了大量開發者,這和互聯網時代 Linux,移動互聯網時代的安卓十分相似。
就像 Linux 和安卓都會在社區上開源出一個核心的版本,然後更多人在這個核心版本上根據他對需求和領網域的理解進行不斷地修改,低成本產生更多适應未來發展的新版本,由環境來評價,然後再迭代回來不斷地開發。
這種眾人拾柴的研發路徑在大模型時代無疑還将發揮巨大作用,開源和閉源究竟哪一個更有效現在還很難説,就像我們無法説 iOS 要安卓更有效一樣。
但是,未來的大模型生态一定會是壟斷與開源并存。