PyTorch

Полное руководство по возможностям библиотеки

Введение в PyTorch

PyTorch — это библиотека для языка Python с открытым исходным кодом, созданная на базе Torch для машинного обучения. Она разрабатывается преимущественно группой искусственного интеллекта Facebook (Meta*).

PyTorch отличается своим подходом к построению динамических вычислительных графов, что делает его особенно удобным для исследователей в области глубокого обучения.

Ключевые особенности PyTorch:

  • Динамический вычислительный граф
  • Императивный стиль программирования
  • Простая интеграция с Python экосистемой
  • Поддержка GPU через CUDA
  • Автоматическое дифференцирование
PyTorch логотип

Основная формула PyTorch

PyTorch = NumPy + CUDA + Автоматическое дифференцирование

Это означает, что PyTorch сочетает в себе знакомый интерфейс работы с многомерными массивами (как в NumPy), возможность использования графических процессоров через CUDA и механизм автоматического вычисления градиентов, необходимый для обучения нейронных сетей.

Место среди других фреймворков

Категории фреймворков глубокого обучения

Схематичное изображение трёх основных категорий фреймворков глубокого обучения

PyTorch относится к фреймворкам с динамическим вычислительным графом, что отличает его от TensorFlow и других библиотек со статическим графом.

Фиксированные модули

Подобно Lego: пользователь комбинирует заранее определённые блоки. Низкая расширяемость, но высокая скорость разработки.

Примеры: Caffe, CNTK, Keras

Статический граф

Как полимерная глина: после «запекания» (компиляции) граф становится фиксированным. Компромисс между гибкостью и скоростью.

Примеры: TensorFlow, Theano, MXNet

Динамический граф

Граф строится динамически при каждом запуске. Максимальная гибкость и расширяемость, все возможности Python.

Примеры: PyTorch, Torch

Архитектура и структура PyTorch

Архитектура PyTorch

Архитектурная схема библиотеки PyTorch

PyTorch построен в виде многоуровневой архитектуры, где каждый уровень обеспечивает определенную функциональность. Эта модульная структура позволяет использовать только необходимые компоненты библиотеки.

Уровни архитектуры PyTorch:

1. Низкоуровневый движок тензоров

Базовый уровень, обеспечивающий операции с многомерными массивами (тензорами). Оптимизирован для работы как на CPU, так и на GPU.

2. Система автоматического дифференцирования

Реализует алгоритм обратного распространения ошибки (backpropagation) для вычисления градиентов сложных функций.

3. Модуль нейронных сетей (torch.nn)

Высокоуровневый API для создания и обучения нейронных сетей с готовыми слоями, функциями активации, критериями потерь.

4. Оптимизаторы и инструменты обработки данных

Включает различные алгоритмы оптимизации и компоненты для загрузки, обработки и манипулирования данными.

5. Специализированные домены

Дополнительные модули для работы с конкретными типами данных, например, torchvision для компьютерного зрения, torchaudio для обработки звука, torchtext для обработки естественного языка.

Релизная стратегия PyTorch

PyTorch использует трехуровневую систему для классификации функций по их стабильности:

Stable

Стабильные функции с долгосрочной поддержкой, полной документацией и без серьезных ограничений производительности. Обратная совместимость сохраняется.

Beta

Функции, API которых может меняться на основе обратной связи от пользователей, или требующие улучшения производительности. Обратная совместимость не гарантируется.

Prototype

Экспериментальные функции, обычно недоступные в стандартных дистрибутивах или скрытые за флагами времени выполнения. Находятся на ранней стадии разработки.

Основные модули PyTorch

PyTorch состоит из нескольких ключевых модулей, каждый из которых отвечает за определенную функциональность библиотеки.

torch

Основной модуль, содержащий базовые операции с тензорами, математические функции и примитивы для создания тензоров.

Включает функции для создания, манипуляции и выполнения операций над тензорами, аналогично NumPy, но с возможностью выполнения на GPU.

torch.autograd

Реализует механизм автоматического дифференцирования для всех операций с тензорами.

Позволяет автоматически вычислять градиенты для обратного распространения ошибки при обучении нейронных сетей.

torch.nn

Высокоуровневый API для создания и обучения нейронных сетей.

Предоставляет готовые реализации слоев, функций активации, функций потерь и других компонентов для построения сложных архитектур нейронных сетей.

torch.optim

Реализует различные алгоритмы оптимизации для обучения моделей.

Включает популярные оптимизаторы: SGD, Adam, RMSProp, Adagrad и другие, а также планировщики скорости обучения.

torch.utils.data

Предоставляет инструменты для эффективной загрузки и обработки данных.

Включает Dataset и DataLoader для организации, батчинга и асинхронной загрузки данных во время обучения.

torch.cuda

Обеспечивает интеграцию с CUDA для выполнения вычислений на GPU.

Позволяет перемещать тензоры между CPU и GPU, контролировать использование памяти и управлять несколькими устройствами.

torch.distributed

Поддерживает параллельные и распределенные вычисления.

Позволяет эффективно обучать модели на нескольких GPU или даже на нескольких машинах.

torch.library

API для расширения PyTorch пользовательскими операторами и функциями.

Позволяет создавать, тестировать и интегрировать новые операторы с полной поддержкой autograd, батчинга и компиляции.

Дополнительные домен-специфичные пакеты

torchvision

Библиотека для работы с изображениями и компьютерным зрением. Включает готовые модели, преобразования данных и популярные наборы данных.

torchaudio

Инструменты для работы с аудиоданными и обработки звука. Предоставляет функции для чтения, преобразования и извлечения признаков из аудиосигналов.

torchtext

Библиотека для обработки естественного языка (NLP). Содержит инструменты для работы с текстовыми данными и языковыми моделями.

torchrec

Библиотека для крупномасштабных рекомендательных систем, оптимизированная для обработки разреженных данных.

torchserve

Фреймворк для развертывания моделей PyTorch в производство с поддержкой масштабирования и мониторинга.

Тензоры и операции

Тензоры являются фундаментальными структурами данных в PyTorch, аналогичными массивам NumPy, но с дополнительными возможностями для автоматического дифференцирования и выполнения на GPU.

Тензоры в PyTorch

Схема работы с тензорами в PyTorch

Типы тензоров

Тип Описание Пример создания
torch.FloatTensor 32-бит, с плавающей точкой torch.FloatTensor(2, 3)
torch.DoubleTensor 64-бит, с плавающей точкой torch.DoubleTensor(2, 3)
torch.IntTensor 32-бит, целочисленный, знаковый torch.IntTensor(2, 3)
torch.LongTensor 64-бит, целочисленный, знаковый torch.LongTensor(2, 3)
torch.ByteTensor 8-бит, целочисленный, беззнаковый torch.ByteTensor(2, 3)

Важно: В отличие от NumPy, PyTorch не выполняет автоматическое приведение типов. Необходимо явно преобразовывать тензоры, используя методы .float(), .long(), .to(dtype=torch.float32) и т.д.

Создание тензоров

# Из списка Python
x = torch.tensor([[1, 2], [3, 4]])

# С определенным типом данных
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]], dtype=torch.float32)

# Заполнение нулями
x = torch.zeros(2, 3)

# Заполнение единицами
x = torch.ones(2, 3)

# Случайные значения из нормального распределения
x = torch.randn(2, 3)

# Случайные значения из равномерного распределения [0, 1)
x = torch.rand(2, 3)

# Единичная матрица
x = torch.eye(3)

# Из NumPy массива
import numpy as np
numpy_array = np.random.rand(2, 3)
x = torch.from_numpy(numpy_array)

Операции с тензорами

Mutable и immutable функции в PyTorch

Графическое представление mutable и immutable функций в PyTorch

Соглашение о наименованиях: В PyTorch функции вида xxx возвращают новый тензор (immutable), а функции вида xxx_ изменяют исходный тензор (mutable/inplace).

Арифметические операции

Immutable операции
  • z = x.add(y) или z = x + y
  • z = x.sub(y) или z = x - y
  • z = x.mul(y) или z = x * y
  • z = x.div(y) или z = x / y
Mutable операции
  • x.add_(y) или x += y
  • x.sub_(y) или x -= y
  • x.mul_(y) или x *= y
  • x.div_(y) или x /= y

Матричные операции

  • z = x.mm(y) — матричное умножение
  • z = x.mv(v) — умножение матрицы на вектор
  • z = x.dot(y) — скалярное произведение
  • z = x.t() — транспонирование
  • bz = bx.bmm(by) — батчевое матричное умножение

Операции редукции

  • s = x.mean(dim) — среднее значение
  • s = x.sum(dim) — сумма
  • s = x.prod(dim) — произведение
  • s = x.max(dim) — максимум
  • s = x.min(dim) — минимум
  • s = x.std(dim) — стандартное отклонение
  • s = x.var(dim) — дисперсия
  • s = x.median(dim) — медиана

Манипуляции формой и преобразования

# Изменение размерности
x = torch.randn(4, 4)
y = x.view(16)  # преобразование в одномерный тензор
z = x.view(-1, 8)  # -1 автоматически определяет размер

# Конкатенация тензоров
a = torch.randn(2, 3)
b = torch.randn(2, 3)
c = torch.cat([a, b], dim=0)  # по первому измерению
d = torch.cat([a, b], dim=1)  # по второму измерению

# Расширение размерности
x = torch.randn(2, 3)
y = x.unsqueeze(0)  # добавляет измерение в начало
z = x.unsqueeze(1)  # добавляет измерение после первого

# Сжатие размерности
x = torch.randn(1, 2, 3)
y = x.squeeze()  # удаляет все измерения размера 1
z = x.squeeze(0)  # удаляет указанное измерение, если его размер 1

Индексирование и срезы

# Индексирование как в Python
x = torch.randn(4, 3)
print(x[0])  # первая строка
print(x[:, 1])  # второй столбец
print(x[0, 1])  # элемент в первой строке, втором столбце

# Индексирование с помощью тензора
indices = torch.tensor([0, 2])
print(x[indices])  # выбирает строки с указанными индексами

# Булево индексирование
mask = x > 0
print(x[mask])  # выбирает элементы, где условие истинно

Интеграция с NumPy

# Из NumPy в PyTorch
import numpy as np
np_array = np.random.rand(2, 3)
torch_tensor = torch.from_numpy(np_array)

# Из PyTorch в NumPy
torch_tensor = torch.randn(2, 3)
np_array = torch_tensor.numpy()

# Важно: тензоры, созданные через from_numpy(), 
# разделяют память с исходным NumPy массивом

Автоматическое дифференцирование

Автоматическое дифференцирование (AutoGrad) — ключевая особенность PyTorch, позволяющая автоматически вычислять градиенты для оптимизации моделей машинного обучения.

«Механизм автоматического дифференцирования, заключённый в модуле torch.autograd, является хоть и не главным, но, без сомнения, важнейшим компонентом библиотеки, без которого та потеряла бы всякий смысл.»

Принцип работы

В PyTorch используется техника дифференцирования, при которой граф вычислений строится динамически во время выполнения (define-by-run). Это позволяет:

  • Автоматически отслеживать все операции с тензорами
  • Вычислять градиенты всех переменных относительно любой другой переменной
  • Сохранять полный контроль над всем процессом вычислений

Основы использования

# Создание тензоров с возможностью вычисления градиентов
x = torch.randn(2, 2, requires_grad=True)
y = torch.randn(2, 2, requires_grad=True)

# Выполнение операций
z = x * y
out = z.mean()

# Вычисление градиентов
out.backward()

# Доступ к градиентам
print(x.grad)  # d(out)/dx
print(y.grad)  # d(out)/dy

Важные свойства:

  • requires_grad — флаг, указывающий, нужно ли отслеживать вычисления для тензора
  • grad — содержит градиент тензора (None, если градиент не был вычислен)
  • grad_fn — содержит ссылку на функцию, создавшую тензор
  • is_leaf — указывает, является ли тензор листовым узлом в графе вычислений

Управление вычислением градиентов

torch.no_grad()

Контекстный менеджер, временно отключающий вычисление градиентов. Полезно при выполнении оценки модели (validation/inference).

with torch.no_grad():
    model_output = model(input_data)

torch.set_grad_enabled()

Функция для включения/отключения вычисления градиентов. Удобна для использования в циклах обучения.

torch.set_grad_enabled(is_training)
# вычисления
torch.set_grad_enabled(True)

detach()

Создает новый тензор, отделенный от графа вычислений. Полезно для прерывания потока градиентов.

detached = x.detach()
# detached не будет накапливать градиенты

retain_grad()

Сохраняет градиенты для промежуточных тензоров, которые обычно не сохраняются после вызова backward().

z = x * y
z.retain_grad()  # сохранит z.grad после backward()

Пример сложного вычисления с градиентами

import torch

# Создаем тензоры с отслеживанием вычислений
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = torch.tensor([4.0, 5.0, 6.0], requires_grad=True)

# Выполняем операции
a = torch.sum(x * y)
b = torch.sum(x)
c = a * b

# Вычисляем градиенты
c.backward()

# Проверяем результаты
print(f"x.grad: {x.grad}")  # d(c)/dx
print(f"y.grad: {y.grad}")  # d(c)/dy

Нейронные сети

Модуль torch.nn предоставляет высокоуровневый интерфейс для создания и обучения нейронных сетей, позволяя строить как простые, так и сложные архитектуры.

Нейронные сети в PyTorch

Структура и компоненты нейронных сетей в PyTorch

Основные компоненты torch.nn

Module

Базовый класс для всех нейронных сетевых компонентов. Все модели и слои должны наследоваться от него.

class MyModel(nn.Module):
    def __init__(self):
        super().__init__()
        # определение слоев
        
    def forward(self, x):
        # логика прямого прохода
        return output

Functional

Функциональный интерфейс для операций, которые не содержат обучаемых параметров (функции активации и др.).

import torch.nn.functional as F
output = F.relu(input)
output = F.max_pool2d(input, kernel_size=2)

Основные слои

Линейные слои

  • nn.Linear(in_features, out_features) — полносвязный слой
  • nn.Bilinear(in1_features, in2_features, out_features) — билинейный слой

Сверточные слои

  • nn.Conv1d(in_channels, out_channels, kernel_size) — одномерная свертка
  • nn.Conv2d(in_channels, out_channels, kernel_size) — двумерная свертка
  • nn.Conv3d(in_channels, out_channels, kernel_size) — трехмерная свертка
  • nn.ConvTranspose2d(in_channels, out_channels, kernel_size) — транспонированная свертка

Рекуррентные слои

  • nn.RNN(input_size, hidden_size) — рекуррентный слой
  • nn.LSTM(input_size, hidden_size) — LSTM слой
  • nn.GRU(input_size, hidden_size) — GRU слой

Функции активации

  • nn.ReLU(), nn.LeakyReLU(), nn.PReLU()
  • nn.Sigmoid(), nn.Tanh()
  • nn.Softmax(dim), nn.LogSoftmax(dim)
  • nn.GELU(), nn.SiLU() (Swish)

Нормализация и регуляризация

  • nn.BatchNorm1d/2d/3d(num_features) — пакетная нормализация
  • nn.LayerNorm(normalized_shape) — нормализация слоя
  • nn.Dropout(p) — случайное отключение нейронов
  • nn.Weight1d/2d/3d(p, reduction) — L1/L2 регуляризация

Функции потерь

  • nn.MSELoss() — среднеквадратичная ошибка
  • nn.CrossEntropyLoss() — кросс-энтропия (сочетает LogSoftmax и NLLLoss)
  • nn.BCELoss() — бинарная кросс-энтропия
  • nn.L1Loss() — средняя абсолютная ошибка
  • nn.NLLLoss() — отрицательное логарифмическое правдоподобие
  • nn.KLDivLoss() — дивергенция Кульбака-Лейблера
  • nn.HuberLoss() — Huber Loss (устойчивый к выбросам)
  • nn.CosineEmbeddingLoss() — косинусное расстояние для эмбеддингов

Определение модели

Существует несколько подходов к определению моделей в PyTorch:

Определение через классы

import torch.nn as nn

class SimpleNN(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_dim, output_dim)
        
    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x
        
model = SimpleNN(10, 50, 3)

Использование Sequential

import torch.nn as nn

model = nn.Sequential(
    nn.Linear(10, 50),
    nn.ReLU(),
    nn.Linear(50, 3)
)

Обучение модели

import torch
import torch.nn as nn
import torch.optim as optim

# Определение модели
model = SimpleNN(input_dim, hidden_dim, output_dim)

# Перенос на GPU (если доступно)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)

# Определение функции потерь и оптимизатора
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Цикл обучения
for epoch in range(num_epochs):
    for inputs, targets in dataloader:
        # Перенос данных на то же устройство, что и модель
        inputs, targets = inputs.to(device), targets.to(device)
        
        # Обнуление градиентов
        optimizer.zero_grad()
        
        # Прямой проход
        outputs = model(inputs)
        
        # Вычисление потерь
        loss = criterion(outputs, targets)
        
        # Обратное распространение и обновление весов
        loss.backward()
        optimizer.step()
        
    print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item():.4f}')

CUDA и производительность

Одно из ключевых преимуществ PyTorch — простая и эффективная поддержка вычислений на GPU через CUDA, что значительно ускоряет обучение моделей глубокого обучения.

Основы работы с CUDA

# Проверка доступности CUDA
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")

# Проверка количества доступных GPU
if torch.cuda.is_available():
    num_gpus = torch.cuda.device_count()
    print(f"Available GPUs: {num_gpus}")
    for i in range(num_gpus):
        print(f"GPU {i}: {torch.cuda.get_device_name(i)}")

# Создание тензора на GPU
x = torch.randn(10, 10, device=device)
# или
x = torch.randn(10, 10).to(device)

# Перемещение тензора между устройствами
x_cpu = x.cpu()
x_gpu = x_cpu.cuda()  # или x_cpu.to('cuda')

# Указание конкретного GPU
if torch.cuda.device_count() > 1:
    x_gpu1 = torch.randn(10, 10, device="cuda:1")  # второй GPU

Важно: Перемещение тензора на GPU создает его копию. Оригинальный тензор остается неизменным.

Перемещение модели на GPU

# Перемещение всей модели на GPU
model = MyModel()
model = model.to(device)

# Если нужно использовать несколько GPU
if torch.cuda.device_count() > 1:
    print(f"Using {torch.cuda.device_count()} GPUs")
    model = nn.DataParallel(model)
    
model = model.to(device)

Оптимизация производительности

Закрепленная память (Pinned Memory)

Ускоряет передачу данных между CPU и GPU, предотвращая копирование через буфер.

dataloader = DataLoader(
    dataset,
    batch_size=32,
    pin_memory=True  # Использование закрепленной памяти
)

Асинхронные операции

PyTorch выполняет операции на GPU асинхронно. Можно использовать это для оптимизации.

# Ожидание завершения всех асинхронных операций
torch.cuda.synchronize()

# Синхронизация конкретного устройства
torch.cuda.synchronize("cuda:1")

Управление памятью

Контроль за использованием памяти GPU для предотвращения утечек.

# Проверка использования памяти
print(f"Allocated: {torch.cuda.memory_allocated() / 1e9} GB")
print(f"Cached: {torch.cuda.memory_reserved() / 1e9} GB")

# Очистка неиспользуемой кэшированной памяти
torch.cuda.empty_cache()

Смешанная точность

Использование вычислений с половинной точностью (FP16) для ускорения без существенной потери качества.

from torch.cuda.amp import autocast, GradScaler

# Инициализация масштабировщика градиентов
scaler = GradScaler()

# В цикле обучения
with autocast():
    outputs = model(inputs)
    loss = criterion(outputs, targets)

# Масштабирование градиентов для предотвращения потери точности
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()

Контекстные менеджеры для CUDA

# Указание устройства по умолчанию для новых тензоров
with torch.cuda.device(1):
    # Все тензоры, созданные здесь, будут на cuda:1
    x = torch.randn(10, 10)  # x будет на cuda:1
    
# Временное использование определенного устройства
x = torch.randn(10, 10)  # на текущем устройстве по умолчанию
with torch.cuda.device(1):
    y = torch.randn(10, 10)  # на cuda:1
    
# После выхода из контекста снова используется предыдущее устройство
z = torch.randn(10, 10)  # на первоначальном устройстве

Практические примеры

Пример 1: Линейная регрессия

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

# Генерация данных
np.random.seed(42)
x = np.random.rand(100, 1)
y = 1 + 2 * x + 0.1 * np.random.randn(100, 1)  # y = 1 + 2x + шум

# Преобразование в тензоры
x_tensor = torch.from_numpy(x).float()
y_tensor = torch.from_numpy(y).float()

# Определение модели
class LinearRegression(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(1, 1)
        
    def forward(self, x):
        return self.linear(x)
    
model = LinearRegression()

# Функция потерь и оптимизатор
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.1)

# Обучение модели
epochs = 100
losses = []

for epoch in range(epochs):
    # Прямой проход
    y_pred = model(x_tensor)
    
    # Вычисление потерь
    loss = criterion(y_pred, y_tensor)
    losses.append(loss.item())
    
    # Обратное распространение
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    if (epoch+1) % 10 == 0:
        print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
        
# Получение параметров модели
w = model.linear.weight.item()
b = model.linear.bias.item()
print(f'Параметры модели: w = {w:.4f}, b = {b:.4f}')

Пример 2: CNN для классификации изображений

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms

# Определение преобразований
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

# Загрузка данных MNIST
train_dataset = torchvision.datasets.MNIST(
    root='./data', train=True, transform=transform, download=True)
test_dataset = torchvision.datasets.MNIST(
    root='./data', train=False, transform=transform, download=True)

train_loader = torch.utils.data.DataLoader(
    train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    test_dataset, batch_size=1000, shuffle=False)

# Определение CNN модели
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.fc1 = nn.Linear(64 * 7 * 7, 128)
        self.fc2 = nn.Linear(128, 10)
        self.relu = nn.ReLU()
        
    def forward(self, x):
        x = self.conv1(x)
        x = self.relu(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.relu(x)
        x = self.pool(x)
        x = x.view(-1, 64 * 7 * 7)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# Инициализация модели, функции потерь и оптимизатора
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = CNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Обучение модели
num_epochs = 5

for epoch in range(num_epochs):
    running_loss = 0.0
    
    for i, (images, labels) in enumerate(train_loader):
        images = images.to(device)
        labels = labels.to(device)
        
        # Прямой проход
        outputs = model(images)
        loss = criterion(outputs, labels)
        
        # Обратное распространение
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        running_loss += loss.item()
        
        if (i+1) % 100 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {running_loss/100:.4f}')
            running_loss = 0.0
    
    # Оценка на тестовом наборе
    model.eval()
    with torch.no_grad():
        correct = 0
        total = 0
        for images, labels in test_loader:
            images = images.to(device)
            labels = labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
        
        print(f'Accuracy: {100 * correct / total:.2f}%')

Пример 3: Трансформер для анализа текста

import torch
import torch.nn as nn
import torch.optim as optim
from torch.nn import TransformerEncoder, TransformerEncoderLayer

# Определение параметров модели
vocab_size = 10000  # размер словаря
embed_dim = 200     # размерность эмбеддингов
hidden_dim = 200    # размерность скрытого состояния
num_layers = 2      # количество слоев трансформера
num_heads = 8       # количество голов внимания
dropout = 0.2       # вероятность дропаута
max_len = 100       # максимальная длина последовательности

# Модель трансформера для классификации текста
class TransformerClassifier(nn.Module):
    def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes, 
                 num_layers, num_heads, max_len, dropout=0.5):
        super().__init__()
        
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        self.pos_encoder = PositionalEncoding(embed_dim, dropout, max_len)
        
        encoder_layers = TransformerEncoderLayer(
            embed_dim, num_heads, hidden_dim, dropout)
        self.transformer_encoder = TransformerEncoder(encoder_layers, num_layers)
        
        self.classifier = nn.Linear(embed_dim, num_classes)
        self.dropout = nn.Dropout(dropout)
        
    def forward(self, x):
        # x имеет форму [batch_size, seq_len]
        
        embedded = self.embedding(x)  # [batch_size, seq_len, embed_dim]
        embedded = self.pos_encoder(embedded)
        
        # Изменение размерности для трансформера: [seq_len, batch_size, embed_dim]
        embedded = embedded.permute(1, 0, 2)
        
        encoded = self.transformer_encoder(embedded)
        
        # Используем выход для первого токена [CLS] как представление всей последовательности
        pooled = encoded[0]
        
        output = self.dropout(pooled)
        output = self.classifier(output)
        
        return output

# Позиционное кодирование
class PositionalEncoding(nn.Module):
    def __init__(self, embed_dim, dropout=0.1, max_len=5000):
        super().__init__()
        self.dropout = nn.Dropout(p=dropout)
        
        pe = torch.zeros(max_len, embed_dim)
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(
            torch.arange(0, embed_dim, 2).float() * (-torch.log(torch.tensor(10000.0)) / embed_dim)
        )
        
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0)
        
        self.register_buffer('pe', pe)
        
    def forward(self, x):
        x = x + self.pe[:, :x.size(1), :]
        return self.dropout(x)

# Пример использования модели
model = TransformerClassifier(
    vocab_size=vocab_size,
    embed_dim=embed_dim,
    hidden_dim=hidden_dim,
    num_classes=2,  # бинарная классификация
    num_layers=num_layers,
    num_heads=num_heads,
    max_len=max_len,
    dropout=dropout
)

# Проверка формы выходных данных
batch_size = 8
seq_len = 64
dummy_input = torch.randint(0, vocab_size, (batch_size, seq_len))
output = model(dummy_input)
print(f"Форма выходных данных: {output.shape}")  # должна быть [batch_size, num_classes]

Экосистема

Вокруг PyTorch сформировалась богатая экосистема библиотек и инструментов, расширяющих его функциональность для различных задач.

torchvision

Пакет для компьютерного зрения, содержит датасеты, модели и преобразования для работы с изображениями.

Ключевые компоненты:
  • torchvision.datasets
  • torchvision.models
  • torchvision.transforms

torchaudio

Библиотека для обработки аудио данных, содержит функции для загрузки, преобразования и работы со звуком.

Ключевые компоненты:
  • torchaudio.datasets
  • torchaudio.transforms
  • torchaudio.models

torchtext

Инструменты для обработки естественного языка (NLP), включая загрузку данных, токенизацию и векторизацию текста.

Ключевые компоненты:
  • torchtext.datasets
  • torchtext.vocab
  • torchtext.data

TorchServe

Фреймворк для развертывания моделей PyTorch в производство, обеспечивающий масштабируемость и мониторинг.

Возможности:
  • RESTful API
  • Управление моделями
  • Мониторинг производительности

PyTorch Lightning

Высокоуровневая обертка над PyTorch, упрощающая организацию кода и обучение сложных моделей.

Преимущества:
  • Структурированный код
  • Автоматическая распределенное обучение
  • Встроенные инструменты для логирования

Captum

Библиотека для интерпретации и объяснения моделей машинного обучения.

Методы интерпретации:
  • Интегрированные градиенты
  • Guided GradCAM
  • LIME, SHAP

TorchDynamo и TorchInductor

Современные компоненты для компиляции и оптимизации PyTorch кода, значительно повышающие производительность.

Доступно через:
  • torch.compile()

Weights & Biases

Инструмент для отслеживания экспериментов, визуализации и сравнения результатов моделей.

Функциональность:
  • Логирование метрик
  • Сохранение артефактов
  • Отслеживание гиперпараметров

Hugging Face Transformers

Библиотека современных моделей трансформеров для NLP, полностью интегрированная с PyTorch.

Популярные модели:
  • BERT, GPT, T5
  • RoBERTa, ALBERT
  • DistilBERT, XLNet

Интеграции

Экспорт моделей

  • ONNX (Open Neural Network Exchange)
  • TorchScript
  • C++ API
  • PyTorch Mobile
  • TensorRT (NVIDIA)

Интеграция с другими инструментами

  • Ray
  • MLflow
  • TensorBoard
  • Streamlit
  • Apache Spark

* Meta (Facebook) признана экстремистской организацией и запрещена на территории РФ