PyTorch
PyTorch — фреймворк глубокого обучения от Meta: динамический граф вычислений, автоградиция и гибкость исследовательского пайплайна. И выбор №1 для естественных языков и картинок.
1. Что такое PyTorch
PyTorch нацелен на гибкость: граф вычислений строится «на лету» (dynamic), поэтому исследовать и отлаживать модели просто. Экосистема: torchvision (картинки), torchtext (тексты), Hugging Face Transformers, Lightning (обёртка обучения).
В науке и индустрии NLP PyTorch — фактически стандарт.
2. Установка
pip install torch torchvisionПроверь CUDA перед GPU-обучением:
import torch
print(torch.__version__)
print(torch.cuda.is_available())3. Тензоры
x = torch.tensor([[1., 2.], [3., 4.]])
print(x.shape) # torch.Size([2, 2])
y = torch.randn(3, 4)
z = x @ x.mT # умножение матриц
a = torch.zeros(2, 3, dtype=torch.float32)
# обмен с NumPy
import numpy as np
arr = x.numpy()
back = torch.from_numpy(arr)Как ndarray из NumPy, но с поддержкой GPU и автоградиции.
4. Autograd — автоматическое дифференцирование
x = torch.tensor(3.0, requires_grad=True)
y = x ** 2 + 5 * x
y.backward()
print(x.grad) # dy/dx = 2*3 + 5 = 11requires_grad=True включает отслеживание; backward() считает градиенты.
5. Модуль nn.Module
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = F.relu(self.fc1(x))
return F.log_softmax(self.fc2(x), dim=1)
model = Net()
print(model)6. Цикл обучения
import torch.optim as optim
optimizer = optim.Adam(model.parameters(), lr=1e-3)
loss_fn = nn.CrossEntropyLoss()
for epoch in range(10):
for xb, yb in train_loader:
optimizer.zero_grad()
out = model(xb)
loss = loss_fn(out, yb)
loss.backward()
optimizer.step()Пять шагов цикла: zero_grad → forward → loss → backward → step — основа всего обучения в PyTorch.
7. DataLoader
from torch.utils.data import Dataset, DataLoader
class MyData(Dataset):
def __init__(self, X, y):
self.X = torch.tensor(X, dtype=torch.float32)
self.y = torch.tensor(y, dtype=torch.long)
def __len__(self):
return len(self.X)
def __getitem__(self, i):
return self.X[i], self.y[i]
loader = DataLoader(MyData(X, y), batch_size=32, shuffle=True)DataLoader перемешивает данные, делит на батчи, работает с многопроцессностью.
8. Обучение на GPU
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = model.to(device)
for xb, yb in train_loader:
xb, yb = xb.to(device), yb.to(device)
# остальной цикл как раньше9. CNN на PyTorch
class CNN(nn.Module):
def __init__(self):
super().__init__()
self.conv = nn.Sequential(
nn.Conv2d(1, 32, 3),
nn.ReLU(),
nn.MaxPool2d(2))
self.fc = nn.Linear(32 * 13 * 13, 10)
def forward(self, x):
x = self.conv(x)
x = x.view(x.size(0), -1)
return self.fc(x)10. Сериализация
torch.save(model.state_dict(), 'model.pth')
loaded = Net()
loaded.load_state_dict(torch.load('model.pth'))
loaded.eval()state_dict — веса и буферы; model.eval() переключает в режим инференса (выключает dropout).
11. Экосистема и тенденции
- Lightning — «fit-функция» для PyTorch: одна строчка вместо цикла.
- Hugging Face — готовые трансформеры: gpt, bert, llama одной строкой.
- torch.compile — JIT-ускорение обучение и выводов.
model.eval() и with torch.no_grad() при инференсе — иначе dropout и autograd сломают результат и съедят память.12. Оптимизаторы и планировщики
Вид оптимизатора сильно влияет на сходимость. Самые распространённые в PyTorch:
optimizer = torch.optim.AdamW(model.parameters(),
lr=1e-4, weight_decay=1e-2)- SGD с momentum — классика, часто требует подбора lr;
- Adam / AdamW — стабилен для внимания и трансформеров;
- Lion, Adagrad — редкие сценарии (спарс-данные).
Планировщики меняют lr по ходу обучения:
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=30)
# каждый шаг или эпоху:
scheduler.step()13. Регуляризация
Приёмы, которые снижают переобучение:
# Dropout в PyTorch
self.dropout = nn.Dropout(0.3)
x = self.dropout(F.relu(self.fc1(x)))
# weight_decay внутри оптимизатора
optimizer = torch.optim.AdamW(model.parameters(), weight_decay=1e-2)- Dropout действует только на тренировке:
model.train() / model.eval(); - weight_decay штрафует большие веса;
- batch norm работает как мягкий регуляризатор;
- аугментации добавляют разнообразие в обучающую выборку.
model.eval() получит случайные активации на инференсе — метрики «плывут» нестабильно.14. Трансформеры через Hugging Face
Библиотека transformers даёт предобученные модели одной строкой:
from transformers import pipeline
clf = pipeline("sentiment-analysis")
print(clf("Курс отличный!")[0])# дообучение BERT под свою классификацию
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(
"bert-base-uncased", num_labels=2)Внутри — архитектура «красной» группы: энкодер, эмбеддинги, слои внимания. Метрики модели растут с данными и удачной тонкой настройкой.
15. Экспорт и инференс: ONNX / TorchScript
Тренировочная модель для продакшена переводится в компактные форматы:
dummy = torch.randn(1, 3, 224, 224)
torch.onnx.export(model, dummy, "model.onnx",
input_names=["input"], output_names=["out"])TorchScript фиксирует граф и исполняется без Python:
traced = torch.jit.trace(model, dummy)
traced.save("model.pt")ONNX удобен, когда сервер работает на другом рантайме — Triton, TensorRT, Python-бэкенды. Все оптимизации проверяй метриками на задержку и точностной тест.
16. Трансферное обучение и fine-tuning
Тренировать сеть с нуля дорого. Загрузи предобученную модель и обучай «поверх» неё:
from torchvision.models import resnet18
model = resnet18(weights="IMAGENET1K_V1")
for p in model.parameters(): # заморозили базу
p.requires_grad = False
model.fc = nn.Linear(512, 10) # новая голова
# кастуй вход под 224x224 — нормализация ImageNet- сначала тренируй только голову — это быстро и стабильно;
- потом «размораживай» часть слоёв с маленьким learning rate;
- проверяй нормализацию данных: модель ожидает статистики претрейна.
17. Скорость: AMP и torch.compile
Mixed precision (AMP) в 2–3 раза ускоряет тренировку на GPU без потери точности; torch.compile — компиляция графа в runtime:
scaler = torch.cuda.amp.GradScaler()
with torch.autocast(device_type="cuda", dtype=torch.float16):
out = model(x)
scaler.scale(loss).backward()
scaler.step(opt); scaler.update()
# или одной строкой при сборке модели
model = torch.compile(model)- AMP требует «совместимую» модель: нормализация и многие хитрости уже решены;
- torch.compile лучше работает с фиксированными формами входов;
- замеряй: ускорение не всегда оправдано на маленьких батчах.
18. Аугментации и баланс классов
Хорошие данные важнее архитектуры. Конструктор torchvision.transforms подключает аугментации «на лету»:
from torchvision import transforms as T
train_tf = T.Compose([
T.RandomResizedCrop(224, scale=(0.8, 1.0)),
T.RandomHorizontalFlip(),
T.ColorJitter(brightness=0.2, contrast=0.2),
T.ToTensor(), T.Normalize(MEAN, STD),
])- аугментации только для train, для validation — resize + normalize;
- при дисбалансе классов добавь
WeightedRandomSampler; - контролируй число параметров: слишком «сильные» аугментации режут accuracy;
- функцию потерь подбирай под метку: CE для классификации, BCE для бинарной.
19. Мониторинг и воспроизводимость
Нейросетевой проект без логов — чёрный ящик. Добавь метрики в TensorBoard и фиксируй сид:
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("runs/exp1")
writer.add_scalar("loss/train", loss.item(), step)
writer.add_histogram("weights", model.fc.weight, step)
# воспроизводимость
torch.manual_seed(42) # + seed для random/numpyfor epoch in range(epochs):
avg, acc = one_epoch(...)
print(f"{epoch:03d} loss={avg:.4f} acc={acc:.3f}")- пиши чекпойнт лучшей модели по val-метрике:
torch.save; - фиксируй seed и версии библиотек — сравнение экспериментов иначе иллюзорно;
- GPU, batch size, lr — всё в конфиге, не в коде.
20. Обработка текста: токенизация и эмбеддинги
Для начала работы с текстовыми данными важно понимать разницу между токенизацией и эмбеддингами:
from transformers import AutoTokenizer, AutoModel
tok = AutoTokenizer.from_pretrained("sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
ids = tok("Привет, мир!", return_tensors="pt")["input_ids"]| Термин | Что это | Когда нужно |
|---|---|---|
| Токенизация | разбиение на токены (слова/субслова) | вход для любой model |
| Эмбеддинг | векторное представление текста | поиск, классификация, кластеризация |
| pos/ner | части речи, именованные сущности | извлечение имен/дат из текста |
- для русского языка бери модели с поддержкой кириллицы: many-multilingual (bert-base-multilingual);
- эмбеддинг текста — через средний пулить токенов, а не только CLS-токен;
- перед попыткой строить модель попробуй быстрый baseline: получи вектора и сделай косинусную близость.
21. Обучение на CPU: стратегии для учебных задач
Процессоры медленнее GPU, но для учебных задач это не приговор — правильно ограничивай нагрузки:
model.to("cpu")
# меньше батчи, дробный lr, больше итераций
for x, y in loader:
x, y = x.to("cpu"), y.to("cpu")- уменьши размер батча и увеличь steps: память CPU ограничена;
- используй `torch.autocast("cpu", dtype=torch.bfloat16)` для быстрых типов, если поддерживается;
- важно число потоков: torch.set_num_threads(cores) часто ускоряет в 2–3 раза;
- для сверток выгоден режим channels-last (memory_format).
22. Чекпойнты: полный цикл сохранения
Сохранять нужно не только веса, но и всё, что нужно для продолжения обучения:
torch.save({
"model": model.state_dict(),
"optimizer": optim.state_dict(),
"epoch": epoch,
"val_acc": best_acc
}, f"ckpt_{epoch}.pt")- сэйв в конце каждой эпохи с номером — прослеживаемость экспериментов;
- best-checkpoint: сохраняй по val_acc, а не по train_loss;
- для возобновления: загрузка optimizer и random-состояний (seed) обязательно;
- экспорт в ONNX (см. раздел про экспорт) — отдельный поток от обучения.
23. Отладка: потеря, NaN и застрявшее обучение
Когда метрики не сходятся, ищи в порядке: данные, потеря, сходимость.
# три причины NaN: градиент, lr, деление на ноль
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)- NaN в loss — чаще всего lr слишком большой или числовая нестабильность деления;
- loss не падает: проверь нормализацию данных (x/255, стандартизация);
- точность «застряла» на значении класса большинства — посмотри распределение классов;
- помогает лог первого батча: выводи предсказания и стандарты, сравнение с loss.
Что дальше
Работа с данными — Pandas/NumPy, классика — Scikit-Learn. Удобная альтернатива пайплайна — TensorFlow+Keras.