Tensör · Lineer Cebir · Hız — Sıfırdan Kur, Anla, Hızlandır
Biyolojik nörondan esinlenen 80 yıllık bir hikâye — her dönüm noktası bir hafta. Hepsi aynı dili konuşuyor: bu haftanın araçları.
1943 McCulloch–Pitts: nöronun
matematiksel modeli → H2
1949 Hebb kuralı → H3
1958 Rosenblatt
perceptronu → H4
1960 Widrow–Hoff, Delta kuralı → H3
araç: nokta çarpım · türev
1969 Minsky–Papert: tek katman XOR'u
çözemez → H4–H5
1986 Rumelhart–Hinton–Williams: geri yayılım →
H6–H7
araç: matris çarpımı · zincir kuralı
1982 Hopfield ağı → H13
1982 Kohonen SOM → H11
1987 ART (Carpenter–Grossberg) → H13
1988 RBF ağları → H10 · LVQ → H12
araç: norm · uzaklık ‖x−c‖
1989 LeCun: evrişimli ağ (CNN) →
H14
2012 AlexNet: GPU + derin CNN → H15
araç: 4B tensör · broadcasting · GPU
Bu hafta: tensör (veri) ve lineer cebir (hesap) — NumPy/PyTorch ile uygulamalı. Türev (değişim) Hafta 3'te, öğrenme kurallarıyla birlikte; otomatik türev (autograd) 7. haftada.
Görüntü, ses, metin — hepsi sayı dizisi olur.
Katman = matris çarpımı; hızlı, paralel.
"Hangi yöne?" sorusunun cevabı. Hafta 3'te, öğrenmeyle birlikte.
Bu hafta ilk ikisini elle anlayıp koda dökeceğiz; türev Hafta 3'te. Dersin geri kalanı hep bu üç dilin cümleleri.
import torch
x = torch.arange(6) # [0, 1, 2, 3, 4, 5]
X = x.reshape(2, 3) # [[0, 1, 2],
# [3, 4, 5]]
X.shape # (2, 3) · X.numel() → 6
torch.zeros(2, 3) # sıfır matrisi (torch.ones / torch.randn)
shape = boyutlar,
numel = eleman sayısı. NumPy'da birebir: np.arange, reshape.
X = torch.arange(12).reshape(3, 4)
# [[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]]
X[-1] # [8, 9, 10, 11] son satır
X[:, 1] # [1, 5, 9] 2. sütun
X[1, 2] # 6 tek eleman
Python gibi 0-tabanlı; a:b
aralığı b hariç. : "tüm o eksen" demek.
Dilime atama yapabilirsin — tek seferde bir bloğu güncelle.
Negatif indeks sondan sayar:
X[-1] son satır, X[:, -1] son sütun.
x = torch.tensor([1., 2, 4, 8])
y = torch.tensor([2., 2, 2, 2])
x + y # [ 3., 4., 6., 10.]
x * y # [ 2., 4., 8., 16.]
x ** y # [ 1., 4., 16., 64.]
torch.exp(x) # [2.7, 7.4, 54.6, 2981.]
torch.cat((x, y)) # [1,2,4,8, 2,2,2,2]
Standart işlemler (+ - * / **) aynı
şekilli tensörlerde eleman-eleman çalışır.
cat ile eksende
birleştir; == ile maske üret; X.sum() ile topla.
Kural: döngü değil, tüm tensör üstünde tek işlem düşün — birazdan bunun hız demek olduğunu ölçeceğiz.
a = torch.tensor([[1], [2], [3]]) # 3×1
b = torch.tensor([[10, 20]]) # 1×2
a + b # → [[11, 21], [12, 22], [13, 23]] (3×2, döngüsüz!)
Boyut 1 olan eksen otomatik
tekrarlanır. Bias eklerken (X @ W + b) tam bunu kullanacağız.
X, Y = torch.ones(3, 4), torch.ones(3, 4)
before = id(Y)
Y = Y + X; id(Y) == before # False → yeni bellek!
Z = torch.zeros_like(Y); Z[:] = X + Y # yerinde yaz
X += Y # yerinde (bellek dostu)
A = X.numpy() # Torch → NumPy
B = torch.from_numpy(A) # NumPy → Torch
a = torch.tensor([3.5])
a.item() # → 3.5 (1-elemanlı → sayı)
Büyük tensörlerde yerinde
işlem (+=, [:]) gereksiz kopya üretmez. .numpy() /
from_numpy kopyalamaz — bellek paylaşılır: birini değiştirirsen öteki de değişir!
| Oda | Alan_m2 | Isitma | Fiyat |
|---|---|---|---|
| 3 | 120 | Kombi | 4200 |
| NaN | 95 | Soba | 2900 |
| 2 | NaN | Kombi | 3100 |
| 4 | 150 | NaN | 5600 |
| 3 | 115 | Soba | 3800 |
import pandas as pd
data = pd.read_csv('ev.csv') # 5 ev × 4 sütun (soldaki tablo)
data.isna().sum() # sütun başına eksik: Oda 1, Alan_m2 1, Isitma 1
X = data.iloc[:, :3] # girdiler: ilk 3 sütun (Oda, Alan_m2, Isitma)
y = data.iloc[:, 3] # hedef: 4. sütun (Fiyat)
Üç sorun var: ① sayısal eksik (Oda, Alan_m2) · ② kategorik eksik (Isitma) · ③ metin değerler (Kombi, Soba). Model yalnız sayı anlar → önce temizlemeliyiz.
X = X.fillna({'Isitma': 'Bilinmiyor'}) # ② kategorik eksik → yeni kategori
X = pd.get_dummies(X, dtype=float) # ③ metin → 0/1 sütunlar (one-hot)
X = X.fillna(X.mean()) # ① sayısal eksik → sütun ortalaması
X = torch.tensor(X.values, dtype=torch.float32) # X.shape → (5, 5)
| Oda | Alan_m2 | Isitma_Bilinmiyor | Isitma_Kombi | Isitma_Soba |
|---|---|---|---|---|
| 3 | 120 | 0 | 1 | 0 |
| 3 | 95 | 0 | 0 | 1 |
| 2 | 120 | 0 | 1 | 0 |
| 4 | 150 | 1 | 0 | 0 |
| 3 | 115 | 0 | 0 | 1 |
yeşil = eksikti, dolduruldu · 4 sütun → 5 sütun, hepsi sayı
② "Bilgi yok" da bir bilgidir: eksik ısıtma Bilinmiyor adlı kendi kategorisi olur.
③ get_dummies
her kategoriye bir 0/1 sütun açar; her evde tam biri 1. dtype=float şart: pandas 2
varsayılanı True/False, torch.tensor hata verir.
① Oda: (3+2+4+3)/4 = 3 · Alan: (120+95+150+115)/4 = 120.
Ön işleme = veriyi eksiksiz sayısal tensöre çevirmek. (Not: ortalamayı tüm veriden aldık; 8. haftada neden yalnız eğitim verisinden alınması gerektiğini göreceğiz.)
🔈 okunuş: ∈ “elemanıdır”: x ∈ ℝ → x bir reel sayıdır·ℝ “reel sayılar”: ℝⁿ: n elemanlı reel vektör
x = torch.tensor(3.0) # skaler
v = torch.arange(4) # [0, 1, 2, 3]
A = torch.arange(6).reshape(3, 2) # [[0,1],[2,3],[4,5]]
A.T # [[0,2,4],[1,3,5]] (2×3)
Vektör = bir eksen, matris = iki eksen, tensör = n eksen. Devrik satır↔sütun takas eder.
Bir örnek genelde bir vektör; bir veri kümesi (batch) bir matris; bir grup görüntü bir 4B tensör.
🔈 okunuş: ⊙ “hadamard”: eleman-eleman çarpım·Aij “A i j”: i. satır, j. sütun
A = torch.tensor([[1., 2], [3, 4]])
B = torch.tensor([[2., 0], [1, 3]])
A * B # [[2, 0], [3, 12]] Hadamard
A + 2 # her elemana skaler ekle
A * 2 # her elemanı ölçekle
Dikkat: A * B (Hadamard) ≠
A @ B (matris çarpımı). İlki eleman-eleman, ikincisi satır×sütun.
🔈 okunuş: Σ “sigma (büyük)”: hepsini topla·x̄ “x bar”: ortalama
A = torch.arange(1., 7).reshape(2, 3) # [[1,2,3],[4,5,6]] (float!)
A.sum(), A.mean() # 21., 3.5 (mean int'te hata verir)
A.sum(axis=0) # [5, 7, 9] (sütunlar)
A.sum(axis=1) # [6, 15] (satırlar)
A.sum(axis=1, keepdims=True) # [[6],[15]] boyut korunur
axis=0 satırlar boyunca toplar →
sütun sonucu. keepdims ekseni 1 olarak tutar.
Normalizasyonda sık kalıp:
A / A.sum(axis=1, keepdims=True) — keepdims sayesinde broadcast çalışır.
axis=0 → sütun toplamı, axis=1 →
satır toplamı · ayrıca sum()=21, mean()=3.5.
🔈 okunuş: xᵀ “x transpoz”: sütun vektörü satıra çevir
x = torch.tensor([1., 2., 3.])
w = torch.tensor([0.5, -1., 2.])
torch.dot(w, x) # 0.5 - 2 + 6 = 4.5
torch.sum(w * x) # aynı sonuç
Ağırlıklı toplam = nokta çarpım. Nöronun
w·x + b ifadesinin ilk yarısı.
Tek nöron bir nokta çarpım; bir katman bunun yüzlercesi → matris çarpımı.
A = torch.tensor([[1., 2], [3, 4]])
x = torch.tensor([1., 1])
torch.mv(A, x) # matris×vektör → [3., 7.]
torch.mm(A, A) # matris×matris → [[7,10],[15,22]]
A @ A # aynısı (NumPy'da: A @ B)
İç boyutlar uyuşmalı: (m×k)·(k×n) → m×n. Bir ağın tüm işi bu çarpımlara iner.
İyi haber: matris çarpımı utanç verecek kadar paralel — önce elle hesaplayalım, sonra hızını ölçelim.
Her hücre = soldaki satır · sağdaki sütun (nokta çarpım). Aynı mantık matris-vektörde de geçerli.
256×256 matris çarpımı = 2·256³ ≈ 33,6 milyon işlem · sonuçlar birebir aynı
A @ B'den kaç kat
yavaş?③ Canlı ölç — şimdi, bu tarayıcıda. Önce tahmin: n iki katına çıkınca süre kaç kat artar?
[canlı] JavaScript · tek iş parçacığı · BLAS yok · 5 turun en iyisi
② Önceden ölçüldü (log ölçek, 256×256, laptop)
[ölçüldü] Surface Laptop 7 · Snapdragon X, 12 çekirdek · Python 3.12.4 · NumPy 1.26.3 · PyTorch 2.3.1 CPU · medyan · 29.09.2026
Fark döngü → vektörleştirme'den ve float64 → float32'den geliyor. Sürpriz: CPU'da NumPy = PyTorch (ikisi de BLAS çağırır). O zaman PyTorch neden var? → sonraki slayt
Her rakam 28×28 = 784 piksel →
reshape(-1) ile bir satır. 60.000 görüntü: X: (60000, 784) ·
W: (784, 512) → Y = X @ W ≈ 48 milyar işlem
Y = X @ W # CPU
Xg = X.to('cuda') # tek satır fark
Wg = W.to('cuda')
Yg = Xg @ Wg # aynı kod, GPU'da
Veri GPU'ya bir kez taşınır (11 ms). Küçük işte (256²) taşıma, GPU'yu CPU'dan yavaş yapar.
② Önceden ölçüldü (log ölçek, sunucu)
[ölçüldü] i9-14900KF (24 çekirdek) + RTX 6000 Ada · NumPy 2.3.3 · PyTorch 2.9 · CUDA 13 · medyan · 29.09.2026 · Python: 100 görüntüde ölçüldü, ×600
PyTorch'un gücü: aynı kod GPU'da → NumPy'dan ~25×, float16 ile ~140×. NumPy GPU'ya çıkamaz.
u = torch.tensor([3., -4.])
torch.linalg.norm(u) # 5. L2 (Öklid uzunluğu)
u.abs().sum() # 7. L1 (mutlak değer toplamı)
torch.linalg.norm(torch.ones(4, 9)) # 6. Frobenius
Örn: \( \|[3,-4]\|_2=\sqrt{9+16}=5 \) (3-4-5 üçgeni), \( \|[3,-4]\|_1=3+4=7 \). Frobenius \( \|\mathbf{A}\|_F \) = matrisi düzleştirip alınan L2.
İki nokta arası uzaklık = farkın normu: \( \|\mathbf{x}-\mathbf{c}\|_2 \) — RBF, SOM, LVQ haftalarının temeli.
Oluştur, dilimle, işle, broadcast, ön-işle → sayısal tensör.
Nokta/matris çarpımı, indirgeme, normlar. Katman = \( \mathbf{XW}+\mathbf{b} \).
‖x‖₂, ‖x‖₁, Frobenius; iki nokta arası uzaklık ‖x − c‖.
Döngü yerine vektörleştir, float32 kullan; PyTorch ile aynı kod GPU'da ~25×.
Sonraki hafta: bu araçlarla ilk yapay nöronu kuracak ve aktivasyon fonksiyonlarını öğreneceğiz; türev Hafta 3'te, autograd + geri yayılım 7. haftada.
A.sum(axis=0) ne verir?A * B hangi işlem?u = [3, −4] için ‖u‖₂ kaçtır?1 · Tensör. arange(12).reshape(3,4);
dilimle, sum(axis=0), mean, broadcasting dene.
2 · Ön işleme. ev.csv'yi indir, oku; ①②③'ü uygula, tensöre çevir. Kontrol:
X.shape == (5, 5), 2. satır [3, 95, 0, 0, 1].
3 · Lineer cebir. A @ B,
mv, dot; torch.norm ile L2/L1 hesapla.
4 ·
Uzaklık. \( \mathbf{x}=[1,2] \) ile \( \mathbf{c}=[4,6] \) arasındaki L2 uzaklığı önce elle,
sonra torch.linalg.norm(x - c) ile bul; L1 uzaklıkla karşılaştır.
İpucu: her adımı önce elle hesapla, sonra kodda doğrula.
Dili öğrendik. Şimdi ilk nöronu kuruyor, aktivasyon fonksiyonlarıyla XOR duvarını aşmanın yolunu görüyoruz.
← Ders Ana Sayfasına Dön