1. Giriş ve Temel Kavramlar
PyTorch, makine öğrenmesi ve derin öğrenme uygulamalarında kullanılan açık kaynaklı bir kütüphanedir. Temel veri yapısı olan Tensor, çok boyutlu dizileri (multi-dimensional arrays) temsil eder ve NumPy dizilerine benzer şekilde çalışır, ancak GPU hızlandırma ve otomatik türev hesaplama (autograd) yetenekleri sunar.
Temel Özellikler:
- GPU hızlandırma desteği (CUDA)
- Otomatik diferansiyasyon (Autograd)
- Dinamik hesap grafiği
- Pythonik API (NumPy benzeri sözdizimi)
2. Kurulum ve İçe Aktarma
1
2
3
4
5
6
7
8
9
| # Gerekli kütüphanelerin kurulumu
# pip install torch torchvision torchaudio
import torch
import numpy as np
# Versiyon kontrolü
print(torch.__version__)
print(torch.cuda.is_available()) # GPU desteği kontrolü
|
3. Tensor Oluşturma ve Veri Tipleri
3.1. Temel Tensor Tipleri
PyTorch’ta tensorler farklı sayısal veri tiplerinde saklanabilir. Seçilen veri tipi hem bellek kullanımını hem de hesaplama hassasiyetini etkiler.
| Veri Tipi | Açıklama | Bellek (bit) | Kullanım Alanı |
|---|
torch.float32 / torch.float | Tek hassasiyetli kayan nokta | 32 | Standart varsayılan, genel amaçlı |
torch.float64 / torch.double | Çift hassasiyetli kayan nokta | 64 | Yüksek hassasiyetli bilimsel hesaplama |
torch.float16 / torch.half | Yarım hassasiyetli | 16 | Bellek tasarrufu ve hız (GPU) |
torch.int32 / torch.int | 32-bit işaretli tam sayı | 32 | Genel indeksleme |
torch.int64 / torch.long | 64-bit işaretli tam sayı | 64 | Etiketler ve indeksleme (varsayılan tam sayı) |
torch.bool | Boolean (True/False) | 8 | Maskeleme işlemleri |
torch.complex64 | Karmaşık sayı | 64 | Sinyal işleme |
3.2. Farklı Yöntemlerle Tensor Oluşturma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # 3.2.1. Veri listesinden oluşturma
data = [[1, 2], [3, 4]]
x_data = torch.tensor(data, dtype=torch.float32)
# 3.2.2. NumPy dizisinden dönüştürme
np_array = np.array([[1, 2], [3, 4]])
x_np = torch.from_numpy(np_array) # Belleği paylaşır (kopya değil!)
# 3.2.3. Sabit değerlerle oluşturma
shape = (2, 3)
x_zeros = torch.zeros(shape) # Sıfırlarla dolu (float32 varsayılan)
x_ones = torch.ones(shape, dtype=torch.int32) # Birlerle dolu
x_full = torch.full(shape, fill_value=7) # Belirli değerle doldurma
x_eye = torch.eye(3) # Birim matris (3x3)
# 3.2.4. Rastgele değerlerle oluşturma
torch.manual_seed(42) # Tekrarlanabilirlik için
x_rand = torch.rand(2, 3) # Düzgün dağılım [0, 1)
x_randn = torch.randn(2, 3) # Standart normal dağılım (ortalama=0, std=1)
x_randint = torch.randint(0, 10, (2, 3)) # Tam sayı rastgele [low, high)
# 3.2.5. Ardışık değerler
x_arange = torch.arange(0, 10, step=2) # [0, 2, 4, 6, 8]
x_linspace = torch.linspace(0, 1, steps=5) # [0.0, 0.25, 0.5, 0.75, 1.0]
|
3.3. Tensor Özelliklerinin İncelenmesi
1
2
3
4
5
6
7
8
| tensor = torch.randn(3, 4, 5)
print(f"Şekil (Shape): {tensor.shape}") # torch.Size([3, 4, 5])
print(f"Boyut sayısı (ndim): {tensor.ndim}") # 3
print(f"Veri tipi (dtype): {tensor.dtype}") # torch.float32
print(f"Cihaz (device): {tensor.device}") # cpu veya cuda:0
print(f"Eleman sayısı (numel): {tensor.numel()}") # 60
print(f"Hafıza düzeni (layout): {tensor.layout}") # torch.strided (dense)
|
4. Cihaz Yönetimi (CPU/GPU)
PyTorch’un en önemli avantajlarından biri, tensorleri GPU’ya (CUDA) taşıyarak paralel hesaplama yapabilmesidir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| # Cihaz belirleme stratejisi
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Kullanılan cihaz: {device}")
# 4.1. Oluştururken cihaz belirtme
x = torch.rand(2, 3, device=device)
# 4.2. Mevcut tensorü taşıma
x_cpu = torch.rand(2, 3)
x_gpu = x_cpu.to(device) # veya x_cpu.cuda()
x_cpu_again = x_gpu.cpu() # GPU'dan CPU'ya geri taşıma
# 4.3. Cihaz uyumluluğu kontrolü
# Aynı cihazda olmayan tensorler üzerinde işlem yapılamaz!
try:
y_cpu = torch.rand(2, 3)
result = x_gpu + y_cpu # HATA!
except RuntimeError as e:
print(f"Cihaz uyumsuzluğu hatası: {e}")
# Doğru kullanım:
y_gpu = y_cpu.to(x_gpu.device)
result = x_gpu + y_gpu # Başarılı
# 4.4. Çoklu GPU desteği
if torch.cuda.device_count() > 1:
print(f"Mevcut GPU sayısı: {torch.cuda.device_count()}")
x = torch.rand(2, 3, device="cuda:0") # İlk GPU
y = torch.rand(2, 3, device="cuda:1") # İkinci GPU (varsa)
|
Dikkat: tensor.to(device) işlemi veri kopyası oluşturur (eğer cihaz farklıysa). Orijinal tensor değişmez.
5. Şekillendirme ve Boyut İşlemleri
5.1. Temel Şekillendirme Yöntemleri
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| x = torch.arange(12) # [0..11]
# 5.1.1. reshape - En yaygın kullanılan
# Bellek düzenini değiştirebilir (kopya oluşturabilir)
x_reshaped = x.reshape(3, 4) # 3 satır, 4 sütun
# 5.1.2. view - Hafızada bitişik (contiguous) veri gerektirir
# Daha hızlıdır, ancak esnek değildir
x_viewed = x.view(3, 4)
# 5.1.3. Otomatik boyut çıkarımı (-1)
x_auto = x.reshape(3, -1) # -1 otomatik olarak 4 olarak hesaplanır
x_auto2 = x.reshape(2, 2, -1) # Son boyut otomatik: 3
# 5.1.4. Boyut ekleme/kaldırma
x = torch.rand(3, 4)
x_unsqueeze = x.unsqueeze(0) # Boyut ekle: (1, 3, 4)
x_unsqueeze2 = x.unsqueeze(-1) # Sona boyut ekle: (3, 4, 1)
x_squeezed = x_unsqueeze.squeeze() # Boyutu 1 olanları kaldır: (3, 4)
# 5.1.5. Boyut permütasyonu (transpose)
x = torch.rand(2, 3, 4)
x_permuted = x.permute(2, 0, 1) # Boyutları yeniden sırala: (4, 2, 3)
x_transposed = x.transpose(0, 2) # Sadece iki boyutu değiştir: (4, 3, 2)
# 5.1.6. Boyutları genişletme (expand - bellek kopyası yok)
x = torch.rand(1, 3)
x_expanded = x.expand(4, 3) # 4x3 şeklinde görünür, ancak bellekte paylaşımlı
|
5.2. Bellek Düzeni (Contiguous vs Non-contiguous)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| x = torch.arange(12).reshape(3, 4)
print(x.is_contiguous()) # True
# Transpose işlemi bellek düzenini bozar
y = x.transpose(0, 1) # 4x3
print(y.is_contiguous()) # False
# View contiguous olmayan tensorde çalışmaz!
try:
z = y.view(12) # HATA!
except RuntimeError:
print("View non-contiguous tensorde başarısız")
# Çözüm: contiguous() kullanmak
z = y.contiguous().view(12) # Başarılı
# Alternatif: reshape (contiguous kontrolü otomatik yapar)
z = y.reshape(12) # Başarılı (gerekirse kopya oluşturur)
|
Önemli: view() ile reshape() arasındaki temel fark: view() her zaman aynı bellek bloğunu kullanmaya çalışırken, reshape() gerekirse yeni bellek tahsis edebilir.
6. İndeksleme ve Dilimleme (Advanced Indexing)
6.1. Temel İndeksleme
1
2
3
4
5
6
7
8
9
10
11
| tensor = torch.arange(24).reshape(2, 3, 4)
# Şekil: (2 batch, 3 satır, 4 sütun)
# Tek eleman erişimi
print(tensor[0, 1, 2]) # Batch 0, Satır 1, Sütun 2 -> tensor(6)
# Dilimleme (Slicing)
print(tensor[0]) # İlk batch: (3, 4)
print(tensor[:, 0]) # Tüm batchlerin ilk satırı: (2, 4)
print(tensor[:, :, 0]) # Tüm batch ve satırların ilk sütunu: (2, 3)
print(tensor[-1]) # Son batch
|
6.2. Gelişmiş İndeksleme (Fancy Indexing)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| x = torch.arange(10).reshape(2, 5)
# 6.2.1. Boolean Maskesi (Boolean Masking)
mask = x > 5
print(mask) # [[False, False, False, False, False],
# [ True, True, True, True, True]]
print(x[mask]) # tensor([6, 7, 8, 9])
# 6.2.2. Tamsayı Listesi/Tensor ile İndeksleme
indices = torch.tensor([0, 2, 4])
print(x[:, indices]) # Tüm satırların 0, 2, 4. sütunları
# 6.2.3. Birden fazla boyutta indeksleme
x = torch.rand(3, 4)
rows = torch.tensor([0, 2])
cols = torch.tensor([1, 3])
print(x[rows, cols]) # x[0,1] ve x[2,3] değerlerini döndürür
# 6.2.4. torch.where - Koşullu seçim
x = torch.randn(3, 3)
result = torch.where(x > 0, x, torch.zeros_like(x)) # Negatifleri sıfırla
# 6.2.5. torch.gather ve torch.scatter
# Belirli indekslere göre toplama/gather işlemi
src = torch.arange(12).reshape(3, 4)
index = torch.tensor([[0, 1, 2, 3],
[3, 2, 1, 0]])
result = torch.gather(src, 0, index) # Dim 0 boyunca toplama
|
7. Broadcasting Mekanizması (Detaylı Analiz)
Broadcasting, farklı şekillerdeki tensorlerin aritmetik işlemlerde otomatik olarak uyumlu hale getirilmesini sağlar.
7.1. Broadcasting Kuralları
- Her boyut çifti (son boyuttan başlayarak) eşit olmalı veya biri 1 olmalı
- İki boyut da mevcut değilse ve biri 1 ise, 1 olarak kabul edilir
- Herhangi bir boyut eşleşmiyorsa ve ikisi de 1 değilse, hata oluşur
7.2. Broadcasting Örnekleri
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # Örnek 1: Vektör + Skaler
x = torch.arange(3).reshape(3, 1) # (3, 1)
y = torch.tensor([10]) # (1,) -> (3, 1) olarak yayılır
print(x + y) # [[10], [11], [12]]
# Örnek 2: Matris + Satır vektörü
x = torch.arange(6).reshape(2, 3) # (2, 3)
y = torch.arange(3).reshape(1, 3) # (1, 3) -> (2, 3) olarak yayılır
# Y her satıra kopyalanır
print(x + y)
# Örnek 3: 3D Tensor + 2D Matris
x = torch.randn(2, 3, 4) # (2, 3, 4)
y = torch.randn(3, 4) # (3, 4) -> (1, 3, 4) -> (2, 3, 4)
print(x + y)
# Hatalı Broadcasting (uyumsuz şekiller)
x = torch.randn(2, 3)
y = torch.randn(2, 4)
# x + y # RuntimeError: boyutlar uyumsuz
|
7.3. Broadcasting Görselleştirmesi
1
2
3
4
5
6
7
8
9
| Tensor A: (3, 1) Tensor B: (1, 3) Sonuç: (3, 3)
[[0], [[0, 1, 2]], [[0, 1, 2],
[1], + = [1, 2, 3],
[2]] [2, 3, 4]]
A yayılır: B yayılır:
[[0, 0, 0], [[0, 1, 2],
[1, 1, 1], [0, 1, 2],
[2, 2, 2]] [0, 1, 2]]
|
Performans Notu: Broadcasting bellekte gerçekten kopya oluşturmaz, sadece hesaplama sırasında “görünüm” oluşturur (virtual tiling), bu sayede bellek verimli olur.
8. Aritmetik ve Lineer Cebir İşlemleri
8.1. Temel Aritmetik
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| x = torch.arange(4).reshape(2, 2).float()
y = torch.ones(2, 2)
# Eleman bazında işlemler (Element-wise)
z_add = x + y # veya torch.add(x, y)
z_sub = x - y # veya torch.sub(x, y)
z_mul = x * y # Hadamard çarpımı (eleman-wise)
z_div = x / (y + 1) # Güvenli bölme
z_pow = x ** 2 # Üs alma
# In-place işlemler (belleği verimli kullanır, _ suffix)
x.add_(y) # x = x + y (x'i değiştirir)
# Diğerleri: sub_, mul_, div_, zero_, fill_
# Karşılaştırma operatörleri
mask = x > 1 # [[False, False], [True, True]]
mask_eq = x == 2
|
8.2. Lineer Cebir İşlemleri
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # 8.2.1. Matris Çarpımı (Matrix Multiplication)
A = torch.randn(3, 4)
B = torch.randn(4, 5)
C = torch.matmul(A, B) # veya A @ B, sonuç: (3, 5)
# 8.2.2. Batch Matris Çarpımı (Batched Matrix Multiplication)
A = torch.randn(2, 3, 4) # 2 adet 3x4 matris
B = torch.randn(2, 4, 5) # 2 adet 4x5 matris
C = torch.bmm(A, B) # 2 adet 3x5 matris sonucu
# 8.2.3. Genel Matris Çarpımı (einsum - Einstein toplamı)
# A: (i,j), B: (j,k) -> C: (i,k)
C = torch.einsum('ij,jk->ik', A, B)
# 8.2.4. Transpoz ve Ters Matris
X = torch.randn(3, 3)
X_inv = torch.inverse(X) # Ters matris (kare ve tersinir olmalı)
X_det = torch.det(X) # Determinant
# 8.2.5. Özdeğer ve Özvektörler
eigenvalues, eigenvectors = torch.eig(X, eigenvectors=True)
# 8.2.6. Tekil Değer Ayrışımı (SVD)
U, S, V = torch.svd(X)
|
8.3. Redüksiyon İşlemleri (Toplama/Ortalama vb.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| x = torch.arange(12).reshape(3, 4).float()
# Tüm elemanlar üzerinde
print(x.sum()) # Toplam: 66.0
print(x.mean()) # Ortalama: 5.5
print(x.max()) # Maksimum: 11.0
print(x.min()) # Minimum: 0.0
print(x.prod()) # Çarpım: 0 (0 içerdiği için)
print(x.std()) # Standart sapma
# Belirli boyutlar boyunca (dim parametresi)
print(x.sum(dim=0)) # Sütunlar boyunca toplama: [12, 15, 18, 21]
print(x.sum(dim=1)) # Satırlar boyunca toplama: [6, 22, 38]
# Argmax/Argmin (maksimum/minimumun indeksleri)
print(x.argmax(dim=1)) # Her satırın maksimum indeksi
# Keepdim parametresi (boyut koruma)
print(x.sum(dim=0, keepdim=True)) # Şekil: (1, 4) yerine (4,)
# Broadcasting ile uyumlu işlemler için kullanışlı
|
9. Bellek Yönetimi ve Verimlilik
9.1. Hafıza Paylaşımı ve Kopyalama
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # Paylaşımlı bellek (View)
x = torch.arange(6)
y = x.view(2, 3)
y[0, 0] = 999
print(x[0]) # 999 - x de değişti!
# Kopya oluşturma (Clone)
x = torch.arange(6)
y = x.clone().view(2, 3) # veya x.detach().clone()
y[0, 0] = 999
print(x[0]) # 0 - x değişmedi
# Detach (gradyan takibini kesme)
x = torch.randn(3, requires_grad=True)
y = x.detach() # Gradyan hesaplanmayacak yeni tensor
|
9.2. Bellek Verimli İşlemler
1
2
3
4
5
6
7
8
9
10
11
12
13
| # In-place operasyonlar bellek tasarrufu sağlar
x = torch.randn(1000, 1000)
x.add_(1) # Yeni tensor oluşturmaz, mevcutu değiştirir
# torch.no_grad() bloğu (Eğitim dışı inference)
with torch.no_grad():
predictions = model(inputs) # Gradyan kaydı yapılmaz, bellek tasarrufu
# Bellek boşaltma (Garbage collection)
import gc
del x # Referansı sil
gc.collect() # Python GC çalıştır
torch.cuda.empty_cache() # GPU önbelleğini temizle (CUDA)
|
10. Autograd ve Otomatik Türev Hesaplama
PyTorch’un dinamik hesap grafiği (dynamic computation graph) özelliği, zincir kuralı (chain rule) uygulayarak otomatik türev hesaplamayı sağlar.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| # 10.1. Gradyan izleme (requires_grad)
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2 + 3 * x + 1 # y = x² + 3x + 1
y.backward() # dy/dx hesapla
print(x.grad) # 2*x + 3 = 7 (x=2 için)
# 10.2. Çok değişkenli fonksiyonlar
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = (x ** 2).sum() # y = x1² + x2² + x3²
y.backward()
print(x.grad) # [2, 4, 6] (2*x)
# 10.3. Jacobian vektör çarpımı (grad_output)
x = torch.randn(3, requires_grad=True)
y = x * 2
v = torch.tensor([1.0, 1.0, 1.0]) # Vektör
y.backward(v) # Jacobian * v
print(x.grad)
# 10.4. Gradyan birikmesi ve sıfırlama
x = torch.tensor(2.0, requires_grad=True)
for i in range(3):
y = x ** 2
y.backward()
print(f"Adım {i}: grad = {x.grad}") # Gradyanlar birikir!
x.grad.zero_() # Sıfırlama (optimizer.step() sonrası gerekli)
# 10.5. Hesap grafiğini engelleme (no_grad ve detach)
x = torch.tensor(2.0, requires_grad=True)
with torch.no_grad():
y = x * 2 # Bu işlem grafde yer almaz, gradyan hesaplanmaz
z = x.detach() * 3 # Detach ile koparılmış kopya
|
Önemli: backward() çağrısı gradyanları biriktirir (accumulates). Eğitim döngülerinde her adımda optimizer.zero_grad() veya tensor.grad.zero_() kullanılmalıdır.
11. Tensor Birleştirme ve Ayrıştırma
11.1. Birleştirme (Concatenation)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # torch.cat - Mevcut boyut boyunca birleştirme
x = torch.randn(2, 3)
y = torch.randn(2, 3)
z = torch.cat([x, y], dim=0) # Dikey: (4, 3)
w = torch.cat([x, y], dim=1) # Yatay: (2, 6)
# torch.stack - Yeni boyut oluşturarak birleştirme
x = torch.randn(2, 3)
y = torch.randn(2, 3)
z = torch.stack([x, y], dim=0) # (2, 2, 3) - Yeni batch boyutu
# x ve y aynı şekilde olmalı
# Dikey ve Yatay stack
z = torch.vstack([x, y]) # dim=0'da cat ile aynı
z = torch.hstack([x, y]) # dim=1'de cat ile aynı
|
11.2. Ayrıştırma (Splitting)
1
2
3
4
5
6
7
8
9
10
| x = torch.arange(12).reshape(3, 4)
# 11.2.1. torch.chunk - Eşit parçalara bölme
chunks = torch.chunk(x, 3, dim=0) # 3 parça: her biri (1, 4)
# 11.2.2. torch.split - Belirli boyutlarda bölme
splits = torch.split(x, [1, 2], dim=0) # 1 satır ve 2 satır olarak böl
# 11.2.3. torch.unbind - Boyut boyunca ayırma
tensors = torch.unbind(x, dim=0) # 3 adet (4,) tensor
|
12. PyTorch vs NumPy Karşılaştırması
| Özellik | PyTorch Tensor | NumPy Array |
|---|
| GPU Desteği | Var (CUDA) | Yok (sadece CPU) |
| Otomatik Türev | Var (Autograd) | Yok (manuel Jacobian gerekir) |
| Veri Tipi Varsayılanı | float32 | float64 |
| Cihaz Yönetimi | Açık (.to(device)) | Yok |
| Hesap Grafiği | Dinamik | Yok |
| İn-place Ops | Destekler (.add_()) | Destekler |
| Boolean indeksleme | Destekler | Daha zengin |
| String desteği | Sınırlı | Daha iyi |
12.1. Köprü Kurma (Interoperability)
1
2
3
4
5
6
7
8
9
| # PyTorch -> NumPy (Paylaşımlı bellek CPU'da)
x_torch = torch.randn(3, 3)
x_np = x_torch.numpy() # Aynı bellek alanını paylaşır (kopya değil!)
x_torch[0, 0] = 999 # x_np de değişir!
# NumPy -> PyTorch
x_np = np.array([1, 2, 3])
x_torch = torch.from_numpy(x_np) # Paylaşımlı bellek
x_torch = torch.tensor(x_np) # Kopya oluşturur (güvenli)
|
Dikkat: GPU’daki tensorler önce .cpu() ile CPU’ya taşınmalıdır, sonra .numpy() çağrılabilir.
13. Yaygın Hata Senaryoları ve Çözümleri
13.1. Cihaz Uyumsuzluğu (Device Mismatch)
1
2
3
4
5
6
7
8
| # HATA:
x = torch.rand(2, 3).cuda()
y = torch.rand(2, 3) # CPU'da
z = x + y # RuntimeError: Expected all tensors to be on the same device
# ÇÖZÜM:
y = y.to(x.device)
z = x + y
|
13.2. Veri Tipi Uyumsuzluğu (Type Mismatch)
1
2
3
4
5
6
7
| # HATA:
x = torch.arange(3) # int64
y = torch.tensor([0.5, 1.5, 2.5]) # float32
# İşlem yapılabilir ama beklenmedik sonuçlar olabilir
# ÇÖZÜM:
x = x.float() # veya x.to(torch.float32)
|
13.3. Şekil Uyumsuzluğu (Shape Mismatch)
1
2
3
4
5
6
7
8
| # HATA:
x = torch.randn(2, 3)
y = torch.randn(2, 4)
z = x + y # RuntimeError: The size of tensor a (3) must match...
# ÇÖZÜM:
print(x.shape, y.shape) # Her zaman kontrol edin
y = y[:, :3] # Veya reshape/transpose kullanın
|
13.4. Gradyan Çizelgesi Kesilmesi (Detached from graph)
1
2
3
4
5
6
7
8
9
10
| # HATA:
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2
z = y.detach()
w = z * 3
w.backward() # x.grad None kalır
# ÇÖZÜM:
w = y * 3 # Detach kullanmayın veya zincirin kopmadığından emin olun
w.backward()
|
13.5. In-place Operasyon ve Gradyan
1
2
3
4
5
6
7
| # HATA (RuntimeError: a leaf Variable that requires grad...):
x = torch.tensor([2.0], requires_grad=True)
x.add_(1) # Leaf tensor üzerinde in-place işlem
# ÇÖZÜM:
x = torch.tensor([2.0], requires_grad=True)
y = x + 1 # Yeni tensor oluştur
|
14.1. Pin Memory (Veri Yükleme Hızlandırma)
1
2
3
4
5
6
| # DataLoader'da kullanım (GPU'ya daha hızlı transfer)
loader = torch.utils.data.DataLoader(
dataset,
batch_size=32,
pin_memory=True # CPU tensorlerini page-locked memory'de tutar
)
|
14.2. Mixed Precision Training (FP16)
1
2
3
| # Bellek tasarrufu ve hız için (RTX GPU'larda özellikle etkili)
x = torch.randn(3, 3, dtype=torch.float16).cuda()
# veya AMP (Automatic Mixed Precision) kullanımı
|
14.3. Veri Sıralama (Contiguity)
1
2
3
4
| # Non-contiguous tensorlerle işlem yaparken dikkat
x = torch.randn(3, 4).t() # Transpose -> non-contiguous
# Önce contiguous hale getirin:
x = x.contiguous()
|
15. Alıştırma Örnekleri
Alıştırma 1: Görüntü Normalizasyonu
Bir batch görüntü tensorü (N, C, H, W) verildiğinde, her kanal için ortalama çıkarıp standart sapmaya bölün:
1
2
3
4
| images = torch.randn(32, 3, 64, 64) # Batch: 32, Kanal: 3, 64x64
mean = images.mean(dim=[0, 2, 3], keepdim=True) # Kanal bazında
std = images.std(dim=[0, 2, 3], keepdim=True)
normalized = (images - mean) / (std + 1e-8)
|
Alıştırma 2: Maske Uygulama
Belirli bir eşik değerinden küçük elemanları sıfırlayın, büyük olanları 1 yapın (binary mask):
1
2
3
| x = torch.randn(2, 3)
mask = (x > 0).float() # Boolean -> Float dönüşümü
result = x * mask # Negatifler sıfırlandı
|
Alıştırma 3: Batch Norm Manuel Implementasyon
1
2
3
4
5
6
7
8
| def manual_batch_norm(x, eps=1e-5):
# x: (batch, features)
mean = x.mean(dim=0, keepdim=True)
var = x.var(dim=0, keepdim=True, unbiased=False)
return (x - mean) / torch.sqrt(var + eps)
x = torch.randn(16, 20)
bn = manual_batch_norm(x)
|
16. Özet ve Hızlı Referans
| İşlem | Fonksiyon | Not |
|---|
| Şekil değiştirme | view(), reshape(), permute() | view contiguous gerektirir |
| Boyut ekleme/kaldırma | unsqueeze(), squeeze() | Parametre olmadan tüm 1’leri kaldırır |
| Birleştirme | cat(), stack(), vstack() | stack yeni boyut ekler |
| Ayrıştırma | chunk(), split(), unbind() | |
| Toplama/Ortalama | sum(), mean(), std() | dim ve keepdim parametreleri |
| Matris çarpımı | matmul(), @, bmm() | |
| Cihaz değiştirme | .to(device), .cuda(), .cpu() | |
| Gradyan kontrolü | requires_grad, detach(), no_grad() | |
| Boolean indeksleme | x[x > 0] | Maskeleme için |
Kritik Hatırlatmalar:
- GPU tensorleri üzerinde NumPy işlemleri çalışmaz (önce
.cpu() gerekir) view() kullanmadan önce is_contiguous() kontrolü yapın veya reshape() kullanın- Eğitim döngülerinde
optimizer.zero_grad() unutmayın torch.from_numpy() ile oluşturulan tensorler belleği paylaşır, torch.tensor() kopya oluşturur