Files

31 KiB

In [1]:
import argparse
import os

import torch
from torch.optim import AdamW
from torch.utils.data import DataLoader
from peft import (
    get_peft_config,
    get_peft_model,
    get_peft_model_state_dict,
    set_peft_model_state_dict,
    LoraConfig,
    PeftType,
    PrefixTuningConfig,
    PromptEncoderConfig,
)

import evaluate
from datasets import load_dataset
from transformers import AutoModelForSequenceClassification, AutoTokenizer, get_linear_schedule_with_warmup, set_seed
from tqdm import tqdm
===================================BUG REPORT===================================
Welcome to bitsandbytes. For bug reports, please submit your error trace to: https://github.com/TimDettmers/bitsandbytes/issues
For effortless bug reporting copy-paste your error into this form: https://docs.google.com/forms/d/e/1FAIpQLScPB8emS3Thkp66nvqwmjTEgxp8Y9ufuWTzFyr9kJ5AoI47dQ/viewform?usp=sf_link
================================================================================
CUDA SETUP: CUDA runtime path found: /home/sourab/miniconda3/envs/ml/lib/libcudart.so
CUDA SETUP: Highest compute capability among GPUs detected: 7.5
CUDA SETUP: Detected CUDA version 117
CUDA SETUP: Loading binary /home/sourab/miniconda3/envs/ml/lib/python3.10/site-packages/bitsandbytes/libbitsandbytes_cuda117.so...
In [2]:
batch_size = 32
model_name_or_path = "roberta-large"
task = "mrpc"
peft_type = PeftType.LORA
device = "cuda"
num_epochs = 20
In [3]:
peft_config = LoraConfig(task_type="SEQ_CLS", inference_mode=False, r=8, lora_alpha=16, lora_dropout=0.1)
lr = 3e-4
In [4]:
if any(k in model_name_or_path for k in ("gpt", "opt", "bloom")):
    padding_side = "left"
else:
    padding_side = "right"

tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, padding_side=padding_side)
if getattr(tokenizer, "pad_token_id") is None:
    tokenizer.pad_token_id = tokenizer.eos_token_id

datasets = load_dataset("glue", task)
metric = evaluate.load("glue", task)


def tokenize_function(examples):
    # max_length=None => use the model max length (it's actually the default)
    outputs = tokenizer(examples["sentence1"], examples["sentence2"], truncation=True, max_length=None)
    return outputs


tokenized_datasets = datasets.map(
    tokenize_function,
    batched=True,
    remove_columns=["idx", "sentence1", "sentence2"],
)

# We also rename the 'label' column to 'labels' which is the expected name for labels by the models of the
# transformers library
tokenized_datasets = tokenized_datasets.rename_column("label", "labels")


def collate_fn(examples):
    return tokenizer.pad(examples, padding="longest", return_tensors="pt")


# Instantiate dataloaders.
train_dataloader = DataLoader(tokenized_datasets["train"], shuffle=True, collate_fn=collate_fn, batch_size=batch_size)
eval_dataloader = DataLoader(
    tokenized_datasets["validation"], shuffle=False, collate_fn=collate_fn, batch_size=batch_size
)
Downloading readme:   0%|          | 0.00/27.9k [00:00<?, ?B/s]
Found cached dataset glue (/home/sourab/.cache/huggingface/datasets/glue/mrpc/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad)
  0%|          | 0/3 [00:00<?, ?it/s]
  0%|          | 0/4 [00:00<?, ?ba/s]
  0%|          | 0/1 [00:00<?, ?ba/s]
  0%|          | 0/2 [00:00<?, ?ba/s]
In [ ]:
model = AutoModelForSequenceClassification.from_pretrained(model_name_or_path, return_dict=True)
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()
model
In [6]:
optimizer = AdamW(params=model.parameters(), lr=lr)

# Instantiate scheduler
lr_scheduler = get_linear_schedule_with_warmup(
    optimizer=optimizer,
    num_warmup_steps=0.06 * (len(train_dataloader) * num_epochs),
    num_training_steps=(len(train_dataloader) * num_epochs),
)
In [7]:
model.to(device)
for epoch in range(num_epochs):
    model.train()
    for step, batch in enumerate(tqdm(train_dataloader)):
        batch.to(device)
        outputs = model(**batch)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        lr_scheduler.step()
        optimizer.zero_grad()

    model.eval()
    for step, batch in enumerate(tqdm(eval_dataloader)):
        batch.to(device)
        with torch.no_grad():
            outputs = model(**batch)
        predictions = outputs.logits.argmax(dim=-1)
        predictions, references = predictions, batch["labels"]
        metric.add_batch(
            predictions=predictions,
            references=references,
        )

    eval_metric = metric.compute()
    print(f"epoch {epoch}:", eval_metric)
  0%|                                                                                                  | 0/115 [00:00<?, ?it/s]You're using a RobertaTokenizerFast tokenizer. Please note that with a fast tokenizer, using the `__call__` method is faster than using a method to encode the text followed by a call to the `pad` method to get a padded encoding.
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:28<00:00,  4.08it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.68it/s]
epoch 0: {'accuracy': 0.7009803921568627, 'f1': 0.8189910979228486}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.18it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.64it/s]
epoch 1: {'accuracy': 0.7622549019607843, 'f1': 0.8482003129890453}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.20it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.63it/s]
epoch 2: {'accuracy': 0.8651960784313726, 'f1': 0.9005424954792043}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.21it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.62it/s]
epoch 3: {'accuracy': 0.8921568627450981, 'f1': 0.9228070175438596}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.20it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.62it/s]
epoch 4: {'accuracy': 0.8970588235294118, 'f1': 0.9257950530035336}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.16it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.01it/s]
epoch 5: {'accuracy': 0.8823529411764706, 'f1': 0.9169550173010381}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:30<00:00,  3.81it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.62it/s]
epoch 6: {'accuracy': 0.8799019607843137, 'f1': 0.9170896785109983}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.16it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.61it/s]
epoch 7: {'accuracy': 0.8799019607843137, 'f1': 0.9150779896013865}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.18it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.61it/s]
epoch 8: {'accuracy': 0.8921568627450981, 'f1': 0.9233449477351917}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.18it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.59it/s]
epoch 9: {'accuracy': 0.8872549019607843, 'f1': 0.9217687074829931}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.16it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.61it/s]
epoch 10: {'accuracy': 0.8774509803921569, 'f1': 0.9137931034482758}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:29<00:00,  3.90it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  6.81it/s]
epoch 11: {'accuracy': 0.9068627450980392, 'f1': 0.9321428571428573}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:28<00:00,  4.05it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.59it/s]
epoch 12: {'accuracy': 0.8946078431372549, 'f1': 0.925476603119584}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.17it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.58it/s]
epoch 13: {'accuracy': 0.8897058823529411, 'f1': 0.922279792746114}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.18it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.61it/s]
epoch 14: {'accuracy': 0.8970588235294118, 'f1': 0.9265734265734265}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.18it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.60it/s]
epoch 15: {'accuracy': 0.8970588235294118, 'f1': 0.9263157894736843}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.17it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.59it/s]
epoch 16: {'accuracy': 0.8921568627450981, 'f1': 0.9233449477351917}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.18it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.58it/s]
epoch 17: {'accuracy': 0.8897058823529411, 'f1': 0.9220103986135182}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:30<00:00,  3.78it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.58it/s]
epoch 18: {'accuracy': 0.8921568627450981, 'f1': 0.9233449477351917}
100%|████████████████████████████████████████████████████████████████████████████████████████| 115/115 [00:27<00:00,  4.16it/s]
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.60it/s]
epoch 19: {'accuracy': 0.8946078431372549, 'f1': 0.924693520140105}

Share adapters on the 🤗 Hub

In [8]:
model.push_to_hub("smangrul/roberta-large-peft-lora", use_auth_token=True)
Out [8]:
CommitInfo(commit_url='https://huggingface.co/smangrul/roberta-large-peft-lora/commit/c2c661898b8b6a0c68ecd068931e598d0a79686b', commit_message='Upload model', commit_description='', oid='c2c661898b8b6a0c68ecd068931e598d0a79686b', pr_url=None, pr_revision=None, pr_num=None)

Load adapters from the Hub

You can also directly load adapters from the Hub using the commands below:

In [11]:
import torch
from peft import PeftModel, PeftConfig
from transformers import AutoModelForCausalLM, AutoTokenizer

peft_model_id = "smangrul/roberta-large-peft-lora"
config = PeftConfig.from_pretrained(peft_model_id)
inference_model = AutoModelForSequenceClassification.from_pretrained(config.base_model_name_or_path)
tokenizer = AutoTokenizer.from_pretrained(config.base_model_name_or_path)

# Load the Lora model
inference_model = PeftModel.from_pretrained(inference_model, peft_model_id)

inference_model.to(device)
inference_model.eval()
for step, batch in enumerate(tqdm(eval_dataloader)):
    batch.to(device)
    with torch.no_grad():
        outputs = inference_model(**batch)
    predictions = outputs.logits.argmax(dim=-1)
    predictions, references = predictions, batch["labels"]
    metric.add_batch(
        predictions=predictions,
        references=references,
    )

eval_metric = metric.compute()
print(eval_metric)
Some weights of the model checkpoint at roberta-large were not used when initializing RobertaForSequenceClassification: ['lm_head.bias', 'roberta.pooler.dense.weight', 'roberta.pooler.dense.bias', 'lm_head.layer_norm.weight', 'lm_head.decoder.weight', 'lm_head.dense.bias', 'lm_head.dense.weight', 'lm_head.layer_norm.bias']
- This IS expected if you are initializing RobertaForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).
- This IS NOT expected if you are initializing RobertaForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
Some weights of RobertaForSequenceClassification were not initialized from the model checkpoint at roberta-large and are newly initialized: ['classifier.dense.bias', 'classifier.out_proj.bias', 'classifier.dense.weight', 'classifier.out_proj.weight']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
  0%|                                                                                                   | 0/13 [00:00<?, ?it/s]You're using a RobertaTokenizerFast tokenizer. Please note that with a fast tokenizer, using the `__call__` method is faster than using a method to encode the text followed by a call to the `pad` method to get a padded encoding.
100%|██████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00,  8.45it/s]
{'accuracy': 0.8946078431372549, 'f1': 0.924693520140105}
In [ ]: