如何利用硬件
這個單元分為內核、并行處理和推理。
內核(Kernels)
我們說的內核一般指的就是GPU,這是我們用于計算的地方,一般說的計算資源就指的是GPU的大小。我們模型所用的數據和參數一般存儲在內存里,假設把內存比喻為倉庫,GPU比喻為工廠,那么我們所要做的就是最大限度提高數據在倉庫和工廠之間運輸的效率,像我們常說的矩陣乘法、融合或分塊等算法都是在減少數據運輸的成本。
并行處理(parallelism)
就如字面意思一樣,多個GPU連接著一個個CPU,彼此并行傳輸數據,我們需要思考如何防止模型參數、激活值(模型在處理輸入數據時,每一層神經網絡的中間輸出結果。這些值反映了模型在特定層對輸入信息的非線性變換結果,是模型理解和生成文本的關鍵中間狀態)或梯度來提高運輸效率,與內核的本質是一樣的,只是這個的關鍵在于并行鏈接的處理方式。
推理(inference)
推理指的是我們實際使用模型的方式,指的是在給定提示的情況下完成生成提示詞的任務。推理的成本比訓練模型的成本大得多,后者是一次性成本,而前者伴隨著模型使用者的增多,需要不斷地提高推理的高效,這就需要不斷地投入成本。推理分為兩個階段:預填充和解碼。預填充階段,模型會根據提示詞,運行得到一些激活值,然后在解碼階段自回歸地生成一個個詞元(token)。在推理中,比較困難的就是解碼階段,因為是一次生成一個token,這很難讓我們的并行處理的GPU進行飽和式的運行,在這里會浪費一些資源,同時由于不斷地移動數據,進一步地放大這種損失。當然,我們可以選擇一些快速推理模型來降低1成本浪費,比如推理型解碼,通過預設一些tokens,假設這些是我們需要的或通過評分認為這些是好的,就全部接受,從而省去了生成一部分token所花費的資源。
在構建這些部分的過程中,我們要養成總是進行基準測試和性能分析的習慣。因為在過程中我們可以寫想要實現的任何一個功能,但我們需要反饋來確定進展在哪個階段以及定位瓶頸,也就是上限在哪里,以便我們確認我們構筑的方向是對的以及處理好一些細節來提高上限。
縮放法則(scaling laws)
之前我們說到過理想情況是在小規模上做實驗并弄清楚問題,然后預測大模型下的超參數和損失。這里會引出一個基本問題,假設給出一個浮點運算預算,應該用多大的模型。如果使用更大的模型,就意味著可以在更少的數據上訓練,相反則是可以在更多的數據上訓練。那么該如何找到這里的平衡點呢?我們一般會根據一個經驗法則去判斷:假定有一個大小為n的模型,那么將n乘以20,得到的結果就是我們要訓練的token的數量。當然這里指的是如何訓練出最佳的模型,而不是最劃算的模型,是忽略了模型的推理成本的。
數據
即使我們做好了架構,調試好了參數,但模型會用于做什么還是取決于我們輸入的數據。如果是多語言數據,那么訓練出的就是多語言模型,輸入的是代碼數據,訓練出的就是代碼模型。那么我們該如何評估模型的能力呢。這就需要用到困惑度指標、標準化測試、跟隨回復以及其他的一些包括評估整個模型的方法。
討論完了評估,我們繼續回溯,就到了如何篩選要訓練的數據了。畢竟我們平時練習用到的數據,很多都是別人處理好的,不管是在網站爬取的統計數據,還是網頁上的文本,都是需要進行大量的細節操作來進行篩選的,以確保數據盡可能多保留我們想要的信息的前提下(一般會用到分類器來過濾掉垃圾信息,以及用去重來保證信息的唯一性,不讓模型重復識別某類信息),更好地被模型識別。
在經歷了這么多步驟后,我們就得到了一個可以預測下一個token的基礎模型。我們會通過對齊(通過技術手段使得模型的輸出是符合我們期望的)的操作來滿足三件事:讓語言模型的能夠跟隨指令去生成對應的token;確定模型的風格;模型能夠拒絕回答一些性質是有害的問題。對其一般分為兩個階段,一個是監督微調,通過少數的數據(一般在一千個就可以讓模型可以跟隨指令了)來達成好的學習效果,另一個是讓模型去學習偏好的數據。即給定問題讓模型去回答,并讓用戶給回答打分,從而得到偏好數據讓模型去學習。最后是在這些數據的基礎上,應用算法,讓模型進行真正的訓練以擁有對應的功能。
學習來源于B站教程:【斯坦福大學 ? CS336】從零開始構建語言模型 | 2025 年春季_嗶哩嗶哩_bilibili