- PyTorch-u virtual mühitdə quraşdırmaq və CPU ilə CUDA versiyalarını fərqləndirmək
- Tenzor yaratmaq, onun shape və dtype xassələrini oxumaq və dəyişmək
- Yayımlama qaydalarını və matris hasilini tətbiq edərək nəticənin ölçüsünü əvvəlcədən demək
- Tenzorları CPU və GPU arasında köçürmək, NumPy massivlərinə çevirmək
NumPy massivləri ədədi hesablamalar üçün əladır, amma dərin öyrənmə üçün onlara iki şey çatmır: onlar GPU-da işləmir və törəmələri avtomatik hesablaya bilmir. PyTorch məhz bu iki boşluğu doldurur. Onun əsas obyekti — tenzor — NumPy massivinə çox bənzəyir, lakin videokartda işləyə və öz qradiyentlərini izləyə bilir. Bu dərsdə tenzorlarla sərbəst işləməyi öyrənəcəyik; növbəti dərs isə avtomatik törəmələrə həsr olunub.
PyTorch nədir və necə quraşdırılır
PyTorch — Meta (keçmiş Facebook) şirkətinin süni intellekt laboratoriyasında yaradılmış açıq mənbəli dərin öyrənmə kitabxanasıdır; 2022-ci ildən Linux Foundation nəzdindəki PyTorch Foundation tərəfindən idarə olunur. Tədqiqatçılar və şirkətlər onu neyron şəbəkələri yaratmaq, öyrətmək və tətbiq etmək üçün geniş istifadə edir. PyTorch brauzerdə işləmir, ona görə bu moduldakı PyTorch kodlarını öz kompüterində işə salmalısan; nəticələri isə hər kodun altında görə bilərsən.
- 1Virtual mühit yarat
Layihə qovluğunda
python -m venv .venvyaz və mühiti aktivləşdir. Belə olduqda PyTorch digər layihələrinə qarışmır. - 2CPU və ya CUDA versiyasını seç
NVIDIA videokartın yoxdursa, CPU versiyası bu modul üçün tamamilə kifayətdir. GPU (CUDA) versiyası üçün dəqiq əmri pytorch.org saytındakı seçicidən — əməliyyat sistemini və CUDA versiyasını seçərək — götür.
- 3Quraşdır və yoxla
pip install torchəmrini icra et, sonra Python-daimport torchyazıb versiyanı çap et.
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 olacaq.Eyni tipli ədədlərdən ibarət çoxölçülü massiv. Ölçülərin sayı (ndim) 0 olanda skalyar, 1 — vektor, 2 — matris, 3 və daha çox — ümumi tenzordur. Hər tenzorun shape (hər ölçü üzrə uzunluq), dtype (elementlərin tipi) və device (CPU və ya GPU) xassələri var.
| Verilən | shape | İzah |
|---|---|---|
| itkinin qiyməti | () | skalyar, 0 ölçü |
| cədvəl verilənləri | (N, D) | N nümunə, D əlamət |
| rəngli şəkil | (3, H, W) | RGB kanalları, hündürlük, en |
| şəkillər paketi | (N, C, H, W) | PyTorch-da şəkillər üçün standart düzülüş |
| mətnlər paketi | (N, T, E) | T token, hər biri E ölçülü vektor |
Tenzor yaratmaq: shape və 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(...)tipi özü müəyyən edir: tam ədədlər →int64, kəsr ədədlər →float32. NumPy-da isə kəsr ədədlər üçün susmaya görəfloat64olur!torch.zeros,torch.ones,torch.arange,torch.linspacehazır tenzorlar yaradır;torch.rand(0 ilə 1 arasında bərabər paylanma) vətorch.randn(standart normal paylanma) isə təsadüfi tenzorlar.torch.manual_seed(42)təsadüfi ədədlər generatorunu sabitləyir — nəticələri təkrarlamaq mümkün olur..float(),.long()və ya.to(torch.float16)tipi dəyişir və yeni tenzor qaytarır.
| dtype | Bayt | Harada işlədilir |
|---|---|---|
torch.float32 | 4 | çəkilər, girişlər, itkilər — susmaya görə tip |
torch.float16 / torch.bfloat16 | 2 | GPU-da qarışıq dəqiqlikli (mixed precision) sürətli öyrətmə |
torch.int64 | 8 | sinif nişanları, indekslər, token nömrələri |
torch.bool | 1 | maskalar (məsələn, x > 0) |
- d₁ … dₖshape-in ölçüləri
- numelelementlərin sayı (
x.numel()) - sbir elementin ölçüsü, bayt (
x.element_size())
224 × 224 ölçülü 64 rəngli şəkildən ibarət paket float32 tipində saxlanılır. Tenzorun shape-i nədir və o, neçə bayt tutur? float16 olsa necə?
Həllini göstərHəllini gizlət
numel = 64 · 3 · 224 · 224 = 9 633 792.
Yaddaş = 9 633 792 · 4 = 38 535 168 bayt ≈ 38,5 MB.
float16-da hər element 2 bayt olduğundan yaddaş iki dəfə azdır: ≈ 19,3 MB. Qarışıq dəqiqlik GPU yaddaşına məhz buna görə qənaət edir.Formanın dəyişdirilməsi və indeksləmə
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)- İndeksləmə NumPy-dakı kimidir:
m[0]— birinci sətir,m[:, 1]— ikinci sütun,m[m > 8]— maska ilə seçmə..item()bir elementli tenzoru adi Python ədədinə çevirir. reshape(2, 6)vəview(2, 6)elementlərin sayını dəyişmədən formanı dəyişir; bir ölçünün yerinə-1yazsan, PyTorch onu özü hesablayar:x.view(-1, 784).viewverilənləri kopyalamır, eyni yaddaşa başqa «pəncərədən» baxır. Buna görəv[0, 0] = 100əməliyyatım-i də dəyişdi!unsqueeze(0)ölçüsü 1 olan yeni ox əlavə edir (məsələn, tək şəkli paketə çevirmək üçün),squeeze()belə oxları silir,.Tmatrisi transponə edir,permuteisə oxların yerini istənilən qaydada dəyişir.
Əməliyyatlar: yayımlama və matris hasili
+, -, *, /, ** operatorları elementlər üzrə işləyir. sum, mean, max kimi reduksiyalar dim arqumenti ilə müəyyən ox boyunca hesablanır: a.mean(dim=0) sütunların orta qiymətidir. Formaları fərqli olan tenzorlar yayımlama (broadcasting) qaydaları ilə uyğunlaşdırılır:
- Formalar sağdan sola müqayisə olunur; qısa formanın solundan ölçüsü 1 olan oxlar əlavə edilmiş sayılır.
- İki ölçü bərabərdirsə və ya onlardan biri 1-dirsə, onlar uyğundur.
- Ölçüsü 1 olan ox digərinin uzunluğuna qədər «uzadılır» (verilənlər 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, Bölçüləri m × n və n × p olan matrislər
- ndaxili ölçü — hər iki matrisdə eyni olmalıdır
- CᵢⱼA-nın i-ci sətri ilə B-nin j-ci sütununun skalyar hasili
Matris hasili neyron şəbəkələrin əsas əməliyyatıdır: (N, D) ölçülü girişləri (D, K) çəkilər matrisinə vurmaqla bütün paketi bir anda emal edirik. Daha çox ölçülü tenzorlarda @ son iki oxa tətbiq olunur, qalan oxlar isə paket oxları sayılır.
Hər əməliyyatın nəticəsinin formasını tap və ya xəta olacağını göstər: a) (64, 3) @ (3, 5); b) (4, 1) + (3,); c) (32, 10) + (10,); d) (2, 3) @ (2, 3); e) (8, 1, 6) + (7, 1).
Həllini göstərHəllini gizlət
b) (3,) → (1, 3); 4 ilə 1, 1 ilə 3 uyğundur: (4, 3).
c) (10,) → (1, 10), hər sətrə əlavə olunur (sürüşmə vektoru belə işləyir): (32, 10).
d) Daxili ölçülər 3 ≠ 2 — xəta. Lazım olan
A @ B.T idi: (2, 2).e) (7, 1) → (1, 7, 1); oxlar üzrə: 8 və 1 → 8, 1 və 7 → 7, 6 və 1 → 6: (8, 7, 6).
GPU və NumPy ilə iş
Videokartda minlərlə sadə nüvə var və matris hasilini paralel hesablayır; böyük modellərin GPU-da öyrədilməsi çox vaxt CPU ilə müqayisədə bir neçə dəfədən onlarla dəfəyə qədər sürətli olur. Standart üsul: kodun əvvəlində device seçmək, sonra modeli və verilənləri .to(device) ilə ora köçürmək. Apple Silicon kompüterlərdə GPU üçün 'mps' qurğusu var.
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 olacaq.torch.from_numpy(arr) massivin yaddaşını paylaşır: arr[0] = 99 dəyişikliyi tenzorda da göründü. Diqqət et ki, dtype float64 qaldı — öyrətmədən əvvəl .float() ilə float32-yə çevirmək lazımdır. Əks istiqamətdə .numpy() yalnız CPU-dakı tenzorlar üçün işləyir: GPU-dakı tenzoru əvvəlcə .cpu() ilə geri gətir, qradiyent izlənirsə, əvvəlcə .detach() çağır: t.detach().cpu().numpy().
Əsas fikirlər
- Tenzor — shape, dtype və device xassələri olan çoxölçülü massivdir; PyTorch-da şəkillər (N, C, H, W) formasında saxlanılır.
- Kəsr ədədlər üçün susmaya görə tip
float32, nişanlar və indekslər üçünint64-dür. viewyaddaşı paylaşır və ardıcıl yaddaş tələb edir; əmin deyilsənsə,reshapeişlət.- Yayımlama formaları sağdan müqayisə edir: ölçülər bərabər və ya biri 1 olmalıdır.
@matris hasilidir: (m × n) @ (n × p) → (m × p). - Model və verilənlər
.to(device)ilə eyni qurğuya köçürülür;from_numpyvə.numpy()yaddaşı paylaşır.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.
torch.tensor([1.5, 2.0]).dtype nəyə bərabərdir?