Simo76 commited on
Commit
c567b69
·
1 Parent(s): 28c5d43

Add Unified LoRA MRPC Benchmark Example Notebook

Browse files

This notebook demonstrates Unified LoRA on the GLUE MRPC (paraphrase detection) task, including setup, data loading, and evaluation of both baseline and unified LoRA models.

Files changed (1) hide show
  1. 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
+ }