Переход с TensorFlow

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

Что такое ПиТорч? Почему PyTorch так важен?

PyTorch — это платформа машинного обучения, разработанная Meta. Это основной конкурент TensorFlow.

В результате небольшого дальнейшего исследования я обнаружил, что многие исследования ML/AI проводятся с использованием PyTorch, но компании предпочитают использовать Tensorflow для создания производственных моделей. Таким образом, если вы хотите иметь возможность понимать множество исследовательских работ по машинному обучению, знание основ PyTorch является обязательным.

В настоящее время я знаю только Tensorflow. В этой статье я расскажу о PyTorch-эквивалентах некоторых базовых компонентов Tensorflow и объясню, как создать базовую модель.

Обзор PyTorch

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

Два основных компонента машинного обучения, модель и набор данных, создаются путем подкласса модуля PyTorch и класса набора данных (находятся в пакетах PyTorch.nn и torch.utils.data соответственно). Затем пользователь должен реализовать несколько методов, чтобы все заработало.

Создание простой модели в PyTorch

Внутри PyTorch.nn есть множество объектов-«модулей», которые могут показаться знакомыми пользователю Tensorflow. Вот как сделать базовую модель:

import torch
from torch import nn
class NeuralNetwork(nn.Module):
  def __init__(self):
    super().__init__()
    self.flatten = nn.Flatten() # equivalent of keras.layers.Flatten
    self.layers = nn.Sequential(
      nn.Linear(28*28, 512), # input shape, output shape         
      nn.ReLU(), # you have to add the activation function after
      nn.Linear(512, 512), 
      nn.ReLU(), 
      nn.Linear(512, 10)
    )
  def forward(self, x):
    # when you call a layer on an input, it will execute its
    # operations. Below, this will flatten x.
    x = self.flatten(x) 
    logits = self.layers(x)
    return logits
model = NeuralNetwork()

В модуле keras.layers Tensorflow есть много эквивалентных компонентов для слоев. Эти компоненты, такие как Linear(), ReLU() и Flatten(), также являются модулями.

Когда модуль вызывается с некоторыми входными данными, его метод forward() будет работать с входными данными. Таким образом, мы должны переопределить метод forward() при создании нашей нейронной сети, указав, как данные должны проходить через нее.

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

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

Не беспокойтесь о загрузчиках данных, мы обсудим это позже.

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

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

Нашему оптимизатору дается ссылка на параметры нашей модели. Для каждого параметра отслеживается значение и атрибут «grad», представляющий градиент.

Мы устанавливаем градиенты равными нулю, используя метод оптимизатора zero_grad(). Это гарантирует, что ранее рассчитанные градиенты не будут использоваться на текущем этапе обратного распространения. Затем мы вызываем метод потерь back() для расчета новых градиентов (принимая во внимание расчеты, связанные с потерями, такие как импульс), и запускаем метод оптимизатора step() для обновления всех весов модели с их градиентами.

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

Создание набора данных

В PyTorch мы можем создать набор данных, создав подкласс класса Dataset.

import torch
from torch.utils.data import dataset
import os
import pandas as pd
class ImageDataset(Dataset):
  def __init__(self, ..., transform=None, target_transform=None):
    # initialize necessary variables
    ...
    self.transform = transform
    self.target_transform = target_transform
  def __len__(self):
    ...
  def __getitem__(self, idx):
    # read the image from filesystem or wherever
    ...
    if self.transform:
      x = self.transform(x)
    if self.target_transform:
      y = self.target_transform(y)
    return x, y

Основная идея заключается в том, что нам нужно переопределить три метода: инициализатор (очевидно), метод длины и метод getitem, чтобы мы могли получить доступ к элементам по индексу.

Большинство наборов данных включают атрибуты преобразования и target_transform, которые представляют собой две функции, применяемые к объектам и меткам соответственно при возврате данных.

Эта структура легко настраивается. Например, если нам нужно несколько источников ввода, мы можем заставить метод __getitem__ возвращать кортеж длины 3, представляющий два источника ввода и цель. Затем мы можем изменить класс нашей модели, чтобы отразить это. Вот что я имею в виду, когда говорю, что разработчикам легко освоить PyTorch.

Загрузчики данных

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

Все, что вам нужно сделать, это инициализировать его.

from torch.utils.data import DataLoader
dl = DataLoader(dataset, batch_size=64, shuffle=True)

Заключение

Надеюсь, это даст вам хорошее представление о том, как работает PyTorch, и либо поможет вам начать изучение фреймворка, либо немного лучше поймет модели, которые вы видите в Интернете!