فاز 7 · درس 4

کدگذاری موقعیت در ترنسفورمر: سینوسی، RoPE و ALiBi

نوع
ساختنی
زمان
حدود 45 دقیقه
زبان‌ها
Python
پیش‌نیاز
فاز 7 · درس 02 (Self-Attention)، فاز 7 · درس 03 (Multi-Head Attention)
نمودار سه‌بعدی نشان‌دهنده بردارهای در حال چرخش ریاضی با زوایای مختلف در کنار امواج سینوسی و خطوط شیب‌دار متصل به هم
فهرست مطالب
  1. صورت مسئله
  2. مفاهیم پایه
  3. سینوسی مطلق
  4. RoPE
  5. ALiBi
  6. در سال 2026 سراغ کدام گزینه برویم؟
  7. پیاده‌سازی از صفر
  8. گام 1: کدگذاری مکانی سینوسی
  9. گام 2: اعمال RoPE روی Q و K
  10. گام 3: شیب‌ها و بایاس در ALiBi
  11. گام 4: اعتبارسنجی ویژگی فاصله‌ی نسبی در RoPE
  12. استفاده در عمل
  13. آماده‌سازی خروجی
  14. تمرین‌ها
  15. اصطلاحات کلیدی
  16. برای مطالعه‌ی بیشتر

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

در مدل‌های امروزی، انتخاب الگوریتم کدگذاری موقعیت نقش تعیین‌کننده‌ای در توانایی مدل برای مدیریت پنجره‌های متنی بزرگ (Context Window) ایفا می‌کند. روش‌های قدیمی سینوسی توانایی برون‌یابی ضعیفی داشتند، اما رویکردهای مدرنی مثل RoPE و ALiBi به استانداردی در مدل‌های متن‌باز تبدیل شده‌اند که امکان گسترش طول بافت را بدون نیاز به آموزش مجدد و با کمترین هزینه محاسباتی فراهم می‌کنند.

در این درس ساختار ریاضی و پیاده‌سازی پایتورچ سه رویکرد اصلی را گام‌به‌گام بررسی می‌کنیم: کدگذاری سینوسی کلاسیک، روش امبدینگ دورانی (RoPE) که در مدل‌هایی نظیر Llama و DeepSeek استفاده می‌شود، و مکانیزم مبتنی بر بایاس خطی (ALiBi). در نهایت، ترفندهای مقیاس‌پذیری مانند YaRN و NTK-aware را برای پردازش متن‌های طولانی یاد خواهید گرفت.

مکانیسم اتنشن (attention) نسبت به جایگشت ناوردا (permutation-invariant) است. بدون سیگنال موقعیت مکانی، جمله‌ی «The cat sat on the mat» با «mat the on sat cat the» خروجی کاملاً یکسانی تولید می‌کند. سه الگوریتم این مشکل را برطرف می‌کنند؛ هر کدام با دیدگاهی متفاوت درباره‌ی این‌که «موقعیت» اصلاً چه معنایی دارد.

صورت مسئله

اتنشن ضرب داخلی مقیاس‌شده (scaled dot-product attention) نسبت به ترتیب کاملاً کور است. ماتریس اتنشن softmax(Q K^T / √d) V صرفاً بر اساس شباهت‌های دوبه‌دو محاسبه می‌شود. اگر سطرهای X را بر بزنید، سطرهای خروجی هم دقیقاً به همان شکل جابه‌جا می‌شوند. درون سازوکار اتنشن، هیچ جزئی به موقعیت توکن‌ها اهمیتی نمی‌دهد.

این ویژگی برای مدل کیسه کلمات (bag-of-words) باگ محسوب نمی‌شود؛ اما برای زبان طبیعی، کد، صوت، ویدیو یا هر چیزی که ترتیب در آن معنا می‌سازد، نقصی مرگبار است.

راه‌حل این است که موقعیت را به شکلی به امبدینگ‌ها (embeddings) تزریق کنیم. در گذر زمان سه پاسخ متمایز شکل گرفته است:

  1. سینوسی مطلق (Vaswani 2017): افزودن sin/cos موقعیت به امبدینگ. ساده است و به پارامتر یادگیری‌پذیر نیاز ندارد، اما تعمیم‌پذیری (extrapolation) آن فراتر از طول دیده‌شده در آموزش بسیار ضعیف است.
  2. امبدینگ موقعیت دورانی یا RoPE (Su 2021): چرخاندن بردارهای Q و K با زاویه‌ای متناسب با موقعیت. این روش موقعیت نسبی را مستقیماً در ضرب داخلی (dot product) کدگذاری می‌کند و در سال 2026 رویکرد غالب بازار است.
  3. اتنشن با بایاس‌های خطی یا ALiBi (Press 2022): حذف کامل امبدینگ موقعیت؛ افزودن یک جریمه‌ی خطی بر اساس فاصله به امتیازهای اتنشن در هر سر (head). تعمیم‌پذیری طول این رویکرد فوق‌العاده است.

تا سال 2026، تقریباً تک‌تک مدل‌های باز پیشرو از RoPE استفاده می‌کنند: Llama 2/3/4، Qwen 2/3، Mistral، Mixtral، DeepSeek-V3 و Kimi. تنها تعداد انگشت‌شماری از مدل‌های با بافت طولانی (long-context) سراغ ALiBi یا گونه‌های مدرن آن رفته‌اند. روش سینوسی مطلق دیگر جنبّه‌ی تاریخی پیدا کرده است.

مفاهیم پایه

مقایسه سینوسی مطلق در برابر دوران‌های RoPE در برابر بایاس فاصله‌ای ALiBi

سینوسی مطلق

از قبل ماتریس ثابت PE را در ابعاد (max_len, d_model) محاسبه می‌کنیم:

PE(pos,2i)=sin⁡(pos/100002i/dmodel)PE(pos,2i+1)=cos⁡(pos/100002i/dmodel)\begin{aligned} PE_{(pos, 2i)} &= \sin\left(pos / 10000^{2i / d_{\text{model}}}\right) \\ PE_{(pos, 2i+1)} &= \cos\left(pos / 10000^{2i / d_{\text{model}}}\right) \end{aligned}

سپس قبل از ورود به اتنشن، مقدار X' = X + PE[:N] را به دست می‌آوریم. هر بُعد یک موج سینوسی با بسامدی متفاوت است. مدل یاد می‌گیرد موقعیت را از روی الگوی فاز بخواند. این روش فراتر از max_len به بن‌بست می‌خورد؛ وقتی مدل فقط موقعیت‌های 0 تا 2047 را دیده باشد، هیچ چیزی به آن یاد نداده که در موقعیت 2048 چه اتفاقی می‌افتد.

RoPE

بردارهای Q و K را می‌چرخانیم (نه امبدینگ‌ها را). برای یک جفت بعد (2i,2i+1)(2i, 2i+1):

[q2i′q2i+1′]=[cos⁡(pos⋅θi)−sin⁡(pos⋅θi)sin⁡(pos⋅θi)cos⁡(pos⋅θi)][q2iq2i+1]θi=base−2i/dhead,base=10000 by default\begin{bmatrix} q'_{2i} \\ q'_{2i+1} \end{bmatrix} = \begin{bmatrix} \cos(pos \cdot \theta_i) & -\sin(pos \cdot \theta_i) \\ \sin(pos \cdot \theta_i) & \cos(pos \cdot \theta_i) \end{bmatrix} \begin{bmatrix} q_{2i} \\ q_{2i+1} \end{bmatrix} \qquad \theta_i = \text{base}^{-2i / d_{\text{head}}}, \quad \text{base} = 10000 \text{ by default}

همین دوران را روی کلیدها (K) با موقعیت pos_k اعمال می‌کنیم. ضرب داخلی qm′⋅kn′q'_m \cdot k'_n تنها تابعی از (m−n)(m - n) می‌شود. یعنی: امتیاز اتنشن تنها به فاصله‌ی نسبی وابسته است، هرچند مبنای دوران‌ها بر اساس موقعیت‌های مطلق بوده است؛ ترفندی بی‌نهایت هوشمندانه.

توسعه‌ی RoPE: برای برون‌یابی به بافت‌های طولانی‌تر بدون بازآموزی، می‌توان base را مقیاس‌بندی کرد (روش‌های NTK-aware، YaRN و LongRoPE). مدل Llama 3 پنجره‌ی بافت خود را با همین ترفند از 8K به 128K رساند.

ALiBi

ترفند امبدینگ را کاملاً کنار بگذارید و مستقیماً روی امتیازهای اتنشن بایاس اعمال کنید:

attn_score[i,j]=qi⋅kjd−mh⋅∣i−j∣\text{attn\_score}[i, j] = \frac{q_i \cdot k_j}{\sqrt{d}} - m_h \cdot |i - j|

در اینجا mhm_h شیب خطی اختصاصی برای هر سر است (مثلاً 1/28h/H1 / 2^{8h/H}). توکن‌های نزدیک‌تر تقویت می‌شوند و توکن‌های دورتر جریمه می‌خورند. این روش هیچ هزینه‌ای در زمان آموزش ندارد. مقاله‌ی اصلی نشان می‌دهد که تعمیم‌پذیری طول آن، سینوسی را پشت سر می‌گذارد و در طول آموزش اولیه با RoPE برابری می‌کند.

در سال 2026 سراغ کدام گزینه برویم؟

گونه تعمیم‌پذیری طول هزینه آموزش استفاده‌شده در
سینوسی مطلق ضعیف رایگان ترنسفورمر اولیه، نسخه‌های نخستین BERT
یادگیری‌پذیر مطلق ندارد ناچیز GPT-2، GPT-3
RoPE با مقیاس‌بندی خوب است رایگان Llama 2/3/4، Qwen 2/3، Mistral، DeepSeek-V3، Kimi
RoPE + YaRN عالی در مرحله‌ی فاین‌تیونینگ Qwen2-1M، Llama 3.1 128K
ALiBi عالی رایگان BLOOM، MPT، Baichuan

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

موقعیت چرخشیموقعیت و پایه را بکشید
ROTARY POSITIONRoPE rotates each pair of dimensions by an angle that grows with position. Low dimensions use high frequencies (rotate fast, encode nearby order); high dimensions use low frequencies (rotate slowly, encode long-range distance). Raising the base stretches every wavelength, extending usable context.
روش RoPE هر جفت از ابعاد را با زاویه‌ای می‌چرخاند که با افزایش موقعیت رشد می‌کند. ابعاد پایین از بسامدهای بالا استفاده می‌کنند (سریع می‌چرخند و ترتیب مجاور را کدگذاری می‌کنند)؛ ابعاد بالا از بسامدهای پایین استفاده می‌کنند (به‌آرامی می‌چرخند و فاصله‌های دوربرد را کدگذاری می‌کنند). افزایش پایه، تمام طول‌موج‌ها را کشیده و زمینه‌ی قابل استفاده را گسترش می‌دهد.

پیاده‌سازی از صفر

گام 1: کدگذاری مکانی سینوسی

کد مربوطه را در code/main.py ببینید. یک محاسبه‌ی جمع‌وجور 4 خطی:

def sinusoidal(N, d):
    pe = [[0.0] * d for _ in range(N)]
    for pos in range(N):
        for i in range(d // 2):
            theta = pos / (10000 ** (2 * i / d))
            pe[pos][2 * i]     = math.sin(theta)
            pe[pos][2 * i + 1] = math.cos(theta)
    return pe

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

گام 2: اعمال RoPE روی Q و K

روش RoPE مستقیماً درجا (in-place) روی Q و K اعمال می‌شود. برای هر جفت از ابعاد:

def apply_rope(x, pos, base=10000):
    d = len(x)
    out = list(x)
    for i in range(d // 2):
        theta = pos / (base ** (2 * i / d))
        c, s = math.cos(theta), math.sin(theta)
        a, b = x[2 * i], x[2 * i + 1]
        out[2 * i]     = a * c - b * s
        out[2 * i + 1] = a * s + b * c
    return out

نکته‌ی حیاتی: دقیقاً همین تابع را روی Q در موقعیت mm و K در موقعیت nn اعمال کنید. ضرب داخلی آن‌ها فاکتور cos⁡((m−n)⋅θi)\cos((m-n) \cdot \theta_i) را در هر جفت مختصات دریافت می‌کند. به این ترتیب اتنشن موقعیت نسبی را رایگان یاد می‌گیرد.

گام 3: شیب‌ها و بایاس در ALiBi

def alibi_bias(n_heads, seq_len):
    # slope_h = 2 ** (-8 * h / n_heads) for h = 1..n_heads
    slopes = [2 ** (-8 * (h + 1) / n_heads) for h in range(n_heads)]
    bias = []
    for m in slopes:
        row = [[-m * abs(i - j) for j in range(seq_len)] for i in range(seq_len)]
        bias.append(row)
    return bias  # add to attention scores before softmax

مقدار bias[h] را به ماتریس امتیاز اتنشن با ابعاد (seq_len, seq_len) در سر h اضافه کنید و سپس سافت‌مکس بگیرید.

گام 4: اعتبارسنجی ویژگی فاصله‌ی نسبی در RoPE

دو بردار تصادفی a, b بردارید. آن‌ها را با (pos_a, pos_b) بچرخانید؛ سپس همین کار را با (pos_a + k, pos_b + k) انجام دهید. ضرب داخلی در هر دو حالت باید در حد خطای ممیز شناور یکسان دربیاید. اصلاً تمام فلسفه‌ی وجودی RoPE همین ویژگی است: این‌که نسبت به جابه‌جایی مطلق ناورداست و فقط فاصله‌ی نسبی اهمیت دارد.

استفاده در عمل

در PyTorch 2.5 به بعد، توابع کمکی RoPE در torch.nn.functional در دسترس هستند. بیشتر کدهای پروداکشن از flash_attn یا xformers استفاده می‌کنند که در آن‌ها RoPE مستقیماً درون کرنل (kernel) اتنشن اعمال می‌شود.

from transformers import AutoModel
model = AutoModel.from_pretrained("meta-llama/Llama-3.2-3B")
# model.config.rope_scaling → {"type": "yarn", "factor": 32.0, "original_max_position_embeddings": 8192}

ترفندهای بافت طولانی در سال 2026:

  • درون‌یابی آگاه از NTK (یا NTK-aware interpolation): هنگام ارتقا از 4K به بالای 16K، مقدار base را به صورت base * (scale_factor)^(d/(d-2)) تغییر مقیاس دهید.
  • روش YaRN: روش هوشمندانه‌تری از درون‌یابی که آنتروپی اتنشن را در بافت‌های طولانی دست‌نخورده نگه می‌دارد. مدل Llama 3.1 128K از همین تکنیک استفاده می‌کند.
  • روش LongRoPE: رویکرد مایکروسافت در سال 2024 که با جست‌وجوی تکاملی، ضرایب مقیاس‌بندی مجزا برای هر بعد پیدا می‌کند. Phi-3-Long از آن بهره می‌برد.
  • درون‌یابی موقعیت + فاین‌تیونینگ: کافی است موقعیت‌ها را به نسبت ضریب گسترش فشرده کنید و مدل را به اندازه‌ی 1 تا 5 میلیارد توکن فاین‌تیون کنید؛ نتیجه‌اش به‌طرز شگفت‌آوری عالی است.

آماده‌سازی خروجی

فایل outputs/skill-positional-encoding-picker.md را بررسی کنید. این مهارت با توجه به طول بافت هدف، نیازهای برون‌یابی و بودجه‌ی آموزش، استراتژی کدگذاری موقعیت مناسب را برای مدل جدید انتخاب می‌کند.

تمرین‌ها

  1. ساده. ماتریس سینوسی PE را به‌صورت هیت‌مپ با ابعاد max_len=512, d=128 رسم کنید. بررسی کنید که آیا با افزایش ایندکس بعد، خطوط واقعاً پهن‌تر می‌شوند یا نه.
  2. متوسط. مقیاس‌بندی NTK-aware را برای RoPE پیاده‌سازی کنید. یک مدل زبانی کوچک را روی توالی‌هایی به طول 256 آموزش دهید، سپس روی طول 1024 با و بدون مقیاس‌بندی تست بگیرید و پرپلکسیتی (perplexity) را بسنجید.
  3. سخت. هر دو روش ALiBi و RoPE را در یک ماژول اتنشن یکسان پیاده کنید. یک ترنسفورمر 4 لایه را برای مسئله‌ی کپی‌کردن (copy task) در توالی‌هایی به طول 512 آموزش دهید. در زمان تست، طول را به 2048 برون‌یابی کنید و میزان افت عملکرد دو مدل را بسنجید.

اصطلاحات کلیدی

اصطلاح در گفت‌وگوها معنای فنی دقیق
Positional encoding «ترتیب رو به اتنشن می‌فهمونه» هر سیگنالی که برای کدگذاری موقعیت به امبدینگ‌ها یا اتنشن اضافه شود.
Sinusoidal «همون اولیه‌ست» توابع sin/cos با فرکانس‌های هندسی که به امبدینگ اضافه می‌شوند؛ تعمیم‌پذیری طول ندارند.
RoPE «امبدینگ دورانی» چرخاندن Q و K با زاویه‌ای وابسته به موقعیت؛ فاصله‌ی نسبی مستقیماً در ضرب داخلی کدگذاری می‌شود.
ALiBi «ترفند بایاس خطی» افزودن −m⋅∣i−j∣-m \cdot \lvert i-j \rvert به امتیازهای اتنشن؛ بدون نیاز به امبدینگ، با قابلیت برون‌یابی عالی.
base «پیچ تنظیم RoPE» ضریب بسامد در RoPE؛ با بالا بردن آن در زمان استنتاج، طول بافت را افزایش می‌دهند.
NTK-aware «ترفند مقیاس‌بندی RoPE» تغییر مقیاس base تا هنگام باز شدن پنجره‌ی بافت، ابعاد فرکانس‌بالا فشرده نشوند.
YaRN «اون مدل پیشرفته‌تره» درون‌یابی و برون‌یابی تفکیک‌شده برای هر بعد، طوری که آنتروپی اتنشن حفظ شود.
Extrapolation «برای طول‌های بالاتر هم جواب میده» توانایی ساختار کدگذاری موقعیت در تولید خروجی درست، فراتر از max_len دیده‌شده در زمان آموزش.

برای مطالعه‌ی بیشتر

سؤالات متداول

چرا مکانیسم اتنشن به کدگذاری موقعیت نیاز دارد؟

چون اتنشن ضرب داخلی مقیاس‌شده نسبت به جایگشت ناوردا (permutation-invariant) است و ترتیب کلمات را تشخیص نمی‌دهد. بدون کدگذاری موقعیت، جابه‌جا شدن کلمات خروجی را تغییر نمی‌دهد.

تفاوت اصلی RoPE با کدگذاری سینوسی چیست؟

کدگذاری سینوسی مقادیر ثابتی را مستقیماً به امبدینگ ورودی جمع می‌کند، اما RoPE بردارهای Query و Key را بر اساس زاویه‌ای متناسب با موقعیت می‌چرخاند و موقعیت نسبی را مستقیماً در ضرب داخلی منعکس می‌کند.

چرا مدل‌های مدرن مثل Llama از RoPE استفاده می‌کنند؟

RoPE سربار پارامتری ندارد، موقعیت نسبی را به خوبی کدگذاری می‌کند و به کمک تغییر مقیاس ابرپارامتر base (مانند رویکردهای YaRN و NTK-aware) می‌توان طول پنجره بافت را به سادگی گسترش داد.

روش ALiBi چگونه موقعیت توکن‌ها را مشخص می‌کند؟

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

ما رو توی گوگل بیشتر ببین

با افزودن نکست ادمین به «منابع ترجیحی» گوگل، درس‌ها و مطالب ما را در بخش اخبار برتر جستجو بیشتر می‌بینید.