چیت‌شیت

ترنسفورمرها و اتنشن

Transformers and Attention

محاسبه اتنشن، اعمال ماسک، تفکیک هدها، افزودن موقعیت‌ها و چیدن بلوک‌ها روی هم. PyTorch و NumPy برگرفته از درس‌ها.

  • ۱۱ بخش
  • ۱۴ درس مرتبط
  • کد و دستورها عیناً از دوره‌ی اصلی
فهرست مطالب
  1. یک بلوک رمزگشای پیش‌نرمال‌سازی لایه‌ای (Pre-LN)
  2. گذر رو به جلو (forward) اتنشن
  3. ابعاد
  4. فرمول‌های کلیدی
  5. وظایف در کد
  6. گذر رو به جلو MultiHeadSelfAttention
  7. پیش‌فرض‌ها و اعداد
  8. عیب‌یابی
  9. کوته‌نوشت‌ها
  10. پرسش‌ها
  11. نکات کاربردی

یک بلوک رمزگشای پیش‌نرمال‌سازی لایه‌ای (Pre-LN)

معماری
x 12امبدینگ ورودیتوکن + موقعیت، B، T، DLayerNorm 1اتنشن علّی چندسرQ، K، V و ماسکافزودن اتصال باقی‌مانده (residual)x + attn(ln1(x))LayerNorm 2MLP موقعیت‌محورD به 4D به Dافزودن اتصال باقی‌مانده (residual)x + mlp(ln2(x))LayerNorm نهایی، LM headلاجیت‌ها B، T، 50257

گذر رو به جلو (forward) اتنشن

گام‌به‌گام
  1. qkv_projیک لایه خطی (B, T, D) را به (B, T, 3 * D) نگاشت می‌کند.
  2. Splitتفکیک به Q، K، V و سپس تغییر شکل به (B, H, T, d_head).
  3. Scoresعملیات q @ k.transpose(-2, -1) ابعاد (B, H, T, T) را می‌دهد.
  4. Scaleتقسیم امتیازها بر sqrt(d_head).
  5. Mask and softmaxدرایه‌های آینده مقدار -inf می‌گیرند، سپس سافت‌مکس روی کلیدها.
  6. Weighted sumمحاسبه weights @ V، سپس merge هدها به (B, T, D).
  7. out_projیک لایه خطی (D, D) هدها را ترکیب می‌کند.

ابعاد

دستورها
Tensorشکل (Shape)
Token ids(B, T)، int64
Token embedding matrix(V, D)
Input to attention(B, T, D)
QKV projection output(B, T, 3 * D)
Q, K, V per head(B, H, T, d_head)، d_head = D // H
Scores and weights(B, H, T, T)
Logits(B, T, 50257) برای GPT-2 small
Cross attention weights(batch, T_dec, T_enc)

فرمول‌های کلیدی

مفهوم‌ها
Attention
$\text{Attention}(Q, K, V) = \mathop{\mathrm{softmax}}\left( \frac{Q K^T}{\sqrt{d_k}} \right) V$
Head width
$d_{\text{head}} = d_{\text{model}} / n_{\text{heads}}$
Causal mask
$M_{ij} = \begin{cases} 0 & \text{if } j \le i \\ -\infty & \text{if } j > i \end{cases}$
Sinusoidal even
$PE_{(pos, 2i)} = \sin\left(pos / 10000^{2i / d_{\text{model}}}\right)$
Sinusoidal odd
$PE_{(pos, 2i+1)} = \cos\left(pos / 10000^{2i / d_{\text{model}}}\right)$
RoPE angle
$\theta_i = \text{base}^{-2i / d_{\text{head}}}$. امتیاز به $(m - n)$ بستگی دارد.
ALiBi
$\text{attn\_score}[i, j] = \frac{q_i \cdot k_j}{\sqrt{d}} - m_h \cdot |i - j|$
Stable softmax
$\mathop{\mathrm{softmax}}(x - c) = \mathop{\mathrm{softmax}}(x)$

وظایف در کد

کار و کد
وظیفهکد
اعمال ماسک علّیscores.masked_fill(mask_slice == 0, float("-inf"))
سافت‌مکس روی کلیدهاF.softmax(scores, dim=-1)
Merge هدهاx.transpose(1, 2).contiguous().view(b, t, h * dh)
افزودن موقعیت‌هاx = tok + pos.unsqueeze(0)
پر کردن جدول سینوسیpe[:, 0::2] = torch.sin(angle)
چرخش Q و Kapply_rope(x, pos, base=10000)
کرنل ادغام‌شده با GQAscaled_dot_product_attention(q, k, v, is_causal=True, enable_gqa=True)
اشتراک ماتریس وزن‌های LM headself.lm_head.weight = self.tok_embed.weight

گذر رو به جلو MultiHeadSelfAttention

کد
python
self.qkv_proj = nn.Linear(d_model, 3 * d_model, bias=True)          # Q، K، V در یک matmul
causal_mask = torch.tril(torch.ones(max_context_length, max_context_length))
self.register_buffer("causal_mask", causal_mask, persistent=False)  # بدون grad
qkv = self.qkv_proj(x)                          # (B, T, 3D)
q, k, v = qkv.chunk(3, dim=-1)                                      # three (B, T, D) views
q = self._split_heads(q)                                            # (B, H, T, d_head)
k = self._split_heads(k)
v = self._split_heads(v)
scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.d_head)
mask_slice = self.causal_mask[:t, :t]                               # بالا چپ (T, T)
scores = scores.masked_fill(mask_slice == 0, float("-inf"))
weights = F.softmax(scores, dim=-1)                                 # مجموع سطرها برابر 1
context = self._merge_heads(torch.matmul(weights, v))  # (B, T, D)
out = self.out_proj(context)                                        # هدها را ترکیب می‌کند

پیش‌فرض‌ها و اعداد

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
Sinusoidal and RoPE base10000افزایش پایه RoPE برای بافت طولانی‌تر
mlp_expansion4بخش MLP از D به 4D به D است
d_head6464 یا 128 در محیط عملیاتی
Init std0.02وزن‌های Linear و Embedding
Residual projection scale1 / sqrt(2 * num_layers)out_proj و fc2
GPT-2 small d_model76812 هد، 12 لایه، حدود 124M
KV bytes per token per layer2 * n_kv_heads * d_head * dtype_sizeتمام هدهای KV، K و V
Compute optimal ratio20توکن به ازای هر پارامتر

عیب‌یابی

عیب‌یابی
  • ValueError روی d_model و n_heads

    علت
    مقدار D بر H بخش‌پذیر نیست
    راه‌حل
    انتخاب H به گونه‌ای که D بر آن بخش‌پذیر باشد
  • seq_len از max_context_length بیشتر است

    علت
    مقدار T از ماسک بزرگ‌تر است
    راه‌حل
    برش به تعداد context_length توکن آخر
  • تقلب مدل روی توکن بعدی

    علت
    نبود ماسک علّی
    راه‌حل
    ماسک کردن مثلث بالایی با -inf
  • خروجی inf از Softmax

    علت
    exp یک عدد بزرگ
    راه‌حل
    ابتدا بیشینه سطر را تفریق کنید
  • توقف یادگیری

    علت
    امتیازها مقیاس‌بندی نشده‌اند
    راه‌حل
    تقسیم بر sqrt(d_head)
  • واگرایی پشته‌ی عمیق لایه‌ها

    علت
    پس‌نرمال‌سازی لایه‌ای (Post-LN) روی مسیر باقی‌مانده
    راه‌حل
    استفاده از پیش‌نرمال‌سازی لایه‌ای (Pre-LN)
  • اشتراک ماتریس وزن‌ها هیچ صرفه‌جویی ندارد

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

    علت
    امبدینگ‌های موقعیت تعمیم‌پذیر نیستند
    راه‌حل
    استفاده از RoPE با مقیاس‌بندی پایه

کوته‌نوشت‌ها

اصطلاح‌ها
MHA
اتنشن چندسر. N هد پرس‌وجو، N هد K/V.
MQA
اتنشن چندپرس‌وجو. یک تصویر K/V مشترک.
GQA
اتنشن پرس‌وجوی گروه‌بندی‌شده. هدهای K/V کمتر، تکرار برای انطباق با Q.
MLA
اتنشن چندسر نهفته. K و V در یک فضای نهفته با رتبه پایین.
RoPE
امبدینگ موقعیت دورانی. چرخش Q و K بر اساس موقعیت.
ALiBi
اتنشن با بایاس‌های خطی. جریمه فاصله روی امتیازها.
RMSNorm
نرمال‌سازی لایه‌ای بدون میانگین.
KV cache
ذخیره K و V مربوط به هر توکن پیشوند.

پرسش‌ها

پرسش و پاسخ
چرا تقسیم بر sqrt(d_k)؟
ضرب‌های داخلی بزرگ سافت‌مکس را اشباع کرده و گرادیان‌ها ناپدید می‌شوند.
چرا -inf در ماسک؟
چون exp(-inf) = 0، در نتیجه موقعیت‌های آینده وزن صفر می‌گیرند.
چرا افزودن موقعیت‌ها؟
اتنشن به‌تنهایی نسبت به جایگشت ناوردا (پایا) است.
چرا GQA؟
حافظه KV cache را به نسبت N/G کاهش می‌دهد در حالی که کیفیت تقریباً حفظ می‌شود.
آیا Flash Attention تقریبی است؟
خیر. یک (max, sum) در حال اجرا آن را دقیق نگه می‌دارد.

نکات کاربردی

نکته‌ها
  • بررسی کنید مجموع سطرهای وزن برابر 1 باشد.
  • بررسی کنید توکن‌های آینده خروجی‌های گذشته را تغییر ندهند.
  • در مقداردهی اولیه تصادفی، انتظار تابع زیان (loss) نزدیک به log(V) داشته باشید.
  • شمارش پارامترها را با مدل مرجع مقایسه کنید.
  • دراپ‌اوت را بعد از سافت‌مکس و بعد از لایه خطی دوم MLP قرار دهید.
  • از وزن‌های اتنشن به‌عنوان اثبات استدلال استفاده نکنید.