Belirttiğiniz yönergeler doğrultusunda,
paylaştığınız dokümanın her bir satırını ve konusunu süre bilgilerinden tamamen
arındırarak, bol örnekli, uygulamalı ve derinlemesine bir rehber hâline
getirdim. Kursun içeriğinde yer alan tüm teorik kavramlar ve pratik aşamalar
aşağıda en detaylı şekilde açıklanmıştır.
📚
"Sıfırdan LLM Geliştirme: Kendi Dil Modelini Oluştur" Ders İçeriği
Analiz ve Uygulama Rehberi
🎯
"Öğrenecekleriniz" Bölümünün Detaylı Açıklaması
Bu bölüm, kursu tamamladığınızda kazanacağınız
temel mühendislik becerilerini ve yetkinlikleri özetler. Yapay zeka dünyasında sadece tüketici (hazır modelleri kullanan
biri) olmaktan çıkıp, üretici (mimariyi kuran, eğiten ve optimize eden)
konumuna gelmenizi hedefler. Bileşenlerin açıklamaları şu şekildedir:
🏗️
Derslerin Satır Satır Ele Alınması ve Derinlemesine
Açıklamaları
📹 Sıfırdan LLM
Geliştirme Tanıtım Videosu
Kursun yol haritası, neden sıfırdan model
geliştirilmesi gerektiği ve eğitim sonunda elde edilecek çıktılar bu bölümde
tanıtılır. Hazır API'lara bağımlı kalmadan yerel
imkanlarla model geliştirmenin önemi vurgulanır.
📚 LLM ile
İlgili Temel Terminoloji, Önemli Makaleler ve Siteler
Yapay zeka literatürüne
giriş adımıdır. Sektörde konuşulan ortak dili anlamak için teorik bir zemin
hazırlanır.
📝 Quiz 1
Temel terminoloji, yapay zeka
tarihindeki dönüm noktaları ve LLM mimarilerinin genel işleyiş mantığı üzerine
bilginizi test eden ilk değerlendirme aşamasıdır.
🛠️ LLM
Geliştirme için Gerekli Kurulum ve Araçlar
Kodlama ortamının hazırlanması adımıdır. Büyük
modeller yüksek işlem gücü gerektirdiğinden, doğru kütüphanelerin kurulması
kritiktir.
·
import torch
·
print("PyTorch Sürümü:", torch.__version__)
·
print("GPU
Kullanılabilir mi?:", torch.cuda.is_available())
📝 Quiz 2
Geliştirme ortamı ayarları, sanal ortam (virtual environment) yönetimi ve PyTorch temel tensör operasyonları hakkındaki bilgileri
ölçer.
✂️ Sıfırdan
Python ile Tokenizer Kodlama
Modeller metinleri doğrudan okuyamaz; onları
sayılara bölmek gerekir. Tokenizer, metni
bilgisayarın anlayacağı "token" adı verilen
parçalara ayıran yapıdır.
·
text = "yapay zeka gelecektir zeka gelecektir"
·
# Benzersiz
kelimeleri bulup sözlük (vocab) oluşturma
·
words = sorted(list(set(text.split())))
·
vocab = {word: i for i, word in enumerate(words)}
·
print("Sözlük (Vocab):", vocab)
·
·
# Metni
sayısal ID listesine dönüştürme (Encode)
·
sample = "zeka gelecektir"
·
encoded = [vocab[w] for w in sample.split()]
·
print("Sayısal
Karşılığı (Encoded):", encoded)
📝 Quiz 3
Kelimeleri ve karakterleri haritalandırma, sözlük
boyutu (vocabulary size) yönetimi ve bilinmeyen
kelimeler (UNK token) ile başa çıkma stratejilerini
test eder.
🌐 Açık Kaynak Tokenizer’ları Kullanma
Sıfırdan mantığı anladıktan sonra, endüstride dev
şirketlerin (OpenAI, Meta) kullandığı gelişmiş ve
optimize edilmiş hazır sistemleri entegre etmeyi öğrenirsiniz.
📝 Quiz 4
Hazır kütüphanelerin verimliliği, özel
karakterlerin (BOS, EOS gibi özel belirteçler) yönetimi ve tokenizasyon
hızlarının karşılaştırılması üzerine sorular içerir.
🧠 Sıfırdan Subword Tokenizer Kodlama
Kelime tabanlı tokenizer'lar
yeni kelimelerle karşılaştığında hata verir (Out of Vocabulary). Karakter tabanlılar ise çok yavaştır. İkisinin
ortası olan "Subword" (Alt kelime) mantığı
bu sorunu çözer.
📝 Quiz 5
Subword
algoritmalarının çalışma mantığı, nadir kelimelerin parçalanma biçimleri ve
sözlük verimliliği analiz edilir.
🛠️ SentencePiece ile BPE Tokenizer
Oluşturma ve Hugging Face’e
Yükleme
Google tarafından geliştirilen SentencePiece ve Byte Pair Encoding (BPE) algoritmalarını kullanarak profesyonel
düzeyde tokenizer üretimi yapılır.
·
# Gerçek
uygulamada Hugging Face Hub kütüphanesi kullanılır
·
from transformers import PreTrainedTokenizerFast
·
# Eğitilen tokenizer kuralları kaydedilir ve paylaşılır
·
print("Tokenizer Hugging Face Hub'a yüklenmeye
hazır.")
📏 Context Length ve Veri Seti
Hazırlama
Modelin bir seferde okuyabileceği maksimum metin
uzunluğuna (Context Length
/ Bağlam Penceresi) karar verilmesi ve verilerin buna göre dilimlenmesi
adımıdır.
📝 Quiz 7
Bağlam uzunluğunun bellek (RAM/VRAM) üzerindeki
etkileri, veri sızıntılarını önleme ve kayan pencere (sliding
window) veri hazırlama tekniklerini ölçer.
🗂️ PyTorch ile DataLoader Oluşturma
Eğitim sırasında verilerin modele tek tek değil,
gruplar halinde (Batch) hızlıca pompalanması gerekir.
DataLoader bu akışı yönetir.
·
import torch
·
from torch.utils.data import Dataset, DataLoader
·
·
class MetinVeriSeti(Dataset):
·
def __init__(self):
·
# Temsili token dizisi
·
self.data
= torch.randint(0, 1000, (100, 8)) # 100 örnek,
her biri 8 token
·
def __len__(self): return len(self.data)
·
def __getitem__(self, idx): return self.data[idx]
·
·
dataset = MetinVeriSeti()
·
dataloader = DataLoader(dataset, batch_size=4, shuffle=True)
·
ilk_grup = next(iter(dataloader))
·
print("İlk Batch Şekli (Batch Size, Context Length):", ilk_grup.shape)
📝 Quiz 8
Batch boyutu
seçimi, karıştırma (shuffle) mekanizmasının önemi ve DataLoader performans optimizasyonları sorgulanır.
📐 Embedding Katmanları ve Anlam Temsili
Kelimelerin sayısal ID'lerinin,
aralarındaki anlamsal ilişkiyi koruyacak şekilde çok boyutlu vektörlere
dönüştürüldüğü katmandır.
📝 Quiz 9
Matris çarpımı olarak embedding
mantığı, ağırlıkların güncellenmesi ve boyut sayısı (dimension)
seçim kriterlerini değerlendirir.
🔄 Sözlük ile Embedding Arasındaki Bağ
Sayısal bir token ID'sinin embedding matrisindeki
ilgili satıra nasıl denk geldiği ve bu geri alma (lookup)
işleminin matematiksel arka planı işlenir.
📝 Quiz 10
Embedding Lookup operasyonunun hesaplama maliyeti ve ağırlık
matrisinin ilk değer ataması (initialization)
konularını test eder.
📍 Basit Positional Embedding Uygulaması
Transformer modelleri,
metindeki kelimeleri sırayla değil hepsini aynı anda okur (paralel işlem). Bu
yüzden kelimelerin cümledeki sıra bilgisini (konumunu) modele eklemek
zorundayız.
📝 Quiz 11
Öğrenilebilir (learnable)
pozisyon embedding yapısının avantajları,
dezavantajları ve uzun metinlerde karşılaşılan sınırlandırmalar ele alınır.
🌊 Sinusoidal Positional Encoding Uygulaması
Öğrenilebilir pozisyon vektörleri yerine, sabit
matematiksel formüller (Sinüs ve Kosinüs dalgaları) kullanarak konum bilgisi
üretme yöntemidir.
📝 Quiz 12
Farklı frekanslardaki sinüs/kosinüs dalgalarının
matris izdüşümleri ve geometrik uzaklık ilişkileri test edilir.
🔄 Rotary Position Encoding (RoPE) Uygulaması
Günümüzdeki modern LLM'lerin
(LLaMA, Mistral)
kullandığı, kelimelerin birbirine göreceli uzaklıklarını çok daha iyi koruyan
gelişmiş bir konumlama tekniğidir.
📝 Quiz 13
Dönme matrisleri, karmaşık sayılarla konum
kodlama ve RoPE mimarisinin geleneksel yöntemlerden
farkları ölçülür.
🧱 Modelin
Temelini Oluşturmak
Oluşturulan tüm bu ön hazırlık bileşenlerinin (Tokenizer, Embedding ve Context Length kısıtlamaları) tek
bir çatı altında birleştirilmesidir.
📝 Quiz 14
nn.Module yapısı,
girdi-çıktı tensör boyutlarının kontrolü ve mimari iskeletin kurulması üzerine
sorular içerir.
🧠 Basit Self-Attention ile Bağlamı Anlamak
Bir kelimenin cümle içerisindeki diğer
kelimelerle olan ilişkisini (hangi kelimeye ne kadar dikkat etmesi gerektiğini)
hesaplayan, Transformer'ın en önemli mekanizmasıdır.
📝 Quiz 15
Attention matrisinin
mantığı, kelimelerin birbirine olan ağırlık payları ve hesaplama karmaşıklığı
incelenir.
📐 Manhattan
Mesafesiyle Anlamsal Yakınlığı Hesaplamak
İki kelime vektörünün birbirine ne kadar
benzediğini ölçmek için kullanılan geometrik bir yöntemdir.
📐 Kosinüs
Benzerliğiyle Anlamsal Yakınlığı Hesaplamak
Vektörlerin uzunluklarına bakmaksızın,
aralarındaki açıya odaklanarak yapılan anlamsal benzerlik ölçümüdür.
🧮 Attention Skoru Hesaplamak: QKV ve Softmax
Self-Attention
mekanizmasının matematiksel motorudur: Query (Soru), Key
(Anahtar) ve Value (Değer) matrisleri oluşturulur.
🛠️
Sıfırdan Self-Attention Katmanı Kodlama
Yukarıda anlatılan Q, K, V matris çarpımlarını ve
Softmax operasyonlarını hazır hiçbir şey kullanmadan PyTorch doğrusal katmanları (nn.Linear) ile kodlama
aşamasıdır.
🔒 Causal Self-Attention ve Dropout Uygulaması
Dil modelleri metin üretirken gelecekteki
kelimeleri görmemelidir, sadece geçmişe bakmalıdır. Causal
(Nedensel) mekanizma bunu sağlar. Dropout ise
ezberlemeyi (overfitting) önler.
🛡️ Masking, Truncation ve Yapısal
Hataları Önlemek
Eğitim esnasında verinin yapısından kaynaklanan
hataların (örneğin padding tokenlarının
model tarafından gerçek kelime gibi algılanması) önüne geçmek için uygulanan
maskeleme ve kesme teknikleridir.
📝 Quiz 21
Maskeleme matrislerinin (alt üçgen matris / lower triangular matrix) yapısı ve geleceği görme sızıntılarının nasıl
engellendiği sorgulanır.
👥 PyTorch ile Multi-Head Attention Kodlama
Tek bir attention
mekanizması yerine, cümlenin farklı yerlerine aynı anda odaklanabilen birden
fazla "baş" (Head) yapısının kurulmasıdır.
📝 Quiz 22
Çok başlı dikkat yapısının boyut bölüşümleri,
tensörlerin parçalanması (splitting) ve yeniden
birleştirilmesi (concatenation) işlemleri test
edilir.
⚖️ Layer Normalization Mantığı ve PyTorch ile Uygulaması
Eğitim sırasında sayıların çok büyümesini veya
küçülmesini önleyerek eğitimin stabil kalmasını sağlayan istatistiksel düzeltme
katmanıdır.
📝 Quiz 23
Batch Normalization ile Layer Normalization arasındaki farklar ve LLM'lerde
neden Layer Normalization
tercih edildiği sorulur.
⚡ Transformer’da Multi-Layer Perceptron (MLP) ve GeLU
Aktivasyonu
Attention katmanından
çıkan verilerin, daha derin kalıpları öğrenebilmesi için doğrusal olmayan bir
yapay sinir ağı katmanından (MLP) geçirilmesidir.
📝 Quiz 24
GeLU fonksiyonunun
matematiksel türevi, gradyan akışına etkisi ve MLP katmanının genişleme
katsayıları (expansion factor)
analiz edilir.
🧱 MLP ve Residual Bağlantılarla Decoder
Bloğu Kurma
Attention katmanı, Layer Norm ve MLP katmanını üst üste koyarak tam bir "Transformer Decoder" hücresi
(bloğu) inşa etme adımıdır.
📝 Quiz 25
Artık bağlantıların (residual
connections) gradyan patlaması/sönümlenmesini nasıl
engellediği ve blokların üst üste eklenme limitleri test edilir.
🔮 LM Head ile Kelime Tahmini Yapmak
Modelin en son katmanıdır. İçerideki karmaşık
sayısal vektörleri tekrar bizim sözlüğümüzdeki kelime olasılıklarına
dönüştürür.
📝 Quiz 26
Dil modeli kafasının (Language Model Head) ağırlık paylaşımı (weight tying) konsepti ve çıktı boyutu hesaplamaları işlenir.
📊 Logits ve Loss Fonksiyonunu
Anlamak
Modelin ürettiği ham tahmin skorlarına "Logits" denir. Loss (Kayıp)
fonksiyonu ise modelin ne kadar yanlış tahmin yaptığını ölçer.
📝 Quiz 27
Logit'lerin ham
olasılıklara dönüştürülme süreçleri ve Cross-Entropy
fonksiyonunun matematiksel tabanı test edilir.
📉 Loss, Optimizer ve Backpropagation’u Anlamak
Modelin yaptığı hatadan ders çıkararak kendi
ağırlıklarını (parametrelerini) güncelleme mekanizmasıdır.
📝 Quiz 28
Türev alma zincir kuralı (chain
rule), AdamW gibi
optimizasyon algoritmalarının çalışma mekanizması sorgulanır.
🔁 Dataset, Tokenizer ve Eğitim
Döngüsü Kurmak
Artık tüm parçalar hazırdır. Kendi metin veri
setimiz, kendi eğittiğimiz tokenizer ve inşa
ettiğimiz Transformer modeli gerçek bir eğitim
döngüsüne (for epoch in range...) sokulur.
📝 Quiz 29
Eğitim adımı (step) ile devir (epoch) arasındaki farklar, öğrenme oranı (learning rate) zamanlaması (scheduling)
konuları ele alınır.
💾 PyTorch ile Model Kaydetme ve Yükleme (torch.save & load_state_dict)
Saatlerce veya günlerce eğitilen modelin
bilgisayara dosya olarak kaydedilmesi ve gerektiğinde kaldığı yerden geri
yüklenmesi işlemidir.
·
# Temsili
kaydetme adımı
·
model_ornek = torch.nn.Linear(10, 2)
·
torch.save(model_ornek.state_dict(), "model_ağırlıkları.pth")
·
print("Model
başarıyla diske kaydedildi.")
·
·
# Temsili geri
yükleme adımı
·
yeni_model = torch.nn.Linear(10, 2)
·
yeni_model.load_state_dict(torch.load("model_ağırlıkları.pth"))
·
print("Model
ağırlıkları dosyadan geri yüklendi.")
📝 Quiz 30
Sadece ağırlıkları kaydetmek ile tüm modeli
kaydetmek arasındaki farklar ve checkpoint yönetimi
test edilir.
📓 Notebook’u
Birleştirip Yayına Hazırlamak
Parça parça kodlanan tüm hücrelerin tek bir temiz
kod dosyasına (Notebook) toplanması ve baştan sona hatasız çalışacak ilk
sürümün (v1 LLM from scratch)
oluşturulmasıdır.
📝 Quiz 31
Kod modülaritesi, kod
blokları arası veri tipi uyumluluğu ve temiz kod yazım prensipleri ölçülür.
✍️ LLM için Generate Fonksiyonu Yazmak
Eğitilen modelin kullanıcıdan gelen bir kelimeye
bakarak kendi kendine yeni cümleler üretmesini (Metin üretimi) sağlayan
döngüsel fonksiyondur.
📝 Quiz 32
Ototekrarlı (autoregressive) üretim mantığı ve nesil üretim döngüsündeki
bellek verimliliği incelenir.
🖥️ Gradio ile Chatbot Arayüzü
Geliştirmek (Bölüm 1 & 2)
Yazdığınız siyah ekran kodunu, herkesin
tarayıcıdan girip mesajlaşabileceği modern bir sohbet robotu arayüzüne
dönüştürme adımıdır.
📝 Quiz 33 ve Quiz 34
Web arayüz entegrasyonu, eşzamansız
(async) istek yönetimi ve kullanıcı oturum
senaryoları test edilir.
🚀 CPU'dan GPU'ya Geçiş ve Batch Processing
Modelin bilgisayar işlemcisinden (CPU) alınıp,
yapay zekayı yüzlerce kat hızlı çalıştırabilen ekran kartına (GPU) taşınması ve
çoklu veri işleme süreçleridir.
📝 Sınav 29
Batch Processing ve Padding: Aynı anda
birden fazla soruya cevap verirken kısa kalan cümlelerin sonuna eklenen dolgu (Padding) tokenlarının attention mekanizması tarafından nasıl göz ardı edileceği
üzerine pratik sınavdır.
📝 Sınav 30
Batch Processing ve MPS ile Hızlandırmak: Apple silicon işlemcili Mac bilgisayarlarda GPU hızlandırması
sağlayan MPS (Metal Performance Shaders)
altyapısının PyTorch ile konfigüre edilmesini ölçen
sınavdır.
📝 Sınav 35
Temperature, Top-P ve
Top-K Nedir?: Modelin ürettiği metinlerin yaratıcılığını ve
doğruluğunu kontrol eden hiperparametre teorisidir.
📝 Sınav 31
Temperature, Top-P ve
Top-K Kodlama: Softmax işleminden
hemen sonra gelen logit değerlerini formüllerle
filtreleyen ve en yüksek olasılıklı kelime gruplarını seçen matematiksel
filtreleme kodunun PyTorch ile yazılması sınavıdır.
📝 Sınav 32
Top-P (Nucleus) Sampling Nedir?: Kelimeleri en
yüksek olasılıktan başlayarak kümülatif (toplam) olasılık değerine göre
filtreleyen tekniktir.
📝 Sınav 33
Arayüzü Geliştirip Parametre Kontrolü Eklemek: Gradio arayüzüne kaydırma çubukları (Slider)
ekleyerek, kullanıcının sohbet ederken Temperature,
Top-K ve Top-P değerlerini canlı olarak değiştirebilmesini sağlayan kodlama
sınavıdır.
🎓 Sınav 34
LLM Fine-Tuning ve
Dağıtım Eğitimi: Modelin genel yeteneklerini kazandıktan sonra
özel bir alanda uzmanlaşması (Fine-Tuning) ve
sunucuya kurulması aşamasıdır.
📝
"Açıklama" Paragraflarının Detaylı Çözümlemesi
Paylaştığınız belgenin alt kısımlarında yer alan
"Açıklama" paragrafları, kursun genel felsefesini, hedef kitlesini ve
nihai vizyonunu ortaya koymaktadır:
Müfredatta yer alan tüm ana başlıkları, mantığını
en şeffaf şekilde görebilmeniz için hazır kütüphane (Hugging
Face vb.) kullanmadan, saf Python ve PyTorch ile çalıştırılabilir kod demoları haline
getirdim.
Bu demoları sırasıyla kopyalayıp bir Jupyter Notebook veya Google Colab
hücresinde doğrudan çalıştırabilirsiniz.
1. Sıfırdan
Python ile Tokenizer Kodlama (Kelimeden ID'ye)
Amaç: Ham metni kelimelerine ayırmak, benzersiz bir
sözlük (vocab) kurmak ve metni sayısal verilere (encode) dönüştürüp tekrar geri çözmek (decode).
class BasitTokenizer:
def __init__(self):
self.word2id =
{}
self.id2word =
{}
self.unk_token
= "<UNK>"
self.pad_token
= "<PAD>"
def sozluk_olustur(self, metinler):
# Özel
belirteçleri ekle
benzersiz_kelimeler = [self.pad_token, self.unk_token]
# Metindeki
tüm kelimeleri temizleyip topla
for metin in metinler:
temiz_metin = metin.lower().replace(".", " .").replace(",", " ,")
for kelime in temiz_metin.split():
if kelime not in benzersiz_kelimeler:
benzersiz_kelimeler.append(kelime)
# Çift yönlü
sözlük haritalama
self.word2id =
{kelime: i for i, kelime in enumerate(benzersiz_kelimeler)}
self.id2word =
{i: kelime for i, kelime in enumerate(benzersiz_kelimeler)}
print(f"✓ Sözlük başarıyla kuruldu. Toplam Kelime Sayısı: {len(self.word2id)}")
def encode(self, metin):
temiz_metin = metin.lower().replace(".", " .").replace(",", " ,")
token_ids = []
for kelime in temiz_metin.split():
# Kelime sözlükte yoksa <UNK> ID'sini ver
token_ids.append(self.word2id.get(kelime,
self.word2id[self.unk_token]))
return token_ids
def decode(self, ids):
return " ".join([self.id2word.get(i, self.unk_token) for i in ids])
# --- UYGULAMA VE TEST ---
egitim_verisi = ["Yapay
zeka gelecektir.", "Kendi dil modelini sıfırdan kur."]
tokenizer = BasitTokenizer()
tokenizer.sozluk_olustur(egitim_verisi)
# Test Etme
ornek_metin = "Yapay
zeka modelini kur."
encoded_ids = tokenizer.encode(ornek_metin)
decoded_metin = tokenizer.decode(encoded_ids)
print(f"\nGirdi Metin: '{ornek_metin}'")
print(f"Sayısal ID Karşılığı (Modelin Okuduğu): {encoded_ids}")
print(f"Geri Çözülen Metin (Decode):
'{decoded_metin}'")
2. PyTorch ile Dataset ve DataLoader Oluşturma
Amaç: Metin tabanlı sayısal verileri, yapay zekanın
eğitim esnasında tüketeceği "Girdi (X)" ve "Hedef/Etiket
(Y)" (Next-Token Prediction)
çiftleri halinde gruplara (Batch) ayırmak.
import torch
from torch.utils.data import Dataset, DataLoader
class YapayZekaVeriSeti(Dataset):
def __init__(self, token_ids, baglam_uzunlugu):
self.token_ids
= torch.tensor(token_ids, dtype=torch.long)
self.baglam_uzunlugu
= baglam_uzunlugu
def __len__(self):
# Toplam kaç
tane kayan pencere örneği çıkarabileceğimizi hesapla
return len(self.token_ids)
- self.baglam_uzunlugu
def __getitem__(self, idx):
# X: Mevcut
kelimeler, Y: Bir sonraki kelime (X'in bir adım
kaymış hali)
x = self.token_ids[idx : idx + self.baglam_uzunlugu]
y = self.token_ids[idx + 1 : idx + self.baglam_uzunlugu + 1]
return x, y
# --- UYGULAMA VE TEST ---
# Temsili olarak tokenizer'dan geçmiş 20 adet kelime ID'si
düşünelim
yapay_tokenler = [3, 7, 2, 9, 11, 5, 8, 4, 14, 1, 9, 2, 5, 12, 6, 8, 3, 15, 7, 10]
BAGLAM_PENCERESI = 4 # Model tek
seferde 4 kelimeye bakarak sonraki kelimeyi tahmin edecek
BATCH_BOYUTU = 2 # Her adımda 2 adet örnek eğitilecek
veri_seti = YapayZekaVeriSeti(yapay_tokenler, baglam_uzunlugu=BAGLAM_PENCERESI)
veri_yukleyici = DataLoader(veri_seti, batch_size=BATCH_BOYUTU,
shuffle=True)
# İlk veri grubunu inceleyelim
ilk_x, ilk_y = next(iter(veri_yukleyici))
print("Girdi
Paketi (Batch X):\n", ilk_x)
print("Hedef
Paketi (Batch Y - Bir sonraki kelimeler):\n", ilk_y)
print(f"\nTensör Boyutları -> X: {ilk_x.shape}, Y: {ilk_y.shape}")
3. Embedding Katmanı ve Anlam Temsili
Amaç: Kelime ID'lerini
rastgele sayılar olmaktan çıkarıp, çok boyutlu uzayda yönü ve büyüklüğü olan
anlam vektörlerine dönüştürmek.
import torch
import torch.nn as nn
# Varsayalım ki sözlüğümüzde (vocab) toplam 10 kelime var.
SOZLUK_BOYUTU = 10
# Her kelimeyi ifade etmek için 4
boyutlu bir uzay seçtik.
EMBEDDING_BOYUTU = 4
# PyTorch
Embedding Katmanı Oluşturma
embedding_katmani = nn.Embedding(num_embeddings=SOZLUK_BOYUTU, embedding_dim=EMBEDDING_BOYUTU)
# Girdi olarak az önceki DataLoader'dan gelen ilk_x
paketini (2 örnek, 4'er kelime) verelim
girdi_tokenleri = torch.tensor([[2, 5, 1, 8],
[4, 9, 3, 2]], dtype=torch.long)
# Kelimeleri Vektör Uzayına
Taşıyalım
vektor_karsiliklari = embedding_katmani(girdi_tokenleri)
print("Girdi
Boyutu (Batch, Context Length):", girdi_tokenleri.shape)
print("Çıktı
Boyutu (Batch, Context Length, Embedding Dim):", vektor_karsiliklari.shape)
print("\nİlk Cümlenin İlk Kelimesinin 4 Boyutlu Anlam
Vektörü:\n", vektor_karsiliklari[0, 0])
4. Sinusoidal Positional Encoding (Konum Bilgisi Enjeksiyonu)
Amaç: Modele kelimelerin cümledeki sırasını (0.
kelime, 1. kelime vb.) anlatmak için sabit matematiksel dalgalar kullanarak
konum matrisi üretmek ve bunu kelime vektörleriyle toplamak.
import torch
import math
def konumsal_kodlama_uret(baglam_uzunlugu, embedding_boyutu):
# Boş bir
konum matrisi oluştur
pe = torch.zeros(baglam_uzunlugu, embedding_boyutu)
# Pozisyon
indeksleri (0, 1, 2...)
pozisyon = torch.arange(0, baglam_uzunlugu, dtype=torch.float).unsqueeze(1)
# Frekans
bölenlerini hesapla
div_term = torch.exp(torch.arange(0, embedding_boyutu, 2).float()
* (-math.log(10000.0) / embedding_boyutu))
# Çift
indekslere Sinüs, tek indekslere Kosinüs dalgası yerleştir
pe[:, 0::2] = torch.sin(pozisyon
* div_term)
pe[:, 1::2] = torch.cos(pozisyon
* div_term)
return pe
# --- UYGULAMA VE TEST ---
KONUM_MATRISI = konumsal_kodlama_uret(baglam_uzunlugu=4, embedding_boyutu=4)
print("Üretilen
Sabit Konum Matrisi (Her satır bir pozisyonu temsil eder):\n", KONUM_MATRISI)
# Bir önceki adımdaki kelime
vektörlerine konum bilgisini ekleyelim (Matris Toplaması)
# Kelime anlamları + Kelime
konumları = Tam Temsil
nihai_girdi = vektor_karsiliklari + KONUM_MATRISI.unsqueeze(0) # Batch boyutuna uyumlu hale getirdik
print("\nHem Anlam Hem Konum İçeren Yeni Vektör Boyutu:", nihai_girdi.shape)
5. Sıfırdan Causal Self-Attention Katmanı
Kodlama
Amaç: Kelimelerin birbirleriyle olan bağlarını
hesaplamak ve metin üretirken gelecekteki kelimeleri görmesini engellemek (Masking).
import torch
import torch.nn as nn
import torch.nn.functional as F
class NedenselDikkatKatmani(nn.Module):
def __init__(self, d_model):
super().__init__()
# Query, Key ve Value matris dönüşümleri için doğrusal katmanlar
self.query
= nn.Linear(d_model, d_model)
self.key = nn.Linear(d_model,
d_model)
self.value
= nn.Linear(d_model, d_model)
def forward(self, x):
B, T, C = x.shape
# Batch, Time (Context), Channels (Embedding Dim)
# Q, K, V
matrislerini üretelim
q = self.query(x)
k = self.key(x)
v = self.value(x)
# Kelimelerin
birbiriyle eşleşme skorlarını bul (Enerji Matrisi)
# Sorumuz (Q)
ile Anahtarları (K) çarpıyoruz
skorlar = torch.bmm(q, k.transpose(1, 2)) / (C ** 0.5) # Ölçeklendirilmiş çarpım
# CAUSAL
MASKING (Geleceği Gizleme): Üst üçgeni eksi sonsuz yap
maske = torch.tril(torch.ones(T, T)).view(1, T, T)
skorlar = skorlar.masked_fill(maske == 0, float('-inf'))
# Olasılıklara
dönüştür (Satır toplamları 1 olacak şekilde)
dikkat_haritasi = F.softmax(skorlar, dim=-1)
# Ağırlıklarla
değerleri (V) çarpıp bağlamsal çıktı üret
cikti = torch.bmm(dikkat_haritasi,
v)
return cikti, dikkat_haritasi
# --- UYGULAMA VE TEST ---
dikkat_motoru = NedenselDikkatKatmani(d_model=4)
katman_cikti, harita = dikkat_motoru(nihai_girdi)
print("Maskelenmiş
Dikkat Ağırlık Matrisi (İlk Örnek):\n", harita[0])
print("\nDikkat Sonrası Yeni Vektör Boyutu (Giriş ile Aynı
Kalmalı):", katman_cikti.shape)
# Dikkat ederseniz matrisin sağ üst
köşesi tamamen 0.0 oldu.
# Yani 1. kelime üretilirken 2, 3
ve 4. kelimelere bakması tamamen engellendi!
6. MLP (Feed Forward) ve GeLU Aktivasyon Fonksiyonu
Amaç: Attention katmanından
gelen verileri doğrusal olmayan (GeLU) bir
süzgeçten geçirerek daha üst düzey semantic
(anlamsal) çıkarımlar yapmasını sağlamak.
class TransformerMLP(nn.Module):
def __init__(self, d_model):
super().__init__()
# Genişleme
katmanı (Genelde mimari boyutun 4 katına genişletilir)
self.fc1 = nn.Linear(d_model, d_model * 4)
# Daraltma
katmanı (Eski orijinal boyuta geri getirir)
self.fc2 = nn.Linear(d_model * 4, d_model)
def forward(self, x):
# Genişlet -> GeLU
Aktivasyonundan Geçir -> Tekrar Daralt
x = self.fc1(x)
x = F.gelu(x)
x = self.fc2(x)
return x
# --- UYGULAMA VE TEST ---
mlp_katmani = TransformerMLP(d_model=4)
mlp_cikti = mlp_katmani(katman_cikti)
print("MLP
İşleminden Geçen Tensörün Son Hali:", mlp_cikti.shape)
7. Model
Kaydetme ve Yükleme Mantığı (state_dict)
Amaç: Tasarlanan sinir ağının eğitildikten sonra disk
üzerine kaydedilmesi ve ardından sıfır bir nesneye enjekte edilerek
canlandırılması.
# Temsili bir katman oluşturalım ve
içindeki eğitilebilir rastgele ağırlıklara bakalım
orijinal_katman = nn.Linear(2, 2)
print("Orijinal
Katmanın Ağırlık Matrisi:\n", orijinal_katman.weight.data)
# Ağırlıkları Bilgisayara Bir Dosya
Olarak Kaydedelim
torch.save(orijinal_katman.state_dict(),
"gecici_model.pth")
print("\n✓ Ağırlıklar 'gecici_model.pth' adıyla diske yazıldı.")
# Şimdi tamamen sıfır ve içi farklı
sayılarla dolu yeni bir katman oluşturalım
yeni_katman = nn.Linear(2, 2)
print("\nYükleme Yapılmadan Önce Yeni Katmanın Rastgele
Ağırlığı:\n", yeni_katman.weight.data)
# Diskteki dosyayı okuyup yeni
katmanın içine enjekte edelim
yeni_katman.load_state_dict(torch.load("gecici_model.pth"))
print("\nYükleme Yapıldıktan Sonra Yeni Katmanın Ağırlığı (Orijinal
ile Aynı Oldu!):\n", yeni_katman.weight.data)
8. Metin
Üretim Algoritması (Temperature Süzgeci ve Multinomial Örnekleme)
Amaç: Modelin ürettiği kelime skorlarını (Logits) çeşitlendirmek. Temperature parametresi
ile modelin yaratıcılığını artırıp azaltmak ve rastgele kelime seçimi yapmak.
def sonraki_tokeni_sec(logits, temperature=1.0):
# Logit değerlerini sıcaklık parametresine bölüyoruz
# Sıcaklık 0'a
yaklaştıkça en yüksek puanlı kelime kesinleşir (Daha az yaratıcı)
# Sıcaklık
büyüdükçe olasılıklar birbirine yaklaşır (Daha çılgın/yaratıcı)
logits = logits / temperature
# Skorları Softmax ile %0 ile %100 arasında
ihtimallere dönüştür
olasiliklar = F.softmax(logits, dim=-1)
# Multinomial (Çoklu terimli) örnekleme yaparak torbadan
bilye çeker gibi kelime ID'si seç
secilen_id = torch.multinomial(olasiliklar, num_samples=1)
return secilen_id, olasiliklar
# --- UYGULAMA VE TEST ---
# Sözlüğümüzde 5 kelime olduğunu ve
modelin bu kelimeler için ürettiği tahmin skorlarını düşünelim
ornek_logits = torch.tensor([2.0, 4.5, 1.0, -0.5, 3.0])
print("---
YÜKSEK SICAKLIK (Temperature = 1.5) | Daha
Riskli/Çeşitli ---")
secim, ihtimaller = sonraki_tokeni_sec(ornek_logits, temperature=1.5)
print("Kelimelerin
Seçilme İhtimalleri (%):",
(ihtimaller * 100).tolist())
print("Seçilen
Kelime ID'si:", secim.item())
print("\n---
DÜŞÜK SICAKLIK (Temperature = 0.2) | Daha
Güvenli/Deterministik ---")
secim, ihtimaller = sonraki_tokeni_sec(ornek_logits, temperature=0.2)
print("Kelimelerin
Seçilme İhtimalleri (%):",
(ihtimaller * 100).tolist())
print("Seçilen
Kelime ID'si:", secim.item())
# Dikkat ederseniz sıcaklık
düştüğünde 2. indeksteki kelimenin şansı neredeyse %99'a
fırladı!
İşte yukarıda parça parça kodladığımız tüm yapı taşlarını (Tokenizer,
Embedding, Positional Encoding, Causal Self-Attention, MLP ve Üretim Algoritması) tek bir çatı altında
toplayan, saf PyTorch ile yazılmış, gerçekten
eğitebileceğiniz ve cümle tamamlatabileceğiniz mini bir GPT modeli.
Bu kod bloğunun tamamını kopyalayıp tek bir
hücrede çalıştırabilirsiniz. Kodun içinde küçük bir metin veri seti
oluşturulmuş ve modelin bu veriyi nasıl ezberleyip yeni cümleler ürettiği adım
adım simüle edilmiştir.
import torch
import torch.nn as nn
import torch.nn.functional as F
import math
#
==========================================
# 1. HAZIRLIK: VERİ SETİ VE BASİT
TOKENIZER
#
==========================================
# Modelin eğitileceği küçük metin
kümesi
ham_veri = """
yapay zeka gelecektir. kendi dil modelini sıfırdan kur.
yapay zeka insanlığa yardım eder. kendi modelini eğit
ve çalıştır.
sıfırdan gpt mimarisi kurmak çok eğlencelidir.
"""
class KarakterTokenizer:
"""Karakter
tabanlı basit bir tokenizer (Eğitim kolaylığı
için)"""
def __init__(self, metin):
self.chars
= sorted(list(set(metin)))
self.vocab_size
= len(self.chars)
self.char2id =
{ch: i for i, ch in enumerate(self.chars)}
self.id2char =
{i: ch for i, ch in enumerate(self.chars)}
def encode(self, s): return
[self.char2id[c] for c in s]
def decode(self, l): return ''.join([self.id2char[i] for i in l])
tokenizer = KarakterTokenizer(ham_veri)
veri_sayisal = tokenizer.encode(ham_veri)
#
==========================================
# 2. MODEL BİLEŞENLERİ (TRANSFORMER
MOTORU)
#
==========================================
class NedenselDikkat(nn.Module):
"""Causal Self-Attention
Katmanı"""
def __init__(self, d_model):
super().__init__()
self.query
= nn.Linear(d_model, d_model)
self.key = nn.Linear(d_model,
d_model)
self.value
= nn.Linear(d_model, d_model)
self.d_model
= d_model
def forward(self, x):
B, T, C = x.shape
q = self.query(x)
k = self.key(x)
v = self.value(x)
# Dikkat
skorlarını hesapla
skorlar = torch.bmm(q, k.transpose(1, 2)) / (C ** 0.5)
# Maskeleme
(Geleceği gizleme)
maske = torch.tril(torch.ones(T, T, device=x.device)).view(1, T, T)
skorlar = skorlar.masked_fill(maske == 0, float('-inf'))
dikkat_haritasi = F.softmax(skorlar, dim=-1)
return torch.bmm(dikkat_haritasi, v)
class BasitMLP(nn.Module):
"""Feed Forward Network ve GeLU Aktivasyonu"""
def __init__(self, d_model):
super().__init__()
self.fc1 = nn.Linear(d_model, d_model * 4)
self.fc2 = nn.Linear(d_model * 4, d_model)
def forward(self, x):
return self.fc2(F.gelu(self.fc1(x)))
class TransformerBloku(nn.Module):
"""Geleneksel
bir GPT Bloğu (Attention + MLP + Residual
+ LayerNorm)"""
def __init__(self, d_model):
super().__init__()
self.ln1 = nn.LayerNorm(d_model)
self.ln2 = nn.LayerNorm(d_model)
self.attention
= NedenselDikkat(d_model)
self.mlp = BasitMLP(d_model)
def forward(self, x):
# Önce Normalizasyon -> Sonra Attention
-> Başlangıç girdisi ile topla (Residual)
x = x + self.attention(self.ln1(x))
# Önce Normalizasyon -> Sonra MLP -> Tekrar topla
x = x + self.mlp(self.ln2(x))
return x
#
==========================================
# 3. ANA MODEL: MİNİ GPT MİMARİSİ
#
==========================================
class MiniGPT(nn.Module):
def __init__(self, vocab_size, d_model, context_length):
super().__init__()
self.context_length
= context_length
# Kelime
(Karakter) anlam haritası
self.token_embedding
= nn.Embedding(vocab_size, d_model)
# Pozisyon
(Konum) anlam haritası (Öğrenilebilir pozisyon seçtik)
self.position_embedding
= nn.Embedding(context_length,
d_model)
# Üst üste
binen 3 adet güçlü deşifre edici blok
self.bloklar
= nn.Sequential(
TransformerBloku(d_model),
TransformerBloku(d_model),
TransformerBloku(d_model)
)
self.ln_final
= nn.LayerNorm(d_model)
self.lm_head
= nn.Linear(d_model, vocab_size) # Vektörleri
tekrar harflere dönüştüren kafa
def forward(self, idx, targets=None):
B, T = idx.shape
# Girişleri
hazırla
tok_emb = self.token_embedding(idx)
pos_emb = self.position_embedding(torch.arange(T, device=idx.device))
x = tok_emb + pos_emb # Anlam ve konum toplandı
# Transformer katmanlarından geçir
x = self.bloklar(x)
x = self.ln_final(x)
logits = self.lm_head(x) # Tahmin skorları (Logits)
# Eğer eğitim
yapılıyorsa Loss (Hata) hesapla
loss = None
if targets is not None:
B, T, C = logits.shape
logits_duz = logits.view(B*T, C)
targets_duz = targets.view(B*T)
loss = F.cross_entropy(logits_duz,
targets_duz)
return logits, loss
def generate(self, idx, max_new_tokens, temperature=1.0):
"""Modelin
ototegrarlı olarak metin üretmesini sağlayan
fonksiyon"""
for _ in range(max_new_tokens):
# Bağlam penceresinden uzun girdileri kırp
idx_cond = idx[:, -self.context_length:]
logits, _ = self(idx_cond)
# Sadece cümlenin en son üretilen harfinin tahminlerine odaklan
logits = logits[:, -1, :] / temperature
probs = F.softmax(logits, dim=-1)
# Sonraki karakteri seç ve mevcut metne ekle
idx_next = torch.multinomial(probs, num_samples=1)
idx = torch.cat((idx, idx_next),
dim=1)
return idx
#
==========================================
# 4. HİPERPARAMETRELER VE EĞİTİM
DÖNGÜSÜ
#
==========================================
# Cihaz seçimi (GPU varsa
kullanılır, yoksa CPU)
cihaz = "cuda" if torch.cuda.is_available() else "cpu"
CONTEXT_LENGTH = 16 # Model tek
seferde geriye dönük en fazla 16 karaktere bakabilir
D_MODEL = 64 # Her bir karakterin ifade edildiği vektör boyutu
model = MiniGPT(vocab_size=tokenizer.vocab_size, d_model=D_MODEL, context_length=CONTEXT_LENGTH).to(cihaz)
optimizer = torch.optim.AdamW(model.parameters(),
lr=1e-3)
print("🚀 Mini GPT Modeli Eğitiliyor (Lütfen Bekleyin)...")
model.train()
# 1000 adımlık hızlı bir eğitim
döngüsü
for adim in range(1000):
# Rastgele bir
kayan pencere seçerek Batch oluşturma
idx = torch.randint(0, len(veri_sayisal) - CONTEXT_LENGTH, (32,))
x = torch.stack([torch.tensor(veri_sayisal[i:i+CONTEXT_LENGTH])
for i in idx]).to(cihaz)
y = torch.stack([torch.tensor(veri_sayisal[i+1:i+CONTEXT_LENGTH+1]) for i in idx]).to(cihaz)
# İleri
Besleme ve Hata Hesaplama
logits, loss = model(x, y)
# Geriye
Yayılım (Backpropagation) ve Güncelleme
optimizer.zero_grad()
loss.backward()
optimizer.step()
if adim % 200 == 0:
print(f"Adım {adim:4d} | Güncel Hata (Loss): {loss.item():.4f}")
print("✓ Eğitim tamamlandı. Hata başarıyla düşürüldü.\n")
#
==========================================
# 5. TEST VE METİN ÜRETİMİ
(GENERATE)
#
==========================================
model.eval()
baslangic_metni = "yapay
zeka "
print(f"🤖 Model Başlangıç İpucunu Alıyor: '{baslangic_metni}'")
# Metni sayısal verilere dönüştür
ve Batch boyutunu (1) ekle
girdi_tensör = torch.tensor([tokenizer.encode(baslangic_metni)],
dtype=torch.long, device=cihaz)
# Modelden 60 karakterlik bir devam
metni üretmesini isteyelim
uretilen_id_listesi = model.generate(girdi_tensör, max_new_tokens=60, temperature=0.7)
nihai_metin = tokenizer.decode(uretilen_id_listesi[0].tolist())
print(f"\n✨ Modelin Tamamladığı Cümle:\n{nihai_metin}")
💡 Kod
Çalıştığında Ne Oluyor?
Sağladığınız
belgeyi satır satır ve bölüm bölüm
ele alarak, hiçbir konuyu atlamadan, özetlemeden, süre bilgilerini tamamen
kaldırarak ve her kavramı günlük hayattan benzetmelerle detaylandırarak
açıklıyoruz. Bu uzun ve teknik eğitim içeriğini 4. sınıf düzeyinde, herkesin
anlayabileceği çok basit bir dille maddeler halinde işleyeceğiz.
BÖLÜM 1: Giriş ve "Öğrenecekleriniz" Paragrafının Detaylı
Açıklaması
Bu kursta
büyük dil modellerinin (yani bilgisayarların bizim gibi konuşmasını sağlayan
sistemlerin) içini açıp her bir parçanın nasıl çalıştığını öğreneceksiniz.
Kursun "Öğrenecekleriniz" kısmında yer alan tüm terimlerin ne anlama
geldiği aşağıda detaylıca açıklanmıştır:
BÖLÜM 2: Kurs Müfredatının Satır Satır Detaylı
İncelenmesi
Müfredatta yer
alan tüm ders başlıklarını ve uygulamaları sırasıyla ele alıyoruz:
Başlangıç ve Ön Gereksinimler
Kelimeleri Sayılara Dönüştürme (Tokenization ve Embeddings)
Kelime Anlam Haritaları (Word Embeddings)
Büyük Dil Modellerini İnşa Etme Dönemi
Yapay Zekayı Eğitme ve Optimizasyon
İnce Ayar (Fine-Tuning) ve Özelleştirme
Komut Eğitimi (Instruction Tuning)
ve Chatbot Yapımı
Yapay Zeka Modellerini Sınava Sokmak (Değerlendirme -
Evaluation)
Yapay Zekanın İçini Açıp İncelemek (Mechanistic Interpretability)
Müdahale Ederek Yapay Zekayı Değiştirme (Causal
Mech Interp)
Matematik ve Python Temelleri (Kursun Sonundaki Destek Bölümleri)
Kursun en
sonunda, yukarıdaki ağır konuları yapabilmeniz için gereken tüm temel dersler
sıfırdan anlatılmaktadır:
BÖLÜM 3: "Açıklama:" Paragraflarının Detaylı İncelemesi
Belgenin alt
kısmındaki tanıtım ve açıklama yazılarının içerdiği mesajlar ve detaylar
şunlardır:
Büyük Dil
Modelleri (LLM) mimarisinin, eğitim optimizasyonunun ve Mekanik
Anlaşılabilirlik (Mechanistic Interpretability)
dünyasının kalbinde yer alan en kritik matematiksel formülleri ve bunların
sıfırdan Python / PyTorch kodlarını içeren devasa bir
teknik rehberi aşağıda bulabilirsiniz.
Her konu; Matematiksel
Mantık, Temiz ve Çalıştırılabilir PyTorch Kodu
ve 4. Sınıf Seviyesinde Basit Benzetme adımlarıyla ele alınmıştır.
1. KISIM: LLM MİMARİSİ VE ÇEKİRDEK MATEMATİK
1.1. Öz-Dikkat (Self-Attention) Mekanizması
Matematiksel Formül
Giriş matrisi
dizisi X olduğunda; Sorgu (Q), Anahtar (K) ve Değer (V) matrisleri doğrusal
projeksiyonlarla elde edilir. Dikkat katsayıları, Q ve K'nın
nokta çarpımı alınıp, anahtar boyutunun kareköküne ($\sqrt{d_k}$)
bölünerek ölçeklenir. Ardından satır bazında Softmax
uygulanarak ağırlıklar bulunur:
$$Q = XW_Q, \quad K = XW_K, \quad V = XW_V$$
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$
PyTorch Kodu
import torch
import torch.nn as nn
import torch.nn.functional as F
class SingleHeadAttention(nn.Module):
def __init__(self, d_model, d_k):
super().__init__()
self.d_k
= d_k
# Doğrusal
dönüşüm vidaları (Ağırlık matrisleri)
self.W_q
= nn.Linear(d_model, d_k, bias=False)
self.W_k
= nn.Linear(d_model, d_k, bias=False)
self.W_v
= nn.Linear(d_model, d_k, bias=False)
def forward(self, x):
# x: [Batch Size, Sequence Length, d_model]
Q = self.W_q(x)
# [B, S, d_k]
K = self.W_k(x)
# [B, S, d_k]
V = self.W_v(x)
# [B, S, d_k]
# Kolay
anlaşılması için adım adım çarpım: Q * K^T
# scores boyutu: [B, S, S] olur. Her kelimenin diğer her
kelimeyle bağı.
scores = torch.bmm(Q, K.transpose(1, 2)) / (self.d_k ** 0.5)
# Olasılık
dağılımına çevir (Satır toplamları 1 olur)
attention_weights = F.softmax(scores, dim=-1)
# Değer
matrisi (V) ile ağırlıkları çarparak yeni anlamı üret
output = torch.bmm(attention_weights, V) # [B, S, d_k]
return output, attention_weights
# Deneme Uygulaması:
x_deneme = torch.randn(1, 4, 16) # 1 cümle, 4 kelime, her kelime 16 sayılık vektör
dikkat_katmani = SingleHeadAttention(d_model=16, d_k=8)
cikti, agirliklar = dikkat_katmani(x_deneme)
print("Dikkat
Çıktı Boyutu:", cikti.shape)
Basit Benzetme
Kütüphane
Örneği: Masanızda 4 farklı ders kitabı var (X). Aradığınız bir bilgiye (Q) en
uygun başlığı (K) bulmak için kitapların kapaklarına bakarsınız. En yüksek
puanı alan kitaptan (V) bilgiyi okuyup kafanıza yazarsınız.
1.2. Nedensel Maskeleme (Causal Masking)
Matematiksel Formül
Üretken
modeller (GPT gibi) gelecekteki kelimeleri göremez. Bu yüzden dikkat matrisinde
geleceğe denk gelen sağ üst üçgen bölgedeki değerler Softmax
öncesinde eksi sonsuza (-∞) yuvarlanır. Böylece softmax(-∞) = 0 olur
ve gelecek kelimelerin etkisi sıfırlanır.
$$M_{ij} = \begin{cases}
0 & \text{eğer } i \ge j \\ -\infty & \text{eğer } i < j
\end{cases}$$
$$\text{MaskedAttention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}} + M\right)V$$
PyTorch Kodu
def causal_masking_demo(Q, K):
# Q ve K
matrislerinin boyutu: [1, 4, 8] olsun (4 kelime)
scores = torch.matmul(Q, K.transpose(-2, -1)) # [1, 4, 4]
seq_len = scores.size(-1)
# Üst üçgeni
1, alt üçgen ve köşegeni 0 yapan maske matrisi
mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1).bool()
# Maskelenen
yerleri çok küçük bir sayı (-inf) ile doldur
scores = scores.masked_fill(mask, float('-inf'))
# Softmax uygulandığında -inf olan
yerler tam 0 olacaktır
attention_weights = F.softmax(scores, dim=-1)
return attention_weights
# Deneme:
q_test = torch.randn(1, 4, 8)
k_test = torch.randn(1, 4, 8)
print("Maskelenmiş
Dikkat Matrisi:\n", causal_masking_demo(q_test, k_test))
Basit Benzetme
Kitap Okuma
Örneği: Bir kitabı okurken sağ sayfanın üzerine elinizi koyup kapatmak gibidir.
Gözünüz sadece o an okuduğunuz kelimeye ve arkasında kalan geçmiş kelimelere
bakabilir.
1.3. Katman Normalizasyonu (Layer Normalization)
Matematiksel Formül
Verilen bir x
girdisinin ortalaması (μ) ve varyansı (σ²) her katman için bağımsızca
hesaplanır. Sayılar normalize edildikten sonra, modelin öğrenilebilir
parametreleri olan γ (ölçekleme) ve β (kaydırma) ile yeniden
şekillendirilir. ε sayısı ise sıfıra bölünme
hatasını engeller.
$$\mu = \frac{1}{d} \sum_{i=1}^{d} x_i, \quad
\sigma^2 = \frac{1}{d} \sum_{i=1}^{d}
(x_i - \mu)^2$$
$$\hat{x}_i =
\frac{x_i - \mu}{\sqrt{\sigma^2 +
\epsilon}}$$
$$y_i = \gamma \hat{x}_i + \beta$$
PyTorch Kodu
class CustomLayerNorm(nn.Module):
def __init__(self, features, eps=1e-5):
super().__init__()
#
Öğrenilebilir terazi parametreleri
self.gamma
= nn.Parameter(torch.ones(features))
self.beta
= nn.Parameter(torch.zeros(features))
self.eps = eps
def forward(self, x):
# x boyutu: [Batch, Seq_Len, Features]
# Son boyut (Features) boyunca ortalama al
mean = x.mean(-1, keepdim=True)
# Son boyut
boyunca varyans al
var = x.var(-1, keepdim=True, unbiased=False)
# Matematiksel
standartlaştırma
x_hat = (x - mean) / torch.sqrt(var + self.eps)
# Ölçekle ve
kaydır
return self.gamma * x_hat + self.beta
# Deneme:
ln_katmani = CustomLayerNorm(features=16)
x_gurultulu = torch.randn(1, 2, 16) * 10 + 5 # Büyük sayılardan oluşan girdi
print("Normalizasyon
Sonrası Çıktı Kontrolü (Ortalama ~0 olmalı):\n", ln_katmani(x_gurultulu).mean().item())
Basit Benzetme
Sınıf Notları
Örneği: Bir öğretmen sınav yapıyor. Sınıfın ortalaması çok yüksek veya çok düşük
çıktığında, tüm notları ortak bir standarda getirip (çan eğrisi gibi) adil bir
şekilde dağıtmak gibidir.
1.4. Yumuşak Maksimum ve Sıcaklık Ayarı (Softmax
& Temperature)
Matematiksel Formül
Modelin
ürettiği ham puanları ($z_i$ -
logits) kelime seçme olasılıklarına dönüştürür.
Formüle eklenen T (Sıcaklık) parametresi 1'den küçükse en yüksek olasılıklı
kelimeyi aşırı öne çıkarır (model ciddi ve robotik olur), 1'den büyükse tüm
kelimelerin şansını birbirine yaklaştırır (model yaratıcı veya saçmalayan bir
yapıya bürünür).
$$P(x_i) = \frac{\exp(z_i
/ T)}{\sum_{j} \exp(z_j / T)}$$
PyTorch Kodu
def softmax_with_temperature(logits, temperature=1.0):
# Sıfıra
bölünme hatasını engellemek için kontrol
if temperature == 0:
temperature = 1e-7
# Logit değerlerini sıcaklığa böl
scaled_logits = logits / temperature
# Olasılıkları
hesapla
probs = F.softmax(scaled_logits,
dim=-1)
return probs
# Deneme:
ham_puanlar = torch.tensor([2.0, 1.0, 0.5])
print("Düşük
Sıcaklık (T=0.2) - Net/Ciddi:", softmax_with_temperature(ham_puanlar,
temperature=0.2))
print("Yüksek
Sıcaklık (T=2.0) - Dağınık/Yaratıcı:", softmax_with_temperature(ham_puanlar,
temperature=2.0))
Basit Benzetme
Dondurma
Seçimi Örneği: Önünüzde Çikolatalı, Çilekli ve Limonlu
dondurmalar var. Sıcaklık çok düşükse (T → 0) her zaman kesinlikle en
sevdiğiniz çikolatayı seçersiniz. Sıcaklık çok yüksekse (T → 2) gözünüzü
kapatıp hiç denemediğiniz limonluyu seçme şansınız artar.
2. KISIM: EĞİTİM, KAYIP FONKSİYONLARI VE OPTİMİZASYON
2.1. Çapraz Entropi Kayıp Fonksiyonu (Cross-Entropy
Loss)
Matematiksel Formül
Yapay zekanın
tahmin ettiği olasılık dağılımı (P) ile olması gereken gerçek hedef (One-hot vektör Y) arasındaki farkı ölçer. Yapay zeka doğru kelimeye ne kadar düşük olasılık verdiyse,
yiyeceği ceza (kayıp puanı) logaritmik olarak o kadar büyür.
$$\mathcal{L}_{CE} = - \sum_{i} Y_i \log(P_i)$$
PyTorch Kodu
class CustomCrossEntropy(nn.Module):
def __init__(self):
super().__init__()
def forward(self, logits, targets):
# logits: [Batch, Classes], targets: [Batch] (Doğru sınıfların indeksleri)
# Adım 1: Log-Softmax hesapla (Sayısal kararlılık için)
max_logits = torch.max(logits, dim=-1, keepdim=True)[0]
stabilized_logits = logits - max_logits
log_sum_exp = torch.log(torch.sum(torch.exp(stabilized_logits), dim=-1, keepdim=True))
log_probs = stabilized_logits - log_sum_exp
# Adım 2:
Sadece doğru olan hedef sınıfların ceza puanlarını topla
batch_indices = torch.arange(logits.size(0))
loss = -log_probs[batch_indices,
targets]
# Ortalama
kaybı dön
return loss.mean()
# Deneme:
ceza_olcer = CustomCrossEntropy()
tahmin_logits = torch.tensor([[1.5, 4.0, 0.1]]) # Model 2. sıradaki kelimeye (indeks 1) güveniyor
gercek_hedef = torch.tensor([1]) # Gerçekten de doğru cevap indeks 1'miş.
print("Hesaplanan
Kayıp Puanı (Düşük çıkmalı):", ceza_olcer(tahmin_logits,
gercek_hedef).item())
Basit Benzetme
Okul Sınavı
Örneği: Öğrenci test sınavında doğru şıkka "%90
eminim" derse az ceza alır, ama doğru şıkka "%5 şans" verip
yanılırsa öğretmeninden büyük bir hata puanı alır.
2.2. AdamW İyileştiricisi (Weight
Decay Özellikli Adam)
Matematiksel Formül
Gradiyenlerin birinci momentini ($m_t$ - momentum/hız) ve ikinci momentini ($v_t$
- dalgalanma gücü) hesaplar. AdamW'nin normal
Adam'dan farkı, ağırlık azaltma (L₂ regülasyonu) işlemini doğrudan
ağırlık güncelleme aşamasında uygulamasıdır.
$$m_t = \beta_1 m_{t-1} + (1 -
\beta_1) g_t, \quad v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2$$
$$\hat{m}_t =
\frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t
= \frac{v_t}{1 -
\beta_2^t}$$
$$\theta_t = \theta_{t-1} - \eta \left(
\frac{\hat{m}_t}{\sqrt{\hat{v}_t}
+ \epsilon} + \lambda \theta_{t-1} \right)$$
PyTorch Kodu
def adamw_step(param, grad, m, v, t, lr=0.001, beta1=0.9, beta2=0.999, weight_decay=0.01, eps=1e-8):
# Birinci
moment (Hız birikmesi)
m = beta1 * m +
(1 -
beta1) * grad
# İkinci
moment (Değişkenlik ölçümü)
v = beta2 * v +
(1 -
beta2) * (grad ** 2)
# Zaman
düzeltme katsayıları
m_hat = m / (1 - beta1 ** t)
v_hat = v / (1 - beta2 ** t)
# Güncelleme
adımı + Ağırlıkların aşırı büyümesini engelleyen Weight
Decay (\lambda * \theta)
param_updated = param - lr * (m_hat / (torch.sqrt(v_hat) + eps) + weight_decay * param)
return param_updated, m, v
# Deneme Parametreleri:
w = torch.tensor([1.0])
g = torch.tensor([0.1])
m_t, v_t = torch.tensor([0.0]), torch.tensor([0.0])
w, m_t, v_t = adamw_step(w, g, m_t, v_t, t=1)
print("Güncellenmiş
Ağırlık Değeri:", w.item())
Basit Benzetme
Bisiklet Sürme
Örneği: Yokuş aşağı bisiklet sürerken hem eski hızınızı korursunuz ($m_t$), hem de yolun taşlı olup olmadığına bakıp freni
ayarlarsınız ($v_t$). Ayrıca çantanızdaki gereksiz
ağırlıkları yolda düşürerek hafiflersiniz (λ).
3. KISIM: MEKANİK ANLAŞILABİLİRLİK (MECHANISTIC INTERPRETABILITY) VE
PROBING
3.1. Kosinüs Benzerliği (Cosine Similarity)
Matematiksel Formül
İki kelime
vektörünün yönsel olarak birbirine ne kadar paralel olduğunu ölçer. Değer 1
çıkarsa kelimeler aynı doğrultudadır, 0 çıkarsa tamamen bağımsızdır, -1 çıkarsa
zıt kutuplardadır.
$$\text{Cosine Similarity}(A, B) = \frac{A \cdot B}{\Vert{}A\Vert{} \Vert{}B\Vert{}} = \frac{\sum_{i} A_i
B_i}{\sqrt{\sum_{i} A_i^2} \sqrt{\sum_{i} B_i^2}}$$
PyTorch Kodu
def custom_cosine_similarity(A, B):
# A ve B: [Vector Dimension] şeklinde iki
tekil kelime vektörü
dot_product = torch.dot(A, B)
norm_A = torch.sqrt(torch.sum(A ** 2))
norm_B = torch.sqrt(torch.sum(B ** 2))
# Sıfıra
bölünme kontrolü
if norm_A == 0 or norm_B == 0:
return torch.tensor(0.0)
return dot_product / (norm_A * norm_B)
# Deneme Uygulaması:
kral_vektor = torch.tensor([0.9, 0.1, 0.0])
kralice_vektor = torch.tensor([0.8, 0.2, 0.1])
araba_vektor = torch.tensor([0.0, 0.0, 0.9])
print("Kral -
Kraliçe Benzerliği (Yüksek olmalı):", custom_cosine_similarity(kral_vektor,
kralice_vektor).item())
print("Kral -
Araba Benzerliği (Düşük olmalı):", custom_cosine_similarity(kral_vektor,
araba_vektor).item())
Basit Benzetme
Ok İşareti
Örneği: İki kişinin ellerindeki okları aynı gökyüzü hedefine doğru tutup
tutmadığına bakmak gibidir. Okların boyu önemli değildir, önemli olan
baktıkları açıdır.
3.2. Aktivasyon Kancaları (Activation Hooks) ile İç Hücre İzleme
Matematiksel Mantık
Model
çalışırken (Forward Pass
esnasında), katmanların ürettiği gizli durum (Hidden State) matrislerini dışarı sızdırmak veya üzerlerinde
değişiklik yapmak için kullanılan kesinti mekanizmalarıdır.
PyTorch Kodu
# İzlemek için çok basit tek
katmanlı bir yapay sinir ağı oluşturalım
class MiniModel(nn.Module):
def __init__(self):
super().__init__()
self.fc
= nn.Linear(4, 4)
def forward(self, x):
return self.fc(x)
# Kanca tetiklendiğinde içine
veriyi kaydedeceğimiz boş bir liste
akil_okuyucu_kutusu = []
# Kanca Fonksiyonu: Model buraya
uğradığında içerideki sayıyı yakalar
def gizli_katman_kancasi(module, input, output):
akil_okuyucu_kutusu.append(output.detach())
# Çalıştırma Simülasyonu:
model = MiniModel()
# Modele kancayı takıyoruz (fc katmanının çıktısını dinle)
handle = model.fc.register_forward_hook(gizli_katman_kancasi)
girdi_verisi = torch.randn(1, 4)
cikti_verisi = model(girdi_verisi)
print("Kanca
Tarafından Gizlice Yakalanan Hücre Değerleri:\n", akil_okuyucu_kutusu[0])
handle.remove() # İşimizi
bitince dinleme cihazını söküyoruz
Basit Benzetme
Hırsız Dinleme
Cihazı Örneği: Bir binanın havalandırma borusuna gizli bir
mikrofon takıp, içerideki ajanların gizli planları konuşurken seslerini
kaydetmek gibidir.
3.3. Logit Lens (Çıkış Merceği) Tekniği
Matematiksel Formül
Modelin 12
katmandan oluştuğunu varsayalım. Logit Lens, modelin
en son katmana kadar gitmesini beklemez. Örneğin 5. katmandaki ara gizli
çıktıyı ($h^{(5)}$) alır ve doğrudan en sondaki Unembedding ($W_U$) matrisi ile çarparak, modelin yolun
ortasındayken aklından hangi kelimenin geçtiğini sorgular.
$$\text{Logits}_{\text{early}} = h^{(l)} W_U$$
PyTorch Kodu
class ToyTransformerWithLogitLens(nn.Module):
def __init__(self, vocab_size, d_model):
super().__init__()
# Katman 1 ve
Katman 2 (Gizli katmanlar)
self.layer1 = nn.Linear(d_model, d_model)
self.layer2 = nn.Linear(d_model, d_model)
# Kelime
Çevirici Matris (Unembedding Matrix)
self.W_u
= nn.Linear(d_model, vocab_size, bias=False)
def forward_with_lens(self, x):
# Yolculuk
Başlıyor
h1 = self.layer1(x)
# LOGIT LENS
ADIMI: Katman 2'ye geçmeden hemen tahmin alalım!
lens_logits = self.W_u(h1)
# Yolculuk
normal seyrinde devam ediyor
h2 = self.layer2(h1)
final_logits = self.W_u(h2)
return final_logits, lens_logits
# Deneme:
lens_model = ToyTransformerWithLogitLens(vocab_size=1000, d_model=16)
test_girdisi = torch.randn(1, 16)
final, erken_tahmin = lens_model.forward_with_lens(test_girdisi)
print("Logit Lens Erken Tahmin Boyutu:", erken_tahmin.shape)
Basit Benzetme
Düşünce Okuma
Örneği: Bir çocuk resmi çizip bitirmeden önce, resmin ortasındayken yanına gidip
"Hımm, galiba bir kedi çiziyorsun değil
mi?" diyerek aklını erkenden tahmin etmek gibidir.
3.4. Seyrek Otonom Kodlayıcılar (Sparse Autoencoders -
SAE)
Matematiksel Formül
Modelin gizli
katmanlarındaki yoğun verileri (h), çok daha yüksek boyutlu ama neredeyse
tamamı sıfırlardan oluşan seyrek özelliklere (f) dönüştürür. L₁ cezası
sayesinde nöronların sadece küçük bir kısmı aktif kalır (ReLU).
$$f = \text{ReLU}(hW_{\text{enc}} + b_{\text{enc}})$$
$$\hat{h} = fW_{\text{dec}}
+ b_{\text{dec}}$$
$$\mathcal{L}_{\text{SAE}} = \Vert{}h - \hat{h}\Vert{}^2 + \alpha \sum_{i} \vert{}f_i\vert{}$$
PyTorch Kodu
class SparseAutoencoder(nn.Module):
def __init__(self, d_model, d_hidden_sae, alpha=0.01):
super().__init__()
self.alpha
= alpha
# Yoğun
katmandan çok geniş/seyrek katmana geçiş
self.encoder
= nn.Linear(d_model, d_hidden_sae)
# Geri toplama
katmanı
self.decoder
= nn.Linear(d_hidden_sae, d_model)
def forward(self, h):
# f: Seyrek
özellik aktivasyonları
f = F.relu(self.encoder(h))
# h_hat: Yeniden kurgulanan girdi
h_hat = self.decoder(f)
# Kayıp
hesaplama: Yeniden kurma hatası + L1 Seyreklik Cezası
reconstruction_loss = F.mse_loss(h_hat, h)
l1_loss = torch.sum(torch.abs(f))
total_sae_loss = reconstruction_loss + self.alpha * l1_loss
return h_hat, total_sae_loss,
f
# Deneme:
sae_katmani = SparseAutoencoder(d_model=16, d_hidden_sae=64, alpha=0.05)
hidden_states_ornek = torch.randn(1, 16)
_, kayip_puani, seyreklik_aktivasyonlari = sae_katmani(hidden_states_ornek)
print("Sıfır
olan nöronların sayısı (Yüksek olmalı):", torch.sum(seyreklik_aktivasyonlari == 0).item(),
"/ 64")
Basit Benzetme
Kavram Sözlüğü
Örneği: Bilgisayarın karmaşık beynindeki milylarca
sayıyı basitleştirerek; "Burası sadece kedilerden bahsederken yanan
nörondur", "Şurası sadece uzayla ilgili kelimelerde yanan
nörondur" diye tek tek insan diline tercüme etmek gibidir.
4. KISIM: MÜDAHALE VE DENEYSEL NEDENSELLİK (CAUSAL INTERVENTION)
4.1. Aktivasyon Düzenleme ve Yama (Activation
Editing / Patching)
Matematiksel Mantık
Modelin temiz
çalışan bir işlem akışındaki aktivasyon değerlerinin bir kısmını söküp, onun
yerine kasti olarak bozucu bir gürültü veya başka bir cümleye ait özellikleri
yamama (A ← B) operasyonudur. Çıktının nasıl değiştiği gözlemlenerek o
katmanın görevi kesin olarak ispatlanır.
PyTorch Kodu
def activation_patching_simulation():
# Temiz Duygu
Aktivasyonu (Model mutlu bir şey düşünüyor)
temiz_aktivasyon = torch.tensor([[5.0, 4.5, 0.1]])
# Kötü
niyetli/Gürültülü müdahale vektörü (Araya girip fikri değiştiriyoruz)
sabotaj_aktivasyonu = torch.tensor([[-10.0, 0.0, 0.0]])
# Yamama
Operasyonu: 0. indeksteki değeri bozuyoruz
manipüle_edilmis_aktivasyon = temiz_aktivasyon.clone()
manipüle_edilmis_aktivasyon[0, 0] = sabotaj_aktivasyonu[0, 0]
return manipüle_edilmis_aktivasyon
print("Müdahale
Sonrası Yeni Hücre Durumu:", activation_patching_simulation())
Basit Benzetme
Çorba Örneği: Bir aşçı
çorba yaparken tam tencereyi karıştıracağı sırada gizlice içine bir kaşık tuz
atmak gibidir. Çorbanın tadının bozulup bozulmadığına bakarak o tuzun çorbayı
ne kadar etkilediğini anlarsınız.
4.2. Dikkat Kafası Susturma (Head Ablation)
Matematiksel Formül
Belirli bir
dikkat kafasının (h) çıktıya katkısını sıfıra indirmek için, o kafadan gelen
projeksiyon matrisinin sonucu bir maske katsayısı olan 0 ile çarpılır.
$$\text{Output} = \sum_{h=1}^{H} \text{Mask}_h \times \text{Attention}_h(Q, K, V)W_O^h$$
$$\text{Susturma
Durumunda: } \text{Mask}_h = 0$$
PyTorch Kodu
class MultiHeadAblationDemo(nn.Module):
def __init__(self, num_heads, d_model):
super().__init__()
self.num_heads
= num_heads
self.d_model
= d_model
def forward(self, head_outputs, ablate_head_idx=None):
# head_outputs: [Batch, Num_Heads, Seq_Len, Dim]
# Bütün
kafalara başlangıçta 1 (açık) değerini ver
mask = torch.ones(self.num_heads)
# Eğer
kapatmak istediğimiz bir kafa indeksi varsa onu 0 (sustur) yap
if ablate_head_idx is not None:
mask[ablate_head_idx] = 0.0
print(f"DIKKAT: {ablate_head_idx}. kafanın fişi çekildi!")
# Maskeyi
boyutlara uydur ve kafaları çarpıp sustur
scaled_outputs = []
for i in range(self.num_heads):
scaled_outputs.append(head_outputs[:,
i] * mask[i])
return torch.cat(scaled_outputs, dim=-1)
# Deneme:
susturucu = MultiHeadAblationDemo(num_heads=3, d_model=12)
kafa_verileri = torch.ones(1, 3, 2, 4) # 3 kafa da 1'lerden oluşan çıktılar veriyor
yeni_cikti = susturucu(kafa_verileri, ablate_head_idx=1)
print("Susturma
Sonrası Çıktı Kontrolü (Ortadaki kafanın alanı sıfırlandı):\n", yeni_cikti)
Basit Benzetme
Sigorta Kutusu
Örneği: Evdeki elektrik sigortalarını tek tek indirip "Mutfaktaki lambalar
söndü mü?" diye bakmak gibidir. Hangi sigorta inince mutfak sönüyorsa, o
sigortanın mutfağa ait olduğunu anlarsınız.