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

《Python機(jī)器學(xué)習(xí)》作者科普長(zhǎng)文:從頭構(gòu)建類GPT文本分類器,代碼開(kāi)源

人工智能 新聞
文章展示了如何將預(yù)訓(xùn)練的大型語(yǔ)言模型(LLM)轉(zhuǎn)化為強(qiáng)大的文本分類器。

近日,機(jī)器學(xué)習(xí)研究員、暢銷書《Python 機(jī)器學(xué)習(xí)》作者 Sebastian Raschka 又分享了一篇長(zhǎng)文,主題為《從頭開(kāi)始構(gòu)建一個(gè) GPT 風(fēng)格的 LLM 分類器》。

文章展示了如何將預(yù)訓(xùn)練的大型語(yǔ)言模型(LLM)轉(zhuǎn)化為強(qiáng)大的文本分類器。機(jī)器之心對(duì)文章內(nèi)容進(jìn)行了不改變?cè)獾木幾g、整理:

為什么要關(guān)注分類呢?首先,針對(duì)分類任務(wù),對(duì)預(yù)訓(xùn)練模型進(jìn)行微調(diào)是一個(gè)簡(jiǎn)單有效的 LLM 知識(shí)入門方式。其次,文本分類有許多商業(yè)應(yīng)用場(chǎng)景,比如:垃圾郵件檢測(cè)、情感分析、客戶反饋分類、主題分類等等。

閱讀完本文,你將找到以下 7 個(gè)問(wèn)題的答案:

1. 需要訓(xùn)練所有層嗎?

2. 為什么微調(diào)最后一個(gè) token,而不是第一個(gè) token?

3. BERT 與 GPT 在性能上有何比較?

4. 應(yīng)該禁用因果掩碼嗎?

5. 擴(kuò)大模型規(guī)模會(huì)有什么影響?

6. LoRA 可以帶來(lái)什么改進(jìn)?

7. Padding 還是不 Padding?

完整代碼可以從 GitHub 找到:https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb

Different categories of finetuning

微調(diào)的不同種類

指令微調(diào)和分類微調(diào)是最常見(jiàn)的語(yǔ)言模型微調(diào)方法。指令微調(diào)是用特定任務(wù)訓(xùn)練模型,提高它理解和執(zhí)行自然語(yǔ)言提示中所描述任務(wù)的能力,如下圖 1 所示。

圖片

圖 1:指令微調(diào)的兩種場(chǎng)景。上方:模型的任務(wù)是判斷文本是否為垃圾郵件;下方:模型的任務(wù)是將英文句子翻譯成德語(yǔ)。

在分類微調(diào)中,模型被訓(xùn)練用于識(shí)別特定的類別標(biāo)簽,比如「垃圾郵件」和「非垃圾郵件」。分類任務(wù)還包括從圖像中識(shí)別不同的植物、給新聞按體育、政治或科技等主題分類,從醫(yī)學(xué)影像中區(qū)分良性和惡性腫瘤等等。

不過(guò)經(jīng)過(guò)分類微調(diào)的模型只能判斷類別,不能對(duì)輸入的文本作出其他判斷。

圖 2:一個(gè)使用 LLM 進(jìn)行垃圾郵件分類的示例。針對(duì)垃圾郵件分類微調(diào)的模型在輸入時(shí)不需要額外的指令,然而,與指令微調(diào)模型相比,它的回答只能是「垃圾郵件」和「非垃圾郵件」。

指令微調(diào)的模型通常能夠執(zhí)行更廣泛的任務(wù)。我們可以將分類微調(diào)的模型視為是高度專業(yè)化的模型,一般來(lái)說(shuō),開(kāi)發(fā)一個(gè)專用模型比開(kāi)發(fā)一個(gè)在各種任務(wù)上表現(xiàn)良好的通用模型更容易。

使用預(yù)訓(xùn)練權(quán)重初始化模型

下圖中展示了將通用預(yù)訓(xùn)練 LLM 轉(zhuǎn)變?yōu)閷iT用于分類任務(wù)的 LLM 需要做的修改:

圖片圖 3:在此跳過(guò)步驟 1-5,直接進(jìn)入步驟 6(將在下一節(jié)開(kāi)始)。

在做修改之前,讓我們先簡(jiǎn)單了解一下正在使用的預(yù)訓(xùn)練 LLM。為簡(jiǎn)便起見(jiàn),假設(shè)我們?cè)O(shè)置了如下代碼來(lái)加載該模型:

model = GPTModel (BASE_CONFIG)

load_weights_into_gpt (model, params)

model.eval ()

在將模型權(quán)重加載到 GPT 后,使用下列文本生成的函數(shù)庫(kù),確保模型生成連貫的文本:

from chapter04 import generate_text_simple

from chapter05 import text_to_token_ids, token_ids_to_text

text_1 = "Every effort moves you"

token_ids = generate_text_simple (

    model=model,

    idx=text_to_token_ids (text_1, tokenizer),

    max_new_tokens=15,

    context_size=BASE_CONFIG ["context_length"]

)

print (token_ids_to_text (token_ids, tokenizer))

根據(jù)以下輸出,我們可以看到模型生成了連貫的文本,這表明模型權(quán)重已正確加載:

Every effort moves you forward.

The first step is to understand the importance of your work

讓我們先看看模型是否可以通過(guò)指令微調(diào)完成垃圾郵件的分類:

text_2 = (

    "Is the following text'spam'? Answer with 'yes' or 'no':"

    "'You are a winner you have been specially"

    "selected to receive $1000 cash or a $2000 award.'"

)

token_ids = generate_text_simple (

    model=model,

    idx=text_to_token_ids (text_2, tokenizer),

    max_new_tokens=23,

    context_size=BASE_CONFIG ["context_length"]

)

print (token_ids_to_text (token_ids, tokenizer))

模型的輸出如下所示:

Is the following text'spam'? Answer with 'yes' or 'no': 'You are a winner you have been specially selected to receive $1000 cash or a $2000 award.'

The following text'spam'? Answer with 'yes' or 'no': 'You are a winner

可以明顯看出模型在準(zhǔn)確遵循指令方面遇到了一些挑戰(zhàn)。這是可以預(yù)見(jiàn)的,因?yàn)樗鼉H經(jīng)過(guò)了預(yù)訓(xùn)練,缺乏指令微調(diào)。

加入分類頭

我們將原始輸出層(這層的功能是將模型內(nèi)部生成的隱藏表示轉(zhuǎn)換為一個(gè)包含 50,257 個(gè) tokens 的詞表)替換為一個(gè)較小的輸出層,該層映射到兩個(gè)類別:0(非垃圾郵件)和 1(垃圾郵件),如下圖 4 所示。

圖片

圖 4:此圖展示了如何通過(guò)改變架構(gòu)將 GPT 模型適配為垃圾郵件分類。最初,模型的線性輸出層將 768 個(gè)隱藏單元映射到一個(gè)包含 50,257 個(gè) tokens 的詞匯表。為了進(jìn)行垃圾郵件檢測(cè),這一層被替換為一個(gè)新的輸出層,該層將相同的 768 個(gè)隱藏單元映射到兩個(gè)類別,分別表示「垃圾郵件」和「非垃圾郵件」。

輸出層節(jié)點(diǎn)

從技術(shù)上講,因?yàn)檫@是一個(gè)二元分類任務(wù),可以只用一個(gè)輸出節(jié)點(diǎn)。然而,這將需要修改損失函數(shù)。因此,我們選擇一種更通用的方法,匹配輸出節(jié)點(diǎn)與分類的數(shù)量。例如,對(duì)于一個(gè)分三類的問(wèn)題,如將新聞文章分類為「科技」、「體育」或「政治」,使用三個(gè)輸出節(jié)點(diǎn),依此類推。

在嘗試進(jìn)行圖 4 中所示的修改之前,先通過(guò) print (model) 輸出模型架構(gòu):

GPTModel (

  (tok_emb): Embedding (50257, 768)

  (pos_emb): Embedding (1024, 768)

  (drop_emb): Dropout (p=0.0, inplace=False)

  (trf_blocks): Sequential (

...

    (11): TransformerBlock (

      (att): MultiHeadAttention (

        (W_query): Linear (in_features=768, out_features=768, bias=True)

        (W_key): Linear (in_features=768, out_features=768, bias=True)

        (W_value): Linear (in_features=768, out_features=768, bias=True)

        (out_proj): Linear (in_features=768, out_features=768, bias=True)

        (dropout): Dropout (p=0.0, inplace=False)

      )

      (ff): FeedForward (

        (layers): Sequential (

          (0): Linear (in_features=768, out_features=3072, bias=True)

          (1): GELU ()

          (2): Linear (in_features=3072, out_features=768, bias=True)

        )

      )

      (norm1): LayerNorm ()

      (norm2): LayerNorm ()

      (drop_resid): Dropout (p=0.0, inplace=False)

    )

  )

  (final_norm): LayerNorm ()

  (out_head): Linear (in_features=768, out_features=50257, bias=False)

)

如上所示,GPTModel 由嵌入層和 12 個(gè)相同的 transformer 塊組成,為簡(jiǎn)潔起見(jiàn),僅顯示最后一個(gè)塊,然后是最終的 LayerNorm 和輸出層 out_head。

接下來(lái),我們將 out_head 替換為一個(gè)新的輸出層,如圖 4 所示,我們將對(duì)這一層進(jìn)行微調(diào)。

選擇微調(diào)特定層與微調(diào)所有層

我們不必對(duì)模型每一層進(jìn)行微調(diào),因?yàn)樯窠?jīng)網(wǎng)絡(luò)的較低層捕捉到的基本的語(yǔ)言結(jié)構(gòu)和語(yǔ)義是通用的,可以在許多不同的任務(wù)和數(shù)據(jù)集中發(fā)揮作用。

因此,我們僅微調(diào)最后幾層(靠近輸出的層)就夠了,這些層更具體于細(xì)微的語(yǔ)言模式和任務(wù)特征。這種方法在計(jì)算上也將更加高效。

為了準(zhǔn)備進(jìn)行分類微調(diào),首先我們凍結(jié)模型,即將所有層設(shè)置為不可訓(xùn)練:

for param in model.parameters ():

    param.requires_grad = False

然后,如圖 4 所示,我們修改輸出層 model.out_head :

torch.manual_seed (123)

num_classes = 2

model.out_head = torch.nn.Linear (

    in_features=BASE_CONFIG ["emb_dim"],

    out_features=num_classes

)

注意,在上述代碼中,我們使用了 BASE_CONFIG ["emb_dim"],它的值在 “gpt2-small(124M)” 模型中為 768。這樣做的目的是為了讓后續(xù)的代碼更加通用,相同的代碼也能處理其他型號(hào)的 GPT-2 模型。

新的 model.out_head 輸出層的 requires_grad 屬性默認(rèn)設(shè)置為 True,這意味著這是模型中唯一會(huì)在訓(xùn)練期間更新的層。

從技術(shù)上講,只訓(xùn)練剛剛添加的輸出層就足夠了。然而,我在實(shí)驗(yàn)中發(fā)現(xiàn),微調(diào)額外的層,可以顯著提高微調(diào)模型的預(yù)測(cè)性能。

此外,我們將最后一個(gè) transformer 塊以及連接該塊與輸出層的 LayerNorm 模塊設(shè)置為可訓(xùn)練,如圖 5 所示。

圖片

圖 5:用我的步驟開(kāi)發(fā)的 GPT 模型包含 12 個(gè)重復(fù)的 transformer 塊。除了輸出層,我們將最后的 LayerNorm 和最后一個(gè) transformer 塊設(shè)置為可訓(xùn)練,而其余 11 個(gè) transformer 塊和嵌入層保持為不可訓(xùn)練。

為了做到這點(diǎn),我們將它們各自的 requires_grad 設(shè)置為 True:

for param in model.trf_blocks [-1].parameters ():

    param.requires_grad = True

for param in model.final_norm.parameters ():

    param.requires_grad = True

盡管我們添加了一個(gè)新的輸出層,并將某些層設(shè)置為不可訓(xùn)練,我們?nèi)匀豢梢允褂眠@個(gè)模型。例如,我們可以像之前那樣輸入一段示例文本:

inputs = tokenizer.encode ("Do you have time")

inputs = torch.tensor (inputs).unsqueeze (0)

print ("Inputs:", inputs)

print ("Inputs dimensions:", inputs.shape)

如輸出所示,上述代碼將輸入編碼為一個(gè)包含 4 個(gè)輸入 tokens 的張量:

Inputs: tensor ([[5211,  345,  423,  640]])

Inputs dimensions: torch.Size ([1, 4])

然后,我們將編碼后的 token IDs 輸入模型:

with torch.no_grad ():

    outputs = model (inputs)

print ("Outputs:\n", outputs)

print ("Outputs dimensions:", outputs.shape)

輸出張量如下所示:

Outputs:

 tensor ([[[-1.5854,  0.9904],

          [-3.7235,  7.4548],

          [-2.2661,  6.6049],

          [-3.5983,  3.9902]]])

Outputs dimensions: torch.Size ([1, 4, 2])

模型將輸出一個(gè) [1, 4, 50257] 的輸出張量,其中 50,257 代表詞匯表的大小。輸出行數(shù)對(duì)應(yīng)于輸入標(biāo)記的數(shù)量(在本例中是 4)。每個(gè)輸出的嵌入維度(列數(shù))現(xiàn)在減少到 2,而不是 50,257,因?yàn)槲覀兲鎿Q了模型的輸出層。

由于我們的主要目標(biāo)是微調(diào)出更擅長(zhǎng)對(duì)垃圾郵件進(jìn)行分類的模型。為了實(shí)現(xiàn)這一點(diǎn),我們不需要對(duì)所有行進(jìn)行微調(diào),可以專注于一個(gè)單一的輸出 token。具體來(lái)說(shuō),我們將專注于最后一行,對(duì)應(yīng)的最后一個(gè)輸出 token,如圖 6 所示。

圖片

圖 6: 本圖展示了 GPT 模型處理一個(gè)包含 4 個(gè) token 的輸入示例,并生成相應(yīng)輸出的詳細(xì)過(guò)程。模型的輸出層經(jīng)過(guò)調(diào)整,輸出張量?jī)H包含 2 列,為了完成分類微調(diào),我們專注于輸出的最后一行,對(duì)應(yīng)的最后一個(gè) token。

可以使用以下代碼從輸出張量中提取最后一個(gè)輸出 token:

print ("Last output token:", outputs [:, -1, :])

Print 出來(lái)結(jié)果如下:

Last output token: tensor([[-3.5983,  3.9902]])

那么,我們?yōu)槭裁匆x擇最后一個(gè) token,而不是其他位置上的 token 呢?

注意力機(jī)制建立了每個(gè)輸入 token 與其他 token 之間的關(guān)系,為了讓「注意力」集中,需要用到因果注意力掩碼。它的原理是限制每個(gè) token 只關(guān)注自己和前面的 token,如下圖 7 所示:

圖 7:因果注意力機(jī)制,矩陣顯示了每個(gè)輸入 token 之間的注意力得分??瞻讍卧癖硎颈谎诖a屏蔽的位置,防止 token 關(guān)注后來(lái)的 token。最后一個(gè) token「time」是唯一需要為所有之前的 token 計(jì)算注意力得分的 token。

如圖所示,序列中的最后一個(gè) token 積累了最多的信息,因此,在微調(diào)過(guò)程中,我們重點(diǎn)關(guān)注這個(gè)最后的 token。

如何將最后一個(gè) token 轉(zhuǎn)換為分類標(biāo)簽預(yù)測(cè),并計(jì)算模型的初始預(yù)測(cè)準(zhǔn)確率。接下來(lái),我們將在后續(xù)部分微調(diào)模型以完成垃圾郵件分類任務(wù)。

評(píng)估模型性能

由于這部分內(nèi)容已經(jīng)很長(zhǎng),我就不詳細(xì)討論模型評(píng)估的細(xì)節(jié)了。不過(guò),我想至少分享一張圖,展示訓(xùn)練過(guò)程中,模型訓(xùn)練集和驗(yàn)證集的分類準(zhǔn)確率,以展示模型確實(shí)學(xué)得很好。

圖 8:訓(xùn)練準(zhǔn)確率(實(shí)線)和驗(yàn)證準(zhǔn)確率(虛線)在早期的訓(xùn)練周期中大幅上升,然后趨于平穩(wěn),達(dá)到了幾乎完美的準(zhǔn)確率 1.0,對(duì)應(yīng) 100%。兩條線在整個(gè)訓(xùn)練過(guò)程中相距較近,表明模型對(duì)訓(xùn)練數(shù)據(jù)并沒(méi)有過(guò)度擬合。

模型的驗(yàn)證準(zhǔn)確率約為 97%。測(cè)試準(zhǔn)確率約為 96%。此外,我們可以看到模型略微有一點(diǎn)點(diǎn)過(guò)擬合,因?yàn)橛?xùn)練集的準(zhǔn)確率稍高。

從補(bǔ)充實(shí)驗(yàn)得出的洞見(jiàn)

到這里,你可能對(duì)某些設(shè)計(jì)選擇有很多疑問(wèn),所以我進(jìn)行了一些補(bǔ)充實(shí)驗(yàn)并把結(jié)果分享了出來(lái)。重新運(yùn)行這些實(shí)驗(yàn)的代碼已經(jīng)放在了以下 GitHub 項(xiàng)目中。

GitHub 地址:https://github.com/rasbt/LLMs-from-scratch/tree/main/ch06/02_bonus_additional-experiments

需要訓(xùn)練所有層嗎?

出于效率原因,我們僅訓(xùn)練輸出層和最后一個(gè) transformer 塊。如前所述,對(duì)于分類微調(diào),無(wú)需更新 LLM 中的所有層。我們更新的權(quán)重越少,訓(xùn)練速度就越快,因?yàn)槲覀儾恍枰诜聪騻鞑テ陂g計(jì)算權(quán)重的梯度。

但是,你可能想知道如果不更新所有層,我們會(huì)留下多少預(yù)測(cè)性能。因此,在下表中,我對(duì)所有層、僅最后一個(gè) transformer 塊(包括最后一層)、僅最后一層進(jìn)行了微調(diào)。

表 1:訓(xùn)練所有層 vs 僅訓(xùn)練最后一個(gè) Transformer 塊(包括最后一層)vs 僅訓(xùn)練最后一層

如上表 1 所示,訓(xùn)練所有層的性能稍好一些:96.67% vs 95.00%。不過(guò),這使運(yùn)行時(shí)間增加了約 2.5 倍。

為什么要微調(diào)最后一個(gè) token,而不是第一個(gè) token?

如果你熟悉 BERT(Devlin et al. 2018)等編碼器式語(yǔ)言模型,你可能知道這些模型有一個(gè)指定的分類 token 作為其第一個(gè) token,如下圖所示:

圖片圖來(lái)自 BERT 原始論文:https://arxiv.org/abs/1810.04805

與 BERT 相比,GPT 是一種具有因果注意力掩碼的解碼器式模型(如圖 7 所示)。這意味著第一個(gè) token 沒(méi)有輸入中任何其他 token 的上下文信息。只有最后一個(gè) token 具有有關(guān)所有其他 token 的信息。

因此,如果我們想使用像 GPT 這樣的模型進(jìn)行分類微調(diào),我們應(yīng)該關(guān)注最后一個(gè) token 標(biāo)記以捕獲所有其他輸入 token 的上下文信息。

如下表所示,我們可以看到使用第一個(gè) token 來(lái)微調(diào) GPT 模型進(jìn)行分類會(huì)導(dǎo)致性能更差。

表 2:微調(diào) GPT 模型中的最后一個(gè) token 與第一個(gè) token。

BERT 與 GPT 的性能比較如何?

說(shuō)到 BERT,你可能想知道它在分類任務(wù)上與類 GPT 模型的性能比較如何?簡(jiǎn)單來(lái)說(shuō),在垃圾郵件分類任務(wù)上,更小的 GPT-2(124M)與更大 BERT(340M)的性能類似,具體如下表 3 所示。

圖片

表 3:GPT-2 與 BERT 的結(jié)果比較。

可以看到,BERT 模型的表現(xiàn)比 GPT-2 稍微好一點(diǎn)(測(cè)試準(zhǔn)確率高 1%),但 BERT 的參數(shù)規(guī)模幾乎是 GPT-2 的 3 倍。此外,數(shù)據(jù)集可能太小且太簡(jiǎn)單了,因此我又在 IMDB Movie Review 數(shù)據(jù)集上嘗試比較了情感分類表現(xiàn)(即預(yù)測(cè)觀看者是否喜歡一部電影)。

圖片

表 4:GPT-2 與 BERT 在影評(píng)分類任務(wù)上的比較。

可以看到,在這個(gè)更大的數(shù)據(jù)集上(包含 25k 訓(xùn)練和 25k 測(cè)試集記錄),GPT-2 與 BERT 兩個(gè)模型的預(yù)測(cè)性能同樣類似。

總的來(lái)說(shuō),在分類任務(wù)上,BERT 和其他編碼器風(fēng)格的模型被認(rèn)為優(yōu)于解碼器風(fēng)格的模型。但是,實(shí)驗(yàn)結(jié)果也表明,編碼器風(fēng)格的 BERT 和解碼器風(fēng)格的 GPT 模型之間沒(méi)有太大的差異。

此外,如果你對(duì)更多基準(zhǔn)比較以及如何進(jìn)一步提升解碼器風(fēng)格模型的分類性能感興趣,可以參閱以下兩篇最近的論文:

  • Label Supervised LLaMA Finetuning:https://arxiv.org/abs/2310.01208
  • LLM2Vec: Large Language Models Are Secretly Powerful Text Encoders:https://arxiv.org/abs/2404.05961

其中第一篇論文討論了:在分類微調(diào)期間移除因果掩碼可以提升解碼器風(fēng)格模型的分類性能。

我們應(yīng)該禁用因果掩碼嗎?

當(dāng)我們?cè)谙乱粋€(gè)詞(next-word)預(yù)測(cè)任務(wù)上訓(xùn)練類 GPT 模型時(shí),GPT 架構(gòu)的核心特征是因果注意力掩碼,這與 BERT 模型或原始 transformer 架構(gòu)不同。

但實(shí)際上,我們可以在分類微調(diào)階段移除因果掩碼, 從而允許我們微調(diào)第一個(gè)而不是最后一個(gè) token。這是因?yàn)槲磥?lái)的 tokens 將不再被掩碼,并且第一個(gè) token 可以看到所有其他的 tokens.

圖片

有 / 無(wú)因果掩碼的注意力權(quán)重矩陣。

幸運(yùn)的是,在類 GPT 大語(yǔ)言模型中禁用因果注意力掩碼只需要改變 2 行代碼。

class MultiheadAttention (nn.Module):

    def __init__(self, d_in, d_out, context_length, dropout, num_heads):

        super ().__init__()

        # ...

    def forward (self, x):

        b, num_tokens, d_in = x.shape

        keys = self.W_key (x)  # Shape: (b, num_tokens, d_out)

        queries = self.W_query (x)

        values = self.W_value (x)

        # ...

        attn_scores = queries @ keys.transpose (2, 3)

        # Comment out the causal attention mask part

        # mask_bool = self.mask.bool ()[:num_tokens, :num_tokens]

        # attn_scores.masked_fill_(mask_bool, -torch.inf)

        attn_weights = torch.softmax (

             attn_scores /keys.shape [-1]**0.5, dim=-1

        )

        context_vec = (attn_weights @ values).transpose (1, 2)

        context_vec = context_vec.contiguous ().view (

            b, num_tokens, self.d_out

        )

        context_vec = self.out_proj (context_vec)

        return context_vec

下表 5 展示了改變代碼后對(duì)垃圾郵件分類任務(wù)帶來(lái)的影響。

圖片

表 5:有無(wú)使用因果注意力掩碼來(lái)微調(diào) GPT-2 分類器的結(jié)果。

可以看到,在微調(diào)階段禁用因果掩碼可以帶來(lái)略微的提升。

增加模型大小會(huì)帶來(lái)哪些影響?

目前為止,我們只看到了最小的 GPT-2(124M)模型的性能,那么與規(guī)模更大的 GPT-2 變體相比如何呢?比如 GPT-2 medium(355M)、GPT-2 large(774M)和 GPT-2 XL(1558M)。結(jié)果如下表 6 所示。

圖片

表 6:不同參數(shù)規(guī)模的 GPT-2 變體的分類微調(diào)結(jié)果。

可以看到,隨著模型參數(shù)增加,預(yù)測(cè)準(zhǔn)確率顯著提升。不過(guò) GPT-2 medium 是個(gè)例外,它在其他數(shù)據(jù)集上的性能同樣很差。我懷疑該模型可能沒(méi)有經(jīng)過(guò)很好的預(yù)訓(xùn)練。

此外,最大的 GPT-2 XL 獲得了比最小的 GPT-2 small(124M)好得多的分類準(zhǔn)確率,但微調(diào)時(shí)間也長(zhǎng)了 7 倍。

LoRA 預(yù)計(jì)能帶來(lái)哪些改進(jìn)?

回到本文第一個(gè)問(wèn)題:我們需要訓(xùn)練所有層嗎?結(jié)果發(fā)現(xiàn),當(dāng)僅僅微調(diào)最后一個(gè) transformer 塊而不是整個(gè)模型時(shí), 我們可以(或幾乎可以)匹配分配性能。所以僅僅微調(diào)最后一個(gè)塊的優(yōu)勢(shì)在于訓(xùn)練速度更快,畢竟不是所有的權(quán)重參數(shù)都要更新。

接下來(lái)的問(wèn)題是與低秩適應(yīng)(LoRA)的比較結(jié)果如何,LoRA 是一種參數(shù)高效的微調(diào)技術(shù)。

圖片

表 7:覆蓋所有層的完整微調(diào) vs 利用 LoRA 的參數(shù)高效微調(diào)。

可以看到,完整微調(diào)(所有層)和 LoRA 在數(shù)據(jù)集上獲得了相似的測(cè)試集性能。

在小模型上,LoRA 會(huì)稍微慢一點(diǎn),添加 LoRA 層帶來(lái)的額外開(kāi)銷可能會(huì)超過(guò)獲得的收益。但當(dāng)訓(xùn)練更大的 15 億參數(shù)模型時(shí),LoRA 的訓(xùn)練速度會(huì)快 1.53 倍。

填充(Padding)還是不填充?

如果我們想要在訓(xùn)練或推理階段分批次地處理數(shù)據(jù)(包括一次處理多個(gè)輸入序列),則需要插入 padding token,以確保訓(xùn)練樣本的長(zhǎng)度相等。

圖片

圖中描述了給定批次中的輸入文本如何在 padding 過(guò)程中保持長(zhǎng)度相等。

在常規(guī)文本生成任務(wù)中,由于 padding tokens 通常要添加到右側(cè),因而 padding 不影響模型的響應(yīng)結(jié)果。并且由于前面討論過(guò)的因果掩碼,這些 padding tokens 也不影響其他 token。

但是,我們對(duì)最后一個(gè) token 進(jìn)行了微調(diào)。同時(shí)由于 padding tokens 在最后一個(gè) token 的左側(cè),因此可能影響結(jié)果。

如果我們使用的批大小為 1,實(shí)際上不需要 pad 輸入。當(dāng)然,這樣做從計(jì)算的角度來(lái)看更加高效(一次只處理一個(gè)輸入樣本)。并且批大小為 1 可以用作一個(gè)變通方法,來(lái)測(cè)試使用 padding 是否影響結(jié)果。

圖片

表 8:有無(wú) padding 時(shí),GPT-2(124M)的訓(xùn)練準(zhǔn)確率、驗(yàn)證準(zhǔn)確率和測(cè)試準(zhǔn)確率變化。

可以看到,避免 padding tokens 的確可以為模型帶來(lái)效果的顯著提升。這里使用了梯度累計(jì)來(lái)模擬批大小 8,以匹配默認(rèn)實(shí)驗(yàn)的批大小,并進(jìn)行公平比較。

作者介紹

圖片

個(gè)人主頁(yè):https://sebastianraschka.com/

Sebastian Raschka 是一名機(jī)器學(xué)習(xí)和人工智能研究員,曾在威斯康星大學(xué)麥迪遜分校擔(dān)任統(tǒng)計(jì)學(xué)助理教授,專門研究深度學(xué)習(xí)和機(jī)器學(xué)習(xí)。他致力于關(guān)于 AI 和深度學(xué)習(xí)相關(guān)的內(nèi)容更簡(jiǎn)單易懂。

Sebastian 還熱衷于開(kāi)源軟件,十多年來(lái),他一直是一個(gè)充滿熱情的開(kāi)源貢獻(xiàn)者。他提出的方法現(xiàn)已成功在 Kaggle 等機(jī)器學(xué)習(xí)競(jìng)賽中得到應(yīng)用。

除了編寫代碼,Sebastian 還喜歡寫作,他撰寫了暢銷書《Python Machine Learning》(《Python 機(jī)器學(xué)習(xí)》)和《Machine Learning with PyTorch and ScikitLearn》。

這篇博客的內(nèi)容是他的新書《Build a Large Language Model (From Scratch)》的第六章。

更多研究細(xì)節(jié),可參考原博客。

責(zé)任編輯:張燕妮 來(lái)源: 機(jī)器之心
相關(guān)推薦

2024-06-24 07:50:00

代碼機(jī)器學(xué)習(xí)

2017-08-04 14:23:04

機(jī)器學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)TensorFlow

2024-10-30 16:59:57

Python機(jī)器學(xué)習(xí)

2022-10-09 08:00:00

機(jī)器學(xué)習(xí)文本分類算法

2024-12-20 16:00:00

Python文本分類聚類

2020-03-23 08:00:00

開(kāi)源數(shù)據(jù)集文本分類

2024-06-13 08:36:11

2024-03-01 13:49:00

數(shù)據(jù)訓(xùn)練

2024-08-15 14:48:57

2024-02-21 14:07:00

2023-11-28 09:00:00

機(jī)器學(xué)習(xí)少樣本學(xué)習(xí)SetFit

2020-12-24 06:54:45

Python機(jī)器學(xué)習(xí)多類分類邏輯回歸

2022-09-11 15:02:22

機(jī)器學(xué)習(xí)算法感知器

2022-06-05 21:16:08

機(jī)器學(xué)習(xí)Python

2021-07-23 08:00:00

深度學(xué)習(xí)框架模型

2017-06-22 09:53:01

機(jī)器學(xué)習(xí)Python樸素貝葉斯

2017-06-20 11:00:13

大數(shù)據(jù)自然語(yǔ)言文本分類器

2018-06-19 08:35:51

情感分析數(shù)據(jù)集代碼

2020-04-17 14:48:30

代碼機(jī)器學(xué)習(xí)Python

2024-02-22 09:51:56

代碼AI
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)