Text Classification
Transformers
lora
fine-tuning
adaptive
research
nested-lora
synaptic-plasticity
rank-adaptation
Instructions to use Simo76/Unified-LoRA with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Simo76/Unified-LoRA with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Simo76/Unified-LoRA")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Simo76/Unified-LoRA", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Add Unified LoRA MRPC Benchmark Example Notebook
Browse filesThis notebook demonstrates Unified LoRA on the GLUE MRPC (paraphrase detection) task, including setup, data loading, and evaluation of both baseline and unified LoRA models.
- notebooks/mrpc_example.ipynb +212 -0
notebooks/mrpc_example.ipynb
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {},
|
| 6 |
+
"source": [
|
| 7 |
+
"# Unified LoRA - MRPC Benchmark Example\n",
|
| 8 |
+
"\n",
|
| 9 |
+
"This notebook demonstrates Unified LoRA on the GLUE MRPC (paraphrase detection) task.\n",
|
| 10 |
+
"\n",
|
| 11 |
+
"**Expected results:**\n",
|
| 12 |
+
"- Baseline LoRA: F1 ~0.78-0.79\n",
|
| 13 |
+
"- Unified LoRA: F1 ~0.78-0.79 (performance parity with adaptive control)\n",
|
| 14 |
+
"- φ(t) convergence from 0.5 → ~0.35-0.40\n",
|
| 15 |
+
"- Mode primarily stays in Multi (1) for stable training"
|
| 16 |
+
]
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
"cell_type": "markdown",
|
| 20 |
+
"metadata": {},
|
| 21 |
+
"source": [
|
| 22 |
+
"## Setup"
|
| 23 |
+
]
|
| 24 |
+
},
|
| 25 |
+
{
|
| 26 |
+
"cell_type": "code",
|
| 27 |
+
"execution_count": null,
|
| 28 |
+
"metadata": {},
|
| 29 |
+
"outputs": [],
|
| 30 |
+
"source": [
|
| 31 |
+
"!pip install -q transformers datasets peft evaluate scikit-learn accelerate"
|
| 32 |
+
]
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"cell_type": "code",
|
| 36 |
+
"execution_count": null,
|
| 37 |
+
"metadata": {},
|
| 38 |
+
"outputs": [],
|
| 39 |
+
"source": [
|
| 40 |
+
"import os\n",
|
| 41 |
+
"os.environ[\"WANDB_DISABLED\"] = \"true\"\n",
|
| 42 |
+
"\n",
|
| 43 |
+
"import torch\n",
|
| 44 |
+
"from datasets import load_dataset\n",
|
| 45 |
+
"from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments\n",
|
| 46 |
+
"from peft import LoraConfig, get_peft_model\n",
|
| 47 |
+
"from torch.utils.data import DataLoader\n",
|
| 48 |
+
"import evaluate\n",
|
| 49 |
+
"\n",
|
| 50 |
+
"# Import UnifiedController\n",
|
| 51 |
+
"import sys\n",
|
| 52 |
+
"sys.path.append('..')\n",
|
| 53 |
+
"from controller import UnifiedController\n",
|
| 54 |
+
"\n",
|
| 55 |
+
"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
|
| 56 |
+
"print(f\"Using device: {device}\")"
|
| 57 |
+
]
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"cell_type": "markdown",
|
| 61 |
+
"metadata": {},
|
| 62 |
+
"source": [
|
| 63 |
+
"## Load Data"
|
| 64 |
+
]
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"cell_type": "code",
|
| 68 |
+
"execution_count": null,
|
| 69 |
+
"metadata": {},
|
| 70 |
+
"outputs": [],
|
| 71 |
+
"source": [
|
| 72 |
+
"dataset = load_dataset(\"glue\", \"mrpc\")[\"train\"].train_test_split(test_size=0.2, seed=42)\n",
|
| 73 |
+
"print(f\"Dataset: {len(dataset['train'])} train | {len(dataset['test'])} test\")\n",
|
| 74 |
+
"\n",
|
| 75 |
+
"model_name = \"distilbert-base-uncased\"\n",
|
| 76 |
+
"tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
|
| 77 |
+
"if tokenizer.pad_token is None:\n",
|
| 78 |
+
" tokenizer.pad_token = tokenizer.eos_token\n",
|
| 79 |
+
"\n",
|
| 80 |
+
"def tokenize(examples):\n",
|
| 81 |
+
" return tokenizer(examples['sentence1'], examples['sentence2'], truncation=True, max_length=128, padding=True)\n",
|
| 82 |
+
"\n",
|
| 83 |
+
"tokenized_train = dataset['train'].map(tokenize, batched=True).rename_column(\"label\", \"labels\")\n",
|
| 84 |
+
"tokenized_test = dataset['test'].map(tokenize, batched=True).rename_column(\"label\", \"labels\")\n",
|
| 85 |
+
"\n",
|
| 86 |
+
"metric = evaluate.combine([\"accuracy\", \"f1\"])\n",
|
| 87 |
+
"\n",
|
| 88 |
+
"def compute_metrics(eval_pred):\n",
|
| 89 |
+
" logits, labels = eval_pred\n",
|
| 90 |
+
" predictions = torch.argmax(torch.tensor(logits), axis=-1)\n",
|
| 91 |
+
" return metric.compute(predictions=predictions, references=labels)"
|
| 92 |
+
]
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"cell_type": "markdown",
|
| 96 |
+
"metadata": {},
|
| 97 |
+
"source": [
|
| 98 |
+
"## Baseline LoRA"
|
| 99 |
+
]
|
| 100 |
+
},
|
| 101 |
+
{
|
| 102 |
+
"cell_type": "code",
|
| 103 |
+
"execution_count": null,
|
| 104 |
+
"metadata": {},
|
| 105 |
+
"outputs": [],
|
| 106 |
+
"source": [
|
| 107 |
+
"print(\"🟡 BASELINE LoRA\")\n",
|
| 108 |
+
"model_base = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)\n",
|
| 109 |
+
"model_base = get_peft_model(model_base, LoraConfig(r=16, lora_alpha=32, target_modules=[\"q_lin\", \"v_lin\"]))\n",
|
| 110 |
+
"\n",
|
| 111 |
+
"trainer_base = Trainer(\n",
|
| 112 |
+
" model=model_base,\n",
|
| 113 |
+
" train_dataset=tokenized_train,\n",
|
| 114 |
+
" eval_dataset=tokenized_test,\n",
|
| 115 |
+
" args=TrainingArguments(\n",
|
| 116 |
+
" output_dir=\"./baseline\",\n",
|
| 117 |
+
" num_train_epochs=3,\n",
|
| 118 |
+
" per_device_train_batch_size=16,\n",
|
| 119 |
+
" fp16=True,\n",
|
| 120 |
+
" eval_strategy=\"epoch\",\n",
|
| 121 |
+
" save_strategy=\"no\",\n",
|
| 122 |
+
" report_to=None\n",
|
| 123 |
+
" ),\n",
|
| 124 |
+
" tokenizer=tokenizer,\n",
|
| 125 |
+
" compute_metrics=compute_metrics\n",
|
| 126 |
+
")\n",
|
| 127 |
+
"\n",
|
| 128 |
+
"trainer_base.train()\n",
|
| 129 |
+
"results_base = trainer_base.evaluate()\n",
|
| 130 |
+
"print(f\"F1: {results_base['eval_f1']:.3f} | Acc: {results_base['eval_accuracy']:.3f}\")"
|
| 131 |
+
]
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"cell_type": "markdown",
|
| 135 |
+
"metadata": {},
|
| 136 |
+
"source": [
|
| 137 |
+
"## Unified LoRA"
|
| 138 |
+
]
|
| 139 |
+
},
|
| 140 |
+
{
|
| 141 |
+
"cell_type": "code",
|
| 142 |
+
"execution_count": null,
|
| 143 |
+
"metadata": {},
|
| 144 |
+
"outputs": [],
|
| 145 |
+
"source": [
|
| 146 |
+
"print(\"🔵 UNIFIED LoRA\")\n",
|
| 147 |
+
"controller = UnifiedController()\n",
|
| 148 |
+
"\n",
|
| 149 |
+
"model_unified = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)\n",
|
| 150 |
+
"model_unified = get_peft_model(model_unified, LoraConfig(r=16, lora_alpha=32, target_modules=[\"q_lin\", \"v_lin\"]))\n",
|
| 151 |
+
"model_unified = model_unified.to(device)\n",
|
| 152 |
+
"\n",
|
| 153 |
+
"train_loader = DataLoader(tokenized_train.remove_columns(['sentence1', 'sentence2', 'idx']), batch_size=16, shuffle=True)\n",
|
| 154 |
+
"optimizer = torch.optim.AdamW(model_unified.parameters(), lr=3e-5)\n",
|
| 155 |
+
"model_unified.train()\n",
|
| 156 |
+
"\n",
|
| 157 |
+
"for epoch in range(3):\n",
|
| 158 |
+
" print(f\"Epoch {epoch+1}/3\")\n",
|
| 159 |
+
" for i, batch in enumerate(train_loader):\n",
|
| 160 |
+
" inputs = {k: v.to(device) for k, v in batch.items() if k in ['input_ids', 'attention_mask', 'labels']}\n",
|
| 161 |
+
" outputs = model_unified(**inputs)\n",
|
| 162 |
+
" new_lr = controller.update(outputs.loss.item())\n",
|
| 163 |
+
" for g in optimizer.param_groups: g['lr'] = new_lr\n",
|
| 164 |
+
" outputs.loss.backward()\n",
|
| 165 |
+
" optimizer.step()\n",
|
| 166 |
+
" optimizer.zero_grad()\n",
|
| 167 |
+
" if (i+1) % 50 == 0:\n",
|
| 168 |
+
" print(f\" [{controller.step}] φ={controller.phi:.3f} M={controller.mode}\")\n",
|
| 169 |
+
"\n",
|
| 170 |
+
"model_unified.eval()\n",
|
| 171 |
+
"trainer_unified = Trainer(\n",
|
| 172 |
+
" model=model_unified, eval_dataset=tokenized_test,\n",
|
| 173 |
+
" args=TrainingArguments(output_dir=\"./u\", per_device_eval_batch_size=16, fp16=True, report_to=None),\n",
|
| 174 |
+
" tokenizer=tokenizer, compute_metrics=compute_metrics\n",
|
| 175 |
+
")\n",
|
| 176 |
+
"results_unified = trainer_unified.evaluate()\n",
|
| 177 |
+
"print(f\"F1: {results_unified['eval_f1']:.3f} | Acc: {results_unified['eval_accuracy']:.3f}\")"
|
| 178 |
+
]
|
| 179 |
+
},
|
| 180 |
+
{
|
| 181 |
+
"cell_type": "markdown",
|
| 182 |
+
"metadata": {},
|
| 183 |
+
"source": [
|
| 184 |
+
"## Results"
|
| 185 |
+
]
|
| 186 |
+
},
|
| 187 |
+
{
|
| 188 |
+
"cell_type": "code",
|
| 189 |
+
"execution_count": null,
|
| 190 |
+
"metadata": {},
|
| 191 |
+
"outputs": [],
|
| 192 |
+
"source": [
|
| 193 |
+
"print(\"\\n📊 COMPARISON\")\n",
|
| 194 |
+
"print(\"| Method | F1 | Acc |\")\n",
|
| 195 |
+
"print(\"|----------|-------|-------|\")\n",
|
| 196 |
+
"print(f\"| Baseline | {results_base['eval_f1']:.3f} | {results_base['eval_accuracy']:.3f} |\")\n",
|
| 197 |
+
"print(f\"| Unified | {results_unified['eval_f1']:.3f} | {results_unified['eval_accuracy']:.3f} |\")\n",
|
| 198 |
+
"print(f\"\\nΔF1: {results_unified['eval_f1'] - results_base['eval_f1']:+.3f}\")\n",
|
| 199 |
+
"print(f\"Final φ: {controller.phi:.3f} | Mode: {controller.mode}\")"
|
| 200 |
+
]
|
| 201 |
+
}
|
| 202 |
+
],
|
| 203 |
+
"metadata": {
|
| 204 |
+
"kernelspec": {
|
| 205 |
+
"display_name": "Python 3",
|
| 206 |
+
"language": "python",
|
| 207 |
+
"name": "python3"
|
| 208 |
+
}
|
| 209 |
+
},
|
| 210 |
+
"nbformat": 4,
|
| 211 |
+
"nbformat_minor": 4
|
| 212 |
+
}
|