- PyTorch'u sanal bir ortama kurmak ve CPU ile CUDA sürümlerini ayırt etmek
- Tensör oluşturmak, shape ve dtype özelliklerini okumak ve değiştirmek
- Yayınlama kurallarını ve matris çarpımını uygulayıp sonucun şeklini önceden söylemek
- Tensörleri CPU ile GPU arasında taşımak ve NumPy dizilerine dönüştürmek
NumPy dizileri sayısal hesaplamalar için harikadır ama derin öğrenme için iki eksikleri vardır: GPU üzerinde çalışmazlar ve türevleri otomatik hesaplayamazlar. PyTorch tam olarak bu iki boşluğu doldurur. Temel nesnesi olan tensör, bir NumPy dizisine çok benzer ama ekran kartında yaşayabilir ve kendi gradyanlarını takip edebilir. Bu derste tensörlerle rahatça çalışmayı öğreneceksin; bir sonraki ders otomatik türev almaya ayrılmıştır.
PyTorch nedir ve nasıl kurulur
PyTorch, Meta'nın (eski adıyla Facebook) yapay zekâ araştırma laboratuvarında geliştirilmiş açık kaynaklı bir derin öğrenme kütüphanesidir; 2022'den beri Linux Foundation bünyesindeki PyTorch Foundation tarafından yönetilir. Araştırmacılar ve şirketler onu sinir ağları kurmak, eğitmek ve kullanıma sunmak için yaygın olarak kullanır. PyTorch tarayıcıda çalışmaz; bu yüzden bu modüldeki PyTorch kodlarını kendi bilgisayarında çalıştırmalısın, çıktılar ise her örneğin altında gösterilir.
- 1Sanal ortam oluştur
Proje klasöründe
python -m venv .venvçalıştır ve ortamı etkinleştir; böylece PyTorch diğer projelerine karışmaz. - 2CPU ya da CUDA sürümünü seç
NVIDIA ekran kartın yoksa bu modül için CPU sürümü tamamen yeterlidir. GPU (CUDA) sürümü için tam komutu pytorch.org sitesindeki seçiciden, işletim sistemini ve CUDA sürümünü seçerek al.
- 3Kur ve kontrol et
pip install torchkomutunu çalıştır, ardından Python'daimport torchyazıp sürümü yazdır.
python -m venv .venv
# Windows: .venv\Scripts\activate macOS/Linux: source .venv/bin/activate
pip install torch numpy
# CPU-only build (smaller download):
pip install torch --index-url https://download.pytorch.org/whl/cpuimport torch
print(torch.__version__)
print(torch.cuda.is_available())2.14.0+cpu False
True yazar.Aynı türden sayılardan oluşan çok boyutlu bir dizi. Boyut sayısı (ndim) 0 ise skaler, 1 ise vektör, 2 ise matris, 3 ve fazlası ise genel bir tensördür. Her tensörün bir shape (her boyuttaki uzunluk), bir dtype (eleman türü) ve bir device (CPU ya da GPU) özelliği vardır.
| Veri | shape | Açıklama |
|---|---|---|
| bir kayıp değeri | () | skaler, 0 boyut |
| tablo verisi | (N, D) | N örnek, D öznitelik |
| renkli bir görüntü | (3, H, W) | RGB kanalları, yükseklik, genişlik |
| bir görüntü yığını | (N, C, H, W) | PyTorch'ta görüntüler için standart düzen |
| bir metin yığını | (N, T, E) | T token, her biri E boyutlu bir vektör |
Tensör oluşturmak: shape ve dtype
import torch
a = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(a)
print(a.shape, a.ndim, a.dtype)
print(torch.tensor([1.5, 2.0]).dtype)
print(torch.zeros(2, 3))
print(torch.arange(0, 10, 3))
torch.manual_seed(42)
print(torch.rand(2, 2))
print(a.float().dtype, a.to(torch.float16).dtype)tensor([[1, 2, 3],
[4, 5, 6]])
torch.Size([2, 3]) 2 torch.int64
torch.float32
tensor([[0., 0., 0.],
[0., 0., 0.]])
tensor([0, 3, 6, 9])
tensor([[0.8823, 0.9150],
[0.3829, 0.9593]])
torch.float32 torch.float16torch.tensor(...)türü kendisi belirler: tam sayılar →int64, ondalıklı sayılar →float32. NumPy'da ise ondalıklı sayılar için varsayılanfloat64'tür!torch.zeros,torch.ones,torch.arangevetorch.linspacehazır tensörler,torch.rand(0 ile 1 arasında düzgün dağılım) vetorch.randn(standart normal dağılım) ise rastgele tensörler oluşturur.torch.manual_seed(42)rastgele sayı üretecini sabitler; böylece sonuçlar tekrarlanabilir olur..float(),.long()ya da.to(torch.float16)türü değiştirir ve yeni bir tensör döndürür.
| dtype | Bayt | Tipik kullanım |
|---|---|---|
torch.float32 | 4 | ağırlıklar, girdiler, kayıplar; varsayılan tür |
torch.float16 / torch.bfloat16 | 2 | GPU'da karma hassasiyetli (mixed precision) hızlı eğitim |
torch.int64 | 8 | sınıf etiketleri, indeksler, token numaraları |
torch.bool | 1 | maskeler (örneğin x > 0) |
- d₁ … dₖshape'teki boyutlar
- numeleleman sayısı (
x.numel()) - sbir elemanın bayt cinsinden boyutu (
x.element_size())
224 × 224 boyutunda 64 renkli görüntüden oluşan bir yığın float32 olarak saklanıyor. Tensörün şekli nedir ve kaç bayt kaplar? float16 olsaydı ne olurdu?
Çözümü gösterÇözümü gizle
numel = 64 · 3 · 224 · 224 = 9.633.792.
Bellek = 9.633.792 · 4 = 38.535.168 bayt ≈ 38,5 MB.
float16'da her eleman 2 bayt olduğundan bellek yarıya iner: ≈ 19,3 MB. Karma hassasiyetin GPU belleğinden tasarruf etmesinin nedeni tam olarak budur.Yeniden şekillendirme ve indeksleme
import torch
m = torch.arange(12).reshape(3, 4)
print(m)
print(m[0], m[:, 1])
print(m[1, 2].item())
print(m[m > 8])
v = m.view(2, 6)
print(v.shape, m.T.shape)
print(m.unsqueeze(0).shape, m.flatten().shape)
v[0, 0] = 100
print(m[0, 0])tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
tensor([0, 1, 2, 3]) tensor([1, 5, 9])
6
tensor([ 9, 10, 11])
torch.Size([2, 6]) torch.Size([4, 3])
torch.Size([1, 3, 4]) torch.Size([12])
tensor(100)- İndeksleme NumPy'daki gibidir:
m[0]ilk satır,m[:, 1]ikinci sütun,m[m > 8]maskeyle seçimdir..item(), tek elemanlı bir tensörü sıradan bir Python sayısına çevirir. reshape(2, 6)veview(2, 6), eleman sayısını değiştirmeden şekli değiştirir; bir boyut yerine-1yazarsan PyTorch onu kendisi hesaplar:x.view(-1, 784).viewveriyi kopyalamaz, aynı belleğe başka bir “pencereden” bakar. Bu yüzdenv[0, 0] = 100işlemim'yi de değiştirdi!unsqueeze(0)1 boyutlu yeni bir eksen ekler (örneğin tek bir görüntüyü yığına çevirmek için),squeeze()bu tür eksenleri siler,.Tmatrisin devriğini alır,permuteise eksenleri istediğin sırayla yeniden düzenler.
İşlemler: yayınlama ve matris çarpımı
+, -, *, /, ** operatörleri eleman bazında çalışır. sum, mean, max gibi indirgemeler dim ile verilen eksen boyunca hesaplanır: a.mean(dim=0) her sütunun ortalamasıdır. Şekilleri farklı tensörler yayınlama (broadcasting) kurallarıyla eşleştirilir:
- Şekiller sağdan sola karşılaştırılır; kısa olan şeklin soluna 1 boyutlu eksenler eklenmiş sayılır.
- İki boyut eşitse ya da biri 1 ise uyumludur.
- 1 boyutlu eksen, diğerinin uzunluğuna kadar “gerilir” (veri kopyalanmadan).
import torch
a = torch.tensor([[1., 2.], [3., 4.]])
b = torch.tensor([10., 20.])
print(a + b)
print(a * a)
print(a @ a)
print(a.sum(), a.mean(dim=0))
X = torch.ones(64, 3)
W = torch.ones(3, 5)
print((X @ W).shape)
print((torch.ones(4, 1) + torch.ones(3)).shape)tensor([[11., 22.],
[13., 24.]])
tensor([[ 1., 4.],
[ 9., 16.]])
tensor([[ 7., 10.],
[15., 22.]])
tensor(10.) tensor([2., 3.])
torch.Size([64, 5])
torch.Size([4, 3])- A, Bboyutları m × n ve n × p olan matrisler
- niç boyut; iki matriste de aynı olmalıdır
- CᵢⱼA'nın i. satırı ile B'nin j. sütununun iç çarpımı
Matris çarpımı sinir ağlarının temel işlemidir: (N, D) boyutlu girdileri (D, K) boyutlu ağırlık matrisiyle çarparak tüm yığını tek seferde işleriz. Daha çok eksenli tensörlerde @ son iki eksene uygulanır, diğer eksenler yığın ekseni sayılır.
Her işlemin sonucunun şeklini bul ya da hata olacağını belirt: a) (64, 3) @ (3, 5); b) (4, 1) + (3,); c) (32, 10) + (10,); d) (2, 3) @ (2, 3); e) (8, 1, 6) + (7, 1).
Çözümü gösterÇözümü gizle
b) (3,) → (1, 3); 4 ile 1 ve 1 ile 3 uyumludur: (4, 3).
c) (10,) → (1, 10) olur ve her satıra eklenir (sapma vektörü böyle çalışır): (32, 10).
d) İç boyutlar 3 ≠ 2: hata. Gereken
A @ B.T idi: (2, 2).e) (7, 1) → (1, 7, 1); eksen eksen: 8 ve 1 → 8, 1 ve 7 → 7, 6 ve 1 → 6: (8, 7, 6).
GPU ve NumPy ile çalışmak
Bir ekran kartında matris çarpımlarını paralel hesaplayan binlerce basit çekirdek vardır; büyük modelleri GPU'da eğitmek çoğu zaman CPU'ya göre kat kat, hatta onlarca kat daha hızlıdır. Standart yöntem: betiğin başında bir device seçmek, sonra modeli ve veriyi .to(device) ile oraya taşımak. Apple Silicon bilgisayarlarda GPU cihazının adı 'mps''tir.
import numpy as np
import torch
device = 'cuda' if torch.cuda.is_available() else 'cpu'
x = torch.ones(2, 2, device=device)
print(device, x.device)
arr = np.array([1.0, 2.0, 3.0])
t = torch.from_numpy(arr)
arr[0] = 99
print(t)
back = (t * 2).numpy()
print(back, type(back).__name__)cpu cpu tensor([99., 2., 3.], dtype=torch.float64) [198. 4. 6.] ndarray
cuda cuda:0 olur.torch.from_numpy(arr) dizinin belleğini paylaşır: arr[0] = 99 değişikliği tensörde de göründü. dtype'ın float64 kaldığına dikkat et; eğitimden önce .float() ile float32'ye çevir. Ters yönde .numpy() yalnızca CPU'daki tensörlerde çalışır: GPU'daki bir tensörü önce .cpu() ile geri getir, gradyan takip ediliyorsa önce .detach() çağır: t.detach().cpu().numpy().
Önemli noktalar
- Tensör; shape, dtype ve device özellikleri olan çok boyutlu bir dizidir; PyTorch görüntüleri (N, C, H, W) şeklinde saklar.
- Ondalıklı sayılar için varsayılan tür
float32, etiketler ve indeksler içinint64'tür. viewbelleği paylaşır ve bitişik bellek ister; emin değilsenreshapekullan.- Yayınlama şekilleri sağdan karşılaştırır: boyutlar eşit olmalı ya da biri 1 olmalıdır.
@matris çarpımıdır: (m × n) @ (n × p) → (m × p). - Model ve veri
.to(device)ile aynı cihaza taşınır;from_numpyve.numpy()belleği paylaşır.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
torch.tensor([1.5, 2.0]).dtype nedir?