Multi-head attention nedir, self-attention transformer’ların içinde nasıl çalışır ve bu mekanizmalar GPT-5 gibi LLM’ler ile CLIP gibi VLM’leri nasıl mümkün kılar? Basit örnekler, diyagramlar ve kodla öğrenin.
Dikkat (attention) mekanizması, daha spesifik olarak self-attention mekanizması, ilk kez 2017 yılında Vaswani ve arkadaşlarının ünlü “Attention is All You Need“ makalesinde tanıtıldı.
Bu mekanizma Transformer modelini çalıştırır; bu da karşılığında LLM’ler ve VLM’ler gibi en güçlü modellerin temelini oluşturur.
Yani evet, oldukça önemlidir!
Ama şu var: Pek çok kişi (ben de eskiden öyleydim!) attention’ın 2017’de icat edildiğini sanıyor.
Öyle değil.
Orijinal attention mekanizması ilk kez 2015 yılında, Bahdanau ve arkadaşları tarafından makine çevirisi bağlamında tanıtıldı. Fikirleri, tek bir sabit bağlam vektörüne dayanmak yerine, her çözümleme adımında kod çözücünün (decoder) girdi cümlesinin farklı bölümlerine odaklanmasına izin vermekti.
Bu küçük değişim büyük bir fark yarattı — ve daha sonra self-attention ve nihayetinde multi-head attention’ın temellerini attı.
Bu noktada aklınıza bir soru gelebilir:
“Attention aslında ne anlama geliyor?”
Bu kavramı iki basit cümleyle tanıtayım:
“Kedipaspasın üstüne oturdu.” → Modelimizde oturdu kelimesinden kedi ve paspas’a dikkat yönlenebilir.
“O susadığındançayını içti.” → içti kelimesinden çay ve susadı’ya dikkat yönlenir; nedeni eylemle ilişkilendirir.
Bu örneklerden attention’ın neyi amaçladığını görmeye başlıyoruz. Tamamen odaklanma ile ilgilidir; modelin, işlediği kelimeyle ilişkili diğer kelimeleri, çoğu zaman anlamsal ya da dilbilgisel ilişkiler temelinde belirlemesine yardımcı olur.
Önemli bir nokta: Attention ağırlıkları ve skorları hesaplanırken, yukarıdaki diyagramda görüldüğü gibi yalnızca belirli bazı belirteçler (token) değil, tüm belirteçler kullanılır (buna daha sonra değineceğiz). Bu da bazı kelimeler arasında, okların kalınlığının da gösterdiği gibi, diğerlerine göre daha güçlü attention olacağı anlamına gelir.
Transformer’ları dil anlama konusunda bu kadar iyi yapan şey budur; attention sayesinde her kelimeyi dinamik olarak diğer tüm kelimelerle ilişkilendirirler.
Ara adımlar
Artık attention’ın ne olduğunu gördük, ancak içsel işlemenin nasıl olduğunu hâlâ bilmiyoruz.
İşte burada Sorgular (Queries), Anahtarlar (Keys) ve Değerler (Values) (kısaca Q, K ve V) devreye girer. Makalenin geri kalanında, örnek cümlemiz “the cat sat on the mat” ile devam edeceğiz.
Öncelikle, bir cümle Transformer’a verildiğinde, hemen bir belirteçleyici (tokenizer) tarafından belirteçlere ayrılır; yaygın bir belirteçleyici Byte-Pair Encoding’dir.
Belirteçlemeyi metni daha küçük birimlere bölmek olarak düşünebiliriz. Cümlemizdeki kelimelerin hepsi kısa olduğundan, bu örnekte her birimin bir kelimeye eşit olduğunu varsayabiliriz. Görsel olarak, belirteçleyiciden geçtikten sonra cümle şöyle görünmelidir:
Noktalama işaretinin (nokta) bile bir belirtece dönüştürüldüğüne dikkat edin. Yine basitlik adına, noktanın kendi başına ayrı bir belirteç olduğunu varsayıyoruz.
Belirteçlemeden sonra, her belirteci belirteçleyici sözlüğüyle kendi Belirteç ID’sine dönüştürürüz. Belirteçleyici sözlüğünü, modelin tanıyabildiği tüm belirteçleri ve bunların Belirteç ID’lerini tutan bir veritabanı/tablolar dizisi olarak düşünebilirsiniz.
Ardından, bu benzersiz belirteç ID’lerinin her biri, bir gömme (embedding) matrisi kullanılarak kendi belirteç gömmesine eşlenir. Tüm bu belirteç gömmelerinin aynı boyutta vektörler olacağını not etmek önemlidir; örneğimizde bunu 512 varsayıyoruz.
Kalan son adım, modelin her belirtecin konumsal bilgisini alması için konumsal gömmeyi eklemektir. İki yaygın yöntem şunlardır:
Bu konumsal gömmelerin temel mekaniği bu eğitimin kapsamı dışındadır. Şimdilik bilmemiz gereken tek şey, girdi vektörlerimizi şu formülle elde ettiğimizdir:
Girdi vektörü = Belirteç Gömmesi + Konumsal Gömme
Sorgular, anahtarlar ve değerler
Artık Q, K, V vektörlerini tanıtmaya hazırız. Başlamak için, girdi içindeki her kelime için üç vektör oluşturduğumuzu not edin:
Sorgu (Q) – kelimenin ne aradığını belirtir
Anahtar (K) – kelimenin başkalarına ne sunduğunu ifade eder
Değer (V) – kelimenin taşıdığı asıl bilgiyi içerir
Bunlar öğrenilebilir dönüşümlerdir ve aynı zamanda kendi matrisleridir. Matematiksel olarak bu dönüşümler şu şekilde yazılır:
Buradan, her belirteç üç yeni vektörle temsil edilebilir. Bu süreci görselleştirmeye yardımcı olmak için aşağıdaki diyagramı oluşturdum:
“Attention is all you need” makalesinde, yeni vektörlerin Attention Ağırlıklarını hesaplamak için nasıl kullanıldığını gösteren bir matematiksel formül verildi. Adım adım ilerleyelim; “oturdu” kelimesindeyken Attention Ağırlıklarını hesapladığımızı varsayalım:
Öncelikle, “oturdu” kelimesinin Sorgu vektörünü, diğer tüm kelimelerin — kendisi dahil — Anahtar vektörleri ile karşılaştırmak için kullanırız. Sonuç, her kelimenin “oturdu” ile ne kadar ilişkili olduğunu söyleyen bir dizi benzerlik skorudur (bunlar skaler değerlerdir). Bunlara daha resmi olarak Attention Skorları denir.
Bu skorlar daha sonra sqrt(d_k) ile ölçeklendirilir; bu, skorların çok büyümesini engelleyerek geriye yayılım ile eğitim sırasında gradyanların dengelenmesine yardımcı olur. Bu ölçeklendirilmiş skorlar daha sonra bir softmax’ten geçirilerek attention ağırlıklarına dönüştürülür.
Softmax, modele her kelimeye ne kadar ağırlık vermesi gerektiğini söyleyen bir olasılık dağılımı verir ve böylece belirli bir belirteç için attention ağırlıkları toplamı 1’e eşit olur.
Son olarak, bu attention ağırlıklarını kullanarak değer vektörlerinin ağırlıklı toplamını alırız.
Bu bize, tüm belirteçlerin bilgisince zenginleştirilmiş ancak özellikle kedi, paspas ve diğer ilgili belirteçlerden beslenen, bağlam içinde “oturdu”yu temsil eden yeni bir vektör verir.
Bu süreç cümledeki her belirteç için gerçekleşir. Her belirteç, diğer tüm belirteçlere ve hatta kendisine dikkat eder. Bu yüzden buna self-attention diyoruz.
Ayrıca, yeni zenginleştirilmiş vektörü tek bir belirteç için hesapladığımızı not edin; pratikte, matris çarpımı son derece verimli olduğundan bunu bir seferde pek çok, hatta tüm belirteçler için yaparız.
Bunu yapabiliriz çünkü mimari tamamen paralelleştirilebilir. Tekrarlayan sinir ağlarının (RNN) sıralı işlemine karşın, bu mekanizma Transformer’ların tüm belirteçleri aynı anda işlemesine olanak tanır; bu da onları hızlı ve güçlü kılar.
Görselleştirmek için yukarıdaki diyagrama bakın. Girdi matrisi X’in sırasıyla Sorgu, Anahtar ve Değer matrislerine dönüştüğünü ve ardından ölçeklendirilmiş noktasal çarpım attention formülünün uygulanarak girdimizdeki tüm belirteçlerin tam zenginleştirilmiş gömme vektörlerinin — A’nın — elde edildiğini görebilirsiniz.
Şimdi PyTorch’ta az önce tartıştıklarımızı kodlayalım. Şaşırtıcı biçimde oldukça kolay:
import torchimport torch.nn.functional as Fdef scaled_dot_product_attention(Q, K, V): d_k = Q.size(-1)# the dimension of the key vectors scores = torch.matmul(Q, K.transpose(-2, -1)) / torch.sqrt(torch.tensor(d_k, dtype=torch.float32)) attn_weights = F.softmax(scores, dim=-1) output = torch.matmul(attn_weights, V) return output, attn_weightsAltyapı:
Basit bir fonksiyon yazarak yukarıdaki tartışmayı birebir uygulayabiliriz! İşte en önemli noktalar:
Q, K ve V tensörleri [batch_size, seq_len, dim] şeklindedir
Çıktı, her belirtecin tüm dizinin bağlamında temsil edildiği yeni bir vektör kümesidir
Attention Skorları, normalleştirilmemiş ham benzerliklerdir
Attention Ağırlıkları, odaklanmayı sağlayan ve toplamı 1 olan (softmax ile) normalleştirilmiş değerlerdir
Farklı Attention Türleri
Ancak henüz söylemediğim önemli bir ayrıntı var. Transformer’da tek bir attention türü yok — aslında üç tane var:
Encoder self-attention
Decoder self-attention
Encoder–decoder (çapraz) attention
Her biri biraz farklı bir rol oynar; hızlıca üzerinden geçelim.
Encoder self-attention
Şu ana kadar incelediğimiz şey budur: encoder içinde, her belirteç aynı girdi dizisindeki diğer tüm belirteçlere dikkat eder; “the cat sat on the mat.” örneğinde olduğu gibi.
Burada dikkat edilmesi gereken nokta, tüm girdinin baştan biliniyor olması nedeniyle herhangi bir kısıt olmamasıdır; bu da modelin her belirteç için, öncesini ve sonrasını anlayacak şekilde derin bağlamsal temsiller kurmasına olanak tanır.
Ayrıca bunun encoder’da gerçekleştiğini de not edin.
Decoder self-attention
Burada işler biraz daha zorlaşır. Artık decoder’da olduğumuz için, metin üretimi sırasında hile olmaması adına her belirtecin geleceği görmesini istemeyiz.
Başka bir örnek verelim: “Köpek çok yüksek sesle havladı.” Model “havladı”yı üretirken (basitlik için her kelimenin bir belirteç olduğunu varsayalım), bir sonraki belirtecin “çok” olduğunu bilmemelidir; aksi halde model yeni belirteç üretmeyi öğrenemez.
Bu sorunu çözmek için, bazen üçgen maske de denilen bir nedensel maske uygularız; bu maske her belirtecin yalnızca kendisine ve kendinden öncekilere dikkat etmesini, asla sonrakilere etmemesini sağlar.
Yukarıdaki diyagramdan, geleceğe ait attention skorlarının maskeleme ile kaldırıldığını; bunun da modelin yeni, doğru ve anlamlı belirteçler üretmeyi öğrenmesine olanak tanıdığını görebiliriz.
Encoder-decoder (çapraz) attention
Decoder üretime başladıktan sonra bile hâlâ orijinal girdiden (yanıt verdiği şey) bilgiye ihtiyaç duyar. İşte çapraz attention burada devreye girer.
Burada, decoder, encoder çıkışına dikkat eder. Dolayısıyla decoder self-attention maskelenmişken, çapraz attention maskelenmez ve decoder’ın tüm encoder belirteçlerine aynı anda bakmasına izin verilir.
Bu kavramı öğrenirken Çeviri Örneğini çok sevmiştim. “Bonjour tout le monde”’u İngilizceye çevirdiğinizi varsayın; decoder her bir İngilizce kelimeye karar verirken tüm Fransızca kelimelere bakabilmeli değil mi?
Çapraz attention tam olarak bunu yapar. Ancak bu yazının kapsamı için gerekli olmadığından burada çapraz attention’a daha derinlemesine girmeyeceğiz.
Multi-Head Attention İhtiyacı
Artık self-attention’ın nasıl çalıştığını anlıyoruz. Ama şimdi şu soru aklınıza gelebilir:
Zaten attention varken neden birden fazla kafa gerekli?
Bunun için, ilk öğrendiğimde sezgimi geliştiren el feneri benzetmesini sunmak istiyorum.
Tek bir attention kafasını, bir cümlenin önemli kısımlarını aydınlatmaya çalışan tek bir el feneri gibi düşünün. Oysa bir cümlede anlaşılması gereken birden fazla ilişki türü vardır: özne-fiil, nesne-zamir, sıfat-isim, uzun menzilli bağımlılıklar vb.
Her seferinde yalnızca tek bir ilişkiyi yakalamak yerine daha fazlasını yakalayabilsek daha iyi olmaz mıydı?
Dolayısıyla çözüm, modele her biri cümlenin farklı kısımlarına odaklanan birden fazla el feneri vermektir. Buna multi-head attention denir.
Tek bir Q, K, V kümesi hesaplayıp tek bir attention işlemi yapmak yerine, gömmeleri daha küçük parçalara böler ve birden çok bağımsız attention kafasını paralel olarak çalıştırırız.
Yukarıdaki diyagramda görüldüğü gibi, girdi gömmesi (basit tutmak için bu durumda tek bir belirteç için) n farklı kafa arasında eşit olarak bölünmüştür.
Örneğimizde, boyutun 512 ve kafa sayısının 8 olduğunu varsayalım; dolayısıyla her attention kafası paralel olarak (512/8=64) boyutu işler ve farklı ilişkileri yakalamaya çalışır.
Her bir kafanın hangi tür ilişkileri işleyebileceğine dair (hangisine baktığını tam olarak hâlâ bilmiyor olsak da) sezginizi daha da geliştirmek için basit bir örnek üzerinden gidelim:
Başka bir kafa, özne–fiil ilişkisine odaklanabilir: “fox → jumps”
Bir diğeri ise uzak mesafe ilişkilerini yakalayabilir: “jumps → over → dog”
Önemli olan, bu kafaların hepsinin eşzamanlı çalışması ve çıktılarının birleştirilip (concatenate)yeniden yansıtılarak (project) orijinal gömme boyutuna (bizim durumda 512) döndürülmesidir.
Birden çok kafayı kodla görselleştirme
Multi-Head Attention’ı tam olarak pekiştirmek için HuggingFace kütüphanesini kullanarak mekanizmanın nasıl çalıştığını görelim.
Önce, ilgili paketlerin tümünü indirmek için yukarıdaki kod hücresini çalıştırın.
from transformers import BertTokenizer, BertModelfrom bertviz import head_viewimport torchmodel_name ='bert-base-uncased'# We will be using the Bert modelmodel = BertModel.from_pretrained(model_name, output_attentions=True)tokenizer = BertTokenizer.from_pretrained(model_name)model.eval() # As we are not training, we have set the model to evaluation mode so no updates are made# This is our input sentencesentence = "The quick brown fox jumps over the lazy dog."# Using the tokenizer to convert the sentence into tokensinputs = tokenizer(sentence, return_tensors='pt')input_ids = inputs['input_ids']# Forward pass with attentionswith torch.no_grad(): outputs = model(**inputs) attentions = outputs.attentions # Tuple of (num_layers, batch, num_heads, seq_len, seq_len)# Here we decode the tokens tokens = tokenizer.convert_ids_to_tokens(input_ids[0])head_view(attentions, tokens) # VisualizationAltyapı:
Elde ettiğimiz çıktı aşağıda görülebilir. 12 farklı renk olduğuna dikkat edin; bu, modelde 12 Kafa olduğu anlamına gelir. Çizgilerin kalınlığı da belirteçler arasındaki attention skorlarının büyüklüğüyle ilişkilidir.
Multi-Head Attention’ın Uygulanması: En İyi Uygulamalar
Bu bölümde, Multi-Head Attention mekanizması için sözde kod (pseudocode) yazacağız. Önce girdimizin: X’in [batch, seq_len, d_model] şeklinde olduğunu varsayalım.
Sonra sözde koda geçebiliriz:
Q = X @ W_Q # Calculating the Query valuesK = X @ W_K # Calculating the Key valuesV = X @ W_V# Calculating the Value valuesQ_i, K_i, V_i = split_into_heads(Q, K, V, num_heads) # Now we split the Q,K,V into multiple different heads (by evenly splitting the dimensions)# Here we compute scaled dot-product attention for each headscores = (Q_i @ K_i.T) / sqrt(head_dim)scores += maskA_i = softmax(scores)A_i = dropout(A_i)Z_i = A_i @ V_iZ = concat_heads(Z_i) # We have to concatenate all of the Heads# This is our final linear projection matrixoutput = Z @ W_Ooutput = dropout(output)Altyapı:
Bunların hepsi artık size tanıdık gelmeli; belki sadece son doğrusal yansıtma matrisi yeni olabilir.
Bunu da hızlıca ele alalım.
Tüm bireysel attention kafaları işini bitirdikten sonra, çıktıları tekrar tek bir vektörde birleştirilir. Ancak bu birleşik çıktının orijinal model boyutuna yeniden şekillendirilmesi gerekir ve burada son doğrusal yansıtma matrisi devreye girer. Birleştirilmiş çıktıyı, Transformer’daki bir sonraki katmana aktarılabilmesi için girdi gömmesiyle aynı boyuta eşler.
Bazı optimizasyon ve en iyi uygulamalardan da bahsedelim:
Paralelleştirme: Her kafa bağımsız olduğundan hepsini paralel hesaplayabiliriz.
Matris çarpımı: Her şeyi doğrusal cebir işlemleriyle (ör. matmul) yığın halinde işleriz; bu işlemler yüksek düzeyde optimize edilmiştir.
FlashAttention (İleri seviye): Düşük seviyeli CUDA teknikleriyle bellek yükünü azaltıp attention’ı hızlandıran — özellikle uzun dizilerde — daha yeni bir tekniktir.
En iyi uygulamalar açısından, attention katmanını kodlarken bakmamız gereken 3 ana hiperparametre vardır:
num_heads: Paralel olarak kaç attention kafası çalıştırılacağı; d_model’ı tam bölmesi gerekir.
head_dim: Her bir kafanın boyutu.
dropout_rate: Aşırı uyumu önlemek için.
Sonuç
Bu yazıda pek çok konuyu ele aldık. Basit bir fikirle başladık: attentionodaklanmaileilgilidir. Ardından, Transformer’ların bu odağı Sorgular, Anahtarlar ve Değerleri kullanarak her bir kelimenin diğer tüm kelimelerle ilişkisini hesaplayarak nasıl kullandığını inceledik.
Self-attention’ın (ve kısaca Nedensel ve Çapraz Attention gibi diğer türlerin) her belirtece zengin, bağlam farkında bir temsil kazandırdığını gördük. Sonra bir adım daha ileri giderek, tek bir “el fenerine” güvenmek yerine modele, cümledeki farklı örüntüleri aynı anda yakalayan birden fazla el feneri verdiğimiz multi-head attention’a geçtik.
Transformer’lara asıl güç veren şey budur. Sadece okuma yapmazlar; tüm diziler boyunca alttaki yapı, anlam ve ilişkileri kavrarlar.
Bu yazıda Transformer’ların bir yönünü ele aldık; ancak öğrenilecek daha çok şey var. Bu yüzden şu kapsamlı kursa göz atın: Transformer Models with PyTorch Course.
Multi-head attention Transformer performansını nasıl artırır?⌄
Birden çok daha küçük attention kafasını paralel çalıştırarak, model aynı anda farklı örüntüleri (sözdizimsel, konumsal vb.) yakalayabilir; bu da doğruluğu ve kararlılığı artırır.
Sorgular, anahtarlar ve değerler ne işe yarar?⌄
Basitçe, sorgular “ne arıyorum?” diye sorar, anahtarlar “ne sunuyorum?” der, değerler ise attention ağırlıklarıyla karıştırılan bilgiyi taşır.
Tek kafalı ve çok kafalı—fark nedir?⌄
Tek kafalı yaklaşım tek bir izdüşüm (projection) kullanır; çok kafalı yaklaşım ise model boyutunu h (yani Kafa sayısı) alt uzaylarına böler; her birinde bağımsız olarak dikkat eder, sonra birleştirip yeniden yansıtır.
Kaç kafa kullanmalıyız?⌄
Bize bağlı! Yalnızca gömme boyutunun h (Kafa sayısı) ile tam bölünebildiğinden emin olmalısınız. Yaygın seçimler 2’nin katlarıdır; ancak daha fazla kafa, hesaplama ve bellek maliyetini artırır.
Multi-head attention nerede kullanılır?⌄
NLP (çeviri, Soru-Cevap, özetleme), görme (ViT) ve konuşma (ASR, Conformer’lar) gibi modern temel modellerin çekirdek yapı taşıdır.
Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Llama 3 gibi LLM'ler de dahil olmak üzere üretim için en yeni yapay zeka modellerini eğitin ve ince ayar yapın. Yapay Zeka Mühendisi olma yolculuğunuza bugün başlayın!
Self-Attention Mekanizmasına Giriş
Dikkat (attention) mekanizması, daha spesifik olarak self-attention mekanizması, ilk kez 2017 yılında Vaswani ve arkadaşlarının ünlü “Attention is All You Need“ makalesinde tanıtıldı.
Bu mekanizma Transformer modelini çalıştırır; bu da karşılığında LLM’ler ve VLM’ler gibi en güçlü modellerin temelini oluşturur.
Yani evet, oldukça önemlidir!
Ama şu var: Pek çok kişi (ben de eskiden öyleydim!) attention’ın 2017’de icat edildiğini sanıyor.
Öyle değil.
Orijinal attention mekanizması ilk kez 2015 yılında, Bahdanau ve arkadaşları tarafından makine çevirisi bağlamında tanıtıldı. Fikirleri, tek bir sabit bağlam vektörüne dayanmak yerine, her çözümleme adımında kod çözücünün (decoder) girdi cümlesinin farklı bölümlerine odaklanmasına izin vermekti.
Bu küçük değişim büyük bir fark yarattı — ve daha sonra self-attention ve nihayetinde multi-head attention’ın temellerini attı.
Bu noktada aklınıza bir soru gelebilir:
“Attention aslında ne anlama geliyor?”
Bu kavramı iki basit cümleyle tanıtayım:
Bu örneklerden attention’ın neyi amaçladığını görmeye başlıyoruz. Tamamen odaklanma ile ilgilidir; modelin, işlediği kelimeyle ilişkili diğer kelimeleri, çoğu zaman anlamsal ya da dilbilgisel ilişkiler temelinde belirlemesine yardımcı olur.
Önemli bir nokta: Attention ağırlıkları ve skorları hesaplanırken, yukarıdaki diyagramda görüldüğü gibi yalnızca belirli bazı belirteçler (token) değil, tüm belirteçler kullanılır (buna daha sonra değineceğiz). Bu da bazı kelimeler arasında, okların kalınlığının da gösterdiği gibi, diğerlerine göre daha güçlü attention olacağı anlamına gelir.
Transformer’ları dil anlama konusunda bu kadar iyi yapan şey budur; attention sayesinde her kelimeyi dinamik olarak diğer tüm kelimelerle ilişkilendirirler.
Ara adımlar
Artık attention’ın ne olduğunu gördük, ancak içsel işlemenin nasıl olduğunu hâlâ bilmiyoruz.
İşte burada Sorgular (Queries), Anahtarlar (Keys) ve Değerler (Values) (kısaca Q, K ve V) devreye girer. Makalenin geri kalanında, örnek cümlemiz “the cat sat on the mat” ile devam edeceğiz.
Öncelikle, bir cümle Transformer’a verildiğinde, hemen bir belirteçleyici (tokenizer) tarafından belirteçlere ayrılır; yaygın bir belirteçleyici Byte-Pair Encoding’dir.
Belirteçlemeyi metni daha küçük birimlere bölmek olarak düşünebiliriz. Cümlemizdeki kelimelerin hepsi kısa olduğundan, bu örnekte her birimin bir kelimeye eşit olduğunu varsayabiliriz. Görsel olarak, belirteçleyiciden geçtikten sonra cümle şöyle görünmelidir:
Noktalama işaretinin (nokta) bile bir belirtece dönüştürüldüğüne dikkat edin. Yine basitlik adına, noktanın kendi başına ayrı bir belirteç olduğunu varsayıyoruz.
Belirteçlemeden sonra, her belirteci belirteçleyici sözlüğüyle kendi Belirteç ID’sine dönüştürürüz. Belirteçleyici sözlüğünü, modelin tanıyabildiği tüm belirteçleri ve bunların Belirteç ID’lerini tutan bir veritabanı/tablolar dizisi olarak düşünebilirsiniz.
Ardından, bu benzersiz belirteç ID’lerinin her biri, bir gömme (embedding) matrisi kullanılarak kendi belirteç gömmesine eşlenir. Tüm bu belirteç gömmelerinin aynı boyutta vektörler olacağını not etmek önemlidir; örneğimizde bunu 512 varsayıyoruz.
Kalan son adım, modelin her belirtecin konumsal bilgisini alması için konumsal gömmeyi eklemektir. İki yaygın yöntem şunlardır:
Bu konumsal gömmelerin temel mekaniği bu eğitimin kapsamı dışındadır. Şimdilik bilmemiz gereken tek şey, girdi vektörlerimizi şu formülle elde ettiğimizdir:
Girdi vektörü = Belirteç Gömmesi + Konumsal Gömme
Sorgular, anahtarlar ve değerler
Artık Q, K, V vektörlerini tanıtmaya hazırız. Başlamak için, girdi içindeki her kelime için üç vektör oluşturduğumuzu not edin:
Bunlar öğrenilebilir dönüşümlerdir ve aynı zamanda kendi matrisleridir. Matematiksel olarak bu dönüşümler şu şekilde yazılır:
Buradan, her belirteç üç yeni vektörle temsil edilebilir. Bu süreci görselleştirmeye yardımcı olmak için aşağıdaki diyagramı oluşturdum:
Ölçeklendirilmiş noktasal çarpımın (scaled dot-product) hesaplanması
“Attention is all you need” makalesinde, yeni vektörlerin Attention Ağırlıklarını hesaplamak için nasıl kullanıldığını gösteren bir matematiksel formül verildi. Adım adım ilerleyelim; “oturdu” kelimesindeyken Attention Ağırlıklarını hesapladığımızı varsayalım:
Öncelikle, “oturdu” kelimesinin Sorgu vektörünü, diğer tüm kelimelerin — kendisi dahil — Anahtar vektörleri ile karşılaştırmak için kullanırız. Sonuç, her kelimenin “oturdu” ile ne kadar ilişkili olduğunu söyleyen bir dizi benzerlik skorudur (bunlar skaler değerlerdir). Bunlara daha resmi olarak Attention Skorları denir.
Bu skorlar daha sonra
sqrt(d_k)ile ölçeklendirilir; bu, skorların çok büyümesini engelleyerek geriye yayılım ile eğitim sırasında gradyanların dengelenmesine yardımcı olur. Bu ölçeklendirilmiş skorlar daha sonra bir softmax’ten geçirilerek attention ağırlıklarına dönüştürülür.Softmax, modele her kelimeye ne kadar ağırlık vermesi gerektiğini söyleyen bir olasılık dağılımı verir ve böylece belirli bir belirteç için attention ağırlıkları toplamı 1’e eşit olur.
Son olarak, bu attention ağırlıklarını kullanarak değer vektörlerinin ağırlıklı toplamını alırız.
Bu bize, tüm belirteçlerin bilgisince zenginleştirilmiş ancak özellikle kedi, paspas ve diğer ilgili belirteçlerden beslenen, bağlam içinde “oturdu”yu temsil eden yeni bir vektör verir.
Bu süreç cümledeki her belirteç için gerçekleşir. Her belirteç, diğer tüm belirteçlere ve hatta kendisine dikkat eder. Bu yüzden buna self-attention diyoruz.
Ayrıca, yeni zenginleştirilmiş vektörü tek bir belirteç için hesapladığımızı not edin; pratikte, matris çarpımı son derece verimli olduğundan bunu bir seferde pek çok, hatta tüm belirteçler için yaparız.
Bunu yapabiliriz çünkü mimari tamamen paralelleştirilebilir. Tekrarlayan sinir ağlarının (RNN) sıralı işlemine karşın, bu mekanizma Transformer’ların tüm belirteçleri aynı anda işlemesine olanak tanır; bu da onları hızlı ve güçlü kılar.
Görselleştirmek için yukarıdaki diyagrama bakın. Girdi matrisi X’in sırasıyla Sorgu, Anahtar ve Değer matrislerine dönüştüğünü ve ardından ölçeklendirilmiş noktasal çarpım attention formülünün uygulanarak girdimizdeki tüm belirteçlerin tam zenginleştirilmiş gömme vektörlerinin — A’nın — elde edildiğini görebilirsiniz.
PyTorch’ta ölçeklendirilmiş noktasal çarpım attention’ın uygulanması
Şimdi PyTorch’ta az önce tartıştıklarımızı kodlayalım. Şaşırtıcı biçimde oldukça kolay:
Basit bir fonksiyon yazarak yukarıdaki tartışmayı birebir uygulayabiliriz! İşte en önemli noktalar:
Q,KveVtensörleri[batch_size, seq_len, dim]şeklindedirFarklı Attention Türleri
Ancak henüz söylemediğim önemli bir ayrıntı var. Transformer’da tek bir attention türü yok — aslında üç tane var:
Her biri biraz farklı bir rol oynar; hızlıca üzerinden geçelim.
Encoder self-attention
Şu ana kadar incelediğimiz şey budur: encoder içinde, her belirteç aynı girdi dizisindeki diğer tüm belirteçlere dikkat eder; “the cat sat on the mat.” örneğinde olduğu gibi.
Burada dikkat edilmesi gereken nokta, tüm girdinin baştan biliniyor olması nedeniyle herhangi bir kısıt olmamasıdır; bu da modelin her belirteç için, öncesini ve sonrasını anlayacak şekilde derin bağlamsal temsiller kurmasına olanak tanır.
Ayrıca bunun encoder’da gerçekleştiğini de not edin.
Decoder self-attention
Burada işler biraz daha zorlaşır. Artık decoder’da olduğumuz için, metin üretimi sırasında hile olmaması adına her belirtecin geleceği görmesini istemeyiz.
Başka bir örnek verelim: “Köpek çok yüksek sesle havladı.” Model “havladı”yı üretirken (basitlik için her kelimenin bir belirteç olduğunu varsayalım), bir sonraki belirtecin “çok” olduğunu bilmemelidir; aksi halde model yeni belirteç üretmeyi öğrenemez.
Bu sorunu çözmek için, bazen üçgen maske de denilen bir nedensel maske uygularız; bu maske her belirtecin yalnızca kendisine ve kendinden öncekilere dikkat etmesini, asla sonrakilere etmemesini sağlar.
Yukarıdaki diyagramdan, geleceğe ait attention skorlarının maskeleme ile kaldırıldığını; bunun da modelin yeni, doğru ve anlamlı belirteçler üretmeyi öğrenmesine olanak tanıdığını görebiliriz.
Encoder-decoder (çapraz) attention
Decoder üretime başladıktan sonra bile hâlâ orijinal girdiden (yanıt verdiği şey) bilgiye ihtiyaç duyar. İşte çapraz attention burada devreye girer.
Burada, decoder, encoder çıkışına dikkat eder. Dolayısıyla decoder self-attention maskelenmişken, çapraz attention maskelenmez ve decoder’ın tüm encoder belirteçlerine aynı anda bakmasına izin verilir.
Bu kavramı öğrenirken Çeviri Örneğini çok sevmiştim. “Bonjour tout le monde”’u İngilizceye çevirdiğinizi varsayın; decoder her bir İngilizce kelimeye karar verirken tüm Fransızca kelimelere bakabilmeli değil mi?
Çapraz attention tam olarak bunu yapar. Ancak bu yazının kapsamı için gerekli olmadığından burada çapraz attention’a daha derinlemesine girmeyeceğiz.
Multi-Head Attention İhtiyacı
Artık self-attention’ın nasıl çalıştığını anlıyoruz. Ama şimdi şu soru aklınıza gelebilir:
Zaten attention varken neden birden fazla kafa gerekli?
Bunun için, ilk öğrendiğimde sezgimi geliştiren el feneri benzetmesini sunmak istiyorum.
Tek bir attention kafasını, bir cümlenin önemli kısımlarını aydınlatmaya çalışan tek bir el feneri gibi düşünün. Oysa bir cümlede anlaşılması gereken birden fazla ilişki türü vardır: özne-fiil, nesne-zamir, sıfat-isim, uzun menzilli bağımlılıklar vb.
Her seferinde yalnızca tek bir ilişkiyi yakalamak yerine daha fazlasını yakalayabilsek daha iyi olmaz mıydı?
Dolayısıyla çözüm, modele her biri cümlenin farklı kısımlarına odaklanan birden fazla el feneri vermektir. Buna multi-head attention denir.
Tek bir Q, K, V kümesi hesaplayıp tek bir attention işlemi yapmak yerine, gömmeleri daha küçük parçalara böler ve birden çok bağımsız attention kafasını paralel olarak çalıştırırız.
Yukarıdaki diyagramda görüldüğü gibi, girdi gömmesi (basit tutmak için bu durumda tek bir belirteç için) n farklı kafa arasında eşit olarak bölünmüştür.
Örneğimizde, boyutun 512 ve kafa sayısının 8 olduğunu varsayalım; dolayısıyla her attention kafası paralel olarak (512/8=64) boyutu işler ve farklı ilişkileri yakalamaya çalışır.
Her bir kafanın hangi tür ilişkileri işleyebileceğine dair (hangisine baktığını tam olarak hâlâ bilmiyor olsak da) sezginizi daha da geliştirmek için basit bir örnek üzerinden gidelim:
Şu cümleyi ele alalım:
“The quick brown fox jumps over the lazy dog.”
Önemli olan, bu kafaların hepsinin eşzamanlı çalışması ve çıktılarının birleştirilip (concatenate) yeniden yansıtılarak (project) orijinal gömme boyutuna (bizim durumda 512) döndürülmesidir.
Birden çok kafayı kodla görselleştirme
Multi-Head Attention’ı tam olarak pekiştirmek için HuggingFace kütüphanesini kullanarak mekanizmanın nasıl çalıştığını görelim.
Önce, ilgili paketlerin tümünü indirmek için yukarıdaki kod hücresini çalıştırın.
Elde ettiğimiz çıktı aşağıda görülebilir. 12 farklı renk olduğuna dikkat edin; bu, modelde 12 Kafa olduğu anlamına gelir. Çizgilerin kalınlığı da belirteçler arasındaki attention skorlarının büyüklüğüyle ilişkilidir.
Multi-Head Attention’ın Uygulanması: En İyi Uygulamalar
Bu bölümde, Multi-Head Attention mekanizması için sözde kod (pseudocode) yazacağız. Önce girdimizin: X’in
[batch, seq_len, d_model]şeklinde olduğunu varsayalım.Sonra sözde koda geçebiliriz:
Bunların hepsi artık size tanıdık gelmeli; belki sadece son doğrusal yansıtma matrisi yeni olabilir.
Bunu da hızlıca ele alalım.
Tüm bireysel attention kafaları işini bitirdikten sonra, çıktıları tekrar tek bir vektörde birleştirilir. Ancak bu birleşik çıktının orijinal model boyutuna yeniden şekillendirilmesi gerekir ve burada son doğrusal yansıtma matrisi devreye girer. Birleştirilmiş çıktıyı, Transformer’daki bir sonraki katmana aktarılabilmesi için girdi gömmesiyle aynı boyuta eşler.
Bazı optimizasyon ve en iyi uygulamalardan da bahsedelim:
En iyi uygulamalar açısından, attention katmanını kodlarken bakmamız gereken 3 ana hiperparametre vardır:
num_heads: Paralel olarak kaç attention kafası çalıştırılacağı; d_model’ı tam bölmesi gerekir.head_dim: Her bir kafanın boyutu.dropout_rate: Aşırı uyumu önlemek için.Sonuç
Bu yazıda pek çok konuyu ele aldık. Basit bir fikirle başladık: attention odaklanma ile ilgilidir. Ardından, Transformer’ların bu odağı Sorgular, Anahtarlar ve Değerleri kullanarak her bir kelimenin diğer tüm kelimelerle ilişkisini hesaplayarak nasıl kullandığını inceledik.
Self-attention’ın (ve kısaca Nedensel ve Çapraz Attention gibi diğer türlerin) her belirtece zengin, bağlam farkında bir temsil kazandırdığını gördük. Sonra bir adım daha ileri giderek, tek bir “el fenerine” güvenmek yerine modele, cümledeki farklı örüntüleri aynı anda yakalayan birden fazla el feneri verdiğimiz multi-head attention’a geçtik.
Transformer’lara asıl güç veren şey budur. Sadece okuma yapmazlar; tüm diziler boyunca alttaki yapı, anlam ve ilişkileri kavrarlar.
Bu yazıda Transformer’ların bir yönünü ele aldık; ancak öğrenilecek daha çok şey var. Bu yüzden şu kapsamlı kursa göz atın: Transformer Models with PyTorch Course.
Uygulama tarafına dalmak istiyorsanız, OCR için Çok Girdili Modeller Geliştirme projesini veya HuggingFace ile Çalışma kursunu da öneririm. Yazıları tercih ediyorsanız, bu sezgisel PyTorch ile Bir Transformer Modeli İnşa Etmenin Eksiksiz Rehberi ve Vision Transformer’lar üzerine diğer rehberime göz atın.