自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

大模型微調(diào):Hugging Face Transformers全流程實戰(zhàn) 原創(chuàng)

發(fā)布于 2024-9-26 10:36
瀏覽
0收藏

隨著大模型在人工智能領(lǐng)域的興起,如何將其應(yīng)用于垂直領(lǐng)域成為關(guān)鍵問題。本文描述了模型微調(diào)技術(shù),通過調(diào)整預(yù)訓(xùn)練模型的參數(shù),使其適應(yīng)特定任務(wù),從而提升模型在特定領(lǐng)域的表現(xiàn)。文中以 Yelp 數(shù)據(jù)集為例,詳細(xì)介紹了如何使用 Hugging Face Transformers 框架對 BERT 模型進行微調(diào),實現(xiàn)評論星級分類任務(wù)。文檔涵蓋了微調(diào)的背景、主流手段、架構(gòu)和工具,并深入講解了微調(diào)的思路和實踐步驟,包括數(shù)據(jù)預(yù)處理、模型選擇、超參數(shù)設(shè)置、訓(xùn)練評估和結(jié)果驗證等。

大模型風(fēng)頭正盛,微調(diào)展現(xiàn)威力

近年來,大型預(yù)訓(xùn)練模型如GPT系列、Llama系列、通義千問在各大科技巨頭的推動下,成為了人工智能領(lǐng)域的明星。然而,除了這些通用模型外,越來越多的垂直領(lǐng)域企業(yè)也在利用這些大模型,通過模型微調(diào),打造符合行業(yè)需求的定制化解決方案。

以一家科技公司為例,公司需要頻繁參與技術(shù)類項目的投標(biāo),每次都要根據(jù)具體項目的要求編寫詳細(xì)的技術(shù)方案。如果直接使用預(yù)訓(xùn)練好的通用語言模型來生成技術(shù)方案,雖然模型在理解語言和生成文本方面表現(xiàn)不錯,但對于科技行業(yè)特有的技術(shù)術(shù)語、項目需求以及公司的業(yè)務(wù)特點,它的輸出質(zhì)量可能并不理想。通過模型微調(diào),公司可以使用少量歷史投標(biāo)文件和行業(yè)相關(guān)的標(biāo)記數(shù)據(jù),對模型進行再訓(xùn)練,使其生成的技術(shù)方案更加貼合公司的技術(shù)風(fēng)格和項目要求。這樣,微調(diào)后的模型不僅能顯著提高方案生成的準(zhǔn)確性,還能幫助公司減少手工編寫時間,提高效率和投標(biāo)成功率。

關(guān)于模型微調(diào),我們還可以舉一個例子:假設(shè)你已經(jīng)學(xué)會了畫畫,能畫出非常漂亮的風(fēng)景畫?,F(xiàn)在,你想畫一只特定品種的小鳥,雖然你已經(jīng)有了基礎(chǔ)的畫畫技巧,但為了畫好這只小鳥,你還需要學(xué)習(xí)一些額外的技巧,比如觀察它的羽毛顏色和翅膀形狀。模型微調(diào)就像是這樣一個過程:AI模型已經(jīng)掌握了很多基礎(chǔ)技能,但要完成特定任務(wù),還需要通過微調(diào)來“特訓(xùn)”,以提高它在某個領(lǐng)域的表現(xiàn)。

從理論上看,模型微調(diào)是針對已經(jīng)經(jīng)過大規(guī)模數(shù)據(jù)預(yù)訓(xùn)練的通用模型進行小規(guī)模的再次訓(xùn)練,使其在特定任務(wù)中表現(xiàn)更好。這種方法不僅節(jié)省了從零開始訓(xùn)練的資源和時間,還通過遷移學(xué)習(xí)的方式,充分利用了預(yù)訓(xùn)練模型中的豐富知識。

在論文BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (Devlin et al., 2018)中就指出通過預(yù)訓(xùn)練和微調(diào)的結(jié)合,顯著提升了模型在多項任務(wù)中的表現(xiàn)。在Transfer Learning for NLP: A Comprehensive Survey (Ruder, 2019) 中也提到遷移學(xué)習(xí)與微調(diào)技術(shù)的演變,以及它們在自然語言處理中的關(guān)鍵作用。這些研究表明,微調(diào)不僅能讓通用模型更好地適應(yīng)具體任務(wù),還能為各行業(yè)提供高效且專業(yè)化的解決方案。這就是為什么在現(xiàn)代AI領(lǐng)域,微調(diào)成為了一項不可或缺的技術(shù)。

主流的微調(diào)手段

既然大模型微調(diào)解決了企業(yè)在垂直領(lǐng)域的大模型使用問題,那么市面上有哪些微調(diào)的手段呢?微調(diào)(Fine-tuning)作為將大型預(yù)訓(xùn)練模型應(yīng)用于特定任務(wù)的重要手段,依賴于對模型參數(shù)的靈活調(diào)整。不同任務(wù)的需求、數(shù)據(jù)量的大小以及計算資源的限制,決定了選擇哪種微調(diào)方式。以下是幾種主流的微調(diào)策略:

  • 基于特征的調(diào)優(yōu)(Feature-Base Approach):在不修改預(yù)訓(xùn)練模型參數(shù)的前提下,通過提取特征向量并應(yīng)用于下游任務(wù)。例如在圖像識別任務(wù)中,利用預(yù)訓(xùn)練模型的輸出作為輸入特征來訓(xùn)練一個簡單的分類器。
  • 輸出層更新的微調(diào)(Finetuning I):凍結(jié)模型的前幾層,僅對輸出層或最后幾層進行更新。這種方法適合在數(shù)據(jù)量有限的情況下,保持模型的高效性,并避免過擬合。
  • 全層更新的微調(diào)(Finetuning II):模型的所有層都會參與更新,適合數(shù)據(jù)量充足且任務(wù)復(fù)雜的場景。它可以讓模型更深層次地適應(yīng)特定領(lǐng)域的特性,但計算開銷較大。
  • 參數(shù)高效微調(diào)(Parameter-Efficient Fine-tuning, PEFT):PEFT 通過適配器訓(xùn)練(Adapter Training)或低秩分解等方法,只增加少量新的參數(shù)進行訓(xùn)練,保持原模型參數(shù)的結(jié)構(gòu)不變。這種方法能夠極大減少計算資源需求,尤其適用于資源有限或需要快速迭代的任務(wù)。
  • 蒸餾(Distillation):將大型模型(教師模型)的知識提取并應(yīng)用到一個較小的模型(學(xué)生模型)中,從而實現(xiàn)性能與計算效率的平衡。學(xué)生模型保留了教師模型中的關(guān)鍵知識,同時大幅減少了計算資源的消耗。
  • 適配器訓(xùn)練(Adapter Training):適配器是一種將少量新增參數(shù)插入到預(yù)訓(xùn)練模型中的技術(shù),能夠讓模型在不完全重訓(xùn)練的情況下適應(yīng)新任務(wù),從而降低計算開銷并提高效率。
  • 提示調(diào)優(yōu)(Prompt-tuning):在這種方式中,通過設(shè)計特定的提示詞來引導(dǎo)模型輸出所需的結(jié)果,而不需要調(diào)整模型參數(shù)。這種方法適合數(shù)據(jù)少且需要快速部署的場景。

微調(diào)的架構(gòu)和工具

前面我們提到了,在不同的應(yīng)用場景需要使用不同的微調(diào)手段,那么有哪些大模型微調(diào)的工具和框架可以幫助開發(fā)者快速上手微調(diào)呢?在業(yè)內(nèi), Hugging Face Transformers 和 DeepSpeed 是兩個備受矚目的工具和架構(gòu),它們的出現(xiàn)使得微調(diào)變得更加高效和可擴展。

1. Hugging Face Transformers

Hugging Face 的 Transformers 框架是目前自然語言處理(NLP)領(lǐng)域中最受歡迎的工具之一。它的優(yōu)勢在于簡化了從預(yù)訓(xùn)練模型加載到微調(diào)整個過程的復(fù)雜性:

  • 豐富的模型庫:Hugging Face 提供了一個龐大的模型庫,包括 BERT、GPT、T5 等預(yù)訓(xùn)練模型。
  • 簡化的微調(diào)流程:借助其高層 API 和 Trainer 模塊,開發(fā)者可以輕松地在自己的數(shù)據(jù)集上微調(diào)模型。Trainer 支持自動混合精度訓(xùn)練、分布式訓(xùn)練和動態(tài)批量大小調(diào)整等功能。
  • 集成的社區(qū)和數(shù)據(jù)集:Hugging Face 平臺上的模型和數(shù)據(jù)集共享機制讓開發(fā)者能夠輕松訪問他人的工作成果。

2. DeepSpeed

DeepSpeed 是微軟推出的一款針對大規(guī)模深度學(xué)習(xí)模型的優(yōu)化工具,它的主要優(yōu)勢在于極大地提高了訓(xùn)練效率,尤其適合處理像 GPT-3 這樣的超大規(guī)模模型。

  • 混合精度訓(xùn)練(FP16/BF16):DeepSpeed 通過混合精度技術(shù),在不犧牲性能的前提下顯著減少模型的內(nèi)存占用,并加快計算速度。
  • 零冗余優(yōu)化(ZeRO Optimizer):DeepSpeed 采用了零冗余優(yōu)化策略,可以在多 GPU 環(huán)境下大幅度減少內(nèi)存開銷,使得在相對有限的硬件資源下也能訓(xùn)練大型模型。
  • 支持大規(guī)模并行化:DeepSpeed 提供了靈活且高效的分布式訓(xùn)練方案,能夠高效擴展至成千上萬的 GPU,適用于大規(guī)模的微調(diào)任務(wù)。

參數(shù)高效的訓(xùn)練:通過對訓(xùn)練過程的優(yōu)化,如梯度累積、張量并行等技術(shù),DeepSpeed 可以在降低內(nèi)存需求的同時提高訓(xùn)練速度。

微調(diào)思路

雖然兩個調(diào)優(yōu)工具都非常優(yōu)秀,但由于本文篇幅有限,所以我們選取Hugging face Transformers 框架來為大家進行大模型調(diào)優(yōu)的實踐。

這里通過一張圖來介紹大模型微調(diào)的思路,如下圖所示,展示了從文本預(yù)處理到模型訓(xùn)練、評估、驗證和保存等全過程。對于本次微調(diào),我們希望解決“分類問題”,讓模型理解“評論內(nèi)容”與“評分星級”之間的關(guān)系,這里我們會提供大量的評論數(shù)據(jù),每條數(shù)據(jù)會打上評分星級。在微調(diào)之后,給模型輸入任何的評論內(nèi)容,它都會返回該評論對應(yīng)的星級。接下來的過程將分為幾個主要步驟:

大模型微調(diào):Hugging Face Transformers全流程實戰(zhàn)-AI.x社區(qū)

 1. 確認(rèn)問題

首先,要確認(rèn)本次微調(diào)要解決的問題:理解“評論內(nèi)容”與“評分星級”之間的對應(yīng)關(guān)系。通過微調(diào)模型,我們希望模型能夠根據(jù)評論的文本內(nèi)容自動預(yù)測其星級評分(1-5星)。微調(diào)后的模型能夠在新的評論輸入時自動給出星級評定。

 2. 裝載數(shù)據(jù)集

本次微調(diào)會使用Yelp 數(shù)據(jù)集,它是一個公開的評論數(shù)據(jù)集,包含了大量用戶對商家的評價和評分,廣泛應(yīng)用于自然語言處理任務(wù)。數(shù)據(jù)集的特點包括:

  • 文本多樣性:包含多種不同類型的評論,覆蓋不同語言風(fēng)格、評論長度。
  • 結(jié)構(gòu)化評分:每條評論都帶有一個結(jié)構(gòu)化的星級評分(1到5星),適合分類問題。
  • 數(shù)據(jù)量龐大:原始數(shù)據(jù)集包含數(shù)條評論,適用于深度學(xué)習(xí)模型的訓(xùn)練。

3. 分詞器處理文本

對評論文本進行分詞,將每條評論分解為詞或詞組。這里我們使用 BERT 自帶的分詞器(Tokenizer),它能夠?qū)⑽谋巨D(zhuǎn)化為模型所需的輸入格式(如 token IDs、attention masks 等)。通過分詞,我們能夠?qū)⒚總€詞或詞組轉(zhuǎn)化為模型理解的向量表示,并保留文本的結(jié)構(gòu)信息。

 4. 生成小數(shù)據(jù)集

為了加快實驗和測試過程,我們從原始的 Yelp 數(shù)據(jù)集中提取一個小樣本數(shù)據(jù)集。小數(shù)據(jù)集可以幫助我們快速迭代模型的訓(xùn)練、調(diào)參和驗證。經(jīng)過分詞器處理后,我們可以將這些小樣本輸入到模型中進行訓(xùn)練和評估。

5. 選擇微調(diào)模型

我們將使用預(yù)訓(xùn)練的 BERT 模型,并根據(jù) Yelp 數(shù)據(jù)集的需求調(diào)整模型的輸出層。BERT 本身經(jīng)過大規(guī)模語料庫的預(yù)訓(xùn)練,具備強大的語言理解能力,通過微調(diào),可以將其適應(yīng)特定的分類任務(wù)。

6. 設(shè)置超參數(shù)

超參數(shù)包括學(xué)習(xí)率、訓(xùn)練輪次、batch size 等。合理的超參數(shù)設(shè)置能夠確保模型的有效訓(xùn)練,避免過擬合或欠擬合問題。在訓(xùn)練過程中,我們將定期監(jiān)控模型的性能,確保其學(xué)習(xí)到評論文本中的有效信息。

7. 訓(xùn)練評估

在訓(xùn)練階段,我們會定期對模型進行評估。這通常在每個訓(xùn)練輪次結(jié)束后進行,通過驗證集上的數(shù)據(jù)來評估模型的性能。通過這樣的方式,能夠?qū)崟r了解模型的學(xué)習(xí)效果,并根據(jù)評估結(jié)果適時調(diào)整,避免過擬合等問題。

8. 計算準(zhǔn)確性計算

通過計算模型的預(yù)測準(zhǔn)確性來衡量其表現(xiàn)。在每次評估時,模型會對驗證集中的數(shù)據(jù)進行預(yù)測,然后將這些預(yù)測結(jié)果與實際標(biāo)簽進行比較。通過計算準(zhǔn)確性,能夠判斷模型在該分類任務(wù)中的成功率,即模型在多大程度上能夠正確預(yù)測評論的星級。

9. 執(zhí)行訓(xùn)練

開始對模型進行微調(diào)訓(xùn)練。

10.保存模型

在訓(xùn)練和驗證完成后,將微調(diào)后的模型進行保存。保存的模型可以用于后續(xù)的預(yù)測和推理任務(wù)。通過調(diào)用保存的模型,我們可以在給定新評論的情況下快速獲得預(yù)測的星級評分。

11. 驗證結(jié)果

將設(shè)計對比實驗:讓未經(jīng)過微調(diào)的模型和經(jīng)過微調(diào)的模型分別對 Yelp 數(shù)據(jù)集中的評論進行星級預(yù)測,查看評分結(jié)果的差異。這樣可以展示微調(diào)后的模型是否能夠更好地理解評論文本與評分之間的關(guān)系,并給出更加準(zhǔn)確的預(yù)測。

通過這些步驟,我們將詳細(xì)探討如何使用 Hugging Face 的工具對 BERT 模型進行微調(diào),并結(jié)合 Yelp 數(shù)據(jù)集,逐步完成從數(shù)據(jù)預(yù)處理、模型訓(xùn)練到結(jié)果驗證的整個流程。

實現(xiàn)微調(diào)

介紹完整個微調(diào)思路之后,我們會通過Hugging Face的Transformers 模型框架編寫微調(diào)的代碼。

由于微調(diào)模型需要算力資源,一般而言都需要多張高顯存的顯卡支持。通過上面的微調(diào)思路大家可以知道,為了演示微調(diào)過程,我們將數(shù)據(jù)集進行了縮減的操作,利用更小的數(shù)據(jù)集來完成微調(diào)。在實際應(yīng)用場景如果需要微調(diào)更大的數(shù)據(jù)集就需要多張高階顯卡。如下圖所示,我們租用AutoDL上的虛擬服務(wù)器,使用3080ti顯卡進行微調(diào),實際測試的效果還不錯,在小數(shù)據(jù)微調(diào)的情況下10-20分鐘可以完成。

大模型微調(diào):Hugging Face Transformers全流程實戰(zhàn)-AI.x社區(qū)

接著,需要安裝必要的組件庫,如下:

!pip install transformers datasets evaluate accelerate scikit-learn

上述庫支持自然語言處理任務(wù),尤其是涉及到模型微調(diào)、評估和數(shù)據(jù)處理的任務(wù)。下面是對每個庫的簡要解釋:

1. transformers

這個庫是由 Hugging Face 提供的,它包含了許多預(yù)訓(xùn)練的自然語言處理模型,支持包括文本分類、生成、翻譯等任務(wù)。

2. datasets

該庫也是由 Hugging Face 提供的,專門用于處理和管理各種機器學(xué)習(xí)數(shù)據(jù)集。它可以加載、預(yù)處理和操作不同格式的數(shù)據(jù)集,支持直接加載許多公開數(shù)據(jù)集如 Yelp、IMDB 等。

3. evaluate

用于評估模型的性能。它提供了各種常用的評估指標(biāo)(如準(zhǔn)確率、精確率、召回率等),方便在模型訓(xùn)練和驗證時計算這些指標(biāo),幫助衡量模型的表現(xiàn)。

4. accelerate

用于加速模型訓(xùn)練的庫,支持分布式訓(xùn)練和加速設(shè)備的無縫切換,比如在CPU和GPU之間轉(zhuǎn)換,或者使用多個GPU進行訓(xùn)練。

5. scikit-learn

非常流行的機器學(xué)習(xí)庫,提供了各種統(tǒng)計學(xué)習(xí)工具、數(shù)據(jù)預(yù)處理和模型評估方法。在自然語言處理項目中,它常用于進行數(shù)據(jù)處理和分類算法的基礎(chǔ)操作,如分詞、向量化、模型評估等。

裝載數(shù)據(jù)集

這里我們使用了Yelp數(shù)據(jù)集,它是從 2015 年的 Yelp 數(shù)據(jù)集挑戰(zhàn)賽中提取的,包含大量的用戶評論,主要用于情感分類和文本分類任務(wù)。通過分析這些評論文本,可以預(yù)測用戶的情感傾向,也就是評分的星級。數(shù)據(jù)集中的評論主要以英文撰寫,每條評論包含兩個核心元素:評論的文本內(nèi)容和對應(yīng)的評分標(biāo)簽。評論內(nèi)容中涉及的文本經(jīng)過特殊處理,雙引號和換行符都進行了轉(zhuǎn)義。評分標(biāo)簽表示評論的星級,范圍從 1 到 5 星不等。整個數(shù)據(jù)集被隨機劃分為訓(xùn)練集和測試集,每個星級類別各包含 130,000 條訓(xùn)練樣本和 10,000 條測試樣本,總共包含 650,000 條訓(xùn)練數(shù)據(jù)和 50,000 條測試數(shù)據(jù)。

數(shù)據(jù)集的格式大致如下:

{
    'label': 0,
    'text': 'I got \'new\' tires from them and within two weeks got a flat...'
}

接著通過如下代碼加載數(shù)據(jù)。

from datasets import load_dataset
dataset = load_dataset("yelp_review_full")
dataset["train"][100]

通過代碼可以看出,load_dataset 函數(shù)可以直接加載 yelp_review_full 數(shù)據(jù)集,它來自 Hugging Face 的 datasets 庫。這個庫內(nèi)置了許多公開可用的數(shù)據(jù)集,Yelp Review Full 就是其中之一。說白了Hugging Face 數(shù)據(jù)庫包含了大量的預(yù)先注冊的數(shù)據(jù)集,并且通過統(tǒng)一的接口 load_dataset 來訪問,需要什么數(shù)據(jù)你告訴Hugging Face 名字就可以了,不用指明數(shù)據(jù)的文件地址。

當(dāng)使用 load_dataset("yelp_review_full") 時,函數(shù)會通過數(shù)據(jù)集名稱自動從 Hugging Face 的數(shù)據(jù)集庫中找到對應(yīng)的資源,并加載相應(yīng)的數(shù)據(jù)集。這意味著你不需要手動下載或準(zhǔn)備數(shù)據(jù)集,Hugging Face 已經(jīng)在其平臺上托管了這個數(shù)據(jù)集,并定義了它的結(jié)構(gòu)和格式。因此,load_dataset 能夠通過提供的名稱直接訪問并加載。

在加載完畢數(shù)據(jù)以后,可以通過dataset["train"][100],查看Yelp Review 數(shù)據(jù)集中提取第 100 條訓(xùn)練數(shù)據(jù),確認(rèn)數(shù)據(jù)已經(jīng)加載完畢。

分詞器文本處理

分詞器的工作是將我們看得懂的語言文字轉(zhuǎn)化為模型能理解的數(shù)字。無論是機器學(xué)習(xí)模型還是深度學(xué)習(xí)模型,它們都只能處理數(shù)字,而不是直接處理文本。我們需要一個方法來把文本“翻譯”成模型能夠理解的形式。分詞器正是負(fù)責(zé)這一“翻譯”工作的工具。通過將句子分解成“詞”或“字符”,然后給每個詞或字符分配一個數(shù)字(通常叫做輸入ID),模型就可以開始處理這些數(shù)字了。

如下圖所示,比如,“我喜歡蘋果”這句話,分詞器就會把“我”翻譯成1,“喜歡”翻譯成2,“蘋果”翻譯成3。而這些數(shù)字是根據(jù)詞匯表(vocabulary)中的子詞來索引的,可以理解為在模型內(nèi)部有一個很大的詞匯表,詞匯表中維護每個詞對應(yīng)的ID,你輸入ID模型就知道你要表達(dá)什么詞(類似身份證與人之間的關(guān)系)。這個詞匯表可以看作是模型用來理解語言的“字典”,其中包含了大量常見的詞和子詞(subwords)。每個子詞在詞匯表中都有一個對應(yīng)的索引 ID,當(dāng)我們輸入一段文本時,分詞器會將它切分成多個子詞,并查找每個子詞在詞匯表中的索引。

大模型微調(diào):Hugging Face Transformers全流程實戰(zhàn)-AI.x社區(qū)

為什么需要詞匯表?因為語言的多樣性非常大,而單詞的數(shù)量是無限的。直接給每個完整的單詞一個唯一的 ID 會導(dǎo)致詞匯表非常龐大,這不僅會增加模型的復(fù)雜性,還容易出現(xiàn)很多未知的詞(也就是詞匯表中沒有的詞)。使用子詞來代替整個單詞能夠減少詞匯表的大小,同時確保即便遇到生僻詞也能通過已知的子詞來表達(dá)。例如,英文"unhappiness" 可以被拆分為 "un-" 、"happi-" 和 “ness”三個子詞,即便模型沒有見過完整的“unhappiness”這個詞,它仍然可以通過上述三個子詞來理解。

如下圖所示,簡單理解,分詞器的工作就是講輸入的文字參照詞匯表,將其轉(zhuǎn)化為子詞ID的形式,然后輸入到大模型中進行處理。

大模型微調(diào):Hugging Face Transformers全流程實戰(zhàn)-AI.x社區(qū)

接著來看代碼:

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-cased")
def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True)
tokenized_datasets = dataset.map(tokenize_function, batched=True)

從 Hugging Face 預(yù)訓(xùn)練模型庫中加載了google-bert/bert-base-cased版本分詞器。

def tokenize_function(examples)用于處理數(shù)據(jù)集中的每一個數(shù)據(jù)點。

tokenizer(examples["text"], padding="max_length", truncation=True):這里使用分詞器將輸入的文本數(shù)據(jù)進行分詞。分詞器會將文本轉(zhuǎn)換為標(biāo)記(tokens),并將其轉(zhuǎn)換為適合模型輸入的數(shù)字化形式。padding="max_length":表示對文本進行填充,使所有文本的長度相同,達(dá)到預(yù)定義的最大長度。truncation=True:如果文本長度超過最大長度,自動截斷多余部分。

tokenized_datasets = dataset.map(tokenize_function, batched=True):使用 map 函數(shù),將定義的分詞函數(shù)應(yīng)用到數(shù)據(jù)集中。通過 batched=True,它批量處理數(shù)據(jù),加快處理速度。最終得到的是一個包含經(jīng)過分詞和預(yù)處理的文本數(shù)據(jù)集,格式化后可直接輸入模型。

生成小數(shù)據(jù)集

在處理大型數(shù)據(jù)集時,訓(xùn)練模型和進行驗證會耗費大量時間和計算資源。因此,我們通常會創(chuàng)建一個小數(shù)據(jù)集來進行快速的實驗和調(diào)試。

加入如下代碼:

small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000))

tokenized_datasets["train"] 和 tokenized_datasets["test"]: 分別從已分詞的數(shù)據(jù)集中獲取訓(xùn)練集和測試集。

  • shuffle(seed=42): 將數(shù)據(jù)集隨機打亂,seed=42 確保打亂的順序是可重復(fù)的,即每次執(zhí)行代碼時得到相同的隨機順序。
  • select(range(1000)): 選擇前 1000 條樣本,生成一個小型的數(shù)據(jù)集,限制訓(xùn)練和測試的規(guī)模為 1000 條數(shù)據(jù),適用于快速測試。

指定微調(diào)模型

微調(diào)數(shù)據(jù)集是基于一個預(yù)訓(xùn)練模型展開的,這里選擇bert-base-cased 模型,用于一個有 5 個分類標(biāo)簽(1-5星的評價)的序列分類任務(wù)。

代碼如下:

from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained("google-bert/bert-base-cased", num_labels=5)

AutoModelForSequenceClassification:是 Hugging Face 的 transformers 庫中提供的模型,用于文本分類任務(wù)。它基于預(yù)訓(xùn)練的 Transformer 模型,并添加一個分類頭(線性層)來處理分類任務(wù)。通過這個類中的from_pretrained("google-bert/bert-base-cased")方法加載預(yù)訓(xùn)練模型。

num_labels=5:定義了分類任務(wù)的標(biāo)簽數(shù)為 5,表示我們要對文本進行 5 類分類任務(wù)。

設(shè)置超參數(shù)

設(shè)置超參數(shù)幫助配置模型訓(xùn)練時的各種參數(shù),比如訓(xùn)練輸出的目錄、批量大小、學(xué)習(xí)率、是否使用 GPU 等。

如下代碼用于設(shè)置訓(xùn)練模型時的超參數(shù),使用 Hugging Face transformers 庫中的 TrainingArguments 類。

from transformers import TrainingArguments
training_args = TrainingArguments(output_dir="test_trainer")

為了簡化演示過程這里只配置了output_dir="test_trainer"作為模型輸出的路徑。在訓(xùn)練過程中,模型的檢查點(checkpoints)、日志文件、以及最終模型都會被保存在這個目錄下。

此外,TrainingArguments 提供了許多其他參數(shù),你可以根據(jù)具體的訓(xùn)練需求來設(shè)置,比如:

  • per_device_train_batch_size:每個設(shè)備上的訓(xùn)練批次大小。
  • learning_rate:設(shè)置學(xué)習(xí)率。
  • num_train_epochs:訓(xùn)練的迭代次數(shù)。
  • evaluation_strategy:定義何時進行評估(例如 "steps", "epoch" 等)。
  • save_steps:在訓(xùn)練過程中保存模型的頻率。
  • logging_dir:用于存放 TensorBoard 日志文件的目錄。

訓(xùn)練評估與計算預(yù)測的準(zhǔn)確性

在模型的訓(xùn)練和評估過程中,特別是在分類任務(wù)中,衡量模型性能的一個關(guān)鍵指標(biāo)就是準(zhǔn)確性。訓(xùn)練好的模型可以在驗證集上進行評估,查看模型在實際數(shù)據(jù)上的表現(xiàn),以此來衡量其分類能力。我們會創(chuàng)建一個compute_metrics 函數(shù),它用來計算預(yù)測結(jié)果和實際標(biāo)簽的差異來評估模型的準(zhǔn)確性。同時會使用evaluate 庫的 accuracy 指標(biāo)得到模型在驗證集上的表現(xiàn)。

代碼如下:

import numpy as np
import evaluate
metric = evaluate.load("accuracy")
def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    return metric.compute(predictions=predictions, references=labels)

metric = evaluate.load("accuracy")加載了 Hugging Face 庫中預(yù)定義的“準(zhǔn)確率”評估指標(biāo)。 compute_metrics(eval_pred) 函數(shù)是為訓(xùn)練/驗證流程提供的評估函數(shù),傳入的參數(shù) eval_pred 包含了兩個部分:logits 和 labels。

logits:模型輸出的原始預(yù)測結(jié)果,通常是未經(jīng)過激活函數(shù)的值(在分類任務(wù)中通常是未經(jīng) softmax 的分?jǐn)?shù))。

為什么突然跳出一個logits來了?這里需要稍微解釋一下,在深度學(xué)習(xí)的分類模型中,模型在最后一層輸出的是各個類別的分?jǐn)?shù)(logits)。這些分?jǐn)?shù)用來表示模型對各個類別的預(yù)測概率。在很多情況下,模型會直接輸出 logits,而不是最終的類別,因為 logits 還可以進一步處理(比如通過 softmax 轉(zhuǎn)換為概率)。

大家還記得嗎?在最開始處理文本的時候,我們需要針對輸入文本進行分詞(tokenization),接著每個詞會被映射成嵌入(embedding)。嵌入作為輸入經(jīng)過模型的層層處理,最后在輸出層產(chǎn)生 logits,用于預(yù)測文本的分類結(jié)果。因此,分詞是處理輸入數(shù)據(jù)的第一步,而 logits 是最終的輸出分?jǐn)?shù),用來確定分類的結(jié)果。

來舉個例子說說logits方便大家理解,假設(shè)我們有一個分類任務(wù),模型需要把一句話分成 5 個類別之一(比如情感分類:0=負(fù)面, 1=中性, 2=正面, 3=疑問, 4=驚訝)。在模型處理輸入之后,它會輸出一個包含 5 個數(shù)值的向量(logits),表示模型對每個類別的信心。

示例:

輸入句子:"I love this product!"

假設(shè)模型的輸出 logits 是:

logits = [2.5, -1.3, 5.2, 0.8, -0.5]

這個向量表示模型對每個類別的信心。這里的 5.2 是 logits 中的最大值,表示模型認(rèn)為這個句子最可能屬于第 2 類(“正面”情感),盡管它對每個類別都有一定的信心值。

所以,這里的logits就是在對預(yù)測結(jié)果進行“打分”,哪個分類上分?jǐn)?shù)越高,模型就會認(rèn)為這個文字描述屬于哪類。

而labels表示的是實際標(biāo)簽,它用于與模型的預(yù)測結(jié)果對比。

logits, labels = eval_pred:將 eval_pred 拆分為 logits 和 labels。

predictions = np.argmax(logits, axis=-1):使用 np.argmax() 函數(shù)從 logits 中找到最大值的索引,代表模型的最終預(yù)測類別。axis=-1 表示沿最后一個維度進行操作,對于每個輸入,輸出模型認(rèn)為最可能的類別。

metric.compute(predictions=predictions, references=labels):計算模型預(yù)測的準(zhǔn)確性。predictions 是模型的預(yù)測值,references 是真實標(biāo)簽。這個函數(shù)返回一個包含準(zhǔn)確性(accuracy)指標(biāo)的字典。

創(chuàng)建Trainer對象執(zhí)行微調(diào)任務(wù)

微調(diào)前的基本工作已經(jīng)完成了, 接下來我們需要創(chuàng)建一個Trainer類,用于簡化訓(xùn)練和評估過程,該類包含了模型、訓(xùn)練參數(shù)、訓(xùn)練和驗證數(shù)據(jù)集,以及評估指標(biāo)計算方法。然后,執(zhí)行trainer.train() 用于微調(diào)訓(xùn)練,模型的權(quán)重會根據(jù)訓(xùn)練數(shù)據(jù)逐步優(yōu)化。最后,trainer.save_model() 會將訓(xùn)練好的模型保存,方便后續(xù)使用。代碼如下:

trainer = Trainer(
    model=model,  # 定義的模型( BERT 分類模型)
    args=training_args,  # 訓(xùn)練的參數(shù),如學(xué)習(xí)率、批次大小、訓(xùn)練周期等
    train_dataset=small_train_dataset,  # 用于訓(xùn)練的小數(shù)據(jù)集
    eval_dataset=small_eval_dataset,  # 用于評估的小數(shù)據(jù)集
    compute_metrics=compute_metrics,  # 之前定義的,驗證的準(zhǔn)確性等指標(biāo)的函數(shù)
)
trainer.train() # 開始訓(xùn)練模型
trainer.save_model() # 保存訓(xùn)練后的模型

執(zhí)行上述代碼,得到如下運行截圖:

大模型微調(diào):Hugging Face Transformers全流程實戰(zhàn)-AI.x社區(qū)

從圖中可以看出,驗證集上的準(zhǔn)確性(Accuracy)分別為:

  • 第一輪:57.3%(0.573000)
  • 第二輪:58.0%(0.580000)
  • 第三輪:59.4%(0.594000)

盡管第三輪的驗證損失增加了,準(zhǔn)確率卻依然提升了一點。這可能表明模型在某些類別上的預(yù)測更準(zhǔn)確,但整體的損失仍然較大,表明模型存在過擬合或不平衡的表現(xiàn)。

同時得到如下運行信息:

TrainOutput(global_step=375, training_loss=0.49261214192708336, metrics={'train_runtime': 127.2273, 'train_samples_per_second': 23.58, 'train_steps_per_second': 2.947, 'total_flos': 789354427392000.0, 'train_loss': 0.49261214192708336, 'epoch': 3.0})

從信息可以看出,模型微調(diào)訓(xùn)練共進行了 3 個 Epoch,執(zhí)行了 375 個訓(xùn)練步數(shù),總運行時間為 127 秒。在訓(xùn)練過程中,模型每秒能夠處理約 23.58 個樣本,每秒執(zhí)行 2.95 個訓(xùn)練步。最終,模型的平均訓(xùn)練損失為 0.49,表明模型在訓(xùn)練數(shù)據(jù)上的表現(xiàn)較為理想。此外,訓(xùn)練的總浮點運算量(FLOPs)為 789,354,427,392,000,展示了訓(xùn)練過程中涉及的大量計算量。

驗證微調(diào)

前面我們通過獲取數(shù)據(jù)集針對BERT模型進行微調(diào),執(zhí)行微調(diào)命令之后完成了微調(diào)的過程,并且通過trainer.save_model()語句將微調(diào)之后的模型保存到本地。接下來,通過對比微調(diào)前后模型對評論信息的星級反饋,來查看微調(diào)之后模型的能力是否提升。

先調(diào)用測試之前的模型輸入評論內(nèi)容,看模型對評論給出什么星級的評定。

如下圖所示,測試的評論是2 star(2星的星級評定)。

大模型微調(diào):Hugging Face Transformers全流程實戰(zhàn)-AI.x社區(qū)

執(zhí)行如下代碼:

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
import numpy as np
# Yelp review 示例
input_text = "My first time going to Barb's Country Junction and I really wanted to like this place, I really did...however,……."
# 加載預(yù)訓(xùn)練模型和 tokenizer
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-cased")
model_pretrained = AutoModelForSequenceClassification.from_pretrained("google-bert/bert-base-cased", num_labels=5)
# 標(biāo)記化輸入文本
inputs = tokenizer(input_text, padding=True, truncation=True, return_tensors="pt")
# 使用預(yù)訓(xùn)練模型進行預(yù)測(沒有經(jīng)過微調(diào))
with torch.no_grad():
    outputs_pretrained = model_pretrained(**inputs)
# 獲取未微調(diào)模型的預(yù)測標(biāo)簽
predicted_label_pretrained = np.argmax(outputs_pretrained.logits, axis=-1).item()
print(f"Prediction before fine-tuning (without knowledge of Yelp reviews): {predicted_label_pretrained}")

得到如下結(jié)果。

Prediction before fine-tuning (without knowledge of Yelp reviews): 3

很明顯,從結(jié)果上看模型預(yù)測的星級為“3”,與數(shù)據(jù)集標(biāo)注的“2”存在差異。

接著利用微調(diào)之后模型進行推理,代碼如下:

model = AutoModelForSequenceClassification.from_pretrained("test_trainer")
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-cased")
# 輸入文本
input_text = "My first time going to Barb's Country Junction and I really wanted to like this place, I really did...however, ……"
# 標(biāo)記化輸入文本
inputs = tokenizer(input_text, padding=True, truncation=True, return_tensors="pt")
# 獲取模型預(yù)測
with torch.no_grad():  # 關(guān)閉梯度計算
    outputs = model(**inputs)
# 獲取預(yù)測標(biāo)簽
predicted_label = np.argmax(outputs.logits, axis=-1).item()
# 輸出結(jié)果
print(f"Predicted label: {predicted_label}")

上述代碼通過model = AutoModelForSequenceClassification.from_pretrained("test_trainer"),獲取微調(diào)之后test_trainer目錄下的模型進行推理。 執(zhí)行結(jié)果如下:

Predicted label: 2

與預(yù)期的結(jié)果相同,說明微調(diào)之后的模型能夠勝任評論星級分類的工作。

總結(jié)

大模型微調(diào)技術(shù)為將預(yù)訓(xùn)練模型應(yīng)用于垂直領(lǐng)域提供了有效途徑。通過微調(diào),我們可以利用預(yù)訓(xùn)練模型的知識,并結(jié)合特定領(lǐng)域的任務(wù)需求,打造定制化解決方案。本文以 Yelp 數(shù)據(jù)集為例,演示了如何使用 Hugging Face Transformers 框架對 BERT 模型進行微調(diào),實現(xiàn)評論星級分類任務(wù)。文檔涵蓋了微調(diào)的背景、主流手段、架構(gòu)和工具,并深入講解了微調(diào)的思路和實踐步驟,包括數(shù)據(jù)預(yù)處理、模型選擇、超參數(shù)設(shè)置、訓(xùn)練評估和結(jié)果驗證等。相信通過本文的學(xué)習(xí),讀者能夠更好地理解大模型微調(diào)技術(shù),并將其應(yīng)用于實際項目中。

作者介紹

崔皓,51CTO社區(qū)編輯,資深架構(gòu)師,擁有18年的軟件開發(fā)和架構(gòu)經(jīng)驗,10年分布式架構(gòu)經(jīng)驗。

?著作權(quán)歸作者所有,如需轉(zhuǎn)載,請注明出處,否則將追究法律責(zé)任
已于2024-9-26 10:43:01修改
收藏
回復(fù)
舉報
回復(fù)
相關(guān)推薦