Thuta Learning
Deep Learning with PyTorch
AdvancedAIintermediate

Transformer Architecture

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Transformer Architecture concept ကို နားလည်ရှင်းပြနိုင်ရန်
  • နမူနာ PyTorch code ကို ကိုယ်တိုင် run ပြီး output စစ်နိုင်ရန်
  • Tutorial Platform project နှင့် production scenario တွင် မှန်ကန်စွာအသုံးချနိုင်ရန်

နားလည်ထားရမယ့် အချက်

'Attention Is All You Need' ကနေ မိတ်ဆက်ခဲ့တဲ့ transformer architecture က recurrence ကို self-attention (sequence ထဲက position တိုင်းက အခြား position တိုင်းအပေါ် attend လုပ်တာ) နဲ့ feedforward network တစ်ခုကို block တွေအဖြစ် ထပ်ခုထားပြီး လုံးဝ အစားထိုးလိုက်တယ်။ Recurrence မရှိတော့လို့ token 1 ကို token 2 မတိုင်ခင် process လုပ်ရမယ်ဆိုတဲ့ requirement လည်း မရှိတော့ဘူး — position တိုင်းကို GPU ပေါ်မှာ တစ်ပြိုင်နက်တည်း တွက်ချက်နိုင်တယ်၊ ဒါကြောင့် hardware တူတူနဲ့ RNN (step-by-step sequential ဖြစ်ရမယ့်) ထက် transformer တွေက train ဖို့ ပိုမြန်တာဖြစ်တယ်။ ဒါပေမယ့် ဒီ parallelism မှာ ကျသင့်ခဲ့ရတာတွေရှိတယ် — self-attention တစ်ခုတည်းက input ကို order မရှိတဲ့ set တစ်ခုအနေနဲ့ ဆက်ဆံတယ် (token နှစ်ခုရဲ့ position ကို ပြောင်းလိုက်ရင် output မပြောင်းဘူး) — ဒါကြောင့် model မှာ word order ကို built-in အနေနဲ့ နားလည်တာ မရှိဘူး။ Positional encoding က ဒီပြဿနာကို ဖြေရှင်းတယ် — attention layer တွေထဲမဝင်ခင် token embedding တွေထဲကို pattern တစ်ခု (position နဲ့ dimension အလိုက် ပြောင်းလဲတဲ့ sinusoidal pattern အများဆုံး) ကို တိုက်ရိုက် ထည့်ပေးတယ်၊ model ကို position information ရအောင် လုပ်ပေးတယ်။ Multi-head attention ကတော့ attention operation များစွာကို parallel ဖြစ်အောင် run တယ်၊ တစ်ခုစီမှာ ကိုယ်ပိုင် learned query/key/value projection ရှိတယ်၊ ဒါကြောင့် head တစ်ခုစီက relationship မျိုးစုံအတွက် specialize ဖြစ်နိုင်တယ် — တစ်ခုက syntactic relationship ကို track လုပ်တယ်၊ တစ်ခုက topical similarity ကို track လုပ်တယ်၊ output တွေကို concatenate လုပ်ပေးတယ်။

လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်

Tutorial Platform ရဲ့ search ranking feature တစ်ခုက user ရဲ့ query တစ်ခုနဲ့ lesson တစ်ခုကြား ဘယ်လောက် သက်ဆိုင်လဲဆိုတာ ဆုံးဖြတ်ဖို့ လိုအပ်တယ်၊ query text ရော lesson text ရော နှစ်ခုစလုံးက word order ပြောင်းရင် အဓိပ္ပာယ်ပြောင်းသွားတဲ့ sequence တွေဖြစ်တယ် ('Rust ကို Go မတိုင်ခင်သင်' နဲ့ 'Go ကို Rust မတိုင်ခင်သင်' က မတူဘူး)။ Transformer encoder တစ်ခုက query တစ်ခုလုံးကို parallel ဖြစ်အောင် process လုပ်တယ် — real time မှာ search result တွေ rank လုပ်ဖို့ လုံလောက်လောက် မြန်တယ် — positional encoding ကတော့ 'မတိုင်ခင်' နဲ့ 'နောက်ပိုင်း' ကို အဓိပ္ပာယ်ရှိနေအောင် ထိန်းပေးထားတယ်၊ attention head များစွာက programming language ဘယ်ဟာလဲ၊ order relationship ကို ဘယ်စကားလုံးက ဖော်ပြနေလဲဆိုတာကို သီးခြားစီ ဖမ်းယူနိုင်ပြီး relevance score တစ်ခုတည်းထဲ ပေါင်းစပ်ပေးတယ်။

အတူတူ စမ်းရေးကြည့်မယ်

python
import torch
import torch.nn as nn

torch.manual_seed(0)

embed_dim, num_heads, seq_len, batch = 16, 4, 5, 2
mha = nn.MultiheadAttention(embed_dim, num_heads, batch_first=True)
x = torch.randn(batch, seq_len, embed_dim)
attn_out, attn_weights = mha(x, x, x)
print("multi-head attention output shape:", attn_out.shape)

def sinusoidal_positional_encoding(seq_len, dim):
    pos = torch.arange(seq_len).unsqueeze(1)
    i = torch.arange(dim).unsqueeze(0)
    angle_rates = 1 / torch.pow(10000, (2 * (i // 2)) / dim)
    angles = pos * angle_rates
    pe = torch.zeros(seq_len, dim)
    pe[:, 0::2] = torch.sin(angles[:, 0::2])
    pe[:, 1::2] = torch.cos(angles[:, 1::2])
    return pe

pe = sinusoidal_positional_encoding(seq_len, embed_dim)
token_embeddings = torch.randn(seq_len, embed_dim)
combined = token_embeddings + pe
print("positional encoding shape:", pe.shape)
print("token embedding + positional encoding shape:", combined.shape)
You should see
multi-head attention output shape: torch.Size([2, 5, 16])
positional encoding shape: torch.Size([5, 16])
token embedding + positional encoding shape: torch.Size([5, 16])

nn.MultiheadAttention ကို self-attention (Q=K=V=x) အနေနဲ့ ခေါ်ထားလို့ output shape က input shape (batch, seq_len, embed_dim) အတိုင်းပဲ ပြန်ရလာတယ်။ positional encoding ကို token embedding ပေါ် element-wise ပေါင်းလို့ shape မပြောင်းဘဲ position information ပါလာတယ်။

၅ မိနစ် စမ်းကြည့်

num_heads ကို 4 ကနေ 8 (embed_dim=16 ကို 4 နဲ့ စား၍ ပြည့်တဲ့ divisor ဖြစ်ရမယ်) ကို ပြောင်းပြီး ပြန် run ကြည့်ပါ — output shape ပြောင်းလဲသွားလား စစ်ဆေးပါ။ ပြီးရင် combined tensor ကို matplotlib နဲ့ heatmap အနေနဲ့ plot လုပ်ကြည့်ပြီး sinusoidal pattern ကို visualize လုပ်ကြည့်ပါ။

သတိလေးတစ်ချက်

embed_dim ကို num_heads နဲ့ စားလို့ မကျေအောင် set လုပ်မိရင် nn.MultiheadAttention က error တက်တယ် — embed_dim တစ်ခုစီကို head အလိုက် ညီညီညာညာ ပိုင်းခွဲနိုင်ရမယ်

positional encoding ကို token embedding နဲ့ concatenate လုပ်မယ့်အစား ပေါင်းရမယ်ဆိုတာ မေ့တတ်ကြတယ် — concatenate လုပ်ရင် dimension တိုးသွားပြီး downstream layer တွေရဲ့ expected shape နဲ့ မကိုက်ညီတော့ဘူး

Wikipedia — Transformer (deep learning architecture)Deep Learning

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • embed_dim ကို num_heads နဲ့ စားလို့ မကျေအောင် set လုပ်မိရင် nn.MultiheadAttention က error တက်တယ် — embed_dim တစ်ခုစီကို head အလိုက် ညီညီညာညာ ပိုင်းခွဲနိုင်ရမယ်
  • positional encoding ကို token embedding နဲ့ concatenate လုပ်မယ့်အစား ပေါင်းရမယ်ဆိုတာ မေ့တတ်ကြတယ် — concatenate လုပ်ရင် dimension တိုးသွားပြီး downstream layer တွေရဲ့ expected shape နဲ့ မကိုက်ညီတော့ဘူး
  • နမူနာ code ကို production system ပေါ် တိုက်ရိုက်မစမ်းဘဲ local/test environment တွင် အရင်အတည်ပြုပါ။

လေ့ကျင့်ခန်း

num_heads ကို 4 ကနေ 8 (embed_dim=16 ကို 4 နဲ့ စား၍ ပြည့်တဲ့ divisor ဖြစ်ရမယ်) ကို ပြောင်းပြီး ပြန် run ကြည့်ပါ — output shape ပြောင်းလဲသွားလား စစ်ဆေးပါ။ ပြီးရင် combined tensor ကို matplotlib နဲ့ heatmap အနေနဲ့ plot လုပ်ကြည့်ပြီး sinusoidal pattern ကို visualize လုပ်ကြည့်ပါ။

You'll know it worked when: multi-head attention output shape: torch.Size([2, 5, 16]) positional encoding shape: torch.Size([5, 16]) token embedding + positional encoding shape: torch.Size([5, 16]) nn.MultiheadAttention ကို self-attention (Q=K=V=x) အနေနဲ့ ခေါ်ထားလို့ output shape က input shape (batch, seq_len, embed_dim) အတိုင်းပဲ ပြန်ရလာတယ်။ positional encoding ကို token embedding ပေါ် element-wise ပေါင်းလို့ shape မပြောင်းဘဲ position information ပါလာတယ်။

Transformer Architecture | Thuta Learning