تنظیم پیشوند (Prefix Tuning) یکی از روش‌های پارامتر-کارآمد برای تخصصی‌سازی مدل‌های زبانی بزرگ است که در آن، به‌جای آموزش کامل مدل، تنها یک پیشوند کوچک آموزش‌پذیر در ابتدای ورودی قرار می‌گیرد.
این روش، به‌دلیل کاهش شدید تعداد پارامترهای آموزش‌پذیر، هزینه و زمان آموزش را به‌طور چشمگیری کاهش می‌دهد.
تنظیم پیشوند، هم برای مدل‌های encoder-decoder و هم برای مدل‌های decoder-only کاربرد دارد.
این روش، در پروژه‌هایی که با محدودیت منابع محاسباتی مواجه هستند، انتخاب اول است.
این راهنما مکانیزم، پیاده‌سازی و کاربردهای تنظیم پیشوند را به‌صورت فنی بررسی می‌کند.

تنظیم پیشوند (Prefix Tuning) یکی از تکنیک‌های پیشرفته در حوزه بهینه‌سازی مدل‌های زبانی است که به‌عنوان یک جایگزین پارامتر-کارآمد برای Fine-tuning کامل مطرح می‌شود. این تکنیک، اولین بار در مقاله‌ای با عنوان «Prefix-Tuning: Optimizing Continuous Prompts for Generation» در سال ۲۰۲۱ معرفی شد و از آن زمان، به یکی از پرکاربردترین روش‌ها در تخصصی‌سازی مدل‌های زبانی تبدیل شده است. برای درک این تکنیک، ابتدا باید با تفاوت پرامپت سخت و نرم و تنظیم پرامپت مبتنی بر گرادیان آشنا باشیم.

در پروژه‌هایی که با محدودیت منابع GPU مواجه بودیم، تنظیم پیشوند ابزار اصلی برای تخصصی‌سازی مدل بدون نیاز به زیرساخت سنگین بوده است. این تکنیک، به‌جای تغییر میلیون‌ها پارامتر، تنها هزاران پارامتر را آموزش می‌دهد و همین ویژگی، آن را به گزینه‌ای جذاب برای تیم‌های کوچک تبدیل می‌کند. اگر با تفاوت پرامپت نویسی و تنظیم دقیق آشنا هستید، آماده‌اید تا به لایه تنظیم پیشوند وارد شوید.

تنظیم پیشوند را می‌توان با اضافه کردن یک مقدمه کوتاه به یک کتاب مقایسه کرد: بدون تغییر محتوای اصلی، خواننده را به سمت تفسیر خاصی هدایت می‌کند. در سامانه‌های LLM، این مقدمه همان پیشوند آموزش‌پذیر است. برای مطالعه بیشتر درباره مبانی، می‌توانید صفحه Fine-tuning را در ویکی‌پدیا ببینید.

تنظیم پیشوند دقیقاً چیست؟

تنظیم پیشوند، روشی برای تخصصی‌سازی مدل‌های زبانی است که در آن، به‌جای آموزش کامل مدل، یک پیشوند کوچک از بردارهای آموزش‌پذیر در ابتدای ورودی هر لایه از مدل قرار می‌گیرد و در طول فرایند آموزش، تنها این پیشوند بهینه می‌شود.

در این روش، وزن‌های اصلی مدل ثابت می‌مانند و تنها پیشوند آموزش می‌بیند. این ویژگی، تنظیم پیشوند را از Fine-tuning کامل متمایز می‌کند.

اجزای تنظیم پیشوند

  • پیشوند (Prefix): یک دنباله از بردارهای آموزش‌پذیر.
  • مدل پایه: مدل زبانی از پیش آموزش‌دیده که وزن‌هایش ثابت است.
  • فرایند آموزش: فرایندی که تنها پیشوند را بهینه می‌کند.
  • خروجی: یک پیشوند آموزش‌دیده که در زمان استنتاج به ابتدای ورودی اضافه می‌شود.

تفاوت با Prompt Tuning

در Prompt Tuning، پیشوند تنها در لایه ورودی قرار می‌گیرد. در تنظیم پیشوند، پیشوند در همه لایه‌های مدل قرار می‌گیرد. این تفاوت، تنظیم پیشوند را قدرتمندتر می‌کند، اما هزینه محاسباتی بیشتری نیز دارد.

تنظیم پیشوند، تخصصی‌سازی مدل با کمتر از یک درصد پارامترهای اصلی است.

چرا تنظیم پیشوند اهمیت دارد؟

تنظیم پیشوند به چند دلیل اهمیت دارد:

کاهش پارامترهای آموزش‌پذیر

در تنظیم پیشوند، تنها بخش کوچکی از پارامترها (معمولاً کمتر از ۱ درصد) آموزش می‌بینند. این کاهش، هزینه و زمان آموزش را به‌طور چشمگیری کاهش می‌دهد.

کاهش حافظه موردنیاز

Fine-tuning کامل، نیازمند ذخیره‌سازی گرادیان‌ها و حالت‌های بهینه‌ساز برای همه پارامترهاست. تنظیم پیشوند، این نیاز را به بخش کوچکی محدود می‌کند.

حفظ عملکرد مدل پایه

در تنظیم پیشوند، وزن‌های مدل پایه ثابت می‌مانند. این ویژگی، مانع از دست رفتن دانش مدل پایه می‌شود.

امکان تخصصی‌سازی چندگانه

با تنظیم پیشوند، می‌توان یک مدل پایه واحد را برای چندین دامنه تخصصی‌سازی کرد، با آموزش چند پیشوند جداگانه. هر پیشوند، در زمان نیاز به مدل اضافه می‌شود.

کارایی در محیط‌های با منابع محدود

در محیط‌هایی که دسترسی به GPUهای قوی محدود است، تنظیم پیشوند یک گزینه عملی است.

ویژگیFine-tuning کاملتنظیم پیشوند
پارامترهای آموزش‌پذیر۱۰۰٪< ۱٪
حافظه موردنیازبالاپایین
زمان آموزشزیادکم
حفظ دانش پایهممکن است از دست برودحفظ می‌شود
چند تخصص با یک مدلنیازمند چند مدلنیازمند چند پیشوند

مکانیزم فنی

مکانیزم تنظیم پیشوند، بر پایه اضافه کردن بردارهای آموزش‌پذیر به هر لایه از مدل است.

ساختار پیشوند

پیشوند، یک تانسور با ابعاد (n_tokens, n_layers, hidden_dim) است. در هر لایه از مدل، یک بخش از این تانسور به عنوان کلید و مقدار به مکانیزم توجه اضافه می‌شود.

روند آموزش

  1. وزن‌های مدل پایه بارگذاری و ثابت می‌شوند.
  2. پیشوند با مقادیر تصادفی مقداردهی اولیه می‌شود.
  3. در هر مرحله آموزش، پیشوند به ورودی اضافه می‌شود.
  4. گرادیان‌ها تنها برای پیشوند محاسبه می‌شوند.
  5. پیشوند با استفاده از گرادیان کاهشی بهینه می‌شود.

پیاده‌سازی

import torch
import torch.nn as nn

class PrefixTuning(nn.Module):
    def __init__(self, n_tokens, n_layers, hidden_dim):
        super().__init__()
        self.prefix = nn.Parameter(
            torch.randn(n_tokens, n_layers, hidden_dim)
        )

    def get_prefix(self, layer_idx):
        return self.prefix[:, layer_idx, :]

این پیاده‌سازی، یک پیشوند چندلایه می‌سازد که در هر لایه به مکانیزم توجه اضافه می‌شود.

مکانیزم توجه با پیشوند

در مکانیزم توجه، پیشوند به عنوان کلید و مقدار اضافه می‌شود:

Key = concat(prefix_key, input_key)
Value = concat(prefix_value, input_value)
Attention = softmax(Q @ K.T) @ V

این ساختار، به مدل اجازه می‌دهد از پیشوند به عنوان یک زمینه اضافی استفاده کند.

معماری و اجزا

تنظیم پیشوند از چند جزء اصلی تشکیل می‌شود:

پیشوند چندلایه

برخلاف Prompt Tuning که تنها در لایه ورودی عمل می‌کند، تنظیم پیشوند در همه لایه‌ها حضور دارد. این ویژگی، قدرت تنظیم را افزایش می‌دهد.

MLP بازتعریف‌کننده

در برخی پیاده‌سازی‌ها، از یک شبکه MLP کوچک برای تولید پیشوند از یک بردار کوچک‌تر استفاده می‌شود. این رویکرد، پارامترهای آموزش‌پذیر را بیشتر کاهش می‌دهد.

پیشوند کلید و مقدار

در هر لایه، پیشوند به دو بخش کلید و مقدار تقسیم می‌شود. این تقسیم، با ساختار مکانیزم توجه مطابقت دارد.

کنترل طول پیشوند

طول پیشوند، یکی از پارامترهای کلیدی است. طول کوتاه‌تر، سرعت بیشتر اما دقت کمتر دارد. طول بلندتر، دقت بیشتر اما هزینه بالاتر دارد.

پیاده‌سازی گام‌به‌گام

پیاده‌سازی تنظیم پیشوند در چند گام انجام می‌شود:

گام اول: بارگذاری مدل پایه

from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b")

# Freeze model weights
for param in model.parameters():
    param.requires_grad = False

گام دوم: ساخت پیشوند

n_tokens = 20
n_layers = model.config.num_hidden_layers
hidden_dim = model.config.hidden_size

prefix = PrefixTuning(n_tokens, n_layers, hidden_dim)

گام سوم: تزریق پیشوند

پیشوند باید در مکانیزم توجه هر لایه تزریق شود. این کار با تغییر forward pass مدل انجام می‌شود یا با استفاده از کتابخانه‌هایی مانند PEFT.

گام چهارم: آموزش

optimizer = torch.optim.AdamW(prefix.parameters(), lr=1e-3)

for batch in dataloader:
    optimizer.zero_grad()
    outputs = model(batch["input_ids"], prefix=prefix)
    loss = compute_loss(outputs, batch["labels"])
    loss.backward()
    optimizer.step()

گام پنجم: ذخیره و بارگذاری

# Save
torch.save(prefix.state_dict(), "prefix.pt")

# Load
prefix = PrefixTuning(n_tokens, n_layers, hidden_dim)
prefix.load_state_dict(torch.load("prefix.pt"))

این ساختار، امکان ذخیره و بارگذاری پیشوند را فراهم می‌کند. نکته مهم این است که تنها پیشوند ذخیره می‌شود، نه کل مدل.

مقایسه با سایر روش‌ها

تنظیم پیشوند، یکی از چندین روش پارامتر-کارآمد است.

Prefix Tuning در مقابل Prompt Tuning

در Prompt Tuning، پیشوند تنها در لایه ورودی قرار می‌گیرد. در Prefix Tuning، پیشوند در همه لایه‌ها حضور دارد. Prefix Tuning قدرتمندتر اما پرهزینه‌تر است. برای جزئیات، پست تفاوت پرامپت سخت و نرم را ببینید.

Prefix Tuning در مقابل P-Tuning

در P-Tuning، از یک ساختار پویا برای تولید پیشوند استفاده می‌شود. برای جزئیات، پست روش P-tuning در پرامپت نویسی را ببینید.

Prefix Tuning در مقابل LoRA

LoRA، بر روی ماتریس‌های وزن مدل عمل می‌کند. Prefix Tuning، بر روی ورودی هر لایه عمل می‌کند. هر دو روش پارامتر-کارآمد هستند اما مکانیزم متفاوتی دارند.

Prefix Tuning در مقابل Adapter

Adapter، لایه‌های کوچک اضافی به مدل اضافه می‌کند. Prefix Tuning، بردارهای اضافی به ورودی اضافه می‌کند.

روشپارامتر آموزش‌پذیرمکانیزم
Fine-tuning کامل۱۰۰٪آموزش همه وزن‌ها
Prefix Tuning< ۱٪بردار در همه لایه‌ها
Prompt Tuning< ۰.۱٪بردار در لایه ورودی
P-Tuning< ۱٪ساختار پویا
LoRA< ۱٪ماتریس‌های کم‌رتبه

کاربردهای عملی

تنظیم پیشوند در چند سناریو کاربرد دارد:

تخصصی‌سازی دامنه‌ای

در پروژه‌هایی که مدل باید در یک دامنه خاص تخصصی شود، تنظیم پیشوند گزینه مناسبی است.

چند تخصص با یک مدل

با آموزش چند پیشوند جداگانه، می‌توان یک مدل پایه واحد را برای چند دامنه تخصصی کرد.

محیط‌های با منابع محدود

در محیط‌هایی که دسترسی به GPUهای قوی محدود است، تنظیم پیشوند یک گزینه عملی است.

شخصی‌سازی

در سامانه‌هایی که هر کاربر نیازمند مدل شخصی‌سازی‌شده است، تنظیم پیشوند به‌عنوان روش کارآمد مطرح است.

حریم خصوصی

در سامانه‌هایی که داده‌ها نباید از سازمان خارج شوند، تنظیم پیشوند یک گزینه امن است.

پروژه‌های تحقیقاتی

در پژوهش‌هایی که به بررسی رفتار مدل نیاز دارند، تنظیم پیشوند یک ابزار مفید است.

پارامترهای کلیدی

تنظیم پیشوند، چند پارامتر کلیدی دارد:

طول پیشوند

طول پیشوند (n_tokens) تعیین می‌کند چه تعداد بردار به مدل اضافه شود. مقادیر معمول بین ۱۰ تا ۱۰۰ است.

عمق پیشوند

تعیین می‌کند پیشوند در چه لایه‌هایی اضافه شود. می‌توان پیشوند را تنها در لایه‌های اول، آخر یا همه لایه‌ها اضافه کرد.

نرخ یادگیری

نرخ یادگیری مناسب برای آموزش پیشوند، معمولاً بین 1e-3 تا 1e-2 است.

MLP بازتعریف

در برخی پیاده‌سازی‌ها، از یک MLP کوچک برای تولید پیشوند از یک بردار کوچک‌تر استفاده می‌شود. این رویکرد، پارامترها را بیشتر کاهش می‌دهد.

محدودیت‌ها

تنظیم پیشوند، محدودیت‌های خاص خود را دارد:

  • نیاز به وزن مدل: برای استفاده از تنظیم پیشوند، باید به وزن‌های مدل دسترسی داشته باشید.
  • پیچیدگی پیاده‌سازی: تنظیم پیشوند پیچیده‌تر از Prompt Tuning است.
  • حافظه در زمان استنتاج: در زمان استنتاج، پیشوند باید در حافظه نگهداری شود.
  • عدم انتقال‌پذیری: پیشوند آموزش‌دیده برای یک مدل، در مدل دیگر قابل استفاده نیست.
  • پیچیدگی تفسیر: پیشوند غیرقابل خواندن است و تفسیر آن دشوار است.
  • پایداری در طول آموزش: در برخی موارد، آموزش پیشوند پایداری کمتری دارد.

پرسش‌های پرتکرار درباره تنظیم پیشوند

تنظیم پیشوند چه تفاوتی با Prompt Tuning دارد؟

در Prompt Tuning، پیشوند تنها در لایه ورودی قرار می‌گیرد. در Prefix Tuning، پیشوند در همه لایه‌ها حضور دارد.

آیا تنظیم پیشوند جایگزین Fine-tuning کامل است؟

در بسیاری از موارد، بله. تنظیم پیشوند می‌تواند عملکردی مشابه Fine-tuning کامل با هزینه کمتر ارائه دهد.

چند پارامتر در تنظیم پیشوند آموزش می‌بیند؟

معمولاً کمتر از ۱ درصد پارامترهای مدل پایه. مقدار دقیق به طول پیشوند و تعداد لایه‌ها بستگی دارد.

آیا تنظیم پیشوند با API قابل استفاده است؟

خیر. تنظیم پیشوند نیازمند دسترسی به وزن مدل است.

آیا تنظیم پیشوند بر کیفیت خروجی اثر منفی دارد؟

در بسیاری از موارد، تنظیم پیشوند کیفیت مشابه Fine-tuning کامل ارائه می‌دهد. اما در وظایف بسیار پیچیده، ممکن است Fine-tuning کامل عملکرد بهتری داشته باشد.

طول پیشوند چقدر باید باشد؟

طول به پیچیدگی وظیفه بستگی دارد. مقادیر معمول بین ۱۰ تا ۱۰۰ توکن است.

آیا تنظیم پیشوند بر امنیت اثر دارد؟

تنظیم پیشوند غیرقابل خواندن است و بررسی امنیتی آن دشوارتر است. برای جزئیات، پست بهترین روش‌های امنیت پرامپت را ببینید.

آیا تنظیم پیشوند با LoRA قابل ترکیب است؟

بله. ترکیب این دو روش می‌تواند دقت را بیشتر کند.

آیا تنظیم پیشوند برای همه مدل‌ها کاربرد دارد؟

تنظیم پیشوند برای اکثر مدل‌های transformer کاربرد دارد، اما پیاده‌سازی آن بین مدل‌ها متفاوت است.

چطور پیشوند آموزش‌دیده را ذخیره کنیم؟

تنها پارامترهای پیشوند ذخیره می‌شوند، نه کل مدل. این ویژگی، حجم ذخیره‌سازی را به‌طور چشمگیری کاهش می‌دهد.

آیا تنظیم پیشوند بر هزینه استنتاج اثر دارد؟

بله. حضور پیشوند در حافظه، هزینه استنتاج را کمی افزایش می‌دهد. اما این افزایش، در مقایسه با Fine-tuning کامل ناچیز است.

نتیجه‌گیری کاربردی

تنظیم پیشوند یکی از روش‌های کارآمد برای تخصصی‌سازی مدل‌های زبانی است که با آموزش یک پیشوند کوچک، عملکرد مدل را در دامنه خاص بهبود می‌دهد. این روش، نیازمند دسترسی به وزن مدل است اما در مقایسه با Fine-tuning کامل، هزینه و زمان کمتری نیاز دارد. تنظیم پیشوند، در پروژه‌هایی که با محدودیت منابع مواجه هستند، انتخاب اول است.

تنظیم پیشوند، تخصصی‌سازی مدل با کمتر از یک درصد پارامترهای اصلی است.

در پروژه‌هایی که با محدودیت GPU مواجه بودیم، تنظیم پیشوند ابزار اصلی برای تخصصی‌سازی مدل بوده است. توصیه می‌کنم این تکنیک را با Prompt Tuning و LoRA مقایسه کنید و بر اساس نیاز پروژه، انتخاب کنید. اگر تجربه‌ای در پیاده‌سازی تنظیم پیشوند در پروژه‌های واقعی دارید، برای ما جالب است بدانید کدام پارامتر بیشترین تأثیر را بر کیفیت خروجی داشته است.