---
title: "Sistem Programlama ve Yapay Zeka: Rust ile Özel GPT-2 Decoder Geliştirmek"
description: "Rust ve tch-rs ile GPT tarzı decoder blokları ve eğitim döngüleri kurmaya yönelik sistem odaklı bir rehber."
date: "2026-07-02"
tags: [Rust, GPT-2, Derin Öğrenme, Sistem Programlama, Yapay Zeka Mühendisliği]
keywords: [Rust yapay zeka, GPT-2 decoder, tch-rs, libtorch, transformer mimarisi, yapay zeka için sistem programlama]
image: "/My.jpeg"
imageAlt: "Murat Tut portfolyo görseli"
aiSummary: "Bu yazı, Rust'ın yapay zeka sistemlerinde nasıl kullanılabileceğini açıklar; tch-rs, GPT tarzı decoder blokları, attention, eğitim döngüleri ve Python esnekliği ile derlenmiş sistem kontrolü arasındaki farklara odaklanır."
---

*Python çalışma zamanı yükünden uzaklaşarak tip güvenli, derlenmiş hızda makine öğrenmesi modelleri ve eğitim döngüleri geliştirmeye dair teknik bir rehber.*

Python uzun yıllardır yapay zeka geliştirme için varsayılan dil oldu. PyTorch, TensorFlow, JAX, Jupyter ve Google Colab gibi araçlar hızlı araştırma ve prototipleme için çok güçlüdür.

Ancak yapay zeka iş yükleri araştırmadan üretim ortamlarına geçtikçe Python'ın bazı sınırları görünür hale gelir:

- **Global Interpreter Lock (GIL)**: Gerçek çok iş parçacıklı paralel yürütmeyi sınırlar.
- **Yüksek bellek yükü**: Dinamik tip sistemi ve garbage collection ek bellek tüketir.
- **Derleme zamanı kontrol eksikliği**: Tensor şekli veya tip hataları çoğu zaman ancak çalışma sırasında ortaya çıkar.

Sistem seviyesinde kontrol isteyen geliştiriciler için **Rust** güçlü bir alternatiftir. **`tch-rs`**, PyTorch'un C++ motoru olan `libtorch` üzerine Rust bağlayıcıları sağlar. Böylece PyTorch performansını Rust'ın bellek güvenliği ve tip sistemiyle birlikte kullanmak mümkün olur.

---

## Rust AI Stack: Neden tch-rs?

Python'da `import torch` yazdığınızda aslında yüksek performanslı C++ motoru olan `libtorch` için bir sarmalayıcı kullanırsınız.

`tch-rs`, bu C++ kütüphanesine doğrudan Rust bağlayıcıları sağlar. Bu, sıfırdan CUDA kernel yazmadan veya derin öğrenme matematiğini baştan kurmadan PyTorch'un tensor performansını, GPU hızlandırmasını ve backpropagation altyapısını kullanmak anlamına gelir.

```
       ┌──────────────────────────────────────────────────┐
       │             Rust Application Code                │
       └───────────┬──────────────────────────────────────┘
                   │ FFI (Foreign Function Interface)
                   ▼
          tch-rs Rust Bindings
                   │
                   ▼
         PyTorch C++ (libtorch)
                   │
           ┌───────┴───────┐
           ▼               ▼
       CUDA Kernels   MPS Kernels
```

---

## 1. Causal Self-Attention Matematiği

GPT-2 gibi üretici transformer modellerinde attention katmanı query ($Q$), key ($K$) ve value ($V$) matrislerini kullanarak token bağımlılıklarını hesaplar. Causal decoder yapısında modelin gelecekteki tokenlara bakması engellenmelidir. Bunun için gelecekteki pozisyonları $-\infty$ yapan alt üçgensel maske matrisi ($M$) kullanılır:

$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}} + M\right)V$$

Burada:

- $Q$, $K$, $V$ giriş embeddinglerinden üretilen Query, Key ve Value matrisleridir:
  $$Q = XW_Q, \quad K = XW_K, \quad V = XW_V$$
- $d_k$, key boyutudur ve softmax sırasında gradyanların kaybolmasını azaltmak için ölçekleme sağlar.
- $M$ causal mask matrisidir:
  $$M_{i,j} = \begin{cases} 0 & \text{if } i \geq j \\ -\infty & \text{if } i < j \end{cases}$$

Rust tarafında bu maske `tch-rs` ile oluşturulabilir:

```rust
// src/model.rs
impl Module for CausalSelfAttention {
    fn forward(&self, x: &Tensor) -> Tensor {
        let kind = x.kind();
        let (_b, t, _c) = x.size3().unwrap();

        let k = self.key_linear.forward(&x);
        let q = self.query_linear.forward(&x);
        let v = self.value_linear.forward(&x);

        let mask = Tensor::ones([t, t], (kind, self.device))
            .tril(0)
            .reshape([1, t, t]);

        Tensor::scaled_dot_product_attention(&q, &k, &v, Option::Some(mask), 0.1, false, Option::None)
    }
}
```

---

## 2. Rust'ta Bellek Sürekliliği

Python/PyTorch'ta `view` gibi işlemler, tensor belleği uygun değilse çoğu zaman çalışma sırasında hata üretir. Rust `tch-rs` tarafında ise transpoze edilmiş bir tensörü `.contiguous()` çağırmadan yeniden şekillendirmek alttaki `libtorch` motorunda paniğe yol açabilir.

Çünkü transpoze işlemleri veriyi fiziksel olarak yeniden dizmek yerine layout metadata'sını değiştirir. Feed-forward ve attention çıktıları birleştirilirken bellek sürekliliği açıkça sağlanmalıdır:

```rust
// Rust içinde bellek düzenleme bloğu
let transposed = attention_output.transpose(1, 2);
let contiguous_tensor = transposed.contiguous();
let reshaped = contiguous_tensor.view([batch_size, seq_len, embed_dim]);
```

---

## 3. Derlenmiş Eğitim Döngüsü Yazmak

Python'da model parametreleri çoğu zaman arka planda daha örtük şekilde güncellenir. Rust'ta optimizer ve backpropagation adımları açık biçimde kurulur:

```rust
// src/main.rs
fn main() -> anyhow::Result<()> {
    let block_size = 128;
    let vocab_size = 968;
    let device = find_device();

    let vs = nn::VarStore::new(device);
    let mut opt = nn::AdamW::default().build(&vs, 1e-4)?;

    let model = Gpt::new(vs.root(), vocab_size, 128, block_size, 4, 4);

    for epoch in 0..100 {
        let (xs, ys, _) = dataset::get_batch_train();

        let logits = model.forward(&xs.to_kind(Kind::Int64).to_device(device));

        let (b, t, c) = logits.size3().unwrap();
        let logits = logits.view([b * t, c]);
        let targets = ys.to_kind(Kind::Int64).to_device(device).view([b * t]);

        let loss = logits.cross_entropy_for_logits(&targets);

        opt.backward_step(&loss);

        if epoch % 10 == 0 {
            println!("Epoch: {}, Loss: {:?}", epoch, loss);
        }
    }
    Ok(())
}
```

---

## PyTorch ve tch-rs Arasındaki Temel Farklar

1. **Atomik gradyan güncellemeleri**: Python'da `optimizer.zero_grad()`, `loss.backward()` ve `optimizer.step()` ayrı ayrı çağrılır. Rust tarafında `opt.backward_step(&loss)` boilerplate kodu azaltır.
2. **Açık reshape işlemleri**: Python dinamik slice sözdizimi sunar. Rust tarafında `.view()` ve `.reshape()` gibi dönüşümler daha açık yazılır.
3. **Variable Store (`VarStore`)**: Rust değişkenleri isimlendirilmiş bir ağaç altında toplar. Bu, thread paylaşımı ve checkpoint serileştirme için daha güvenli bir yapı sağlar.

---

## Mühendislik Çıkarımları

1. **Sessiz hataları erken yakalayın**: Derin öğrenme modellerinde tensor boyutu hataları uzun eğitimlerden sonra ortaya çıkabilir. Rust daha açık tip ve yapı disiplini sağlar.
2. **Bellek sürekliliğine dikkat edin**: Transpose işlemleri belleği fiziksel olarak yeniden dizmez. `view` öncesinde contiguity kontrol edilmelidir.
3. **Düşük çalışma zamanı yükü**: `cargo build --release` ile native binary üretmek, edge sunucularda daha küçük bellek iziyle inference veya eğitim çalıştırmayı kolaylaştırır.
