mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/AI/AI-llm-architecture/0.-basic-llm-concepts.md', 'src/
This commit is contained in:
parent
638e610d38
commit
a7c78fc6ce
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
## Ön Eğitim
|
## Ön Eğitim
|
||||||
|
|
||||||
Ön eğitim, büyük bir dil modelinin (LLM) geliştirilmesinde temel aşamadır; bu aşamada model, geniş ve çeşitli metin verilerine maruz kalır. Bu aşamada, **LLM dilin temel yapıları, kalıpları ve inceliklerini öğrenir**, dilbilgisi, kelime dağarcığı, sözdizimi ve bağlamsal ilişkiler dahil. Bu kapsamlı veriyi işleyerek model, dil ve genel dünya bilgisi hakkında geniş bir anlayış kazanır. Bu kapsamlı temel, LLM'nin tutarlı ve bağlam açısından ilgili metinler üretmesini sağlar. Ardından, bu önceden eğitilmiş model, belirli görevler veya alanlar için yeteneklerini uyarlamak amacıyla özel veri setleri üzerinde daha fazla eğitim alarak ince ayar yapılabilir; bu da hedeflenen uygulamalardaki performansını ve alaka düzeyini artırır.
|
Ön eğitim, büyük bir dil modelinin (LLM) geliştirilmesinde temel aşamadır; bu aşamada model, geniş ve çeşitli metin verilerine maruz kalır. Bu aşamada, **LLM dilin temel yapıları, kalıpları ve inceliklerini öğrenir**, dilbilgisi, kelime dağarcığı, sözdizimi ve bağlamsal ilişkiler dahil. Bu kapsamlı veriyi işleyerek model, dil ve genel dünya bilgisi hakkında geniş bir anlayış kazanır. Bu kapsamlı temel, LLM'nin tutarlı ve bağlamsal olarak ilgili metinler üretmesini sağlar. Ardından, bu önceden eğitilmiş model, belirli görevler veya alanlar için yeteneklerini uyarlamak amacıyla özel veri setleri üzerinde daha fazla eğitim alarak ince ayar yapılabilir; bu da hedeflenmiş uygulamalardaki performansını ve alaka düzeyini artırır.
|
||||||
|
|
||||||
## Ana LLM Bileşenleri
|
## Ana LLM Bileşenleri
|
||||||
|
|
||||||
Genellikle bir LLM, onu eğitmek için kullanılan yapılandırma ile karakterize edilir. Bir LLM eğitirken yaygın bileşenler şunlardır:
|
Genellikle bir LLM, onu eğitmek için kullanılan yapılandırma ile karakterize edilir. Bir LLM eğitirken yaygın bileşenler şunlardır:
|
||||||
|
|
||||||
- **Parametreler**: Parametreler, sinir ağındaki **öğrenilebilir ağırlıklar ve önyargılardır**. Bu, eğitim sürecinin kayıp fonksiyonunu minimize etmek ve modelin görev üzerindeki performansını artırmak için ayarladığı sayılardır. LLM'ler genellikle milyonlarca parametre kullanır.
|
- **Parametreler**: Parametreler, sinir ağındaki **öğrenilebilir ağırlıklar ve önyargılardır**. Bu, eğitim sürecinin kayıp fonksiyonunu minimize etmek ve modelin görev üzerindeki performansını artırmak için ayarladığı sayılardır. LLM'ler genellikle milyonlarca parametre kullanır.
|
||||||
- **Bağlam Uzunluğu**: Bu, LLM'yi ön eğitim için kullanılan her cümlenin maksimum uzunluğudur.
|
- **Bağlam Uzunluğu**: Bu, LLM'yi ön eğitmek için kullanılan her cümlenin maksimum uzunluğudur.
|
||||||
- **Gömme Boyutu**: Her token veya kelimeyi temsil etmek için kullanılan vektörün boyutu. LLM'ler genellikle milyarlarca boyut kullanır.
|
- **Gömme Boyutu**: Her token veya kelimeyi temsil etmek için kullanılan vektörün boyutu. LLM'ler genellikle milyarlarca boyut kullanır.
|
||||||
- **Gizli Boyut**: Sinir ağındaki gizli katmanların boyutu.
|
- **Gizli Boyut**: Sinir ağındaki gizli katmanların boyutu.
|
||||||
- **Katman Sayısı (Derinlik)**: Modelin kaç katmana sahip olduğu. LLM'ler genellikle on katman kullanır.
|
- **Katman Sayısı (Derinlik)**: Modelin kaç katmana sahip olduğu. LLM'ler genellikle on katman kullanır.
|
||||||
@ -30,18 +30,18 @@ GPT_CONFIG_124M = {
|
|||||||
```
|
```
|
||||||
## PyTorch'ta Tensörler
|
## PyTorch'ta Tensörler
|
||||||
|
|
||||||
PyTorch'ta, **tensör** çok boyutlu bir dizi olarak hizmet veren temel bir veri yapısıdır ve skalarlar, vektörler ve matrisler gibi kavramları potansiyel olarak daha yüksek boyutlara genelleştirir. Tensörler, özellikle derin öğrenme ve sinir ağları bağlamında, PyTorch'ta verilerin temsil edilmesi ve işlenmesi için birincil yoldur.
|
PyTorch'ta, bir **tensör**, skalarlar, vektörler ve matrisler gibi kavramları potansiyel olarak daha yüksek boyutlara genelleştiren çok boyutlu bir dizi olarak hizmet eden temel bir veri yapısıdır. Tensörler, özellikle derin öğrenme ve sinir ağları bağlamında, PyTorch'ta verilerin temsil edilmesi ve işlenmesi için birincil yoldur.
|
||||||
|
|
||||||
### Tensörlerin Matematiksel Kavramı
|
### Tensörlerin Matematiksel Kavramı
|
||||||
|
|
||||||
- **Skalarlar**: Tek bir sayıyı (sıfır boyutlu) temsil eden 0. dereceden tensörler. Örnek: 5
|
- **Skalarlar**: Tek bir sayıyı (sıfır boyutlu) temsil eden 0. dereceden tensörler. Örnek: 5
|
||||||
- **Vektörler**: Bir boyutlu sayı dizisini temsil eden 1. dereceden tensörler. Örnek: \[5,1]
|
- **Vektörler**: Bir boyutlu sayı dizisini temsil eden 1. dereceden tensörler. Örnek: \[5,1]
|
||||||
- **Matrisler**: Satır ve sütunlarla iki boyutlu dizileri temsil eden 2. dereceden tensörler. Örnek: \[\[1,3], \[5,2]]
|
- **Matrisler**: Satır ve sütunlarla iki boyutlu dizileri temsil eden 2. dereceden tensörler. Örnek: \[\[1,3], \[5,2]]
|
||||||
- **Daha Yüksek Dereceli Tensörler**: 3. dereceden veya daha yüksek tensörler, verileri daha yüksek boyutlarda temsil eder (örneğin, renkli görüntüler için 3D tensörler).
|
- **Daha Yüksek Dereceli Tensörler**: Üç veya daha fazla boyutta verileri temsil eden 3. dereceden veya daha yüksek tensörler (örneğin, renkli görüntüler için 3D tensörler).
|
||||||
|
|
||||||
### Tensörler Veri Konteyneri Olarak
|
### Tensörler Veri Konteyneri Olarak
|
||||||
|
|
||||||
Hesaplama perspektifinden, tensörler çok boyutlu veriler için konteynerler olarak işlev görür; her boyut verinin farklı özelliklerini veya yönlerini temsil edebilir. Bu, tensörleri makine öğrenimi görevlerinde karmaşık veri setlerini işlemek için son derece uygun hale getirir.
|
Hesaplama perspektifinden, tensörler çok boyutlu veriler için konteyner görevi görür; her boyut verinin farklı özelliklerini veya yönlerini temsil edebilir. Bu, tensörleri makine öğrenimi görevlerinde karmaşık veri setlerini işlemek için son derece uygun hale getirir.
|
||||||
|
|
||||||
### PyTorch Tensörleri vs. NumPy Dizileri
|
### PyTorch Tensörleri vs. NumPy Dizileri
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ PyTorch tensörleri, sayısal verileri depolama ve işleme yetenekleri açısın
|
|||||||
|
|
||||||
### PyTorch'ta Tensör Oluşturma
|
### PyTorch'ta Tensör Oluşturma
|
||||||
|
|
||||||
Tensörleri `torch.tensor` fonksiyonunu kullanarak oluşturabilirsiniz:
|
Tensörleri `torch.tensor` fonksiyonu kullanarak oluşturabilirsiniz:
|
||||||
```python
|
```python
|
||||||
pythonCopy codeimport torch
|
pythonCopy codeimport torch
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ Bir tensörün veri türünü `.dtype` niteliğini kullanarak kontrol edebilirsi
|
|||||||
tensor1d = torch.tensor([1, 2, 3])
|
tensor1d = torch.tensor([1, 2, 3])
|
||||||
print(tensor1d.dtype) # Output: torch.int64
|
print(tensor1d.dtype) # Output: torch.int64
|
||||||
```
|
```
|
||||||
- Python tamsayılarından oluşturulan tensörler `torch.int64` türündedir.
|
- Python tam sayılarından oluşturulan tensörler `torch.int64` türündedir.
|
||||||
- Python ondalık sayılarından oluşturulan tensörler `torch.float32` türündedir.
|
- Python ondalık sayılarından oluşturulan tensörler `torch.float32` türündedir.
|
||||||
|
|
||||||
Bir tensörün veri türünü değiştirmek için `.to()` yöntemini kullanın:
|
Bir tensörün veri türünü değiştirmek için `.to()` yöntemini kullanın:
|
||||||
@ -203,7 +203,7 @@ Birden fazla katmana sahip daha büyük sinir ağlarında, gradyanları hesaplam
|
|||||||
|
|
||||||
- **İleri Geçiş:** Girdileri her katmandan geçirerek ağın çıktısını hesaplayın.
|
- **İleri Geçiş:** Girdileri her katmandan geçirerek ağın çıktısını hesaplayın.
|
||||||
- **Kayıp Hesaplama:** Ağın çıktısını ve hedef etiketleri kullanarak kayıp fonksiyonunu değerlendirin.
|
- **Kayıp Hesaplama:** Ağın çıktısını ve hedef etiketleri kullanarak kayıp fonksiyonunu değerlendirin.
|
||||||
- **Geri Geçiş (Geri Yayılım):** Çıktı katmanından giriş katmanına kadar zincir kuralını uygulayarak ağdaki her parametreye göre kaybın gradyanlarını hesaplayın.
|
- **Geri Geçiş (Geri Yayılım):** Çıktı katmanından giriş katmanına kadar zincir kuralını özyinelemeli olarak uygulayarak ağdaki her parametreye göre kaybın gradyanlarını hesaplayın.
|
||||||
|
|
||||||
### **2. Geri Yayılım Algoritması**
|
### **2. Geri Yayılım Algoritması**
|
||||||
|
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
## Tokenizing
|
## Tokenizing
|
||||||
|
|
||||||
**Tokenizing** verilerin, örneğin metinlerin, daha küçük, yönetilebilir parçalara _token_ denilen birimlere ayrılması sürecidir. Her token, benzersiz bir sayısal tanımlayıcı (ID) ile atanır. Bu, metni makine öğrenimi modelleri tarafından işlenmeye hazırlamak için temel bir adımdır, özellikle doğal dil işleme (NLP) alanında.
|
**Tokenizing**, verileri, örneğin metni, daha küçük, yönetilebilir parçalara _token_ denir. Her token, benzersiz bir sayısal tanımlayıcı (ID) ile atanır. Bu, metni makine öğrenimi modelleri tarafından işlenmeye hazırlamak için temel bir adımdır, özellikle doğal dil işleme (NLP) alanında.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu ilk aşamanın amacı çok basittir: **Girdiyi mantıklı bir şekilde token'lara (id'lere) ayırmak**.
|
> Bu ilk aşamanın amacı çok basittir: **Girişi mantıklı bir şekilde token'lara (id'lere) ayırmak**.
|
||||||
|
|
||||||
### **Tokenizing Nasıl Çalışır**
|
### **How Tokenizing Works**
|
||||||
|
|
||||||
1. **Metni Bölme:**
|
1. **Metni Bölme:**
|
||||||
- **Temel Tokenizer:** Basit bir tokenizer, metni bireysel kelimelere ve noktalama işaretlerine ayırabilir, boşlukları kaldırır.
|
- **Temel Tokenizer:** Basit bir tokenizer, metni bireysel kelimelere ve noktalama işaretlerine ayırabilir, boşlukları kaldırır.
|
||||||
@ -15,12 +15,12 @@
|
|||||||
Metin: `"Hello, world!"`\
|
Metin: `"Hello, world!"`\
|
||||||
Tokenlar: `["Hello", ",", "world", "!"]`
|
Tokenlar: `["Hello", ",", "world", "!"]`
|
||||||
2. **Bir Kelime Dağarcığı Oluşturma:**
|
2. **Bir Kelime Dağarcığı Oluşturma:**
|
||||||
- Tokenları sayısal ID'lere dönüştürmek için bir **kelime dağarcığı** oluşturulur. Bu kelime dağarcığı, tüm benzersiz tokenları (kelimeler ve semboller) listeler ve her birine belirli bir ID atar.
|
- Token'ları sayısal ID'lere dönüştürmek için bir **kelime dağarcığı** oluşturulur. Bu kelime dağarcığı, tüm benzersiz token'ları (kelimeler ve semboller) listeler ve her birine belirli bir ID atar.
|
||||||
- **Özel Tokenlar:** Çeşitli senaryoları ele almak için kelime dağarcığına eklenen özel sembollerdir:
|
- **Özel Tokenlar:** Çeşitli senaryoları ele almak için kelime dağarcığına eklenen özel sembollerdir:
|
||||||
- `[BOS]` (Dizinin Başlangıcı): Bir metnin başlangıcını belirtir.
|
- `[BOS]` (Dizinin Başlangıcı): Bir metnin başlangıcını belirtir.
|
||||||
- `[EOS]` (Dizinin Sonu): Bir metnin sonunu belirtir.
|
- `[EOS]` (Dizinin Sonu): Bir metnin sonunu belirtir.
|
||||||
- `[PAD]` (Doldurma): Bir partideki tüm dizileri aynı uzunlukta yapmak için kullanılır.
|
- `[PAD]` (Doldurma): Bir partideki tüm dizileri aynı uzunlukta yapmak için kullanılır.
|
||||||
- `[UNK]` (Bilinmeyen): Kelime dağarcığında olmayan tokenları temsil eder.
|
- `[UNK]` (Bilinmeyen): Kelime dağarcığında olmayan token'ları temsil eder.
|
||||||
- _Örnek:_\
|
- _Örnek:_\
|
||||||
Eğer `"Hello"` ID `64` ile atanmışsa, `","` `455`, `"world"` `78`, ve `"!"` `467` ise:\
|
Eğer `"Hello"` ID `64` ile atanmışsa, `","` `455`, `"world"` `78`, ve `"!"` `467` ise:\
|
||||||
`"Hello, world!"` → `[64, 455, 78, 467]`
|
`"Hello, world!"` → `[64, 455, 78, 467]`
|
||||||
@ -29,19 +29,19 @@ Eğer `"Bye"` gibi bir kelime kelime dağarcığında yoksa, `[UNK]` ile değiş
|
|||||||
`"Bye, world!"` → `["[UNK]", ",", "world", "!"]` → `[987, 455, 78, 467]`\
|
`"Bye, world!"` → `["[UNK]", ",", "world", "!"]` → `[987, 455, 78, 467]`\
|
||||||
_(Varsayalım ki `[UNK]` ID `987`'dir)_
|
_(Varsayalım ki `[UNK]` ID `987`'dir)_
|
||||||
|
|
||||||
### **Gelişmiş Tokenizing Yöntemleri**
|
### **Advanced Tokenizing Methods**
|
||||||
|
|
||||||
Temel tokenizer basit metinler için iyi çalışırken, büyük kelime dağarcıkları ve yeni veya nadir kelimeleri ele almakta sınırlamaları vardır. Gelişmiş tokenizing yöntemleri, metni daha küçük alt birimlere ayırarak veya tokenizasyon sürecini optimize ederek bu sorunları ele alır.
|
Temel tokenizer basit metinler için iyi çalışırken, büyük kelime dağarcıkları ve yeni veya nadir kelimeleri ele alırken sınırlamaları vardır. Gelişmiş tokenizasyon yöntemleri, metni daha küçük alt birimlere ayırarak veya tokenizasyon sürecini optimize ederek bu sorunları ele alır.
|
||||||
|
|
||||||
1. **Byte Pair Encoding (BPE):**
|
1. **Byte Pair Encoding (BPE):**
|
||||||
- **Amaç:** Kelime dağarcığının boyutunu azaltır ve nadir veya bilinmeyen kelimeleri sıkça karşılaşılan byte çiftlerine ayırarak ele alır.
|
- **Amaç:** Kelime dağarcığının boyutunu azaltır ve nadir veya bilinmeyen kelimeleri sıkça karşılaşılan byte çiftlerine ayırarak ele alır.
|
||||||
- **Nasıl Çalışır:**
|
- **Nasıl Çalışır:**
|
||||||
- Token olarak bireysel karakterlerle başlar.
|
- Token olarak bireysel karakterlerle başlar.
|
||||||
- En sık karşılaşılan token çiftlerini tek bir token haline getirerek birleştirir.
|
- En sık karşılaşılan token çiftlerini tek bir token haline getirerek birleştirir.
|
||||||
- Daha fazla sık çift birleştirilemeyecek duruma gelene kadar devam eder.
|
- Daha fazla sık çift birleştirilemeyecek hale gelene kadar devam eder.
|
||||||
- **Faydalar:**
|
- **Faydalar:**
|
||||||
- Tüm kelimelerin mevcut alt kelime tokenları ile temsil edilebilmesi nedeniyle `[UNK]` tokenına ihtiyaç duyulmaz.
|
- Tüm kelimelerin mevcut alt kelime token'larını birleştirerek temsil edilebilmesi nedeniyle `[UNK]` token'ına ihtiyaç duyulmaz.
|
||||||
- Daha verimli ve esnek bir kelime dağarcığı sağlar.
|
- Daha verimli ve esnek bir kelime dağarcığı.
|
||||||
- _Örnek:_\
|
- _Örnek:_\
|
||||||
`"playing"` `["play", "ing"]` olarak token'lanabilir eğer `"play"` ve `"ing"` sıkça karşılaşılan alt kelimelerse.
|
`"playing"` `["play", "ing"]` olarak token'lanabilir eğer `"play"` ve `"ing"` sıkça karşılaşılan alt kelimelerse.
|
||||||
2. **WordPiece:**
|
2. **WordPiece:**
|
||||||
@ -53,18 +53,18 @@ Temel tokenizer basit metinler için iyi çalışırken, büyük kelime dağarc
|
|||||||
- Hangi alt kelimelerin birleştirileceğine karar vermek için olasılıksal bir model kullanır.
|
- Hangi alt kelimelerin birleştirileceğine karar vermek için olasılıksal bir model kullanır.
|
||||||
- **Faydalar:**
|
- **Faydalar:**
|
||||||
- Yönetilebilir bir kelime dağarcığı boyutu ile kelimeleri etkili bir şekilde temsil etme arasında denge kurar.
|
- Yönetilebilir bir kelime dağarcığı boyutu ile kelimeleri etkili bir şekilde temsil etme arasında denge kurar.
|
||||||
- Nadir ve bileşik kelimeleri verimli bir şekilde ele alır.
|
- Nadir ve bileşik kelimeleri etkili bir şekilde ele alır.
|
||||||
- _Örnek:_\
|
- _Örnek:_\
|
||||||
`"unhappiness"` `["un", "happiness"]` veya `["un", "happy", "ness"]` olarak token'lanabilir, kelime dağarcığına bağlı olarak.
|
`"unhappiness"` `["un", "happiness"]` veya `["un", "happy", "ness"]` olarak token'lanabilir, kelime dağarcığına bağlı olarak.
|
||||||
3. **Unigram Language Model:**
|
3. **Unigram Language Model:**
|
||||||
- **Kullananlar:** SentencePiece gibi modeller.
|
- **Kullananlar:** SentencePiece gibi modeller.
|
||||||
- **Amaç:** En olası alt kelime token setini belirlemek için olasılıksal bir model kullanır.
|
- **Amaç:** En olası alt kelime token setini belirlemek için olasılıksal bir model kullanır.
|
||||||
- **Nasıl Çalışır:**
|
- **Nasıl Çalışır:**
|
||||||
- Potansiyel tokenların büyük bir seti ile başlar.
|
- Potansiyel token'ların büyük bir seti ile başlar.
|
||||||
- Eğitim verilerinin modelin olasılığını en az artıran tokenları iteratif olarak kaldırır.
|
- Eğitim verilerinin modelin olasılığını en az artıran token'ları iteratif olarak kaldırır.
|
||||||
- Her kelimenin en olası alt kelime birimleri ile temsil edildiği bir kelime dağarcığı oluşturur.
|
- Her kelimenin en olası alt kelime birimleri ile temsil edildiği bir kelime dağarcığı oluşturur.
|
||||||
- **Faydalar:**
|
- **Faydalar:**
|
||||||
- Esnek olup dili daha doğal bir şekilde modelleyebilir.
|
- Esnek ve dili daha doğal bir şekilde modelleyebilir.
|
||||||
- Genellikle daha verimli ve kompakt tokenizasyonlar ile sonuçlanır.
|
- Genellikle daha verimli ve kompakt tokenizasyonlar ile sonuçlanır.
|
||||||
- _Örnek:_\
|
- _Örnek:_\
|
||||||
`"internationalization"` daha küçük, anlamlı alt kelimelere `["international", "ization"]` olarak token'lanabilir.
|
`"internationalization"` daha küçük, anlamlı alt kelimelere `["international", "ization"]` olarak token'lanabilir.
|
||||||
|
|||||||
233
src/AI/AI-llm-architecture/2.-data-sampling.md
Normal file
233
src/AI/AI-llm-architecture/2.-data-sampling.md
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
# 2. Veri Örnekleme
|
||||||
|
|
||||||
|
## **Veri Örnekleme**
|
||||||
|
|
||||||
|
**Veri Örnekleme**, GPT gibi büyük dil modellerinin (LLM'ler) eğitimi için verileri hazırlamada kritik bir süreçtir. Bu, metin verilerini modelin önceki kelimelere dayanarak bir sonraki kelimeyi (veya token'ı) tahmin etmeyi öğrenmesi için kullandığı giriş ve hedef dizilerine organize etmeyi içerir. Doğru veri örnekleme, modelin dil kalıplarını ve bağımlılıklarını etkili bir şekilde yakalamasını sağlar.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Bu ikinci aşamanın amacı çok basittir: **Giriş verilerini örnekleyin ve genellikle veri kümesini belirli bir uzunluktaki cümlelere ayırarak ve beklenen yanıtı da üreterek eğitim aşamasına hazırlayın.**
|
||||||
|
|
||||||
|
### **Veri Örneklemenin Önemi**
|
||||||
|
|
||||||
|
GPT gibi LLM'ler, önceki kelimeler tarafından sağlanan bağlamı anlayarak metin üretmek veya tahmin etmek için eğitilir. Bunu başarmak için, eğitim verileri modelin kelime dizileri ile bunların sonraki kelimeleri arasındaki ilişkiyi öğrenebileceği bir şekilde yapılandırılmalıdır. Bu yapılandırılmış yaklaşım, modelin genelleştirmesine ve tutarlı ve bağlamsal olarak ilgili metinler üretmesine olanak tanır.
|
||||||
|
|
||||||
|
### **Veri Örneklemede Temel Kavramlar**
|
||||||
|
|
||||||
|
1. **Tokenizasyon:** Metni token (örneğin, kelimeler, alt kelimeler veya karakterler) adı verilen daha küçük birimlere ayırma.
|
||||||
|
2. **Dizi Uzunluğu (max_length):** Her giriş dizisindeki token sayısı.
|
||||||
|
3. **Kaydırma Penceresi:** Tokenize edilmiş metin üzerinde bir pencereyi hareket ettirerek örtüşen giriş dizileri oluşturma yöntemi.
|
||||||
|
4. **Adım:** Kaydırma penceresinin bir sonraki diziyi oluşturmak için ileriye doğru hareket ettiği token sayısı.
|
||||||
|
|
||||||
|
### **Adım Adım Örnek**
|
||||||
|
|
||||||
|
Veri örneklemesini açıklamak için bir örnek üzerinden geçelim.
|
||||||
|
|
||||||
|
**Örnek Metin**
|
||||||
|
```arduino
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||||
|
```
|
||||||
|
**Tokenizasyon**
|
||||||
|
|
||||||
|
Bir **temel tokenleştirici** kullandığımızı varsayalım, bu metni kelimelere ve noktalama işaretlerine ayırır:
|
||||||
|
```vbnet
|
||||||
|
Tokens: ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", "adipiscing", "elit."]
|
||||||
|
```
|
||||||
|
**Parametreler**
|
||||||
|
|
||||||
|
- **Maksimum Dizi Uzunluğu (max_length):** 4 token
|
||||||
|
- **Kaydırma Penceresi Adımı:** 1 token
|
||||||
|
|
||||||
|
**Girdi ve Hedef Dizileri Oluşturma**
|
||||||
|
|
||||||
|
1. **Kaydırma Penceresi Yaklaşımı:**
|
||||||
|
- **Girdi Dizileri:** Her girdi dizisi `max_length` token içerir.
|
||||||
|
- **Hedef Dizileri:** Her hedef dizisi, ilgili girdi dizisini hemen takip eden token'ları içerir.
|
||||||
|
2. **Dizileri Oluşturma:**
|
||||||
|
|
||||||
|
<table><thead><tr><th width="177">Pencere Pozisyonu</th><th>Girdi Dizisi</th><th>Hedef Dizi</th></tr></thead><tbody><tr><td>1</td><td>["Lorem", "ipsum", "dolor", "sit"]</td><td>["ipsum", "dolor", "sit", "amet,"]</td></tr><tr><td>2</td><td>["ipsum", "dolor", "sit", "amet,"]</td><td>["dolor", "sit", "amet,", "consectetur"]</td></tr><tr><td>3</td><td>["dolor", "sit", "amet,", "consectetur"]</td><td>["sit", "amet,", "consectetur", "adipiscing"]</td></tr><tr><td>4</td><td>["sit", "amet,", "consectetur", "adipiscing"]</td><td>["amet,", "consectetur", "adipiscing", "elit."]</td></tr></tbody></table>
|
||||||
|
|
||||||
|
3. **Elde Edilen Girdi ve Hedef Dizileri:**
|
||||||
|
|
||||||
|
- **Girdi:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
[
|
||||||
|
["Lorem", "ipsum", "dolor", "sit"],
|
||||||
|
["ipsum", "dolor", "sit", "amet,"],
|
||||||
|
["dolor", "sit", "amet,", "consectetur"],
|
||||||
|
["sit", "amet,", "consectetur", "adipiscing"],
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Hedef:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
[
|
||||||
|
["ipsum", "dolor", "sit", "amet,"],
|
||||||
|
["dolor", "sit", "amet,", "consectetur"],
|
||||||
|
["sit", "amet,", "consectetur", "adipiscing"],
|
||||||
|
["amet,", "consectetur", "adipiscing", "elit."],
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Görsel Temsil**
|
||||||
|
|
||||||
|
<table><thead><tr><th width="222">Token Pozisyonu</th><th>Token</th></tr></thead><tbody><tr><td>1</td><td>Lorem</td></tr><tr><td>2</td><td>ipsum</td></tr><tr><td>3</td><td>dolor</td></tr><tr><td>4</td><td>sit</td></tr><tr><td>5</td><td>amet,</td></tr><tr><td>6</td><td>consectetur</td></tr><tr><td>7</td><td>adipiscing</td></tr><tr><td>8</td><td>elit.</td></tr></tbody></table>
|
||||||
|
|
||||||
|
**Adım 1 ile Kaydırma Penceresi:**
|
||||||
|
|
||||||
|
- **İlk Pencere (Pozisyonlar 1-4):** \["Lorem", "ipsum", "dolor", "sit"] → **Hedef:** \["ipsum", "dolor", "sit", "amet,"]
|
||||||
|
- **İkinci Pencere (Pozisyonlar 2-5):** \["ipsum", "dolor", "sit", "amet,"] → **Hedef:** \["dolor", "sit", "amet,", "consectetur"]
|
||||||
|
- **Üçüncü Pencere (Pozisyonlar 3-6):** \["dolor", "sit", "amet,", "consectetur"] → **Hedef:** \["sit", "amet,", "consectetur", "adipiscing"]
|
||||||
|
- **Dördüncü Pencere (Pozisyonlar 4-7):** \["sit", "amet,", "consectetur", "adipiscing"] → **Hedef:** \["amet,", "consectetur", "adipiscing", "elit."]
|
||||||
|
|
||||||
|
**Adım Anlama**
|
||||||
|
|
||||||
|
- **Adım 1:** Pencere her seferinde bir token ileri hareket eder, bu da yüksek oranda örtüşen dizilerle sonuçlanır. Bu, bağlamsal ilişkilerin daha iyi öğrenilmesine yol açabilir ancak benzer veri noktalarının tekrar edilmesi nedeniyle aşırı uyum riski artırabilir.
|
||||||
|
- **Adım 2:** Pencere her seferinde iki token ileri hareket eder, örtüşmeyi azaltır. Bu, tekrarları ve hesaplama yükünü azaltır ancak bazı bağlamsal nüansları kaçırabilir.
|
||||||
|
- **max_length'e Eşit Adım:** Pencere, tüm pencere boyutu kadar ileri hareket eder, bu da örtüşmeyen dizilerle sonuçlanır. Bu, veri tekrarını en aza indirir ancak modelin diziler arasındaki bağımlılıkları öğrenme yeteneğini sınırlayabilir.
|
||||||
|
|
||||||
|
**Adım 2 ile Örnek:**
|
||||||
|
|
||||||
|
Aynı tokenleştirilmiş metni ve `max_length` değerini 4 kullanarak:
|
||||||
|
|
||||||
|
- **İlk Pencere (Pozisyonlar 1-4):** \["Lorem", "ipsum", "dolor", "sit"] → **Hedef:** \["ipsum", "dolor", "sit", "amet,"]
|
||||||
|
- **İkinci Pencere (Pozisyonlar 3-6):** \["dolor", "sit", "amet,", "consectetur"] → **Hedef:** \["sit", "amet,", "consectetur", "adipiscing"]
|
||||||
|
- **Üçüncü Pencere (Pozisyonlar 5-8):** \["amet,", "consectetur", "adipiscing", "elit."] → **Hedef:** \["consectetur", "adipiscing", "elit.", "sed"] _(Devam ettiğini varsayarak)_
|
||||||
|
|
||||||
|
## Kod Örneği
|
||||||
|
|
||||||
|
Bunu daha iyi anlamak için [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb) adresinden bir kod örneğine bakalım:
|
||||||
|
```python
|
||||||
|
# Download the text to pre-train the LLM
|
||||||
|
import urllib.request
|
||||||
|
url = ("https://raw.githubusercontent.com/rasbt/LLMs-from-scratch/main/ch02/01_main-chapter-code/the-verdict.txt")
|
||||||
|
file_path = "the-verdict.txt"
|
||||||
|
urllib.request.urlretrieve(url, file_path)
|
||||||
|
|
||||||
|
with open("the-verdict.txt", "r", encoding="utf-8") as f:
|
||||||
|
raw_text = f.read()
|
||||||
|
|
||||||
|
"""
|
||||||
|
Create a class that will receive some params lie tokenizer and text
|
||||||
|
and will prepare the input chunks and the target chunks to prepare
|
||||||
|
the LLM to learn which next token to generate
|
||||||
|
"""
|
||||||
|
import torch
|
||||||
|
from torch.utils.data import Dataset, DataLoader
|
||||||
|
|
||||||
|
class GPTDatasetV1(Dataset):
|
||||||
|
def __init__(self, txt, tokenizer, max_length, stride):
|
||||||
|
self.input_ids = []
|
||||||
|
self.target_ids = []
|
||||||
|
|
||||||
|
# Tokenize the entire text
|
||||||
|
token_ids = tokenizer.encode(txt, allowed_special={"<|endoftext|>"})
|
||||||
|
|
||||||
|
# Use a sliding window to chunk the book into overlapping sequences of max_length
|
||||||
|
for i in range(0, len(token_ids) - max_length, stride):
|
||||||
|
input_chunk = token_ids[i:i + max_length]
|
||||||
|
target_chunk = token_ids[i + 1: i + max_length + 1]
|
||||||
|
self.input_ids.append(torch.tensor(input_chunk))
|
||||||
|
self.target_ids.append(torch.tensor(target_chunk))
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.input_ids)
|
||||||
|
|
||||||
|
def __getitem__(self, idx):
|
||||||
|
return self.input_ids[idx], self.target_ids[idx]
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Create a data loader which given the text and some params will
|
||||||
|
prepare the inputs and targets with the previous class and
|
||||||
|
then create a torch DataLoader with the info
|
||||||
|
"""
|
||||||
|
|
||||||
|
import tiktoken
|
||||||
|
|
||||||
|
def create_dataloader_v1(txt, batch_size=4, max_length=256,
|
||||||
|
stride=128, shuffle=True, drop_last=True,
|
||||||
|
num_workers=0):
|
||||||
|
|
||||||
|
# Initialize the tokenizer
|
||||||
|
tokenizer = tiktoken.get_encoding("gpt2")
|
||||||
|
|
||||||
|
# Create dataset
|
||||||
|
dataset = GPTDatasetV1(txt, tokenizer, max_length, stride)
|
||||||
|
|
||||||
|
# Create dataloader
|
||||||
|
dataloader = DataLoader(
|
||||||
|
dataset,
|
||||||
|
batch_size=batch_size,
|
||||||
|
shuffle=shuffle,
|
||||||
|
drop_last=drop_last,
|
||||||
|
num_workers=num_workers
|
||||||
|
)
|
||||||
|
|
||||||
|
return dataloader
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Finally, create the data loader with the params we want:
|
||||||
|
- The used text for training
|
||||||
|
- batch_size: The size of each batch
|
||||||
|
- max_length: The size of each entry on each batch
|
||||||
|
- stride: The sliding window (how many tokens should the next entry advance compared to the previous one). The smaller the more overfitting, usually this is equals to the max_length so the same tokens aren't repeated.
|
||||||
|
- shuffle: Re-order randomly
|
||||||
|
"""
|
||||||
|
dataloader = create_dataloader_v1(
|
||||||
|
raw_text, batch_size=8, max_length=4, stride=1, shuffle=False
|
||||||
|
)
|
||||||
|
|
||||||
|
data_iter = iter(dataloader)
|
||||||
|
first_batch = next(data_iter)
|
||||||
|
print(first_batch)
|
||||||
|
|
||||||
|
# Note the batch_size of 8, the max_length of 4 and the stride of 1
|
||||||
|
[
|
||||||
|
# Input
|
||||||
|
tensor([[ 40, 367, 2885, 1464],
|
||||||
|
[ 367, 2885, 1464, 1807],
|
||||||
|
[ 2885, 1464, 1807, 3619],
|
||||||
|
[ 1464, 1807, 3619, 402],
|
||||||
|
[ 1807, 3619, 402, 271],
|
||||||
|
[ 3619, 402, 271, 10899],
|
||||||
|
[ 402, 271, 10899, 2138],
|
||||||
|
[ 271, 10899, 2138, 257]]),
|
||||||
|
# Target
|
||||||
|
tensor([[ 367, 2885, 1464, 1807],
|
||||||
|
[ 2885, 1464, 1807, 3619],
|
||||||
|
[ 1464, 1807, 3619, 402],
|
||||||
|
[ 1807, 3619, 402, 271],
|
||||||
|
[ 3619, 402, 271, 10899],
|
||||||
|
[ 402, 271, 10899, 2138],
|
||||||
|
[ 271, 10899, 2138, 257],
|
||||||
|
[10899, 2138, 257, 7026]])
|
||||||
|
]
|
||||||
|
|
||||||
|
# With stride=4 this will be the result:
|
||||||
|
[
|
||||||
|
# Input
|
||||||
|
tensor([[ 40, 367, 2885, 1464],
|
||||||
|
[ 1807, 3619, 402, 271],
|
||||||
|
[10899, 2138, 257, 7026],
|
||||||
|
[15632, 438, 2016, 257],
|
||||||
|
[ 922, 5891, 1576, 438],
|
||||||
|
[ 568, 340, 373, 645],
|
||||||
|
[ 1049, 5975, 284, 502],
|
||||||
|
[ 284, 3285, 326, 11]]),
|
||||||
|
# Target
|
||||||
|
tensor([[ 367, 2885, 1464, 1807],
|
||||||
|
[ 3619, 402, 271, 10899],
|
||||||
|
[ 2138, 257, 7026, 15632],
|
||||||
|
[ 438, 2016, 257, 922],
|
||||||
|
[ 5891, 1576, 438, 568],
|
||||||
|
[ 340, 373, 645, 1049],
|
||||||
|
[ 5975, 284, 502, 284],
|
||||||
|
[ 3285, 326, 11, 287]])
|
||||||
|
]
|
||||||
|
```
|
||||||
|
## Referanslar
|
||||||
|
|
||||||
|
- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
|
||||||
@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
## Token Embeddings
|
## Token Embeddings
|
||||||
|
|
||||||
Metin verilerini tokenize ettikten sonra, GPT gibi büyük dil modelleri (LLM'ler) için verileri hazırlamanın bir sonraki kritik adımı **token embedding'leri** oluşturmaktır. Token embedding'leri, ayrık token'leri (örneğin kelimeler veya alt kelimeler) modelin işleyip öğrenebileceği sürekli sayısal vektörlere dönüştürür. Bu açıklama, token embedding'lerini, başlatılmasını, kullanımını ve modelin token dizilerini anlama yetisini artıran konumsal embedding'lerin rolünü detaylandırır.
|
Metin verilerini tokenize ettikten sonra, büyük dil modelleri (LLM'ler) gibi GPT için verileri hazırlamanın bir sonraki kritik adımı **token embedding'leri** oluşturmaktır. Token embedding'leri, ayrık token'leri (örneğin kelimeler veya alt kelimeler) modelin işleyebileceği ve öğrenebileceği sürekli sayısal vektörlere dönüştürür. Bu açıklama, token embedding'lerini, başlatılmasını, kullanımını ve modelin token dizilerini anlama yetisini artırmada pozisyonel embedding'lerin rolünü detaylandırır.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu üçüncü aşamanın amacı çok basit: **Sözlükteki önceki her token'e modelin eğitimi için istenen boyutlarda bir vektör atamak.** Sözlükteki her kelime, X boyutlu bir uzayda bir noktaya sahip olacaktır.\
|
> Bu üçüncü aşamanın amacı çok basit: **Sözlükteki önceki her bir token'e modelin eğitimi için istenen boyutlarda bir vektör atamak.** Sözlükteki her kelime, X boyutlu bir uzayda bir noktaya sahip olacaktır.\
|
||||||
> Başlangıçta her kelimenin uzaydaki konumunun "rastgele" başlatıldığını ve bu konumların eğitilebilir parametreler olduğunu unutmayın (eğitim sırasında geliştirilecektir).
|
> Başlangıçta her kelimenin uzaydaki konumunun "rastgele" başlatıldığını ve bu konumların eğitilebilir parametreler olduğunu unutmayın (eğitim sırasında geliştirilecektir).
|
||||||
>
|
>
|
||||||
> Ayrıca, token embedding sırasında **başka bir embedding katmanı oluşturulur** ki bu, (bu durumda) **kelimenin eğitim cümlesindeki mutlak konumunu** temsil eder. Bu şekilde, cümledeki farklı konumlarda bir kelime farklı bir temsil (anlam) alacaktır.
|
> Ayrıca, token embedding sırasında **başka bir embedding katmanı oluşturulur** ki bu, (bu durumda) **kelimenin eğitim cümlesindeki mutlak konumunu** temsil eder. Bu şekilde, cümledeki farklı konumlarda bir kelime farklı bir temsil (anlam) alacaktır.
|
||||||
|
|
||||||
### **Token Embedding Nedir?**
|
### **Token Embedding Nedir?**
|
||||||
|
|
||||||
**Token Embedding'leri**, token'ların sürekli bir vektör uzayındaki sayısal temsilleridir. Sözlükteki her token, sabit boyutlarda benzersiz bir vektör ile ilişkilendirilir. Bu vektörler, token'lar hakkında anlamsal ve sözdizimsel bilgileri yakalayarak modelin verilerdeki ilişkileri ve kalıpları anlamasını sağlar.
|
**Token Embedding'leri**, token'ların sürekli bir vektör uzayındaki sayısal temsilleridir. Sözlükteki her token, sabit boyutlarda benzersiz bir vektör ile ilişkilendirilir. Bu vektörler, token'lar hakkında anlamsal ve sözdizimsel bilgileri yakalar, böylece modelin verilerdeki ilişkileri ve kalıpları anlamasını sağlar.
|
||||||
|
|
||||||
- **Sözlük Boyutu:** Modelin sözlüğündeki benzersiz token'ların (örneğin, kelimeler, alt kelimeler) toplam sayısı.
|
- **Sözlük Boyutu:** Modelin sözlüğündeki benzersiz token'ların (örneğin, kelimeler, alt kelimeler) toplam sayısı.
|
||||||
- **Embedding Boyutları:** Her token'in vektöründeki sayısal değerlerin (boyutların) sayısı. Daha yüksek boyutlar daha ince bilgileri yakalayabilir ancak daha fazla hesaplama kaynağı gerektirir.
|
- **Embedding Boyutları:** Her token'in vektöründeki sayısal değerlerin (boyutların) sayısı. Daha yüksek boyutlar daha ince bilgileri yakalayabilir ancak daha fazla hesaplama kaynağı gerektirir.
|
||||||
@ -82,7 +82,7 @@ Eğitim sırasında, giriş verilerindeki her token, karşılık gelen gömme ve
|
|||||||
|
|
||||||
**Veri Yapısı:**
|
**Veri Yapısı:**
|
||||||
|
|
||||||
- Her batch, `(batch_size, max_length, embedding_dim)` şeklinde 3D bir tensör olarak temsil edilir.
|
- Her batch, `(batch_size, max_length, embedding_dim)` şekline sahip 3D bir tensör olarak temsil edilir.
|
||||||
- Örneğimiz için şekil `(8, 4, 256)` olacaktır.
|
- Örneğimiz için şekil `(8, 4, 256)` olacaktır.
|
||||||
|
|
||||||
**Görselleştirme:**
|
**Görselleştirme:**
|
||||||
@ -133,18 +133,18 @@ Token gömmeleri bireysel token'ların anlamını yakalarken, bir dizideki token
|
|||||||
### **Pozisyonel Gömme Türleri:**
|
### **Pozisyonel Gömme Türleri:**
|
||||||
|
|
||||||
1. **Mutlak Pozisyonel Gömme:**
|
1. **Mutlak Pozisyonel Gömme:**
|
||||||
- Dizideki her pozisyona benzersiz bir konum vektörü atar.
|
- Dizideki her pozisyona benzersiz bir pozisyon vektörü atar.
|
||||||
- **Örnek:** Herhangi bir dizideki ilk token aynı pozisyonel gömme vektörüne sahiptir, ikinci token başka birine sahiptir, ve bu şekilde devam eder.
|
- **Örnek:** Herhangi bir dizideki ilk token aynı pozisyonel gömme vektörüne, ikinci token başka birine ve devam eder.
|
||||||
- **Kullananlar:** OpenAI’nin GPT modelleri.
|
- **Kullananlar:** OpenAI’nin GPT modelleri.
|
||||||
2. **Göreli Pozisyonel Gömme:**
|
2. **Göreli Pozisyonel Gömme:**
|
||||||
- Token'lar arasındaki göreli mesafeyi kodlar, mutlak konumlarını değil.
|
- Token'lar arasındaki göreli mesafeyi kodlar, mutlak pozisyonlarını değil.
|
||||||
- **Örnek:** İki token'ın ne kadar uzakta olduğunu belirtir, mutlak konumlarına bakılmaksızın.
|
- **Örnek:** İki token'ın ne kadar uzak olduğunu belirtir, mutlak pozisyonlarına bakılmaksızın.
|
||||||
- **Kullananlar:** Transformer-XL gibi modeller ve bazı BERT varyantları.
|
- **Kullananlar:** Transformer-XL gibi modeller ve bazı BERT varyantları.
|
||||||
|
|
||||||
### **Pozisyonel Gömme Nasıl Entegre Edilir:**
|
### **Pozisyonel Gömme Nasıl Entegre Edilir:**
|
||||||
|
|
||||||
- **Aynı Boyutlar:** Pozisyonel gömmeler, token gömmeleriyle aynı boyutluluğa sahiptir.
|
- **Aynı Boyutlar:** Pozisyonel gömmeler, token gömmeleriyle aynı boyutluluğa sahiptir.
|
||||||
- **Toplama:** Token gömmelerine eklenir, token kimliğini pozisyonel bilgiyle birleştirir ve genel boyutluluğu artırmaz.
|
- **Toplama:** Token kimliğini pozisyonel bilgiyle birleştirerek, genel boyutluluğu artırmadan token gömmelerine eklenir.
|
||||||
|
|
||||||
**Pozisyonel Gömme Ekleme Örneği:**
|
**Pozisyonel Gömme Ekleme Örneği:**
|
||||||
|
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
## Dikkat Mekanizmaları ve Sinir Ağlarındaki Kendine Dikkat
|
## Dikkat Mekanizmaları ve Sinir Ağlarındaki Kendine Dikkat
|
||||||
|
|
||||||
Dikkat mekanizmaları, sinir ağlarının **her bir çıktı parçasını oluştururken girdiğin belirli kısımlarına odaklanmasını** sağlar. Farklı girdilere farklı ağırlıklar atayarak, modelin mevcut görevle en ilgili girdileri belirlemesine yardımcı olur. Bu, makine çevirisi gibi görevlerde, tüm cümlenin bağlamını anlamanın doğru çeviri için gerekli olduğu durumlarda kritik öneme sahiptir.
|
Dikkat mekanizmaları, sinir ağlarının her çıktı parçasını oluştururken girdi verisinin belirli kısımlarına odaklanmasını sağlar. Farklı girdilere farklı ağırlıklar atayarak, modelin mevcut görevle en ilgili girdileri belirlemesine yardımcı olur. Bu, makine çevirisi gibi görevlerde, tüm cümlenin bağlamını anlamanın doğru çeviri için gerekli olduğu durumlarda kritik öneme sahiptir.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu dördüncü aşamanın amacı çok basit: **Bazı dikkat mekanizmaları uygulamak**. Bunlar, **LLM'yi eğitmek için kullanılan mevcut cümledeki bir kelimenin komşularıyla olan ilişkisini yakalayacak çok sayıda **tekrarlanan katman** olacak.**\
|
> Bu dördüncü aşamanın amacı çok basit: **Bazı dikkat mekanizmaları uygulamak**. Bunlar, **LLM'yi eğitmek için kullanılan mevcut cümledeki bir kelimenin komşularıyla olan ilişkisini yakalayacak çok sayıda **tekrarlanan katman** olacak.**\
|
||||||
> Bunun için çok sayıda katman kullanılacak, bu nedenle çok sayıda eğitilebilir parametre bu bilgiyi yakalayacak.
|
> Bunun için çok sayıda katman kullanılır, bu nedenle çok sayıda eğitilebilir parametre bu bilgiyi yakalayacaktır.
|
||||||
|
|
||||||
### Dikkat Mekanizmalarını Anlamak
|
### Dikkat Mekanizmalarını Anlamak
|
||||||
|
|
||||||
Dil çevirisi için kullanılan geleneksel sıralı modellemelerde, model bir girdi dizisini sabit boyutlu bir bağlam vektörüne kodlar. Ancak, bu yaklaşım uzun cümlelerle zorlanır çünkü sabit boyutlu bağlam vektörü gerekli tüm bilgileri yakalayamayabilir. Dikkat mekanizmaları, modelin her çıktı tokenini oluştururken tüm girdi tokenlerini dikkate almasına olanak tanıyarak bu sınırlamayı aşar.
|
Dil çevirisi için kullanılan geleneksel sıralı modellemelerde, model bir girdi dizisini sabit boyutlu bir bağlam vektörüne kodlar. Ancak, bu yaklaşım uzun cümlelerle başa çıkmakta zorlanır çünkü sabit boyutlu bağlam vektörü gerekli tüm bilgileri yakalayamayabilir. Dikkat mekanizmaları, modelin her çıktı token'ını oluştururken tüm girdi token'larını dikkate almasına olanak tanıyarak bu sınırlamayı aşar.
|
||||||
|
|
||||||
#### Örnek: Makine Çevirisi
|
#### Örnek: Makine Çevirisi
|
||||||
|
|
||||||
@ -18,13 +18,13 @@ Almanca "Kannst du mir helfen diesen Satz zu übersetzen" cümlesini İngilizcey
|
|||||||
|
|
||||||
### Kendine Dikkate Giriş
|
### Kendine Dikkate Giriş
|
||||||
|
|
||||||
Kendine dikkat, ya da içsel dikkat, dikkat mekanizmasının tek bir dizide uygulanarak o dizinin bir temsilini hesapladığı bir mekanizmadır. Bu, dizideki her tokenin diğer tüm tokenlere dikkat etmesine olanak tanır ve modelin tokenler arasındaki bağımlılıkları, dizideki mesafelerine bakılmaksızın yakalamasına yardımcı olur.
|
Kendine dikkat, ya da intra-dikkat, dikkat mekanizmasının tek bir dizide uygulanarak o dizinin bir temsilini hesapladığı bir mekanizmadır. Bu, dizideki her token'ın diğer tüm token'lara dikkat etmesine olanak tanır ve modelin token'lar arasındaki bağımlılıkları, dizideki mesafelerine bakılmaksızın yakalamasına yardımcı olur.
|
||||||
|
|
||||||
#### Temel Kavramlar
|
#### Temel Kavramlar
|
||||||
|
|
||||||
- **Tokenler**: Girdi dizisinin bireysel öğeleri (örneğin, bir cümledeki kelimeler).
|
- **Token'lar**: Girdi dizisinin bireysel elemanları (örneğin, bir cümledeki kelimeler).
|
||||||
- **Gömme**: Anlamsal bilgiyi yakalayan tokenlerin vektör temsilleri.
|
- **Gömme**: Token'ların vektör temsilleri, anlamsal bilgiyi yakalar.
|
||||||
- **Dikkat Ağırlıkları**: Her tokenin diğerlerine göre önemini belirleyen değerler.
|
- **Dikkat Ağırlıkları**: Her token'ın diğerlerine göre önemini belirleyen değerler.
|
||||||
|
|
||||||
### Dikkat Ağırlıklarını Hesaplama: Adım Adım Bir Örnek
|
### Dikkat Ağırlıklarını Hesaplama: Adım Adım Bir Örnek
|
||||||
|
|
||||||
@ -34,14 +34,14 @@ Kendine dikkat, ya da içsel dikkat, dikkat mekanizmasının tek bir dizide uygu
|
|||||||
- **shiny**: `[0.53, 0.34, 0.98]`
|
- **shiny**: `[0.53, 0.34, 0.98]`
|
||||||
- **sun**: `[0.29, 0.54, 0.93]`
|
- **sun**: `[0.29, 0.54, 0.93]`
|
||||||
|
|
||||||
Amacımız, **shiny** kelimesi için **bağlam vektörünü** kendine dikkat kullanarak hesaplamaktır.
|
Amacımız, **shiny** kelimesi için kendine dikkat kullanarak **bağlam vektörünü** hesaplamaktır.
|
||||||
|
|
||||||
#### Adım 1: Dikkat Puanlarını Hesapla
|
#### Adım 1: Dikkat Puanlarını Hesapla
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Sadece sorgunun her boyut değerini ilgili tokenin her boyutuyla çarpın ve sonuçları toplayın. Her token çifti için 1 değer elde edersiniz.
|
> Sadece sorgunun her boyut değerini ilgili token'ınki ile çarpın ve sonuçları toplayın. Her token çifti için 1 değer elde edersiniz.
|
||||||
|
|
||||||
Cümledeki her kelime için, **shiny** ile ilgili dikkat puanını, gömmelerinin noktasal çarpımını hesaplayarak hesaplayın.
|
Cümledeki her kelime için, **shiny** ile ilgili dikkat puanını, gömmelerinin nokta çarpımını hesaplayarak hesaplayın.
|
||||||
|
|
||||||
**"Hello" ile "shiny" arasındaki Dikkat Puanı**
|
**"Hello" ile "shiny" arasındaki Dikkat Puanı**
|
||||||
|
|
||||||
@ -58,9 +58,8 @@ Cümledeki her kelime için, **shiny** ile ilgili dikkat puanını, gömmelerini
|
|||||||
#### Adım 2: Dikkat Puanlarını Normalleştirerek Dikkat Ağırlıklarını Elde Et
|
#### Adım 2: Dikkat Puanlarını Normalleştirerek Dikkat Ağırlıklarını Elde Et
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Matematik terimlerinde kaybolmayın, bu fonksiyonun amacı basit, tüm ağırlıkları normalleştirin ki **toplamları 1 olsun**.
|
> Matematik terimlerinde kaybolmayın, bu fonksiyonun amacı basit, tüm ağırlıkları normalleştirin ki **toplamları 1 olsun**.\
|
||||||
>
|
> Ayrıca, **softmax** fonksiyonu, üstel kısım nedeniyle farklılıkları vurguladığı için, yararlı değerleri tespit etmeyi kolaylaştırır.
|
||||||
> Ayrıca, **softmax** fonksiyonu kullanılır çünkü üstel kısım nedeniyle farklılıkları vurgular, yararlı değerleri tespit etmeyi kolaylaştırır.
|
|
||||||
|
|
||||||
Dikkat puanlarına **softmax fonksiyonunu** uygulayarak, toplamı 1 olan dikkat ağırlıklarına dönüştürün.
|
Dikkat puanlarına **softmax fonksiyonunu** uygulayarak, toplamı 1 olan dikkat ağırlıklarına dönüştürün.
|
||||||
|
|
||||||
@ -83,7 +82,7 @@ Dikkat ağırlıklarını hesaplama:
|
|||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Her dikkat ağırlığını alın ve ilgili token boyutlarıyla çarpın, ardından tüm boyutları toplayarak sadece 1 vektör (bağlam vektörü) elde edin.
|
> Her dikkat ağırlığını alın ve ilgili token boyutlarıyla çarpın, ardından tüm boyutları toplayarak sadece 1 vektör (bağlam vektörü) elde edin.
|
||||||
|
|
||||||
**Bağlam vektörü**, tüm kelimelerin gömmelerinin ağırlıklı toplamı olarak hesaplanır ve dikkat ağırlıkları kullanılır.
|
**Bağlam vektörü**, tüm kelimelerin gömmelerinin ağırlıklı toplamı olarak hesaplanır, dikkat ağırlıklarını kullanarak.
|
||||||
|
|
||||||
<figure><img src="../../images/image (16).png" alt="" width="369"><figcaption></figcaption></figure>
|
<figure><img src="../../images/image (16).png" alt="" width="369"><figcaption></figcaption></figure>
|
||||||
|
|
||||||
@ -109,7 +108,7 @@ Ağırlıklı gömmeleri toplama:
|
|||||||
|
|
||||||
### Sürecin Özeti
|
### Sürecin Özeti
|
||||||
|
|
||||||
1. **Dikkat Puanlarını Hesapla**: Hedef kelimenin gömmesi ile dizideki tüm kelimelerin gömmeleri arasındaki noktasal çarpımı kullanın.
|
1. **Dikkat Puanlarını Hesapla**: Hedef kelimenin gömmesi ile dizideki tüm kelimelerin gömmeleri arasındaki nokta çarpımını kullanın.
|
||||||
2. **Ağırlıkları Elde Etmek için Puanları Normalleştir**: Dikkat puanlarına softmax fonksiyonunu uygulayarak toplamı 1 olan ağırlıklar elde edin.
|
2. **Ağırlıkları Elde Etmek için Puanları Normalleştir**: Dikkat puanlarına softmax fonksiyonunu uygulayarak toplamı 1 olan ağırlıklar elde edin.
|
||||||
3. **Bağlam Vektörünü Hesapla**: Her kelimenin gömmesini dikkat ağırlığı ile çarpın ve sonuçları toplayın.
|
3. **Bağlam Vektörünü Hesapla**: Her kelimenin gömmesini dikkat ağırlığı ile çarpın ve sonuçları toplayın.
|
||||||
|
|
||||||
@ -163,7 +162,7 @@ values = torch.matmul(inputs, W_value)
|
|||||||
|
|
||||||
**Puanları Ölçekle**
|
**Puanları Ölçekle**
|
||||||
|
|
||||||
Nokta ürünlerinin çok büyük hale gelmesini önlemek için, bunları anahtar boyutunun karekökü `dk` ile ölçeklendir:
|
Nokta ürünlerinin çok büyük olmasını önlemek için, bunları anahtar boyutunun karekökü `dk` ile ölçeklendir:
|
||||||
|
|
||||||
<figure><img src="../../images/image (13).png" alt="" width="295"><figcaption></figcaption></figure>
|
<figure><img src="../../images/image (13).png" alt="" width="295"><figcaption></figcaption></figure>
|
||||||
|
|
||||||
@ -176,7 +175,7 @@ Nokta ürünlerinin çok büyük hale gelmesini önlemek için, bunları anahtar
|
|||||||
|
|
||||||
#### Adım 3: Bağlam Vektörlerini Hesapla
|
#### Adım 3: Bağlam Vektörlerini Hesapla
|
||||||
|
|
||||||
İlk örnekte olduğu gibi, her birini dikkat ağırlığı ile çarparak tüm değer matrislerini topla:
|
İlk örnekte olduğu gibi, sadece tüm değer matrislerini topla ve her birini dikkat ağırlığı ile çarp:
|
||||||
|
|
||||||
<figure><img src="../../images/image (15).png" alt="" width="328"><figcaption></figcaption></figure>
|
<figure><img src="../../images/image (15).png" alt="" width="328"><figcaption></figcaption></figure>
|
||||||
|
|
||||||
@ -226,7 +225,7 @@ print(sa_v2(inputs))
|
|||||||
|
|
||||||
## Nedensel Dikkat: Gelecek Kelimeleri Gizleme
|
## Nedensel Dikkat: Gelecek Kelimeleri Gizleme
|
||||||
|
|
||||||
LLM'ler için modelin, **bir sonraki token'ı tahmin etmek** amacıyla mevcut konumdan önceki token'ları dikkate almasını istiyoruz. **Nedensel dikkat**, aynı zamanda **maskelenmiş dikkat** olarak da bilinir, dikkat mekanizmasını değiştirerek gelecekteki token'lara erişimi engelleyerek bunu başarır.
|
LLM'ler için modelin, **bir sonraki token'ı tahmin etmek** amacıyla mevcut pozisyondan önceki token'ları dikkate almasını istiyoruz. **Nedensel dikkat**, aynı zamanda **maskelenmiş dikkat** olarak da bilinir, dikkat mekanizmasını değiştirerek gelecekteki token'lara erişimi engelleyerek bunu başarır.
|
||||||
|
|
||||||
### Nedensel Dikkat Maskesi Uygulama
|
### Nedensel Dikkat Maskesi Uygulama
|
||||||
|
|
||||||
@ -327,7 +326,7 @@ print("context_vecs.shape:", context_vecs.shape)
|
|||||||
|
|
||||||
### Kod Örneği
|
### Kod Örneği
|
||||||
|
|
||||||
Önceki kodu yeniden kullanmak ve sadece birkaç kez çalıştıran bir sarmalayıcı eklemek mümkün olabilir, ancak bu, tüm başları aynı anda işleyen [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb) daha optimize edilmiş bir versiyonudur (pahalı for döngülerinin sayısını azaltır). Kodda görebileceğiniz gibi, her bir token'ın boyutları baş sayısına göre farklı boyutlara bölünmüştür. Bu şekilde, token 8 boyuta sahipse ve 3 baş kullanmak istiyorsak, boyutlar 4 boyuttan oluşan 2 diziye bölünecek ve her baş bunlardan birini kullanacaktır:
|
Önceki kodu yeniden kullanmak ve sadece birkaç kez çalıştıran bir sarmalayıcı eklemek mümkün olabilir, ancak bu, tüm başları aynı anda işleyen [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb) adresinden daha optimize edilmiş bir versiyondur (pahalı for döngülerinin sayısını azaltır). Kodda görebileceğiniz gibi, her bir token'ın boyutları baş sayısına göre farklı boyutlara bölünmüştür. Bu şekilde, eğer token 8 boyuta sahipse ve 3 baş kullanmak istiyorsak, boyutlar 4 boyuttan oluşan 2 diziye bölünecek ve her baş bunlardan birini kullanacaktır:
|
||||||
```python
|
```python
|
||||||
class MultiHeadAttention(nn.Module):
|
class MultiHeadAttention(nn.Module):
|
||||||
def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
|
def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
|
||||||
@ -409,7 +408,7 @@ Başka bir kompakt ve verimli uygulama için PyTorch'taki [`torch.nn.MultiheadAt
|
|||||||
> [!TIP]
|
> [!TIP]
|
||||||
> ChatGPT'nin, her başın tüm token'ların tüm boyutlarını kontrol etmesi yerine token'ların boyutlarını başlar arasında bölmenin neden daha iyi olduğuna dair kısa yanıtı:
|
> ChatGPT'nin, her başın tüm token'ların tüm boyutlarını kontrol etmesi yerine token'ların boyutlarını başlar arasında bölmenin neden daha iyi olduğuna dair kısa yanıtı:
|
||||||
>
|
>
|
||||||
> Her başın tüm gömme boyutlarını işlemesine izin vermek, her başın tam bilgiye erişimi olacağı için avantajlı gibi görünse de, standart uygulama **gömme boyutlarını başlar arasında bölmektir**. Bu yaklaşım, hesaplama verimliliği ile model performansı arasında bir denge sağlar ve her başın çeşitli temsilleri öğrenmesini teşvik eder. Bu nedenle, gömme boyutlarını bölmek, her başın tüm boyutları kontrol etmesinden genellikle tercih edilir.
|
> Her başın tüm gömme boyutlarını işlemesine izin vermek, her başın tam bilgilere erişimi olacağı için avantajlı gibi görünse de, standart uygulama **gömme boyutlarını başlar arasında bölmektir**. Bu yaklaşım, hesaplama verimliliği ile model performansını dengeler ve her başın çeşitli temsilleri öğrenmesini teşvik eder. Bu nedenle, gömme boyutlarını bölmek, her başın tüm boyutları kontrol etmesinden genellikle tercih edilir.
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu beşinci aşamanın amacı çok basit: **Tam LLM mimarisini geliştirmek**. Her şeyi bir araya getirin, tüm katmanları uygulayın ve metin oluşturmak veya metni kimliklere ve geriye dönüştürmek için tüm işlevleri oluşturun.
|
> Bu beşinci aşamanın amacı çok basit: **Tam LLM mimarisini geliştirmek**. Her şeyi bir araya getirin, tüm katmanları uygulayın ve metin oluşturmak veya metni kimliklere ve geriye dönüştürmek için tüm işlevleri oluşturun.
|
||||||
>
|
>
|
||||||
> Bu mimari, eğitim ve eğitimden sonra metin tahmini için kullanılacaktır.
|
> Bu mimari, hem eğitim hem de eğitimden sonra metin tahmini için kullanılacaktır.
|
||||||
|
|
||||||
LLM mimarisi örneği [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb):
|
LLM mimarisi örneği [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb):
|
||||||
|
|
||||||
@ -14,13 +14,13 @@ Yüksek seviyeli bir temsil aşağıda gözlemlenebilir:
|
|||||||
<figure><img src="../../images/image (3) (1) (1) (1).png" alt="" width="563"><figcaption><p><a href="https://camo.githubusercontent.com/6c8c392f72d5b9e86c94aeb9470beab435b888d24135926f1746eb88e0cc18fb/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830345f636f6d707265737365642f31332e776562703f31">https://camo.githubusercontent.com/6c8c392f72d5b9e86c94aeb9470beab435b888d24135926f1746eb88e0cc18fb/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830345f636f6d707265737365642f31332e776562703f31</a></p></figcaption></figure>
|
<figure><img src="../../images/image (3) (1) (1) (1).png" alt="" width="563"><figcaption><p><a href="https://camo.githubusercontent.com/6c8c392f72d5b9e86c94aeb9470beab435b888d24135926f1746eb88e0cc18fb/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830345f636f6d707265737365642f31332e776562703f31">https://camo.githubusercontent.com/6c8c392f72d5b9e86c94aeb9470beab435b888d24135926f1746eb88e0cc18fb/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830345f636f6d707265737365642f31332e776562703f31</a></p></figcaption></figure>
|
||||||
|
|
||||||
1. **Girdi (Tokenize Edilmiş Metin)**: Süreç, sayısal temsillere dönüştürülen tokenize edilmiş metinle başlar.
|
1. **Girdi (Tokenize Edilmiş Metin)**: Süreç, sayısal temsillere dönüştürülen tokenize edilmiş metinle başlar.
|
||||||
2. **Token Gömme ve Pozisyon Gömme Katmanı**: Tokenize edilmiş metin, bir **token gömme** katmanından ve bir **pozisyon gömme katmanından** geçirilir; bu, kelime sırasını anlamak için kritik olan bir dizideki tokenların konumunu yakalar.
|
2. **Token Gömme ve Pozisyon Gömme Katmanı**: Tokenize edilmiş metin, kelime sırasını anlamak için kritik olan bir dizideki token'ların konumunu yakalayan bir **token gömme** katmanı ve bir **pozisyon gömme katmanı** aracılığıyla geçer.
|
||||||
3. **Transformer Blokları**: Model, her biri birden fazla katmana sahip **12 transformer bloğu** içerir. Bu bloklar aşağıdaki diziyi tekrarlar:
|
3. **Transformer Blokları**: Model, her biri birden fazla katmana sahip **12 transformer bloğu** içerir. Bu bloklar aşağıdaki diziyi tekrarlar:
|
||||||
- **Masked Multi-Head Attention**: Modelin girdi metninin farklı kısımlarına aynı anda odaklanmasına olanak tanır.
|
- **Masked Multi-Head Attention**: Modelin girdi metninin farklı kısımlarına aynı anda odaklanmasını sağlar.
|
||||||
- **Katman Normalizasyonu**: Eğitimi stabilize etmek ve geliştirmek için bir normalizasyon adımı.
|
- **Katman Normalizasyonu**: Eğitimi stabilize etmek ve geliştirmek için bir normalizasyon adımı.
|
||||||
- **İleri Besleme Katmanı**: Dikkat katmanından gelen bilgileri işlemek ve bir sonraki token hakkında tahminlerde bulunmakla sorumludur.
|
- **İleri Besleme Katmanı**: Dikkat katmanından gelen bilgileri işlemek ve bir sonraki token hakkında tahminlerde bulunmakla sorumludur.
|
||||||
- **Dropout Katmanları**: Bu katmanlar, eğitim sırasında birimlerin rastgele düşürülmesiyle aşırı uyumu önler.
|
- **Dropout Katmanları**: Bu katmanlar, eğitim sırasında birimlerin rastgele düşürülmesiyle aşırı uyumu önler.
|
||||||
4. **Son Çıktı Katmanı**: Model, **4x50,257 boyutlu bir tensör** çıktısı verir; burada **50,257** kelime dağarcığının boyutunu temsil eder. Bu tensördeki her bir satır, modelin dizideki bir sonraki kelimeyi tahmin etmek için kullandığı bir vektöre karşılık gelir.
|
4. **Son Çıktı Katmanı**: Model, **50,257** kelime dağarcığı boyutunu temsil eden **4x50,257 boyutunda bir tensör** üretir. Bu tensördeki her bir satır, modelin dizideki bir sonraki kelimeyi tahmin etmek için kullandığı bir vektöre karşılık gelir.
|
||||||
5. **Amaç**: Amaç, bu gömmeleri alıp tekrar metne dönüştürmektir. Özellikle, çıktının son satırı, bu diyagramda "ileri" olarak temsil edilen bir sonraki kelimeyi oluşturmak için kullanılır.
|
5. **Amaç**: Amaç, bu gömmeleri alıp tekrar metne dönüştürmektir. Özellikle, çıktının son satırı, bu diyagramda "ileri" olarak temsil edilen bir sonraki kelimeyi oluşturmak için kullanılır.
|
||||||
|
|
||||||
### Kod temsili
|
### Kod temsili
|
||||||
@ -210,8 +210,8 @@ torch.sqrt(torch.tensor(2.0 / torch.pi)) *
|
|||||||
```
|
```
|
||||||
#### **Amaç ve İşlevsellik**
|
#### **Amaç ve İşlevsellik**
|
||||||
|
|
||||||
- **GELU (Gaussian Error Linear Unit):** Modele doğrusal olmayanlık katan bir aktivasyon fonksiyonu.
|
- **GELU (Gaussian Error Linear Unit):** Modelle doğrusal olmayanlık getiren bir aktivasyon fonksiyonu.
|
||||||
- **Düzgün Aktivasyon:** Negatif girdileri sıfıra indiren ReLU'nun aksine, GELU girdileri çıktılara düzgün bir şekilde eşler ve negatif girdiler için küçük, sıfırdan farklı değerler sağlar.
|
- **Düzgün Aktivasyon:** Negatif girdileri sıfıra indiren ReLU'nun aksine, GELU girdileri çıktılara düzgün bir şekilde haritalar, negatif girdiler için küçük, sıfırdan farklı değerler sağlar.
|
||||||
- **Matematiksel Tanım:**
|
- **Matematiksel Tanım:**
|
||||||
|
|
||||||
<figure><img src="../../images/image (2) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
<figure><img src="../../images/image (2) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||||
@ -258,18 +258,18 @@ Bu daha önceki bir bölümde açıklandı.
|
|||||||
|
|
||||||
#### **Amaç ve İşlevsellik**
|
#### **Amaç ve İşlevsellik**
|
||||||
|
|
||||||
- **Çoklu Başlı Kendine Dikkat:** Modelin bir token'ı kodlarken girdi dizisi içindeki farklı pozisyonlara odaklanmasını sağlar.
|
- **Çoklu Başlı Kendine Dikkat:** Modelin bir token'ı kodlarken girdi dizisi içindeki farklı pozisyonlara odaklanmasına olanak tanır.
|
||||||
- **Ana Bileşenler:**
|
- **Ana Bileşenler:**
|
||||||
- **Sorgular, Anahtarlar, Değerler:** Girdinin lineer projeksiyonları, dikkat puanlarını hesaplamak için kullanılır.
|
- **Sorgular, Anahtarlar, Değerler:** Girdinin lineer projeksiyonları, dikkat puanlarını hesaplamak için kullanılır.
|
||||||
- **Başlar:** Paralel çalışan birden fazla dikkat mekanizması (`num_heads`), her biri azaltılmış bir boyutla (`head_dim`).
|
- **Başlar:** Paralel çalışan birden fazla dikkat mekanizması (`num_heads`), her biri azaltılmış bir boyutla (`head_dim`).
|
||||||
- **Dikkat Puanları:** Sorgular ve anahtarların noktasal çarpımı olarak hesaplanır, ölçeklenir ve maske uygulanır.
|
- **Dikkat Puanları:** Sorgular ve anahtarların noktasal çarpımı olarak hesaplanır, ölçeklendirilir ve maske uygulanır.
|
||||||
- **Maskeleme:** Gelecek token'lara dikkat edilmesini önlemek için nedensel bir maske uygulanır (GPT gibi otoregresif modeller için önemlidir).
|
- **Maskeleme:** Gelecek token'lara dikkat edilmesini önlemek için nedensel bir maske uygulanır (GPT gibi otoregresif modeller için önemlidir).
|
||||||
- **Dikkat Ağırlıkları:** Maskelenmiş ve ölçeklenmiş dikkat puanlarının softmax'ı.
|
- **Dikkat Ağırlıkları:** Maskelenmiş ve ölçeklendirilmiş dikkat puanlarının softmax'ı.
|
||||||
- **Bağlam Vektörü:** Dikkat ağırlıklarına göre değerlerin ağırlıklı toplamı.
|
- **Bağlam Vektörü:** Dikkat ağırlıklarına göre değerlerin ağırlıklı toplamı.
|
||||||
- **Çıktı Projeksiyonu:** Tüm başların çıktısını birleştirmek için lineer katman.
|
- **Çıktı Projeksiyonu:** Tüm başların çıktısını birleştiren lineer katman.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu ağın amacı, aynı bağlamdaki token'lar arasındaki ilişkileri bulmaktır. Ayrıca, aşırı uyumu önlemek için token'lar farklı başlara bölünmüştür, ancak her başta bulunan nihai ilişkiler bu ağın sonunda birleştirilir.
|
> Bu ağın amacı, aynı bağlamdaki token'lar arasındaki ilişkileri bulmaktır. Ayrıca, aşırı uyum sağlamayı önlemek için token'lar farklı başlara bölünmüştür, ancak her başta bulunan nihai ilişkiler bu ağın sonunda birleştirilir.
|
||||||
>
|
>
|
||||||
> Ayrıca, eğitim sırasında **nedensel bir maske** uygulanır, böylece belirli bir token'a bakarken sonraki token'lar dikkate alınmaz ve **aşırı uyumu önlemek** için bazı **dropout** uygulanır.
|
> Ayrıca, eğitim sırasında **nedensel bir maske** uygulanır, böylece belirli bir token'a bakarken sonraki token'lar dikkate alınmaz ve **aşırı uyumu önlemek** için bazı **dropout** uygulanır.
|
||||||
|
|
||||||
@ -294,12 +294,12 @@ return self.scale * norm_x + self.shift
|
|||||||
- **Katman Normalizasyonu:** Bir partideki her bireysel örnek için özellikler (gömme boyutları) boyunca girdileri normalleştirmek için kullanılan bir teknik.
|
- **Katman Normalizasyonu:** Bir partideki her bireysel örnek için özellikler (gömme boyutları) boyunca girdileri normalleştirmek için kullanılan bir teknik.
|
||||||
- **Bileşenler:**
|
- **Bileşenler:**
|
||||||
- **`eps`:** Normalizasyon sırasında sıfıra bölmeyi önlemek için varyansa eklenen küçük bir sabit (`1e-5`).
|
- **`eps`:** Normalizasyon sırasında sıfıra bölmeyi önlemek için varyansa eklenen küçük bir sabit (`1e-5`).
|
||||||
- **`scale` ve `shift`:** Normalleştirilmiş çıktıyı ölçeklendirmek ve kaydırmak için modelin öğrenebileceği parametreler (`nn.Parameter`). Sırasıyla birler ve sıfırlar ile başlatılır.
|
- **`scale` ve `shift`:** Normalleştirilmiş çıktıyı ölçeklendirmek ve kaydırmak için modelin kullanabileceği öğrenilebilir parametreler (`nn.Parameter`). Sırasıyla birler ve sıfırlar ile başlatılır.
|
||||||
- **Normalizasyon Süreci:**
|
- **Normalizasyon Süreci:**
|
||||||
- **Ortalama Hesapla (`mean`):** Gömme boyutu boyunca giriş `x`'in ortalamasını hesaplar (`dim=-1`), yayılma boyutunu koruyarak (`keepdim=True`).
|
- **Ortalama Hesaplama (`mean`):** Gömme boyutu boyunca giriş `x`'in ortalamasını hesaplar (`dim=-1`), yayılma için boyutu korur (`keepdim=True`).
|
||||||
- **Varyans Hesapla (`var`):** Gömme boyutu boyunca `x`'in varyansını hesaplar, boyutu da koruyarak. `unbiased=False` parametresi, varyansın yanlı tahminci kullanılarak hesaplanmasını sağlar (örnek sayısı `N` yerine `N-1` ile bölünerek), bu da örnekler yerine özellikler üzerinde normalleştirme yaparken uygundur.
|
- **Varyans Hesaplama (`var`):** Gömme boyutu boyunca `x`'in varyansını hesaplar, boyutu da korur. `unbiased=False` parametresi, varyansın yanlı tahminci kullanılarak hesaplanmasını sağlar (örnek sayısı `N` yerine `N-1` ile bölünerek), bu da örnekler yerine özellikler üzerinde normalleştirme yaparken uygundur.
|
||||||
- **Normalleştir (`norm_x`):** `x`'ten ortalamayı çıkarır ve varyansın karekökü artı `eps` ile böler.
|
- **Normalleştirme (`norm_x`):** `x`'ten ortalamayı çıkarır ve varyansın karekökü artı `eps` ile böler.
|
||||||
- **Ölçek ve Kaydır:** Normalleştirilmiş çıktıya öğrenilebilir `scale` ve `shift` parametrelerini uygular.
|
- **Ölçekleme ve Kaydırma:** Normalleştirilmiş çıktıya öğrenilebilir `scale` ve `shift` parametrelerini uygular.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Amaç, aynı token'ın tüm boyutları boyunca 0 ortalama ve 1 varyans sağlamaktır. Bunun amacı, **derin sinir ağlarının eğitimini stabilize etmek** için iç değişken kaymasını azaltmaktır; bu, eğitim sırasında parametrelerin güncellenmesi nedeniyle ağ aktivasyonlarının dağılımındaki değişimi ifade eder.
|
> Amaç, aynı token'ın tüm boyutları boyunca 0 ortalama ve 1 varyans sağlamaktır. Bunun amacı, **derin sinir ağlarının eğitimini stabilize etmek** için iç değişken kaymasını azaltmaktır; bu, eğitim sırasında parametrelerin güncellenmesi nedeniyle ağ aktivasyonlarının dağılımındaki değişimi ifade eder.
|
||||||
@ -370,9 +370,9 @@ return x # Output shape: (batch_size, seq_len, emb_dim)
|
|||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Transformer bloğu tüm ağları bir araya getirir ve eğitim istikrarını ve sonuçlarını iyileştirmek için bazı **normalizasyon** ve **dropout** uygular.\
|
> Transformer bloğu tüm ağları bir araya getirir ve eğitim istikrarını ve sonuçlarını iyileştirmek için bazı **normalizasyon** ve **dropout** uygular.\
|
||||||
> Her ağın kullanımından sonra dropout uygulandığını, normalizasyonun ise öncesinde yapıldığını not edin.
|
> Dropout'ların her ağın kullanımından sonra yapıldığını, normalizasyonun ise öncesinde uygulandığını not edin.
|
||||||
>
|
>
|
||||||
> Ayrıca, bir ağın çıkışını girişi ile **eklemeyi** içeren kısa yolları da kullanır. Bu, ilk katmanların son katmanlar kadar "çok" katkıda bulunmasını sağlayarak kaybolan gradyan sorununu önlemeye yardımcı olur.
|
> Ayrıca, bir ağın çıkışını girişi ile **eklemeyi** içeren kısa yolları da kullanır. Bu, başlangıç katmanlarının son katmanlar kadar "çok" katkıda bulunmasını sağlayarak kaybolan gradyan sorununu önlemeye yardımcı olur.
|
||||||
|
|
||||||
### **GPTModel**
|
### **GPTModel**
|
||||||
|
|
||||||
@ -434,15 +434,15 @@ return logits # Output shape: (batch_size, seq_len, vocab_size)
|
|||||||
#### **Amaç ve İşlevsellik**
|
#### **Amaç ve İşlevsellik**
|
||||||
|
|
||||||
- **Gömme Katmanları:**
|
- **Gömme Katmanları:**
|
||||||
- **Token Gömme (`tok_emb`):** Token indekslerini gömmelere dönüştürür. Hatırlatma olarak, bunlar kelime dağarcığındaki her token'ın her boyutuna verilen ağırlıklardır.
|
- **Token Gömme (`tok_emb`):** Token indekslerini gömmelere dönüştürür. Hatırlatma olarak, bunlar kelime dağarcığındaki her tokenin her boyutuna verilen ağırlıklardır.
|
||||||
- **Pozisyonel Gömme (`pos_emb`):** Gömmelere pozisyon bilgisi ekleyerek token'ların sırasını yakalar. Hatırlatma olarak, bunlar metindeki pozisyonuna göre token'a verilen ağırlıklardır.
|
- **Pozisyonel Gömme (`pos_emb`):** Gömmelere pozisyonel bilgi ekleyerek tokenlerin sırasını yakalar. Hatırlatma olarak, bunlar metindeki pozisyonuna göre tokenlere verilen ağırlıklardır.
|
||||||
- **Dropout (`drop_emb`):** Gömmelere düzenleme için uygulanır.
|
- **Dropout (`drop_emb`):** Gömmelere düzenleme için uygulanır.
|
||||||
- **Transformer Blokları (`trf_blocks`):** Gömmeleri işlemek için `n_layers` transformer bloğunun yığını.
|
- **Transformer Blokları (`trf_blocks`):** Gömmeleri işlemek için `n_layers` transformer bloğunun yığını.
|
||||||
- **Son Normalizasyon (`final_norm`):** Çıktı katmanından önce katman normalizasyonu.
|
- **Son Normalizasyon (`final_norm`):** Çıktı katmanından önce katman normalizasyonu.
|
||||||
- **Çıktı Katmanı (`out_head`):** Son gizli durumları kelime dağarcığı boyutuna projekte ederek tahmin için logitleri üretir.
|
- **Çıktı Katmanı (`out_head`):** Son gizli durumları kelime dağarcığı boyutuna projekte ederek tahmin için logitleri üretir.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu sınıfın amacı, **bir dizideki bir sonraki token'ı tahmin etmek** için diğer bahsedilen tüm ağları kullanmaktır; bu, metin üretimi gibi görevler için temeldir.
|
> Bu sınıfın amacı, **bir dizideki bir sonraki tokeni tahmin etmek** için diğer bahsedilen tüm ağları kullanmaktır; bu, metin üretimi gibi görevler için temeldir.
|
||||||
>
|
>
|
||||||
> **Belirtilen kadar transformer bloğu kullanacağını** ve her transformer bloğunun bir çok başlı dikkat ağı, bir ileri besleme ağı ve birkaç normalizasyon kullandığını not edin. Yani 12 transformer bloğu kullanılıyorsa, bunu 12 ile çarpın.
|
> **Belirtilen kadar transformer bloğu kullanacağını** ve her transformer bloğunun bir çok başlı dikkat ağı, bir ileri besleme ağı ve birkaç normalizasyon kullandığını not edin. Yani 12 transformer bloğu kullanılıyorsa, bunu 12 ile çarpın.
|
||||||
>
|
>
|
||||||
@ -579,7 +579,7 @@ total_transformer_blocks_params = 7,085,568 * 12 = 85,026,816
|
|||||||
|
|
||||||
**a. Son Katman Normalizasyonu**
|
**a. Son Katman Normalizasyonu**
|
||||||
|
|
||||||
- **Parametreler:** `2 * emb_dim` (ölçek ve kaydırma)
|
- **Parametreler:** `2 * emb_dim` (ölçek ve kaydır)
|
||||||
```python
|
```python
|
||||||
pythonCopy codefinal_layer_norm_params = 2 * 768 = 1,536
|
pythonCopy codefinal_layer_norm_params = 2 * 768 = 1,536
|
||||||
```
|
```
|
||||||
@ -608,7 +608,7 @@ total_params = 163,009,536
|
|||||||
```
|
```
|
||||||
## Metin Üretimi
|
## Metin Üretimi
|
||||||
|
|
||||||
Önceki gibi bir sonraki token'ı tahmin eden bir modele sahip olmak, çıktının son token değerlerini almak için gereklidir (çünkü bunlar tahmin edilen token'ın değerleri olacaktır), bu da **sözlükteki her bir giriş için bir değer** olacak ve ardından `softmax` fonksiyonunu kullanarak boyutları 1'e toplam olan olasılıklara normalize etmek ve ardından en büyük girişin indeksini almak, bu da sözlükteki kelimenin indeksi olacaktır.
|
Bir önceki gibi bir sonraki token'ı tahmin eden bir modele sahip olmak, çıktının son token değerlerini almak için gereklidir (çünkü bunlar tahmin edilen token'ın değerleri olacaktır), bu da **sözlükteki her giriş için bir değer** olacak ve ardından `softmax` fonksiyonunu kullanarak boyutları 1'e toplam olan olasılıklara normalize etmek ve ardından en büyük girişin indeksini almak, bu da sözlükteki kelimenin indeksi olacaktır.
|
||||||
|
|
||||||
[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb) kodu:
|
[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb) kodu:
|
||||||
```python
|
```python
|
||||||
|
|||||||
941
src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md
Normal file
941
src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md
Normal file
@ -0,0 +1,941 @@
|
|||||||
|
# 6. Ön Eğitim ve Modellerin Yüklenmesi
|
||||||
|
|
||||||
|
## Metin Üretimi
|
||||||
|
|
||||||
|
Bir modeli eğitmek için, o modelin yeni token'lar üretebilmesi gerekecek. Ardından, üretilen token'ları beklenenlerle karşılaştırarak modeli **gerekli token'ları öğrenmesi için eğiteceğiz**.
|
||||||
|
|
||||||
|
Önceki örneklerde bazı token'ları zaten tahmin ettiğimiz için, bu amaçla o fonksiyonu yeniden kullanmak mümkündür.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Bu altıncı aşamanın amacı çok basit: **Modeli sıfırdan eğitmek**. Bunun için önceki LLM mimarisi, tanımlı kayıp fonksiyonları ve optimizasyon kullanarak veri setleri üzerinde döngülerle tüm model parametrelerini eğitmek için kullanılacaktır.
|
||||||
|
|
||||||
|
## Metin Değerlendirmesi
|
||||||
|
|
||||||
|
Doğru bir eğitim gerçekleştirmek için, beklenen token için elde edilen tahminleri ölçmek gereklidir. Eğitimin amacı, doğru token'ın olasılığını maksimize etmektir; bu, diğer token'lara göre olasılığını artırmayı içerir.
|
||||||
|
|
||||||
|
Doğru token'ın olasılığını maksimize etmek için, modelin ağırlıkları, bu olasılığın maksimize edilmesi için değiştirilmelidir. Ağırlık güncellemeleri **geri yayılım** yoluyla yapılır. Bu, **maksimize edilecek bir kayıp fonksiyonu** gerektirir. Bu durumda, fonksiyon **gerçekleştirilen tahmin ile istenen arasındaki fark** olacaktır.
|
||||||
|
|
||||||
|
Ancak, ham tahminlerle çalışmak yerine, n tabanlı bir logaritma ile çalışacaktır. Yani, beklenen token'ın mevcut tahmini 7.4541e-05 ise, **7.4541e-05**'in doğal logaritması (taban *e*) yaklaşık olarak **-9.5042**'dir.\
|
||||||
|
Örneğin, 5 token'lık bir bağlam uzunluğuna sahip her giriş için modelin 5 token tahmin etmesi gerekecek; ilk 4 token, girdinin sonuncusu ve beşincisi tahmin edilen olacaktır. Bu nedenle, her giriş için bu durumda 5 tahminimiz olacak (ilk 4'ü girdi olsa da model bunu bilmez) ve dolayısıyla 5 beklenen token ve 5 maksimize edilecek olasılık olacaktır.
|
||||||
|
|
||||||
|
Bu nedenle, her tahmine doğal logaritma uygulandıktan sonra, **ortalama** hesaplanır, **eksi işareti kaldırılır** (bu _çapraz entropi kaybı_ olarak adlandırılır) ve bu, **0'a mümkün olduğunca yakın bir şekilde azaltılması gereken sayıdır** çünkü 1'in doğal logaritması 0'dır:
|
||||||
|
|
||||||
|
<figure><img src="../../images/image (10) (1).png" alt="" width="563"><figcaption><p><a href="https://camo.githubusercontent.com/3c0ab9c55cefa10b667f1014b6c42df901fa330bb2bc9cea88885e784daec8ba/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830355f636f6d707265737365642f63726f73732d656e74726f70792e776562703f313233">https://camo.githubusercontent.com/3c0ab9c55cefa10b667f1014b6c42df901fa330bb2bc9cea88885e784daec8ba/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830355f636f6d707265737365642f63726f73732d656e74726f70792e776562703f313233</a></p></figcaption></figure>
|
||||||
|
|
||||||
|
Modelin ne kadar iyi olduğunu ölçmenin bir diğer yolu da karmaşıklıktır. **Karmaşıklık**, bir olasılık modelinin bir örneği ne kadar iyi tahmin ettiğini değerlendirmek için kullanılan bir metriktir. Dil modellemesinde, bir dizideki bir sonraki token'ı tahmin ederken **modelin belirsizliğini** temsil eder.\
|
||||||
|
Örneğin, 48725 karmaşıklık değeri, bir token'ı tahmin etmesi gerektiğinde, kelime dağarcığındaki 48,725 token'dan hangisinin doğru olduğu konusunda emin olmadığını gösterir.
|
||||||
|
|
||||||
|
## Ön Eğitim Örneği
|
||||||
|
|
||||||
|
Bu, [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/ch05.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/ch05.ipynb) adresinde önerilen başlangıç kodudur, bazen hafifçe değiştirilmiştir.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
<summary>Burada kullanılan önceki kod ama önceki bölümlerde zaten açıklandı</summary>
|
||||||
|
```python
|
||||||
|
"""
|
||||||
|
This is code explained before so it won't be exaplained
|
||||||
|
"""
|
||||||
|
|
||||||
|
import tiktoken
|
||||||
|
import torch
|
||||||
|
import torch.nn as nn
|
||||||
|
from torch.utils.data import Dataset, DataLoader
|
||||||
|
|
||||||
|
|
||||||
|
class GPTDatasetV1(Dataset):
|
||||||
|
def __init__(self, txt, tokenizer, max_length, stride):
|
||||||
|
self.input_ids = []
|
||||||
|
self.target_ids = []
|
||||||
|
|
||||||
|
# Tokenize the entire text
|
||||||
|
token_ids = tokenizer.encode(txt, allowed_special={"<|endoftext|>"})
|
||||||
|
|
||||||
|
# Use a sliding window to chunk the book into overlapping sequences of max_length
|
||||||
|
for i in range(0, len(token_ids) - max_length, stride):
|
||||||
|
input_chunk = token_ids[i:i + max_length]
|
||||||
|
target_chunk = token_ids[i + 1: i + max_length + 1]
|
||||||
|
self.input_ids.append(torch.tensor(input_chunk))
|
||||||
|
self.target_ids.append(torch.tensor(target_chunk))
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.input_ids)
|
||||||
|
|
||||||
|
def __getitem__(self, idx):
|
||||||
|
return self.input_ids[idx], self.target_ids[idx]
|
||||||
|
|
||||||
|
|
||||||
|
def create_dataloader_v1(txt, batch_size=4, max_length=256,
|
||||||
|
stride=128, shuffle=True, drop_last=True, num_workers=0):
|
||||||
|
# Initialize the tokenizer
|
||||||
|
tokenizer = tiktoken.get_encoding("gpt2")
|
||||||
|
|
||||||
|
# Create dataset
|
||||||
|
dataset = GPTDatasetV1(txt, tokenizer, max_length, stride)
|
||||||
|
|
||||||
|
# Create dataloader
|
||||||
|
dataloader = DataLoader(
|
||||||
|
dataset, batch_size=batch_size, shuffle=shuffle, drop_last=drop_last, num_workers=num_workers)
|
||||||
|
|
||||||
|
return dataloader
|
||||||
|
|
||||||
|
|
||||||
|
class MultiHeadAttention(nn.Module):
|
||||||
|
def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
|
||||||
|
super().__init__()
|
||||||
|
assert d_out % num_heads == 0, "d_out must be divisible by n_heads"
|
||||||
|
|
||||||
|
self.d_out = d_out
|
||||||
|
self.num_heads = num_heads
|
||||||
|
self.head_dim = d_out // num_heads # Reduce the projection dim to match desired output dim
|
||||||
|
|
||||||
|
self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)
|
||||||
|
self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)
|
||||||
|
self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)
|
||||||
|
self.out_proj = nn.Linear(d_out, d_out) # Linear layer to combine head outputs
|
||||||
|
self.dropout = nn.Dropout(dropout)
|
||||||
|
self.register_buffer('mask', torch.triu(torch.ones(context_length, context_length), diagonal=1))
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
b, num_tokens, d_in = x.shape
|
||||||
|
|
||||||
|
keys = self.W_key(x) # Shape: (b, num_tokens, d_out)
|
||||||
|
queries = self.W_query(x)
|
||||||
|
values = self.W_value(x)
|
||||||
|
|
||||||
|
# We implicitly split the matrix by adding a `num_heads` dimension
|
||||||
|
# Unroll last dim: (b, num_tokens, d_out) -> (b, num_tokens, num_heads, head_dim)
|
||||||
|
keys = keys.view(b, num_tokens, self.num_heads, self.head_dim)
|
||||||
|
values = values.view(b, num_tokens, self.num_heads, self.head_dim)
|
||||||
|
queries = queries.view(b, num_tokens, self.num_heads, self.head_dim)
|
||||||
|
|
||||||
|
# Transpose: (b, num_tokens, num_heads, head_dim) -> (b, num_heads, num_tokens, head_dim)
|
||||||
|
keys = keys.transpose(1, 2)
|
||||||
|
queries = queries.transpose(1, 2)
|
||||||
|
values = values.transpose(1, 2)
|
||||||
|
|
||||||
|
# Compute scaled dot-product attention (aka self-attention) with a causal mask
|
||||||
|
attn_scores = queries @ keys.transpose(2, 3) # Dot product for each head
|
||||||
|
|
||||||
|
# Original mask truncated to the number of tokens and converted to boolean
|
||||||
|
mask_bool = self.mask.bool()[:num_tokens, :num_tokens]
|
||||||
|
|
||||||
|
# Use the mask to fill attention scores
|
||||||
|
attn_scores.masked_fill_(mask_bool, -torch.inf)
|
||||||
|
|
||||||
|
attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1)
|
||||||
|
attn_weights = self.dropout(attn_weights)
|
||||||
|
|
||||||
|
# Shape: (b, num_tokens, num_heads, head_dim)
|
||||||
|
context_vec = (attn_weights @ values).transpose(1, 2)
|
||||||
|
|
||||||
|
# Combine heads, where self.d_out = self.num_heads * self.head_dim
|
||||||
|
context_vec = context_vec.reshape(b, num_tokens, self.d_out)
|
||||||
|
context_vec = self.out_proj(context_vec) # optional projection
|
||||||
|
|
||||||
|
return context_vec
|
||||||
|
|
||||||
|
|
||||||
|
class LayerNorm(nn.Module):
|
||||||
|
def __init__(self, emb_dim):
|
||||||
|
super().__init__()
|
||||||
|
self.eps = 1e-5
|
||||||
|
self.scale = nn.Parameter(torch.ones(emb_dim))
|
||||||
|
self.shift = nn.Parameter(torch.zeros(emb_dim))
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
mean = x.mean(dim=-1, keepdim=True)
|
||||||
|
var = x.var(dim=-1, keepdim=True, unbiased=False)
|
||||||
|
norm_x = (x - mean) / torch.sqrt(var + self.eps)
|
||||||
|
return self.scale * norm_x + self.shift
|
||||||
|
|
||||||
|
|
||||||
|
class GELU(nn.Module):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
return 0.5 * x * (1 + torch.tanh(
|
||||||
|
torch.sqrt(torch.tensor(2.0 / torch.pi)) *
|
||||||
|
(x + 0.044715 * torch.pow(x, 3))
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
class FeedForward(nn.Module):
|
||||||
|
def __init__(self, cfg):
|
||||||
|
super().__init__()
|
||||||
|
self.layers = nn.Sequential(
|
||||||
|
nn.Linear(cfg["emb_dim"], 4 * cfg["emb_dim"]),
|
||||||
|
GELU(),
|
||||||
|
nn.Linear(4 * cfg["emb_dim"], cfg["emb_dim"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
return self.layers(x)
|
||||||
|
|
||||||
|
|
||||||
|
class TransformerBlock(nn.Module):
|
||||||
|
def __init__(self, cfg):
|
||||||
|
super().__init__()
|
||||||
|
self.att = MultiHeadAttention(
|
||||||
|
d_in=cfg["emb_dim"],
|
||||||
|
d_out=cfg["emb_dim"],
|
||||||
|
context_length=cfg["context_length"],
|
||||||
|
num_heads=cfg["n_heads"],
|
||||||
|
dropout=cfg["drop_rate"],
|
||||||
|
qkv_bias=cfg["qkv_bias"])
|
||||||
|
self.ff = FeedForward(cfg)
|
||||||
|
self.norm1 = LayerNorm(cfg["emb_dim"])
|
||||||
|
self.norm2 = LayerNorm(cfg["emb_dim"])
|
||||||
|
self.drop_shortcut = nn.Dropout(cfg["drop_rate"])
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
# Shortcut connection for attention block
|
||||||
|
shortcut = x
|
||||||
|
x = self.norm1(x)
|
||||||
|
x = self.att(x) # Shape [batch_size, num_tokens, emb_size]
|
||||||
|
x = self.drop_shortcut(x)
|
||||||
|
x = x + shortcut # Add the original input back
|
||||||
|
|
||||||
|
# Shortcut connection for feed-forward block
|
||||||
|
shortcut = x
|
||||||
|
x = self.norm2(x)
|
||||||
|
x = self.ff(x)
|
||||||
|
x = self.drop_shortcut(x)
|
||||||
|
x = x + shortcut # Add the original input back
|
||||||
|
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
class GPTModel(nn.Module):
|
||||||
|
def __init__(self, cfg):
|
||||||
|
super().__init__()
|
||||||
|
self.tok_emb = nn.Embedding(cfg["vocab_size"], cfg["emb_dim"])
|
||||||
|
self.pos_emb = nn.Embedding(cfg["context_length"], cfg["emb_dim"])
|
||||||
|
self.drop_emb = nn.Dropout(cfg["drop_rate"])
|
||||||
|
|
||||||
|
self.trf_blocks = nn.Sequential(
|
||||||
|
*[TransformerBlock(cfg) for _ in range(cfg["n_layers"])])
|
||||||
|
|
||||||
|
self.final_norm = LayerNorm(cfg["emb_dim"])
|
||||||
|
self.out_head = nn.Linear(cfg["emb_dim"], cfg["vocab_size"], bias=False)
|
||||||
|
|
||||||
|
def forward(self, in_idx):
|
||||||
|
batch_size, seq_len = in_idx.shape
|
||||||
|
tok_embeds = self.tok_emb(in_idx)
|
||||||
|
pos_embeds = self.pos_emb(torch.arange(seq_len, device=in_idx.device))
|
||||||
|
x = tok_embeds + pos_embeds # Shape [batch_size, num_tokens, emb_size]
|
||||||
|
x = self.drop_emb(x)
|
||||||
|
x = self.trf_blocks(x)
|
||||||
|
x = self.final_norm(x)
|
||||||
|
logits = self.out_head(x)
|
||||||
|
return logits
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
```python
|
||||||
|
# Download contents to train the data with
|
||||||
|
import os
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
file_path = "the-verdict.txt"
|
||||||
|
url = "https://raw.githubusercontent.com/rasbt/LLMs-from-scratch/main/ch02/01_main-chapter-code/the-verdict.txt"
|
||||||
|
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
with urllib.request.urlopen(url) as response:
|
||||||
|
text_data = response.read().decode('utf-8')
|
||||||
|
with open(file_path, "w", encoding="utf-8") as file:
|
||||||
|
file.write(text_data)
|
||||||
|
else:
|
||||||
|
with open(file_path, "r", encoding="utf-8") as file:
|
||||||
|
text_data = file.read()
|
||||||
|
|
||||||
|
total_characters = len(text_data)
|
||||||
|
tokenizer = tiktoken.get_encoding("gpt2")
|
||||||
|
total_tokens = len(tokenizer.encode(text_data))
|
||||||
|
|
||||||
|
print("Data downloaded")
|
||||||
|
print("Characters:", total_characters)
|
||||||
|
print("Tokens:", total_tokens)
|
||||||
|
|
||||||
|
# Model initialization
|
||||||
|
GPT_CONFIG_124M = {
|
||||||
|
"vocab_size": 50257, # Vocabulary size
|
||||||
|
"context_length": 256, # Shortened context length (orig: 1024)
|
||||||
|
"emb_dim": 768, # Embedding dimension
|
||||||
|
"n_heads": 12, # Number of attention heads
|
||||||
|
"n_layers": 12, # Number of layers
|
||||||
|
"drop_rate": 0.1, # Dropout rate
|
||||||
|
"qkv_bias": False # Query-key-value bias
|
||||||
|
}
|
||||||
|
|
||||||
|
torch.manual_seed(123)
|
||||||
|
model = GPTModel(GPT_CONFIG_124M)
|
||||||
|
model.eval()
|
||||||
|
print ("Model initialized")
|
||||||
|
|
||||||
|
|
||||||
|
# Functions to transform from tokens to ids and from to ids to tokens
|
||||||
|
def text_to_token_ids(text, tokenizer):
|
||||||
|
encoded = tokenizer.encode(text, allowed_special={'<|endoftext|>'})
|
||||||
|
encoded_tensor = torch.tensor(encoded).unsqueeze(0) # add batch dimension
|
||||||
|
return encoded_tensor
|
||||||
|
|
||||||
|
def token_ids_to_text(token_ids, tokenizer):
|
||||||
|
flat = token_ids.squeeze(0) # remove batch dimension
|
||||||
|
return tokenizer.decode(flat.tolist())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Define loss functions
|
||||||
|
def calc_loss_batch(input_batch, target_batch, model, device):
|
||||||
|
input_batch, target_batch = input_batch.to(device), target_batch.to(device)
|
||||||
|
logits = model(input_batch)
|
||||||
|
loss = torch.nn.functional.cross_entropy(logits.flatten(0, 1), target_batch.flatten())
|
||||||
|
return loss
|
||||||
|
|
||||||
|
|
||||||
|
def calc_loss_loader(data_loader, model, device, num_batches=None):
|
||||||
|
total_loss = 0.
|
||||||
|
if len(data_loader) == 0:
|
||||||
|
return float("nan")
|
||||||
|
elif num_batches is None:
|
||||||
|
num_batches = len(data_loader)
|
||||||
|
else:
|
||||||
|
# Reduce the number of batches to match the total number of batches in the data loader
|
||||||
|
# if num_batches exceeds the number of batches in the data loader
|
||||||
|
num_batches = min(num_batches, len(data_loader))
|
||||||
|
for i, (input_batch, target_batch) in enumerate(data_loader):
|
||||||
|
if i < num_batches:
|
||||||
|
loss = calc_loss_batch(input_batch, target_batch, model, device)
|
||||||
|
total_loss += loss.item()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return total_loss / num_batches
|
||||||
|
|
||||||
|
|
||||||
|
# Apply Train/validation ratio and create dataloaders
|
||||||
|
train_ratio = 0.90
|
||||||
|
split_idx = int(train_ratio * len(text_data))
|
||||||
|
train_data = text_data[:split_idx]
|
||||||
|
val_data = text_data[split_idx:]
|
||||||
|
|
||||||
|
torch.manual_seed(123)
|
||||||
|
|
||||||
|
train_loader = create_dataloader_v1(
|
||||||
|
train_data,
|
||||||
|
batch_size=2,
|
||||||
|
max_length=GPT_CONFIG_124M["context_length"],
|
||||||
|
stride=GPT_CONFIG_124M["context_length"],
|
||||||
|
drop_last=True,
|
||||||
|
shuffle=True,
|
||||||
|
num_workers=0
|
||||||
|
)
|
||||||
|
|
||||||
|
val_loader = create_dataloader_v1(
|
||||||
|
val_data,
|
||||||
|
batch_size=2,
|
||||||
|
max_length=GPT_CONFIG_124M["context_length"],
|
||||||
|
stride=GPT_CONFIG_124M["context_length"],
|
||||||
|
drop_last=False,
|
||||||
|
shuffle=False,
|
||||||
|
num_workers=0
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Sanity checks
|
||||||
|
if total_tokens * (train_ratio) < GPT_CONFIG_124M["context_length"]:
|
||||||
|
print("Not enough tokens for the training loader. "
|
||||||
|
"Try to lower the `GPT_CONFIG_124M['context_length']` or "
|
||||||
|
"increase the `training_ratio`")
|
||||||
|
|
||||||
|
if total_tokens * (1-train_ratio) < GPT_CONFIG_124M["context_length"]:
|
||||||
|
print("Not enough tokens for the validation loader. "
|
||||||
|
"Try to lower the `GPT_CONFIG_124M['context_length']` or "
|
||||||
|
"decrease the `training_ratio`")
|
||||||
|
|
||||||
|
print("Train loader:")
|
||||||
|
for x, y in train_loader:
|
||||||
|
print(x.shape, y.shape)
|
||||||
|
|
||||||
|
print("\nValidation loader:")
|
||||||
|
for x, y in val_loader:
|
||||||
|
print(x.shape, y.shape)
|
||||||
|
|
||||||
|
train_tokens = 0
|
||||||
|
for input_batch, target_batch in train_loader:
|
||||||
|
train_tokens += input_batch.numel()
|
||||||
|
|
||||||
|
val_tokens = 0
|
||||||
|
for input_batch, target_batch in val_loader:
|
||||||
|
val_tokens += input_batch.numel()
|
||||||
|
|
||||||
|
print("Training tokens:", train_tokens)
|
||||||
|
print("Validation tokens:", val_tokens)
|
||||||
|
print("All tokens:", train_tokens + val_tokens)
|
||||||
|
|
||||||
|
|
||||||
|
# Indicate the device to use
|
||||||
|
if torch.cuda.is_available():
|
||||||
|
device = torch.device("cuda")
|
||||||
|
elif torch.backends.mps.is_available():
|
||||||
|
device = torch.device("mps")
|
||||||
|
else:
|
||||||
|
device = torch.device("cpu")
|
||||||
|
|
||||||
|
print(f"Using {device} device.")
|
||||||
|
|
||||||
|
model.to(device) # no assignment model = model.to(device) necessary for nn.Module classes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-calculate losses without starting yet
|
||||||
|
torch.manual_seed(123) # For reproducibility due to the shuffling in the data loader
|
||||||
|
|
||||||
|
with torch.no_grad(): # Disable gradient tracking for efficiency because we are not training, yet
|
||||||
|
train_loss = calc_loss_loader(train_loader, model, device)
|
||||||
|
val_loss = calc_loss_loader(val_loader, model, device)
|
||||||
|
|
||||||
|
print("Training loss:", train_loss)
|
||||||
|
print("Validation loss:", val_loss)
|
||||||
|
|
||||||
|
|
||||||
|
# Functions to train the data
|
||||||
|
def train_model_simple(model, train_loader, val_loader, optimizer, device, num_epochs,
|
||||||
|
eval_freq, eval_iter, start_context, tokenizer):
|
||||||
|
# Initialize lists to track losses and tokens seen
|
||||||
|
train_losses, val_losses, track_tokens_seen = [], [], []
|
||||||
|
tokens_seen, global_step = 0, -1
|
||||||
|
|
||||||
|
# Main training loop
|
||||||
|
for epoch in range(num_epochs):
|
||||||
|
model.train() # Set model to training mode
|
||||||
|
|
||||||
|
for input_batch, target_batch in train_loader:
|
||||||
|
optimizer.zero_grad() # Reset loss gradients from previous batch iteration
|
||||||
|
loss = calc_loss_batch(input_batch, target_batch, model, device)
|
||||||
|
loss.backward() # Calculate loss gradients
|
||||||
|
optimizer.step() # Update model weights using loss gradients
|
||||||
|
tokens_seen += input_batch.numel()
|
||||||
|
global_step += 1
|
||||||
|
|
||||||
|
# Optional evaluation step
|
||||||
|
if global_step % eval_freq == 0:
|
||||||
|
train_loss, val_loss = evaluate_model(
|
||||||
|
model, train_loader, val_loader, device, eval_iter)
|
||||||
|
train_losses.append(train_loss)
|
||||||
|
val_losses.append(val_loss)
|
||||||
|
track_tokens_seen.append(tokens_seen)
|
||||||
|
print(f"Ep {epoch+1} (Step {global_step:06d}): "
|
||||||
|
f"Train loss {train_loss:.3f}, Val loss {val_loss:.3f}")
|
||||||
|
|
||||||
|
# Print a sample text after each epoch
|
||||||
|
generate_and_print_sample(
|
||||||
|
model, tokenizer, device, start_context
|
||||||
|
)
|
||||||
|
|
||||||
|
return train_losses, val_losses, track_tokens_seen
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate_model(model, train_loader, val_loader, device, eval_iter):
|
||||||
|
model.eval()
|
||||||
|
with torch.no_grad():
|
||||||
|
train_loss = calc_loss_loader(train_loader, model, device, num_batches=eval_iter)
|
||||||
|
val_loss = calc_loss_loader(val_loader, model, device, num_batches=eval_iter)
|
||||||
|
model.train()
|
||||||
|
return train_loss, val_loss
|
||||||
|
|
||||||
|
|
||||||
|
def generate_and_print_sample(model, tokenizer, device, start_context):
|
||||||
|
model.eval()
|
||||||
|
context_size = model.pos_emb.weight.shape[0]
|
||||||
|
encoded = text_to_token_ids(start_context, tokenizer).to(device)
|
||||||
|
with torch.no_grad():
|
||||||
|
token_ids = generate_text(
|
||||||
|
model=model, idx=encoded,
|
||||||
|
max_new_tokens=50, context_size=context_size
|
||||||
|
)
|
||||||
|
decoded_text = token_ids_to_text(token_ids, tokenizer)
|
||||||
|
print(decoded_text.replace("\n", " ")) # Compact print format
|
||||||
|
model.train()
|
||||||
|
|
||||||
|
|
||||||
|
# Start training!
|
||||||
|
import time
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
torch.manual_seed(123)
|
||||||
|
model = GPTModel(GPT_CONFIG_124M)
|
||||||
|
model.to(device)
|
||||||
|
optimizer = torch.optim.AdamW(model.parameters(), lr=0.0004, weight_decay=0.1)
|
||||||
|
|
||||||
|
num_epochs = 10
|
||||||
|
train_losses, val_losses, tokens_seen = train_model_simple(
|
||||||
|
model, train_loader, val_loader, optimizer, device,
|
||||||
|
num_epochs=num_epochs, eval_freq=5, eval_iter=5,
|
||||||
|
start_context="Every effort moves you", tokenizer=tokenizer
|
||||||
|
)
|
||||||
|
|
||||||
|
end_time = time.time()
|
||||||
|
execution_time_minutes = (end_time - start_time) / 60
|
||||||
|
print(f"Training completed in {execution_time_minutes:.2f} minutes.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Show graphics with the training process
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.ticker import MaxNLocator
|
||||||
|
import math
|
||||||
|
def plot_losses(epochs_seen, tokens_seen, train_losses, val_losses):
|
||||||
|
fig, ax1 = plt.subplots(figsize=(5, 3))
|
||||||
|
ax1.plot(epochs_seen, train_losses, label="Training loss")
|
||||||
|
ax1.plot(
|
||||||
|
epochs_seen, val_losses, linestyle="-.", label="Validation loss"
|
||||||
|
)
|
||||||
|
ax1.set_xlabel("Epochs")
|
||||||
|
ax1.set_ylabel("Loss")
|
||||||
|
ax1.legend(loc="upper right")
|
||||||
|
ax1.xaxis.set_major_locator(MaxNLocator(integer=True))
|
||||||
|
ax2 = ax1.twiny()
|
||||||
|
ax2.plot(tokens_seen, train_losses, alpha=0)
|
||||||
|
ax2.set_xlabel("Tokens seen")
|
||||||
|
fig.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
# Compute perplexity from the loss values
|
||||||
|
train_ppls = [math.exp(loss) for loss in train_losses]
|
||||||
|
val_ppls = [math.exp(loss) for loss in val_losses]
|
||||||
|
# Plot perplexity over tokens seen
|
||||||
|
plt.figure()
|
||||||
|
plt.plot(tokens_seen, train_ppls, label='Training Perplexity')
|
||||||
|
plt.plot(tokens_seen, val_ppls, label='Validation Perplexity')
|
||||||
|
plt.xlabel('Tokens Seen')
|
||||||
|
plt.ylabel('Perplexity')
|
||||||
|
plt.title('Perplexity over Training')
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
epochs_tensor = torch.linspace(0, num_epochs, len(train_losses))
|
||||||
|
plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
|
||||||
|
|
||||||
|
|
||||||
|
torch.save({
|
||||||
|
"model_state_dict": model.state_dict(),
|
||||||
|
"optimizer_state_dict": optimizer.state_dict(),
|
||||||
|
},
|
||||||
|
"/tmp/model_and_optimizer.pth"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
### Metni <--> id'lere dönüştüren fonksiyonlar
|
||||||
|
|
||||||
|
Bu, kelime dağarcığındaki metinleri id'lere ve tersine dönüştürmek için kullanılabilecek bazı basit fonksiyonlardır. Bu, metin işleme sürecinin başında ve tahminlerin sonunda gereklidir:
|
||||||
|
```python
|
||||||
|
# Functions to transform from tokens to ids and from to ids to tokens
|
||||||
|
def text_to_token_ids(text, tokenizer):
|
||||||
|
encoded = tokenizer.encode(text, allowed_special={'<|endoftext|>'})
|
||||||
|
encoded_tensor = torch.tensor(encoded).unsqueeze(0) # add batch dimension
|
||||||
|
return encoded_tensor
|
||||||
|
|
||||||
|
def token_ids_to_text(token_ids, tokenizer):
|
||||||
|
flat = token_ids.squeeze(0) # remove batch dimension
|
||||||
|
return tokenizer.decode(flat.tolist())
|
||||||
|
```
|
||||||
|
### Metin oluşturma fonksiyonları
|
||||||
|
|
||||||
|
Önceki bölümde, **en olası token**'ı elde eden bir fonksiyon tanımlandı. Ancak bu, her giriş için her zaman aynı çıktının üretileceği anlamına gelir, bu da çok deterministik hale getirir.
|
||||||
|
|
||||||
|
Aşağıdaki `generate_text` fonksiyonu, `top-k`, `temperature` ve `multinomial` kavramlarını uygulayacaktır.
|
||||||
|
|
||||||
|
- **`top-k`**, en üst k token dışında tüm token'ların olasılıklarını `-inf`'ye düşürmeye başlayacağımız anlamına gelir. Yani, k=3 ise, bir karar vermeden önce yalnızca en olası 3 token'ın olasılığı `-inf`'den farklı olacaktır.
|
||||||
|
- **`temperature`**, her olasılığın sıcaklık değeri ile bölüneceği anlamına gelir. `0.1` değeri, en yüksek olasılığı en düşük olasılıkla karşılaştırarak artırırken, örneğin `5` sıcaklığı daha düz bir dağılım yaratır. Bu, LLM'nin yanıtlarındaki varyasyonu artırmaya yardımcı olur.
|
||||||
|
- Sıcaklık uygulandıktan sonra, tüm kalan token'ların toplam olasılığının 1 olması için tekrar bir **`softmax`** fonksiyonu uygulanır.
|
||||||
|
- Son olarak, en büyük olasılığa sahip token'ı seçmek yerine, fonksiyon **`multinomial`** uygulanarak **son olasılıklara göre bir sonraki token'ı tahmin eder**. Yani, token 1'in %70 olasılığı, token 2'nin %20 ve token 3'ün %10 olasılığı varsa, %70 oranında token 1 seçilecek, %20 oranında token 2 ve %10 oranında token 3 seçilecektir.
|
||||||
|
```python
|
||||||
|
# Generate text function
|
||||||
|
def generate_text(model, idx, max_new_tokens, context_size, temperature=0.0, top_k=None, eos_id=None):
|
||||||
|
|
||||||
|
# For-loop is the same as before: Get logits, and only focus on last time step
|
||||||
|
for _ in range(max_new_tokens):
|
||||||
|
idx_cond = idx[:, -context_size:]
|
||||||
|
with torch.no_grad():
|
||||||
|
logits = model(idx_cond)
|
||||||
|
logits = logits[:, -1, :]
|
||||||
|
|
||||||
|
# New: Filter logits with top_k sampling
|
||||||
|
if top_k is not None:
|
||||||
|
# Keep only top_k values
|
||||||
|
top_logits, _ = torch.topk(logits, top_k)
|
||||||
|
min_val = top_logits[:, -1]
|
||||||
|
logits = torch.where(logits < min_val, torch.tensor(float("-inf")).to(logits.device), logits)
|
||||||
|
|
||||||
|
# New: Apply temperature scaling
|
||||||
|
if temperature > 0.0:
|
||||||
|
logits = logits / temperature
|
||||||
|
|
||||||
|
# Apply softmax to get probabilities
|
||||||
|
probs = torch.softmax(logits, dim=-1) # (batch_size, context_len)
|
||||||
|
|
||||||
|
# Sample from the distribution
|
||||||
|
idx_next = torch.multinomial(probs, num_samples=1) # (batch_size, 1)
|
||||||
|
|
||||||
|
# Otherwise same as before: get idx of the vocab entry with the highest logits value
|
||||||
|
else:
|
||||||
|
idx_next = torch.argmax(logits, dim=-1, keepdim=True) # (batch_size, 1)
|
||||||
|
|
||||||
|
if idx_next == eos_id: # Stop generating early if end-of-sequence token is encountered and eos_id is specified
|
||||||
|
break
|
||||||
|
|
||||||
|
# Same as before: append sampled index to the running sequence
|
||||||
|
idx = torch.cat((idx, idx_next), dim=1) # (batch_size, num_tokens+1)
|
||||||
|
|
||||||
|
return idx
|
||||||
|
```
|
||||||
|
> [!TIP]
|
||||||
|
> `top-k` için yaygın bir alternatif olan [**`top-p`**](https://en.wikipedia.org/wiki/Top-p_sampling), aynı zamanda çekirdek örnekleme olarak da bilinir, en yüksek olasılığa sahip k örneği almak yerine, tüm sonuçlanan **kelime dağarcığını** olasılıklara göre **düzenler** ve en yüksek olasılıktan en düşük olasılığa kadar **toplar** ve bir **eşik değere ulaşana kadar** devam eder.
|
||||||
|
>
|
||||||
|
> Ardından, **yalnızca bu kelimeler** kelime dağarcığının göreli olasılıklarına göre dikkate alınacaktır.
|
||||||
|
>
|
||||||
|
> Bu, her durumda optimal k'nın farklı olabileceği için `k` örneği seçmeye gerek kalmadan, **yalnızca bir eşik** belirlemeyi sağlar.
|
||||||
|
>
|
||||||
|
> _Bu iyileştirmenin önceki kodda yer almadığını unutmayın._
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Üretilen metni iyileştirmenin bir diğer yolu, bu örnekte kullanılan açgözlü arama yerine **Beam search** kullanmaktır.\
|
||||||
|
> Açgözlü aramanın her adımda en olası bir sonraki kelimeyi seçip tek bir diziyi oluşturmasının aksine, **beam search her adımda en yüksek puan alan 𝑘 k kısmi dizileri** ( "beams" olarak adlandırılır) takip eder. Birden fazla olasılığı aynı anda keşfederek, verimlilik ve kaliteyi dengeler, açgözlü yaklaşımın erken, alt optimal seçimler nedeniyle kaçırabileceği **daha iyi bir genel** diziyi bulma şansını artırır.
|
||||||
|
>
|
||||||
|
> _Bu iyileştirmenin önceki kodda yer almadığını unutmayın._
|
||||||
|
|
||||||
|
### Loss functions
|
||||||
|
|
||||||
|
**`calc_loss_batch`** fonksiyonu, tek bir partinin tahmininin çapraz entropisini hesaplar.\
|
||||||
|
**`calc_loss_loader`** tüm partilerin çapraz entropisini alır ve **ortalama çapraz entropiyi** hesaplar.
|
||||||
|
```python
|
||||||
|
# Define loss functions
|
||||||
|
def calc_loss_batch(input_batch, target_batch, model, device):
|
||||||
|
input_batch, target_batch = input_batch.to(device), target_batch.to(device)
|
||||||
|
logits = model(input_batch)
|
||||||
|
loss = torch.nn.functional.cross_entropy(logits.flatten(0, 1), target_batch.flatten())
|
||||||
|
return loss
|
||||||
|
|
||||||
|
def calc_loss_loader(data_loader, model, device, num_batches=None):
|
||||||
|
total_loss = 0.
|
||||||
|
if len(data_loader) == 0:
|
||||||
|
return float("nan")
|
||||||
|
elif num_batches is None:
|
||||||
|
num_batches = len(data_loader)
|
||||||
|
else:
|
||||||
|
# Reduce the number of batches to match the total number of batches in the data loader
|
||||||
|
# if num_batches exceeds the number of batches in the data loader
|
||||||
|
num_batches = min(num_batches, len(data_loader))
|
||||||
|
for i, (input_batch, target_batch) in enumerate(data_loader):
|
||||||
|
if i < num_batches:
|
||||||
|
loss = calc_loss_batch(input_batch, target_batch, model, device)
|
||||||
|
total_loss += loss.item()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return total_loss / num_batches
|
||||||
|
```
|
||||||
|
> [!TIP]
|
||||||
|
> **Gradient clipping**, büyük sinir ağlarında **eğitim istikrarını** artırmak için kullanılan bir tekniktir; bu teknik, gradyan büyüklükleri için bir **maksimum eşik** belirleyerek çalışır. Gradyanlar bu önceden tanımlanmış `max_norm` değerini aştığında, modelin parametrelerine yapılan güncellemelerin yönetilebilir bir aralıkta kalmasını sağlamak için orantılı olarak ölçeklendirilir. Bu, patlayan gradyanlar gibi sorunları önler ve daha kontrollü ve istikrarlı bir eğitim sağlar.
|
||||||
|
>
|
||||||
|
> _Bu iyileştirmenin önceki kodda yer almadığını unutmayın._
|
||||||
|
>
|
||||||
|
> Aşağıdaki örneğe bakın:
|
||||||
|
|
||||||
|
<figure><img src="../../images/image (6) (1).png" alt=""><figcaption></figcaption></figure>
|
||||||
|
|
||||||
|
### Verileri Yükleme
|
||||||
|
|
||||||
|
`create_dataloader_v1` ve `create_dataloader_v1` fonksiyonları daha önceki bir bölümde tartışılmıştır.
|
||||||
|
|
||||||
|
Buradan itibaren, metnin %90'ının eğitim için kullanılacağı, %10'unun ise doğrulama için kullanılacağı ve her iki kümenin de 2 farklı veri yükleyicisinde saklandığı belirtilmiştir.\
|
||||||
|
Bazen veri setinin bir kısmının modelin performansını daha iyi değerlendirmek için bir test seti olarak bırakıldığını unutmayın.
|
||||||
|
|
||||||
|
Her iki veri yükleyici de aynı batch boyutunu, maksimum uzunluğu, stride'ı ve işçi sayısını (bu durumda 0) kullanmaktadır.\
|
||||||
|
Ana farklar, her birinin kullandığı veridir ve doğrulayıcı, son veriyi atmamaktadır ve veriyi karıştırmamaktadır çünkü doğrulama amaçları için gerekli değildir.
|
||||||
|
|
||||||
|
Ayrıca, **stride'ın bağlam uzunluğu kadar büyük olması**, verilerin eğitiminde kullanılan bağlamlar arasında örtüşme olmayacağı anlamına gelir (aşırı uyumu azaltır ama aynı zamanda eğitim veri setini de azaltır).
|
||||||
|
|
||||||
|
Dahası, bu durumda batch boyutunun 2 olduğunu ve verilerin 2 batch'e bölündüğünü unutmayın; bunun ana amacı paralel işlemeyi sağlamak ve her batch başına tüketimi azaltmaktır.
|
||||||
|
```python
|
||||||
|
train_ratio = 0.90
|
||||||
|
split_idx = int(train_ratio * len(text_data))
|
||||||
|
train_data = text_data[:split_idx]
|
||||||
|
val_data = text_data[split_idx:]
|
||||||
|
|
||||||
|
torch.manual_seed(123)
|
||||||
|
|
||||||
|
train_loader = create_dataloader_v1(
|
||||||
|
train_data,
|
||||||
|
batch_size=2,
|
||||||
|
max_length=GPT_CONFIG_124M["context_length"],
|
||||||
|
stride=GPT_CONFIG_124M["context_length"],
|
||||||
|
drop_last=True,
|
||||||
|
shuffle=True,
|
||||||
|
num_workers=0
|
||||||
|
)
|
||||||
|
|
||||||
|
val_loader = create_dataloader_v1(
|
||||||
|
val_data,
|
||||||
|
batch_size=2,
|
||||||
|
max_length=GPT_CONFIG_124M["context_length"],
|
||||||
|
stride=GPT_CONFIG_124M["context_length"],
|
||||||
|
drop_last=False,
|
||||||
|
shuffle=False,
|
||||||
|
num_workers=0
|
||||||
|
)
|
||||||
|
```
|
||||||
|
## Sanity Checks
|
||||||
|
|
||||||
|
Amaç, eğitim için yeterli token olup olmadığını kontrol etmek, şekillerin beklenenler olup olmadığını doğrulamak ve eğitim ve doğrulama için kullanılan token sayısı hakkında bilgi almaktır:
|
||||||
|
```python
|
||||||
|
# Sanity checks
|
||||||
|
if total_tokens * (train_ratio) < GPT_CONFIG_124M["context_length"]:
|
||||||
|
print("Not enough tokens for the training loader. "
|
||||||
|
"Try to lower the `GPT_CONFIG_124M['context_length']` or "
|
||||||
|
"increase the `training_ratio`")
|
||||||
|
|
||||||
|
if total_tokens * (1-train_ratio) < GPT_CONFIG_124M["context_length"]:
|
||||||
|
print("Not enough tokens for the validation loader. "
|
||||||
|
"Try to lower the `GPT_CONFIG_124M['context_length']` or "
|
||||||
|
"decrease the `training_ratio`")
|
||||||
|
|
||||||
|
print("Train loader:")
|
||||||
|
for x, y in train_loader:
|
||||||
|
print(x.shape, y.shape)
|
||||||
|
|
||||||
|
print("\nValidation loader:")
|
||||||
|
for x, y in val_loader:
|
||||||
|
print(x.shape, y.shape)
|
||||||
|
|
||||||
|
train_tokens = 0
|
||||||
|
for input_batch, target_batch in train_loader:
|
||||||
|
train_tokens += input_batch.numel()
|
||||||
|
|
||||||
|
val_tokens = 0
|
||||||
|
for input_batch, target_batch in val_loader:
|
||||||
|
val_tokens += input_batch.numel()
|
||||||
|
|
||||||
|
print("Training tokens:", train_tokens)
|
||||||
|
print("Validation tokens:", val_tokens)
|
||||||
|
print("All tokens:", train_tokens + val_tokens)
|
||||||
|
```
|
||||||
|
### Eğitim ve ön hesaplamalar için cihaz seçimi
|
||||||
|
|
||||||
|
Aşağıdaki kod, kullanılacak cihazı seçer ve henüz hiçbir şey eğitilmeden bir başlangıç noktası olarak bir eğitim kaybı ve doğrulama kaybı hesaplar.
|
||||||
|
```python
|
||||||
|
# Indicate the device to use
|
||||||
|
|
||||||
|
if torch.cuda.is_available():
|
||||||
|
device = torch.device("cuda")
|
||||||
|
elif torch.backends.mps.is_available():
|
||||||
|
device = torch.device("mps")
|
||||||
|
else:
|
||||||
|
device = torch.device("cpu")
|
||||||
|
|
||||||
|
print(f"Using {device} device.")
|
||||||
|
|
||||||
|
model.to(device) # no assignment model = model.to(device) necessary for nn.Module classes
|
||||||
|
|
||||||
|
# Pre-calculate losses without starting yet
|
||||||
|
torch.manual_seed(123) # For reproducibility due to the shuffling in the data loader
|
||||||
|
|
||||||
|
with torch.no_grad(): # Disable gradient tracking for efficiency because we are not training, yet
|
||||||
|
train_loss = calc_loss_loader(train_loader, model, device)
|
||||||
|
val_loss = calc_loss_loader(val_loader, model, device)
|
||||||
|
|
||||||
|
print("Training loss:", train_loss)
|
||||||
|
print("Validation loss:", val_loss)
|
||||||
|
```
|
||||||
|
### Eğitim fonksiyonları
|
||||||
|
|
||||||
|
`generate_and_print_sample` fonksiyonu, bir bağlam alacak ve modelin o noktada ne kadar iyi olduğunu anlamak için bazı token'lar üretecektir. Bu, her adımda `train_model_simple` tarafından çağrılır.
|
||||||
|
|
||||||
|
`evaluate_model` fonksiyonu, eğitim fonksiyonuna belirtilen sıklıkta çağrılır ve model eğitimindeki o noktada eğitim kaybını ve doğrulama kaybını ölçmek için kullanılır.
|
||||||
|
|
||||||
|
Büyük fonksiyon `train_model_simple`, modeli gerçekten eğiten fonksiyondur. Beklentileri şunlardır:
|
||||||
|
|
||||||
|
- Eğitim verisi yükleyici (verilerin zaten ayrılmış ve eğitim için hazırlanmış haliyle)
|
||||||
|
- Doğrulayıcı yükleyici
|
||||||
|
- Eğitim sırasında kullanılacak **optimizer**: Bu, gradyanları kullanacak ve kaybı azaltmak için parametreleri güncelleyecek olan fonksiyondur. Bu durumda, göreceğiniz gibi, `AdamW` kullanılır, ancak daha birçok seçenek vardır.
|
||||||
|
- Her turda gradyanları biriktirmemek için `optimizer.zero_grad()` çağrılır.
|
||||||
|
- **`lr`** parametresi, modelin parametrelerini güncellerken optimizasyon sürecinde atılan **adımların boyutunu** belirleyen **öğrenme oranıdır**. Daha **küçük** bir öğrenme oranı, optimizer'ın ağırlıklara **daha küçük güncellemeler** yapması anlamına gelir, bu da daha **kesin** bir yakınsama sağlayabilir ancak eğitimi **yavaşlatabilir**. Daha **büyük** bir öğrenme oranı eğitimi hızlandırabilir ancak kayıp fonksiyonunun minimumunu **aşma riski** taşır (**kayıp fonksiyonunun minimize edildiği noktayı atlama**).
|
||||||
|
- **Ağırlık Çürümesi**, büyük ağırlıkları cezalandıran ekstra bir terim ekleyerek **Kayıp Hesaplama** adımını değiştirir. Bu, optimizer'ı daha küçük ağırlıklarla çözümler bulmaya teşvik eder, veriyi iyi bir şekilde uyum sağlamak ile modeli basit tutmak arasında denge kurarak makine öğrenimi modellerinde aşırı uyumu önler.
|
||||||
|
- L2 düzenlemesi ile SGD gibi geleneksel optimizatörler, ağırlık çürümesini kayıp fonksiyonunun gradyanı ile birleştirir. Ancak, **AdamW** (Adam optimizatörünün bir varyantı) ağırlık çürümesini gradyan güncellemesinden ayırarak daha etkili bir düzenleme sağlar.
|
||||||
|
- Eğitim için kullanılacak cihaz
|
||||||
|
- Epoch sayısı: Eğitim verisi üzerinde geçilecek süre sayısı
|
||||||
|
- Değerlendirme sıklığı: `evaluate_model` çağrılma sıklığı
|
||||||
|
- Değerlendirme iterasyonu: `generate_and_print_sample` çağrıldığında modelin mevcut durumunu değerlendirirken kullanılacak batch sayısı
|
||||||
|
- Başlangıç bağlamı: `generate_and_print_sample` çağrıldığında kullanılacak başlangıç cümlesi
|
||||||
|
- Tokenizer
|
||||||
|
```python
|
||||||
|
# Functions to train the data
|
||||||
|
def train_model_simple(model, train_loader, val_loader, optimizer, device, num_epochs,
|
||||||
|
eval_freq, eval_iter, start_context, tokenizer):
|
||||||
|
# Initialize lists to track losses and tokens seen
|
||||||
|
train_losses, val_losses, track_tokens_seen = [], [], []
|
||||||
|
tokens_seen, global_step = 0, -1
|
||||||
|
|
||||||
|
# Main training loop
|
||||||
|
for epoch in range(num_epochs):
|
||||||
|
model.train() # Set model to training mode
|
||||||
|
|
||||||
|
for input_batch, target_batch in train_loader:
|
||||||
|
optimizer.zero_grad() # Reset loss gradients from previous batch iteration
|
||||||
|
loss = calc_loss_batch(input_batch, target_batch, model, device)
|
||||||
|
loss.backward() # Calculate loss gradients
|
||||||
|
optimizer.step() # Update model weights using loss gradients
|
||||||
|
tokens_seen += input_batch.numel()
|
||||||
|
global_step += 1
|
||||||
|
|
||||||
|
# Optional evaluation step
|
||||||
|
if global_step % eval_freq == 0:
|
||||||
|
train_loss, val_loss = evaluate_model(
|
||||||
|
model, train_loader, val_loader, device, eval_iter)
|
||||||
|
train_losses.append(train_loss)
|
||||||
|
val_losses.append(val_loss)
|
||||||
|
track_tokens_seen.append(tokens_seen)
|
||||||
|
print(f"Ep {epoch+1} (Step {global_step:06d}): "
|
||||||
|
f"Train loss {train_loss:.3f}, Val loss {val_loss:.3f}")
|
||||||
|
|
||||||
|
# Print a sample text after each epoch
|
||||||
|
generate_and_print_sample(
|
||||||
|
model, tokenizer, device, start_context
|
||||||
|
)
|
||||||
|
|
||||||
|
return train_losses, val_losses, track_tokens_seen
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate_model(model, train_loader, val_loader, device, eval_iter):
|
||||||
|
model.eval() # Set in eval mode to avoid dropout
|
||||||
|
with torch.no_grad():
|
||||||
|
train_loss = calc_loss_loader(train_loader, model, device, num_batches=eval_iter)
|
||||||
|
val_loss = calc_loss_loader(val_loader, model, device, num_batches=eval_iter)
|
||||||
|
model.train() # Back to training model applying all the configurations
|
||||||
|
return train_loss, val_loss
|
||||||
|
|
||||||
|
|
||||||
|
def generate_and_print_sample(model, tokenizer, device, start_context):
|
||||||
|
model.eval() # Set in eval mode to avoid dropout
|
||||||
|
context_size = model.pos_emb.weight.shape[0]
|
||||||
|
encoded = text_to_token_ids(start_context, tokenizer).to(device)
|
||||||
|
with torch.no_grad():
|
||||||
|
token_ids = generate_text(
|
||||||
|
model=model, idx=encoded,
|
||||||
|
max_new_tokens=50, context_size=context_size
|
||||||
|
)
|
||||||
|
decoded_text = token_ids_to_text(token_ids, tokenizer)
|
||||||
|
print(decoded_text.replace("\n", " ")) # Compact print format
|
||||||
|
model.train() # Back to training model applying all the configurations
|
||||||
|
```
|
||||||
|
> [!TIP]
|
||||||
|
> Öğrenme oranını artırmak için **lineer ısınma** ve **kosinüs azalması** adı verilen birkaç ilgili teknik vardır.
|
||||||
|
>
|
||||||
|
> **Lineer ısınma**, başlangıç öğrenme oranını ve maksimum öğrenme oranını tanımlamak ve her epoch'tan sonra bunu sürekli güncellemektir. Bunun nedeni, eğitime daha küçük ağırlık güncellemeleriyle başlamak, modelin eğitim aşamasında büyük, dengesiz güncellemelerle karşılaşma riskini azaltmasıdır.\
|
||||||
|
> **Kosinüs azalması**, **ısınma** aşamasından sonra yarım-kosinüs eğrisi izleyerek **öğrenme oranını kademeli olarak azaltan** bir tekniktir; bu, ağırlık güncellemelerini yavaşlatarak **kaybın minimumunu aşma riskini en aza indirmeyi** ve sonraki aşamalarda eğitim istikrarını sağlamayı amaçlar.
|
||||||
|
>
|
||||||
|
> _Bu iyileştirmelerin önceki kodda yer almadığını unutmayın._
|
||||||
|
|
||||||
|
### Eğitime başla
|
||||||
|
```python
|
||||||
|
import time
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
torch.manual_seed(123)
|
||||||
|
model = GPTModel(GPT_CONFIG_124M)
|
||||||
|
model.to(device)
|
||||||
|
optimizer = torch.optim.AdamW(model.parameters(), lr=0.0004, weight_decay=0.1)
|
||||||
|
|
||||||
|
num_epochs = 10
|
||||||
|
train_losses, val_losses, tokens_seen = train_model_simple(
|
||||||
|
model, train_loader, val_loader, optimizer, device,
|
||||||
|
num_epochs=num_epochs, eval_freq=5, eval_iter=5,
|
||||||
|
start_context="Every effort moves you", tokenizer=tokenizer
|
||||||
|
)
|
||||||
|
|
||||||
|
end_time = time.time()
|
||||||
|
execution_time_minutes = (end_time - start_time) / 60
|
||||||
|
print(f"Training completed in {execution_time_minutes:.2f} minutes.")
|
||||||
|
```
|
||||||
|
### Eğitim evrimini yazdırma
|
||||||
|
|
||||||
|
Aşağıdaki fonksiyon ile modelin eğitim sürecindeki evrimi yazdırmak mümkündür.
|
||||||
|
```python
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.ticker import MaxNLocator
|
||||||
|
import math
|
||||||
|
def plot_losses(epochs_seen, tokens_seen, train_losses, val_losses):
|
||||||
|
fig, ax1 = plt.subplots(figsize=(5, 3))
|
||||||
|
ax1.plot(epochs_seen, train_losses, label="Training loss")
|
||||||
|
ax1.plot(
|
||||||
|
epochs_seen, val_losses, linestyle="-.", label="Validation loss"
|
||||||
|
)
|
||||||
|
ax1.set_xlabel("Epochs")
|
||||||
|
ax1.set_ylabel("Loss")
|
||||||
|
ax1.legend(loc="upper right")
|
||||||
|
ax1.xaxis.set_major_locator(MaxNLocator(integer=True))
|
||||||
|
ax2 = ax1.twiny()
|
||||||
|
ax2.plot(tokens_seen, train_losses, alpha=0)
|
||||||
|
ax2.set_xlabel("Tokens seen")
|
||||||
|
fig.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
# Compute perplexity from the loss values
|
||||||
|
train_ppls = [math.exp(loss) for loss in train_losses]
|
||||||
|
val_ppls = [math.exp(loss) for loss in val_losses]
|
||||||
|
# Plot perplexity over tokens seen
|
||||||
|
plt.figure()
|
||||||
|
plt.plot(tokens_seen, train_ppls, label='Training Perplexity')
|
||||||
|
plt.plot(tokens_seen, val_ppls, label='Validation Perplexity')
|
||||||
|
plt.xlabel('Tokens Seen')
|
||||||
|
plt.ylabel('Perplexity')
|
||||||
|
plt.title('Perplexity over Training')
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
epochs_tensor = torch.linspace(0, num_epochs, len(train_losses))
|
||||||
|
plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
|
||||||
|
```
|
||||||
|
### Modeli Kaydet
|
||||||
|
|
||||||
|
Eğer daha sonra eğitime devam etmek istiyorsanız, modeli + optimizasyonu kaydetmek mümkündür:
|
||||||
|
```python
|
||||||
|
# Save the model and the optimizer for later training
|
||||||
|
torch.save({
|
||||||
|
"model_state_dict": model.state_dict(),
|
||||||
|
"optimizer_state_dict": optimizer.state_dict(),
|
||||||
|
},
|
||||||
|
"/tmp/model_and_optimizer.pth"
|
||||||
|
)
|
||||||
|
# Note that this model with the optimizer occupied close to 2GB
|
||||||
|
|
||||||
|
# Restore model and optimizer for training
|
||||||
|
checkpoint = torch.load("/tmp/model_and_optimizer.pth", map_location=device)
|
||||||
|
|
||||||
|
model = GPTModel(GPT_CONFIG_124M)
|
||||||
|
model.load_state_dict(checkpoint["model_state_dict"])
|
||||||
|
optimizer = torch.optim.AdamW(model.parameters(), lr=5e-4, weight_decay=0.1)
|
||||||
|
optimizer.load_state_dict(checkpoint["optimizer_state_dict"])
|
||||||
|
model.train(); # Put in training mode
|
||||||
|
```
|
||||||
|
Ya da sadece kullanmayı planlıyorsanız modeli:
|
||||||
|
```python
|
||||||
|
# Save the model
|
||||||
|
torch.save(model.state_dict(), "model.pth")
|
||||||
|
|
||||||
|
# Load it
|
||||||
|
model = GPTModel(GPT_CONFIG_124M)
|
||||||
|
|
||||||
|
model.load_state_dict(torch.load("model.pth", map_location=device))
|
||||||
|
|
||||||
|
model.eval() # Put in eval mode
|
||||||
|
```
|
||||||
|
## GPT2 Ağırlıklarının Yüklenmesi
|
||||||
|
|
||||||
|
GPT2 ağırlıklarını yerel olarak yüklemek için 2 hızlı betik bulunmaktadır. Her ikisi için de [https://github.com/rasbt/LLMs-from-scratch](https://github.com/rasbt/LLMs-from-scratch) deposunu yerel olarak klonlayabilirsiniz, ardından:
|
||||||
|
|
||||||
|
- Betik [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/gpt_generate.py](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/gpt_generate.py) tüm ağırlıkları indirecek ve OpenAI'den beklenen formatlara dönüştürecektir. Betik ayrıca gerekli yapılandırma ile ve "Her çaba seni ileri taşır" ifadesiyle hazırlanmıştır.
|
||||||
|
- Betik [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/02_alternative_weight_loading/weight-loading-hf-transformers.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/02_alternative_weight_loading/weight-loading-hf-transformers.ipynb) yerel olarak herhangi bir GPT2 ağırlığını yüklemenizi sağlar (sadece `CHOOSE_MODEL` değişkenini değiştirin) ve bazı istemlerden metin tahmin etmenizi sağlar.
|
||||||
|
|
||||||
|
## Referanslar
|
||||||
|
|
||||||
|
- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
|
||||||
@ -13,11 +13,11 @@ LoRA, **büyük modelleri** yalnızca modelin **küçük bir kısmını** deği
|
|||||||
|
|
||||||
<figure><img src="../../images/image (9) (1).png" alt=""><figcaption></figcaption></figure>
|
<figure><img src="../../images/image (9) (1).png" alt=""><figcaption></figcaption></figure>
|
||||||
|
|
||||||
2. **Orijinal Model Ağırlıklarını Değiştirmeden Tutma**: LoRA, orijinal model ağırlıklarını aynı tutmanıza olanak tanır ve yalnızca **yeni küçük matrisleri** (A ve B) günceller. Bu, modelin orijinal bilgisinin korunması anlamına geldiği için faydalıdır ve yalnızca gerekli olanı ayarlarsınız.
|
2. **Orijinal Model Ağırlıklarını Değiştirmeden Tutar**: LoRA, orijinal model ağırlıklarını aynı tutmanıza olanak tanır ve yalnızca **yeni küçük matrisleri** (A ve B) günceller. Bu, modelin orijinal bilgisinin korunması anlamına geldiği için faydalıdır ve yalnızca gerekli olanı ayarlarsınız.
|
||||||
3. **Verimli Görev-Özel İnce Ayar**: Modeli **yeni bir göreve** uyarlamak istediğinizde, modelin geri kalanını olduğu gibi bırakırken yalnızca **küçük LoRA matrislerini** (A ve B) eğitebilirsiniz. Bu, tüm modeli yeniden eğitmekten **çok daha verimlidir**.
|
3. **Verimli Görev-Özel İnce Ayar**: Modeli **yeni bir göreve** uyarlamak istediğinizde, modelin geri kalanını olduğu gibi bırakırken yalnızca **küçük LoRA matrislerini** (A ve B) eğitebilirsiniz. Bu, tüm modeli yeniden eğitmekten **çok daha verimlidir**.
|
||||||
4. **Depolama Verimliliği**: İnce ayar yaptıktan sonra, her görev için **tamamen yeni bir modeli** kaydetmek yerine, yalnızca **LoRA matrislerini** saklamanız gerekir; bu matrisler, tüm modele kıyasla çok küçüktür. Bu, modeli çok fazla depolama alanı kullanmadan birçok göreve uyarlamayı kolaylaştırır.
|
4. **Depolama Verimliliği**: İnce ayar yaptıktan sonra, her görev için **tamamen yeni bir modeli** kaydetmek yerine, yalnızca **LoRA matrislerini** saklamanız gerekir; bu matrisler, tüm modele kıyasla çok küçüktür. Bu, modeli çok fazla depolama alanı kullanmadan birçok göreve uyarlamayı kolaylaştırır.
|
||||||
|
|
||||||
LoRA katmanlarını ince ayar sırasında Lineer olanların yerine uygulamak için burada önerilen kod [https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb):
|
LoRA katmanlarını ince ayar sırasında Lineer olanlar yerine uygulamak için burada önerilen kod [https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb):
|
||||||
```python
|
```python
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,110 @@
|
|||||||
|
# 7.1. Sınıflandırma için İnce Ayar
|
||||||
|
|
||||||
|
## Nedir
|
||||||
|
|
||||||
|
İnce ayar, büyük miktarda veriden **genel dil kalıplarını** öğrenmiş bir **önceden eğitilmiş modeli** alıp bunu **belirli bir görevi** yerine getirecek şekilde veya alan spesifik dili anlamak için **uyarlama** sürecidir. Bu, modelin daha küçük, görev spesifik bir veri seti üzerinde eğitimine devam edilerek gerçekleştirilir; böylece model, yeni verinin inceliklerine daha iyi uyum sağlamak için parametrelerini ayarlarken, zaten edinmiş olduğu geniş bilgiyi kullanabilir. İnce ayar, modelin sıfırdan yeni bir model eğitmeye gerek kalmadan, özel uygulamalarda daha doğru ve ilgili sonuçlar vermesini sağlar.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> LLM'yi "anlayan" bir metin için önceden eğitmek oldukça pahalı olduğundan, genellikle açık kaynaklı önceden eğitilmiş modelleri belirli bir görevi yerine getirmesi için ince ayar yapmak daha kolay ve ucuzdur.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Bu bölümün amacı, zaten önceden eğitilmiş bir modeli ince ayar yapmayı göstermektir; böylece LLM yeni metin üretmek yerine, verilen metnin her bir verilen kategoriye ait olma **olasılıklarını** seçecektir (örneğin, bir metnin spam olup olmadığını).
|
||||||
|
|
||||||
|
## Veri setini hazırlama
|
||||||
|
|
||||||
|
### Veri seti boyutu
|
||||||
|
|
||||||
|
Elbette, bir modeli ince ayar yapmak için LLM'nizi özelleştirmek için bazı yapılandırılmış verilere ihtiyacınız var. [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb) adresinde önerilen örnekte, GPT2 bir e-postanın spam olup olmadığını tespit etmek için [https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip](https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip) verilerini kullanarak ince ayar yapılmıştır.
|
||||||
|
|
||||||
|
Bu veri seti, "spam" olanlardan çok daha fazla "spam olmayan" örnek içermektedir; bu nedenle kitap, **"spam olmayan" örneklerden yalnızca "spam" olanlar kadarını kullanmayı** önermektedir (bu nedenle, eğitim verisinden tüm ekstra örnekleri kaldırmak). Bu durumda, her birinden 747 örnek vardı.
|
||||||
|
|
||||||
|
Ardından, **veri setinin %70'i** **eğitim** için, **%10'u** **doğrulama** için ve **%20'si** **test** için kullanılır.
|
||||||
|
|
||||||
|
- **Doğrulama seti**, modelin **hiperparametrelerini** ince ayar yapmak ve model mimarisi hakkında kararlar almak için eğitim aşamasında kullanılır; bu, modelin görülmemiş veriler üzerindeki performansına geri bildirim sağlayarak aşırı uyum sağlamayı önlemeye yardımcı olur. Nihai değerlendirmeyi önyargılamadan yinelemeli iyileştirmelere olanak tanır.
|
||||||
|
- Bu, bu veri setinde yer alan verilerin doğrudan eğitim için kullanılmadığı, ancak en iyi **hiperparametreleri** ayarlamak için kullanıldığı anlamına gelir; bu nedenle bu set, modelin performansını test seti gibi değerlendirmek için kullanılamaz.
|
||||||
|
- Aksine, **test seti**, model tamamen eğitildikten ve tüm ayarlamalar tamamlandıktan **sonra yalnızca** kullanılır; bu, modelin yeni, görülmemiş verilere genelleme yeteneğini tarafsız bir şekilde değerlendirir. Test setindeki bu nihai değerlendirme, modelin gerçek dünya uygulamalarında nasıl performans göstermesi gerektiğine dair gerçekçi bir gösterge sunar.
|
||||||
|
|
||||||
|
### Girdi uzunluğu
|
||||||
|
|
||||||
|
Eğitim örneği, aynı uzunlukta girdiler (bu durumda e-posta metni) beklediğinden, her girişi en büyük olanın boyutuna kadar genişletmek için `<|endoftext|>` kimliklerini doldurma olarak eklemeye karar verildi.
|
||||||
|
|
||||||
|
### Modeli başlatma
|
||||||
|
|
||||||
|
Açık kaynaklı önceden eğitilmiş ağırlıkları kullanarak modeli eğitmek için başlatın. Bunu daha önce yaptık ve [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb) talimatlarını takip ederek bunu kolayca yapabilirsiniz.
|
||||||
|
|
||||||
|
## Sınıflandırma başlığı
|
||||||
|
|
||||||
|
Bu özel örnekte (bir metnin spam olup olmadığını tahmin etme), GPT2'nin tam kelime dağarcığına göre ince ayar yapmaktan ziyade, yeni modelin e-postanın spam (1) olup olmadığını (0) söylemesini istiyoruz. Bu nedenle, yalnızca spam olup olmadığını gösteren olasılıkları veren son katmanı **değiştireceğiz** (yani 2 kelimelik bir kelime dağarcığı gibi).
|
||||||
|
```python
|
||||||
|
# This code modified the final layer with a Linear one with 2 outs
|
||||||
|
num_classes = 2
|
||||||
|
model.out_head = torch.nn.Linear(
|
||||||
|
|
||||||
|
in_features=BASE_CONFIG["emb_dim"],
|
||||||
|
|
||||||
|
out_features=num_classes
|
||||||
|
)
|
||||||
|
```
|
||||||
|
## Ayarları ince ayar yapmak
|
||||||
|
|
||||||
|
Hızlı bir şekilde ince ayar yapmak için tüm parametreleri ince ayar yapmak yerine sadece bazı son parametreleri ince ayar yapmak daha kolaydır. Bunun nedeni, alt katmanların genellikle temel dil yapıları ve uygulanabilir anlamları yakaladığı bilinmektedir. Bu nedenle, sadece **son katmanları ince ayar yapmak genellikle yeterlidir ve daha hızlıdır**.
|
||||||
|
```python
|
||||||
|
# This code makes all the parameters of the model unrtainable
|
||||||
|
for param in model.parameters():
|
||||||
|
param.requires_grad = False
|
||||||
|
|
||||||
|
# Allow to fine tune the last layer in the transformer block
|
||||||
|
for param in model.trf_blocks[-1].parameters():
|
||||||
|
param.requires_grad = True
|
||||||
|
|
||||||
|
# Allow to fine tune the final layer norm
|
||||||
|
for param in model.final_norm.parameters():
|
||||||
|
|
||||||
|
param.requires_grad = True
|
||||||
|
```
|
||||||
|
## Eğitim için kullanılacak girdiler
|
||||||
|
|
||||||
|
Önceki bölümlerde LLM, modelin dili daha iyi anlaması için, tahmin edilen her token'ın kaybını azaltarak eğitildi; bu, tahmin edilen token'ların neredeyse tamamının giriş cümlesinde olduğu (sadece sonunda gerçekten tahmin edilen 1 token vardı) anlamına geliyordu.
|
||||||
|
|
||||||
|
Bu durumda, modelin spam olup olmadığını tahmin edebilmesiyle ilgileniyoruz, bu nedenle yalnızca tahmin edilen son token ile ilgileniyoruz. Bu nedenle, önceki eğitim kayıp fonksiyonlarımızı yalnızca bu token'ı dikkate alacak şekilde değiştirmek gerekiyor.
|
||||||
|
|
||||||
|
Bu, [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb) adresinde şu şekilde uygulanmıştır:
|
||||||
|
```python
|
||||||
|
def calc_accuracy_loader(data_loader, model, device, num_batches=None):
|
||||||
|
model.eval()
|
||||||
|
correct_predictions, num_examples = 0, 0
|
||||||
|
|
||||||
|
if num_batches is None:
|
||||||
|
num_batches = len(data_loader)
|
||||||
|
else:
|
||||||
|
num_batches = min(num_batches, len(data_loader))
|
||||||
|
for i, (input_batch, target_batch) in enumerate(data_loader):
|
||||||
|
if i < num_batches:
|
||||||
|
input_batch, target_batch = input_batch.to(device), target_batch.to(device)
|
||||||
|
|
||||||
|
with torch.no_grad():
|
||||||
|
logits = model(input_batch)[:, -1, :] # Logits of last output token
|
||||||
|
predicted_labels = torch.argmax(logits, dim=-1)
|
||||||
|
|
||||||
|
num_examples += predicted_labels.shape[0]
|
||||||
|
correct_predictions += (predicted_labels == target_batch).sum().item()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return correct_predictions / num_examples
|
||||||
|
|
||||||
|
|
||||||
|
def calc_loss_batch(input_batch, target_batch, model, device):
|
||||||
|
input_batch, target_batch = input_batch.to(device), target_batch.to(device)
|
||||||
|
logits = model(input_batch)[:, -1, :] # Logits of last output token
|
||||||
|
loss = torch.nn.functional.cross_entropy(logits, target_batch)
|
||||||
|
return loss
|
||||||
|
```
|
||||||
|
Her bir batch için yalnızca **son tahmin edilen token'ın logits'leriyle** ilgilendiğimizi unutmayın.
|
||||||
|
|
||||||
|
## Tam GPT2 ince ayar sınıflandırma kodu
|
||||||
|
|
||||||
|
GPT2'yi bir spam sınıflandırıcısı olarak ince ayar yapmak için tüm kodu [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/load-finetuned-model.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/load-finetuned-model.ipynb) adresinde bulabilirsiniz.
|
||||||
|
|
||||||
|
## Referanslar
|
||||||
|
|
||||||
|
- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# 7.2. Talimatları Takip Etmek İçin İnce Ayar
|
# 7.2. Talimatları Takip Etmek için İnce Ayar
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu bölümün amacı, **metin üretmekten ziyade talimatları takip etmek için önceden eğitilmiş bir modeli ince ayar yapmayı** göstermektir; örneğin, bir sohbet botu olarak görevlere yanıt vermek.
|
> Bu bölümün amacı, **metin üretmekten ziyade talimatları takip etmek için önceden eğitilmiş bir modeli ince ayar yapmayı** göstermektir; örneğin, bir sohbet botu olarak görevlere yanıt vermek.
|
||||||
@ -19,7 +19,7 @@ The area of a circle is calculated using the formula \( A = \pi r^2 \). Plugging
|
|||||||
|
|
||||||
\( A = \pi (5)^2 = \pi \times 25 = 25\pi \) square units.
|
\( A = \pi (5)^2 = \pi \times 25 = 25\pi \) square units.
|
||||||
```
|
```
|
||||||
- Phi-3 İstem Stili Örneği:
|
- Phi-3 İstem Tarzı Örneği:
|
||||||
```vbnet
|
```vbnet
|
||||||
<|User|>
|
<|User|>
|
||||||
Can you explain what gravity is in simple terms?
|
Can you explain what gravity is in simple terms?
|
||||||
@ -49,30 +49,30 @@ desired_response = f"\n\n### Response:\n{data[50]['output']}"
|
|||||||
|
|
||||||
print(model_input + desired_response)
|
print(model_input + desired_response)
|
||||||
```
|
```
|
||||||
O halde, her zamanki gibi, veri kümesini eğitim, doğrulama ve test için setlere ayırmak gereklidir.
|
Sonra, her zamanki gibi, veri kümesini eğitim, doğrulama ve test için setlere ayırmak gereklidir.
|
||||||
|
|
||||||
## Batching & Data Loaders
|
## Batching & Data Loaders
|
||||||
|
|
||||||
Sonra, eğitim için tüm girdileri ve beklenen çıktıları gruplamak gereklidir. Bunun için:
|
Sonra, eğitim için tüm girdileri ve beklenen çıktıları gruplamak gereklidir. Bunun için:
|
||||||
|
|
||||||
- Metinleri tokenleştirin
|
- Metinleri tokenleştir
|
||||||
- Tüm örnekleri aynı uzunluğa (genellikle uzunluk, LLM'yi önceden eğitmek için kullanılan bağlam uzunluğu kadar büyük olacaktır) doldurun
|
- Tüm örnekleri aynı uzunluğa (genellikle uzunluk, LLM'yi önceden eğitmek için kullanılan bağlam uzunluğu kadar büyük olacaktır) doldur
|
||||||
- Özel bir collate fonksiyonunda girişi 1 kaydırarak beklenen tokenleri oluşturun
|
- Özel bir birleştirme fonksiyonunda girişi 1 kaydırarak beklenen tokenleri oluştur
|
||||||
- Eğitim kaybından hariç tutmak için bazı doldurma tokenlerini -100 ile değiştirin: İlk `endoftext` tokeninden sonra, diğer tüm `endoftext` tokenlerini -100 ile değiştirin (çünkü `cross_entropy(...,ignore_index=-100)` kullanmak, -100 olan hedefleri yok sayacağı anlamına gelir)
|
- Eğitim kaybından hariç tutmak için bazı doldurma tokenlerini -100 ile değiştir: İlk `endoftext` tokeninden sonra, diğer tüm `endoftext` tokenlerini -100 ile değiştir (çünkü `cross_entropy(...,ignore_index=-100)` kullanmak, -100 olan hedefleri yok sayacağı anlamına gelir)
|
||||||
- \[Opsiyonel\] LLM'nin yalnızca yanıtı nasıl üreteceğini öğrenmesi için soruya ait tüm tokenleri -100 ile maskeleyin. Alpaca stilinde bu, `### Response:`'a kadar her şeyi maskelemek anlamına gelecektir.
|
- \[Opsiyonel\] LLM'nin yalnızca yanıtı nasıl üreteceğini öğrenmesi için soruya ait tüm tokenleri -100 ile maskele. Alpaca stilinde bu, `### Response:`'a kadar her şeyi maskelemek anlamına gelecektir.
|
||||||
|
|
||||||
Bunu oluşturduktan sonra, her veri kümesi (eğitim, doğrulama ve test) için veri yükleyicilerini oluşturma zamanı.
|
Bunu oluşturduktan sonra, her veri kümesi (eğitim, doğrulama ve test) için veri yükleyicilerini oluşturma zamanı.
|
||||||
|
|
||||||
## Load pre-trained LLM & Fine tune & Loss Checking
|
## Load pre-trained LLM & Fine tune & Loss Checking
|
||||||
|
|
||||||
Bir önceden eğitilmiş LLM'yi yükleyip ince ayar yapmak gereklidir. Bu, diğer sayfalarda zaten tartışılmıştır. Sonra, LLM'yi ince ayar yapmak için daha önce kullanılan eğitim fonksiyonunu kullanmak mümkündür.
|
İnce ayar yapmak için önceden eğitilmiş bir LLM yüklemek gereklidir. Bu, diğer sayfalarda zaten tartışılmıştır. Sonra, LLM'yi ince ayar yapmak için daha önce kullanılan eğitim fonksiyonunu kullanmak mümkündür.
|
||||||
|
|
||||||
Eğitim sırasında, eğitim kaybının ve doğrulama kaybının epochlar boyunca nasıl değiştiğini görmek de mümkündür; böylece kaybın azalıp azalmadığını ve aşırı uyumun olup olmadığını görebilirsiniz.\
|
Eğitim sırasında, eğitim kaybı ve doğrulama kaybının epochlar boyunca nasıl değiştiğini görmek de mümkündür; böylece kaybın azalıp azalmadığını ve aşırı uyumun olup olmadığını görebilirsiniz.\
|
||||||
Aşırı uyum, eğitim kaybı azalırken doğrulama kaybının azalmadığı veya hatta arttığı durumlarda meydana gelir. Bunu önlemek için, bu davranışın başladığı epoch'ta eğitimi durdurmak en basit şeydir.
|
Aşırı uyum, eğitim kaybı azalırken doğrulama kaybının azalmadığı veya hatta arttığı durumlarda meydana gelir. Bunu önlemek için, bu davranışın başladığı epoch'ta eğitimi durdurmak en basit şeydir.
|
||||||
|
|
||||||
## Response Quality
|
## Response Quality
|
||||||
|
|
||||||
Bu, kayıp değişimlerine daha fazla güvenilebilecek bir sınıflandırma ince ayarı olmadığı için, test setindeki yanıtların kalitesini kontrol etmek de önemlidir. Bu nedenle, tüm test setlerinden üretilen yanıtları toplamak ve **kalitelerini manuel olarak kontrol etmek** önerilir; böylece yanlış yanıtlar olup olmadığını görebilirsiniz (LLM'nin yanıt cümlesinin formatını ve sözdizimini doğru bir şekilde oluşturması ancak tamamen yanlış bir yanıt vermesi mümkündür. Kayıp değişimi bu davranışı yansıtmayacaktır).\
|
Bu, kayıp değişimlerine daha fazla güvenilebilecek bir sınıflandırma ince ayarı olmadığı için, test setindeki yanıtların kalitesini kontrol etmek de önemlidir. Bu nedenle, tüm test setlerinden üretilen yanıtları toplamak ve **kalitelerini manuel olarak kontrol etmek** önerilir; böylece yanlış yanıtlar olup olmadığını görebilirsiniz (LLM'nin yanıt cümlesinin formatını ve sözdizimini doğru bir şekilde oluşturması mümkün, ancak tamamen yanlış bir yanıt vermesi de mümkündür. Kayıp değişimi bu davranışı yansıtmayacaktır).\
|
||||||
Ayrıca, üretilen yanıtları ve beklenen yanıtları **diğer LLM'lere geçirerek yanıtları değerlendirmelerini istemek** de mümkündür.
|
Ayrıca, üretilen yanıtları ve beklenen yanıtları **diğer LLM'lere geçirerek yanıtları değerlendirmelerini istemek** de mümkündür.
|
||||||
|
|
||||||
Yanıtların kalitesini doğrulamak için çalıştırılacak diğer testler:
|
Yanıtların kalitesini doğrulamak için çalıştırılacak diğer testler:
|
||||||
|
|||||||
@ -22,7 +22,7 @@ Bilmeniz gereken bazı temel kavramlar için bu gönderiyi okumaya başlamalıs
|
|||||||
## 2. Veri Örnekleme
|
## 2. Veri Örnekleme
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu ikinci aşamanın amacı çok basit: **Girdi verisini örneklemek ve genellikle veri kümesini belirli bir uzunluktaki cümlelere ayırarak ve beklenen yanıtı da üreterek eğitim aşamasına hazırlamak.**
|
> Bu ikinci aşamanın amacı çok basit: **Girdi verisini örneklemek ve genellikle veri setini belirli bir uzunluktaki cümlelere ayırarak ve beklenen yanıtı da üreterek eğitim aşamasına hazırlamak.**
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
2.-data-sampling.md
|
2.-data-sampling.md
|
||||||
@ -34,7 +34,7 @@ Bilmeniz gereken bazı temel kavramlar için bu gönderiyi okumaya başlamalıs
|
|||||||
> Bu üçüncü aşamanın amacı çok basit: **Sözlükteki önceki her token'a modelin eğitimi için istenen boyutlarda bir vektör atamak.** Sözlükteki her kelime, X boyutlu bir uzayda bir nokta olacaktır.\
|
> Bu üçüncü aşamanın amacı çok basit: **Sözlükteki önceki her token'a modelin eğitimi için istenen boyutlarda bir vektör atamak.** Sözlükteki her kelime, X boyutlu bir uzayda bir nokta olacaktır.\
|
||||||
> Başlangıçta her kelimenin uzaydaki konumu "rastgele" başlatılır ve bu konumlar eğitilebilir parametrelerdir (eğitim sırasında geliştirilecektir).
|
> Başlangıçta her kelimenin uzaydaki konumu "rastgele" başlatılır ve bu konumlar eğitilebilir parametrelerdir (eğitim sırasında geliştirilecektir).
|
||||||
>
|
>
|
||||||
> Ayrıca, token gömme sırasında **gömme katmanının başka bir katmanı oluşturulur** ki bu, **eğitim cümlesindeki kelimenin mutlak konumunu** temsil eder. Bu şekilde, cümledeki farklı konumlarda bir kelimenin farklı bir temsili (anlamı) olacaktır.
|
> Ayrıca, token gömme sırasında **gömme katmanlarının başka bir katmanı oluşturulur** ki bu, **eğitim cümlesindeki kelimenin mutlak konumunu** temsil eder. Bu şekilde, cümledeki farklı konumlarda bir kelimenin farklı bir temsili (anlamı) olacaktır.
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
3.-token-embeddings.md
|
3.-token-embeddings.md
|
||||||
@ -44,7 +44,7 @@ Bilmeniz gereken bazı temel kavramlar için bu gönderiyi okumaya başlamalıs
|
|||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu dördüncü aşamanın amacı çok basit: **Bazı dikkat mekanizmaları uygulamak**. Bunlar, **sözlükteki bir kelimenin, LLM'yi eğitmek için kullanılan mevcut cümledeki komşularıyla olan ilişkisini yakalayacak çok sayıda **tekrarlanan katman** olacaktır.\
|
> Bu dördüncü aşamanın amacı çok basit: **Bazı dikkat mekanizmaları uygulamak**. Bunlar, **sözlükteki bir kelimenin, LLM'yi eğitmek için kullanılan mevcut cümledeki komşularıyla olan ilişkisini yakalayacak çok sayıda **tekrarlanan katman** olacaktır.\
|
||||||
> Bunun için çok sayıda katman kullanılmaktadır, bu nedenle çok sayıda eğitilebilir parametre bu bilgiyi yakalayacaktır.
|
> Bunun için çok sayıda katman kullanılacak, bu nedenle çok sayıda eğitilebilir parametre bu bilgiyi yakalayacaktır.
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
4.-attention-mechanisms.md
|
4.-attention-mechanisms.md
|
||||||
@ -53,9 +53,9 @@ Bilmeniz gereken bazı temel kavramlar için bu gönderiyi okumaya başlamalıs
|
|||||||
## 5. LLM Mimarisi
|
## 5. LLM Mimarisi
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu beşinci aşamanın amacı çok basit: **Tam LLM'nin mimarisini geliştirmek.** Her şeyi bir araya getirin, tüm katmanları uygulayın ve metin oluşturmak veya metni kimliklere dönüştürmek ve tersine çevirmek için tüm fonksiyonları oluşturun.
|
> Bu beşinci aşamanın amacı çok basit: **Tam LLM'nin mimarisini geliştirmek.** Her şeyi bir araya getirin, tüm katmanları uygulayın ve metin oluşturmak veya metni kimliklere dönüştürmek ve tersine çevirmek için tüm işlevleri oluşturun.
|
||||||
>
|
>
|
||||||
> Bu mimari, hem eğitim hem de eğitimden sonra metin tahmin etmek için kullanılacaktır.
|
> Bu mimari, hem eğitim hem de eğitimden sonra metin tahmini için kullanılacaktır.
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
5.-llm-architecture.md
|
5.-llm-architecture.md
|
||||||
@ -64,7 +64,7 @@ Bilmeniz gereken bazı temel kavramlar için bu gönderiyi okumaya başlamalıs
|
|||||||
## 6. Ön Eğitim ve Modellerin Yüklenmesi
|
## 6. Ön Eğitim ve Modellerin Yüklenmesi
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu altıncı aşamanın amacı çok basit: **Modeli sıfırdan eğitmek.** Bunun için önceki LLM mimarisi, tanımlanan kayıp fonksiyonları ve optimizasyon kullanarak veri setleri üzerinde döngülerle tüm model parametrelerini eğitmek için kullanılacaktır.
|
> Bu altıncı aşamanın amacı çok basit: **Modeli sıfırdan eğitmek.** Bunun için önceki LLM mimarisi, tanımlı kayıp fonksiyonları ve optimizasyon kullanarak veri setleri üzerinde döngülerle tüm model parametrelerini eğitmek için kullanılacaktır.
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
6.-pre-training-and-loading-models.md
|
6.-pre-training-and-loading-models.md
|
||||||
@ -73,7 +73,7 @@ Bilmeniz gereken bazı temel kavramlar için bu gönderiyi okumaya başlamalıs
|
|||||||
## 7.0. İnce Ayar için LoRA İyileştirmeleri
|
## 7.0. İnce Ayar için LoRA İyileştirmeleri
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> **LoRA'nın kullanımı, zaten eğitilmiş modelleri ince ayar yapmak için gereken hesaplamayı büyük ölçüde azaltır.**
|
> **LoRA'nın kullanımı,** zaten eğitilmiş modelleri **ince ayar yapmak için gereken hesaplamayı** büyük ölçüde azaltır.
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
7.0.-lora-improvements-in-fine-tuning.md
|
7.0.-lora-improvements-in-fine-tuning.md
|
||||||
@ -82,7 +82,7 @@ Bilmeniz gereken bazı temel kavramlar için bu gönderiyi okumaya başlamalıs
|
|||||||
## 7.1. Sınıflandırma için İnce Ayar
|
## 7.1. Sınıflandırma için İnce Ayar
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu bölümün amacı, yeni metin oluşturmak yerine LLM'nin **verilen metnin her bir verilen kategoriye sınıflandırılma olasılıklarını** seçmesini sağlamak için zaten önceden eğitilmiş bir modeli nasıl ince ayar yapacağınızı göstermektir (örneğin, bir metin spam mı değil mi).
|
> Bu bölümün amacı, **yeni metin oluşturmak yerine, LLM'nin verilen metnin her bir verilen kategoriye ait olma olasılıklarını seçmesini** sağlamak için zaten önceden eğitilmiş bir modeli nasıl ince ayar yapacağınızı göstermektir (örneğin, bir metnin spam olup olmadığını belirlemek).
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
7.1.-fine-tuning-for-classification.md
|
7.1.-fine-tuning-for-classification.md
|
||||||
@ -91,7 +91,7 @@ Bilmeniz gereken bazı temel kavramlar için bu gönderiyi okumaya başlamalıs
|
|||||||
## 7.2. Talimatları Takip Etmek için İnce Ayar
|
## 7.2. Talimatları Takip Etmek için İnce Ayar
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> Bu bölümün amacı, metin oluşturmak yerine **talimatları takip etmek için zaten önceden eğitilmiş bir modeli nasıl ince ayar yapacağınızı** göstermektir; örneğin, bir sohbet botu olarak görevlere yanıt vermek.
|
> Bu bölümün amacı, **metin oluşturmak yerine talimatları takip etmek için zaten önceden eğitilmiş bir modeli nasıl ince ayar yapacağınızı** göstermektir; örneğin, bir sohbet botu olarak görevlere yanıt vermek.
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
7.2.-fine-tuning-to-follow-instructions.md
|
7.2.-fine-tuning-to-follow-instructions.md
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user