PEFT 文件

IA3

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

IA3

IA3 透過三個學習到的向量來乘以模型的啟用值(自注意力塊和編碼器-解碼器注意力塊中的鍵和值,以及位置前饋網路的中間啟用值)。這種 PEFT 方法引入的可訓練引數數量甚至比 LoRA 更少,後者引入的是權重矩陣而非向量。原始模型的引數保持凍結,只更新這些向量。因此,針對新的下游任務進行微調時,它更快、更便宜、更高效。

本指南將向您展示如何使用 IA3 訓練一個序列到序列模型,以便根據一些財經新聞來 *生成情感*。

對訓練序列到序列模型的一般過程有所瞭解會非常有幫助,能讓您更專注於如何應用 IA3。如果您是新手,我們建議您先閱讀 Transformers 文件中的翻譯摘要指南。準備好後,再回來看看在您的訓練中加入 PEFT 是多麼簡單!

資料集

您將使用 financial_phrasebank 資料集的 `sentences_allagree` 子集。該子集包含的財經新聞在情感標籤上獲得了 100% 的標註員一致性。透過資料集檢視器可以更好地瞭解您將要處理的資料和句子。

使用 load_dataset 函式載入資料集。該資料集子集僅包含訓練集,因此使用 `train_test_split` 函式建立一個訓練集和驗證集。建立一個新的 `text_label` 列,以便更容易理解 `label` 值 `0`、`1` 和 `2` 的含義。

from datasets import load_dataset

ds = load_dataset("financial_phrasebank", "sentences_allagree")
ds = ds["train"].train_test_split(test_size=0.1)
ds["validation"] = ds["test"]
del ds["test"]

classes = ds["train"].features["label"].names
ds = ds.map(
    lambda x: {"text_label": [classes[label] for label in x["label"]]},
    batched=True,
    num_proc=1,
)

ds["train"][0]
{'sentence': 'It will be operated by Nokia , and supported by its Nokia NetAct network and service management system .',
 'label': 1,
 'text_label': 'neutral'}

載入一個分詞器並建立一個預處理函式,該函式:

  1. 對輸入進行分詞、填充和截斷至 `max_length`
  2. 對標籤應用相同的分詞器,但使用與標籤長度對應的較短 `max_length`
  3. 掩碼填充令牌
from transformers import AutoTokenizer

text_column = "sentence"
label_column = "text_label"
max_length = 128

tokenizer = AutoTokenizer.from_pretrained("bigscience/mt0-large")

def preprocess_function(examples):
    inputs = examples[text_column]
    targets = examples[label_column]
    model_inputs = tokenizer(inputs, max_length=max_length, padding="max_length", truncation=True, return_tensors="pt")
    labels = tokenizer(targets, max_length=3, padding="max_length", truncation=True, return_tensors="pt")
    labels = labels["input_ids"]
    labels[labels == tokenizer.pad_token_id] = -100
    model_inputs["labels"] = labels
    return model_inputs

使用 map 函式將預處理函式應用於整個資料集。

processed_ds = ds.map(
    preprocess_function,
    batched=True,
    num_proc=1,
    remove_columns=ds["train"].column_names,
    load_from_cache_file=False,
    desc="Running tokenizer on dataset",
)

建立訓練和評估的 `DataLoader`,如果您的資料集樣本在 CPU 上,設定 `pin_memory=True` 可以加速訓練期間資料到 GPU 的傳輸。

from torch.utils.data import DataLoader
from transformers import default_data_collator

train_ds = processed_ds["train"]
eval_ds = processed_ds["validation"]

batch_size = 8

train_dataloader = DataLoader(
    train_ds, shuffle=True, collate_fn=default_data_collator, batch_size=batch_size, pin_memory=True
)
eval_dataloader = DataLoader(eval_ds, collate_fn=default_data_collator, batch_size=batch_size, pin_memory=True)

模型

現在您可以載入一個預訓練模型作為 IA3 的基礎模型。本指南使用 bigscience/mt0-large 模型,但您可以使用任何您喜歡的序列到序列模型。

from transformers import AutoModelForSeq2SeqLM

model = AutoModelForSeq2SeqLM.from_pretrained("bigscience/mt0-large")

PEFT 配置和模型

所有的 PEFT 方法都需要一個配置,其中包含並指定了如何應用該 PEFT 方法的所有引數。建立一個 IA3Config,指定任務型別並將推理模式設定為 `False`。您可以在 API 參考中找到該配置的其他引數。

呼叫 print_trainable_parameters() 方法,比較 PeftModel 的可訓練引數數量與基礎模型中的引數數量!

配置設定好後,將其與基礎模型一起傳遞給 get_peft_model() 函式,以建立一個可訓練的 PeftModel

from peft import IA3Config, get_peft_model

peft_config = IA3Config(task_type="SEQ_2_SEQ_LM")
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()
"trainable params: 282,624 || all params: 1,229,863,936 || trainable%: 0.022980103060766553"

訓練

設定最佳化器和學習率排程器。

import torch
from transformers import get_linear_schedule_with_warmup

lr = 8e-3
num_epochs = 3

optimizer = torch.optim.AdamW(model.parameters(), lr=lr)
lr_scheduler = get_linear_schedule_with_warmup(
    optimizer=optimizer,
    num_warmup_steps=0,
    num_training_steps=(len(train_dataloader) * num_epochs),
)

將模型移動到 GPU,並建立一個訓練迴圈,報告每個週期的損失和困惑度。

from tqdm import tqdm

device = "cuda"
model = model.to(device)

for epoch in range(num_epochs):
    model.train()
    total_loss = 0
    for step, batch in enumerate(tqdm(train_dataloader)):
        batch = {k: v.to(device) for k, v in batch.items()}
        outputs = model(**batch)
        loss = outputs.loss
        total_loss += loss.detach().float()
        loss.backward()
        optimizer.step()
        lr_scheduler.step()
        optimizer.zero_grad()

    model.eval()
    eval_loss = 0
    eval_preds = []
    for step, batch in enumerate(tqdm(eval_dataloader)):
        batch = {k: v.to(device) for k, v in batch.items()}
        with torch.no_grad():
            outputs = model(**batch)
        loss = outputs.loss
        eval_loss += loss.detach().float()
        eval_preds.extend(
            tokenizer.batch_decode(torch.argmax(outputs.logits, -1).detach().cpu().numpy(), skip_special_tokens=True)
        )

    eval_epoch_loss = eval_loss / len(eval_dataloader)
    eval_ppl = torch.exp(eval_epoch_loss)
    train_epoch_loss = total_loss / len(train_dataloader)
    train_ppl = torch.exp(train_epoch_loss)
    print(f"{epoch=}: {train_ppl=} {train_epoch_loss=} {eval_ppl=} {eval_epoch_loss=}")

分享您的模型

訓練完成後,您可以使用 `push_to_hub` 方法將模型上傳到 Hub。您需要先登入您的 Hugging Face 賬戶,並在提示時輸入您的令牌。

from huggingface_hub import notebook_login

account = <your-hf-account-name>
peft_model_id = f"{account}/mt0-large-ia3"
model.push_to_hub(peft_model_id)

推理

要載入模型進行推理,請使用 from_pretrained() 方法。我們還從資料集中載入一條財經新聞,為其生成情感。

from peft import AutoPeftModelForSeq2SeqLM

model = AutoPeftModelForSeq2SeqLM.from_pretrained("<your-hf-account-name>/mt0-large-ia3").to("cuda")
tokenizer = AutoTokenizer.from_pretrained("bigscience/mt0-large")

i = 15
inputs = tokenizer(ds["validation"][text_column][i], return_tensors="pt")
print(ds["validation"][text_column][i])
"The robust growth was the result of the inclusion of clothing chain Lindex in the Group in December 2007 ."

呼叫 `generate` 方法來生成預測的情感標籤。

with torch.no_grad():
    inputs = {k: v.to(device) for k, v in inputs.items()}
    outputs = model.generate(input_ids=inputs["input_ids"], max_new_tokens=10)
    print(tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True))
['positive']
< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.